The elephant in the room: The context
We tend to talk about this is good, this is bad when we talk about engineering practices, principles, designs, etc. In software everything…
We tend to talk about this is good, this is bad when we talk about engineering practices, principles, designs, etc.
In software everything is a trade-off, we need to understand what’s working best for the context we are working on.
context: the situation within which something exists or happens, and that can help explain it
https://dictionary.cambridge.org/dictionary/english/context
Software is managed by some forces that pushes it through different directions, some of them:
Customers
Competency
Time
Knowledge
Building vs Running
People
Money
All of those things around your code, your company and your workforce are in fact the context in which your code is written.
Basically, to create something, you have to answer the question of what can we do to solve this problem to our customer in a way that we can obtain more money than the investment we are doing with these people and their knowledge?.
But this is just the starting point, perhaps, you don’t have the people to build your product, perhaps you don’t have the money to invest in everything.
And this is usually the situation, all those factors are constrained by our current circumstances.
The scenario changes all the time, there is no final stage, people will arrive and leave the company, investments will come and leave. The company will be reorganized, even it will be closed at some time.
In this scenario, your software needs to be affected by the context, it’s not that you can build the perfect solution apart from your context. Developers try to do that, but that’s only a loose of time and money.
There is no perfect solution, even if you try to implement it you are just creating overengineering solutions, this doesn’t mean every architecture or design is the same, it just shows the problem, good enough is much better than perfect.
But good enough change all the time, new features, new business, new people with new ideas change what means good enough. So instead of focusing on the perfect solution, focus on allowing your code to change easily, not to cover all the possible scenarios, just one and having enough things inside to allow the change. Software should be something easy to change.
Best practices, software design patterns, architectures are all of them things that work better under some circumstances. We need to understand those circumstances.
Open source
An open source project with a hundred of developers around the world (in different timezones) needs a way to verify that the code introduced by those people is not malicious.
The people that started with the project (a small group) need to control where the code go and how, so they want to preserve some characteristics, but they need the priceless efforts of the community.
In this scenario where trust is not a must, where the core group just trust on themselves, they need a tool to help to maintain their code.
Contributors will be working in their houses sometime, not always, they are not paid, contributors cannot agree on working the same hours every day. So in this context it’s better asynchronous communication because of the context on how the project is created.
Time is not so important, people don’t care if they have the feature this week or next one, money is not so important here, contributors help because they want to be part of something bigger.
PR’s seems to be a good fit in scenarios where you cannot trust.
Small software team
A few people working in the same timezone the same hours (or a similar set of hours seems) seems a different context than open source projects.
In this scenario, companies have offices to meet, there are meetings, coordination is much more important. Companies try to reduce lead times as much as they can to understand faster if their products work, if the new features work, etc.
So in this scenario where coordination is very important, where we trust in our people because we talk frequently with them, PR’s and async work is not the best way to solve the problem.
Pair programming, mob programming, trunk based development are practices to solve better the problem of working with trust in a team.
They will help you to solve problems sooner, with better quality and sharing the knowledge around the team.
Proof of concept
In a proof of concept, we are not interested on creating a product for the customer, we are interested on gaining enough knowledge about a technology or an idea to understand if this is possible or not in the real world.
A proof of concept (POC) is something we are not going to maintain, it’s something will not be used to gain money. Your customers will not see the proof of concept, so it is something that needs to be done faster, and I don’t care about bugs, edge cases.
The level of quality of a POC is irrelevant, we are not going to maintain it. It’s not going to live more days than the time it was built.
So do we have to write tests for a POC done by one person in one week to answer a question?. I will say no, we don’t need to write tests, we don’t care about the design, so we are not going to worry about that.
No tests means no TDD, the context tells you that you are loosing your time, because code is not the important part here, but gaining knowledge.
Software that will live years
In the other side if your code will live years, if it will be changed by several different developers during the next month.
If your code is going to live more days than the time required to be written, in that case you need to care about maintainability.
So testing is important, it will help you to maintain the functionality that you want to maintain in your code.
Because your software has a basal cost that grows and grows with time.
If you are in a situation where every five years you are rewriting everything, your organization is not very good on maintainability. Right now, in this scenario (software that lives years), it is cheaper to change software by updating it than rewriting it.
Native app
If you are building a desktop application, for example for a PC, you have some limitations on the release process. You can release a new version of your software, but usually you cannot force people to use it.
You need to live maintaining different versions of your code, you need to think about a sunshine process to discard some of the versions at some point. Because no organization is able to maintain all the versions of their code all the time.
At some point some of them will be deprecated, in this scenario fragmentation is an important problem to focus. This is why I say that libraries have a hidden cost that we don’t usually pay attention.
You will also need a branching model that help you with different versions, when you have to fix a security issue in one old version.
Gitflow can help you in this scenario, where multiple versions are a fact, and you need to maintain them.
Web app
If you are building an application, and you can force your clients to use the latest version, in that scenario the fragmentation problem disappears.
You don’t need at all to focus on old versions, there is only one, the latest one. So you don’t need for all different branches or tags, you just need to sync your system with the latest versions of all the parts.
Continuous Integration and Continuous Deployment are great ways to achieve this in the most effective way.
I don’t know to test
This is another big problem, the knowledge, it’s impossible to have hexagonal architecture if just one person in the team understand the term.
So it will be key to share knowledge to allow learning inside the organization.
If your organization only thinks in terms of feature factories, the company will need to fight against difficult problems.
High levels of technical debt, high rotation, poor innovation.
Continuous improvement
If we create an environment where change is the normal thing to happen, the context will change to adapt better the knowledge and the code to the current problems we have in the organization.
The context matters, but the context can change, it can change top-down and bottom-up. Usually, top-down is much more effective, but sometimes people hack the system to continue working in the old way.
Bottom-up is much more difficult because middle management resistance that usually feel these changes as something against them. But in the other side, bottom-up if you are able to convince middle management is much more effective.
In general context matters, we need to select the trade-offs taking into account the context. But context changes continuously, we need to be ready for changing our practices to adapt better to the new situations.
We need to learn faster, as always the more important thing in software is to adapt.