Incremental Architecture
Embarking on a software project entails traversing distinct stages, each demanding a unique mindset to ensure success.
In this article, we delve into the three fundamental phases I prioritize and shed light on my strategic approach throughout each stage.
-
Initial Phase: In this context, the primary emphasis lies on fostering a culture of learning and experimentation while striving to provide value to the project. It’s crucial not to become overly fixated on pristine code or achieving the perfect architecture during this stage. Since you’re not yet live and modifications come at a lower cost, seize this opportunity to explore and test different approaches.
-
Recovery phase: The timing of entering this phase may vary for each project, contingent upon factors such as project duration and associated deadlines. The critical aspect here is to consolidate all the insights gained from the initial phase and begin improving the project’s architecture with a focus on achieving a clean and streamlined domain.
-
Pre go-live: In the weeks leading up to the go-live phase, it is crucial to take the time to thoroughly assess any potential gaps in the project. This includes ensuring the presence of robust monitoring and alerting systems, establishing a streamlined deployment process, addressing operational tasks, implementing effective roll-back solutions, and incorporating essential functionalities. Devote these days to completing all tasks that will ultimately facilitate smoother production support for the application.
Initial Phase
When starting a project, it’s important to recognize that getting a clean architecture right from the beginning can be challenging. The truth is, no matter how hard you try, the initial requirements are often incomplete, making it difficult to achieve perfection. Instead of striving for an ideal architecture, it’s more effective to adopt an incremental approach and focus on learning and understanding the domain.
To lay a strong foundation, take the time to delve into the intricacies of the domain. By immersing yourself in the subject, you’ll gain valuable insights that inform your decision-making process. Through an iterative methodology, gradually introduce design principles into your application. Start small and experiment with the domain, allowing for flexibility and adaptability to future changes. This way, you can refine your architecture based on a better understanding of the true requirements.
By generating functionalities, you’ll gain a deeper understanding of the specific needs of your domain. This knowledge helps you prioritize the essential components while distinguishing them from the less critical ones. Focus on the core needs and design an architecture that truly serves the project’s objectives.
Establishing Boundaries for Maintainable Code
In software development, there’s always a trade-off to consider. It’s crucial to avoid creating an unmaintainable codebase. To mitigate this risk, focus on defining clear boundaries and establishing robust interfaces between components as you build them.
For instance, if you decide to delay implementing a database in the initial weeks, you can still define an interface and follow the repository pattern to access some form of memory storage. This approach allows you to continue development smoothly, while keeping the option open for integrating a database seamlessly when the time is right.
Setting good boundaries not only helps you defer critical architectural decisions until you have more information, but also enables you to introduce new features and continue learning along the way. By implementing well-defined interfaces, you create a foundation that promotes flexibility and adaptability as the project evolves.
Clean code masturbation
Clean code is undoubtedly important, but defining it can be a subjective matter. If you ask your teammates to define clean code, you’ll likely receive varied responses. For instance, I personally consider clean code as code that is easy to test. If your code proves challenging to unit test, it may indicate a flawed implementation. Adopting a mindset focused on testability helps create code that is both easy to understand and test.
However, it’s crucial to avoid fixating on finding the most sophisticated and elegant solutions during this phase. Remember, the code will inevitably change. Instead of spending excessive time pursuing the perfect approach, prioritize practicality and pragmatism.
The emphasis should be on finding effective solutions for the present, acknowledging that the codebase will evolve over time. By prioritizing functionality and maintainability, you strike a balance between clean code practices and the need to deliver timely solutions.
Recovery phase
As a project progresses, there comes a point when the need for change becomes evident. As new functionalities are added, the realization of existing issues and repetitive tasks becomes more apparent. This is a clear indication that it’s time to invest and make changes to your system.
The advantage of waiting until this stage to invest in refactoring lies in the fact that you now have a set of functionalities that provide valuable feedback and insights. This knowledge allows you to refactor your code in a way that makes sense and facilitates easier adaptation for the next phase.
By leveraging the feedback and lessons learned from the existing functionalities, you can strategically restructure your codebase. This refactoring process aims to improve the overall architecture, enhance maintainability, and increase agility for future changes and enhancements.
Embracing the recovery phase as an opportunity to invest in refactoring empowers you to address underlying issues, streamline workflows, and optimize the system for better performance and scalability. By capitalizing on the feedback and knowledge gained, you can make informed decisions and create a codebase that is well-positioned for the next stage of development.
Harder reviews
Good code review plays a pivotal role in enhancing project outcomes. It offers a fresh perspective and helps identify potential issues, ensuring higher code quality and reducing the likelihood of bugs. Additionally, code reviews foster knowledge sharing and collaboration among team members, leading to improved overall codebase consistency and better long-term maintainability.
Pre go-live
After investing months, weeks, or even years into project development, the long-awaited moment to go live has arrived. As this milestone approaches, it is crucial to dedicate part of this time to address any lingering technical aspects. Ensuring a seamless deployment and rollback process becomes paramount, alongside implementing a robust monitoring and alerting system.
While it is ideal to have these elements properly established from the beginning, there are instances where developers may overlook them. However, this should not serve as an excuse to launch a system into production without a well-defined roll-out plan and operational processes in place. Taking the time to meticulously prepare and optimize these technical aspects guarantees a smoother transition and helps mitigate potential risks during the go-live phase.
By prioritizing the establishment of a streamlined deployment process, a reliable rollback mechanism, and an effective monitoring and alerting system, you can instill confidence in the project’s stability and performance. This attention to detail ensures that any potential issues are promptly addressed, minimizing disruptions and maximizing the system’s overall reliability.