I was recently following a link to The Wiki, the original c2.com wiki by Cunningham & Cunningham, Inc. It was a link to the FourLayerArchitecture page. At the very bottom, it currently says “Last edit August 25, 2006”. In the early 2000s, the wiki had to be closed for editing by the general public because of abuse, and this page seemingly lays dormant ever since.
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 am using ReSwift in my app. I like ReSwift because I can create a representation of my app in a “State” Swift module without any UIKit/AppKit dependency. There, I put all the data that the app is supposed to represent at any given moment in time. To get a feeling for this, have a look at two apps of mine:
The folks at Swifting.io wrote a blog post about iOS software architectures. The comparison of VIPER and Clean Swift/VIP is very interesting: the VIP approach favors uni-directional flow, which I like very much. The article is worth a read for that alone!
They falsely consider MVC and MVVM to be software architecture approaches, though, and too point out that MVVM and MVC suffer from similar drawbacks.
When facing a legacy code base, changing the mess to an orderly architecture can cause confusion: where to start? What to do? An exemplary question: How do I refactor a Big Ball of Mud into layered architecture? Refactoring the existing code base seems like a logical step; after all, refactorings are designed to improve existing code, and improvement is what you’re up to.
Picking up on my post “MVVM Is Quite Okay at What It Is Supposed to Do”, here’s a few images which illustrate the problem of mistaking MVVM for a solution to a structural problem. It’s the whole post in 2 images. Model–View–View-Model helps with the view layer. It can be a tool to break up a view controller into smaller things. But it’s still only a refactoring of view components into more objects.
As soon as you write a piece of software, you “architect” it. Can’t get around that; but if you do not do it consciously, the resulting structure may not be great. Taking ownership of the process is important to change the result and create maintainable software. When we write/architect software, we worry about two things:
Criticism targeting MVVM (Model–View–View-Model) from late last year essentially points out it’s not the silver bullet some take it for. Most of the stuff is missing the point. How are you supposed to make sense of it? What’s good advice for your project?
They moved to a Flux-inspired “unidirectional flow” approach where state changes are performed in a Store (in the backend, if you will) and updates pushed to the user interface (the frontend). No ad-hoc view updates, no shortcuts. User events are emitted, handled by the store, and state updates affect the view. That’s it. So it’s always obvious how the user interface got into the state it’s in: all the details are plainly visible in the current state object.
Ben’s post is very deep and detailed. You’ll learn a ton from it:
architectural discussion: why “unidirection flow”, and why Flux?
setup of actions/events and the store type
basic state–view bindings via Reactive Cocoa
how testing stores (and views) is straightforward with this setup
I can’t wait for the next post in this series. Most of this easily applies to ReSwift, too, of course. And guess who just got inspired to refactor TableFlip so the model and view become even more loosely coupled?
Façades are very important tools when I flesh-out the modules of an application. They turn out to be only the logical consequence of basic object-oriented programming principles, internal cohesion of objects namely, paired with decoupling of application modules (like “model” and “view”). Take a complex view that has many subviews. When you need to update a single piece of the user interface, how do you get there?
Now that TableFlip is nearing completion, I want to share details of how I created this piece of software with you. Today, I’ll start with the bigger picture: the application architecture. Earlier this year, I got to know ReSwift from a talk by Benjamin Encz which I loved.
Sam Ritchie wrote “Building a Unidirectional Data Flow app with Realm” the other day. I haven’t worked with Realm before, but the state propagation seems super interesting now that I dabble with ReSwift from time to time. His post excited me to try out Realm, soon.
Chris Eidhof of objc.io put some experimental code on GitHub where quite a few Cocoa view components are contained by classes he owns himself. The AppDelegate is super instructive: Your Cocoa app needs an NSApplicationDelegate. But it doesn’t have to do anything except route events to the proper collaborators. Still it’s the first object we usually put logic in only to (hopefully) refactor it out later.
One of the commenters nailed it: any MV* variant focuses on architecting view components. Only VIPER takes the application as a whole into account. MVC by itself is an architectural pattern, but not an approach to app architecture in itself.
A UIViewController belongs into the user interface layer and is, in fact, a composite view itself. That’s confusing at first because of the name. This insight will liberate you from thinking that a view controller is sufficient to glue data to UIKit components. There’s room for a whole application between these two.
The VIPER example is exceptionally good. It takes VIPER’s heritage of Clean Architecture and Hexagonal into account and defines the Interactor through an output port. In that way Bohdan’s sample code is more east-oriented and cleaner than what you’d usually find on the topic:
protocolGreetingProvider{funcprovideGreetingData()}protocolGreetingOutput:class{funcreceiveGreetingData(greetingData:GreetingData)}classGreetingInteractor:GreetingProvider{weakvaroutput:GreetingOutput!funcprovideGreetingData(){letperson=Person(firstName:"David",lastName:"Blaine")// usually comes from data access layerletsubject=person.firstName+" "+person.lastNameletgreeting=GreetingData(greeting:"Hello",subject:subject)self.output.receiveGreetingData(greeting)}}
Usually, you’d model provideGreetingData() as a function that returns the data to the caller. This will cause trouble in async processes of course.
You see in the full example that the amount of types seem to explode. Don’t be afraid of that as long as you can assign each type a specific responsibility. Then it won’t turn into the mess everyone seems to be afraid of.
Having used VIPER in apps myself, I see a problem with the names, though. XYZInteractor and XYZPresenter aren’t much better than XYZController in terms of expressiveness. On top of that, a concrete Presenter is always modelled to act as event handler, too. Don’t let this fool you into thinking you absolutely have to do this yourself – there’s always room to separate writing from reading operations, or event handling from view population.
I really like the power of enums in Swift, so I was naturally inclined to see what the presentation “Simplifying Login with Swift Enums” by David East had to offer. Here’s the setting: you’re going to offer multiple ways to authenticate users with your app. How do you model this?
Lammert Westerhoff compared MVVM to Presentation Controls recently. Since nobody likes massive view controllers, I had a look, too, and found a few interesting things. To write a real app with his tips in mind, we’re going to need a bit more, though, and refactor things a bit.
It happens that just yesterday I read about architecture smells in code. Among the examples was “subclasses don’t redefine methods”. In my post about Core Data and expressive domains earlier this week, I did just that: create a Egg subclass of CoreDataEgg to inherit CoreDataEgg’s behavior. That’s not what abstraction to superclasses is meant to do.
It happens quite a lot that I want to create a small UML diagram. Mostly for this website, but often for books, too. All the Java-based Mac applications get on my nerves quickly, though. That’s when I found draw.io the other day. It’s simple, lightweight, and works from within your browser with various storage options.
Oy vey, now there’s a ton of AltConf 2015 talks online, too! So much to digest! In “250 Days Shipping With Swift and VIPER” by Brice Pollock, he shows how the folks at Coursera do some clever things with the VIPER iOS app architecture: they use a Router which handles internal URLs.
Ryan Quan of Brigade Engineering has published an article about using the VIPER iOS app software architecture. Their write-up is really good: message passing is illustrated with code samples – and they even use neat box graphs!
I use a VIPER-like approach in my apps, too, and I’d like to invite you to try it for yourself. VIPER is inspired by Clean Architecture and Hexagonal.
In a nutshell, you decouple the view controllers from event handling from data management. You introduce so-called “Wireframes” to set up a module or “stack” of objects to display a view controller with certain data. The Wireframes set up everything once. Afterwards, event handlers take over, called “Presenters”. They perform transitions between scenes. View controllers do not much more than setting up the view and reacting to IBActions.
This will make maintaining code easier because the view controllers are finally put on a diet. Figuring out how data has to flow differently takes some getting used to. I’m going to write about this in a future post.
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.
I’m working on a way to make the Word Counter watch files and folders on a user’s disk. This will enable to measure project progress. Until now, I always used .plist files to store records with the end in mind that I’m going to switch to a better alternative in the future. Since I’m adding all-new data tracking, I thought I might as well try different solutions now.
Some time ago, I read about database design and mapping object hierarchies to database tables. Ruby on Rails’ default approach is to use a technique called Single-Table Inheritance. This design pattern has some drawbacks.