A S.O.L.I.D Design
As mentioned in a previous post, I just recently led the launch of a search focused web application. It’s time now to reflect a bit on the techniques and technology used.
From the start I was looking for a supporting framework that was conducive for rapid development that did not sacrifice stability, integrity, or consistency. I wanted a set of tools that not only allowed our developers to quickly build out features, but also avoid getting stuck “in the trenches” building out core function. My approach to accomplish this was leveraging a collection of object-oriented principles, frameworks, and debugging tools. I’m going to break this up between those three since they are each interesting and important, starting with the principles I used for the project.
For me, commonly accepted design theories are ideas put to practice that have been vetted and adopted by the consensus. While it’s still important to be innovative and be a free-thinker, I believe in standing on the shoulders of giants; building from what is known to work. This does not limit the ability to be creative or do something different, but instead empowers by laying out benefits and avoided caveats through comprehending the principles.
Object-oriented design can be nebulous and feel vague, but this is the spirit of object-oriented architecture. Concepts are abstract and isolated, which allow them to be independently combined to make a whole. What’s important to take away is they are a means to an end: a solidly structured application that can efficiently be extended and maintained.
With that said, it is time to go over the concepts I went with, which can be place into three groups: S.O.L.I.D, MVC, and ORM. Both MVCs and ORMs seem to follow the S.O.L.I.D pattern, so there is overlay, but that doesn’t mean they are required to follow any of the S.O.L.I.D principles. As said before, object-oriented concepts are intended to be independently applied.
To me, what this all means is you have a system comprised of objects that each have a unique role. They play nice with each other, and don’t get greedy and take over another components role. This is an awesome design pattern, because it keeps roles encapsulated and extensible. It reduces the chances of rogue code lying in wait. And by separating out roles and keeping objects decoupled, it is much easier to build new features without modifying core code that would results in testing and bugs.
Organizing the three key layers of a web application is essential to to keeping an orderly, and reusable codebase. Logic can be separate into at least three basic “buckets” by role: Model, View, and Controller. This structuring isn’t meant to be taken as absolute, and does not directly translate into a specific file structure. There is code that will fall outside the model, controller, and view role, such as components that handle routing and security. Instead, like other OO principles, it is a set of guidelines to help achieve a better codebase.
The interface in which data is accessed can dictate many design factors of the web application. An ORM allows data to be accessed and manipulated as normal objects. All business logic is encapsulated within the data object, instead of being strewn about the application. This means that data is accessed consistently throughout the application through a set of centralized objects and tools . While this concept introduces a level of complexity compared to straight queries or a light wrapper, the ability to work with data as a collection of objects is very powerful and clean.
This project was a test of how necessary it was to create a S.O.L.I.D application. The organization of code, and separation of roles had enormous benefits that kept me sane. Our course was not without trial and error. There were times these principles weren’t followed, and it resulted in fragile and inflexible components that haunted us later in the project.
There is a quote that I like that goes “There is no problem in computer science that cannot be solved by adding another layer of indirection, except having too many layers of indirection”. There is a conundrum of simplicity vs extensibility. Adding that extra layer all depends on what the desired endgame will be for the application, and it can be a difficult judgement call.