React, Vue, and Business Logic
By: Greg Solo
Tags: JavaScript, Vue, Programming, React, Tech

React and Vue are no different. They exist to help you build UI (or, on the contrary, make it more difficult — depending on your frontend-religion). Nothing more, nothing less. But UI is not important.

Yes, it may be aesthetically pleasing; it may sell your product a great deal. But bad UI can quickly kill your entire company. These are all true from marketing, aesthetics, sales perspectives.

But from a software architecture point of view, UI is secondary. Data and logic, on the other hand, are essential. They determine the practical uniqueness of software, and they are the most valuable part of the software.

I guess, as any reasonable professional you’d like to protect the most valuable part of your programs as much as possible. There are many ways you can do so. First of all, you can protect it from your bugs. One of the best ways to do so is, of course, testing. Nothing gives us hope in better tomorrow than 100% test coverage.

Secondly, you can protect the heart of the application from other’s bugs. As a professional developer, you probably think ten times before allowing a library v0.0.1 from an unknown publisher to touch your sacred Business Rules. After all, if we want to be healthy, we stay away from form junk food. For the same reason, we should stay away from external libraries we are not sure about.

Thirdly, and I will keep your attention on this one for a while, we should try to protect our valuable application core from unreasonable changes. Uncle Bob keeps saying this simple but crucial truth for many years in the books, articles, conferences, and meetups. Yet still, we keep ignoring his great advice. Don’t believe me? Try to recall how many times you have seen something like this in the source code:

componentDidMount() { axios.get(‘/articles/’) }

or

methods: { calculateDiscount(){ // actual code that

// makes business-critical calculations

// for the price of the product } }

I’ve seen a lot. And many of them I authored myself. And it’s quite easy to fall into this trap because we were told that our components are supposed to be smart. Not all of them, of course, there are also “dumb”, “functional”, “stateless”, “presentational” components. They are different. They are only for UI purposes. They contain no business logic whatsoever.

But there is a cluster of “smart”, “stateful” components. To mentally separate them from “UI components”, we even call them “containers” some times. It’s easy to conclude, “oh, then it means we should place our business logic inside these “smart” components!”. But now you have at least 2 problems.

First, your business logic is now coupled with the UI. We can call smart components anything we want (even “containers” or “higher-order functions”), but they remain part of the UI.

Simply because these components either directly render DOM (e.g React/Vue component) or tightly coupled with those who do so (e.g Redux Containers).

And coupling business logic with UI is a substantial violation of the Single Responsibility Principle (“S” in SOLID). Every time you change these UI elements, you have a risk of potential changes in business logic. In other words, your logic depends on UI.

Bob Marting wrote an entire book (“Clean Code”) explaining why this is such a problem, and I highly recommend to read it if you haven’t yet. But at this point, I assume we all did.

The second problem is that the business logic of your application, that most valuable and critical part of the software, depends on 3rd party solution. Using Uncle Bob’s terminology, your application has “married” this 3rd party library/framework.

And don’t get me wrong, I have nothing against frameworks nor libraries per se. They can be helpful in many ways: render a solid structure, provide a common language for developers from different teams, help with onboarding new team members, and of course, take a tedious, repetitive work out of your hands. But I am voting for reasonable usage of such a powerful tool for it comes with a price.

Let’s assume that we did our homework and didn’t pick the freshest, super-hot yet untested by others (for several years of production usage!) framework. We also made our consideration quite carefully and picked the best solution for us, not just the most popular one, thoughtfully comparing the pros and cons.

Even so, we now “committed” to this framework. Why is that bad? Imagine, the new version is released. You know, the one we should really, really migrate to since it fixes 25+ critical vulnerabilities that come from the npm dependencies this framework uses. Or even worse, the team/company/CTO/PM/You decides to switch from one framework to another because… well, you know… reasons.

And now, we are at risk of changing the app’s business logic even though the actual logic of the business didn’t change at all. We didn’t receive any new memos from the marketing or business analytics team. We calculate the discounts the same way we did before. We fetch the same APIs. Nothing changed on our end, yet we have to make changes. Thus, we violate the Single Responsibility Principle again and pay the price.