The clean marketing architecture
It has never been about refactor
Clean does not mean refactored, or even correct
It means clickbait / buzzword, and some ritual you can join as part of the community; It becomes a social identity.
Like Introducing MVVM into your SwiftUI project.
This is another snippet pulled from the same official same app
Where is view model? Why do you need view model? Why do you need a tutorial telling you to build something you don’t need? There are even tutorials telling you to build
ViewModelProtocol before you can build view model.
Note that it uses the name
MemeCreator , not
MemeCreatorView . It doesn’t need to be interpreted as a view. It can be interpreted as a model, even a controller in some sense. Isn’t this what I’ve been saying? This is the model side of a model-view binding. You cannot access view directly because
var body is a computed property; and you cannot mutate model directly because it’s a immutable value type. Dual protection.
Note the usage of @State, they are properties that don’t need to be shared. So what’s the point of moving them to a @ObservableObject, which is not value type and can be shared?
Note the composition of protocols
Sendable . Why do you need
ViewModelProtocol for generics? Think of composition in terms of vector space: v = ax + by. You design protocols so that they are orthogonal, i.e.; independent and self-contained. Then you build your app from a basis in vector space. Most of the time you work in value type, which cannot be mutated or inherited. Composition is key to refactoring your codes.
Do you also notice that I’ve got all that from working on a code snippet? I’ll show you what happens to those who think they are too good to study official tutorials.
Ultra ultimate clean architecture with Combine based on dependency injection plus Redux-like state management that fixes SwiftUI
I pulled this snippet from a Clean Architecture for SwiftUI + Combine github.
Compare this “fetch” with the
PandaCollectionFetchershown above in Apple sample app.
This is a perfect opportunity to check your skills. This is what code review is all about. I highly suggest you think about it before reading on. (besides the usage of async/await, which is new)
- load function can be refactored
You’d argue “but Panda doesn’t refactor it either!”. Hint: one is beginner level tutorial, one is the cleanest architecture proposed by multiple veteran contributors with a combine of decade+ experiences.
It isn’t about refactor then, is it?
If you bother to refactor it, you can do it in a function call
getImage(url:) which can be easily reused as part of a
webservice. Function over object.
Not everything has to be an object. Do you need a type
Adder that conforms to
Additionwhen all you want is
a+b ? Do not over-generalize.
Interactor by definition is stateful. A fetch is stateful.
When you have mutable state, you use reference type. What happens if you don’t? Value type becomes a redundant wrapper.
In this case, the code passes a
webRepository into interactor so it can call
Then wtf didn’t you just directly call
webRepository.load(imageURL:) without a f-ing useless wrapper! This wrapper has to conform to some
ImageInteractor shit when it’s
webRepository that does all the heavy-lifting. You can easily extend
webRepository to take in an extra parameter.
Let me remind you how a low-tech, beginner fetch is done in official sample.
class PandaCollectionFetcher: ObservableObject
A reference type!!!
Putting reference type inside a value type is code smell. You can induce any kind of side effect via reference type. But you pass it around like an immutable value type which should not induce side effects.
MVVM doesn’t need to consider this because there wasn’t value type back then, or in Java.
By this single line, you can tell
a. these guys don’t even know that Interactor is about state management, yet they create all these fancy names and protocols that will eventually serve no purpose
b. lack of understanding of basic networking
c. lack of refactor experiences and emphasis
It isn’t about refactor then, is it?
The marketing architecture
You are not thinking the big picture.
The big picture is NOT to write highly refactored code in production.
The big picture is to sell tutorials and earn ad revenues from youtube so you don’t have to write dumb shit code anymore.
We need to look at this from a business perspective.
- Telling people to study official tutorial is bad for business.
2. You need something iconic, routine that can be reproduced times and times again so people can feel they are participating in concrete production activities.
3. You want to throw in buzzwords, and create problems in SDK that need fixing as appetizer. This gives participant a sense of purpose. That they are using techniques to solve problems. It also takes away their focus when they are busy figuring out all the redundant protocols and generics they have to write.
4. If you were a lazy developer but wants to retire on ads revenue, what are your options? Are there well-known “architectures” that require people to write more codes, preferably brute-force code that need repeating for every view?
Of course there are. That is the industry. That is what you google for. And they know what keywords you google.
For example, you heard about MVVM. You google swiftUI MVVM. Then there is “clean architecture + Combine + Redux that fixes SwiftUI”.
You are thinking “oh shit, that is a lot to learn, I need to subscribe to some author/youtuber”. That’s how they got you.
You may be thinking, that you can then search for tutorials without MVVM.
Bang! They got you again! There are already videos on youtube that teach you how to write SwiftUI without MVVM.
It’s in fact very clever if you think about it.
First they sold you tutorials on MVVM. And when you finally had enough because it doesn’t seem to go anywhere but boilerplate after half a decade, they smell this and sell you tutorials on “why you don’t actually need MVVM”. Then they sold you how to write without MVVM. Fool you once, twice, thrice…
The same procedure can be applied to Clean Architecture, VIPER, VIP… basically all variants of MVVM. The one thing they have in common beside view model, is that they don’t want you to refactor.
Refactor is to make a piece of code reusable. Or if you are SDK, automatic.
If you have to create a view model for every view, why isn’t it refactored?
See how SwiftUI refactors it. You still have binding, but doesn’t require additional overheads.
Because it isn’t about refactor, is it?
I mainly discuss MVVM variants here, but note that SwiftUI essentially makes it automatic. So it will be increasingly difficult to maintain this mirage when tides are turning.
As you can see, people are already applying marketing architecture to Redux-based SwiftUI.
As a wrap, I’m going to do a quick code review of the Redux aspects from the same author in above github. You can use it as an exercise to check your understanding of SwiftUI.
Why you quit using @ObservableObject for wrong reasons
This is the article. Why I quit using the ObservableObject.
I’ll sketch his arguments first. Paraphrasing, so take it with a grain of salt.
First he said “single source of truth” is a buzzword. What’s next? Dependency injection is a buzzword too?
He then claimed SwiftUI has performance issues, which becomes a problem when you use Redux AppState which is a app-wide state management.
Since AppState is global, it must contain states irrelevant to some view. When a view updates itself due to irrelevant state changes, it causes performance issues. This is reasonable, because a view shouldn’t update when its state does not change.
So to solve this problem, he needs a “filter” on publisher to filter out only target state changes. If you are familiar with SwiftUI, this means you should use Combine for full-fledged publishers instead of @ObservableObject, which is a specialized publisher as a shortcut.
He went on ranting about how @ObservableObject is awkward to be customized (because it is not designed to be a generalized publisher), so he quit using it after various attempts.
He blamed it on SwiftUI, saying @ObservableObject is dog shit (obviously I’m paraphrasing), unfit for Redux. This is obviously dog shit, in my opinion.
If you are not going to use @ObservableObject, you don’t have @EnvironmentObject, which leaves you only @Environment. So you need to define environment keys and such.
Then you use full-fledged publisher with proper filtering, i.e.;
RemoveDuplicates , which of course requires repetition for every view.
Finally, with filter, you can subscribe to only target states to avoid unnecessary view updates induced by global AppState.
Now the challenge for you. Can you one shot his arguments? As in shutdown, nullify, negate, counter his arguments with one simple refactor. No pressure, this guy is only the face of SwiftUI clean architecture.
I’ll share mine.
Then don’t use global AppState. Only observe states you need using @ObservableObject or better yet, @StateObject. Since irrelevant states don’t affect you, why subscribing to them then filtering them out?
Then you realize you’ve come full circle back to vanilla SwiftUI SDK. This is what happens when you think you are too good to study official tutorial.
To be fair, this article is written in late 2019. It’s not fair to judge it using years of experience, but then again, he never felt the need to take it down or correct it. The github is last updated just months ago. His article about how MVVM is the new standard in SwiftUI is still a top search result.
That’s what I’m talking about.
It has never been about refactor. Clean never means correct, or well designed.
Clean is a marketing architecture.