I probably should have waited for the next iteration, but I was starting a new side-project and, well, there was that checkbox to use SwiftUI staring at me, taunting me, luring me in with the sweet promise of unending UI layout bliss. So I scrunched up my face, clicked the box, waited a minute for the trumpets to die down, and then created the project.
I’ve been a native (emphasis mine) mobile developer for many years, having learned on iOS 31; and ever since, I’ve been a staunch supporter and firm believer in native-only development. Cross-platform development? Eww, gross, and language please; those words are dirty. No thank you, sir. I’m a clean developer, a master craftsman who actually cares about their work. I don’t slop things together in whatever language. No, I use
objective-c Swift. Native-first, native-only, hoo-rah (fist pump)! I breath rarified air from a bag.
Or maybe 4? I know I released my first app on iOS 4, but I can’t recall if I actually started in iOS 3. Let’s just say 3, cause it sounds better, right? Also, that fish I didn’t catch because I don’t fish was at least 80 lbs. ↩
One of the key pillars of good architecture revolves around Interface Design. The reason for this is deceptively simple: software is complex and we want to do everything we can to make it as simple and easy as possible. Part of the entire point of OOP (Object Oriented Programming) is to abstract complicated code into objects and then hide that complexity behind a simplified interface. That way programmers don’t need to know what’s going on behind the scenes, and instead can deal with the abstraction. The interface should be the only thing someone needs to know about that object to use it. The only time someone should even consider the implementation is when they’re modifying it. This is an essential tool in battling the complexity of a codebase.
Most developers have heard of the Single Responsibility Principle (SRP). It is one of the principle pillars of SOLID and frequently touted as a core principle that all developers should strive for when designing their code. It is also one of the least understood principles I’ve ever seen. Most developers will agree that it’s really important, but these same developer will have a hard time defining SRP means in concrete terms. They have an even harder time translating the amorphous concept into their code.
Over the past few years, I’ve seen an increasing interest in software architecture as an important, perhaps now even an integral, part of software development. While this may seem obvious now, it’s still surprising to me just how much architecture is considered as an afterthought by many developers. At least in the mobile space, it’s taken a long time for architecture to enter the foreground of the conversation for software development. But even as the discussion about software architecture grows, I’ve noticed that the conversation tends to center on individual architectures as a solution to specific problems inherent in software development. You can see detailed descriptions of VIPER, MVVM (and it’s variants), the ubiquitous MVC as well as a scattering of others for app development. While each of these solutions do address specific set of problems 1, what they do not do is teach developers how to create their own architectures to address problems specific to their own development. As such, many developers will try to use an existing architecture to solve the wrong problem, or else failing that, to forget about architecture altogether and hobble along as best as they can.
Now that I’ve spent quite a bit more time implementing a “handler” based development approach, I’m finding that there’s quite a bit I like about it. I still have some frustrations with it, and some unresolved questions, but overall I think this approach has some serious merits that warrant consideration as an Architecture approach to handling complex dependencies.
Lately I’ve been writing a Swift module for a project at work. I decided to branch out a little bit by utilizing a different design philosophy than I’ve used in the past. While Apple sits around and pretends that protocol based development is actually something new and exciting, I’ve been much more interested in the functional abilities that Swift seems to endow us with. To that end, I decided to escew protocols and instead define the dependencies in my objects using handlers1 instead. This means instead of defining a protocol and requiring an object that conforms to this protocol, I simply require the specific behavior itself. An example of a simple handler might be:
Or callbacks, functors, whatever… I’m going to stick with the term “Handler” because it seems to implicate the dependency, like I’m depending on someone else to “handle” the dependent behavior I need. If you want, feel free to copy this and do a search & replace for callback or functor or another term you feel more comfortable with. ↩
If you read my Architecting Complexity post, you know I feel pretty strongly about the need for Software Architecture 1 in software development in general, but especially in “app” development. So far, I’ve not gone in to very much detail into my approach to applying Software Architecture to software development. To be fair, I’m going to focus only on app development, but many of the principles here apply much more broadly. It just happens that developing apps is something I do a lot, so I’ve developed a consistent strategy regarding it.
Yes, it should always be capitalized. ↩
There are a lot of blog posts and probably even more opinions about Swift. I will continue this short, but certainly worthy trend.
When I first started developing software, I made very limited use of protocols. I would occasionally model my software from what I’d seen Apple do with delegates, but once blocks came out I mostly abandoned delegates for callbacks, which I much prefer despite the inherent risks of reference cycles and the weak dance. Because really, why would I want to write my interface in a completely separate file when I already have a convenient “header” file right here. And yet, as I’ve continued to build software and especially as I learn more about software architecture, I find my eschewing interface files and depending on protocols more and more. Let’s just say I’ve become a convert to “protocol based software development”. What exactly do I mean by this?
As a contractor, I come across a lot of other people’s projects and may I just say, there’s a lot of crap out there. And I mean that. Not just “Oh, this developer could have done better here and there”, but more alone the lines of “Sorry, I can’t work with this. Your best option is to rewrite the whole damn thing.” To be clear, I’m not necessarily talking about a person’s coding skills. Certainly, I’ve come across some questionable code and downright stupid approaches to solving problems, but this is not what I’m talking about. I’m talking about a complete lack of any kind of architecture to the codebase. Too often I come across projects that seem to be trying to typify the “anti-design pattern”, usually by stuffing quite literally everything into the View Controllers.
There are three things I told myself I would not do when I started developing in Swift:
My wife used to come home and jokingly complain that I’d sat around all day typing in gibberish into a computer screen. Well, of course it’s gibberish to the uninitiated plebeian. We call it a “language” for a reason. You’ve gotta study and learn the language; you’ve gotta speak it and immerse yourself for the jumble of random characters to magically transform themselves into a document full of meaning and, if you’re really good, perhaps even profundity.