Growing Object-Oriented Software, Guided By Tests (chapter 17)

Feb 20, 22

We can think of a program’s main method as a ‘matchmaker’. It introduces different parts of the system to each other and then sits in the background waiting to be told when to close.

To help understand if main is doing too much, look at the packages it imports.

Try to keep constructors super simple (just set fields). Anything complicated may be liable to break tests in the future (and will be hard to refactor).

Extract interfaces where appropriate, use them to organize your code. Remember the single responsibility principle and dependency inversion!

Extracting a class can be a good way to see its dependencies.

Use the correct kind of peer objects. Sometimes we use a dependency when it would be better to use a notification

At this point of the book, the author’s have refactored to a design that matches the ‘ports and adapters’ style like here. The key point is that they arrived here incrementally by just following a test-first approach. This shows how making code easier to test, should hopefully ensure that our code is loosely coupled and easy to extend if required.

Fix smaller problems in the code, commit often and we should be able to replicate this. When refactoring, don’t bite off more than you can chew!

Pairing can help while refactoring, as will need to vocalise the proposed change. A second opinion is also super valuable during the process. If you are getting stuck, maybe draw a simple interaction diagram.

There may be more than one approach that you can take when refactoring - try to use your best judgement and let the tests guide you. This is also another reason why you should work incrementally, and commit often. Sometimes you will need to roll back your changes!