loading...
Cover image for Vue 3 Composition API – The Wrong Solution To The Right Problem

Vue 3 Composition API – The Wrong Solution To The Right Problem

martinsotirov profile image Martin Sotirov ・3 min read

Love at first Vue

I was an early adopter of Vue.js in 2016, and my very first project with the framework was to port an existing Vue 1 app to the brand new Vue 2. As a React user I was skeptical at first. What I was seeing was a weird mixture of features “stolen” from all the major frontend frameworks.

It took almost no time for me to permanently fall in love though.

This “weird mixture” seemed to represent the perfect balance between React’s flexibility, Angular’s structured modules and jQuery’s flat learning curve.

And from then on, I was an early evangelist for Vue. I did presentations on Vue at all the major JavaScript meetups in my area. I went to the Vue.js Amsterdam conference every year.

I used Vue in all the projects where it made sense and in many where it was probably the wrong tool. I was even doing hybrid iOS apps with Cordova long before there were any solutions for Vue on mobile.

RFC shit storm

Then in June 2019 came the RFC shit storm when the Composition API was announced imposed.

During the heated discussions on GitHub, Hacker News and Reddit I had a some rather unpleasant interactions with core team members where I and everyone else who was disagreeing were told that we need React style hooks because all the business logic must be in components and they know best because it's their framework.

GitHub Gist Comments

In the end, thanks to the huge developer outcry the initial plan to deprecate the old component syntax was abandoned, so v3 will still support the old Vue syntax we love. Yay!

The age-old problem of code reuse

The Composition API came about as a solution to the age-old problem of code reuse and encapsulation of business logic. Multiple programming languages have been born as a solution to this problem and in fact the whole discipline of Object Oriented Programming can be traced back to the dream of code reuse.

That problem has already been solved, and just because suddenly it's OK to have CSS in our JavaScript files, it doesn't mean we have to completely throw out 30 years of programming knowledge and completely reinvent everything.

Design patterns books

In fact, if you read old versions of the Vue.js docs, you will see that it is advertised as the ViewModel in the MVVM design pattern (or MVP as Martin Fowler initially called it).

Technically, Vue.js is focused on the ViewModel layer of the MVVM pattern. It connects the View and the Model via two way data bindings.

Reuse of the ViewModel was never a goal for MVVM frameworks though! Neither is the encapsulation of "renderless" business logic not tied to a specific view. The ViewModel's sole job is to manage the state of a specific part of the app (a single component).

Thankfully, there are still sane voices in the JavaScript community which sadly aren't heard loud enough.

The wrong solution to the right problem

Code reuse and encapsulation of business logic absolutely are valid problems but bending a technology focused on the view layer of an application to do additional things is not the right solution.

The Composition API supposedly solves the problems with:

  • Mixins
  • Renderless Components
  • Higher Order Components

If you absolutely must use some kind of component inheritance and breaking your components down or extracting common functionality in service classes is not an option, that means you are either structuring your app's architecture the wrong way or Vue.js simply isn't the right tool for the project.

Vue.js is not a silver bullet that's applicable in 100% of the use cases, and that's ok.

It is simply unfortunate that when the Vue.js Core Team tried to solve the age-old problem of code reuse and business logic encapsulation, they decided to find inspiration in React rather than Angular.

This, in my opinion, disrupts the very delicate balance Vue.js had between the diametrically opposed approaches of Angular and React, which is precisely what made Vue appealing to many of us in the first place.

Discussion

pic
Editor guide
Collapse
koehr profile image
Norman

I don't see why the composition API is a problem here. I think it is the right solution to a completely different problem. You talk about code reuse but mean business logic. These are two different things. Code reuse obviously applies to business logic as well but that doesn't mean it doesn't apply to the view layer.

Also you also show snippets of discussions without enough context. The composition API is meant to fix very vue-specific problems and it does this well. Some people thought it will change the way to use Vue because they jumped to conclusions too quickly. The same angry people also cried out loud when they heard that Vue3 will be written in TypeScript because again they jumped to the wrong conclusions.

Collapse
martinsotirov profile image
Martin Sotirov Author

I am including encapsulation of business logic when I talk about the topic of code reuse simply because both things were used as justifications for the Composition API's existence.

Also, the official plan was to change the way to use Vue by deprecating the Options API, so no jumping to conclusions there. That plan was thankfully laid to reset after the much deserved developer outcry.

You are right that there is not enough context for the screenshots of conversations but sadly I couldn't find the link to Akryum's Gist where one of the discussions took place.

Collapse
drewtownchi profile image
Drew Town

I agree. I've worked on some medium sized enterprise apps and code reuse in the view layer was definitely a problem. A problem that composition API could have helped us solve. We tried renderless components, we tried just importing functions, we tried overly bloated base components. All of these felt clunky because we couldn't share functionality between components without this odd non-standard layer.

The composition API is definitely solving a problem. It may not be a problem everyone has but it is a problem. I'll rarely, if ever, use it on my little blog website but I would have used it all the time at my previous job.

Collapse
martinsotirov profile image
Martin Sotirov Author

I've also consulted on large enterprise apps where the team has quickly hit problems with a bloated structure of components, and so far the solution was never mixins or renderless components but rather plain old JavaScript in the form of service classes, auxiliary helper functions or simply refactoring and breaking down the components.

Thread Thread
drewtownchi profile image
Drew Town

Oh I don't disagree that helper functions and service classes can solve many code re-use problems especially around business logic type problems and API access. And that's what we did.

I do think the the composition API will help with view layer re-usability problems. Things like a drag-and-drop library, event handling, special formatting logic (numbers, truncation, etc. etc.) and animations. Those were our big pain points of trying to figure out good ways to re-use Vue code.

Yes, I know for some of those you could pull in a special helper function and run it through a method. But, it would have been nice to be able to use computed and watch methods in some of them rather than have to remember to use that method on all changes

Thread Thread
martinsotirov profile image
Martin Sotirov Author

I get what you mean because I've had to make these decisions when refactoring too. In 90% of the cases where I've needed to reuse code at the level of computed properties or watchers, it has turned out in the end that my component structure wasn't optimal and could be refactored or further broken down into sub components.

In the other 10% it was always the case that I am trying to keep the code DRY at the micro level where some duplication simply won't hurt.

Thread Thread
drewtownchi profile image
Drew Town

The problem we were having is with tons of little components scattered around we were setting pretty bad perf problems when loading large data sets. The comp API seems promising in that it shouldn't have the same perf cost as rendering a full component.

I don't think it'll be perfect for all situations but I think it'll be a nice tool to have IF you need it. I don't think most end users will need it often.

Thread Thread
martinsotirov profile image
Martin Sotirov Author

I'm all for having more tools at our disposal.

My only concern was that if suddenly all the documentation and tutorials for new users are with the Composition API this might firstly hurt Vue.js adoption and secondly lead to the eventual deprecation of the Options API.

Collapse
jsn1nj4 profile image
JSn1nj4‍‍👨‍💻

When I saw the composition API, I thought it could be a neat tool in the toolbox.

If we're talking about business logic in the view layer though, I have to agree—especially when the view layer is handled completely in the browser as in SPAs.

Before I heard about View a few years ago, I was learning Meteor. It was a fun tool to learn and I loved the idea of using a framework that was an SPA out of the box and used JS on both client and server. But there was a practice (even encouraged in the docs) of running some Meteor methods that would normally need to be run server-side to update MongoDB also on the client (the client side used MiniMongo as its data store).

So it was trying to do DB updates in both to give the appearance that the changes happened more quickly—and then the changes would be rolled back if the server side contradicted the change made client-side.

I really don't understand why exposing all of this to the browser is/was thought to be ok, so I definitely agree with you about keeping business logic separate.

Collapse
smolinari profile image
Scott Molinari

You've failed to give us your idea or suggestion as to what the better solution to better code reuse could have been and why it would be better. So, this article ends up just sounding like a rant to me.

You do mention refactoring because, if one needs the composition API, they are more then likely doing something wrong and could just refactor. Really? Are you sure that is true? I don't. My best guess is, you've not understood how the Composition API can help you and thus, haven't embraced the fact it could help you. That's ok. But, you shouldn't write about your lack of understanding like this, as if it's Vue's problem, in a rant. There are many other devs who are embracing it. They can't all be wrong. Right?

You also fail to mention the other main reason for this API direction of Vue - It's for a much better TypeScript support. This is very important for larger developer teams (too) and developer ease of use. (You do understand that I hope). That shouldn't be forgotten or rather should be weighed against the cons of the API, which you also fail to mention in any detail. You never say the new API has inherent problems, except your opinion of it possibly disrupting some delicate balance Vue makes between React and Angular. I disagree wholeheartedly against this perspective. That might have been the case while Vue was growing, now Vue needs to grow in other directions. And, the new Composition API will pull more (smart) React and Angular devs and companies using these technologies to Vue, strengthening its place in the market and allowing that growth.

I will agree that it is very easy to muddle up code reuse concepts with all the new possibilities we are seeing with single file components. In Jake Schatz's presentation you elude to, Jake is trying to give the message of not allowing business "knowledge" to leak into the UI. He is clearly demonstrating we should use abstractions to simplify code and enable better code reuse. He notes two patterns, the "builder" and the "command" design patterns. And, if we are brutally honest, the Composition API is 100% built to support both patterns much better than the current and often loved Options API (I love it too, btw). Imagine a "useCommand" or "useBuilder" and "useDirector" functions (objects).

So, unless you can come up with a better solution, you should stop ranting, because that is all it is. A rant. It has no value other than to get your opinion out in the open. And, you should know, opinion without reasonable and substantiating fact is a lousy opinion. Sorry, but if you want to back up your opinion, come up with what you feel could have been a better direction and why. Then your rant isn't just a rant, but a smart counter argument and I personally would thank you for it.

Collapse
martinsotirov profile image
Martin Sotirov Author

I am sorry if my personal rant has offended you. You are right that I should have expanded on some points like what a better alternative would look like.

Personally I don't think that Vue.js needed better methods for code reuse because, like I said in my article, if you end up needing composition functions or mixins, your problems could probably be solved by other forms of refactoring – e.g. breaking components down and using vanilla service classes.

Otherwise, if you or the core dev team insist on changing the way Vue works, the now abandoned Class API would have been a much better alternative, and in fact it would have been much more idiomatic OOP Typescript, if you're all about the improved TS support.

If you fail to see the merit of my "balance between Angular and React argument", then you are severely misunderstanding the position Vue occupies in the general JavaScript ecosystem. As a consultant I've helped multiple middle sized to large companies introduce Vue.js to their dev teams, and "better code reuse" or "better typescript support" were literally never mentioned as reasons. The single most often mentioned reason was that Vue.js has a much flatter learning curve and (compared to Angular and React) much less boilerplate, i.e. "the fine balance" I was referring to in my article.

If a team would find themselves in the position of needing much more strictly organized code structure or much better native TypeScript support, they would simply reach for Angular. If on the other hand, they need much better and "pure" functional approach to their code base, they would simply reach for React. My point is, those use cases are already solved better in other frameworks, and Vue should stick to what makes it desirable in the first place. Vue is not a silver bullet that is valid in all the use cases.

Collapse
kayodeadechinan profile image
Kayode Adechinan

I think you summarized very well what i always thought. Thanks.

Collapse
zhoulion profile image
zhouquan

below would equal true👇
vue3 - sfc + (render:() =>jsx) === react with hook.
BTW, vue3@beta is released and i had a try.In my own option I still prefer jsx rather sfc

Collapse
fk1blow profile image
Dragos Tudorache

It says "clean code" not oop code