January 6, 2015
Tip #32 – Fail the build when there is a test failure
Systematic reuse needs automated tests – lots of them. Ensure that your continuous builds don’t keep running when they encounter a failing test – this makes mistakes visible faster and easier to fix. If you are using Maven, you can use the surefire plugin configuration as shown below:
January 4, 2015
It has been a busy fortnight and have started reading a number of books:
…plus excited to take How to Learn: Powerful mental tools to help you master tough subjects via Coursera.
January 4, 2015
Wrote earlier about why interfaces are important and in this post want to elaborate on their advantages for building reusable services. Service interfaces contain only the operation or method definitions and have no implementations. They can be used in a variety of ways:
- Package service interfaces into a separate artifact to make it easy for client teams to integrate with services without pulling in bulky set of transitive dependencies
- Bind the interfaces to one or more transport / integration technology via standard Dependency Injection (DI). For example, service interfaces can be integrated with a REST-ful Resource or a EMS listener.
- Service interfaces can be backed by stub and/or mock implementation for automated unit and regression testing.
- Service interfaces can be decorated with common cross-cutting concerns to separate them from the implementation. This is the strategy implemented via the Java Dynamic Proxy example.
- Service interfaces can be implemented as a proxy to a remote implementation. For example, the client invokes the functionality via the interface but the runtime implementation makes a call to a server side API. This is useful if your teams need the flexibility to swap local / remote implementations depending on performance / dependency management related requirements
January 3, 2015
A lot of teams are building services for clients both internal and external to your organization. Typically, there is quite a bit of focus on succeeding from a functional sense – did we get the key requirements addressed? does it cover the plethora of rules across markets / jurisdictions? and so on. Some of the more experienced teams, consider the non-functional aspects as well – e.g. logging, auditing, exception handling, metrics, etc. and I talked about the value of service mediation for addressing these in an earlier post.
There is an expanded set of capabilities that are also necessary when addressing non-functional requirements – those that are very relevant specially when your service grows in popularity and usage. They fall under two categories: operational agility and fault-tolerance. Here are a few candidate capabilities in both these categories:
Operational Agility / Supportability:
- Ability to enable / disable both services and operations within a service
- Ability to provision additional service instances based on demand (elastic scaling)
- Maintenance APIs for managing resources (reset connection pool, individual connections, clear cached data, etc.)
- Ability to view Service APIs that are breaching and ones that are the risk of breaching operational SLAs
- Model and detect out of band behavior with respect to resource consumption, transaction volumes, usage trends during a time period etc.
- Failing fast when there is no point executing operations partially
- Ability to detect denial of service attacks from malicious clients
- Ability to gracefully handle unexpected usage spikes via load shedding, re-balancing, deferring non-critical tasks, etc.
- Detecting failures that impact individual operations as well as services as a whole
- Dealing with unavailable downstream dependencies
- Leveraging time outs when integrating with one or more dependencies
- Automatically recovering from component failures
In future posts, I will expand on each of these topics covering both design and implementation strategies. It is also important to point out that both these aspects are heavily interconnected and influence each other.
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.