Домой United States USA — software A Case for Outside-In Development

A Case for Outside-In Development

318
0
ПОДЕЛИТЬСЯ

Outside-in software development focuses on first creating a decoupled, robust backend before developing the UI. Learn about the benefits of this approach.
There is no reason to have a backend when there is no front-end. There is no reason to have an API when there is no one to consume it. There is no reason to have a class when there is no other class (or framework) to use it. There is no reason to have a method when there is no one calling it.
Let’s look at some of the most important advantages of inside-out development:
Some questions related to the business requirements only emerge when we start working on the code. Start coding from the domain model allows us to focus on the business rules straightaway, giving us an opportunity to uncover business inconsistencies, clarify requirements with more details, and validate assumptions. Getting a quick feedback on important areas of the system is a risk mitigation strategy.
Investigative and preventive work that allow developers to uncover problems that can significantly change their understanding of the scope and cost of the project before investing too much in the solution. Identifying and mitigating risks before building too much code minimises re-work and helps to keep the cost of the project down.
Developers should work on the most valuable tasks first and there is a common belief that the domain model is arguably the most valuable piece of software. A counter-argument to that is that software has no business value if it is not used by anyone. From this perspective, the domain model only has value when the full feature is implemented and used in production.
User Interfaces are notorious to be volatile while business rules tend to change far less once they are defined. Starting with the business rules first allows backend developers to make some progress while front-end developers iterate on the UI design.
Let’s look at some of the disadvantages of this approach:
Without the guidance of a well-defined and concrete need from the external world (being a user interface or API — delivery mechanism), we can easily build things that are not needed. When we finally define the delivery mechanism and try to plug it in, we quickly realize that the backend does not exactly satisfy all the needs of the delivery mechanism. At this point, we need to either write some plumbing code to connect both sides, change the backend or worse, compromise on the usability defined by the delivery mechanism so that we can reuse the code in the backend as is.
Users or external systems consuming our APIs don’t care about our backend. We can only get feedback from them if we can provide something for them to use or access. It doesn’t matter what we do on the backend. If the user journey (via the user interface) or APIs are not suitable, our backend has no value. If the front-end or APIs are done after the domain model (backend), we will only get feedback when the whole feature is done and that is too late.
A great way to deliver software incrementally is to slice our features into thin vertical slices. This becomes very hard when we start from the domain model, as we are not writing code to satisfy a specific external need. Vertical slices should be guided by outside requirements and we won’t have them if we start building the domain model first.
Without being able to find a proper thin vertical slice, we need to wait for the whole feature to be done in order to get feedback and deploy. It is also difficult to predict when a feature will be done when the delivery mechanism is treated as an afterthought.
Another danger of focusing on the backend first is that when the backend is done, developers are generally out of time or not so keen to work on the front-end. They end up rushing the front-end implementation causing two main problems: a) a bad user experience, b) lower quality standards when compared to the backend, leading to a messy and difficult-to-maintain delivery mechanism.
Mobile, front-end and backend teams should not work in parallel while the APIs are not defined. This is also true for cross-functional teams where mobile, front-end, and backend developers are in the same team. 1 Having backend developers defining APIs cause a lot of friction and re-work once mobile and front-end developers try to integrate their code.
Let’s take a deeper look at the advantages of Inside-Out development and check if they are real advantages and if some of them can be applied to Outside-In development as well.
One of the biggest advantages of Inside-Out Development is to tackle the core of the system first and hopefully uncover unknown problems — this is called risk mitigation. But is risk mitigation a thing we should only do in Inside-Out Development? Are all types of risk mitigation and exploratory work at the same level?
Quite often we are not sure what the solution for a given business requirement should look like, how the business requirements should be designed, which tools we should use, or how some frameworks work. Some exploratory work is needed. 2
Let’s look at some categories of exploratory work:
There is a difference between trying to uncover unknowns as early as possible and actually delivering a feature. They should not be part of the same task. Whenever we are unsure about what needs to be done or how things should work, we should create a spike (or any other time-boxed activity) to investigate the problem. Once we have more information we can then commit to building a feature. Do not mix exploratory work with feature development.
Among the four categories above, I find there is value to create separate spikes for Technical, Architecture, and Macro Design investigations but not so much for Micro Design. That’s an area of my code that naturally emerges through Outside-In TDD. Discovery at micro design level normally has far less impact on the project than discovery at higher levels. That means that focusing on up-front design at the micro level is normally a waste of time, but the same is not true for the other levels.
Another argument to start development from the domain model (Inside-Out) is that the user interface (UI) is volatile and its implementation should be done after the domain model is finished. Well, it is often true that the UI changes more often than the business rules do, but do all the UI changes really impact the backend? Let’s have a look at the most common types of UI changes and their respective impact on the backend code:
Aesthetic changes are related to the look and feel of the UI — normally done by web designers, front-end developers and user experience specialists without any impact in the backend. Aesthetic changes are normally the most common type of changes in the UI.
Data changes are related to the data displayed to the user or required from the user. These changes involve a change in the data the existing APIs receive or return. The impact on the backend varies according to the data and the complexity to return or store the required data.
As discussed before, the way we decide to structure our delivery mechanism and domain model will make our backend more or less susceptible to UI changes. In a well-structured web application, changes in the backend can be significantly reduced if the delivery mechanism is fully responsible for the navigation of the system while the domain model is only exposing business flows and managing data. Although designed to satisfy user’s needs, the domain model should have no knowledge of how those business flows are presented to users.
Every user interaction with the user interface represents a user need. It is the systems’ job to satisfy the user’s need every time the user requests something. If the user only wants to navigate from one part of the website to another, then this logic belongs to the delivery mechanism and not the domain model. However, if the user wants to store or retrieve information, then the logic belongs to the domain model.
In order to agree on how we should design software, we should first agree with a few basic principles. For the rest of the post I’ll assume we all agree with the following:
Value is only delivered when the system is in production and satisfactorily used.
We should strive to deliver value as soon and as often as possible.
We should do the appropriate due diligence before building anything.
We should get feedback as soon and as often as possible.
We should always work in small and valuable increments.
We should keep things as simple as possible, but no simpler.
We should only build what really needs to be built, nothing more.
We should not work on technical tasks if they do not have business value.
Outside-In development is an approach that focuses on building just enough well-engineered code to satisfy an external need, reducing accidental complexity by removing speculative work.
Code should only be written to satisfy an external need, being from a user, an external system, or another piece of code.
We should only build what really needs to be built, nothing more.

Continue reading...