Where is my "Business logic"!?
Tags: businesslogic, domainlogic, architecture
Published: 2024-05-18 19:02:29

It's common to hear you should separate your "business logic". There are numerous articles emphasizing the importance of this separation. And then there are a lot of suggestions showing the structure of a project with this separation of "Business logic" or "Domain logic". But I used to have a basic problem while trying the separation. The problem is- what are the things I should consider as "Business logic"? Where is it? Then I came up to a very simple answer- "separate the I/O".

So, imagine in the software, existing or proposed, all the I/O has been taken care of. So, reading/decoding/parsing/encoding/writing is not your problem. All you are left with the data, in the structure you intended. So, you have to-
- Validate the input.
- Do the whatever you want to do with it.
- Return the output.
And if you then write your program with only these concerns, Voilà! You got your "Business logic" or "Domain logic"!!

Now, the things left to do are doing the technical part. Here you take the input, decode it, parse it, (de)serialize it into the structure defined by your domain logic layer and then send it to them. Then receive the outcome, serialize it, encode it and show/send as output. Your program is run by this technical part, but it always follows the business logic.

Then there is another point to keep in mind. There can be internal and external, inputs and outputs. The external input is the one you are getting from the "Request" of a user or external service. And then you may require some more input from your database, which is the internal input. And after processing, you may save some updates to the data in your database and send some data in the response, which are internal and external outputs, respectively. So, the "business logic" layer should take these two types of inputs separately and return the two types of output separately.

The "technical" layer of the program should handle reading/writing all these inputs and outputs. In most of the time, the internal/DB input is dependent on the external input. And the external input should be validated before retrieving the internal input. You may even want to apply some kind of business logic "before" retrieving the internal input. So, the internal/DB input should not be passed as direct data to the business logic layer. Rather, you should pass a lambda/delegate to the business layer, which can be used by the business layer to retrieve the internal/DB inputs. In this way, the business logic layer will be indifferent to the way the internal/DB data is being retrieved, but still can control whether it should be used or not.

For the internal/DB output, the business layer does not need to know how the data is being saved. It should just mark the data which should be saved. Again, the structure of the different types of input and output data is being defined by the business logic layer and the technical layer would just follow it. Any error in the serialization/deserialization is the concern of the technical layer.

Another point to keep in mind is the "mutations". All the changes (create/update/delete operations) in the internal/DB data should happen in the business layer. The technical layer will be "saving" the change, but "making" the change is responsibility of the business layer.

Sometimes it may seem the business layer is doing very little or nothing at all. It may raise the question that is it worth the trouble separating this little part to a totally separate layer? The answer is, yes it will be totally worth it, especially in the long term.

And this separation of business layer has another benefit, now you can easily do the unit testing. Basically, you have to write unit tests for all the cases of business logic layer. And if you have separated the business logic from the I/O, you most probably would not need any "mocking".

In ideal cases, you should be able to rewrite or refactor your technical layer without touching the business layer. Same goes for the storage engine, user interfaces, the device of the user etc. And in the longer term, this is definitely going to happen. Happy coding!