In the spirits of Thanksgiving and Black Friday

As the holidays are around the corner and 2019 is upon us, I want to share a few updates with you.

  1. The Clean Swift Handbook is undergoing a huge update. I added a brand new chapter about an iOS developer’s journey. And I’m not done. In the coming weeks, there’ll be another chapter on the origin and motivation behind the Clean Architecture. You’ll also find the complete system (with detailed steps) explicitly defined for you to follow when you implement features and fix bugs. Existing chapters of the book will also be expanded based on the last year’s feedback.

    If you bought the book or the bundle, you should already receive an email about the update. Or, you can also go to your Gumroad account to download the latest version. From now to next Monday, you can save 20% off either book, or the bundle. Just enter the promo code blackfriday at checkout.

  2. I’m building a new course to teach how to build a complex, non-trivial iOS app in a real work environment. The app you’ll be building is not any demo app that you find in other books and courses. It involves specific business logic, networking, custom views, among others. Unless you’re building a hobby app, nobody works alone. You’ll be learning how to write code that is fully encapsulated such that every developer productivity is maximized. You’ll learn how to divide the work to avoid code conflicts. It’s going to be one of its kind.

    The course is designed to be at least 3 months long. You’ll be working very closely with me in a team environment. So the number of seats is going to be extremely limited. There’ll be more details to come. If you think you’ll be interested, reply to this email and let me know now. I can send you updates as soon as it’s ready to launch. This course is a lot of work for me, which leads me to …

  3. I’m trying something new on the consulting side. Consultants typically charge an hourly rate. I generally don’t do that. Instead, I opt for a small project upfront. If things go well, we’ll end up with a longer term engagement. However, that also means, at the beginning of a new project, there are more contracts, paperwork and scoping work.

    I want to get that time back to work on the course. So, I’m starting a new way to do consulting work. Staring now, you can hire me by the hours at US$150/hr. Simply go here and choose the number of hours you want to buy. At this point, I’m only taking iOS work written in Swift and built with the Clean Swift architecture. It can be a new or existing project. I’ll re-evaluate after 6 months to see if I want to continue to offer this with any rate adjustment.

Happy Holidays!

Are you ready to go beyond the VIP cycle?

Many developers have told me the VIP cycle in Clean Swift has helped them a LOT. It’s a complete mindset shift in terms of how you build iOS apps. And they wanted more. The VIP cycle and its unidirectional nature are awesome. But what about the workers and custom views? They want to know how I would design classes and functions outside of the VIP cycle.

Maybe you found out about Clean Swift and read some of my articles, because you are an iOS developer who wants to take that next step. You want to learn how to write maintainable and testable code. But your existing app is built with MVC or MVVM, and you’re dealing with massive view controllers or massive view models. At this point, it’s just not feasible to switch the app to a new architecture. It’s already built, just slightly broken. Or, it is just a pain in the butt to work with on a daily basis. You want to keep your existing architecture, but also want to do things right. There is hope. You can still practice good software design principles to your classes and functions regardless of your app’s architecture.

You may have read and learned about design patterns, but are having troubles knowing when, where, and how to apply them to their own projects. Design patterns are iterated and proven from real, working, large scale software. They are valuable knowledge over many years. Understanding and applying them is an essential skill to acquire in your development career.

But understanding != applying. Reading and learning about design patterns alone doesn’t make writing well designed software any easier. Everything makes sense when you’re reading. But applying these patterns to real projects is totally different. It requires you to be extremely conscious about every line of code you write. At the same time, you are trying to focus on solving the problem on hand. Your brain is doing two things at the same time. We can think and drive a car at the same time easily. But deep thinking and problem solving are not meant to be multitasked. Our brains just aren’t wired to do that. You can’t be implementing a feature while trying to make sure your code adhere to all the software design principles.

Real Software —> Designed Patterns WORKS

But:

Designed Patterns —> Real Software DOESN’T WORK

In other words, extracting good design patterns from real working software works. But trying to force feed design patterns into software doesn’t work.

In this book, I turn that traditional approach upside down. I choose to take an architecture-agnostic and design pattern-agnostic approach to explain good software design. I won’t be talking about the design patterns explicitly. Instead, through working with a simple function, I’ll demonstrate how you can write good software by explaining with plain old English that you can understand. You’ll find that it’s just common sense. You’ll not need to do the mental translation from design patterns to good working code. You’ll just write good working code.

And there’s one more thing. Software does not stay the same. Software evolves. Requirements change. In the book, we’ll introduce a change in requirement and evaluate the before and after version of the code to see which is easier to maintain. Maintainability doesn’t just apply to app code. You’ll also learn how to write maintainable unit tests, and know to fully cover your app.

Start writing better functions today:

Buy Function Keys now for just $29

Continue reading →

How to effectively refactor MVC code and add unit tests

The following question arose in my mentorship Slack (a monthly subscription program that you can subscribe and unsubscribe on a monthly basis).


Question: Hey Ray, hope you’re doing fine. I got another question. I’m on this one project with MVC. We have 2 very heavy services that are the heart of the app. The DB-Service which communicates with Realm and handles things like updating objects, checking if an update is needed, delete objects, etc. On the other hand, there is the NetworkService which checks if a connection is there before making a request. If not, it returns local content if available and does the usual downloading of content and handing the stuff over to the DB-Service.

Both of these files are singletons and they are 700 and 900 lines of code. Most of the time very complicated code with a lot of conditionals, e.g. in plain language:

Get this collection and all the stuff that is needed for it. If it has a parent download the parent of it and the main content of it. Download all the resources but only once. If there is no connection try to get offline content. If there is a connection, check if the current stored content is up to date and then don’t download anything, etc., etc.

Now, we want to refactor those services. But before I would like to add unit tests as then we can verify if it has worked correctly before and also afterward. But I have seen that this is not really possible in the way that the code works right now. So I need to make the refactoring upfront. Is there a good way to split large services into smaller chunks and remove singletons?

I thought about dependency injection but don’t know if this is a good idea. Overall, there are 8 VCs that use the DB-Service. It’s maybe also possible to split the services to smaller chunks by making one service per VC. That’s maybe more reasonable and can be combined with the dependency injection.


Answer: Adding unit tests to bad code doesn’t help, as you’ve already known. There is simply no way to write good unit tests easily for bad code. By doing so, you’ll just become more frustrated with the existing code, and the resulting tests will be bad code too. So you’ll end up with 2x bad code.

As you can see from the Wistia videos. Instead of writing unit tests for the existing app, I just redo (not refactor) one feature, one scene at a time while adding unit tests for this new code. The trick is to not modify the existing scene, but to create a new scene with a different name and port one feature at a time, keeping it small. This allows you to quickly switch between the old and new scene, while giving you the total freedom to do whatever with the new scene.

Note that this doesn’t mean it’s a complete rewrite either. When you’re porting one feature at a time, you’ll probably find that you can simply copy and paste a lot of code from the old class to the new class. Make sure any public API methods are thoroughly unit tested while you’re doing this. Since you already figure out the high-level use cases, you can base your new classes on these use cases and the edge conditions.

You mentioned you’re dealing with large service classes, not scenes. But the same concept for scenes still applies to services and workers. I would create a new worker and start porting one tiny feature at a time. In the process, keep you eyes open for multiple workers. I’m sure you’ll find out a large service class will be better to be broken up into multiple ones. For example, at the very least, there should be a class to check for networking connection, a class to do the actual download, a class to check if the data is up to date, a class to persist to DB, …etc.

Regarding your concern about singletons, singletons by themselves aren’t the real problem. It’s the misuse of singletons that’s the problem. There are legitimate use cases for singletons.

Regarding dependency injection, the old code isn’t isolated in a way that facilitates dependency injection. You may be able to modify it to allow some dependency injection. But 99% of the code will not be kept, and thus the time will be wasted anyway. I recommend against that.

How the VIP cycle fully encapsulate the UserDefaults details from the rest of your app

One of my students asked in my mentorship Slack group (a monthly subscription program that you can subscribe and unsubscribe on a monthly basis) about how to use UserDefaults properly in a Clean Swift architecture. I’ve seen multiple takes on this question in other blogs. Here’s my take:

Question: I’m a beginner programmer and the CleanStore sample app is still a little complicated for me. Do you have a basic example that takes a number input and saves it to UserDefaults so I can follow the logic of the VIP architecture? I.E One scene sets a few properties of an object in the UserDefaults and another view gets the properties from the UserDefaults store.


Answer: It’s important to understand there is a difference between high-level use case and low-level implementation detail. For example, ‘saving the user ID’ is a high-level use case, whereas ‘saving a number to UserDefaults’ is a low-level implementation detail. You can save the user ID to a file, plist, UserDefaults, or Core Data, …etc. That’s an implementation detail, and it should be able to change without affecting the rest of your app. So we don’t create and name a use case as SaveNumberToNSUserDefaults. Instead, we simply call it Login. When you trigger the use case, you know the user ID is saved for later use. But you don’t care the mechanism by which it is saved. If the mechanism changes to save to a plist, you still trigger the same Login use case. The invocation shouldn’t need to change.

Let’s create a hypothetical scenario. In the Welcome scene, the user is prompted to enter the userID and password. After the user is authenticated, he’ll be shown the Home scene which displays a greeting containing his userID. In this example, we can save the userID to UserDefaults in the Login use case of the Welcome scene. After login, we’ll then retrieve the userID in the ShowGreeting use case of the Home scene.

Here is a sample project to demonstrate a simple login system using the VIP cycle. It saves the userID in UserDefaults.

Testing Asynchronous Operations

How would you go about unit testing your networking calls? They are asynchronous, so the results won’t come back right away. The following is an excerpt of the latest chapter I just added to my book Effective Unit Testing on this exact topic.


All the unit tests that you’ve seen so far are for testing synchronous operations. That is, the outputs can be observed and verified immediately after invoking the method on the test subject. The outputs can be function return values, state changes, or methods invoked on a dependency. All of these happen right away in the same thread. When you write the assertions in the Then phase, you’re guaranteed that the outputs have already been set so that you can safely compare the actual v.s. expected. You don’t have to worry about whether the outputs are ready or not. They are ready.

However, a lot of stuff that we do in modern iOS development are asynchronous operations, such as Core Data, networking, or even some expensive drawing code or events. The results will come, but not right away. It takes time for the task to finish, and the outputs be set. In iOS, these asynchronous operations are usually coded in one of two ways:

  • Completion handler block
  • Delegate method

Asynchronous operations present a challenge to unit testing. In the Then phase, the results may or may not have been set to the outputs for you to observe and verify. When you write your assertions, the test may pass this time (if the outputs have been set), but fail at another time (if the outputs haven’t been set).

The most common asynchronous operation is networking. Fetching data from an API over the network has latency, because data takes time to travel through wires around the globe. There can also be numerous points of failures. The server may be down. Packets can get dropped. Multiplexing can produce errors. Connection may be lost. There are many variables that can result in errors and/or delays. As a result, asynchronous testing necessitates some special handling. Fortunately, Xcode has built-in support to help with that.

As quoted in Apple’s URL Session Programming Guide:

Like most networking APIs, the NSURLSession API is highly asynchronous. If you use the default, system-provided delegate, you must provide a completion handler block that returns data to your app when a transfer finishes successfully or with an error. Alternatively, if you provide your own custom delegate objects, the task objects call those delegates’ methods with data as it is received from the server (or, for file downloads, when the transfer is complete).

Let’s look at completion handler blocks and delegate methods, separately, in more details. We’ll use a networking example that fetches public gists from the GitHub API to illustrate how to write unit tests for asynchronous operations.

Continue reading →