Instead of talking about a specific technology or a specific project, in this post I will talk about software architecture and avoidable mistakes.
It would be far easier to talk about and praise the successes, but I find mistakes an interesting topic nonetheless, mainly because they are very useful in bettering the learning process.
I’ll start by providing a bit of context and then share my views on software architecture, which I believe to be the most important part of software development and how to avoid falling into the most common traps.
A starting point
When any programmer is asked the question: "Which do you prefer: starting a project from scratch, or maintaining an existing one?"
They answer: "Starting something from scratch!"
This may seem obvious because the sense of accomplishment is usually greater if we can say: "This is my doing (at least a considerable chunk of it). It did not exist before, and now it does!"
But there is more to it. The human brain likes order, it likes to infer patterns from the chaos and apparent random information. On software development, this is also true.
But what happens in an existing project? It's likely that the project already has some level of perceived chaos in it and it certainly has more than a non-existing one.
Therefore, the immediate response is to prefer starting a project from the ground up, where you can control that chaos completely according to your experience.
Of course, in software Utopia, we would never do something that would introduce chaos by our own negligence. Alas, we do not live in that world, but we do have tools and principles to guide us.
Good architecture saves the day
The best tool we have available for dealing with the pesky tasks of regression, fixing bugs and the like, is forward planning. A good architecture is our friend.
A well designed solution is worth thousands of hours since it'll really save us a lot of time in the future.
Most of us have read the books, we know the things to do. We also should do tests and apply the design patterns religiously. “Let's really focus on keeping this MVC; let’s apply BDD for this; let's design the feature tests before we write production code.”
Sometimes, we forget the importance of what the first step should be, even before all that.
Sure, before you write production code, yes, please go ahead and write your first tests.
But even before writing your first tests, the design team have probably already gathered all the requirements, negotiations have been made with the client and the other stakeholders, they might even have produced a few versions of the design of the product you're about to build and they were pre-approved, so you might think that you should start coding soon.
Except you shouldn’t.
The whole team should sit and talk about the product they're about to build. They should grab a piece of paper or go to a whiteboard and start enumerating all the features the product is going to have.
Clearly identify all the technical requirements and feasibility of the proposed solution. Challenge every step of it and really imagine a solution using a different approach, maybe different frameworks, even a different language.
Bottom line is, there isn’t such a thing as spending too much time on architecture.
Learning with mistakes
For me, one of the best ways to learn is by making mistakes.
Since making mistakes can be embarrassing or frustrating, when we do make them, we tend to pay attention to what happened and strive to find the solution and figure out the best way to not make that same mistake again.
That equals experience.
"Experience is simply the name we give our mistakes."
Recently, I’ve been working on a fairly complex iOS project. Right at the start of the project, there were a few things that were off. Requirements were not 100% defined, pre-requisites were not 100% met, APIs were not yet ready...
But probably the most important thing was: we had not defined the architecture of the project as well as we should have.
I only became aware of this when the damage was done, of course. There were lots of regression, rewriting of features and several times I said to myself: “Why haven’t I done this the right way?”
One such pitfall was that no testing framework was used. At all. Tests and validation were made with user tests and sparse peer code reviews. Then, when a testing framework was indeed brought to the project, it was too late.
One of the best known and accepted frameworks for iOS development simply did not play well with all the intricacies, multiple languages and bad decisions made when designing the product architecture (from a technical perspective).
A better approach: a few rules of thumb
Back to the drawing board. You receive a new project, and you even might have been involved in the requirements gathering phase. Regardless of already having an idea of the overall technical solution for this project, I would recommend:
1. Write everything down. Make schematics, component diagrams, class diagrams, flowcharts, whatever you feel necessary to help you - and the team - understand the full picture of the problem at a quick glance.
Refer to it as often as needed. This will probably be revised several times before the first line of code is written.
2. When all the components/modules are identified, try to find solid existing solutions for them. Open sourced frameworks are the way to go as they are already being used by several people and therefore, tested and a lot more bug-free than your own custom solution might become.
3. When choosing external or third-party frameworks, make sure they “play nice” with the rest of the frameworks. Try to find enough evidence that confirms compatibility between all the frameworks you’re going to use.
Having to change frameworks during development because you found out that something does not work as intended when in presence of another framework, forces you to spend time searching for a different solution anyway, and will make you waste even more time making those unwanted regressions.
4. Choose a good test framework. Similarly to the previous step, make sure the test framework will work without effort with all the other frameworks you’re going to use.
A test framework is only as good as the coverage it can give you on a particular project. If it’s not well suited, or outright does not support a specific technology or module you’re planning on using, don’t rely on it.
Testing 8 out of 10 features is not good enough.
For the next project I’ll be involved, I’ll do my best to follow these principles and update them as needed. Perhaps one or more of these assumptions will be challenged and refined.
If your own experience has taught you differently, feel free to share your views and recommendations on what the first steps to take when starting a new project should be.