DEV Community

Discussion on: In Defense of Clean Code: 100+ pieces of timeless advice from Uncle Bob

 
peerreynders profile image
peerreynders

If I put my own very similar units in front of some library units, any ideas of being decoupled is really just an idea.

This is assuming a one-to-one distinct abstraction to concrete library relationship. That type of alignment isn't necessarily the best way to move forward.

In my experience, the most successful projects are always the ones with less complexity.

I think it's more important to evaluate if complexity is managed appropriately. In my view OOD invariably adds complexity in order to manage complexity — it can work but it often isn't a slam dunk.

So it has to be a conscious, case-by-case decision, in my opinion.

That's pretty much a given. Guidelines tend to be a starting point, not some absolute truth.

What ultimately devalued the video for me was the example - why would there be a need for a concrete messaging abstraction? The actual goal is to have the application logic be "ignorant" of the messaging solution that is being used to handle messages. This idea is similar to Persistence Ignorance (PI):

Well, PI means clean, ordinary classes where you focus on the business problem at hand without adding stuff for infrastructure-related reasons.
Jimmy Nilsson, Applying Domain-Driven Design and Patterns 2006, p. 183

"The Application" will only need to send a finite number of message types, and receive a finite number of message types. Worst case each send-type has its own function into the infrastructure and the application exposes a separate function for each receive-type. The application is only interested in providing the data for outgoing messages and extracting the data from the incoming messages. The application really doesn't care what happens on the other side of the application boundary.

Quote

… and then you find out that there are messaging libraries that abstract the underlying transport whether it be Azure Service Bus or Rabbit MQ, etc. …

Rabbit MQ has no business being inside the application boundary.

To use J. B. Rainsberger's terminology:

  • Rabbit MQ has to live in the Horrible Outside World (HOW)
  • The application exists in the Happy Zone (HZ).
  • The HOW and HZ are separated by the DeMilitarized Zone (DMZ; where the "adapters" live; narrowing API, pattern of usage API)
  • The HZ can depend on the HZ
  • The DMZ can depend on the DMZ
  • The DMZ can depend on the HZ
  • The HOW is permitted to depend on the HZ
  • The DMZ may depend on the HOW
  • The HZ cannot depend on the DMZ
  • The DMZ is allowed to talk to the HZ by implementing an HZ interface.
  • The HZ cannot depend on the HOW (… and yet this is exactly what many frameworks encourage you to do — I call it the creepy hug problem — it's nice to be hugged unless the hug is a little bit too long and a little bit too tight by somebody you don't know that well)
  • The HOW is allowed to talk to the HZ by implementing an HZ interface.

FYI: Mock Roles, not Objects

Quote

Now again the reason you're abstracting these things is because you want to isolate them. And you might want to isolate them because you don't want to depend on them directly. Again most people say so I can swap it out.

The "swap out" argument is specious but isolation is the prize.

Isolation is the pre-requisite to being able to leverage fast micro-tests — "tests to detect change", i.e. establish rapid feedback as we refactor the code to reduce the volatility in the marginal cost of adding the next feature.

Doesn't this HOW/DMZ/HZ stuff slow us down?

In the beginning perhaps but again J.B. Rainsberger explains The Scam:

The cost of the first few features is actually quite a bit higher than it is doing it the "not so careful way" … eventually you reach the point where the cost of getting out of the blocks quickly and not worrying about the design is about the same as the cost of being careful from the beginning … and after this being careful is nothing but profit.

He acknowledges that "the scam" is initially incredibly seductive but eventually there comes the point where the cost of continuing is higher than the cost of starting again.

So the initial investment is aimed at going well for long enough, so you'll beat fast all the time.