I see a repeated tendency in .NET to create base classes for API client classes, SQL repos, etc. The base class does all sorts of authentication, tokens, maybe retry logic, etc. They have several dependencies of their own, sometimes as many as 10.
That means the inherited classes have large constructors, and in order to test those classes we have to create mocks or pass something for those constructor arguments.
It makes the tests difficult to write and maintain, even though the tests have nothing to do with anything going on in that bloated base class.
Suggestion: Get rid of the inheritance. Take whatever is in that bloated base class, put it a non-abstract class, give it an interface, and inject it into API client classes, repositories, etc., instead of inheriting from it.
Now instead of calling something like
ExecuteRequest<Something>(whatever);
where it calls the base class, you can do
_requestHandler.ExecuteRequest<Something>(whatever);
Now whatever behavior is in your class is easy to test by mocking that interface. Whatever goes on in that other class - getting auth tokens, retries, etc, is all hidden from the classes that depend on the interface.
You can change that other class - add dependencies, whatever - and you won't have to go back and edit every single class that depends on it along with tons of tests.
In other words, prefer composition over inheritance. Just because multiple classes need some common behavior doesn't mean they should obtain it by inheriting from it.
Class inheritance is like drugs. Use it when there's a valid reason, like polymorphism. The rest of the time just say no, even if all your friends are doing it.
• • •
Missing some Tweet in this thread? You can try to
force a refresh
It doesn't matter how many people are in the store. Walmart will always have enough self-checkout registers closed or out of order so that you have to wait in line.
Every night Walmart moves the shelves a millimeter closer together so that the busiest aisles with poles supporting the ceiling get narrower and the least busy aisles get wider.
Walmart has displays that talk to me and tell me to buy stuff when I walk past, but none that I can ask "Which aisle are dried figs on?" because that technology hasn't been invented in 2021.
Here's a random, half-baked musing. It will go nowhere useful.
Suppose developers united and decided that if code didn't meet certain standards, we would refuse to work on it.
I'll use unit tests as an example of such a standard.
If your code has been committed past some cutoff date, no member of the United Federation of Excellent Developers will work on it.
Sorry, you'll have to find developers from the ever-shrinking pool of non-Federation developers to work on your code. They probably won't do very good work, but so what? You didn't care about that in the first place.
Don't try to account for race conditions. Eliminate them. Prevent them.
Ever see a delay added to code to account for a race condition? At least two bad things can happen, and it's not either/or. 1/
The first risk is that the delay might not be long enough. Or it might be long enough most of the time. Or for now, until something changes. Even after adding a delay, it's still a race condition. You've still got the same problem. 2/
The second risk is that some or all of the time the delay is longer than needed or entirely unnecessary. After all, the length of the delay is usually a guess. Guess too little and the risk of the race causing a problem remains. 3/
Have you heard of the "curse of knowledge?" It sounds conceited, like "Poor me, cursed with all this knowledge."
It just means that sometimes we forget what other people don't know, or what it's like not to understand something. 1/
A great remedy for the curse of knowledge as it relates to writing code is answering questions on #stackoverflow. It forces you to figure out what concepts someone doesn't know and relate to them so you can explain them. 2/
That's an opportunity. We all learn differently. This means you're communicating with someone who, for whatever reason, has gotten to a certain point without picking up that concept. Why don't they know it? It could be that everything they've read assumed they already did. 3/
Imagine an assembly line building cars. At what step do the doors get painted? Probably before they're attached to the car.
Suppose you follow it down the assembly line and find two, maybe three points where the car is inspected to see if the doors are painted. 1/?
If the car arrives at that step and the doors aren't painted, they get painted then. Maybe that happens when the fuel cap is attached, or when the tires are put on, or both. Maybe once in a while the doors get an extra layer of paint. 2/?
That might sound like a good thing. It means they're taking extra steps to ensure that a car never leaves the assembly line with the doors unpainted. But do you see the problem with that process? 3/?
In order to modify code we must understand it. Understanding code requires effort, whether a little or a lot. We should minimize it, but I wouldn't generally call it waste.
What if that effort reveals that the code does nothing? 1/?
Sometimes it's as simple as identifying dead code. In other cases we follow parameters passed from one method to another or properties of objects and after digging through the code realize that we never use them. 2/?
Understanding code that does nothing is waste in its purest form.
Remember your first day working on a new project, struggling with the cognitive load of seeing dozens of folders full of classes and wondering how long it will be before you can work in it productively? 3/?