Effect-TS / website

Source code for Effect's documentation website
https://www.effect.website
97 stars 84 forks source link

Improving "Effect Essentials" #100

Closed ethanniser closed 1 year ago

ethanniser commented 1 year ago

Some initial ideas on how this section can be improved:

Happy to do work on any/all of these

gcanti commented 1 year ago

I agree with almost all the points. I have worked a bit on "Building Pipelines" and "Using Generators". However, regarding the "Do Simulation", I'm not convinced it should be included in the page about generators as it would divert the focus from the main topic.

ethanniser commented 1 year ago

However, regarding the "Do Simulation", I'm not convinced it should be included in the page about generators as it would divert the focus from the main topic.

To me having "Generators" and "Do Simulation" in different places doesn't make a lot of sense, they both do not not adding any specific functionality, instead they simply provide some alternative syntax/style of writing the same code.

In that way I think "Code Style" is a good place to put both, but I understand if this topic is something we want to introduce earlier rather than later.

Thoughts on changing the topic from strictly "generators"/"do simulation" to "avoiding callback hell" or "writing Effects in a "imperative" way"? This way both can fit in the same page.


The changes you made to generators and pipeline look good, thank you for those.

I still think the Dual APIs section could be further improved. I think that to a fresh reader it can come off as though there are 2 different versions of every function, when in fact there is only ever one.

Effect.map(effect, increment)
pipe(effect, Effect.map(increment))

I think its confusing to call these "different variants", when they are the exact same- with some syntactic sugar on the second one

I think it would server better to reinforce to the reader what pipe does and how because nearly every function takes the "data" as the first argument, pipe can be a useful way to avoid nesting function calls, but at the end of the day the end code is the exact same.

(I am aware of the tooltip explaining this at the very bottom but I think it could be better communicated overall)

With all that said, as they represent very similar ideas, I actually think we should consider merging the "dual api" part with the "pipe part" instead of having them at opposite ends of the page,

Heres what I was thinking for this new merged section that would go at the top of the page

thoughts?

gcanti commented 1 year ago

"Avoiding Callback Hell" is a good title for a page that talks about Do Simulation, but it is more about pipe than Effect.gen. The use of generators allows much more than just solving the callback problem; it allows you to use normal control flow like if/else, while, etc. Therefore, it holds much more importance for us (and for users who want to adopt it). Avoiding nested callbaks is just one of the many things it is capable of doing.

I think its confusing to call these "different variants"

We could call them (TypeScript) "overloadings", that's what they are actually.

ethanniser commented 1 year ago

I agree on the important of generators, and so it makes sense to leave it in Essentials.

The use of generators allows much more than just solving the callback problem; it allows you to use normal control flow like if/else, while, etc.

I just reread the page and I think we could do a better job of explicitly calling this out. We show it in the examples but I think some additional text explanation could help drive the point home of what is so powerful about generators.


As for pipe, is there a need to distinguish between "data-first" and "data-last' at all? Those terms are never mentioned again anywhere in the docs. I think if we can show the reader what pipe does and that just calling the functions plainly is the same thing they will be able understand any examples of both styles. I don't think anyone is going to come away thinking they need to use pipe for every function call, or never use it all.

I think something like this (basically what is there now with a clear disclaimer that pipe/not-pipe are the exact same) at the top of "Building Pipelines" is all that's needed to set the reader up for success understanding the code to come.

ethanniser commented 1 year ago

Just realized my mental model for data first/last was completely wrong and so many of this feedback was too. So my apologies for that, I'm out right now but I will add another comment later explaining what I was confused on.

ethanniser commented 1 year ago

Basically what happened was I incorrectly assumed what pipe was doing. In the past I have worked with R, in which pipes are 'hack pipes'

x |> y(z) === y(x, z)

However, most functional languages (and Effect) use 'F# style pipes'

The tc39 javascript pipe operator proposal explains the distinction between the two really well.

Looking back at the examples in the docs:

const result = pipe(5, increment, double, subtractTen) // 2

pipe being 'f# style' seems obvious, but I think the overloading nature of map and flatMap tripped me up, and thinking things were the other way

When earlier I said

I think its confusing to call these "different variants", when they are the exact same- with some syntactic sugar on the second one

I thought that pipe was doing:

pipe(x, Effect.map(f)) === Effect.map(x, f)

but that is (now obviously) wrong, whats actually happening is

pipe(x, Effect.map(f)) === Effect.map(f)(x)

which is an overload as you correctly pointed out, had I looked closer at the api reference I wouldve seen this:

export declare const map: {
  <A, B>(f: (a: A) => B): <R, E>(self: Effect<R, E, A>) => Effect<R, E, B>
  <R, E, A, B>(self: Effect<R, E, A>, f: (a: A) => B): Effect<R, E, B>
}

a nice alternative to

pipe(x, (x) => map(x, f))

is there a need to distinguish between "data-first" and "data-last' at all?

I was very wrong, this an important distinction.


I think this confusion could be common with how the page is currently written:

here are my suggestions if you agree with any, if not no worries:

gcanti commented 1 year ago

@ethanniser I agree with many of your suggestions, and I have worked further on "Building Pipelines". However after this discussion I have reconsidered my initial choice to talk about dual APIs in the documentation regarding pipelines. Applying the same principle mentioned in the discussion about error management and the @effect/data/Data module

Don't explain anything the learner doesn't need to know in order to complete the tutorial.

(from https://documentation.divio.com/tutorials/#provide-the-minimum-necessary-explanation)

and since explaining dual is not strictly necessary to write a very first pipeline, I have chosen to move dual APIs to its own section (namely under Guides/Code Style).

In addition, by doing this, if it becomes necessary to expand the documentation regarding dual APIs, we can do so without further burdening and unnecessarily complicating the topic of pipelines.

gcanti commented 1 year ago

I think some additional text explanation could help drive the point home of what is so powerful about generators

Done https://github.com/Effect-TS/website/pull/118