Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Andrey Popp
    @andreypopp
    @ds300 thanks, super useful feedback, I improved the article
    David Sheldrick
    @ds300
    No worries. I only did grammar feedback for the first one, will try to get around to the others soon.
    Will Mruzek
    @mruzekw

    I'm trying to build a game with DerivableJS

    https://gist.github.com/mruzekw/84a43be6490ae532515e90252933a38f

    It's simple. The user is shown a 5x5 matrix of squares. Nine of them are highlighted for 5 seconds. Then the user has to select those squares to win the game.
    You can find a demo here: http://mruzekw.github.io/recall-reactjs/

    I'm currently defining when the player has won. I currently have:

    let playerWon = gameOver.and(curBoard.derive((curBoard) => {
      return isCorrectSelection(
        expectedBoard,
        curBoard.toJS()
      );
    }))

    But I think I'm missing something cause it's not working...

    Will Mruzek
    @mruzekw
    Actually it might be working, one sec please
    Will Mruzek
    @mruzekw

    It was actually working. Had something wrong in my view code.

    I wondered if anyone would be willing to take a look at it. I'm especially curious about my use of setTimeout() and if that's the way to go

    David Sheldrick
    @ds300
    I'll take a look tomorrow :+1:
    Will Mruzek
    @mruzekw
    No worries, thanks
    David Sheldrick
    @ds300

    @mruzekw Your use of setTimeout seems fine to me. You can change

    let gameOver = turnCount.derive((count) => {
      return count === 9;
    });

    to

    const gameOver = turnCount.is(9);

    Also, if you keep expectedBoard as Immutable data held in an atom, then you don't need isCorrectSelection and you can just define playerWon as

    const playerWon = gameOver.and(curBoard.is(expectedBoard));

    Otherwise, looks really nice :)

    Will Mruzek
    @mruzekw
    Thanks for taking a look @ds300 !
    Liron Shapira
    @liron00
    hey guys
    i recently published this blog post, and afterwards i've been following up on all the comments and emails, doing a lot of research into what existing solutions are out there
    Liron Shapira
    @liron00
    my conclusion is, there are a ton of databases out there, yet somehow none of them support FRP
    the only FRP thing out there is Materialized Views
    which could theoretically be great except they are very limited
    so, i am thinking about building some kind of backend FRP data layer
    i would consider literally just running Derivable on a single server with 128gb of ram, and calling that my database. i just need a bit more durability than that.
    @ds300 thoughts?
    David Sheldrick
    @ds300
    Have you thought about Domain Driven Design + Event Sourcing? It properly solves denormalization problems. I'm currently building a service with DDD after only ever doing traditional databases before and it's like a dream. I can link you to learning material if it's a new concept to you.
    David Sheldrick
    @ds300
    Oh wait, just got to that part of the article :D
    Liron Shapira
    @liron00
    haha ya, i am a fan of event sourcing. i would like to do frp and event sourcing.
    check out this thread i had with greg young
    David Sheldrick
    @ds300

    Also, I notice this approach is imperative / trigger style, meaning we have to spread out the code for a computed value across all the dependencies where it's computed from. Is there a more declarative / materialized view / Functional Reactive Programming style approach?

    Greg's example updates state in an imperative style, but it's trivial to get a more FRP-style with these systems by using the reducer pattern (as seen in Elm, Redux, etc). For any stateful entity in your system (denormalized by virtue of simply not being an event), all you need to do is put together a stream of all the events from your journal which could effect the entity's value, and then write the logic for each event type, saying what it means for that particular piece of state. It's a profoundly simple separation of concerns in theory and practice. Having state-only FRP like Derivable would be a relatively thin layer of icing on top of the enormous and delicious cake that is event sourcing :)

    Liron Shapira
    @liron00
    hm, are you sure about that? it seems like dependency tracking at scale is more than icing
    when you say "all you need to do is put together a stream of all the events from your journal which could effect the entity's value"
    isn't that the fundamental problem of writing clunky code which my post talks about?
    having to manually reason that it has to be either "newMessage" or "seenRoom" or "markAsRead" or "deleteRoom" or "deleteMessage", etc
    by your logic, redux is already great so we don't really need derivable/mobx/vueJS :)
    i do agree that it's always quite easy to write the first "layer" of the denormalization graph, like defining the Message object as a function of the event stream
    but the moment you have a field which is extra denormalized, not like User.name but like User.numUnreadRooms, i think FRP becomes critical right? you need a derivable computation
    David Sheldrick
    @ds300

    isn't that the fundamental problem of writing clunky code which my post talks about?
    having to manually reason that it has to be either "newMessage" or "seenRoom" or "markAsRead" or "deleteRoom" or "deleteMessage", etc

    I'm not sure I follow. In your blog post you say

    A good codebase is one that makes you, the programmer, nimble. Such a codebase minimizes your workload in the face of ever-changing (1) behavioral requirements and (2) schema field definitions.

    The normalized approach, for all its performance flaws, at least lets us take our beast of a query and wrap it in a function — something like getNumUnreadRooms(userId). That function can be referenced from anywhere in our codebase, so any change to the schema field definition of User.numUnreadRooms requires us to change our code in only one place. With the normalized approach, we are nimble.

    But one gets exactly the same benefits with event sourcing. Domain changes don't cascade exponentially. New features and changes to existing features are often stupefyingly easy to accomplish because you get this same separation of concerns. The main difference is that you write pure reducers instead of pure query functions.

    David Sheldrick
    @ds300

    by your logic, redux is already great so we don't really need derivable/mobx/vueJS :)

    Haha 🙈 - I think that Derivables are extremely useful for computing derived state and using it to trigger side effects. I'm using Redux without Derivable right now in a React Native app and I often feel crippled without Derivable and frustrated by the boilerplate and indirection that Redux requires to effectively deal with derived state.

    However, I haven't felt any of that pain while working on the backend.
    I'm sure there are some backend use cases that would benefit from Derivable or something similar though
    Liron Shapira
    @liron00
    Haha well what do you think of my specific example, User.numUnreadRooms?
    You wouldn't feel any pain sprinkling ad hoc code to denormalized that in 5 forgettable places?
    Ok I will admit that event Sourcing solves the problem of schema migrations even without FRP
    Cuz you can just rerun the events and projections
    But still do you really want to write User.numUnreadRooms in a pure imperative style? Maybe you can add to Greg's post to show the full code needed because I'm not sure how painful the whole thing becomes
    Oskar Börjesson
    @oskbor
    @ds300 thanks for the quick reply on github, i just stumbled upon the backlog (not an experienced githubber yet) and will dive in tomorrow!