karimayachi / karimayachi.github.io

MIT License
2 stars 0 forks source link

What to take as a starting point? #3

Open karimayachi opened 4 years ago

karimayachi commented 4 years ago

TKO should provide all the requirements for the MVVM-style requirement, but maybe is bloated, non-performant and not production ready and prove difficult to incorporate Composition-style requirements.

Knockdown may provide the requirements for the Composition-style requirement, but may not perform MVVM-style parsing of HTML?

Starting from scratch is of course least favorable, but may be necessary if above solutions don't suffice.

avickers commented 4 years ago

TKO

In my estimation, the amount of work required might exceed the work required for greenfield development.

There are still functions in there designed to account for IE6 quirks, even though TKO doesn't even support IE6. There's a lot of refactoring to do, and there's a massive number of modules that the code weaves its way through.

Then there's the maintenance that comes with a framework that's added most of the hot features from the past 7 years and declared them all to be optional bolt-ons.

I think that, if we wanted to start with TKO, we would probably just want to pull out the core modules and deprecate a lot of the ambitious additions.

Knockdown

What do you mean by MVVM-style parsing of HTML, precisely?

index.html

<body>
    <h1 data-bind="text: title"></h1>
    <p data-bind="text: content"></p>
</body>

index.js

const ko = new Knockdown(document) // or some node
const viewModel = {
    title: ko.observable("Hello World"),
    content: ko.observable("Thanks for stopping by.")
}
ko.applyBindings(viewModel)

This works. Not only does it work, but you can add and remove bindings dynamically and Knockdown will automatically account for them. A Mutation Observer tracks all changes to data-bind attributes inside the child tree. MO doesn't pierce the Shadow DOM; so, Web Components are properly encapsulated; and, allows for Views inside of Views.

However, if you mean putting conditional logic inside of the raw HTML, ie creating anonymous computed/dependent observables, that is blocked by CSP. To get around this safely, we'd basically be going down the rabbit hole of Lexical Analysis, Tokenization, and writing a Compiler.

While that was a nice convenience feature with KO3, I'm not sure that I feel that being able to put logic directly inside the View is a requirement of MVVM. It could just as easily be argued that a strict adherence to MVVM would mean that logic should be inside of the VM in the first place. Personally, I'm of the less opinionated mindset; and so, I don't mind what KO did; however, CSP does; and, I feel compliance is more important than convenience in this instance. In fact, lack of CSP support is probably what killed off KO's marketshare more so than lack of a version 4, imo.

Greenfield

I guess it depends on what the final scope of the project is as to how much work this is. A fairly unopnionated framework can be easy to write, but it also allows for a wide range of use cases, which means lots and lots of patching and test writing early in the development lifecycle.

With Knockdown, I was surprised how quickly I got to an MVP. That said, getting to a production ready product has also proven to be more work than I really considered.

It is possible that it could prove to be the best option depending on the final specs, but it may be possible to salvage at least some code from either TKO or KD if that proves true.

karimayachi commented 4 years ago

What do you mean by MVVM-style parsing of HTML, precisely?

Yeah, sorry, wasn't really clear on this :-) I meant just what you showed, simple two-way bindings. Wasn't sure if KD does that the same as KO.

I agree on not supporting JavaScript in HTML. With all it's CSP problems, etc. It comes in handy sometimes, but nothing you can't fix by having functions in the viewmodel. I hardly ever have JavaScript functions in bindings.

I do however think that we need basic conditional logic.

<h1 data-bind="text: title"></h1>

<h1 data-bind="visible: showAllTitles || showPrintables">My Title</h1>

<h1 data-bind="click: function() { alert('HACKED YOUR PAGE'); }">My Title</h1>

That's where TKO (maybe) comes in: there is a lot of binding and parsing logic already.

I think that, if we wanted to start with TKO, we would probably just want to pull out the core modules and deprecate a lot of the ambitious additions.

Agreed. So maybe we can use KD and pull in some parsing logic from TKO or something like that.

avickers commented 4 years ago

OK, so it sounds like we're saying that data-bindings should have their own Domain Specific Language of sorts. What is the scope here? How complex should the expressions be allowed to become?

karimayachi commented 4 years ago

How complex should the expressions be allowed to become?

As simple as possible. 😄

What I never liked about Knockout is that they (I'm over simplifying a lot here I think) parse a binding to be a property on the viewmodel or JavaScript in a string to be eval-ed. So in the first case I could use the property name and have Knockout unwrap the underlying observable, whereas in the second case I would have to resolve the observable-function.

<h1 data-bind="visible: showAllTitles">My Title</h1>

<h1 data-bind="visible: showAllTitles() || showPrintables()">My Title</h1>

It's a really small thing, but it has confused many an intern at my company and inevitably leads to mistakes with unexperienced developers.

Since we would stay clear from evals and would have to make a condition parsing method, we could do away with this inconsistency.

In the long run I would love to have nested ternary and boolean operators, but for an MVP it would probably be enough to have only non-nested OR and AND.

There are probably condition-parsing libraries that could assist here, although for the simple case it shouldn't be too hard to make something.

avickers commented 4 years ago

It seems like we're really talking about an implementation of the shunting-yard algorithm. I suspect there will be no shortage of CC0 starting points, including TKO.

I am not really comfortable with the idea of things like nested ternaries in the core library for a number of reasons:

Also, I feel like we need to be able to explain the boundaries of what's allowed in, at most, a short paragraph.

That said, I feel that there's a very compelling case for && and ||, and quite likely even simple ternaries.

I get that using complex conditional logic inside of HTML would be optional, but I'd be concerned about how decision makers (PO/PMs) would react if they read an article on, for instance, Medium where someone went overboard with this. The use of any sort of logic or JS inside of HTML has long been polarizing, even before the XSS aspect was fully appreciated.

All that said, I can see how, in shops where you have more experienced teams of engineers doing all the work, it would potentially enhance legibility and maintainability. I feel like the best solution in this case is to create a plugin that provides for a more liberal and expansive binding parser, so that there is an explicit opt-in. Is that a good compromise?