Posts
Teams should prioritize live code reviews
Pull requests were originally created by open-source communities to enable asynchronous collaboration on shared codebases. In these environments, contributions are often reviewed over several days or even weeks, since many contributors participate part-time. This asynchronous approach works well in such settings, allowing maintainers to review code when it's convenient for them.
Complexity vs. collaboration
The ability to unit test code is highly correlated with the modularization of said code. The more modular code is, the easier it is to write accurate tests for it. When code is tightly coupled, writing good unit tests becomes nearly impossible. Therefore, unit testing has introduced new ways of thinking about code. This post is about one such important concept: separating code into complexity and collaboration. This not only helps with unit testing but also improves modularization and long-term maintainability.
Code smell: Public setters
Public setters have two huge problems: they expose the internal state of objects and therefore increase the coupling of the system over time. This might not be obvious to new developers or to experienced developers who haven’t worked in systems with strong encapsulation practices. Therefore it is a widely used practice that hurts software quality in the industry. Sometimes setters are useful, but there are major downsides to long term maintainability. Overall code becomes clearer and easier to work with over time if public setters are omitted.
Don't name it Service!
Developers often fall into the trap of naming classes
XService
— likeFoodService
for food-related logic. Over time,FoodService
accumulates methods likeadd
,save
,get
,build
,getMore
, and evengetXWithYWhileZ
. This pattern leads to bloated, unmaintainable code that violates core design principles and creates tightly coupled systems.Intentional Validation: Ditching Frameworks for Clarity and Control
In most applications, validation is typically done using a validation framework that helps setup validation faster. This article argues that using these validation frameworks is an antipattern to clean code. It introduces complexities that makes the code harder to debug, is hard/impossible to properly test and is not extendable enough. While validation frameworks offer quick setup and standardization, they can introduce hidden complexity and become limiting over time. Instead it is suggested that each project should do its validation manually, because it in the end is more maintainable and stable than the common approach.
Eliminating NullPointerExceptions in Java
In
C#
, nullable reference types must be explicitly declared. For example, astring
is not nullable, but astring?
is. By introducing this concept, the developer is forced to consider null for any nullable reference. This concept also exists in languages likeKotlin
, a modern JVM language that is fully interoperable withJava
. Unfortunately, inJava
, all reference types are nullable by default. This post is meant to be practical advice for getting rid ofNullPointerException
in existing codebases.Feature-oriented folder structure
In many applications the source code is split into the different layers that the application consists of from a technical architecture perspective. For example with a
feature1
andfeature2
, the following could be the folder structure in a simple onion architecture:Current date is an infrastructure concern
Getting the current date is an easy task in most languages. In Java you can call
LocalDate.now()
, in C#DateTime.Now
or Rustchrono::offset::Local::now()
. This seems quite easy to do, so most developers will do it close to where the date is needed. The argument this article presents is that you want to push this code into the infrastructure layer of your code. This applies both to getting the date and time, but for simplicify, the date is the focus.Code smell: Don't talk to strangers
“Don’t talk to strangers” can be a useful rule of thumb for identifying code smells when writing code.
Code smell: Arrowhead code
A tip for recognising a common code smell is to look for arrowheads. Consider the following python code:
The diminishing returns of rewriting a system without the original authors
Choosing to rewrite an existing system is a big decision. It usually requires a project to reach a point where the technical debt is too much to deal with, or the technology is so ancient that the compentencies no longer exists. However, it can also come from an engineering team that have gone the wrong way, or chosen to rely on a technology that has become deprecated. This particular story is about the later case. It aims to illustrate the two most important takeaways: domain independence and tribal knowledge.
Benchmarking EFCore 3.1 Cartesian explosion problem
In Entity Framework Core 3.1 any LinQ expression is translated into a single SQL statement. This will not be a problem for most queries, but it can cause performance problems if developers are not cautious of this when crafting queries. This article will introduce a simplified model of a performance problem that was discovered and solved in a production environment.
subscribe via RSS