Tips - forceUnwrap https://forceunwrap.com Lift your Swift skills & career to the next level Thu, 24 Aug 2023 17:18:18 +0000 en-US hourly 1 https://wordpress.org/?v=7.0 https://forceunwrap.com/wp-content/uploads/2023/03/cropped-ForceUnwrap-32x32.jpg Tips - forceUnwrap https://forceunwrap.com 32 32 The Art of Constructive Code Review: Why “It’s Sh*t Code” Doesn’t Cut ItπŸŽ¨πŸ’»πŸ”πŸš« https://forceunwrap.com/the-art-of-constructive-code-review-why-its-shit-code-doesnt-cut-it/ https://forceunwrap.com/the-art-of-constructive-code-review-why-its-shit-code-doesnt-cut-it/#respond Thu, 24 Aug 2023 17:11:48 +0000 https://forceunwrap.com/?p=464 Embark on a humorous yet insightful journey through the world of code reviews. Discover the good, the bad, and the downright funny feedback developers face, and learn the art of giving constructive comments that elevate code quality and team morale.

The post The Art of Constructive Code Review: Why β€œIt’s Sh*t Code” Doesn’t Cut ItπŸŽ¨πŸ’»πŸ”πŸš« first appeared on forceUnwrap.

]]>
Code reviews: that special time when developers come together, coffee in hand, hoping for the best but expecting the worst. It’s a time of bonding… or breaking. All depends on the feedback!

When Feedback Turns Comical (But not in a good way) πŸ€¦β€β™‚οΈ

We’ve all been there. The long-awaited moment when your code goes under the microscope, and you get gems like:

  • “This is garbage.” πŸ—‘
  • “Sh*t code!” πŸ’©
  • “Do you even know how to code?” 🧐
  • “You must be joking with this pull request.” πŸ˜‚
  • “This looks like spaghetti code thrown against a wall.” 🍝
  • “You’ve just set the project back by weeks.” πŸ“†βͺ

Decoding “It’s Sh*t Code” πŸ”

When faced with such cryptic feedback as “It’s Sh*t Code”, a developer might wonder:

  • Lack of Guidance: This phrase doesn’t illuminate the problem, nor does it suggest ways to rectify it. ❓
  • Morale Impact: Sharp criticisms can sap motivation, leading to dwindling enthusiasm for the task at hand. 😞
  • Clarity Concerns: “Sh*t” refers to…? πŸ€” Without context, it’s hard to pinpoint what “sh*t” refers to. Is it about the structure, the logic, or something else?
  • Professionalism: Using crude language is unprofessional and can degrade the team culture and trust. 🚫

The Gentle Art of “Not Making Your Colleague Cry” 😒➑😊

Ideal feedback during a code review should be:

  • Explicit: Less “What is this mess?” More “This section could use a comment for clarity.” ✍
  • Neutral-Toned: Keep the focus on the code, separating it from the coder. πŸ‘©β€πŸ’»πŸ”
  • Solution-Oriented: Instead of just highlighting a problem, suggest a potential fix. πŸ’‘

The Beauty of Constructive Zingers ✨

Constructive feedback not only points out issues but also guides towards improvement:

  • Instead of: “This code is messy.”
    Suggest: “Consider breaking this function into smaller ones to improve readability and maintainability.” πŸ‘“
  • Instead of: “This section seems off.”
    Suggest: “Maybe we can modularize this part for better clarity.” 🧱
  • Instead of: “The chosen algorithm seems slow.”
    Suggest: “Given our requirements, perhaps [algorithm] might offer faster performance.” πŸš€
  • Instead of: “I can’t follow this logic.” or “This part is confusing.”
    Suggest: “Maybe we can modularize this part for better clarity.” πŸ€·β€β™‚οΈβž‘πŸ€“

Embracing the Benefits of Thoughtful Feedback 🌈

  • Elevated Code Standards: Better feedback, better code, better coffee breaks. β˜•πŸ˜Œ
  • Positive Team Environment: Less side-eye, more high-fives. πŸ™„βž‘πŸ™Œ
  • Personal Growth: We’re all here to level up, right? 🌱➑🌳

Share Your Hall of Fame… or Shame πŸ˜…

What’s the most “creative” feedback you’ve received? The funnier, the better. Let’s laugh (or cry) together and create a more constructive code review culture. πŸ˜‚πŸ˜­

To Infinity and Beyond πŸš€

Code reviews: the final frontier in a developer’s journey. Let’s make it less about surviving and more about thriving, one constructive comment at a time. 🌟🌌

The post The Art of Constructive Code Review: Why β€œIt’s Sh*t Code” Doesn’t Cut ItπŸŽ¨πŸ’»πŸ”πŸš« first appeared on forceUnwrap.

]]>
https://forceunwrap.com/the-art-of-constructive-code-review-why-its-shit-code-doesnt-cut-it/feed/ 0
Swift’s print vs dump: A Deep Dive https://forceunwrap.com/swifts-print-vs-dump-a-deep-dive/ https://forceunwrap.com/swifts-print-vs-dump-a-deep-dive/#respond Thu, 24 Aug 2023 08:09:39 +0000 https://forceunwrap.com/?p=456 Swift's print offers clean, user-friendly output, often needing customization. In contrast, dump provides deep introspection, ideal for debugging.

The post Swift’s print vs dump: A Deep Dive first appeared on forceUnwrap.

]]>
Swift, Apple’s powerful and expressive language, is full of nuances that can either make your life easier or add a layer of complexity. Two seemingly simple yet profoundly distinct functions in Swift are print and dump. At first glance, both appear to display information, but when you delve deeper, you’ll see that they serve very different purposes. Using the provided sample code, let’s explore their differences.

Sample Code Overview

First, let’s dissect the provided sample:

class Person {
    let name: String
    let surname: String
    let age: Int

    init(name: String, surname: String, age: Int) {
        self.name = name
        self.surname = surname
        self.age = age
    }
}

let person = Person(name: "John", surname: "Doe", age: 21)

Here, we have a simple Person class that stores an individual’s name, surname, and age. An instance of this class, person, is initialized with the values “John”, “Doe”, and 21, respectively.

The print Function

Let’s first discuss the print function:

print("--- Print ---")
print(person)

When you run this, you might see something like:

--- Print ---
Person

The print function displays the textual representation of the passed argument. For most Swift standard library types, this function will show a useful and clear representation. For example, if you pass a string or an array to print, it will pretty much show you the content as you’d expect.

However, when you pass a custom object, like our Person instance, you get a default representation (like Person) which isn’t particularly useful.

To make print more informative for custom types, you’d typically have to implement the CustomStringConvertible protocol and provide a description computed property:

extension Person: CustomStringConvertible {
    var description: String {
        return "\(name) \(surname), \(age) years old"
    }
}

With this in place, print(person) would output:

John Doe, 21 years old

The dump Function

Now, let’s see what happens when we use the dump function:

print("--- Dump ---")
dump(person)

You’ll probably get output like this:

--- Dump ---
β–Ώ Person
  - name: John
  - surname: Doe
  - age: 21

The dump function provides a detailed breakdown of the passed argument. In this case, it shows the internal properties of the Person instance.

This function is especially useful for debugging purposes. You don’t need to implement any additional protocols or provide a custom description. It just inspects the object and presents you with a more in-depth view of its contents.

Performance of print vs dump

Another aspect worth examining between print and dump is their performance impact. While for most casual use cases you might not notice a significant difference, when dealing with large datasets or frequently called operations, understanding the relative costs can be beneficial.

print Performance

The print function, especially when you’re using the default or custom string representations, tends to be lighter on performance. It simply takes an object’s representation and writes it to the standard output. When dealing with simple and small data types, the overhead introduced by print is minimal.

However, when you implement the CustomStringConvertible protocol to give a custom representation, there’s potential overhead depending on the complexity of the description computed property. The more operations and concatenations you perform, the slower it can become, especially if called frequently.

dump Performance

The dump function, being more introspective, can be a bit heavier on performance. It delves deep into the object, revealing not just top-level properties but also nested structures. This deeper dive can introduce more computational overhead, especially when dealing with complex and large objects or hierarchies.

In practice, using dump repeatedly on large structures might slow down your debugging sessions or, if mistakenly used in production code, your application’s performance. It’s designed for detailed introspection, and this depth comes at a cost.

dump and String Interpolation

An interesting quirk about the dump function is its behavior with string interpolation. When you attempt to use dump on a string that contains nested objects via interpolation, such as dump("Test: \(person)"), it doesn’t dissect the object within the string as you might expect. Instead, it treats the whole content similarly to how print would, displaying the string as-is without deeper introspection of the nested object. This can be misleading if you’re expecting the detailed breakdown that dump typically offers. When using dump, it’s best to directly pass the object of interest rather than nesting it inside a string to ensure you get the detailed output you’re seeking.

Structs and Readability in Swift

In Swift, structs enjoy a level of readability that often surpasses that of classes, especially when it comes to debugging and logging. Due to the way Swift’s compiler auto-synthesizes certain functionalities for structs, when you print a struct instance (even when nested inside a string), you usually get a clear and readable output without needing the introspective depth of dump. For example, executing print("Test: \(person)") with a struct version of our Person would yield a detailed output, showcasing all its properties. This inherent readability of structs provides an advantage in clarity, often rendering the use of dump unnecessary.

Recommendations

For general logging and display purposes in production, stick to print. If you need detailed introspection for debugging, use dump but be wary of its performance impact on larger structures. Always test performance in scenarios that mirror real-world usage, especially if logging or data display operations are frequent.

In conclusion, while both print and dump have their unique strengths, it’s essential to be mindful of their performance implications in specific scenarios.

Conclusion

While both print and dump allow you to display information about objects and data in Swift, they serve slightly different purposes:

  • print is for presenting a clean, human-readable representation, often requiring some customization for custom types.
  • dump is more for debugging and introspection, offering a detailed view of the internals of an object or data structure without any additional work on your part.

By understanding and using these functions appropriately, you can make your Swift development and debugging processes much smoother.

The post Swift’s print vs dump: A Deep Dive first appeared on forceUnwrap.

]]>
https://forceunwrap.com/swifts-print-vs-dump-a-deep-dive/feed/ 0
How to fix committing to the wrong Git branch? https://forceunwrap.com/how-to-fix-committing-to-the-wrong-git-branch/ https://forceunwrap.com/how-to-fix-committing-to-the-wrong-git-branch/#respond Fri, 18 Aug 2023 12:34:01 +0000 https://forceunwrap.com/?p=453 Committing to the wrong Git branch can be a daunting mistake for developers, but fear not! Explore a step-by-step guide to navigate and rectify such mishaps, ensuring your code remains organized and your repository unscathed.

The post How to fix committing to the wrong Git branch? first appeared on forceUnwrap.

]]>
It’s a scenario that most developers face at some point in their careers: you’ve just made a commit, only to realize moments later that you’ve committed to the wrong Git branch. Panic might set in as you worry about how to undo this mistake without causing more confusion or messing up the repository. Fear not, because Git offers tools to help you correct such mistakes. Here’s a step-by-step guide to help you navigate this situation.

Step 1: Safely Undo the Last Commit

First, make sure that you haven’t pushed your changes to a remote repository. If you have, it becomes a bit more complicated, especially if other people have pulled from that branch in the meantime.

If you haven’t pushed the commit, you can use the following command to revert it:

git reset --soft HEAD~1

Here’s what this command does:

  • git reset: This is a command that allows you to reset your current HEAD to a specified state.
  • --soft: This option ensures that the changes in the wrongfully committed files are retained in the index. In other words, they will be staged and ready to be committed again.
  • HEAD~1: This refers to the commit before the latest one. By resetting to this commit, you’re effectively undoing the last commit.

Once executed, your commit will be undone, but the changes will still be there, staged and waiting for a new commit.

Step 2: Switch to the Correct Branch

Before you can commit your changes to the correct branch, you need to check out that branch. Use the following command, replacing correct-branch-name with the name of the branch where you intended to make your commit:

git checkout correct-branch-name

If you don’t already have this branch locally, you can create and switch to it using:

git checkout -b correct-branch-name

Step 3: Commit Your Changes

Now that you’re on the right branch, you can commit your changes. Since they are already staged (thanks to the --soft flag we used earlier), you can simply commit them:

git commit -m "Your commit message here"

Replace “Your commit message here” with an appropriate message for your commit.

Step 4: Verify Everything is Correct

Always double-check your work. Ensure you’re on the right branch and that your commit has been applied correctly:

git log --oneline

This command will display the commit history in a concise format. Your most recent commit should be at the top, and you should be on the correct branch.

Conclusion

Mistakes happen, and committing to the wrong Git branch is a common one. Thankfully, Git is a powerful tool that provides ways to fix such issues with ease. Always remember to double-check your branch before committing, and should you find yourself having committed to the wrong branch, simply follow the steps above to rectify the situation.

The post How to fix committing to the wrong Git branch? first appeared on forceUnwrap.

]]>
https://forceunwrap.com/how-to-fix-committing-to-the-wrong-git-branch/feed/ 0
Copy on write iOS developer interview question explained https://forceunwrap.com/copy-on-write-interview-question-explained/ https://forceunwrap.com/copy-on-write-interview-question-explained/#respond Wed, 15 Mar 2023 12:20:53 +0000 https://forceunwrap.com/?p=327
var firstArray = [1, 2, 3, 4, 5]    // [1, 2, 3, 4, 5]
var secondArray = firstArray        // [1, 2, 3, 4, 5]

print(firstArray == secondArray)    // true

secondArray.append(6)               // [1, 2, 3, 4, 5, 6]

print(firstArray.count)             // 5
print(secondArray.count)            // 6

print(firstArray == secondArray)    // false

In Swift, when an array is assigned to another variable, a copy of the array is not created immediately. Instead, the new variable refers to the same memory location as the original array. This means that any changes made to the new variable are reflected in the original array as well.

However, Swift also uses a technique called Copy-On-Write (COW) to optimize memory usage. When a mutable operation is performed on an array (e.g. adding or removing an element), Swift checks whether the array has more than one reference to its memory location. If it does, Swift creates a new copy of the array before performing the mutation, so that the original array remains unchanged.

In the code provided, firstArray is created with the values [1, 2, 3, 4, 5], and then secondArray is assigned to firstArray. Since secondArray is not mutated at this point, it still refers to the same memory location as firstArray.

The first print statement outputs true because firstArray and secondArray both contain the same values.

Next, the value 6 is appended to secondArray. Since secondArray now has more than one reference to its memory location, Swift creates a new copy of the array before appending the value. This means that firstArray remains unchanged, and the print statement that outputs 5 shows that firstArray still has 5 elements.

The post Copy on write iOS developer interview question explained first appeared on forceUnwrap.

]]>
https://forceunwrap.com/copy-on-write-interview-question-explained/feed/ 0
Avoid generating unwanted git .orig and .backup files https://forceunwrap.com/avoid-generating-unwanted-git-orig-and-backup-files/ https://forceunwrap.com/avoid-generating-unwanted-git-orig-and-backup-files/#respond Mon, 03 Oct 2022 13:00:26 +0000 https://forceunwrap.com/?p=279 To avoid generating unwanted git .orig and .backup files, you can modify the configuration by executing the following command:

git config --global mergetool.keepBackup false

Typically, when using git mergetool to resolve merge conflicts, the tool will save the conflicted version of the file with a .orig and .backup suffixes. However, if the mergetool.keepBackup configuration option is set to false, these .orig and .backup files will not be preserved. It’s worth noting that the default value for this option is true, meaning that backup files will be kept by default.

The post Avoid generating unwanted git .orig and .backup files first appeared on forceUnwrap.

]]>
https://forceunwrap.com/avoid-generating-unwanted-git-orig-and-backup-files/feed/ 0
Pass some View as parameter to another View https://forceunwrap.com/pass-some-view-as-parameter-to-another-view/ https://forceunwrap.com/pass-some-view-as-parameter-to-another-view/#respond Fri, 26 Aug 2022 10:53:43 +0000 https://forceunwrap.com/?p=237
import SwiftUI

struct CustomNavView<Content: View>: View {
    let content: Content
    let title: String
    
    init(title: String, @ViewBuilder content: () -> Content) {
        self.content = content()
        self.title = title
    }
    
    var body: some View {
        NavigationLink(destination: self.content) {
            Text(title)
        }
        .padding()
    }
}

Usage:

CustomNavView(title: "Picker sample in SwiftUI") {
    EmptyView()
}

Changelog:

// Good stuff. 🙇‍♂
git commit -m "Update to trailing closure as head_of_roses recommends" 

The post Pass some View as parameter to another View first appeared on forceUnwrap.

]]>
https://forceunwrap.com/pass-some-view-as-parameter-to-another-view/feed/ 0
Line breaks – multiple guard statements https://forceunwrap.com/line-breaks-multiple-guard/ https://forceunwrap.com/line-breaks-multiple-guard/#respond Fri, 17 Jun 2022 08:55:12 +0000 https://forceunwrap.com/?p=171 Proper line breaking makes a difference. Don’t put everything in one line. The usual character limit is 120 symbols per line. Put each statement in new line. else could be on a separate line.

Pro tip:
I prefer to put in on a new line for better readability. In my experience I have noticed, that putting else on a new line, helps spoting start and end of guard without reading the context inside the guard.

// Don't
guard
		let clientID = Bundle.main.object(forInfoDictionaryKey: "ApiClientID") as? String,
		let serverClientID = Bundle.main.object(forInfoDictionaryKey: "ApiServerClientID") as? String
else {
		return
}

// Don't
guard let clientID = Bundle.main.object(forInfoDictionaryKey: "ApiClientID") as? String, let serverClientID = Bundle.main.object(forInfoDictionaryKey: "GoogleServerClientID") as? String else { return }

// Do
guard let clientId = Bundle.main.object(forInfoDictionaryKey: "ApiClientID") as? String,
			let serverClientId = Bundle.main.object(forInfoDictionaryKey: "ApiServerClientID") as? String
else {
		return
}

How do you line break guard with multiple statements? Share in the comments below.

The post Line breaks – multiple guard statements first appeared on forceUnwrap.

]]>
https://forceunwrap.com/line-breaks-multiple-guard/feed/ 0
Loops https://forceunwrap.com/loops/ https://forceunwrap.com/loops/#respond Tue, 07 Jun 2022 14:52:28 +0000 https://forceunwrap.com/?p=153 forEachΒ is the preferred way of dealing with loop in a Senior life.Β forΒ inΒ is what you learn in school. Or in other words, next step of walking – running.
Do it like adults do.

// Don't
for val in sequence {
		value.doSomething(
}

// Do
sequence.forEach {
		$0.doSomething()
}

// Do
sequence.forEach { value in
		value.doSomething()
}

Of course there are times when you need for in, but more about that later on.

The post Loops first appeared on forceUnwrap.

]]>
https://forceunwrap.com/loops/feed/ 0
Class https://forceunwrap.com/class/ https://forceunwrap.com/class/#respond Mon, 06 Jun 2022 20:05:52 +0000 https://forceunwrap.com/?p=147 Most of the times, people forget to use final in a class. If you don’t extend the class – add final. This will allow for you to build faster, as compiler will not look for class extensions.

// Don't add final, unless you plan to extend the class
class AuthenticationService {
		// Implementation
}

// Do add final, if you are not extending
final class AuthenticationService {
		// Implementation
}

The post Class first appeared on forceUnwrap.

]]>
https://forceunwrap.com/class/feed/ 0
Array https://forceunwrap.com/array/ https://forceunwrap.com/array/#respond Fri, 03 Jun 2022 17:47:08 +0000 https://forceunwrap.com/?p=138 Try to make your code as easily readable for others as you can.

#Challenge, spot a piece of hard to read code on stackoverflow.com. Edit the question/answer, so the code would be easier to read and understand for everyone else. People having the same issue and looking for an answer will surely be grateful for easily readable code.
#swift-code-style.

// Don't
let array = ["Tom", "John", "Joe", "Alan", "Alex", "Adam", "Tim", "Tom", "John", "Joe", "Alan", "Alex", "Adam", "Tim"]

// Do
let names = [
		"Tom",
		"John",
		"Joe",
		"Alan",
		"Alex",
		...
]

The post Array first appeared on forceUnwrap.

]]>
https://forceunwrap.com/array/feed/ 0