POSTS
System Architecture and Frameworks
A small starting journey into the world of software archtitecture
Recently I was on vacation and had a bit of time to my hands to read some books (Yeah I know.. ^^)
So I stumbled upon a book called Clean Architecture - A Craftsman’s Guide to Software Structure and Design
I think I’m a “good” developer, meaning I can get things done in a good amount of time.
The next big thing
As a web developer in the current time, I think I’m as prone as everyone else in this industry, to always want to use the next big thing.
There are many frameworks; there is React, Angular, Vue, “old” ones like JQuery or Backbone (if this is the correct name). But also newer ones like Svelte which is also different from the “older” ones like angular and react. Then there is are things like GraphQL and REST. Were GraphQL is really much better than REST but also not so really.
We have things like Firebase and AWS lambda, which is better than monolith but also not.
If we switch to other platforms, we have the same problems:
- App development: Flutter vs. React Native vs. Xamarin
- Server with Node: Express vs. Hapi and so forth
This brings me to the following conclusion:
We always think in terms of frameworks, not in terms of the system.
The point I want to make is the following: We focus more on the framework, which should be a tool to get our job done faster than on getting up our business rules.
My expierince
I have written a few applications at work in the last 3-4 years. They ranged from simple web pages, workflow solutions to document viewers, and normal SPAs.
I always tried to use the new cool thing, namely Angular on the frontend to GraphQL on the backend, to nest for my backend server. I could do this because I’m the only web developer, right?
I always thought, if I keep up with the latest and coolest framework, I would be a good developer.
I thought that the framework would make me good.
But after the initial features, which I could write in a very rapid manner. Things slowed down, always. It got hard to change things (in my opinion). It wasn’t smooth anymore. It felt sluggish to change simple things. A small bugfix would need an hour to change, not minutes like at the beginning.
Don’t get me wrong; I structured my code in the way I the frameworks advised me to. I would create modules; I used my service, I created middleware.
Example: A Angular SPA
No matter how I tried to structure my angular app (and, I’m calling it on purpose like this). It got hard to add features. I used best practices were I could to structure my ANGULAR app.
As mentioned above, I added modules to group components and used services to add my business logic and tried to keep my components as logic free as possible.
However, it got hard to add things; it got hard to refactor things.
I passed the Apptitude test
The funny thing is that the author of this book has a word for this Apptitude
. Without me noticing I was passing this so-called Apptitude
test.
What is meant with this is that someone is good at creating the first version of the app. We get it out to the market. Maybe we say ourselves, that we can make it better in the future, that we can refactor it to make it better. However, this is almost always a lie.
What we are missing is: We forget to add a clean architecture to our app.
But I get it done…
Yes, I know. This pill is hard to swallow. I had the same reaction while reading this book…
The statement which opened my eyes was the following:
A framework is just a detail.
When creating a software architecture, we try to structure our system into different parts. We use many principles, which were created, changed, and modified over the last decade by other developers as best practices.
Some of them are SOLID, REP, CCP, CRP, SRP, CQRS, …
These princliples were discovered while solving common problemes while developing software. Combined, they help us to make software that is easy to adapt to new requirements and keeping changes in the source code to a minimum.
What I mean with all of this
I’m currently developing a user portal, which shows the subscriptions of a user, make changes to his account (change password, email, address), buy new subscriptions and terminate old ones.
Because I know angular quite well I used it here as well.
In the beginning, I just started to good; this was before I had read this book. I created my services, and so on. You get the picture. I had traces of other frameworks everywhere. I used angular in every service, sprinkled Firebase into each of my services.
I was developing at a rapid speed. Man, I thought I was flying through it.
I had the profile page up in no time, had my log in working with Firebase in matters of a few afternoons (working a few hours each afternoon)
I was quite proud of it until I wasn’t anymore. After reading this book, I went over my Angular App again. Moreover, it was screaming ANGULAR. It wasn’t screaming USER PORTAL, which should be the case.
Refactoring
So I started with my newfound wisdom:
- Use cases and actors - I went over my requirements again and tried to group the use cases (requirements) by actors (who is using it). This satisfies the SRP at the highest level (not at source code level)
- I started to extract my business logic from my angular services.
Why I extracted my business logic? Because the framework should only be a detail.
I started to make a base class for my user. This abstract base class defined all the logic a user should be able to do. I created a repository to handle the creation of a user (namely logging in and out), and I created an interactor that encapsulated everything from my angular service.
I also made sure that my business logic doesn’t know what is using it. It shouldn’t matter if I call it from an angular service, a react app or from vanilla JS.
With the base user class, I’m also able to switch my authentication system. If I want to change the authentication provider, I can do this because now all the firebase logic is encapsulated in my FirebaseUser.
My FirebaseUserRepository
is responsible for creating each instance of these. However, they both are a specialized version of the User
and Repository
class which are used by the interactor (which gets the repository injected through the constructor)
Conclusion
What I want to get over with this post is, that architecture is independent of which framework you want to use. It doesn’t matter for the higher-order business logic what is calling it. And it shouldn’t know and care about.
Also knowing about the SRP and trying to keeping the higher-order logic away from the lower order logic is a blessing.
I developed for four years without recognizing these principles enough and fighting the consequences of this.