In any development team that’s even slightly bigger, solid tools will become an important efficiency enabler. They can make your developers much more productive and perhaps even more importantly make your project or projects more cohesive, making it easier to move developers between various parts of them and increasing maintainability.
My company, Thorgate, can be described as product development agency. We currently have around 15 developers who work on multiple projects with lifespans ranging from few months to several years. We’ve learned the importance of investing into solid tools and lifting your team to the next level. Although this post is largely written from an agency’s point of view, the ideas are very much applicable to software development in general as well.
The History of Thorgate Project Template
One of the most important tools we use is our project template. It forms the foundation of most of our work and helps us get started much faster than would otherwise be possible. It also forces a set of conventions and best practises on our projects, which makes it a lot easier to exchange knowledge between different parts of the team. This has many benefits that we’ll look at shortly.
Our template was born out of both idealistic desire to find and follow a set of best practices, as well as of a pragmatic need for executing different projects rapidly and encouraging synergy and reuse between them.
Most of our projects are web applications built with Django and we often use React for the frontend. Django gives us a solid framework with conventions and guidelines out of the box, while React ecosystem was pretty much a wild west when we started using it. In both cases, as our portfolio grew both in the number of projects as well as their complexity, we began feeling the need for a higher level of standardization within Thorgate.
Our biggest pain point was projects diverging from each other. It meant that working on them required even more project-specific know-how and similar problems in different projects frequently had different solutions for no good reason. We needed a way to maintain our sanity and bring back some level of coherence to our projects.
In essence our project template can be described as a set of best practices for developers to follow. This covers both the choice of components and packages to use as well as coding style and other considerations. We aim to have a single coding style, a similar structure and same frequently used packages shared by all our projects.
On the one hand, this simplifies onboarding of new developers who can learn the practices of not just one project but of the whole company right from the start. They also have more people to ask from, at least as far as the basics are concerned, and get coherent answers.
On the other hand, your existing people and projects will also benefit by the knowledge that gets more distributed throughout the company. Having a ready toolbox of common components makes the developers more effective as they can focus on assembling these standard components and working on the product-specific pieces, instead of making the same component choices again and again plus trying to figure out how to use them.
This is similar to how Bootstrap brought standardized and good-looking UI elements to the world of web development. Arguments can be made about Bootstrap vs other similar frameworks, or about the choices made by Bootstrap developers. But I think it’s indisputable that the push for standardization it brought was extremely useful.
Another important goal of the template is to ensure coherent development practices. The template helps ensure that we usually choose one solution for each problem and then use it throughout all our projects. This includes choices ranging from project structure to how unit tests are created and executed, to how we deploy projects.
Obviously each project is different in its own way, but mostly they have common chunks that can be standardized across the company. As a result it becomes easier to move people from one project to another and reassign people if need be. Project maintenance is also alleviated – as soon as one project is upgraded, the lessons learned can be used in others. Finally, it also helps to increase quality and consistency as good practices are continuously promoted throughout the company and applied in all your projects.
On the whole, the template is meant to remove roadblocks from our developers and bring consistency to their work.
Building Your Foundations
Now that the purpose of a good foundation is clear, how do you begin creating one?
In my opinion, one of the most important choices is the right level of abstraction. The foundations you build need to support real-world projects and real-world usecases, and thus have to be practical enough. On the other hand, you’ll want to be able to reuse your foundations for a variety of different projects which requires flexibility and generalization.
Picking the right level abstractness thus involves quite a lot of revisiting of previous projects and figuring out which parts of them are also being used elsewhere and could be standardized. The approach I’ve chosen is to develop common features in the projects where they’re used and include them in the template later, when the same functionality has popped up in two or three projects in total. Writing two or three solutions to a common problem often gives you insight into subtly different requirements of each package which might not be clear at first. This is also referred to as Write Everything Twice (though also often used negatively in the context of code duplication) or the Rule of Three.
Your projects are dynamic - their features and requirements change over time. What was useful a year ago might no longer be practical today, and more recent projects often require additions to your toolbox. The foundations have to reflect that and keep up, or they will become obsolete. Changes to the foundations don’t come without risks though. Ideally you want all of your projects to be kept up to date and use the most recent versions of your tools, in order to make use of the resulting synergy. However, if these tools change too much without backwards compatibility or easy migration path, the overhead of staying up to date might be too big and your projects can’t keep up.
It is thus advisable to keep the number of breaking changes to a minimum and get the bigger architectural decisions with largest impact right at the start. Easier said than done of course, but keeping in mind the suggestion of writing two or three solutions to a problem before including them in the template often helps.
Obviously your foundations can consist of multiple pieces. As an example, in addition to the project template, we also have a companywide wiki which is more convenient for storing non-code information. This includes the standard components lists as well some how-tos and best practices.
Finally, solid foundations can also improve communication between different roles within your company. They can serve as a baseline for project managers, designers, as well as developers so that all parties know what to expect. As an example we’re also trying to standardise the used components between designers and developers. This has the advantage of designers using common components already at the design phase, knowing what each of those components is capable of and how they can be used. They will also be more aware of how each of those components can styled. All this will mean less changes and conflicts when the developers begin implementing the designs.
Similarly project managers can tap into this shared knowledge and be better able to communicate the time costs, advantages and disadvantages of related technical decisions to customers. They can offer faster feedback to client ideas and are better able to represent the more technical side, knowing which changes could be implement quickly without much custom development.
Ultimately you will end up with a companywide shared library of well-known components capabilities and limitations of which are known to various parties throughout the company. Obviously each product will have its own needs and will also need custom components but the time and quality savings of component reuse should not be underestimated.