Make your business logic readable, and your configuration logic extendable

What the hell do you mean with business logic and configuration logic? I swear I have not coined the term and I did read it somewhere that was not Clean Code, but I can’t for my life find it. Yet, with time I have come to see that this piece of info is one of the most useful one liners I usually give for advice.

Business logic tells our program what we want to do. It tells the story of the use case we are implementing. It’s usually very top level, follows a flow of function calls, and can almost be read as plain text. Does it sound as the best practices for testing? It is! Because business logic can be found mostly in tests (where they are a logical implication: we tell what our code does), but I like to extend that to any top-level access in any use-case: the entry point of a class, the public functions of a business object, the logic of a component…

Configuration logic, in the other hand, tells our program how to do stuff. It states paths, relationships and logic. It implements our abstractions and our programming patterns. It, at its core, stores efficiently how the program should store, retrieve and transform data. And efficiently means, most of all, maintenable: open close principle, least responsibility principle, inversion of logic principle… SOLID and beyond.

In a nutshell: business logic is at the top, configuration logic is at the bottom. Business logic must be readable. Configuration logic must be extendable.

Let me put a very basic example:

public static void main(String[] args) {

sayHiShoutingTo("joshi");
}

private static void sayHiShoutingTo(final String otherPerson) {

String greetings = greet(otherPerson);

greetings = shouting(greetings);

sayItOutLoud(greetings);
}

private static String greet(final String otherPerson) {
return "Hi "+otherPerson+"!";
}

private static String shouting(final String greetings) {
return greetings.toUpperCase();
}

private static void sayItOutLoud(final String greetings) {
System.out.println(greetings);
}

We can see that the main implementation could be considered business logic. It is quite readable. We know what it wants to do.

The bottom part is obviously configuration logic. We are telling how to retrieve the data, transform it, and where to store (or output) it.

And what about the middle part: it is business and configuration at the same time! It acts as configuration to the top layer because it tells how to retrieve that info. But it acts as business for the bottom layer because it tells us what we will do!

Remember: business is what is in top of any abstraction layer. And is not called business for nothing: it’s what interfaces the rest of the application. The public access part. Is what solves the use case. (And we don’t care what is behind the counter)

And that means is the one who is gonna be more visible. The most read during the application life. And, hence, the one which you should focus more on readability.

In the other hand, the business logic not only is the part you want to be as readable as you can. It is also the part which is more of a pain to modify, because is the only one you will be exposing to the application. This means a few things:

  • Every part of the application using it must be tested for regression if it’s changed
  • They are hard to generalize, because each use case must do something different. They are highly specialized
  • We don’t want logic in this layer. Seriously. Not. it reduces readability and makes the code tiresome to read. If you have some logic, surely it can be in a much better named function.
  • For fuck sake, even just changing the method’s name or paremeters needs a mass refactor and is even impossible in some languages!

That’s where configuration logic comes. This is where we implement the logic our business will use.

And like in any business, behind the counter is where the magic happens. Here is where we will focus on our domain logic. It should be:

  • Accessible, so any business logic can use it easily.
  • Parametrizable, to allow different behaviours for different cases.
  • Extensible, and easily on top of that. Because they are not shared, we are free to make as much as we need without fearing overloading the API.
  • Efficient, because we can focus on doing abstractions or algorithms without fearing bloating the code.

But what about business logic? Why doesn’t it be like this? Surely they will need to be parametizable to allow different configurations, or to put together similar code. Right?

Nope. Because different use cases should be in different methods, even if their code is very similar. Because they are different use cases, they will be maintained separately.

The DRY principle has aged somewhat bad. In the past, the minigame was on how we can lower total line codes by putting together the same code. This became a big problem when applications evolved.

  • Suddenly, domain items that seemed the same, had to be specialized for different use cases.
  • Replicating code meant to have to maintain two different things. And it was only minor details…
  • Yet, the details kept creeping in. Suddenly, you have 2/3 different use cases using the same logic just because you didn’t want to break DRY.

And it’s wrong: If two methods refer to different use cases, create two different methods for it, even if they end using the same configuration logic behind the scenes! You can always create more configuration methods, and changing business logic to point to a different configuration method is much easier.

The key is, you can play as much as you want with the inner pieces (configuration), but the external API is much harder to change (business)!

Let’s look again at the previous example, how easy is to make another business flow that doesn’t shout. Or that says goodbye. Can you guess what the code will do only from the method names? Can you see how we use configuration logic to aid us in that?

The core idea is to do layers: business-config/business-config and so on. If it’s not enough, then create more layers going down. There is no limit how much you can create of configuration code!

And that’s pretty much it. Have you noticed this pattern somewhere else? Do you agree or not? Please, leave it in the comments :)

4h day of #100DaysOfContent

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +741K followers.

José 'Joshi' Ráez Rodríguez

Written by

(Trying to be a) Software crafter, T shaped knowledge. Any technology is a tool to be used in the right circumstances. Our power lies in our decisions.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +741K followers.