The Perfect Model-View-Whatever Architecture By Ryan Kay (MVP/MVC/MVVM)
This article was originally meant as a relatively jargon free exposition of the different shifts in perspective I went through as one striving to master software architecture and design. If you please, let me take you on my journey from beginner all the way to novice; where I’m at now. ;)
Part way through writing this article, I had to confront the issue of why it’s even worth it to chase perfection of software design, and some recent horror stories from some of my brogrammers and siscripters, prompted me to push back on the opinions of what I will call “pseudo-pragmatists”; to be defined eventually.
If you would like to see my current style of architecture explained in code (Kotlin code, that is) without my storytelling, I discuss my current approach to end to end architectures in Kotlin, in this video. It was live, so expect minor technical issues.
There was a time several years ago, when I spent several weeks attempting to learn all that I could about Model-View-Presenter. MVP, is a GUI (Graphical User Interface) architecture, or pattern (depending on how you define the term); which promotes a separation of three different kinds of code (analogous to data, user interface, and logic).
Being a self-taught developer with little direction, the applications which I had built previous to that time, followed the Big-Ball-Of-Mud-Architecture (no discernible architecture at all; just several huge files). Prior to my learning task, I had just come across an open source application which presented something approximating Model-View-Controller. It was the best code I’d ever seen (although I wasn’t even sure what that meant), and I felt strongly that further investigation was required.
“I am feel. I am very feel.”
- Oleksandr Usyk, Undisputed Cruiserweight Boxing Champion
In retrospect, the fact that I was almost illiterate of what could be considered quite-mild software jargon, would eventually teach me a very valuable lesson in learning new programming concepts. In any case, no matter how many articles I read, my brain was simply unable to see what all of these verbal definitions meant; let alone how to actually apply them in my monolithic code bases.
It’s not that I had difficulty with the general idea of what was going on, but rather that I was frantically trying to find an exact definition of Model-View-Presenter; based on vague, surface level explanations of what each aspect of it meant. I could have spat out some verbal recitation of what I thought MVP was, but I was missing the most important aspect of any concept in software development and design: knowing it in the code.
After a week or two of frustration, I concluded that reading another five articles was not going to help me. Instead, I decided to just build the simplest application I could think of, which could employ some kind of separation between user interface, logic, and data.
I built a calculator.
I believe the effect this had on my learning process is worthy of a different article, so I’ll address it another time. Although I didn’t do the best job of actually implementing MVP, it was the first time that I prioritized understanding a concept through direct experience, as opposed to working off of abstract verbal definitions.
The Right Explanations
Not long after, I happened to be listening to Fragmented Podcast, and hosts Kaushik Gopal, and Donn Felker, mentioned that they held Martin Fowler’s work in high regard; as far as GUI architectures are concerned.
Note: I mention these names to give credit where it’s due; not to imply that this article necessarily reflects the same opinions of these individuals whom I owe a debt of gratitude towards.
After diving in to Martin’s explanation of “Passive View”, I was very fortunate to have finally come across someone who cared enough about people like me, to actually explain how to build it, when to use it, and when to consider alternatives. This was quite a treat for me as I really had lost almost all of my faith in programming teachers at this phase in my studies. The overwhelming majority of explanations I was given, were rubbish in all ways except SEO efficiency; at least to a beginner like me.
While Martin supplied me with a far deeper understanding of what MVP actually looked like in a serviceable example, he also introduced the idea that its primary benefit was testing. This was another very novel idea (I mean the idea of testing in general), as the only explanation I’d seen of unit tests and/or instrumented tests was a bit of platform documentation that was possessed of a horrendous degree of assumed knowledge and jargon. I mean no disrespect to the platform engineers, but it quite literally scared me away from something which I could quite easily explain to a child at this point (in concept, to be specific).
I won’t be focusing on the testing aspect of architectures in this article, but I brought that point up to re-emphasize that testing and architectures (which apply separation of concerns, dependency injection, and code-to-an-interface), go together like pancakes and syrup; or perhaps like mathematical theorems and proofs if you’d prefer a less tasty but more accurate analogy. They really do compliment each other well.
Some time later, I was starting to feel damn happy with the front end architectures of my applications (Dunning-Kruger effect perhaps), but the fact that I was only thinking in terms of three layers (MVP), turned out to be yet another unfortunate road block. Specifically, it seemed like the general consensus was that the model (that which persists, and provides access to, data), shouldn’t have much logic in it. While I do believe that to be a good principle, the question of where to put complex back end logic haunted me for quite some time.
My first approach was to make my presenters very intimate with the various parts of my back end (don’t get any funny ideas about that sentence). This wasn’t a big deal in small applications with one or two IO devices, but in my more complex applications (with things like user authentication and remote IO devices), my presenters started to fill with a horrendous mass of nested asynchronous functions (the staircase to callback hell). Once again, I started hating how damn ugly my code had become.
I recall feeling quite dejected at this point, as I’d gone as far as advocating people adopt MVP architectures for it’s ease of legibility, testing, and organization. But in truth, I wasn’t quite passing the test of high-cohesion in my own projects. There were also plenty of limitations imposed by my platform that I did not have the skills to circumvent; which meant that I was almost always breaking separation of concerns in order to compensate.
I knew what I wanted to build, but my reality hadn’t quite caught up to my ideals.
Cleaning Things Up
I owe a great deal to Robert C. “Uncle Bob” Martin as well. He has on a few occasions (about twice), confused the hell out of me; but I never quite got as far as saying that he was wrong in those situations. Given that he has been building software for longer than I have existed in this shared reality simulation, I’ll give him the benefit of the doubt.
After muddling through for a time, and having to take a break from programming for many months (don’t ever lift heavy weights with bad posture), I watched a video of Uncle Bob explaining “Clean” software architecture. The first time I watched the video, my brain didn’t quite know how to process what had just happened. It was like someone just hammered on my neo-cortex with decades of wisdom and experience. Even passing comments gave me solutions to problems I didn’t even know I was about to run in to.
So I watched the video again, slowly, and took notes. I made a list of the different labels he used, but instead of looking at articles, I searched for open source code samples. Much to my luck, I came across Fernando Cejas’ great project here. It took quite some time for me to understand his repository (it was was far more advanced that anything I’d seen before), and I even went as far as going through every class in it, and attempting to explain the purpose of each one in my own terms.
Between learning the API stack and design which Fernando employed, and studying a good deal of Uncle Bob’s work on SOLID design principles, I was for the first time ever, starting to feel like I didn’t suck at programming completely. At the same time, I made friends with a few other young developers who were happy to learn, discuss, and share these ideas with me. Although it’s in my character to try and learn everything on my own terms and at my own pace; I am very much a product of the open source community.
Shut Up And Tell Me What The Perfect Architecture Is!
That’s about how I imagine you, dear reader, are starting to feel, so let me get to the part where I really disappoint you. There is a light at the end of the tunnel however; I simply mean to give you the most truthful representation of what I think about software architecture and its relevance to us developers.
After a while, when you’ve seen as many different approaches to software architecture as I have, you start to get the feeling that there’s about as many ways to do Model-View-Whatever, as there are developers doing Model-View-Whatever.
If you spend a bit of time experimenting with different styles, you’ll tend to pick up a few new tricks each time (it is worth it!), but you may also start to recognize that almost every architectural pattern works well in certain situations, while simultaneously being counter-productive in others. Variables such as the scale of the application, (multi-)platform requirements, user interface complexity, network access, and one’s propensity towards test coverage, largely dictate what a given developer would consider to be an optimal solution for the problem at hand.
To make matters even more confusing, there are a fair number of individuals out there who are strongly convinced that architecture is a waste of time. In fact, a good deal of very commercially successful applications have no discernible architecture whatsoever (I have no real metric for how many, but if you go looking, you’ll find plenty of horror stories). I can’t even say that if your only goal is to get the client to sign the cheque as fast as possible, or you just happen to have a giant marketing apparatus and a half-decent idea for a product, that architecture mastery is worth the blood, sweat, and tears.
Now that I’ve plausibly crushed your dreams of finding the one universally applicable style of building applications, and stated that it isn’t necessary if you’re only goal is to fill the emptiness in your heart with piles of cash, I reckon its time to give some encouragement to my fellow craftspeople, students, and ethical entrepreneurs.
Be Uncommon Amongst Uncommon People
- David Goggins (@davidgoggins)
I’ll now speak very plainly about what I feel it means to want to be good at your profession, and the benefits of walking a path to architecture mastery. I’ve in the past, offended some well-meaning individuals who thought I was being critical of their skill levels or intentions, and I wish to emphasize that I’m only intending to offend individuals who confuse pragmatism with greed and laziness (I call them pseudo-pragmatists, as I have nothing against pragmatism in general). I don’t care if you suck at programming as much as I did when I started (this isn’t false modesty, I was worst in my class in high school); I simply wish to give you something other than money to chase after. Don’t worry; if you’re really good at what you do, you’ll find a way to get paid and actually feel like you earned it.
You Will Begin To Attract The Right People
I won’t explain why, but I was truly a misanthrope as a child, and I had plenty of good reasons to be. At this point, I feel both humbled and blessed to have met individuals from across the globe (quite literally), whom I now consider to be brothers and sisters (or brogrammers and siscripters as I’ve taken to calling them). There are people out there who are willing to help you, encourage you, teach you, and show by example that what you thought was your best, is but a fraction of your potential.
This isn’t some law of attraction bulls**t; you will need to put yourself out there to some degree to meet these people. Start by sharing your progress (public repositories are a great start), and don’t make the assumption I made when I started; that programmers are by and large, critical and rude. The ones who are any good know exactly what you’re going through, and will often go out of their way to help if you ask politely and respectfully.
A word of warning though: Don’t ever ask someone to do your work for you. That attitude and approach will likely be met with resistance or critical response; and rightfully so.
You’ll Stop Making Your Life Harder And Risking Your Reputation At The Same Time
Here’s a secret that the pseudo-pragmatists will never fully grasp: Building, maintaining, fixing, and modifying monolithic piles of s**t is a horrendously annoying thing to do (regardless of monetary incentive). But since that’s all they do, they won’t know anything different.
Instead of focusing on solving logical problems, building more efficient algorithms, and sorting out complex problem domains (I don’t know if you’re the same, but I was wired to enjoy that part of programming), they’ll be endlessly roadblocked and frustrated by all the bad decisions and corner cutting they made even moments prior to their current task.
To give you an analogy from a different profession I’ve worked in, this is directly equivalent to being a carpenter who:
- Fastens an entire structure together with nails instead of screws because nails are faster and simpler (you’ll find mistakes are hard to correct as you’ll often break many things just trying to rip out and replace a single board)
- Doesn’t create a properly measured foundation (you’ll find that if you’re foundation is off by even a small amount, as a matter of geometry, you will have to make greater and greater compensations as you continue to build the structure from the ground up)
- Doesn’t build the structure in a well-thought out order (you’ll therefore frequently make stupid mistakes such as installing drywall without realizing that you forgot to account for doors and windows in the frame of the structure)
A good number of carpenters will go through their entire life applying such an approach.
With that in mind, who do you want to hire? Who do you want to work with? Who do you want to be an apprentice to? Who do you think will attract the best clients, repeat business, and unapologetically deserve high compensation? I hope those answers don’t require much contemplation for you.
You Will Start To Enjoy Learning New Things
The best programmers learn new skills, and practice their craft, every day (well, 98% of days; sometimes a short break is necessary to reignite your passion). The most poorly kept secret I can give you, is that the way you become damn good at what you do (not just decent), is that you must work harder than almost everyone else.
Unfortunately, if you don’t actually enjoy the process of building applications, you will learn less efficiently (interest and enjoyment are directly tied to retention of new information), and you will be fighting your own motivational capacity every step of the way.
When you start to see how applying separation of concerns, using abstractions, and writing tests (among other things), allows you to create more legible, scalable, modular, and logically sound applications, you’ll probably start to be excited about exploring new architectures and approaches. Not to mention, you’ll eventually reach the point when you can take all of the knowledge you learned from the masters, and the experience of solving difficult problems with patterns, and use this to create truly unique solutions to the most difficult aspects of software development!
When learning is directly tied to the quality, monetary success, and ease of production of your projects, you may even begin to feel like your day isn’t complete if you haven’t learned something. That’s a good place to be, since there is no completion; only progress or stagnation.
It’s always a struggle for me to decide whether to speak my mind or not on these topics. Whether or not you believe me when I say it, I don’t ever wish to imply that I’ve mastered my craft. At this point, I’m content to just enjoy walking my path without worrying so much about how far I’ve traveled (other than as a general indicator of progress). It’s also become my greatest joy in life to try and help others find their way in whatever capacity I can.
I was recently given horror stories from several Junior Developers in the wiseAss community who have worked their asses off to secure their first jobs in the IT industry (many of whom are like me in that they couldn’t afford an education). It hurt me quite a bit inside to hear that there really are developers and project managers out there that actively discourage the idea of having skill, respect, and appreciation of their craft.
Not only did this force me to confront my own demons as an extreme perfectionist (I’ll admit, by many standards, I don’t care enough about the bottom line, I just want to build amazing software and share what I’ve learned); but it made me question why I work so hard to improve my skills every day.
Now that I’ve taken stock of the situation and reflected on my own progress as a student of software development and design, the conclusion that I’d like to share with anyone who is about to enter the professional world, is this:
If your team or employer doesn’t actively encourage you to become better at what you do, or they tell you that good software design is a worthless endeavor, I’d advise you to do three things:
- Smile, nod, and do what they say (they’re paying you, and it’s their right to dictate business operations in this way)
- Keep studying on the side and learning from open source projects
- Prepare an exit strategy, and employ it as soon as it makes sense to do so
Good luck on the path, and know that there are good people out there, even if you have to go through hell to find them.
The Part Where I Ask For Something In Return, But Expect Very Little
If my rambling was of any use to you, then please do me a favour and consider supporting me, and the wiseAss community in general, in attempting to encourage new developers to invest in their skills and education.
Since almost all of my content is free, if you have any inclination to help me with this goal, the answer is: Yes, I do need your help in whatever capacity you can provide.
Support wiseAss here: