June 10, 2016
Let’s say your team built an amazing managed platform – one that provides large scale systematic reuse and provides several compelling benefits to your organization and it’s developer community.
You break open the champagne and celebrate right? Not so fast!
Sustaining and evolving the platform requires discipline and persistence. Like any other complex system, entropy will set it and if you don’t get ahead of it, the platform will wither away.
So, what does platform entropy look like and how do we tackle it? Instead of trying to define it, let me suggest a few signs to watch out for:
- Focus shifts disproportionately from improving a platform’s key functional use cases – i.e. the platform is not constantly improving the manner in which it is addressing the bread-and-butter business problem it was designed for.
- There isn’t a core group of committers who are constantly monitoring the health and well being of the platform codebase. This includes tracking and fixing nagging bugs, modifying and correcting abstractions, introducing better documentation, making it easy for new developers to understand and extend functionality, etc. If there isn’t anyone obsessing about a sustainable codebase, entropy will win. It is just a matter of time.
- There isn’t a committed platform road map and releases start to become more and more ad-hoc. If the platform code base isn’t released in a frequent, easy to execute fashion, don’t be surprised if it gets harder and harder do deploy critical fixes and upgrades!
- The feedback from existing and potential client developers aren’t acted upon. Are you truly listening to your client developers? are they complaining of onboarding complexities? platform jargon that takes a long time to learn? inability to test their code without jumping through hoops?
- Not investing effort in making the platform easy to support. Supportability helps with overall platform health in numerous ways – most importantly, drives ability for your clients to self-service their interactions. If support tooling and automation is short-changed, you will spend ever increasing amount of time and effort trying to get the platform to behave in production. If your team is having a tough time differentiating between platform issues vs. issues in the client code, it is time to invest in better and more supportable tooling. Both your teams and clients deserve that investment.
June 7, 2016
You need to practice minimal design to be effective with systematic reuse. The design needs to continuously look for opportunities to align iteration goals with your systematic reuse roadmap. Too many developers mistakenly think that adopting agile means abandoning design. This couldn’t be farther from the truth. You design whether you explicitly allocate time for it or not. Your code will reflect the design and you will impact the technical debt for your codebase in one way, shape, or form. Implementing user stories and paying down technical debt should be your end goal and not avoiding design altogether.
Always design for meeting your iteration goals. Avoid designing for several weeks or months and surely avoid putting technical elegance ahead of delivering real user needs. You should design minimally. Just enough to take advantage of existing reusable components, identify new ones, and plan refactoring to existing code. Specifically this means:
1. Keeping a list of short tem and medium term business goals in mind when designing
2. Always looking for ways to make domain relevant software assets more reusable
3. You are aware of what distribution channels your business is looking to grow
4. Design reflects the domain as close as possible and that your reusable assets map to commonly occurring entities in your business domain
5. Value is placed on identifying the product lines that your business wants to invest in and evolving your reusable assets to mirror product line needs.
6. Design isn’t a pursuit of perfection but an iterative exercise in alignment with your domain.
What you decide to encapsulate, abstract, and scale are all natural byproducts of this design approach. Rather than spend a lot of effort with a one time design approach you need to do just enough design.
January 2, 2015
Systematic reuse takes conscious, disciplined effort – question is – where are the systematic reuse opportunities? how can we maximize these opportunities? – it may or may not surprise you that there is rarely a special, designated ‘project’ to achieve reuse or build a reusable API. Teams are busy and they want to solve tangible problems – they work on projects more often than reusable libraries and services. Some reuse advocates lament this situtation – they wish the organization supports systematic reuse with a protected budget, appropriate team members, and the organizational mandate to enforce reuse APIs and standards. I used to wish this too and I was wrong – way off the mark 🙂
Now for the good news – the great thing about the lack of a reuse budget is that, you can focus on the more important thing: achieving business objectives either by saving costs, creating new revenue lines, and reducing uncessary risk. Projects have the necessary business objectives baked into them – that’s why they are funded, resourced, executed, and tracked. Finally, they have an important constraint: time. Projects have deadlines. Schedule risk is a key one with reuse efforts and having a project deadline ensures the asset is going to be useful and relevant to the project at hand. Below are a few tips to get the maximum out of projects:
- Review the requirements – whether it is a set of tickets, a sprint plan, or a formal document – review and categorize requirements into ones that are specific to the project, common to the product line, and common across projects.
- Ensure you are engaged with the development team throughout the project lifecycle – reviewing and identifying opportunities for identifying, leveraging, and refactoring code. Very often, reviews are done long after development is complete with an impending deadline. This leaves little room for introspection, refactoring, or improvements to the codebase.
- Identify existing components and services that are potential reuse candidates – most importantly, identify assets that are readily reusable (even if they are part of an existing project codebase), ones that need minor refactoring, and ones that need substantial refactoring / development. Minor refactorings and enhancements which can be done in parallel while users are testing / verifying functionality is one of many possibilities.
- Insist on development teams using agreed upon interfaces for reuse-eligible functionality. Dev teams can either create a bespoke implementation, fork off an existing implementation, or leverage a reusable API. However, none of this is possible if the projects use bespoke classes / APIs. Interfaces give your team the freedom and pluggability to swap implementations, evolve asset maturity, and ultimately carve code off the project to seed and grow a reusable API. It doesn’t matter if the interface is implemented by a local component, a remote service, with or without persistence, etc. – the implementation will depend on performance and resiliency characteristics in addition to functional needs.
July 21, 2013
There are certain key interception points during the development process that can greatly increase the likelihood of systematic reuse. Some agile practices can really help:
- Estimating User Stories – constantly seek synergies and ways to connect new requirements with existing ones or those from other projects the team is working on. You know you are successful when the most junior member of the team is finding commonalities and points out areas to explore for systematic reuse. Very often however, reality is starkly different – similar, slightly varying functionality gets implemented over and over again across projects due to time constraints, lack of awareness, and implementation considerations – e.g. legacy system won’t be able to use this component” or “the existing system implementation is hard to refactor…”, etc
- Pair programming – the real strength with pairing is the variety in perspectives. One person can go for depth (identify a very efficient algorithm) and another can focus on breadth (identify existing components to reuse/extend or contribute current work). It is also convenient when pairing to switch perspectives and identify ways to improve the code by eliminating what is not necessary. Hard to expect one developer to be your systematic reuse superstar every time across every project.
- Code reviews – this is a rich area for reuse opportunities because of two key reasons – one, the idea is proven – it is in code and executing – not just vaporware. Equally important, it is a chance to re-look at the implementation with a detached perspective. Discover unspoken design assumptions, needless couplings, and free up code to be more extensible. Look for unnecessary 3rd party library dependencies, code quality violations that compromise layering (presentation code invoking database or data access logic having UI formatting logic, etc.), and constantly eliminate duplicate boiler-plate code. Remember – continuous alignment and not perfection is the intent here.
- Retrospective – when discussing what went well and what needs to improve – explicitly invest in learning the team’s challenges with systematic reuse. Listen for key signals from the dev team – do they have access to source code? how easy or difficult is the existing component library? what functional goal can be achieved faster if there was further investment in a reusable component?
February 17, 2013
Want to envision, design, and implement reusable software components that your development community will enthusiastically adopt? Co-create! Here are 5 tips to leverage co-creation when driving systematic reuse initiatives:
- Have an idea that applies to multiple projects? Get the project leads to co-ordinate and align resources and partner with developers from both teams to develop the design
- Share the source code of all your reusable components so every developer in the team can see under the hood how the component works and how it can be improved
- Work hands-on with developers when defining classes, external interfaces, etc. – not just via block diagrams but actual code. Pair program and show them how to think using abstractions, what aspects of the design to make extensible and the rationale for it, etc. – you’ll be surprised how effective this is and how much all parties learn from the process
- Share the big picture – every time and across every project – developers and development managers need to be convinced that their contribution aligns with the overall technical strategy. This should also highlight why a shared component’s test coverage and robustness needs to be high and continuously improved
- Use design reviews, code reviews, and retrospectives to continually look for ways to collaborate and leverage each other. See boiler plate code that can be better encapsulated, or missing tests, or a smarter algorithm – get your hands into the code and work with the concerned developer. They will appreciate why you want them to use a particular design pattern or think about a problem in a certain way. Added bonus – just like item #3 – every participant will learn from the exercise.
Finally, co-creating reusable components greatly reduces friction associated with having to implement a design that was mandated. You want passion and enthusiasm from the dev community – not compliance!
July 1, 2012
In the zeal to create a reusable component, you should be careful not to over-engineer i.e. pursue perfection. The functional needs have to be at the core of the reusable asset’s ability to solve a particular problem. When in doubt, remember that as time goes on, the team will learn the nuances of the problem domain and will be able to make better design decisions. Explore the domain with the team rather than force a solution. How exactly do we do that? We can:
- Practice creation of simple, domain-aligned abstractions
- Continuously validate the domain with functional experts in the team
- Consciously exclude aspects of the domain that aren’t relevant / well understood when defining reusable components
It is critical for the team to discover and stumble upon reusable assets – rather than big design up front efforts lasting for months. Keep it agile and continuously evolving and improving.
April 13, 2011
Wrote earlier about the importance of refactoring and continuous alignment within the context of systematic reuse effectiveness. Reducing technical debt is an integral aspect of refactoring. This post provides tips for reducing technical debt in your software assets:
- Minimize redundant definitions of key domain objects (i.e. competing, conflicting definitions of the same domain object across related applications)
- Minimize similar solutions for slightly varying business processes and instead create common process flows
- Loosen tightly coupled integration/transport logic with business logic
- Provide consistent strategies for implementing cross cutting concerns
- Replace tactical implementation for a problem that has a better open-source alternative
- Eliminate redundant approaches for managing configuration information
- Harmonize multiple, incompatible interfaces and make them more domain relevant
- Minimize excessive coupling with a particular technology/implementation stack
- last but not the least – create a comprehensive suite of automated tests
Are there similar themes in your development efforts? What steps are you taking to ensure technical debt is addressed?