In most cases, if you rely on comments to explain code, you’re doing it wrong. I’ll show you some ways to achieve self-documenting code. No, it’s not utopic.

Photo by Artur Shamsutdinov on Unsplash

The myth that code needs comments comes from the university. The rule to make your code self-explanatory rather than using comments existed in all companies I was at and it worked out fine. So what are the problems with code comments?

Subjectivity. Comments are subject to the reader’s interpretation. Natural languages are ambiguous but code doesn’t lie.

Code never lies; comments sometimes do. Ron Jeffries

They allow bad code to exist. Comments are an excuse to make bad code with good explanations.

A comment is a failure to express yourself in code. If you fail, then write a comment; but…


CODEX

Clean and hexagonal architectures can be complex topics. Let’s break them down using an iterative learning model.

Image by Rishabh Dutta via WallpaperUse Copyright-free

Why another article about this? I struggled in the beginning to understand the clean architecture, so I decided to write my own explanation in a way that resembles how we learn: by building progressively refined iterative models.


CODEX

I built a utility app to control Yeelight/Xiaomi LED Lights. It can be accessed from the Windows system tray.

I’m a fan of Xiaomi/Yeelight LEDs, especially because they can be used as smart home devices. You can control these lights with Xiaomi Home, Google Home, or Yeelights apps, but I wanted something that I could use while I was at my Windows PC so I didn’t have to look for the smartphone, unlock it, and look for the app and open it.

I imagined something in the Windows tray, which, with minimum clicks, allowed me to control the LEDs. I searched the web for a while but there was nothing. I found Yeelight Control (not working), Yeelight UWP, Yeelight…


CODEX

Dependency Injection (DI) is the most common way to decoupling and separation of concerns, promoting testability and readability. Let’s analyze some related design patterns that I’ve spotted in some projects.

📝 I used Kotlin in the code samples, but all the patterns apply regardless of the language or runtime.

You don’t need a DI framework

I use frameworks and libraries when it pays off. In what concerns DI, I recommend doing it manually. Check how clear and effective vanilla DI is:

val coffeeProvider = CoffeeProvider(System.getenv("PROVIDER_URL"))
val coffeeNotifier = CoffeeNotifier()
val coffeeMaker = CoffeeMaker(coffeeProvider, coffeeNotifier)

“Dependency Injection” is a 25-dollar term for a 5-cent concept. [… it] means giving an object its instance variables. Really. That’s it. Dependency Injection Demystified

DI is a design concern, not a tool. The way to achieve it is to learn its…


CODEX

I heard about contract testing as an alternative to integration testing and finally decided to learn its concepts and try it out using Pact.io.

How do you ensure multiple apps and services of the same system play well together?
You could run end-to-end testing but it’s nearly impossible to test all the combinations. Also, the effective pinpointing of problems would be very low.
You could also test in isolation, on a per-app basis by simulating the other services' replies, but since they can evolve independently, the safety net is low as each set of tests may pass although the integration is broken.
Finally, integration testing is the typical solution because tests are run against the depended-on services. …


Does your backlog contain technical stories like migrations, upgrades, refactors, and other chores? I’ll try to convince you not to.

A board in Pivotal Tracker

I assume you, developer or not, care about your backlog. Backlogs, like codebases, need and deserve care from everyone in the team. I’m a fan of continuous codebase improvement through constant refactoring. I love coding and I care a lot about all the codebases I work with. I understand migrations and upgrades need to happen, so why do I propose we stop creating technical stories? There’s a lot of harm in doing so. Let’s see why.

A tech-driven approach

What are you paid for? I often hear “to write code”. I don’t agree with that at all since I believe we’re paid to…


There are multiple techniques, and the ones you use depend on your testing strategy.

The techniques to test the data layer can be direct, like testing against an in-memory database (e.g. H2) or against a real database (e.g. using Docker) or indirect, like launching the backend application or testing as the end-user (UI tests). Let’s go over the direct options. The presented techniques can be applied regardless of the database technology (e.g. PostgreSQL, Redis, MongoDB).

📝 When deciding the techniques you’ll use, bear in mind the testing automation goals and where it fits in your automated testing strategy.

Testing against an in-memory database

In order to unit test the data layer, we need to properly isolate it. Let’s imagine…


One of the goals of automated testing is “testing as a safety net” but that doesn’t mean that you should unit test everything. (De)serialization is an example of something that you should not test directly.

According to the hexagonal architecture, an adapter belongs to the outer layer of your app; it’s the glue between a component and the outside world, whether a database, a gateway for a REST API, your own REST API, etc. Adapters should only deal with parsing, (de)serialization, routing, error handling, and similar; they should never contain any kind of business logic.

Source: Hexagonal Architecture with Java and Spring

The need to store and transmit data requires some kind of string representation which is given by serializers (object → string). Deserializers do the opposite (string → object). JSON is just a possible string representation but there are others.

🛑 The wrong way to test (de)serializers

@Test
fun…


Do you feel safe regarding your testing strategy? Do you follow testing patterns consistently? Are you tired of debating what is a unit versus an integration test? I’ll propose a way to visualize your testing strategy so you can tackle those questions.

The testing strategy is how you approach the automated testing of your software. Given its importance, it should be taken seriously. I’ll propose a visual way to represent it, as visual representations promote discussion, a shared understanding, and support decision making.

In a world full of technicians and politicians all having different levels of understanding, a graphic representation was often the only way to make a point; a single plummeting graphic usually aroused ten times the reaction inspired by volumes of spreadsheets. Digital Fortress

Before starting…

… we need to define some terminology (inspired in xUnit Test Patterns). I avoid the terms…


There are a few things we keep hearing and doing but we seldom question, like “code comments are good” or “magic numbers are bad”. Let’s address the latter.

Creating constants can be a symptom of some underlying anti-patterns. But aren’t magic numbers (or strings, etc.) a bad practice? Well… don’t follow rules just because you always did it. Let’s address the typical arguments (we’ll use Kotlin in the snippets).

“But I can use them in the tests!”

This is the worst reason to create constants. Tests should know nothing about the implementation other than its public APIs. Initially, a certain constant was local/private but you promoted it to global for the sake of testing. This was a bad idea because now the tests are coupled with the implementation. Tests should be seen as clients of the…

Luís Soares

full-stack developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store