Hey! I'm Alejo, a software developer, and this is my personal site. I post links and comments to interesting things on the internet, and sometimes I write stuff.
[…] any solution that involves allocating a table, preprocessing strings, and so on, is going to take longer to do all that stuff than the blazingly-fast-99.9999%-of-the-time brute force algorithm takes to just give you the answer. The additional complexity is simply not worth it in scenarios that are relevant to VB developers.
Being a senior developer is not just about applying patterns everywhere, but also knowing when not to. It’s about finding the right solution for the right problem and discarding unnecessary things (patterns/complexity, etc.), because You Ain’t Gonna Need It.
The key here isn’t that you are trying to look at things in isolation, the key is that you are trying to isolate things that are preventing you from getting quick feedback on the state of the system.
We usually repeat some things without stopping to think about them in detail. We like to say that Unit Tests are supposed to test small “units” of the system in isolation, and we take for granted that we should mock anything that looks like an external dependency. But sometimes we end up, basically, testing mocks, because we focus so much on the “unit” internals that we forgot to test its significant interactions with other components.
The key issue with unit testing the system as a set of individually separated components is that concept that there is value in each component independently. There isn’t. The whole is greater than the sum of its parts is very much in play here.
I’d say there is a lesson here (at least for myself): stop mocking all the things just because they are “external” dependencies. Take a look at the overall logic and interactions, create tests that can verify the requirements, and start mocking whatever gets in the way of obtaining quick feedback.
We all like to joke about how all “old” code is “bad code”, and even more when talking about our own. But I think it’s very rude to belittle other people’s code (even if it’s “old”), saying things like “this code is garbage” or something along those lines, just because it’s missing some style conventions or “good” patterns and practices.
I myself was guilty of that a few years ago, but I’ve learnt that every code has a context, a reasoning and some trade-offs behind it. No one writes “bad code” intentionally (well, assuming a professional environment).
[…] rather than criticising and assuming bad decisions, I should think back to what I knew at the time of making the decision and what I now know, at the time of criticising that prior decision. When thinking about that code I wrote six months ago along with the context in which it was written it became clear that it wasn’t an idiotic or bad decision, but a reasonable one at the time.
Something nice to remember during your next code review :D
A blog post from Oren Eini aka Ayende Rahien, inspired by a twitter discussion about using vanilla DI vs a full-blown IoC container:
For stuff that doesn’t change very often, we do things manually. For the things that we add a lot of, we make it as smooth as possible.
Ultimately, it comes at one of my favorite software architecture guidelines: use the right tool for the right case. We are so used to use DI Containers - like, it’s taken for granted when you use
dotnet new - that we don’t even think about whether it is really necessary or not, and sometimes, a container might not be the best tool for the job.
What we have done is optimize one aspect, which we deal with often, while manually dealing with the stuff that is rarely changing. That means that if I do need to make a change there, the level of magic involved is greatly reduced.
^ this. Sometimes, on critical pieces of the software, adding more layers of abstraction can cause issues in the long run - maintainability, performance, etc. - because it works “magically”, but you can’t debug magic.
I suggest to think deeply about what you mean when you say “clean” or “dirty”. Do you get a feeling of revolt? Righteousness? Beauty? Elegance? How sure are you that you can name the concrete engineering outcomes corresponding to those qualities? How exactly do they affect the way the code is written and modified?
A lot of people follow “rules” and “conventions” just for the sake of it, but don’t really care about the why’s. I mean, rules and conventions are good, but they usually exist for a reason, and sometimes, that reason does not apply to your code.
Don’t follow rules as a religion. Or, in Dan’s words:
Don’t be a clean code zealot
We developers like to think way ahead and design for scalability, extensibility and a lot of other things, but, sometimes, we don’t need to. Often, all that thinking actually ends up in analysis paralysis.
I cannot quote this enough:
For certain type of applications, there is a hard cap of what load you can be expected to handle. And you should absolutely take advantage of this. The more stuff you can not do, the better you are. And if you can make reasonable assumptions about your load, you don’t need to go crazy.
In any case, WebAssembly itself won’t replace Angular or React, because WebAssembly is not a UI framework. But UI frameworks built using other languages, such as C#, Go, or Rust, will almost certainly compete with Angular and React.
I haven’t dug into WebAssembly yet, but I’m starting to find more and more articles around it. And I suppose we will start seeing a lot of UI frameworks for different “traditionally backend-only” languages.
This is an old post (from more than ten years ago!) by Jeff Atwood, that I stumbled upon while going trough my “read it later” emails.
It’s painful for most software developers to acknowledge this, because they love code so much, but the best code is no code at all. Every new line of code you willingly bring into the world is code that has to be debugged, code that has to be read and understood, code that has to be supported. Every time you write new code, you should do so reluctantly, under duress, because you completely exhausted all your other options. Code is only our enemy because there are so many of us programmers writing so damn much of it.
It reminded me of something that I heard a few years ago, when I was being introduced to a new Tech Manager. One of the things that he said about the new development department policy was “try to reuse first, buy if you can’t reuse, and develop only if there are no more options left”.
I have to confess that I was too junior at the time to understand it (I was like “what!? I want to develop new things!”), but now I recognize it as really good advice.
A short but very cool article about the QueryTypes feature in EF Core (2.1 and newer).
Nothing beats handcrafted SQL query in terms of performance or feature availability from the database engine itself. And understanding, at least on a basic level, SQL and execution plans helps preventing performance issues with using ORM.
I once read: code is read by humans (other team members, or your future self), more than it is read by machines. So, make it more human-readable.
I also found this final piece of advice awesome:
Remember that a code base is owned primarily by a team (even if you practice individual code ownership over bits of it). A professional programmer is prepared to bend her personal style to reflect the needs of the team.
Older content is found in the archive.