When I had some time off between jobs, I needed something to work on (I get restless without something to do). I contacted Bill at MindSea to see if he had any need of some contract work. We’ve been bumping into each other online for years. He had some work for me to do, so I jumped on board.
I set about doing the things contractors do: setting up email accounts, configuring source control, logging into Trello boards, and – most importantly – getting familiar with the codebase I’d be working on.
This post is about doing things the right way instead of the easy way. It’s about taking time to write properly abstracted, modularized code instead of one giant class. In order to make that point, I’m going to talk about two things relating to my brief time at MindSea: ramping up and abstractions.
The codebase I’d spend most of my time in was the East Coast Music Association app. My first impressions of working with the ECMA app were very positive. There is a bit of a sniff test I use when first working with a codebase. That test includes:
- How long is an average view controller?
- How long is the app delegate?
- Is there lots of layout code in view controllers?
The ECMA app passed my sniff test with flying colours.
Most view controllers weighed in at a modest few hundred lines of code. Very encouraging. I check for the length of the longest view controller and the app delegate because they’re indicators of the level of engineering that has gone into the codebase. Proper engineering, not just software development, emphasizes well-abstracted, modularized code.
The app delegate was responsible solely for app delegate-appropriate things, like responding to application lifecycle events. When the app is first launched, it loads some custom fonts and appearance. And that’s it. Perfect. The application delegate is a convenient spot to place things, since it is accessible from anywhere within the application code. However, this convenience often comes at a cost: a bloated app delegate is difficult to manage and usually involves de facto global state, which is better avoided if possible.
Finally, I always look for extensive layout code in view controllers. Somewhat famously, MindSea uses Storyboards. The ECMA app uses Storyboards and Autolayout. There were only two lines of code referring to Autolayout constraints in any view controller. Spot-on. The role of a view controller is to manage the hierarchy of its root view property. While it’s *technically* acceptable to lay out that entire hierarchy in a view controller, it’s not advisable. Managing the state of an entire view hierarchy often leads to bloated code that’s hard to maintain. If layout in code is necessary, it’s better to subclass your view instances and have them lay out their own subviews, instead.
I was able to get going and start fixing bugs and implementing features in no time. As I mentioned earlier, the sniff test is meant to measure the level of abstraction and use of modularization in a codebase. Let’s talk about abstractions now.
Abstractions matter. They matter a lot. Programmers are not, as Rob Rix puts it, paid to type. We’re paid to think. The abstractions we choose matter because they dictate how we – and future programmers – will interact with the code.
I once worked with a company that told me if just two lines of code are repeated, then there’s probably a better abstraction that I should be using instead. A bit extreme, I know, but I took that to heart. I haven’t looked back and that advice has served me well.
Abstractions have a downside, too. While each piece of code might be highly-cohesive and easy to understand, the complex behaviour demonstrated by a complete product requires these simple pieces to interact. When your code is in more pieces, it takes more time to understand where those pieces are, how they interact with one another, and how they achieve their common goal.
There is a balance to be struck, I believe, between something so abstract it takes weeks of study to fully understand and something like a three thousand line view controller. If you have a bloated view controller that’s managing a lot of internal state, it can be a nightmare to debug, refactor, and expand.
So where do you draw the line? I think that, with experience, one is exposed to more abstractions. The larger your repertoire of abstractions is, the easier it is to recognize situations in code where one would be appropriate. As much as reading can help, I don’t believe that there is any substitute for experience.
With a properly-modularized codebase using the proper abstractions, I was able to get ramped up and building new features in no time on the ECMA app. These abstractions took time for the initial developers, but it paid off when a new developer came on board. Remember that you only write code once, but you read it many, many times. Writing well-abstracted code is an investment that pays off later, and I feel privileged to have worked with a team that understands that.
EDITORIAL NOTE: This guest blog post was written by Ash Furrow. Ash is the author of several books on iOS development, and shares his knowledge through his blog, ashfurrow.com, and as a guest speaker at conferences around the world.