You can only improve things inside the frame you pick. If your frame is too narrow for the problem you try to solve, you cannot properly take everything into perspective. That’s a trivial statement as it’s only re-stating the same thing, but it’s worth stressing. Apply this to code. If you focus on code heuristics to improve your code base, you cannot improve the structure of your program. Even though the structure is manifested as code, it’s not code you should be thinking about. It’s concepts. Code is just the textual representation you stare at all day. Structure is what the imaginary entities of your invention bring forth.
I like to see that Soroush and I think among the same lines. For one, that makes me feel less like a loony. And since he writes a lot more in recent months, it means my sloppy blogging schedule does not affect spreading ancient wisdom. In February, Soroush blogged about writing “Just Controllers”: service objects, usually reference types, that you use to orchestrate processes and offer a simpler API. Requiring a delegate to be plugged-in is one way to design a simpler API: the delegate procotol defines all the output events from the service object, or controller. That’s all there is going to happen as far as outside code is concerned. But on its inside, the controller can do the fanciest of things to accomplish its goal. These implementation details are hidden from code that uses these service objects. It’s object-oriented programming 101 all over again – encapsulation, information hiding, stuff like that. But, and this is a big But, the go-to massive view controllers in iOS apps are a symptom of not encapsulating properly. Go and delineate a few more boundaries inside your app. As with raising children, boundaries help your code grow properly, too!
Dependency Injection means you do not create objects where you use them but “inject” objects a function/method/object depends on from outside. This is a useful trick to make code testable, for example. Once you adopt the mindset, it becomes second nature. From the Java world stems the imperative to program against interfaces, not implementations. In Swift, this means to define injected dependencies not as concrete types but as protocols.
The other day, I wrote a post about bind() and the >>= operator and how it can help chain function calls together. The example was a bit too contrived and making it fit the requirements left us with really bad code. I came up with an even better implementation: use plain Swift objects and express your intent carefully.
Singletons have their use. I use two Singletons regularly in my projects: a DomainPublisher and a ServiceLocator. The latter is a registry of service objects which is global so the service objects don’t have to be. For practical use, most Singletons are overcomplicated or overly restrictive. Here’s how I suggest you implement Singletons in your apps:
There’s this saying that the Strategy pattern can be realized in Swift using blocks. Without blocks, a Strategy object implements usually one required method of an interface (or protocol) to encapsulate a variation of behavior. This behavior can be switched at runtime. It’s like a plug-in.
Erica Sadun brought up a topic which is bugging me for some time already. It’s how Swift encourages you to handle optionals. It’s related to handling exceptions, which I covered earlier. Either you use if-let to unwrap them implicitly and do all the stuff inside the nested code block, or you end up with code which is a lot wordier than I’d like it to be.
This is an excerpt of my book “Exploring Mac App Development Strategies”, on a sale right now! I learned that the “view model” in the architectural style of MVVM is a “model of the view” instead of a “model for the view”. Let me explain the difference and the benefits of being able to chose between both.
UIStoryboardSegues are a blessing to add rudimentary navigation between view controllers in iOS projects. User interaction can trigger segues without any code. That’s all good and well to move back and forth between mostly static scenes in your Storyboard. Passing data around is not so easy, though, without making things more complicated.
Srdan Rasic wrote a good post on creating wrappers around value objects (like Strings, say) and custom-glue them to an application’s interface. It’s a technique I have used in my book on Mac architecture at one point but which seems to be tremendously useful for virtually anything view-related once you get to a high enough level of abstraction.
It’s weird that articles related to programming are so hard to quote. Instead of a quotation, let the resulting code illustrates what he has to say:
class ArticleViewController {
var bodyTextView: UITextView
var titleLabel: UILabel
var dateLabel: UILabel
var thumbnailImageView: UIImageView
var viewModel: ArticleViewViewModel {
didSet {
viewModel.title.bindAndFire {
[unowned self] in
self.titleLabel.text = $0
}
viewModel.body.bindAndFire {
[unowned self] in
self.bodyTextView.text = $0
}
viewModel.date.bindAndFire {
[unowned self] in
self.dateLabel.text = $0
}
viewModel.thumbnail.bindAndFire {
[unowned self] in
self.thumbnailImageView.image = $0
}
}
}
}
So now when viewModel’s properties change, the view controller will update the corresponding interface component. Sweet.