Is this a good module or not?
My answer: can’t tell. It depends on how the module interacts with other modules.
Personal blog
Well just Bartek, you're a wizard
Is this a good module or not?
My answer: can’t tell. It depends on how the module interacts with other modules.
First – realize what constitutes good tests.
The answer: little (ideally: zero) false positives. Feel free to read my previous article that elaborates on this topic.
But how exactly? Here is my answer:
Continue readingThis is the most important, yet the most unspoken trait of good tests. Tests should be the oracle.
If all tests are green – the app will work on prod. If at least one test is red – the app won’t work.
Think Continuous Delivery. Every step in the process has to be automated. When tests are green, there is no room for extra human checks before going prod. The decision (deploy – no deploy) is handed over to your tests.
Do you trust your tests this much? Is this even possible to be this confident about tests?
Continue readingConsider a method that calculates some ETA:
class Calendar {
add3WorkingDays(): Date {
const result = new Date();
let daysAdded = 0;
while (daysAdded < 3) {
result.setDate(result.getDate() + 1);
if (this.isWorkingDay(result)) {
daysAdded++;
}
}
return result;
}
isWorkingDay(date: Date): boolean {
const day = date.getDay();
return day !== 0 && day !== 6;
}
}
Notice how add3WorkingDays
depends on the time when it’s called (result
is initially now). Because of that, you’d have trouble writing reliable unit tests for this.
My recommendation: change the implicit dependency of now
to explicit one and inject it:
add3WorkingDays(date: Date): Date {
const result = new Date(date);
// no changes from here
It takes only so much to implement dependency injection, the most overcomplicated technique in the history of programming. You don’t need frameworks, containers, service locators, interfaces, or decorators. You only need to know how to parameterize a method.
Oh, by the way, we changed the interface of the method too. We have to change all the callers: calendar.add3WorkingDays()
-> calendar.add3WorkingDays(new Date())
Does this mean you don’t want to introduce dependency injection later in the project, to avoid risky refactors? No. You can still have DI without changing the interface using the default parameter:
add3WorkingDays(date: Date = new Date())
If you “automate everything” you end up with cargo-cult of your process.
What you should do instead is employing Elon’s 5 steps protocol (“the Algorithm”) that consists of in order:
Always. In. That. Order.
If you automate something that meets unnecessary requirements – you’re doing it wrong.
If you automate something that shouldn’t even exist – you’re doing it wrong.
If you automate something before you try and simplify it real hard – you’re doing it wrong.
If you automate something prior to accelerating it’s cycle time – you’re doing it wrong.
Every such automation helps cultivate current pathology.
Possibly the most common error of a smart engineer is to optimise a thing that should not exist,
Elon
What a waste it is to automate “everything”!
Automate aggressively but first own the progress and make sure you automate the right thing.
We often design our code so that one procedure comprises many classes, often grouped by layers. For example, in web dev, that could be controllers, models, repositories, etc:
Layers are good. Often at least two layers are desirable for maintainability: domain and low-level. If you’re like me, you like 2-5 layers but not too many.
Now how do you test such code? It comes naturally to want to test each component separately and mock out the collaborators from other layers. I believe it’s because unit tests are said to be run “in isolation”:
My advice – don’t automatically do this. Aim for this instead:
Test first? How do I test something that is not yet written? And before all, why? It makes no sense.
Try it a few times and you’ll see how powerful it is!
Open–closed principle? The more I close my code to modification, the more closed it gets for extention. You can’t have both. It makes no sense.
Only until you realize that it’s actually possible – with interfaces or other dependency inversion techniques.
The best code comment is the one that never existed? Comments are the only thing that allows me to navigate my messy code. You want me to stop writing them? It makes no sense.
Yes, stop writing comments and delete all of them. But only after you clean up the code to the extent that comments are not needed. There are ways to do it.
Continue readingThere it is. 5th and the last theme. “Crave for clear rules”, as the official description says.
What kind of rules could it be that I crave? What challenges can the rules bring?
Processes have negative connotations. They are on the right side of the agile manifesto. And I claim myself agile. How come?
To me, a process doesn’t have to mean a big and slow corporate machine. Process is a visible extract of how we do things in our team. Visible! That’s the missing part of almost every “process” I ever saw.
Process is a communication tool.
Processes can and should be automated. But first, they need to be visible.
And yes, individuals and interactions can trump processes. These situations should lead to improving the process. Not to anarchy!
My favorite talent, if I may choose one!
When picturing your code in terms of product and user stories, it doesn’t really matter how you solve people’s problems.
Too often programmers are married to the idea that all they do is code. We can solve problems otherwise!
Most of the time it ends up being code, but even then there are many, many possible solutions.
Out of my 5 CliftonStrengths talents, it’s time for the third one – Developer.
Cool name for a programmer, isn’t it?
I know of the Curse of knowledge.
I know people learn differently. YouTube videos, documentation, books, courses, learning by doing… All of that can be a legit source to learn from. Depends on who is a student.
That said, I have a very strong candidate for the best way of learning & teaching programming. Which is…
Continue reading© 2024 Bartosz Krajka
Theme by Anders Noren — Up ↑
Recent Comments