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

Complexity, Verbosity #110

Open
deklanw opened this issue Aug 13, 2019 · 7 comments
Open

Complexity, Verbosity #110

deklanw opened this issue Aug 13, 2019 · 7 comments

Comments

@deklanw
Copy link
Contributor

deklanw commented Aug 13, 2019

This is just an observation. Turbine seems to me to be both complex and verbose.

Complexity: The API surface area just to get started is large.

Verbosity: Just intuitively the library feels verbose to me. I compared the TodoMVC example in lines and characters to a few other libraries. It was the longest by both measures.

It's not clear to me how much is accidental complexity or whether the verbosity can be fixed anywhere.

@paldepind
Copy link
Member

Thanks a lot for sharing your opinion. This is definitely worth talking about.

I think I understand you are coming from, but it would be very useful if you would share a bit more details about what you find complex and verbose.

With API surface area do you mean the number of functions, the number of types, or the complexity of each type or function? Do you mean the API of Hareactive, or Turbine, or both? Any part of the API in particular that you felt was unnecessarily complex.

With regards to verbosity, which TodoMVC examples did you compare to? Any parts, in particular, that triggers your intuition about the library being verbose? Do you think the email validator is verbose? Or do you only think the verbosity creeps up in other examples?

Personally I think Turbine is only adequately complex and, most of the time, I don't think it is verbose. I actually think it can be very consice. But, before I write a more comprehensive response I'd love to hear you point of view in more detail 😄

@Jomik
Copy link
Member

Jomik commented Aug 16, 2019

This seems to be sort of related to some of the concerns I have brought up over the time with @paldepind. However I mostly agree that it is not overly verbose.
The API is getting large, because a lot of helper functions, that should make the API more intuitive, is being added.
We could actually get away with a way smaller API, in Hareactive, but it would also make it a lot more complex for the user to achieve what they want, rather than simply having a larger API.

I also think it would be awesome if you could share the code examples that you used for the comparisons, it is definitely something I would like to look at.

@deklanw
Copy link
Contributor Author

deklanw commented Aug 16, 2019

Yes, I partially am talking about the large API

import { fgo, sequence, IO, combine } from "@funkia/jabz";
import {
  Behavior,
  sample,
  snapshot,
  Stream,
  performStream,
  changes,
  lift,
  snapshotWith,
  accumCombine,
  moment,
  shiftCurrent,
  empty
} from "@funkia/hareactive";

But, to me this isn't the biggest deal. I think optimizing for long-term productivity is more important than short-term productivity. If I worked with Turbine regularly I'm sure the API wouldn't be a problem.

Few weeks ago I did some counting. This isn't meant to be taken too seriously, just a quick check. I understand it's not some objective measure. Some may have been changed from when I counted, I removed some comments, may have missed a comment here or there, etc. Some are typed. Some aren't. Some are split across files, so there's some extra characters for duplicate imports, etc.

cwws = characters without white space

Turbine (split across files. Very modular. Many types.):
553 lines, 9991 cwws.
Cyclejs (split across files. Very modular) https://github.com/cyclejs/todomvc-cycle/tree/onionify:
403 lines, 7870 cwws.
Rust-Dominator https://github.com/Pauan/rust-dominator/tree/master/examples/todomvc:
429 lines, 6880 characters without white space.
Reflex (excluded CSS at bottom (idk why its there)) https://github.com/reflex-frp/reflex-todomvc/blob/develop/src/Reflex/TodoMVC.hs:
211 lines, 6512 cwws.
Reframe (includes spec) https://github.com/Day8/re-frame/tree/master/examples/todomvc/src/todomvc:
350 lines, 6065 cwws.
Elm https://github.com/evancz/elm-todomvc/blob/master/src/Main.elm:
378 lines, 5389 cwws.
React + Hooks (split across files) https://codesandbox.io/s/74yq01ovl1:
394 lines, 4989 cwws.
Surplus (split across files) https://github.com/adamhaile/surplus-todomvc/tree/master/src:
213 lines, 3785 cwws.
Solid https://github.com/ryansolid/solid-todomvc/tree/master/src:
156 lines, 2932 cwws.
Svelte https://github.com/sveltejs/svelte-todomvc/blob/master/src/TodoMVC.svelte:
149 lines, 1913 cwws.

I think comparison with Svelte and Elm is interesting. Svelte: untyped, reactive, impure. Elm: typed, pure. Turbine: typed, functional reactive, pure. Personally, the Svelte example seems the easiest to grok, not least because of the terseness.

These comparisons lead me to reflect: how much is purity worth? Is it worth 10x verbosity? 5x? 2x? What are the advantages of Turbine vs Elm? Are there ways to simplify and tersify Turbine? How would these verbosity numbers look for a larger app like RealWorld app? Any plans to implement that with Turbine? https://github.com/gothinkster/realworld

@paldepind
Copy link
Member

Hi again @deklanw. Here's a small reply.

But, to me this isn't the biggest deal. I think optimizing for long-term productivity is more important than short-term productivity. If I worked with Turbine regularly I'm sure the API wouldn't be a problem.

Ok. I'm glad that we agree on that one. Turbine isn't an attempt at making the simplest thing possible and Hareactive has a large API because those functions are useful. I think developers can handle that. Lodash has a large API for arrays and Bluebird has a large API for promises. That is exactly why those libraries are useful. As long as an API consists of many othorgonal functions I think an API of some size is acceptable.

Are there ways to simplify and tersify Turbine?

Sparked by this thread we've started implementing some ideas that take us in that direction. The key idea is this: take the current loop function, rename it to component, and make it the default choice for creating components instead of the modelView function. This has two advantages. 1/ loop is quite a bit simpler than modelView. 2/ This approach involves a lot less boilerplate. So it should adress both of your points 😄 I've created a work in progress PR that implements these changes. I've also done some other refactorings of the TodoMVC example and from the git diff it appears to have reduced the line count by around 80-100. Take a look at the PR if you're interested. I'll write a reply to your other questions later 😄

@paldepind
Copy link
Member

Hi again @deklanw. I think we have now answered "yes" to your question:

Are there ways to simplify and tersify Turbine?

We've made quite a few changes to Turbine in order to cut down on complexity and verbosity and we've found on an alternative to generator functions. This has made the API simpler and cut down on the line count in the examples. If you have the time please take a second look at the TodoMVC example. I think that it is now very competitive in terms of verbosity when compared to other full implementations of TodoMVC (note that some of the implementations you mentioned above miss certain functionality/has bugs).

@deklanw
Copy link
Contributor Author

deklanw commented Sep 26, 2019

That was fast! 350 lines, 7362 cwws. A huge improvement, definitely.

I'm not totally sure what on and start are doing here but I'm sure the README will explain eventually. Great work!

@janat08
Copy link

janat08 commented Jun 20, 2020

The start and on are still not explained. Typescript lets you comment on types, and you can then produce docs from that. Cyclejs does it.

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

4 participants