Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function-based Component API (extended discussion) #54

Closed
drakeba opened this issue Jun 24, 2019 · 26 comments
Closed

Function-based Component API (extended discussion) #54

drakeba opened this issue Jun 24, 2019 · 26 comments

Comments

@drakeba
Copy link

drakeba commented Jun 24, 2019

Opening a new issue with a copy of my previous comment as per @yyx990803's request:

As someone who is not normally a part of these types of conversations, this one has caught my eye (and obviously many others). First off, I've read the RFC in its entirety, I've read through every single comment on it to date, I've read the Reddit posts & (most of) the comments on those as of early this morning, and I've read the Hacker News thread as well. Point is, I've done my due diligence before adding my voice to an already loud conversation. I disagree with the oft-presented idea that the external threads are passing out misleading ideas, I left my reading of this thread with a similar mood, albeit with the luxury of seeing changes made in response to community concerns. (which is great!)

I acknowledge that this RFC solves some internal and typing problems, particularly for TS users and larger applications. From that aspect, it's awesome. Truly.

Many, MANY people have brought up how they feel the object API is more intuitive, easier to understand, and easier for them to implement. I won't continue to beat that horse because the dev team has repeated now ad nauseam that they'll keep it around, but make no mistake, from an outside perspective that feels more like a patronizing way to shut people up then a good will gesture acknowledging different use-cases of the framework. It very much comes off as "ok fine, we won't remove it....yet." Correcting a mis-representation of an idea is not a big deal, but pretending like it wasn't originally presented as a deprecation is not the same thing. I would hope you can see how that doesn't inspire confidence in those of us who are quite happy with the current API tone but not the new one?

Furthermore, the comments of "if you don't like it, don't upgrade when to v4" or "just use a plugin" are dismissive and disingenuous as well. If there's no future for me or my company in a technology moving past a certain point, then why invest any more time than I have to into using that technology at all? That's not a threat of intent, but it's a practical decision that should be made sooner rather than later when talking about a change this significant. I've seen many challenges to the actual significance of the change and all I can say is that yes, for me it is quite a significant change.... and clearly I'm not alone.

There's been plenty of comments with the basic tone of trust us, we know what's better for you. If all applications and all development teams looked the same, then maybe I could buy into that. This comment even took it further and said:

Trust me, if you have been working as a project leader/architect for more than five years maintaining frontend projects that are complex and meaningful enough, you might probably agree that, the ultimate way to improve your team's productivity and meet your deadlines is not to stick to some old and familiar development fashion that comforts you, but quite the opposite -- to go with frameworks that are type-safe, composition/reusability friendly and help them envolve to furthermore meet these standards.

That was especially distasteful and condescending to me, as if smaller apps using Vue weren't worthy to be part of the conversation any longer. I've been on both sides of that fence, both large projects and small, and I can honestly say that it was never EVER the size of the project that made it "meaningful".

Early on, I found Vue to be an inviting alternative to front end development vs. the other alternatives that were either A) not as intuitive to me or B) constantly changing to such a degree that it made standards compliance a time sink with no reasonable ROI. The object API was easy to understand and had IMO a low barrier to entry. I've evangelized for Vue with the last 3 companies I've worked for, and successfully convinced 2/3 of those teams to go with Vue for new projects for both the under the hood features (which we all know, love, and appreciate) but also for the ease of on-boarding and low cost of training someone new with the 2.x api. I disagree with the dev team's insistence that this new RFC concept contains that same spirit as it is presented here, but my biggest concern is those on the core team (not all, to be clear) who have had such dismissive and condescending attitudes towards the backlash, Evan included.

Finally, coding preference is absolutely a valid metric to use for choosing one framework over another, and is IMO just as valid here. I think most of us want to see Vue improve without sacrificing that which made us love it, both technical and code aesthetic if possible.

@yyx990803
Copy link
Member

yyx990803 commented Jun 24, 2019

First of all, thank you for the candid criticism and constructive feedback.

Regarding messaging around deprecation:

I admit the original phrasing of "deprecation" can be concerning to many users. This is why we updated the phrasing and adoption strategy immediately after objections have been made. However, we emphasized the new "additive" positioning from that point on not to hide the original phrasing (edit history is public after all), but in the hope of preventing further confusion. Looking back, we definitely could have handled the whole situation better by understanding what the users were really upset about and addressing that more directly.

Furthermore, the comments of "if you don't like it, don't upgrade when to v4" or "just use a plugin" are dismissive and disingenuous as well.

I don't think any core team member expressed such opinions, especially not in a dismissive manner. What we did say was "if you don't like it, you can keep using the current API since it's not going away", which I believe is quite neutral in tone. I know the thread is long and there are many people involved, but please don't assume that all opinions in favor of the RFC are from the core team.

There's been plenty of comments with the basic tone of trust us, we know what's better for you.

The comment you quoted is not from a core team member - and it in no way represents the core team's attitude towards users against this RFC. We respect all users.

my biggest concern is those on the core team (not all, to be clear) who have had such dismissive and condescending attitudes towards the backlash, Evan included.

Again, please let us know if any core team member comes across as dismissive or condescending in official RFC discussions - but so far in this RFC thread I don't think any of us are.

You may think some of my tweets on Twitter come off that way, but it's important to note I never said that everyone opposing the RFC falls into the "never read it" category. There are valid criticisms (like yours), but I think we can also agree that a decent number of the comments were made out of "feelings" while ignoring most of the reasoning laid out in the RFC. I reserve my right to express my frustration and disappointment towards such comments on my personal Twitter account.

Finally, coding preference is absolutely a valid metric to use for choosing one framework over another, and is IMO just as valid here. I think most of us want to see Vue improve without sacrificing that which made us love it, both technical and code aesthetic if possible.

I too personally value code aesthetics quite highly. However, as you may have noticed, the RFC thread also has MANY users expressing how they find the RFC to be solving the exact problem they are facing right now. And they have also mentioned that the current object-based syntax is the exact bottleneck that hinders the scalability of their projects. I acknowledge that many of you may never personally experienced this (which is totally valid, and even great!), but if an aesthetics choice comes at a real maintenance burden (admittedly only in certain types of projects), then it's no longer just an aesthetics problem. Denying some users' opportunity to solve their problems with a better abstraction due to the aesthetics preference of some other users seems like the wrong trade-off to make.

@mika76

This comment has been minimized.

@MattiasMartens
Copy link

MattiasMartens commented Jun 24, 2019

From reading the RFC I feel like the Vue team is understating how easy it would be to implement Vue's object component API with the functional API. In terms of features, the object API is a strict subset of the functional API.

I understand the pushback that comes from not wanting to rewrite existing code. I don't understand the pushback that comes from thinking the object API is aesthetically superior. What made me fall in love with Vue was not the syntax, and it certainly wasn't the presence of non-negotiable idioms. It was the unifying vision that whatever code you write should foreground your intention.

The reactivity API is a great example of this. I don't want to get into the weeds of how my subtotal stays in sync with the line items above it, I tell Vue I want this and it does it for me. I absolutely adore this approach to framework design and I see it guiding almost every major design decision that the Vue team has had to make.

Here's the thing. Choosing between a method, a watcher, a prop, a data field, and a computed property is not about intention. It's an implementation detail. There are dozens of correct ways to implement a moderately complex network of forms, flows, and interactions, all equally correct, all leaning to greater or lesser degrees on particular APIs. The decisions I make between them should not constrain the way I use code to express my intention. There is very little relationship between the choice of APIs and the goal I am trying to accomplish.

The object fields are a constraint on expressiveness. They may be a desirable constraint in some cases, but they are a constraint nonetheless. To argue against the functional API on this basis is to say that the constraints you prefer are the constraints everyone else ought to use as well.

There's also the argument that a new idiom will splinter the community. I don't buy that. Vue has never suffered due to an abundance of correct ways to do things. Newbies copy and paste, intermediates figure out how to write in styles they like, and experts figure out how to adapt code written in one style into another.

I can't stress enough how easy it is to translate object API code into functional API code:

  1. See a field whose meaning comes from the key of the object it's nested in (e.g. "methods", "computed")? Wrap it in a function with the name of that enclosing key. (Unless it's "data", then use value.)
  2. See a reference to this.aThing? Replace it with just aThing.value.

That alone gets you 75% of the way to adapting your internal library of idioms. Outside of how it will look, the change is not that radical.

And, inside of how it will look, there will be many ways of defining components in ways that resemble the existing style to whatever degree you want.

To be honest, I find it really hard to believe that folks are as attached to the existing syntax as they claim. And I find it disheartening that they would be willing to prevent the rest of the community from discovering the new idioms that this proposal makes possible on the basis of that attachment.

@Akryum
Copy link
Member

Akryum commented Jun 24, 2019

I can't stress enough how easy it is to translate object API code into functional API code

Even your computer can do it 😸

@mika76
Copy link

mika76 commented Jun 24, 2019

@Akryum do you have a github for your "suspicious project" 😉 I wouldn't mind posting a couple of ideas if there was one. One springs to mind, could you make it work with whole SFC's if possible - would easier to see the whole thing in one...

@Akryum
Copy link
Member

Akryum commented Jun 24, 2019

Here you go: https://github.com/vuejs/function-api-converter

One springs to mind, could you make it work with whole SFC's if possible - would easier to see the whole thing in one...

I initially focused on the script part, but yeah supporting the whole SFC will be the final goal.

@smolinari
Copy link
Contributor

I can't stress enough how easy it is to translate object API code into functional API code:

True, but it I find it hard to imagine it could figure out what methods, computed properties, data, etc. belong to a specific feature of a component. I do believe a computer, with a complex component, will spit out a bunch of spaghetti code. 😁

Scott

@Akryum
Copy link
Member

Akryum commented Jun 24, 2019

@smolinari It can 🐈

https://twitter.com/Akryum/status/1142898754401591296 🤖

The grouping and comments are automatically generated.

Logic is here

@smolinari
Copy link
Contributor

Well, that is a great little tool. @Akryum

And the resulting code looks quite clean, almost like with the object API. 😉

Scott

@MattiasMartens
Copy link

Great work on that @Akryum!

@smolinari One thing I would point out here is that grouping by feature is value added. I wouldn't expect a converter to be able to switch code grouped by field type to code grouped by feature, even if that's a thing you can do now (and even if @Akryum 's tool indeed does exactly that).

A direct translation of existing code would be more like:

{
  setup() {
    // Data
    const value1 = value(x);
    const value2 = value(y);

    // Computed
   const computed1 = computed(fn1);
   const computed2 = computed(fn2);

   return {
     value1,
     value2,
     computed1,
     computed2
   };
  }
}

But maybe this serves to illustrate how, the moment you don't have to group your field definitions by field type, your brain doesn't want to do it that way? 🙂

@smolinari
Copy link
Contributor

I wouldn't expect a converter to be able to switch code grouped by field type to code grouped by feature

That is what I meant. I don't think a converter can do that. How would it know what the feature is or know how to name it? Oohh, one of the hardest things to do right in programming!!!!

To get that done, you'd need some sort of wicked machine learning and AI. And thank the heavens, we haven't gotten that far. I hope we never do. Creation of beautiful things should be man's greatest accomplishment and always its greatest advantage over machines. That and being able to love each other. 😁

Scott

@Akryum
Copy link
Member

Akryum commented Jun 24, 2019

Not bad 😁

image

image

@smolinari
Copy link
Contributor

@Akryum - Looks good.

On the point of automation, couldn't Vue do the wrapping of reactive data and state during compilation? I mean, reactivity is now being made an opt-in, when in fact most data will want be reactive. So make non-reactivity the opt-in and just make any variable getting an assignment in setup() reactive? Would that be feasible at all?

Scott

@Akryum
Copy link
Member

Akryum commented Jun 24, 2019

Vue should also work without compilation.

@smolinari
Copy link
Contributor

Or non-compiled Vue would need to stick to the object API. 😁

But, if that can't be a choice, I understand. 👍 Thanks!

Scott

@drakeba
Copy link
Author

drakeba commented Jun 25, 2019

@yyx990803 I apologize for the late response, I spent all of today driving and could not participate in the day's discussions. I got home to this comment by @Akryum that made me extremely happy though:

We no longer have any plan of deprecating the Object API. It will stay for the foreseeable future. No refactoring needed. This also means we don't plan to drop it for Vue 4 too.

I don’t want to drag this out anymore, particularly after the core team has responded to the community concerns, but I’d like to give you proper respect by at least acknowledging your post and a couple of points within.

Looking back, we definitely could have handled the whole situation better by understanding what the users were really upset about and addressing that more directly.

Agreed, and I appreciate you acknowledging that point and working hard towards a resolution.

I know the thread is long and there are many people involved, but please don't assume that all opinions in favor of the RFC are from the core team.

This is a great point, and I can admit that I was definitely guilty of assigning many opinions to the core team that were ultimately unfair to you guys. Apologies for that, I’m still learning who’s who in here and my emotions were also on high.

I reserve my right to express my frustration and disappointment towards such comments on my personal Twitter account.

I giggled a little bit at that one… not because you’re wrong, of course you have the right to be frustrated and disappointed and to express that on your private accounts….. but it reads as if maybe, just maybe, you underestimate your own renown, at least in our community. Your public Twitter is an extension of you is an extension of Vue, at least to me. I can own that if I’m wrong though. ;)

Denying some users' opportunity to solve their problems with a better abstraction due to the aesthetics preference of some other users seems like the wrong trade-off to make.

Agreed, and I think the final solution was the best I’ve heard thus far. We should definitely try to keep the features that people love while continuing to solve problems for those that need it. I didn’t think the original functional API concept did that, but I’m quite satisfied with where you guys landed.

I appreciate the efforts you and the core team put into resolving this “core crisis”. The initial response was a bit wanting, true, but you all recovered and, in my opinion, landed in a much better place without alienating anyone in the end. Lessons learned from all sides hopefully, and in this case, I’m personally quite happy to have been wrong about how I perceived the response.

Now hopefully we can all get back to solving the problems of our users. ;)

@martinsotirov
Copy link

Not bad 😁

image

image

These code snippets scream lack of readability and clarity to me. I appreciate that there are personal preferences and you might like that style of imperative programming which the new API favors, but to me this is WordPress or even jQuery spaghetti all over again.

@Akryum
Copy link
Member

Akryum commented Jun 25, 2019

@martinsotirov Again, those are automatically generated from an experimental tool for migration easing purposes.

Here is what it would actually look like in the end: https://gist.github.com/Akryum/05964e81d09fb5088b7769cff15f5e7c

@smolinari
Copy link
Contributor

Yeah. The final result is what I'd expect from a human, not a machine. 😁 But certainly your "translator" is an excellent start for refactoring. @Akryum

Scott

@majkelch
Copy link

For such complex change and new approach I'd like to see some real examples. What I mean by that?
I mean real application with like: vue-router, vuex, boostrap/vuetify, axios (or whatever other popular choices are). Not a simple to-do app, but something that is close to real life application.
What structure would that app have? How communication would look? How would structure of bigger components look like? How would setup() look with more than just a couple of computed?

Imo examples in this RFC are too trivial or very abstracted from "real life" work...

@alexbikazzan
Copy link

While I can agree to some extent that the risk of spaghetti is slightly higher and that readability and that aesthetics might suffer a bit I don't think it's nearly as much as people here make it out to be. In my opinion, it's marginal.

What I love most about Vue is SFCs, which to me is 80% of making components scannable and clear, and SFCs are here to stay if I'm reading this RFC and the discussions correctly.

I've been coding a lot of Angular lately (work stuff you know :)) and I always have to split screen and tab between files to find out what state maps to what element and where different parts of logic is coming from. That is never the case with Vue.

If we can do stuff like this with the new proposal:

function useMouse() {
  const x = value(0)
  const y = value(0)
  const update = e => {
    x.value = e.pageX
    y.value = e.pageY
  }
  onMounted(() => {
    window.addEventListener('mousemove', update)
  })
  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })
  return { x, y }
}

// in consuming component
const Component = {
  setup() {
    const { x, y } = useMouse()
    const { z } = useOtherLogic()
    return { x, y, z }
  },
  template: `<div>{{ x }} {{ y }} {{ z }}</div>`
}

then I'm all for it. Mixins are neat, but this is better.

Secondly, I don't think logic composition is a problem for large apps exclusively. I've been working in small teams mostly and we face these challenges all the time.

Anyway, I think a solid starter template in the vue-cli will go a long way in keeping the learning curve low, and I'm sure the docs for 3.0 will be awesome as always 💯

@daniesg
Copy link

daniesg commented Jun 28, 2019

I really am coming around to the function API. I initially really hated this, but I'm really starting to appreciate what you guys are trying to do.

If it's one last thing that's really bothering me, it really is the readability of it. But (unless I'm being naive), I think it could improve by simply just grouping things in the return statement.

In one of the examples, there is:

return {
    state,
    double, // computed
    increment //method
  }

is there any reason it couldn't just be something like

return {
    state,
    computed: { double },
    methods: { increment },
  }

I'm always going to want to find some kind of tldr or summary first, and my eyes are always instantly drawn to that return statement. I understand at the same type it seems redundant (at least the computed part), and I'm sure there will be some kind of convention about grouping like things together, but I really think it helps readability when you force some kind of grouping.

also, the comment above mine with the example (@alexbikazzan) was super helpful.

@smolinari
Copy link
Contributor

@alexbikazzan - It works! https://codesandbox.io/s/function-based-api-example-vue-rfc-78nc1

I had to comment out z, but I think what you wanted to see is there. 😃

Scott

@alexbikazzan
Copy link

@smolinari, I sure hope it works, it's an example from the RFC itself :)

@smolinari
Copy link
Contributor

Well, now it is a real working example. 😁

Scott

@yyx990803
Copy link
Member

Closing in favor of #78

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants