One of the best things you can do for a codebase is to keep the business logic separate from everything else.
Imagine you have an app from 20 years ago, written in an old framework no one uses anymore. Thousands of people rely on it for their jobs, because it is the only app that deeply understands how this particular industry works.
The user experience could be so much better but the app works and no competitor beat them yet. Now you're tasked with bringing this giant to the modern days by adopting current technologies to improve the overall experience.
You take a quick look at the code, and being a seasoned dev with a sharp sword, you prepare for war. You know it's going to take your team a long time and it's going to be messy. Why?
Because most of your time will be spent untangling the logic that needs to stay from the parts that need to go. And what needs to stay is the business logic. The rest is old framework code no one cares about.
Now, while you untangle this mess, are you going to leave another one for future generations? Of course not. Because you know the current framework you're using now will undoubtedly be replaced by something else in a decade or so, you will do your best to keep the business code separate from everything else.
To do so, ask yourself the following question at all times:
If I were to migrate to a completely different framework tomorrow, would I be able to take the business logic with me?
If the answer is "yes", you're writing code that lasts. If not, you're borrowing from the future and some refactoring is in order.
Top comments (3)
Frameworks like React are built on components, but these are ui-components. They do not support or enforce an abstraction below that level. So, it's completely up to you to choose the right approach.
Do you have any suggestions, how to do the separation?
Oh yeah! I'll write more about it, but we suggest keeping all your business logic in a
business
folder. Make sure the folder is a collection of composable functions (github.com/seasonedcc/composable-f...) only.Use a separate layer to load and mutate data (we call this layer "controllers"), like Remix's loader and actions. In that layer, call the composable functions to get the data that will be passed to components. Whenever you're dealing with external data or HTTP data (query string, form data, etc), use Zod schemas on the controllers to ensure the data is valid. We recommend using composable-functions'
applySchema
to apply the schemas before calling the functions.Lastly, pass the data to your UI components as props.
@efpage, I just published an article with a lot of detail on how we do the separation: dev.to/seasonedcc/molecules-of-bus...