Move Field Refactoring in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Move Method refactoring.

Here’s a video walkthrough of the Move Method refactoring in Swift and when you might want to use it:

Video Transcript:

Hey, what’s up everybody, it’s Andy the Clean Swifter and I’m back here to show you another refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” Each week we’re taking a look at a different refactoring from that book and how to implement it in Swift 3. This week we’re going to talk about the Move Field refactoring. Now the Move Field refactoring you’re going to see, and I bet you’re going to write it off as something so trivial that you’ll be wondering why I’m even making a video about it. Before you do that, I want you to realize that the essence of refactoring is identifying an inefficiency with regard to the structure of your code, and improving it. It’s the building blocks of being able to look for these, knowing what to do, and building up that body of experience about refactoring and being able to apply that in much larger puzzles after you’re put together these smaller pieces and fundamentals along the way. Move Field is just that. It’s a fundamental refactoring where you’re going to see that in one class, or struct, that one field exists and it might not be the best place for it. You’re going to take that field and find a better place for it, and you’re going to move it there. All references will then point to that new field in the new location. Remember, the point is you’re taking a field from an inappropriate place to a better place. You’re not always going to be able to identify that up front. Don’t try to over optimize your code, whether it’s from a performance standpoint, or a refactoring standpoint. Go with your first natural design, and then once you get there, reevaluate it, and look for that better place of what the code could be. In this case we’re going to look at it from the perspective of the Move Field refactoring.

Just this week I’m going back to revisit some code in an app I worked on over a year ago. We went to long extents to refactor a NSFetchedResultsController from a UIViewController from it’s tableView datasource and delegate. They are all separate classes in separate files in Objective-C. Going back to that code, it’s hard to digest and understand. At the time, we thought we were being so clever with this refactoring, and thought the code was going to be so flexible for further design. Little did we know, it would be the last update we’d make to that code for a year and a half. We’re actually going back to it now, and rather than being flexible for design, it’s kind of hard to improve. My moral here with these basic refactorings, remember, yes they are basic, but they’re the fundamental for doing something bigger, and being able to put the puzzle pieces together to ultimately improve your code. Let’s look at the Move Field refactoring.

We’re going to reuse the sample code that we used in our refactoring last week, Move Method, and continue with that. I’ve added a new method here, displayFirstName() that will help explain this example for Move Field. In general, there’s a struct that represents a person’s name. It has a first and last String. There’s a view controller with a label, a name, and nickname String. There’s a viewDidLoad() implementation, and another method to displayFirstName() and lower on is a separate class for NameLabel. For the Move Field refactoring, what we’re going to do is identify a field in a class and find a new place for that field that makes more sense. Let’s take a look at this view controller to identify that field that’s going to move. viewDidLoad() sets a name label based on the first name. There’s this other method which isn’t being called at the moment, which is displayFirstName(). displayFirstName() looks like it is doing something a little different than setNameLabel. displayFirstName() is actually going to use nickname, the String on this view controller, and then based on whether there is a nickname or not, format the string and set it on the label. The first thing that jumps out to me is that nickname is being used here as a variable separate from the Name object. That to me smells a little bit. I think the nickname would be more appropriate as an attribute on the Name struct. This is where we are going to start honing in on our Move Field refactoring. Move Field refactoring now that I’ve picked nickname as something that doesn’t make sense in this view controller, and would make better sense in the Name struct, I’m simply going to pull this out of the view controller, and insert it into the Name struct. And now that the nickname is there I’m going to get a compiler error here back in the view controller because nickname is no longer a property on the view controller, and instead it’s being provided by the Name. Then I can access it through name and if name has a nickname then set it to be this interesting label where it’s the firstName plus the nickname, or just set the label to be the first name. That’s it! That’s Move Field in a nutshell. Depending on which logic might be used for computing nickname on setting or getting, you may want to consider different types of encapsulation for the logic which might happen at that point. None of that is happening here. In essence, Move Field is removing a property from one class, and adding it to another, in this case a struct. In my opinion, this is a much cleaner implementation. nickname goes with a Name. It’s no longer a property hanging off the view controller. It’s well enapsulated within Name.

There you have it, it’s the Move Field refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” It is a very simple refactoring, and you saw a very simple implementation of it where you move one field from a class to another class, all in the sake of finding a better home for that field which can make more logical sense for your code, and support a better encapsulation of your code. I hope you enjoyed this video. You can buy Martin Fowler’s book. “Refactoring, Improving the Design of Existing Code” in the Amazon Affiliate link in the description for this video. I hope you tune in next week for another refactoring. In the meantime, happy cleaning.

Weekend Reading, September 9, 2016

Weekend Reading, September 9, 2016, click here

Happy Friday fellow Clean Swifters, I’d like to welcome a bunch of new readers who discovered cleanswifter.com from Dave Verwer’s iOS Dev Weekly. I’m heading down onto the Chesapeake Bay this weekend for some fishing and crabbing. It’s been a banner year for Blue Claw crabs. In the downtime, here’s what I’ll be reading to catch up from the week.

Also, I’m wondering: What do you to to improve your software development skills?

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

Post Weekend Reading for August 29, 2016

Post Weekend Reading for August 29, 2016, click here

Happy Monday fellow Clean Swifters.

First off, my apologies for not getting this weekend-reading published on Friday! I wouldn’t be human I couldn’t admit that the end of the summer is really busy, and while I wanted to get this out on Friday, life got in the way. That doesn’t mean the links stop coming though, or that you should skip sharpening that axe. I’ll just be setting aside a little more time this week to catch up. Here’s what caught my eye last week.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

SFSpeechRecognizer Tips for iOS 10

Did you know that there’s a new iOS 10 API for transcribing audio in your iOS apps? I didn’t know that this was possible myself until I came across the Speech Framework introduced in iOS 10. In fact, I was actually watching one of Sam Davies’ screencasts on Ray Wenderlich’s new video site called Audio File Speech Transcription (both the screencast and the new videos site are fantastic by the way) where he covered how the API can be used to transcribe an audio file. The screencast itself is a fantastic short overview of how to use the framework to create an app that transcribes 90’s rap music files. I’m not going to try and recreate a tutorial on the basics of the API. Instead, when trying it out myself I discovered a couple nuances not mentioned in Sam’s screencast. Here’s a couple SFSpeechRecognizer tips.

Requires A Device

Use of SFSpeechRecognizer, the main class that makes speech transcription possible, will not actually transcribe anything unless you are running your app on a device (as of Xcode 8 beta 6). This was a surprise to me, especially considering that speech transcription of an audio file, rather than microphone input, has nothing to do with a physical device. I’m wondering if it has something to do with the underlying implementation of Siri and something that only exists on the actual device. Regardless, you are lucky enough to have access to a Bool on SFSpeechRecognizer called isAvailable. This Bool simply indicates whether speech recognition is available at the time of usage. I was actually banging my head trying to figure out how to get Sam’s sample project to actually work within the iOS Simulator. His screencast seemed to transcribe speech no problem in the app I was viewing on screen. Finally I looked closer and noticed that he was screensharing from an iOS device through Quicktime! Mystery solved! Either way, don’t make the same mistake as me and wonder why code like this didn’t work:

guard let recognizer = SFSpeechRecognizer() else {
  return
}

if !recognizer.isAvailable {
  print("Speech recognition not available")
  return
}

Timeouts

The other interesting discovery I made when playing around with SFSpeechRecognizer is that there is an undocumented limitation on how big of a file can be transcribed at once. I’m still playing around with the details as to where the limits are, but I have discovered, that longer running SFSpeechURLRecognitionRequest will timeout. I’m not even talking that long, like I had problems with a 5 minute video. For example, I tried transcribing my video Replace Temp With Query that is 4 minutes and 45 seconds long, and this was all the text that was returned before the timeout happens:

Hey what’s up everybody Danny from clean swiffer.com I’m here to show you another we factor in this week from our valors book we factoring in improving the design of existing time this week we’re gonna take a look at the re-factoring called replaced temp with Cory please temp with berries are factoring that’s a lot like expect nothing but there’s one difference it’s a little more specific with a place template query we’re going to specifically target temporary variables within our code and extract them into reusable piece of code so

Ya, not much (and not very accurate either). Either I should create a Radar for this, or Apple only intends for this API to be used for transcription of short audio clips. Time will tell.

Partial Transcription To The Rescue

Despite the undocumented timeout putting a crimp in my plans for using the Speech Framework in a couple longer running use cases, another Bool caught my eye: shouldReportPartialResults. It turns out my setting this flag to true, the Speech Framework will periodically provide transcribed results to you as they are discovered. Just set the value to true and you’ll see results continuously reported as they are determined:

let request = SFSpeechURLRecognitionRequest(url: url)
request.shouldReportPartialResults = true
recognizer.recognitionTask(with: request) {
  (result, error) in
  guard error == nil else { print("Error: \(error)"); return }
  guard let result = result else { print("No result!"); return }

  print(result.bestTranscription.formattedString)
}

Transcribing Realtime Playback

Despite these two shortcomings of short timeouts and requiring a device (which I hope Apple will fix at some point as the API matures), speech transcription is a really cool technology. Did you notice that voicemails in iOS 10 are automatically transcribed? It’s freakin awesome that you can glance at text for a voicemail rather than needing to listen?

Anyway another really cool real-world example of use of the Speech Framework is in the GitHub open source project Speech Recognition from zats. Apparently with some help from Apple, he came up with a way to transcribe a video on the fly. There’s some gnarly AVFoundation Objective-C code that made this possible. Be sure to take a look at his project and give it a go. And in fact, I’m wondering if I can use the techniques here to work around the timeout limitation I experienced with raw use of SFSpeechRecognizer. (Update: Turns out it did!)

Back Story

If you’ve read this far about SFSpeechRecognizer tips, I might as well bore you with some details on the back story as to why the SFSpeechRecognizer API caught my interest. With the videos I create for this site, it’s important to me to provide a transcription of the videos. I realize that watching a video isn’t always possible, so I like having a text alternative. It probably also helps with SEO as well. The thing is, transcribing the videos is a tedious process. For about a 5 minute video, it takes me about 30 minutes to transcribe it, and I type fast. Additionally, that’s only raw transcription. I’d like to do so much more. For example, I think the Realm videos are really well done. Specifically, two things I like are the links to jump to specific spots in the video from the transcription, and I also like the source code samples in the transcription. For me to do this it would take more time, so in attempt to look for a quick and easy fix to buy back some time, I figured I could use the new iOS 10 Speech Framework to code a speech transcription app to automatically transcribe my videos for me. I’m still working on it and definitely leveraging these SFSpeechRecognizer tips.

They say that necessity is the mother of all invention, right?

Wrap Up

How will you be putting these SFSpeechRecognizer tips to work? Have you had a chance to try out the new Speech Framework or any of the SFSpeechRecognizer APIs? Have you run into any other tricky spots or overcome any hurdles?

Happy cleaning.

Weekend Reading for August 19, 2016

Weekend Reading for August 19, 2016, click here

Happy Friday fellow Clean Swifters. Who’s watching the Olympics? There’s something that professional software engineering has in common with professional sports: practice makes perfect.

How do you practice your craft?

Reading is a big part of how I stay up to date, and I use the weekends as catch up time. Here’s what I’ll be reading this weekend.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

Split Temporary Variable in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Split Temporary Variable refactoring.

Here’s a video walkthrough of the Split Temporary Variable refactoring in Swift and when you might want to use it:

Video Transcript:

Hey what’s up everybody, it’s Andy from cleanswifter.com and I’m here to show you another refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” This week, in Swift 3, I’m going to show you how to do Martin Fowler’s refactoring “Split Temporary Variable.” This refactoring fixes a bad habit of mine that goes all the way back to my first couple classes in computer science. Specifically, this bad habit is when you create a temporary variable that you then reuse and reuse throughout a method for multiple purposes. This is bad because these variables are very poorly named and as a result, it’s really hard to figure out what they do. A general best practice is to only create a variable that will be used for a specific purpose. If you have to then create another temporary variable for a different purpose, do that rather than reuse the original. In order to do this, we’re basically going to look for cases where a temporary variable is used, and assigned to multiple times and then investigate whether that is a good candidate to be split into multiple temporary variables. Let’s take a look at some code.

Here’s a view controller in which there are a couple properties: two strings which represent first and last name, a name label, a welcome label, and a computed property which represents the person’s full name (which is their first name combined with their last name, separated by a space). Down here in viewDidLoad(), this is where things get a little ugly. First, there’s a variable named i. Who knows what i even means? And i gets assigned a string “My first name is” with the firstName value. i is assigned to nameLabels text. Later, i is also assigned a new value which is “Welcome” with the value of fullName. That new value is then assigned to the welcomeLabels text. I can see what’s going on here. It’s that two strings are being created and ultimately set on the labels, but I have no idea why this variable is named i, or why it’s being reused. The first way that you can get the compiler to be able to help you fix this, is simply change the definition of i from a var to a let. Let me show you that, in Swift, the compiler will alert you to any variables that are defined and only assigned to once. The compiler is telling us here that i was never mutated so consider changing it to a let which actually makes it a constant. I could do this. In this case where the compiler is detecting that it is only assigned to once, I can automatically use the IDE to fix it. But let’s go back to the original code. The compiler is not going to identify that as something to be changed because it’s assigned to twice despite this very poorly named variable i. So what I’m going to do here is change this to let and what that’s going to do is enable the compiler to show me all other places that i is assigned to. Those assignments are what I’m going to target for splitting out into their own thing. I’ve already made the decision that i is being inappropriately reused in was that don’t make sense. Once this is switched to a let I see the compiler gives me an error with a suggested fix. Xcode tells me to consider changing the definition of i from let to var to make it mutable. Yes. That would make this compile, that’s not what I want to do because that’s the opposite way of this refactoring. Instead, what I should do here, is actually create a new variable, and for now we’ll just call it n, and now there are two temp variables here. I need to actually use n in the new place where it should be read. Already this is an improvement because I’m using two temp variables and there’s no chance of collision between the two, and it’s a step towards making this even better. The final step in this refactoring is to actually come up with good names for the temporary variables. Let’s call these firstNameString and for the other one we’ll call it welcomeMessageString. Now be sure to take the new variable names and use them in the right place. Now you see the result of the refactoring. You can see where we started with one single temporary variable that was being reused and very poorly named such that the code was not very readable where now I have two temporary variables, both well named, and used in this resulting way.

There you have it, that’s the Split Temporary Variable refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” You can buy the book in the Amazon Affiliate link in the description for this video. I hope to see you next time for another refactoring, and in the meantime,

Happy cleaning.

Weekend Reading for August 12, 2016

Weekend Reading for August 12, 2016, click here

Happy Friday fellow Clean Swifters. I’m heading up to the Poconos in Pennsylvania this weekend looking forward to some much needed downtime. That doesn’t mean I haven’t loaded up my Instapaper queue! Here’s what I’ll be reading.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

Introduce Explaining Variable in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Introduce Explaining Variable refactoring.

Here’s a video walkthrough of the Introduce Explaining Variable refactoring in Swift and when you might want to use it:

Video Transcript:

Hey, what’s up everybody, it’s Andy the clean swifter, and I’m back to show you another refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” This week, I’m going to show you in Swift I’m going to show you the refactoring “Introduce Explaining Variable.” This refactoring can be used as an alternative to Extract Method when you have a complex piece of code that you want to simplify. The way that you’re going to simplify it is to create a new temporary variable that is well named and can be used to break up some complicated logic. Imagine sometimes you’ll be creating a complicated if statement to represent some conditional code, where there’s a lot of different things you need to check. All of a sudden you end up with several different and clauses, a couple different ors, and some parens grouping them, and before you know it, you’ve created a piece of very hard to read code. That’s bad because it’s a way to introduce bugs. It’s easy to accidentally change the logic of that statement such that you create a bug. Temporary variables can be used to break it up. You’ll take a piece of that if statement, that conditional cause, extract it into a temporary variable that is well named, and then reference that temporary variable in the conditional clause to then help explain it to the reader. You might instead use extract method to put it into a brand new, well named, method that returns a boolean that also helps explain its purpose to the reader, but in the case that you don’t want to do that, sometimes it may not be worth a method of its own, you can use this to introduce a variable to help explain the complicated conditional code. Let’s take a look at Introduce Explaining Variable:

Here’s a view controller similar to last week, where in this view controller there are two strings that represent a first and last name, a label that will be set with the name, and then also a welcome label which will give a customized welcome message based on something about the name. Down here in viewDidLoad() we’re going to set the nameLabel to be the fullName but now here we’re going to do some conditional logic to set the welcomeLabel based on the person’s name. Right off the bat, I’m trying to read this code and I come across this if statement and I see there are at least four different things being checked in order to determine how the welcomeLabel will be set. This to me isn’t very readable. We can use this refactoring to help improve the readability of this code. In order to use the refactoring, Introduce Explaining Variable, what I’m going to do is that I first need to understand what the condition is checking, and then I’m going to find a way to break it apart. Looking at this, it’s checking if the firstName starts with “A” and the lastName starts with “A” and the firstName ends with “A” and the lastName ends with “A” the welcomeLabel is set with a message that indicates they have a lot of “A”s in their name because just like my name “Andy”, “A” is the best letter in the alphabet. What’s the explaining variable I’m going to introduce? Well I could create two variables to each represent whether each name starts and ends with “A”, or a variable to represent whether both names start with “A” and another to represent that both end with “A”. For instance, let firstNameStartsAndEndsWithA, and to set that, I’m going to take this code right here, cut it out, and paste it in there. So that boolean represents the fact that firstName may or may not start and end with the letter “A”. And now I’m going to do the same thing for lastName. Now update the original if statement to represent the original behavior, and you should have unit tests to actually verify this, but it’s not a requirement. Now reading through this updated code, it is easily read aloud. I can look at the if statement alone, skipping over the variable definition, and understand the logic the if statement is checking. Well named temporary variables go a long way to give you quick readability of a complicated if statement. Now I can read this and understand if the first name starts and ends with “A”, and the last name starts and ends with “A”, I give a specific welcome message that they have a lot of “A”s in their name, otherwise their name is boring. Fowler does describe you could take this even further, and instead extract both of these new temps into their own method which might be called “lots of As in name” and then call that method from the if statement. It’s just one alternative. In this case, I choose that using temporary variables is appropriate, and leave it at this.

There you have it, that’s the Introduce Explaining Variable refactoring and it’s a way that you’re going to reduce the complexity of code specifically often times in complicated conditional clauses by introducing temporary variables. I hope you liked this refactoring, Introduce Explaining Variable from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” You can buy the book through my Amazon Affiliate link in the description for this video. I’ll see you next time.

Happy cleaning.

Weekend Reading for August 5, 2016

Weekend Reading for August 5, 2016, click here

Happy Weekend fellow Clean Swifters. Aside from checking out this year’s incredible Perseid meteor shower , I found some good reading.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

XCTest Target Membership Rule #1

I just had to learn a lesson the hard way, and wanted to pass on to you what I’m going to call the XCTest Target Membership Rule. It took some head banging of mine to discover this rule, and I don’t want you to go through the same pain.

The XCTest Target Membership Rule

The actual implementation files for your app should not be included with the Target Membership for your XCTest target.

xctest target membership

If you were to check the box next to TestStaticTests you would start to see this error in the Console when running your tests:

objc[14049]: Class ViewController is implemented in both <path cut>/TestStatic.app/TestStatic and <path cut>/TestStaticTests.xctest/TestStaticTests. One of the two will be used. Which one is undefined. 

The runtime for XCTest is telling you that it has found the same class defined in two places, the two targets for which you specified the file should be included. And furthermore, you’re also being told that the behavior with regard to which implementation is used will be “undefined.” The funny thing was, I actually found this error message to be misleading. I found that in practice, both copies of the implementation are actually used if you can believe that!

Here’s an in-depth question I posted on StackOverflow documenting the odd behavior I noticed, and included a sample project demonstrating it as well.

Background

These past few weeks I’ve been working on an older project, specifically AWeber Stats. If you notice, that app hasn’t been updated since April 2015, that’s a while. As a result a lot of the dependencies were out of date, so one thing the team set out to do was update the dependencies, and CocoaPods seemed like a good place to start. We were previously on version 0.34.1 and planned to update to 1.0.1 (which at the time of this writing is the latest version). We use Ruby Gems to manage the dependency versions for CocoaPods specifically. This allows us to have per-project control of which version of CocoaPods end up being used. This gives us the reassurance that we must explicitly designate the desire to update a given project’s CocoaPod’s version, and thus accordingly test and verify the update.

I move forward with the update, bumping the version of CocoaPods to 1.0.1 as defined in our Gemfile. CocoaPods 1.0 actually defines a new schema for Podfiles so I subsequently migrated the Podfile to the new format, and successfully ran pod install. Everything has gone smoothly up to this point. Then I opened my Xcode workspace and attempt to run our test suite.

100s of failures.

In addition to the failures, I saw many instances of that Console warning from earlier:

...One of the two will be used. Which one is undefined.

Now the thing is, remember, at this point I hadn’t yet discovered the XCTest Target Membership Rule. And as it turns out, nearly every implementation file in the project for the app target, also existed in membership for the test target. And in fact, as I dusted the cobwebs off of my mind, and thought back to the original work on the project, I specifically remember needing to designate those implementation files as having membership in the test target. Specifically, it was errors like this that would appear of the class under test was not part of the test target:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_MyArrayController", referenced from:
      objc-class-ref in MyArrayControllerTests.o

So where did the need to include that file with the test target go? Why was Xcode now telling me that I shouldn’t include these files with both targets?

Well I never got to the bottom of it. I have two guesses at this point: something either in Xcode, or in CocoaPods changed to modify the behavior how XCTest integrates with the classes under test.

Closing Thoughts

I’m still digging to get to the bottom of this. In the meantime, I will not forget the XCTest Target Membership Rule. A couple other lessons surfaced:

  1. Don’t wait to keep your project up to date – It’s easy to launch an app on the store, or hand it off to a client, and semi-forget about it. The app is live, attracting customers, and functioning well. Just remember, at some point it will either need to be updated or die. And the longer you wait, the harder it will be to bring it up to contemporary standards. It’s much easier to make more frequent small changes, than wait 15 months, return to an unfamiliar code base, and try to bring it up to speed.
  2. Know your tool chain – I’m still not fully aware of what changed between the last app update and today such that such a fundamental piece of project functionality changed. I’m taking this as a kick in the butt to get my head wrapped around third party dependencies being used. And if you can’t do that (for whatever reason – time, complexity, interest, etc.), don’t use them. There are plenty of ways to manually install third party code, or even write it from scratch. Of course other people have already invented the wheel, just don’t blindly use the tools without a foundational understanding of how to troubleshoot them when they go wrong.

Happy cleaning.