Modifiability is about making changes and our interest on it centers around cost and risk of making change.
While planning for modifiability an architect have to consider following questions .
- What can change ? — A change can happen to any aspect of the system
- What is the likelihood of the change ? — One can’t plan for all the change but make some tough decisions about which changes most likely and plan for it.
- When is the change made and who makes it ? — Is the change made at time of compiling code or at runtime by end user through configurations ?
- What is the cost of the change ? — Making a system more modifiable will incur two types of cost. a) Cost of introducing mechanisam to make the system modifiable b) Cost of modifying the system using mechanisam.
Following are the tactics used for achieving modifiability
- Size of the module
Tactics that will split the modules into smaller pieces so that cost of making changes are reduced.
Modules have responosiblities . When a change is made to a module , it’s responsibilites too change in some way. If couple of modules have their responsibilities overlap then change in one module will affect other one as well. This is called coupling , stronger the coupling more expensive are the changes.
It means how strongly the responsibilites of a module is related. Higher the cohesion lesser probability that the change will impact more responsibilities and wider testing surface and hence more expensive to make change. So stronger cohesion is friend of modifiability.
How to execute above mentioned tactics
- Reduce the size of module
Refactoring is the key and while refactoring we should look at many programming principles like SRP , SOLID , DRY
Encapsulation — Encapsulation introduce an interface / API . So it will reduce the chances of change propagting to other modules , if we are working with well-defined interfaces.
User an intermediary — A depedency between two modules can be broken using an intermediary .For example publish-subscribe will change the consumer’s dependency on producer.
Restirct dependencies — This is seen in layered architecure where a layer can talk to layer below only. So this way we can control the dependency between different modules.
Abstract common services — In case where two modules have same services , it’s better to abstract that into a common place with well defined interfaces.So that way the changes can be controlled.
Design checklist for modifiability
- Allocation of responsibilities — Determine which changes or categories of changes are likely to occur
- Co-ordination model — Determine which functionality or quality attribute can change at runtime and it affects coordination.
- Data Model — Determine which changes or category of changes are likely to occure to data model abstractions.Design the data model so that items allocated to each elements of the data model are likely to change together.
- Mapping among architecture elements — Determine if it is desirable to change the way in which functionality is mapped to computational elements.For example , execution dependencies , assignment of data to databases or assignment of runtime elements to process.
- Resource Management — Determine how change in a responsibility will impact the resource usage. For example . what resource limits will change due to modification of responsibilites or what new resources needs.
- Binding Time — Determine the latest time the change needs to be make. Later the binding time , lesser the cost.
- Choice of technologies — Will your choice of technology help or inhibit ability to make changes , test and deploy ?
By answering the above design checklist , we can evaluate our design choices with respective to the modifiability of the design.