As I said, in your small example it probably doesn't matter. But I've also
seen larger examples with more fields in the top level model. My point is
that if there are any cross-field validity constraints, then it's probably
a bad idea to have lots of code that is not only able to but expected to
produce new models. Classic TEA allows one to have the page handler code
handle pages — keeping the top level model ignorant of the details and
unable to muck with the page model — while the top level code handles and
enforces the constraints for the top level model.

Export as little as possible. If you have constraints on how pieces
interact and you can't just make the type system enforce them, then make
sure there is only one module that can modify those pieces. Reduce the
surface area in case you have to go hunting for bugs.

Mark

On Wed, Mar 29, 2017 at 5:57 PM Witold Szczerba <[email protected]>
wrote:

> I'm not really sure what are you suggesting, Mark. Is it's all really
> about that CSRF token, then OK, I could have hide it behind opaque type and
> expose just the bare minimum, so noone could tinker with it's value. Or I
> could turn the simple architecture into more complicated (extra mappings of
> models and commands?) just in the name of... what would that be? And what
> if all that barriers and safety guards turns against me by being too
> restrictive?
>
> Just because you can change that token, does it mean you could do it by
> mistake? I don't really think that would the case. And if you have to, you
> could just do it, without developing circles around all those "safety"
> guards, I guess...
>
> 30.03.2017 1:36 AM "Mark Hamburg" <[email protected]> napisał(a):
>
> While it cuts down on the boilerplate, it seems like this creates a fair
> amount of exposure for what might otherwise be internal structures. For
> example, if the page update functions all get and produce full models, then
> each of the modules implementing those update functions becomes a place
> where any cross-field invariants have to be maintained. Now, if you can
> build your model in such a way that all representable states are also
> considered legal — the corollary to making illegal states impossible — then
> you don't have a problem. But if you can't arrange this, then you've taken
> a validity concern and spread it through your codebase. Functional
> programming protects you from a particular data instance being modified but
> you still need to figure out how you guarantee that all data instances that
> get produced are valid. In your little example — which probably is small
> enough not to trigger a problem — would you consider it acceptable for a
> page update to change the CSRF token? If not, then the page update should
> not produce a new Model.
>
> Mark
>
> On Wed, Mar 29, 2017 at 3:29 PM, Witold Szczerba <[email protected]>
> wrote:
>
> The best solution to deal with your problems is to use Swiss knife of
> functional programming, i.e.* function composition*. You would be
> surprised how about anything could be handled by this *simple* technique.
>
> Few weeks ago there was a question asked on Reddit about nesting data in a
> model. It was actually more about structuring the application, so I think
> your questions are related. I have answered providing a little example of
> the structure of my own application. I think you could be interested, so
> please take a look:
>
>
> https://www.reddit.com/r/elm/comments/5wikog/easy_questions_beginners_thread_week_of_20170227/deeptz3/
>
> In my opinion (yes, I am repeating myself) the most simple layout of all
> the "modules" is to have an update functions like this:
>
> *update: XyzMsg -> Model -> ( Model, Cmd Msg )*
>
> Where XyzMsg is the module's message, Model is top level model and Msg is
> top level message. The main update function just delegates to the update
> functions of each module, so it looks like a table of contents of possible
> actions and the main model looks like a table of contents of the possible
> states. It really makes working with the application a pleasure :) Every
> time I go back to the other app written in AngularJS, I feel like I am lost
> in a thick fog.
>
> I hope it helps!
>
> Regards,
> Witold Szczerba
>
> P.S.
> My application has grown a little bit since then, the main model is now a
> little bit different:
>
> type Page
>     = NoPage
>     | AnnouncementListPage (WebData (List Announcement))
>     | AnnouncementItemPage (WebData AnnouncementForm)
>     | PayoutCancelledListPage (WebData PayoutListForm)
>
>
> type alias Model =
>     { page : Page
>     , csrfToken : String
>     }
>
> As you can see, now I am able to keep a `csrfToken` independent of the
> current page. Now I can add even more things not related to the actual
> page, like e.g. logged in user.
>
>
> On Wed, Mar 29, 2017 at 11:29 PM, Juan Ibiapina <[email protected]>
> wrote:
>
> Thanks for the explanation.
>
> I understand the choices made so far, but I still haven't been able to
> find good solutions for some simple problems:
>
> 1. I don't want to have every single possible message handled in the same
> place. It gets too big.
>
> 2. My global update function deals with everything in the app, including a
> message to update the value of the e-mail input field when the user is
> typing. This seems like a small concern that should be handled by the login
> page (or a component?). I don't want to clutter my model with temporary
> data.
>
> 3. On my User info page, my model is the same as other pages, so it has
> Maybe User. Since I have authorization, I *know* that there will always be
> a user when I go to the user info page. I want this to be reflected on the
> code, so I never have to check if there is a user.
>
> So far these issues are pointing me towards some sort of page separation,
> but I haven't been able to come up with something I like yet.
>
> On Wed, Mar 29, 2017 at 9:54 PM, Mark Hamburg <[email protected]>
> wrote:
>
> The config approach pops up various places — e.g., elm-sortable-table —
> but isn't as well specified anywhere that I've seen because it doesn't have
> as clear a pattern to specify.
>
> Cmd.map (and Html,map) come out of what could be called Classic TEA. The
> classic Elm architecture was built to allow decomposition by using tagged
> messages to route through the compound model. For example, if you wanted to
> have a number of pages, you could have a top level model that served as a
> page switcher and it would use tagged messages to route to the current page
> (or to discard messages if they weren't bound for the current page). This
> worked well though I know programmers who grouse at the amount of message
> routing boilerplate one has to write.
>
> But then people started trying to build React style component models with
> this and had trouble. At which point, various people in the Elm community
> decided that nesting was a bad idea and advocated strongly for flatness
> with functions being the only decomposition mechanism and those without
> much in the way of architectural guidance. Basically, this was a case of
> the pendulum swinging wildly and the architecture for building complex
> applications seemingly getting cast aside without a replacement.
>
> My advice would be to use the message routing patterns from classic TEA in
> the places it makes sense to break ones app apart — just know that it isn't
> particularly well suited to building components.
>
> For example, our codebase contains a module providing a model and
> corresponding messages and update function for managing the sign up/sign in
> process. It knows how to talk to our server. It knows what validation to
> do. It understands the errors coming back from the server. It knows nothing
> about how to display the data and instead provides a function to fill in a
> ViewData structure that contains the information needed by the view code.
> We can now reuse this logic in a variety of places where we need SUSI
> logic. Each of those hosting cases then routes messages to and from the
> logic using a message case of the form `ToLogic Logic.Msg` and using
> `Cmd.map ToLogic` to promote logic layer messages to view layer messages.
>
> Mark
>
> On Wed, Mar 29, 2017 at 11:50 AM, Juan Ibiapina <[email protected]>
> wrote:
>
> Where can I find more information about that Config approach? I'm not able
> to find a way to organise multiple page applications that I like.
>
> On Wed, Mar 29, 2017 at 6:24 AM, Peter Damoc <[email protected]> wrote:
>
> If you have a series of pages that each has Cmds and you have these pages
> unified under one app, you need to lift each page Cmd to become an app Cmd.
>
> There used to be a nesting architecture where this was demonstrated but
> now that's been dropped in favor of the Config approach.
>
>
>
> On Wed, Mar 29, 2017 at 1:09 AM, Brian Marick <[email protected]> wrote:
>
> I’m having trouble thinking of a scenario in which you’d use `Cmd.map`.
>
>
>
>
>
> Is it for a case where you create a `Cmd a` where `a` is something
> different than the usual `Msg`, then transform it into a `Msg`? (When would
> you do such a thing?)
>
>
>
>
>
> Or for a case where you want to change the `Msg` constructor that `Cmd`
> “wraps”? (Ditto.)
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
> --
> There is NO FATE, we are the creators.
> blog: http://damoc.ro/
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
> --
> Juan
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
> --
> Juan
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
>
>
>
>
>
> --
>
>
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
>
>
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
>
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to