The main reason to separate is when the smaller pieces have their own
conceptual integrity. That becomes something one can manage independently
and maintain more local invariants about thereby making that piece of the
code easier to reason about. But a dependency has to be managed somewhere
and generally that needs to happen wherever things come together in the
model hierarchy.

For example, let's say we have a list of chats and a current chat. We're
going to receive the list of chats from the server. The current chat is
going to be something we're going to determine locally. The protocol that
we speak with the server might be involved enough that we want to wrap this
in its own module. (For example, the server might be shipping deltas rather
than whole lists.) One of the things that can happen is that a chat could
get deleted, so an update to the chat list could cause us to have to update
the current chat. Here is how that code roughly works out. (I've got some
monadic types that make it easier to write update functions, but I'm
staying away from them in this example.)

type alias Model =
    { chatList : ChatList.Model
    , currentChat : Maybe ChatID
    }

type Msg
    = ToChatList ChatList.Msg
    | ...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ToChatList chatListMsg ->
            updateChatList (ChatList.update chatListMsg) model

updateChatList : (ChatList.Model -> ( ChatList.Model, Cmd ChatList.Msg ) )
-> Model -> ( Model, Cmd Msg )
updateChatList chatListUpdater model =
    let
        ( newChatList, chatListCmd ) =
            chatListUdpater model.chatList
        newModel =
            { model | chatList = newChatList }
        cmd =
            Cmd.map ToChatList chatListCmd
        ( finalModel, finalCmd ) =
            updateChatListDependencies newModel
    in
        ( finalModel, Cmd.batch [ cmd, finalCmd ] )

updateChatListDependencies : Model -> ( Model, Cmd Msg )
updateChatListDependencies model =
    let
        newCurrentChat =
            model.currentChat
                |> Maybe.andThen (constrainToChatList (ChatList.getList
model.chatList))
    in
        ( { model | currentChat = newCurrentChat }, Cmd.none )

constrainToChatList : List Chat -> ChatID -> Maybe ChatID
constrainToChatList chatList chatID =
    if List.any (Chat.id >> (==) chatID) chatList then
        Just chatID
    else
        Nothing

The key logic here with respect to the dependent values is in updateChatList
and its call to updateChatListDependencies. In this implementation, the
model is not responsible for directly maintaining the list of chats but it
is responsible for maintaining the constraints that depend on the list of
chats.

Mark

On Tue, Mar 21, 2017 at 6:35 AM, Eirik Sletteberg <[email protected]
> wrote:

> That was what I was thinking, put all the application state in one model,
> and all updaters will deal with that single model, instead of each Updater
> having its own sub-model. In the end, almost all the data is dependent
> somehow.
>
> tirsdag 21. mars 2017 12.22.15 UTC+1 skrev Fedor Nezhivoi følgende:
>>
>> > for example the User Profile model might need data from the Session
>> model
>>
>> This is probably the biggest issue with how people used to do it in
>> Redux. If you read it closely then you'll see that your data is dependent.
>> By separating it between modules you do not make it in decoupled, you just
>> create more boilerplate and complexity in how it works together. This was
>> one of the reasons Redux discarded `waitFor` mechanism from Flux. If you
>> have dependent data just put it in one reducer, that's it. I guess this
>> pretty much applies here for Elm as well.
>>
> --
> 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