I have a tremendous amount of respect to Michael Feathers, so it is a no brainer to see his presentation.
Michael is talking about why Global Variables are not evil. We already have global state in the application, removing it is bad/impossible. Avoiding global variables leads to very deep argument passing chains, where something needs an object and it passed through dozens of objects that just pass it down. We already have the notions on how to test systems using globals (Singletons). He also talks about Repository Hubs & Factory Hubs – which provide the scope for the usage of a global variable.
- Refactor toward explicit seams, do not rely on accidental seams, make them explicit.
- Test Setup == Coupling, excessive setup == excessive coupling.
- Slow tests indicate insufficient granularity of coupling <- I am not sure that I agree with, see my previous posts about testing for why.
- It is often easier to mock outward interfaces than inward interfaces (try to avoid mocking stuff that return data)
- One of the hardest things in legacy code is making a change and not knowing what it is affecting. Functional programming makes it easier, because of immutability.
- Seams in a functional languages are harder. You parameterize functions in order to get those seams.
- TUF – Test Unfriendly Feature – IO, database, long computation
- TUC – Test Unfriendly Construct – static method, ctor, singleton
- Never Hide a TUF within a TUC
- No Lie principal – Code should never lie to you. Ways that code can lie:
- Dynamically replacing code in the source
- Addition isn’t a problem
- System behavior should be “what I see in the code + something else”, never “what I see minus something else”
- Weaving & aspects
- Impact on inheritance
- The Fallacy of Restricted Languages
- You want to rewrite if the architecture itself is bad, if you have issues in making changes rapidly, it is time for refactor the rough edges out.