5

We have an application where the customer has changed their mind about a large area of functionality and this area requires a large amount of re-work.

Whilst the re-work itself is not an issue, it has introduced a situation where the impact of the changes is wide ranging including:

  • Data
  • Query Logic / Table structure
  • Business logic
  • Display / Presentation

Ideally we'd like to incorporate these changes at the same time as several other development streams, but we're worried that the impact of the changes will have a negative impact on how frequently we can deliver. We can cater for some of this through branches, but it made me wonder what the possibilities are for guarding against this kind of thing from an application architecture or development practice point of view.

Things we currently do:

  • Abstract query logic into repositories - This is great for small changes, but when the overall logic in an area changes, e.g. instead of getting a list of users which meet a certain criteria, we now need to get a list of organisations which joined to locations.
  • Abstract business logic into services - This is exactly the same as the repositories in that we can't really guard against entire logic shifts, but small changes can be accommodated with limited impact.
  • Ensure configuration is kept out of code which needs re-deployment, a combination of database rows or web.config values.
  • Other patterns which promote aspects of flexibility like factories where appropriate etc.
  • Feature flagging for selection of functionality if two approaches were developed originally. etc

Are there any other current best practices to guard against changes, without incorporating branches etc?

2 Answers2

4

The only thing you can do to help reduce the impact of a change is to split your overall project up into many components, so while a major change will impact several of them, many will not be affected.

eg if the customer decides they need a new button that sends data through the middletier to be stored in a new column in the DB, you're going to have to change every layer in your system. However, if the system is also split 'horizontally' too then the UI impact will only affect part of the UI layer, the rest will not be changed. Similarly, if you have a lot of services in your middle tier that each process certain parts of the data, you'll only have to change one of them - the rest will be unaffected. the DB too, can be partitioned into independant schemas.

So for example, you need to get a list of users, so you have a service that manages user data. When you need to get a list of organisations too, you add a new service that deals with this and merge the data together in the UI (for example) which means you have not had to alter your user-access code at all. I think this kind of approach is termed microservices, though obviously 'micro' doesn't have to mean tiny, just logically separated.

I would not try to introduce abstractions as all that will happen is these will tie your layers together (eg a DB change will still require the underlying table change, but now the wrapping DAL layer will need change too, and having a DAL will not necessarily let you split the DB into sections, unless you get into a lot more complexity).

gbjbaanb
  • 48,749
  • 7
  • 106
  • 173
-1

Unit tests and Integration tests can be used to protect your logic from code changes.

  1. If you currently have a good code coverage, and you need to re-work a section, then the approach would be easier, you can change your tests to reflect the result after the re-work and once you have done the change you can re-run the test cases, to make sure it's all working. (In practice it would be a good idea to use a continuous integration server to run tests after each commit, and with this you can do smaller changes at a time and make sure all the logic is intact with the CI server status)

  2. If you do not have tests, then it would be a good idea to create some. If you are under tight deadline, you could start with integration tests where the tests will verify the output of the given input from the presentation level. For each place where change is needed you can start with creating tests for the expected output after the changes, and do the changes so and make sure tests are green.