Understand the need before trying to persuade
It is often tempting to persuade a developer or a development manager so they agree to reuse a software asset. However, if you repeatedly persuade without understanding the need, the business requirement it is unlikely that your efforts will bear fruit. Instead of persuasion, try listening, empathizing, and truly understanding the requirement. Figure this part out and then identify the asset can be leveraged or developed. Why? because when you truly listen you might discover that your existing asset does meet the need perfectly as-is or it doesn’t meet the need at all. Maybe your reusable service needs to meet a certain performance metric. Or if the existing service is leveraged, it will increase schedule risk. Whatever.
The point is your existing asset’s relevance to the problem at hand.Listen, evaluate, and persuade (if applicable). In that order.
Focus on reusable business (or domain-specific) software assets
Business assets are what makes your application or product line unique, your organization special, and ultimately differentiate you from the competition. The faster you can develop, release, and iteratively improve your domain assets the faster you will meet changing business needs and delight your customers
It is that simple
Too often, developers in their zeal to create a technical masterpiece, focus on building reusable components and services for problems that either have solutions inside your firm or from the open-source community. Now, if you have to, you have to – but try to avoid building stuff for which solutions already exist. Now, isn’t that what software reuse is all about?
Never release a reusable software asset without a suite of automated regression tests
If you are going to bet on a reusable software asset and advertise it to the world you need to have a suite of regression tests for it. Why? without regression tests, current and potential consumers will not have adequate confidence in the asset. The very foundation of reuse is to get a higher quality – less opportunity for errors, bugs, incorrect implementation of requirements – from not having to produce something that is already exists. To make sure you can deliver on this promise, a comprehensive suite of automated regression tests is a must. It will not only help you for your immediate consumer but for everyone thereafter.
Name your software assets appropriately
Whether you are naming a method, a class, a component, a library, or a service – pause a minute to really think about the software’s purpose and capabilities in order to assign a name.
An appropriate name will help you when trying to mine for existing software assets to be reused. Additionally, the effort will be fruitful when you are trying to refactor existing software assets to be more reusable.
Whenever you come across a method like doEverything() or a service SendDataToXYZSystemService – take a minute to rename them appropriately. Too often, a bad name will cause that extra bit of research for you to evaluate a capability that exists in your applications. If the name is too obtuse, you might not recognize functionality that is already there and build a duplicate one.
Good names are obviously tied to your problem domain but general guidelines still are valid – it is a good idea to name software assets based on the business functionality or capability. If you are publishing order updates to another system, why not call the asset PublishOrderUpdates instead of SendDataToABCSystem?
When you name an asset in a simple, clear, and accurate manner you will be surprised how often it will help you reuse it.
Get requirements from production support for your reusable asset
There is one thing you should do before placing your reusable asset into production and that is talk to your production support staff. Get their input, share your design, and get their feedback early and often. This will not only make your asset supportable (imagine a reusable asset without logging or instrumentation or ability to report on key metrics) it will also get you a valuable partner. Production support will soon learn to trust your assets, your services, and will demand that multiple projects leverage the capability. It is one thing for you to sell reuse but another thing for your partners to voice support.
Separate Reusable assets from the rest of your application code The simplest way to ensure that you can leverage reusable assets across projects and applications is to separate what is reusable into its own repository. Physically separate the source code and version control it as an independent entity. As with everything else this needs to be done iteratively and isn’t a must have for the initial release of the product. As assets evolve and become reusable they can be refactored out into their own repository for you to manage them better. Key thing is when they do become reusable you move them out.
Co-create reusable software assets as often as possible
There are a variety of reasons systematic reuse initiatives fail including technical and organizational reasons. If there is no buy-in from development groups that are prospective users of these reusable assets it will not be possible for your initiatives to succeed. I often hear that developers and development managers don’t want to reuse or develop a reusable capability because they don’t feel included in the realization of reusable assets.
How to deal with this factor? Instead of trying to convince, co-create reusable assets!
If you get a requirement to build an email alert notification need – work with the original development team and involve them in the design. Better would be to get them to develop a portion or all of the capability. If they co-created it with you, they will not think of the asset as a black box that they are being forced to use. You will be surprised with this – they will start helping you foster reuse by sharing this with their partners in the organization.
Document Capabilities as well as limitations
When documenting a reusable software asset donot only capture only capabilities. Be sure to document limitations as well. This is important because limitations directly influence refactoring work. When trying to match a user story with an existing asset the limitations will determine the extent to which you need to update the existing code in order to implement the story. Limitations are not a bad thing per se especially since you want to prioritize overcoming them within the context of a real user need. This exercise is made a lot easier when you capture the limitations ahead of time – this way you don’t have to review your code or ask several developers in order to come up with the refactorings needed.
Review all code
Code reviews are one of the most effective ways to ensure that your reusable assets are being utilized appropriately. Often times in a rush to get the product out the door, developers might put in code not realizing functionality that already exists elsewhere. Because it takes time and discipline to review code it is a good idea to do this in small chunks. The key is consistency not so much quantity of code. You would want a quick way to refer to what reusable assets exist and marry that with changes to your code. I often find myself discovering ideas for new reusable assets while doing code reviews also. Over time you will start to see patterns and duplication across code fragments and application functionality which will help you achieve synergies.
Encapsulate Complex Decisions If you have a set of business rules that are complex in nature determining decisions in your business process flow, it is better to encapsulate the into a separate component. If you have a rules engine in your architecture you can place these rules here and expose the rule as a decision service. If your implementation environment doesn’t have a rules engine, you can encapsulate rules as objects so they are isolated from the rest of the process orchestration logic. Why? Two immediate benefits: your rules can be changed independent of the process flow and your rules can be reused across multiple business process orchestrations.
Build Reusable Services
The following are useful tips when designing and implementing reusable services.
Expose only logical data attributes and “standardized” values to external consumers in the service contract. This will ensure that the data service has maximum flexibility to change physical system implementations underneath and the consumer will not be adversely impacted.
Reuse business object schemas across data service operations and while preparing WSDL documents. This will ensure logical data model alignment as well as consistent definition of business objects simplifying consumption and maintenance effort.
Expose event driven publication services for data propagation to downstream consumers using standard publication messages. This will greatly reduce (and potentially eliminate) the need for source specific messages and needless data transformations. Standard publication messages could be versioned and new consumers could be added via configuration on a messaging broker without requiring development effort.
Provide multiple flavors of services based on commonly used use cases for the data service. A light flavor of a service will be useful for clients who do not want to parse a large business object message returned by the full flavor.
Strive for abstraction of data source specific semantics in order to insulate the consumer from physical data source processing/logic. This practice applies to identifiers, data values, data structures, and data orchestration logic that could be coupled to a physical source if proper care isn’t taken.
Prefer reliable transports when invoking data services asynchronously. Although it is possible to simulate asynchronous processing using transport protocols such as HTTP it is not advisable to do so. In the event the data consumer becomes unavailable messages are lost.
Distribute Configuration For Various Testing Needs
If a reusable component requires runtime configuration (properties, XML files etc.) alongside the binaries, make it easier for the asset’s consumer to integrate these artifacts in their tests. For instance, using maven assembly the configuration files can be packaged as a jar file and added in the_test_scope. This will make the configuration available in the classpath when executing unit tests in the module. The configuration can be packaged per environment and using the dependency classifier the appropriate artifact can be used. This approach works for integration and performance testing as well – for instance, performance tests might use a different set of values for the configuration artifacts since they execute in a dedicated environment.
Inject Common Reusable Capabilities via JUnit Rules
JUnit has an extremely useful extension mechanism –Rules. The @Rule annotation can help provide additional capabilities to your test methods. For example, ContiPerf provides annotations for performance testing. Similarly, you can provide reusable framework hooks for developers to use alongside their test methods.
Some examples where this can be applied – capturing test execution metrics and publishing to a API for offline trending/analysis or setting up plumbing components to facilitate in-memory db testing via H2db, or data folders, etc.
Implementing a JUnit rule is quite straight forward – here’s an article from David Gassner that provides a sample rule implementation.
Standardize Error Metadata
Standardise error metadata across reusable assets so that multiple assets can report errors in a consistent manner. If error codes are consistent, how you to chose to log them or react to them can also be standardised across the product line. If each reusable asset gives you a unique set of error codes it makes it difficult for dealing with them. Standard error codes themselves could have a naming convention depending on where the error occurred, which component/module/service the error originated, and type of resource impacted by the error etc. I like to use a dot (“.”) notation when reporting errors – e.g. when the XYZ module in ABC product cannot fetch a database connection the error code is: DB_CONNECTION_ERROR. You can have stack trace and error location to pinpoint where the error occurred but it is important that all database connection errors across your reusable inventory use the same error code. If we need to retry the connection, or notify a database support team, or whatever remedial action needs to be taken can be initiated across the product line using a single mechanism to handle errors.