One mistake we make a lot of times as Software Engineers is letting frameworks define our architecture. It should be the other way round.
According to Ivar Jacobson, Software architectures are structures that support the use cases of the system. Just as the plans for a house or a library scream about the use cases of those buildings, so should the architecture of a software application scream about the use cases of the application.
Notice how easy it is for you to identify a bank when you see one, or say how easy it is to identify a stadium when you see one. That’s the effect of architecture.
Now using a bank as an example, when you see a bank, right from the entrance, you can almost notice a security door, one or two ATMs. As you enter, you can expect to see a long desk with a few people as cashiers. You’d expect to see some seats for people to sit while waiting. You’d probably expect to see a desk where you can pick up forms or fill them. And lots more.
All these features have been identified to be influenced by the use cases. A bank is expected to have a security door for the safety of the staff and customers. ATMs are important for instant withdrawal of cash. A long desk with cashiers is needed for customers to be attended to for cases of deposits and the likes. Customers would need to fill deposit forms, account opening forms, etc and so would need a desk to pick up the forms and fill them. All these speak of use cases of the bank. This might not be so for the case of a library, where you’d expect to see more of bookshelves, tables and chairs, etc.
Let’s imagine what could have happened while architecting the bank:
|We need to have a safe entrance to the bank.||Installs a security door|
|Having a location for instant payment won’t be bad.||Installs Automated Teller Machines|
|Our customers need a space where they can be attended to.||A long marble desk with cashiers.|
|Customers would need a waiting area||Comfy seats would be nice.|
Above is a simple mapping between a few architecture concerns and frameworks used – Bank use case. From the above table, we could notice a trend, the architecture is defined, then a framework/tool is chosen. A bank does not choose to have a safe entrance because they have a security door, instead, a bank chooses to have a security door as a tool/framework to cater for the need to have a safe entrance (architecture). The same concept applies to the rest as well. This means the framework is flexible, can be changed/replaced without the architecture being affected negatively.
Now let’s take a look at a software system, using mobile app as case study.
We now know that a good architecture is centered on use cases so you, as a software architect, can describe the structures that support those use cases without necessarily committing to frameworks, tools, and environments. Meaning, in the process of architecting a mobile app for Company X, the first concern is to make sure the app is usable, not the frameworks to be used. Emphasis that is to be made should be the use cases, not the environment. A good software architecture allows decisions about frameworks, databases, and other environment-specific issues and tools to be deferred. The decision to use Room or Realm for database, RxJava, Coroutines, RxSwift or Combine for asynchronous programming, all could be decided much later in the project. The decision to change your mind about those tools should be easy as well, given a good architecture. Meaning, in a few months, if you decide to change from Realm to Room, or say from RxSwift to Combine, you should be able to do so seamlessly and with no issues of regression.
A good architecture is testable. Having carefully chosen your frameworks, you should be able to unit-test your use cases without any of these frameworks in place. You shouldn’t need your remote network connected to test a “fetch data from remote” use case. Likewise, you shouldn’t need your database connected to test a “fetch data from local” use case. This would be possible with proper dependency inversion, layer separation and mocking put in place.
A good architecture should tell readers about the system and its use case, not about the frameworks you used in the system. Say you are building a banking or financial system, any engineer who looks at the source code should have the first impression of “Oh it’s a banking system”. And such an engineer should be able to learn all the use cases of the system without necessarily knowing how the system is delivered.
So what is an example of good software architecture? Well, ever heard of Clean Architecture? Watch this space for articles describing how Clean Architecture could come to play in architecting your mobile applications to be well-decoupled, scalable and testable.