Making incremental changes
Note: The below template might be helpful in if not all, but with most of the cases.
Consider you are given a task to implement a print API to print the documents. So you would need several components like,
- An interface
- Printer implementations
- Some utility classes
public interface IPrinter { /**
* @param Document - Document to print
* @return - true if printed successfully, false otherwise
*/
public boolean print(Document document);
}
and you have different flavors for printer like,
public class BlackAndWhitePrinter implements IPrinter { @Override
public boolean print(Document document) {
//.. add logic to print the document in black and white }
}
and
public class ColorPrinter implements IPrinter {
@Override
public boolean print(Document document) {
//.. add logic to print the document in black and white }
}
and utility class to fetch the location of the printer from,
public final class LocationUtils { private LocationUtils() { } public static String getCurrentLocation() {
//... logic to return current location
}}
Let’s see how we could plan for continuous development and delivery of this feature.
1. Top Down / Bottom Up
There are two ways that we could start with. Once you have the dependency tree (ie; the class diagram) at hand it would help you to get an idea on how to you could release the changes (bottom up/ top down/ combination of both).
Bottom up approach where you could publish the utility classes (eg; LocationUtils) followed by publishing the classes which depends on them.
Or Top down approach where you publish the interface first, then followed by it’s implementation. Always, make sure that you plan for classes along with it’s unit tests in a single release.
Plan for pushing the code as dead code (ie; not referenced from anywhere within existing flow) followed by enabling them.
2. Wiring the change
Now that the API which are required for printing the documents are ready, there might be few modules in the project which are waiting for their availability. Make necessary change to invoke the new API maintaining the backward compatibility (if applicable).
3. Releasing the feature
There can be multiple ways to release a feature like,
- Enabling/ disabling the feature completely with feature flags/toggles
- Releasing the feature for a particular region
- Controlling the feature only for x% of customer traffic
- Releasing the feature only for internal users etc.
At this phase, make sure you have enough control mechanisms to detect the failure immediately and have rollback mechanisms in-place when there is a failure. Make sure that all possible failure scenarios are thought through and you have mitigation path (eg; rollback/recovery strategy) when there is a failure.
Making small incremental changes is beneficial for both the author and reviewer of the change in following ways,
- Makes code review easier (consumes lesser time to review),
- Helps the reviewer to catch the bugs easily
- Helps get feedback at early stage
- Increases delivery speed