Re: [elm-discuss] Re: Design of Large Elm apps

2016-09-01 Thread Mark Hamburg
One nice thing that comes out of this architecture is that if one could run 
pieces on separate threads, it would split very naturally between the service 
side and the client side. The only ugly part is that in addition to moving data 
over whatever bridge we're using, we also need to move tagger functions and I 
can imagine that being harder to do than pure data.

We're looking at how much code sharing we can do between an iOS app written in 
Swift and a web app written in Elm. One of the potential answers is that the 
service side code could run in a JavaScript context while leaving the UI itself 
in native code.

Mark

> On Sep 1, 2016, at 12:21 PM, Erik Lott  wrote:
> 
> Mark: I spent some time last night looking at a simplified scenario.
> 
> Here's a quick explanation for anyone who cares: An app has an API module 
> which contains all of the task/command related logic needed to communicate 
> with the server. The API module also manages some internal state related to 
> these tasks/commands (e.g. task queue, data cache, etc), so it is a 
> "stateful" module that sends Msg's and has an update function. This state 
> must live near the top level of the application, since it exists for the 
> lifespan of the application. Question: How can other deeply nested modules 
> make use of the API module?
> 
> After I attacked this from a bunch of different angles, I think I agree with 
> you Mark: I don't really see another way to make this work without swapping 
> the existing Cmd in the update cycle for a custom implementation (or cheating 
> by using javascript/native/ports).
> 
> Original update cycle
> update : Msg -> Model -> (Model, Cmd)
> 
> New update cycle
> update : Msg -> Model -> (Model, ClientCommand)
> 
> This adds some additional layers of abstraction at the top of the app where 
> everything is wired together, but aside from that, this isn't so bad. 
> 
> 
>> On Wednesday, August 31, 2016 at 4:32:13 PM UTC-4, Mark Hamburg wrote:
>> I re-read your message, Erik, and my reply and realized that I hadn't 
>> answered all of the questions. The routing I've been working with handles 
>> both commands created by the client side and handled by the service side and 
>> commands created by the client and handled by "normal" external means. This 
>> gets addressed through the type declaration:
>> 
>> type ClientCommand msg
>> = Batch (List (ClientCommand msg))
>> | PlatformCmd (Platform.Cmd msg)
>> | APIFromClient (APICommand msg)
>> 
>> The key point here is in having the platform and API commands split out so 
>> that they can be mapped differently. From the client standpoint, if you can 
>> make a Cmd, then you can call ClientCommand.fromCmd and turn it into a 
>> ClientCommand which can then be batched with API commands. At the point 
>> where the "client" meets the "service" in the model, these get turned back 
>> into Platform.Cmd's (through Task.succeed to set up the delivery of the the 
>> APICommand value to the service).
>> 
>> If I could figure out how to do this with tasks, that might well be simpler 
>> and easier to plug in. I may need to take a pass at that again.
>> 
>> Mark
>> 
>> P.S. I don't really like the words "client" and "service" but they seemed 
>> better at least than "client" and "server" since the latter would suggest 
>> code running on another machine which while this separation enables that 
>> possibility is not something that is happening here. I thought about 
>> "viewModel" and "dataModel" but that seemed to have a certain amount of 
>> verbal noise in saying "model" everywhere.
>> 
>>> On Sun, Aug 28, 2016 at 7:52 PM, Erik Lott  wrote:
>>> Mark, tell me about this code:
>>> 
>>> type APICommand msg
>>> = AddForum (Error -> msg) (ForumID -> msg) String
>>> | DeleteForum (Error -> msg) (() -> msg) ForumID
>>> | PostMessage (Error -> msg) (() -> msg) ForumID String
>>> 
>>> 
>>> type APISubscription msg
>>> = ForumList (List (ForumID, String) -> msg)
>>> | MessageList (Array.Array String -> msg) ForumID
>>> 
>>> 
>>> Conceptually, I appreciate what you're trying to do here (create a simple 
>>> system driven by domain messages - AddForum, DeleteForum, etc) , but the 
>>> actual implementation worries me. I'm wondering why you're not simply 
>>> creating an API module instead:
>>> 
>>> module API exposing(addForum, deleteForum, postMessage)
>>> 
>>> addForum: String -> Task Http.Error Forum
>>> // code here...
>>> 
>>> deleteForum: String -> Task Http.Error Never
>>> // code here
>>> 
>>> etc
>>>  
>>> 
>>> I know that you mentioned that you have some additional complexity (task 
>>> queue, websockets,etc), but I haven't actually seen anything that would 
>>> cause me to abandon the built-in command/subscriptions system. What if you 
>>> need to do something in the page that is not necessarily domain related, 
>>> but requires a task/command - e.g. generate a random number? Are these 
>>> types of 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-31 Thread Mark Hamburg
I re-read your message, Erik, and my reply and realized that I hadn't
answered all of the questions. The routing I've been working with handles
both commands created by the client side and handled by the service side
and commands created by the client and handled by "normal" external means.
This gets addressed through the type declaration:

type ClientCommand msg
= Batch (List (ClientCommand msg))
| PlatformCmd (Platform.Cmd msg)
| APIFromClient (APICommand msg)


The key point here is in having the platform and API commands split out so
that they can be mapped differently. From the client standpoint, if you can
make a Cmd, then you can call ClientCommand.fromCmd and turn it into a
ClientCommand which can then be batched with API commands. At the point
where the "client" meets the "service" in the model, these get turned back
into Platform.Cmd's (through Task.succeed to set up the delivery of the the
APICommand value to the service).

If I could figure out how to do this with tasks, that might well be simpler
and easier to plug in. I may need to take a pass at that again.

Mark

P.S. I don't really like the words "client" and "service" but they seemed
better at least than "client" and "server" since the latter would suggest
code running on another machine which while this separation enables that
possibility is not something that is happening here. I thought about
"viewModel" and "dataModel" but that seemed to have a certain amount of
verbal noise in saying "model" everywhere.

On Sun, Aug 28, 2016 at 7:52 PM, Erik Lott  wrote:

> Mark, tell me about this code:
>
> type APICommand msg
> = AddForum (Error -> msg) (ForumID -> msg) String
> | DeleteForum (Error -> msg) (() -> msg) ForumID
> | PostMessage (Error -> msg) (() -> msg) ForumID String
>
>
> type APISubscription msg
> = ForumList (List (ForumID, String) -> msg)
> | MessageList (Array.Array String -> msg) ForumID
>
>
> Conceptually, I appreciate what you're trying to do here (create a simple
> system driven by domain messages - AddForum, DeleteForum, etc) , but the
> actual implementation worries me. I'm wondering why you're not simply
> creating an API module instead:
>
> module API exposing(addForum, deleteForum, postMessage)
>
> addForum: String -> Task Http.Error Forum
> // code here...
>
> deleteForum: String -> Task Http.Error Never
> // code here
>
> etc
>
>
> I know that you mentioned that you have some additional complexity (task
> queue, websockets,etc), but I haven't actually seen anything that would
> cause me to abandon the built-in command/subscriptions system. What if you
> need to do something in the page that is not necessarily domain related,
> but requires a task/command - e.g. generate a random number? Are these
> types of situations factored into your design?
>
>
>
>
> On Saturday, August 27, 2016 at 6:14:41 PM UTC-4, Mark Hamburg wrote:
>
>> I'm working on some example code. I'm varying between a moderately
>> fleshed out example of the plumbing but with little backing it up and a
>> fully worked but trivial to the point of not being interesting example. The
>> general model, however, works as follows:
>>
>> • We have a service model and a client model. The idea is that after
>> agreeing on an API, these can then undergo independent development.
>> Furthermore, we should be able to do things like mock the service rapidly
>> and then fill it in with a version that talks to the web service or
>> whatever is needed. Similarly, we could mock the client side quickly if we
>> just wanted to test the service APIs.
>>
>> • The API is represented by a union type: APICommand clientMsg. A
>> typical entry would be something like:
>>
>> | PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String
>>
>>
>>
>> • APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type
>> that provides standard Cmd-style functionality (batch, map). It also
>> provides a way to embed non-API commands of type Cmd clientMsg. I would
>> have liked to just use a different type of message within Cmd to do this
>> rather than reconstructing map and batch — trivial though they may be —
>> but mapping for platform commands is built around tagging results as they
>> come back and we need to adjust the tagging functions on API commands
>> before they get to the service.
>>
>> • The update function for the client has the signature:
>>
>> clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg)
>>
>> This gets applied at the "root" level when processing messages destined
>> for the client. On the way back, it can turn the client commands into
>> platform commands of type Cmd (RootMsg serviceMsg clientMsg) where the
>> RootMsg type provides for messages bound for the client, messages bound
>> for the service, and API commands bound for the service.
>>
>> • The service processes both its own messages and API commands (in
>> separate update functions in my latest code). Service updates 

[elm-discuss] Re: Design of Large Elm apps

2016-08-30 Thread Erik Lott
@JoshAdams has been kind enough to share a simple single level SPA example 
on another thread that might be of use to some folks arriving here.

Here's what I've been working on.  The recent git history is all about 
> refactoring.  Haven't introduced 'sub-components with state' or w/e and 
> don't see it coming soon.  It's an Elm-SPA with a Phoenix backend: 
> https://github.com/knewter/time-tracker 
> 




On Thursday, August 4, 2016 at 6:15:53 PM UTC-4, Ryan Erb wrote:
>
> Got a few questions regarding the best way, or what options there are for 
> scaling up to a large site.
> If i have a site with lots of features what is the best way to orgainze 
> everything?
>
> *One Elm page to rule them all?* With this approach you only have to deal 
> with one update happening, you can separate code into different modules, 
> but the update function would be HUGE. Guess this would be the same as a 
> single page application?
>
> *One Elm page per HTML page?* This way every page deals with only what it 
> is used for. You can write common things in reusable modules. One problem 
> might be switching to other elm pages. The only really good way right now 
> that i have is using a port to "window.locaion.href" to another elm page. 
> Then pulling all the data it requires from the server using more ports.
>
> *One Elm page per feature?* This way you can write separate apps for each 
> part of your page. One for the header menu bar, one for a sidebar, and one 
> for each main feature. This way you can mix and match and piece together 
> for a full page. BUT you might have to do a lot of port talking between 
> each section.
>
> *Some other way?*?
>
> Been searching around a cant seem to find any blogs or topics on this 
> subject. Our stack is Elm/Phoenix/Elixir/Postgres.
>
> If anyone has created a large application using Elm would happy to have 
> your input on what worked/ didn't work for you.
>
> Thanks,
>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-29 Thread Charles-Edouard Cady


On Sunday, August 28, 2016 at 10:14:43 AM UTC+2, Richard Feldman wrote:
>
> Components should only update their own private non-shared state that 
>> other components don't need. Shared states such as your server queue are 
>> updated at the highest level and each sub component merely receives a 
>> function to run the update.
>>
>
> Apologies, but I have read and re-read this and I'm still not sure what 
> it's saying. :x
>

Oh dear.. Given this was supposed to be a summary of what I understood from 
your reply to a question I had about extensible records, it's rather 
embarrassing for me! Looks like I'm not on the path to enlightenment after 
all!

Still, I think the idea was worth sharing so I'll clarify.
By "component" I mean any elm module you wish to use in several 
applications.
The elm architecture tutorials covers two extreme cases:
(1) the application has completely independent components (eg. two 
independent counter widgets)
(2) all parts of the application share the same state

If I take the example of a clock widget (time picker) used in several 
places of an application, it has both an external state (the time) and an 
internal state (eg. which part of the widget is hovered) that the rest of 
the application neither knows nor cares about.
All I'm saying is that the clock's update should only make changes to the 
internal state & not change external state which will be updated by passing 
a (Date -> msg) function to the clock's view: it almost seems as if, in 
Elm, you delegate upwards...

In the case of the server requests, I'm simply suggesting to give each 
"update" function an extra (Request -> msg) parameter so that the ordering 
of the request & actual execution is done at a single place in the 
application higher up where more context is available.

I think using all of Msg+update+view+Model in a component is not always 
necessary & maybe the elm architecture tutorial could have an extra example 
or two with, eg. a date picker to illustrate the case where you have 
reusable parts that maintain a private state & use a shared state.
 

>
> That's totally on me, but I'm quickly becoming convinced that Evan's view 
> of the term "components" 
>  
> is dead-on: our speaking in terms of "components" seems to result in way 
> more confusion than positive outcomes. I'm on board with the idea that we 
> should stop using it to describe portions of Elm programs, and instead 
> focus discussions on terms whose definitions are clearly applicable: 
> modules, functions, data, and the first-class Elm Architecture building 
> blocks of Model, Msg, update, and view.
>
> I gather that this is has to do with an interaction between two update 
> functions...is there some way to rephrase it in terms of how those two 
> update functions interact?
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Mark Hamburg
More specifically:

(:>) (model, Batchable op)
-> (model -> (model, Batchable op))
-> (model, Batchable op)
(:>) (oldModel, oldOps) update =
let
(newModel, newOps) = update oldModel
in
(newModel, Batchable.batch [oldOps, newOps])


On Sun, Aug 28, 2016 at 9:55 PM, Mark Hamburg  wrote:

> I have started thinking about whether there would be a useful refactoring
> of Cmd and Sub to support some shared structure that could also work with
> the sort of emulations that I've been building. It's not that the
> emulations are hard — writing batch, map, and none just aren't that much
> code — but rather that I'd like to write a standard operator to do the
> following:
>
> (:>) (model, Batchable ops)
> -> (model -> (model, Batchable ops))
> -> (model, Batchable ops)
>
>
> Where Batchable would cover Cmd and my Cmd emulations. This then allows
> update sequences to look like:
>
> (model, Batchable.none)
> :> firstUpdate
> :> secondUpdate
>
>
> This would make the generalization of the Elm architecture that keeps the
> "command pattern" but doesn't use the "Cmd type" fit in perfectly well
> with the simpler Cmd patterns.
>
> Mark
>
>
> On Sun, Aug 28, 2016 at 9:33 PM, Mark Hamburg 
> wrote:
>
>> Why does Elm work in terms of commands rather than tasks? That's somewhat
>> rhetorical, but in the case of effect managers it allows an effect manager
>> to do things like maintain additional state, batch together operations, etc.
>>
>> In the case of this system, this allows for the API service provider to
>> again do caching and batching, to manage login status, etc.. It also allows
>> for more general translation of the way the UI interacts with the backend
>> service. For example, the cloud service might just communicate via a web
>> socket connection spewing out notifications across all of the forums for
>> which the user was a member. This isn't going to map directly to the
>> activity that the UI is currently interested in displaying.
>>
>> The "problem" with commands and subscriptions is that the mapping really
>> only applies to the tagging that happens on the way back down from the
>> cloud (or wherever) and can't alter the commands and subscriptions on the
>> way up to address any mismatch between the needs of the UI and the
>> facilities provided by the backend service.
>>
>> Mark
>>
>> On Sun, Aug 28, 2016 at 7:52 PM, Erik Lott  wrote:
>>
>>> Mark, tell me about this code:
>>>
>>> type APICommand msg
>>> = AddForum (Error -> msg) (ForumID -> msg) String
>>> | DeleteForum (Error -> msg) (() -> msg) ForumID
>>> | PostMessage (Error -> msg) (() -> msg) ForumID String
>>>
>>>
>>> type APISubscription msg
>>> = ForumList (List (ForumID, String) -> msg)
>>> | MessageList (Array.Array String -> msg) ForumID
>>>
>>>
>>> Conceptually, I appreciate what you're trying to do here (create a
>>> simple system driven by domain messages - AddForum, DeleteForum, etc) , but
>>> the actual implementation worries me. I'm wondering why you're not simply
>>> creating an API module instead:
>>>
>>> module API exposing(addForum, deleteForum, postMessage)
>>>
>>> addForum: String -> Task Http.Error Forum
>>> // code here...
>>>
>>> deleteForum: String -> Task Http.Error Never
>>> // code here
>>>
>>> etc
>>>
>>>
>>> I know that you mentioned that you have some additional complexity (task
>>> queue, websockets,etc), but I haven't actually seen anything that would
>>> cause me to abandon the built-in command/subscriptions system. What if you
>>> need to do something in the page that is not necessarily domain related,
>>> but requires a task/command - e.g. generate a random number? Are these
>>> types of situations factored into your design?
>>>
>>>
>>>
>>>
>>> On Saturday, August 27, 2016 at 6:14:41 PM UTC-4, Mark Hamburg wrote:
>>>
 I'm working on some example code. I'm varying between a moderately
 fleshed out example of the plumbing but with little backing it up and a
 fully worked but trivial to the point of not being interesting example. The
 general model, however, works as follows:

 • We have a service model and a client model. The idea is that after
 agreeing on an API, these can then undergo independent development.
 Furthermore, we should be able to do things like mock the service rapidly
 and then fill it in with a version that talks to the web service or
 whatever is needed. Similarly, we could mock the client side quickly if we
 just wanted to test the service APIs.

 • The API is represented by a union type: APICommand clientMsg. A
 typical entry would be something like:

 | PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String



 • APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type
 that provides standard Cmd-style functionality (batch, map). It also
 provides a way to embed non-API 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Mark Hamburg
Why does Elm work in terms of commands rather than tasks? That's somewhat
rhetorical, but in the case of effect managers it allows an effect manager
to do things like maintain additional state, batch together operations, etc.

In the case of this system, this allows for the API service provider to
again do caching and batching, to manage login status, etc.. It also allows
for more general translation of the way the UI interacts with the backend
service. For example, the cloud service might just communicate via a web
socket connection spewing out notifications across all of the forums for
which the user was a member. This isn't going to map directly to the
activity that the UI is currently interested in displaying.

The "problem" with commands and subscriptions is that the mapping really
only applies to the tagging that happens on the way back down from the
cloud (or wherever) and can't alter the commands and subscriptions on the
way up to address any mismatch between the needs of the UI and the
facilities provided by the backend service.

Mark

On Sun, Aug 28, 2016 at 7:52 PM, Erik Lott  wrote:

> Mark, tell me about this code:
>
> type APICommand msg
> = AddForum (Error -> msg) (ForumID -> msg) String
> | DeleteForum (Error -> msg) (() -> msg) ForumID
> | PostMessage (Error -> msg) (() -> msg) ForumID String
>
>
> type APISubscription msg
> = ForumList (List (ForumID, String) -> msg)
> | MessageList (Array.Array String -> msg) ForumID
>
>
> Conceptually, I appreciate what you're trying to do here (create a simple
> system driven by domain messages - AddForum, DeleteForum, etc) , but the
> actual implementation worries me. I'm wondering why you're not simply
> creating an API module instead:
>
> module API exposing(addForum, deleteForum, postMessage)
>
> addForum: String -> Task Http.Error Forum
> // code here...
>
> deleteForum: String -> Task Http.Error Never
> // code here
>
> etc
>
>
> I know that you mentioned that you have some additional complexity (task
> queue, websockets,etc), but I haven't actually seen anything that would
> cause me to abandon the built-in command/subscriptions system. What if you
> need to do something in the page that is not necessarily domain related,
> but requires a task/command - e.g. generate a random number? Are these
> types of situations factored into your design?
>
>
>
>
> On Saturday, August 27, 2016 at 6:14:41 PM UTC-4, Mark Hamburg wrote:
>
>> I'm working on some example code. I'm varying between a moderately
>> fleshed out example of the plumbing but with little backing it up and a
>> fully worked but trivial to the point of not being interesting example. The
>> general model, however, works as follows:
>>
>> • We have a service model and a client model. The idea is that after
>> agreeing on an API, these can then undergo independent development.
>> Furthermore, we should be able to do things like mock the service rapidly
>> and then fill it in with a version that talks to the web service or
>> whatever is needed. Similarly, we could mock the client side quickly if we
>> just wanted to test the service APIs.
>>
>> • The API is represented by a union type: APICommand clientMsg. A
>> typical entry would be something like:
>>
>> | PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String
>>
>>
>>
>> • APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type
>> that provides standard Cmd-style functionality (batch, map). It also
>> provides a way to embed non-API commands of type Cmd clientMsg. I would
>> have liked to just use a different type of message within Cmd to do this
>> rather than reconstructing map and batch — trivial though they may be —
>> but mapping for platform commands is built around tagging results as they
>> come back and we need to adjust the tagging functions on API commands
>> before they get to the service.
>>
>> • The update function for the client has the signature:
>>
>> clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg)
>>
>> This gets applied at the "root" level when processing messages destined
>> for the client. On the way back, it can turn the client commands into
>> platform commands of type Cmd (RootMsg serviceMsg clientMsg) where the
>> RootMsg type provides for messages bound for the client, messages bound
>> for the service, and API commands bound for the service.
>>
>> • The service processes both its own messages and API commands (in
>> separate update functions in my latest code). Service updates return 
>> (serviceModel,
>> ServiceCommand serviceMsg clientMsg) where ServiceCommand again mirrors
>> Cmd in terms of providing batch and map support. (This could actually be
>> represented as a Cmd (Either serviceMsg clientMsg) but I'm not sure that
>> leveraging Cmd in that case provides more clarity.)
>>
>> • The root update function again maps the service commands appropriately
>> to generate commands of type Cmd (RootMsg serviceMsg clientMsg) 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Erik Lott
Mark, tell me about this code:

type APICommand msg
= AddForum (Error -> msg) (ForumID -> msg) String
| DeleteForum (Error -> msg) (() -> msg) ForumID
| PostMessage (Error -> msg) (() -> msg) ForumID String


type APISubscription msg
= ForumList (List (ForumID, String) -> msg)
| MessageList (Array.Array String -> msg) ForumID


Conceptually, I appreciate what you're trying to do here (create a simple 
system driven by domain messages - AddForum, DeleteForum, etc) , but the 
actual implementation worries me. I'm wondering why you're not simply 
creating an API module instead:

module API exposing(addForum, deleteForum, postMessage)

addForum: String -> Task Http.Error Forum
// code here...

deleteForum: String -> Task Http.Error Never
// code here

etc
 

I know that you mentioned that you have some additional complexity (task 
queue, websockets,etc), but I haven't actually seen anything that would 
cause me to abandon the built-in command/subscriptions system. What if you 
need to do something in the page that is not necessarily domain related, 
but requires a task/command - e.g. generate a random number? Are these 
types of situations factored into your design?




On Saturday, August 27, 2016 at 6:14:41 PM UTC-4, Mark Hamburg wrote:
>
> I'm working on some example code. I'm varying between a moderately fleshed 
> out example of the plumbing but with little backing it up and a fully 
> worked but trivial to the point of not being interesting example. The 
> general model, however, works as follows:
>
> • We have a service model and a client model. The idea is that after 
> agreeing on an API, these can then undergo independent development. 
> Furthermore, we should be able to do things like mock the service rapidly 
> and then fill it in with a version that talks to the web service or 
> whatever is needed. Similarly, we could mock the client side quickly if we 
> just wanted to test the service APIs.
>
> • The API is represented by a union type: APICommand clientMsg. A typical 
> entry would be something like:
>
> | PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String
>
>
>
> • APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type 
> that provides standard Cmd-style functionality (batch, map). It also 
> provides a way to embed non-API commands of type Cmd clientMsg. I would 
> have liked to just use a different type of message within Cmd to do this 
> rather than reconstructing map and batch — trivial though they may be — 
> but mapping for platform commands is built around tagging results as they 
> come back and we need to adjust the tagging functions on API commands 
> before they get to the service.
>
> • The update function for the client has the signature:
>
> clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg) 
>
> This gets applied at the "root" level when processing messages destined 
> for the client. On the way back, it can turn the client commands into 
> platform commands of type Cmd (RootMsg serviceMsg clientMsg) where the 
> RootMsg type provides for messages bound for the client, messages bound 
> for the service, and API commands bound for the service.
>
> • The service processes both its own messages and API commands (in 
> separate update functions in my latest code). Service updates return 
> (serviceModel, 
> ServiceCommand serviceMsg clientMsg) where ServiceCommand again mirrors 
> Cmd in terms of providing batch and map support. (This could actually be 
> represented as a Cmd (Either serviceMsg clientMsg) but I'm not sure that 
> leveraging Cmd in that case provides more clarity.)
>
> • The root update function again maps the service commands appropriately 
> to generate commands of type Cmd (RootMsg serviceMsg clientMsg) which 
> route to the service and client as appropriate.
>
> The amount of code is actually pretty small and as discussed above, it 
> provides a very nice separation of concerns between the client side and the 
> server side and allows each to be coded following standard Elm architecture 
> patterns with the caveat that one doesn't actually use Cmd during 
> propagation.
>
> So, with that, I would be happy were it not for the fact that it's dawned 
> on me that subscriptions are going to be more difficult because I can't 
> simply wait for the runtime to ask the root model for subscriptions and 
> then plumb it appropriately. This is because the service model will almost 
> certainly need to adjust its state based on the client subscription 
> requests — see some effects managers for examples — and when asked for 
> subscriptions we can't update the root model. So, I will need to perform an 
> internal subscription update after every client model update. This isn't 
> fatal but I could imagine it being inefficient. I could also send a strobe 
> to do this but that might introduce more delay than I'd like. That said, 
> I've wondered whether subscriptions need lazy support akin to what we have 
> 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Richard Feldman
Here's a primer on Elm modules:
https://dennisreimann.de/articles/elm-modules-import.html

Indeed, "component" and "child" are not first-class constructs in Elm, and
so can mean different things to different people. Sorry for the confusion!

I'm going to make a point to start discussing things using terms that have
first-class language support, and see how that goes. :)

On Sun, Aug 28, 2016, 11:58 AM Nick H  wrote:

> Well, "module" is a keyword in Elm, so I really hope everybody who knows
> Elm knows exactly what this is!
>
> On Sun, Aug 28, 2016 at 11:23 AM, Rex van der Spuy 
> wrote:
>
>>
>>
>> On Sunday, August 28, 2016 at 4:14:43 AM UTC-4, Richard Feldman wrote:
>>>
>>>
 I gather that this is has to do with an interaction between two update
>>> functions...is there some way to rephrase it in terms of how those two
>>> update functions interact?
>>>
>>
>> Richard, this has been a huge area of confusion for me in the
>> child-parent discussions that I've been following over the past few months!
>> What's a "module", what's a "child", what's a "component"? Everyone seems
>> to have different mental models for what these things are include me :)
>> ... resulting in some muddy and inconclusive discussions.
>>
>> ... just a observation from someone in the Peanut Gallery.
>> Carry on! This is a fun thread :)
>>
> --
>>
> 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 elm-discuss+unsubscr...@googlegroups.com.
>>
>
>> For more options, visit https://groups.google.com/d/optout.
>>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Elm Discuss" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/elm-discuss/_cfOu88oCx4/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Nick H
Well, "module" is a keyword in Elm, so I really hope everybody who knows
Elm knows exactly what this is!

On Sun, Aug 28, 2016 at 11:23 AM, Rex van der Spuy 
wrote:

>
>
> On Sunday, August 28, 2016 at 4:14:43 AM UTC-4, Richard Feldman wrote:
>>
>>
>>> I gather that this is has to do with an interaction between two update
>> functions...is there some way to rephrase it in terms of how those two
>> update functions interact?
>>
>
> Richard, this has been a huge area of confusion for me in the child-parent
> discussions that I've been following over the past few months! What's a
> "module", what's a "child", what's a "component"? Everyone seems to have
> different mental models for what these things are include me :) ...
> resulting in some muddy and inconclusive discussions.
>
> ... just a observation from someone in the Peanut Gallery.
> Carry on! This is a fun thread :)
>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-28 Thread Richard Feldman

>
> Components should only update their own private non-shared state that 
> other components don't need. Shared states such as your server queue are 
> updated at the highest level and each sub component merely receives a 
> function to run the update.
>

Apologies, but I have read and re-read this and I'm still not sure what 
it's saying. :x

That's totally on me, but I'm quickly becoming convinced that Evan's view 
of the term "components" 
 
is dead-on: our speaking in terms of "components" seems to result in way 
more confusion than positive outcomes. I'm on board with the idea that we 
should stop using it to describe portions of Elm programs, and instead 
focus discussions on terms whose definitions are clearly applicable: 
modules, functions, data, and the first-class Elm Architecture building 
blocks of Model, Msg, update, and view.

I gather that this is has to do with an interaction between two update 
functions...is there some way to rephrase it in terms of how those two 
update functions interact?

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-27 Thread Mark Hamburg
Not using Cmd does make (!) far less useful.

Mark

On Sat, Aug 27, 2016 at 3:14 PM, Mark Hamburg  wrote:

> I'm working on some example code. I'm varying between a moderately fleshed
> out example of the plumbing but with little backing it up and a fully
> worked but trivial to the point of not being interesting example. The
> general model, however, works as follows:
>
> • We have a service model and a client model. The idea is that after
> agreeing on an API, these can then undergo independent development.
> Furthermore, we should be able to do things like mock the service rapidly
> and then fill it in with a version that talks to the web service or
> whatever is needed. Similarly, we could mock the client side quickly if we
> just wanted to test the service APIs.
>
> • The API is represented by a union type: APICommand clientMsg. A typical
> entry would be something like:
>
> | PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String
>
>
>
> • APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type
> that provides standard Cmd-style functionality (batch, map). It also
> provides a way to embed non-API commands of type Cmd clientMsg. I would
> have liked to just use a different type of message within Cmd to do this
> rather than reconstructing map and batch — trivial though they may be —
> but mapping for platform commands is built around tagging results as they
> come back and we need to adjust the tagging functions on API commands
> before they get to the service.
>
> • The update function for the client has the signature:
>
> clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg)
>
> This gets applied at the "root" level when processing messages destined
> for the client. On the way back, it can turn the client commands into
> platform commands of type Cmd (RootMsg serviceMsg clientMsg) where the
> RootMsg type provides for messages bound for the client, messages bound
> for the service, and API commands bound for the service.
>
> • The service processes both its own messages and API commands (in
> separate update functions in my latest code). Service updates return 
> (serviceModel,
> ServiceCommand serviceMsg clientMsg) where ServiceCommand again mirrors
> Cmd in terms of providing batch and map support. (This could actually be
> represented as a Cmd (Either serviceMsg clientMsg) but I'm not sure that
> leveraging Cmd in that case provides more clarity.)
>
> • The root update function again maps the service commands appropriately
> to generate commands of type Cmd (RootMsg serviceMsg clientMsg) which
> route to the service and client as appropriate.
>
> The amount of code is actually pretty small and as discussed above, it
> provides a very nice separation of concerns between the client side and the
> server side and allows each to be coded following standard Elm architecture
> patterns with the caveat that one doesn't actually use Cmd during
> propagation.
>
> So, with that, I would be happy were it not for the fact that it's dawned
> on me that subscriptions are going to be more difficult because I can't
> simply wait for the runtime to ask the root model for subscriptions and
> then plumb it appropriately. This is because the service model will almost
> certainly need to adjust its state based on the client subscription
> requests — see some effects managers for examples — and when asked for
> subscriptions we can't update the root model. So, I will need to perform an
> internal subscription update after every client model update. This isn't
> fatal but I could imagine it being inefficient. I could also send a strobe
> to do this but that might introduce more delay than I'd like. That said,
> I've wondered whether subscriptions need lazy support akin to what we have
> for views.
>
> Mark
>
> P.S. The heart of this work was in making it possible to write an API like
> the following:
>
> type Error
> = NoPermission
> | NoConnection
> | ServiceFailure
>
>
> type ForumID = ForumID String
>
>
> type APICommand msg
> = AddForum (Error -> msg) (ForumID -> msg) String
> | DeleteForum (Error -> msg) (() -> msg) ForumID
> | PostMessage (Error -> msg) (() -> msg) ForumID String
>
>
> type APISubscription msg
> = ForumList (List (ForumID, String) -> msg)
> | MessageList (Array.Array String -> msg) ForumID
>
> Everything else was just the work to allow the client side and the service
> side to hew as closely as possible to the Elm architecture while getting
> the appropriate interaction between the two.
>
>
>
> On Fri, Aug 26, 2016 at 11:55 PM, Charles-Edouard Cady <
> charlesedouardc...@gmail.com> wrote:
>
>> Would it be possible in your architecture to  perform server requests at
>> the highest level of your application? You would then send a a->Msg to each
>> sub component. That way server requests would only be performed in one
>> place where you could fine-tune how you want them performed.
>> This comes from 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-27 Thread Mark Hamburg
I'm working on some example code. I'm varying between a moderately fleshed
out example of the plumbing but with little backing it up and a fully
worked but trivial to the point of not being interesting example. The
general model, however, works as follows:

• We have a service model and a client model. The idea is that after
agreeing on an API, these can then undergo independent development.
Furthermore, we should be able to do things like mock the service rapidly
and then fill it in with a version that talks to the web service or
whatever is needed. Similarly, we could mock the client side quickly if we
just wanted to test the service APIs.

• The API is represented by a union type: APICommand clientMsg. A typical
entry would be something like:

| PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String



• APICommand clientMsg is wrapped up inside a ClientCommand clientMsg type
that provides standard Cmd-style functionality (batch, map). It also
provides a way to embed non-API commands of type Cmd clientMsg. I would
have liked to just use a different type of message within Cmd to do this
rather than reconstructing map and batch — trivial though they may be — but
mapping for platform commands is built around tagging results as they come
back and we need to adjust the tagging functions on API commands before
they get to the service.

• The update function for the client has the signature:

clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg)

This gets applied at the "root" level when processing messages destined for
the client. On the way back, it can turn the client commands into platform
commands of type Cmd (RootMsg serviceMsg clientMsg) where the RootMsg type
provides for messages bound for the client, messages bound for the service,
and API commands bound for the service.

• The service processes both its own messages and API commands (in separate
update functions in my latest code). Service updates return (serviceModel,
ServiceCommand serviceMsg clientMsg) where ServiceCommand again mirrors Cmd
in terms of providing batch and map support. (This could actually be
represented as a Cmd (Either serviceMsg clientMsg) but I'm not sure that
leveraging Cmd in that case provides more clarity.)

• The root update function again maps the service commands appropriately to
generate commands of type Cmd (RootMsg serviceMsg clientMsg) which route to
the service and client as appropriate.

The amount of code is actually pretty small and as discussed above, it
provides a very nice separation of concerns between the client side and the
server side and allows each to be coded following standard Elm architecture
patterns with the caveat that one doesn't actually use Cmd during
propagation.

So, with that, I would be happy were it not for the fact that it's dawned
on me that subscriptions are going to be more difficult because I can't
simply wait for the runtime to ask the root model for subscriptions and
then plumb it appropriately. This is because the service model will almost
certainly need to adjust its state based on the client subscription
requests — see some effects managers for examples — and when asked for
subscriptions we can't update the root model. So, I will need to perform an
internal subscription update after every client model update. This isn't
fatal but I could imagine it being inefficient. I could also send a strobe
to do this but that might introduce more delay than I'd like. That said,
I've wondered whether subscriptions need lazy support akin to what we have
for views.

Mark

P.S. The heart of this work was in making it possible to write an API like
the following:

type Error
= NoPermission
| NoConnection
| ServiceFailure


type ForumID = ForumID String


type APICommand msg
= AddForum (Error -> msg) (ForumID -> msg) String
| DeleteForum (Error -> msg) (() -> msg) ForumID
| PostMessage (Error -> msg) (() -> msg) ForumID String


type APISubscription msg
= ForumList (List (ForumID, String) -> msg)
| MessageList (Array.Array String -> msg) ForumID

Everything else was just the work to allow the client side and the service
side to hew as closely as possible to the Elm architecture while getting
the appropriate interaction between the two.



On Fri, Aug 26, 2016 at 11:55 PM, Charles-Edouard Cady <
charlesedouardc...@gmail.com> wrote:

> Would it be possible in your architecture to  perform server requests at
> the highest level of your application? You would then send a a->Msg to each
> sub component. That way server requests would only be performed in one
> place where you could fine-tune how you want them performed.
> This comes from Richard's answer to a question I had on composability.
> Components should only update their own private non-shared state that other
> components don't need. Shared states such as your server queue are updated
> at the highest level and each sub component merely receives a function to
> run the update.
> Does that 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-26 Thread Richard Feldman

>
> I know you just like to let stuff accumulate in one monolithic piece, but 
> if you wanted to subdivide some of the major sections into sub-modules


Just to be clear, at work we split things up into *modules* at the drop of 
a hat. If a particular file is too long, pulling some of it out into a 
different module is typically trivial and uncontroversial.

You're talking about entire model/view/update triplets that have different 
Msg types and are responsible for their own isolated state, though, which 
is a totally different thing. :)

if you wanted to subdivide some of the major sections into sub-modules, 
> would you have them stop using Platform.Cmd to communicate upward
>

Oh I definitely would only use Cmd to communicate directly to the Elm 
Runtime for things like effects and JS interop. I don't think it's the 
right tool for organizing internal Elm code in an application. I would use 
Msg for that, and things like Html.App.map and Cmd.map to facilitate that 
if necessary. :)

AppCommand seems like overkill. We need to prioritize our HTTP requests. Do 
we really need a drop-in replacement an entire foundational core library to 
do that? Why not just say "we have a business need to do HTTP requests in a 
certain way, so everybody on the team, use this way instead of making 
vanilla elm-http calls" instead?

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-26 Thread Mark Hamburg
Oops. Typo. That should be

| Queued Int (Cmd msg)



On Fri, Aug 26, 2016 at 3:03 PM, Mark Hamburg  wrote:

> Thanks, Richard. That all works if everything is essentially sitting
> together at the top level and talk to the model. As I said, writing the
> queue isn't really the hard part. I know you just like to let stuff
> accumulate in one monolithic piece, but if you wanted to subdivide some of
> the major sections into sub-modules, would you have them stop using
> Platform.Cmd to communicate upward and instead say use something like:
>
> type AppCommand msg
> = Immediate (Cmd msg)
> | Queued Int (Cmd Msg)
> | Batch (List (AppCommand msg))
>
>
> with appropriate implementations for AppCommand.batch, AppCommand.map, and
> AppCommand.none?
>
> The general guidelines for code development would then perhaps be:
>
> • Structure in terms of models, messages, init, update, subscriptions, and
> view (leaving some pieces out where they aren't appropriate).
> • Be prepared to replace the standard platform types for Cmd and Sub if
> you need to bridge between what your application logic needs and what your
> server (or other backend) provides but when doing so follow the same API
> patterns so that the shift is easy to make.
> • More generally document what you need and what you deliver via types and
> use transformations to go from one type to another. The tagging pattern in
> the standard Elm examples is just a particularly simple form of
> transformation.
> • Don't subdivide too much.
>
> If these are the guidelines, then it might be good if Elm did not auto
> import pieces of Platform like Platform.Cmd and if Task.perform were
> replaced with Platform.Cmd.fromTask.  That way the guide could talk in
> terms of building applications based on "commands" and "subscriptions" but
> could also say that Platform.Cmd and Platform.Sub were just examples of
> such types that were used at the boundary layer between the application,
> the runtime system, and the effect managers and were also for most simple
> and many not so simple programs but were in no way sacrosanct beyond their
> role at the boundary.
>
> Mark
>
> On Fri, Aug 26, 2016 at 2:18 PM, Richard Feldman <
> richard.t.feld...@gmail.com> wrote:
>
>> I'm trying to rebuild the successor to some past systems in Elm and one
>>> thing we learned on those systems was that to get good performance it was
>>> critical that we prioritize HTTP fetches so that we didn't ask for the low
>>> priority items at the same time as the high priority items. From a
>>> correctness standpoint, the particular fetches are a local problem and the
>>> Elm architecture provides a reasonable way to route those. But the
>>> prioritization is a global problem. To go with that, I need cancelation
>>> support because that's the other key piece in getting responsiveness and
>>> what that means in practice is that if something hasn't left the queue yet,
>>> I need a way to cancel it.
>>>
>>
>> Okay, now we're getting somewhere!
>>
>> So you have a specific problem where you need a global queue for
>> dispatching HTTP requests according to your applications' particular
>> business logic.
>>
>> Here's how I would approach this if I had these same design constraints.
>> I would add something like this to my model:
>>
>> requestQueue : Dict RequestId { order : Int, request : Task Never Msg }
>>
>> Then I'd introduce a function to enqueue messages with a particular
>> priority level that determines the order value.
>>
>> I'd also introduce a Msg called Dispatch that pulls the next thing off
>> the queue (sorting Dict.values by the order field) and uses Task.perform
>> to run the HTTP request.
>>
>> To allow canceling, I'd add this to my top-level Msg:
>>
>> | CancelRequest RequestId
>>
>> This is what I would do if I had your particular business need. Seems
>> pretty reasonable!
>>
>> I also think it would be no problem to introduce this to an existing Elm
>> application after the fact. Just start by deleting your dependency on
>> elm-http, and the compiler will immediately tell you every single place you
>> were doing HTTP "the old way." Go through and transition those direct HTTP
>> calls to use a stubbed-out implementation of "the new way," and then
>> finally reintroduce the elm-http dependency to make the queue work for real!
>>
>> I'll also note that this use case seems very specific to your
>> application. I would avoid trying to overgeneralize this into any kind of
>> pattern that others should follow. :)
>>
>> --
>> 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 elm-discuss+unsubscr...@googlegroups.com.
>> 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 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-26 Thread Mark Hamburg
Thanks, Richard. That all works if everything is essentially sitting
together at the top level and talk to the model. As I said, writing the
queue isn't really the hard part. I know you just like to let stuff
accumulate in one monolithic piece, but if you wanted to subdivide some of
the major sections into sub-modules, would you have them stop using
Platform.Cmd to communicate upward and instead say use something like:

type AppCommand msg
= Immediate (Cmd msg)
| Queued Int (Cmd Msg)
| Batch (List (AppCommand msg))


with appropriate implementations for AppCommand.batch, AppCommand.map, and
AppCommand.none?

The general guidelines for code development would then perhaps be:

• Structure in terms of models, messages, init, update, subscriptions, and
view (leaving some pieces out where they aren't appropriate).
• Be prepared to replace the standard platform types for Cmd and Sub if you
need to bridge between what your application logic needs and what your
server (or other backend) provides but when doing so follow the same API
patterns so that the shift is easy to make.
• More generally document what you need and what you deliver via types and
use transformations to go from one type to another. The tagging pattern in
the standard Elm examples is just a particularly simple form of
transformation.
• Don't subdivide too much.

If these are the guidelines, then it might be good if Elm did not auto
import pieces of Platform like Platform.Cmd and if Task.perform were
replaced with Platform.Cmd.fromTask.  That way the guide could talk in
terms of building applications based on "commands" and "subscriptions" but
could also say that Platform.Cmd and Platform.Sub were just examples of
such types that were used at the boundary layer between the application,
the runtime system, and the effect managers and were also for most simple
and many not so simple programs but were in no way sacrosanct beyond their
role at the boundary.

Mark

On Fri, Aug 26, 2016 at 2:18 PM, Richard Feldman <
richard.t.feld...@gmail.com> wrote:

> I'm trying to rebuild the successor to some past systems in Elm and one
>> thing we learned on those systems was that to get good performance it was
>> critical that we prioritize HTTP fetches so that we didn't ask for the low
>> priority items at the same time as the high priority items. From a
>> correctness standpoint, the particular fetches are a local problem and the
>> Elm architecture provides a reasonable way to route those. But the
>> prioritization is a global problem. To go with that, I need cancelation
>> support because that's the other key piece in getting responsiveness and
>> what that means in practice is that if something hasn't left the queue yet,
>> I need a way to cancel it.
>>
>
> Okay, now we're getting somewhere!
>
> So you have a specific problem where you need a global queue for
> dispatching HTTP requests according to your applications' particular
> business logic.
>
> Here's how I would approach this if I had these same design constraints. I
> would add something like this to my model:
>
> requestQueue : Dict RequestId { order : Int, request : Task Never Msg }
>
> Then I'd introduce a function to enqueue messages with a particular
> priority level that determines the order value.
>
> I'd also introduce a Msg called Dispatch that pulls the next thing off
> the queue (sorting Dict.values by the order field) and uses Task.perform
> to run the HTTP request.
>
> To allow canceling, I'd add this to my top-level Msg:
>
> | CancelRequest RequestId
>
> This is what I would do if I had your particular business need. Seems
> pretty reasonable!
>
> I also think it would be no problem to introduce this to an existing Elm
> application after the fact. Just start by deleting your dependency on
> elm-http, and the compiler will immediately tell you every single place you
> were doing HTTP "the old way." Go through and transition those direct HTTP
> calls to use a stubbed-out implementation of "the new way," and then
> finally reintroduce the elm-http dependency to make the queue work for real!
>
> I'll also note that this use case seems very specific to your application.
> I would avoid trying to overgeneralize this into any kind of pattern that
> others should follow. :)
>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-26 Thread Josh Adams

>
>  Before committing to a new framework like Elm, one would first like to 
> know that it can be scaled, how it can be, what will be necessary to 
> refactor code to make it scalable and what pitfalls one could have avoided 
> in the first place that may become big problems later. I feel more 
> comfortable about the start simple approach once I've got that figured out.
>

So...it's super nice and scalable.  Use us as arguments from authority (not 
that I'm a huge authority on this or anything, but I've built enough large 
systems (billions of dollars in transactions per year, etc) in other 
languages and done enough elm that I'm entirely convinced.  The problem 
stems from people *really* wanting to invent a problem before they've hit 
it.  I did it too early on in Elm.  And I was mad when I got responses like 
this.

Then I breathed a bit and though "huh these people have been doing it for a 
while, why don't I just take their advice and see how it goes".  And it was 
glorious.

-Josh

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-26 Thread 'Rupert Smith' via Elm Discuss
On Friday, August 26, 2016 at 12:53:01 AM UTC+1, Mark Hamburg wrote:
>
> On Aug 25, 2016, at 2:51 PM, Richard Feldman  > wrote:
>
> Richard's definition of large application (36,000 lines) and my definition 
>> (Photoshop, Lightroom, ...) are rather different in scale
>>
>
> OP said "If i have a site with lots of features what is the best way to 
> orgainze everything?" and our code base precisely fits the bill for what he 
> asked for advice about. :)
>
>
> Point taken.
>
> However, I fear that your argument to worry about scaling later dances 
> around the fact that some scaling issues arrive the moment you would like 
> to have two people work on something.
>

And it should also be added that sometimes the need to scale comes after 
you have already hacked out a non-scalable code base and is accompanied by 
pressure from a business that needs scalability yesterday. Before 
committing to a new framework like Elm, one would first like to know that 
it can be scaled, how it can be, what will be necessary to refactor code to 
make it scalable and what pitfalls one could have avoided in the first 
place that may become big problems later. I feel more comfortable about the 
start simple approach once I've got that figured out.

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-25 Thread Mark Hamburg
And when we go to four programmers, we use mob programming... :-P

On Thu, Aug 25, 2016 at 5:22 PM, Nick H  wrote:

> some scaling issues arrive the moment you would like to have two people
>> work on something
>
>
> Well, those two people are going to be pair programming, right? ;-P  am winking so hard right now>
>
> On Thu, Aug 25, 2016 at 4:52 PM, Mark Hamburg 
> wrote:
>
>> On Aug 25, 2016, at 2:51 PM, Richard Feldman 
>> wrote:
>>
>> Richard's definition of large application (36,000 lines) and my
>>> definition (Photoshop, Lightroom, ...) are rather different in scale
>>>
>>
>> OP said "If i have a site with lots of features what is the best way to
>> orgainze everything?" and our code base precisely fits the bill for what he
>> asked for advice about. :)
>>
>>
>> Point taken.
>>
>> However, I fear that your argument to worry about scaling later dances
>> around the fact that some scaling issues arrive the moment you would like
>> to have two people work on something. At that point, they can generally
>> both be more productive if you can subdivide the work, put an API in place
>> in between, and then let each proceed in a separate file. This avoids lots
>> of opportunities for toes to get stepped on either in actual coding or in a
>> source code merge.
>>
>> Breaking things out into new utility types and functions is pretty clear,
>> but what are the useful patterns to take an app and subdivide it so that
>> two people can work on it at once? What are the API design principles one
>> should apply?
>>
>> Mark
>>
>> --
>> 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 elm-discuss+unsubscr...@googlegroups.com.
>> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-25 Thread Nick H
>
> some scaling issues arrive the moment you would like to have two people
> work on something


Well, those two people are going to be pair programming, right? ;-P 

On Thu, Aug 25, 2016 at 4:52 PM, Mark Hamburg  wrote:

> On Aug 25, 2016, at 2:51 PM, Richard Feldman 
> wrote:
>
> Richard's definition of large application (36,000 lines) and my definition
>> (Photoshop, Lightroom, ...) are rather different in scale
>>
>
> OP said "If i have a site with lots of features what is the best way to
> orgainze everything?" and our code base precisely fits the bill for what he
> asked for advice about. :)
>
>
> Point taken.
>
> However, I fear that your argument to worry about scaling later dances
> around the fact that some scaling issues arrive the moment you would like
> to have two people work on something. At that point, they can generally
> both be more productive if you can subdivide the work, put an API in place
> in between, and then let each proceed in a separate file. This avoids lots
> of opportunities for toes to get stepped on either in actual coding or in a
> source code merge.
>
> Breaking things out into new utility types and functions is pretty clear,
> but what are the useful patterns to take an app and subdivide it so that
> two people can work on it at once? What are the API design principles one
> should apply?
>
> Mark
>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-25 Thread Richard Feldman

>
> some scaling issues arrive the moment you would like to have two people 
> work on something. At that point, they can generally both be more 
> productive if you can subdivide the work, put an API in place in between, 
> and then let each proceed in a separate file.
>

I understand this concept, and my recommendation takes it into account.

Having multiple people working on the same part of the code base comes up 
for us all the time!

It's totally fine. Nobody wants to reorganize our code base afterwards. :)

I get that you are worried about this in theory, but what I'm saying is 
that in practice we frequently do the thing you're saying is should be 
painful, and we've found that it actually just isn't.

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-25 Thread Mark Hamburg
On Aug 25, 2016, at 2:51 PM, Richard Feldman  
wrote:

>> Richard's definition of large application (36,000 lines) and my definition 
>> (Photoshop, Lightroom, ...) are rather different in scale
> 
> OP said "If i have a site with lots of features what is the best way to 
> orgainze everything?" and our code base precisely fits the bill for what he 
> asked for advice about. :)

Point taken.

However, I fear that your argument to worry about scaling later dances around 
the fact that some scaling issues arrive the moment you would like to have two 
people work on something. At that point, they can generally both be more 
productive if you can subdivide the work, put an API in place in between, and 
then let each proceed in a separate file. This avoids lots of opportunities for 
toes to get stepped on either in actual coding or in a source code merge.

Breaking things out into new utility types and functions is pretty clear, but 
what are the useful patterns to take an app and subdivide it so that two people 
can work on it at once? What are the API design principles one should apply?

Mark

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-25 Thread Mark Hamburg
Richard's definition of large application (36,000 lines) and my definition 
(Photoshop, Lightroom, ...) are rather different in scale, so maybe that's 
part of the difference in perspective and my sense that one needs to find 
good ways to carve things apart.

With that in mind, let me put an example out. Imagine working on something 
akin to Slack (or any number of other chat systems). For the view, we need 
an updating list of channels and for any channel, we need an updating list 
of messages. We need ways to create channels and post messages. This first 
really well with the 0.17 architecture. The lists of channels and messages 
are subscriptions. Channel creation and message posting are commands.

Now, if these were working with a RESTful interface, we might generate the 
commands by generating HTTP tasks and converting those to commands and we 
would handle the subscriptions again by generating HTTP tasks coupled with 
timer tasks for when to re-query.

But in the interests of performance and to avoid polling, the service is 
built using web sockets and speaks a particular message protocol to do so. 
Now, we really want to use the web sockets effects manager. But the 
commands and subscriptions it provides — particularly the subscriptions — 
don't really fit with the needs of the view. We want to maintain some form 
of local data model that interacts with the server via web sockets. That 
would be pretty easy but that data model then doesn't fit as neatly with 
the commands and subscriptions needed by the view. At least not when we 
essentially have to query it for "subscribed" values after every update — 
e.g., after every update to the data model, we need to fetch the list of 
forums and see whether it changed or the update function for the data model 
has to provide this information in a form that allows it to be routed to 
the subscriptions from the view model side.

I want the UX developer and the client-side backend developer to get 
together and specify an API for what the UX needs and the abstraction 
provided by the backend. In this case, the commands and subscriptions 
listed above. I then want the UX developer to be able to go off and build 
using this API and I want the backend developer to similarly be able to go 
off and build the implementation of this API in as straightforward a way as 
possible.

What it feels like we need is a way to build effects managers based on 
other effects managers and an embrace of effects managers as a more general 
part of the architecture rather than a piece used for a limited range of 
platform API interfacing to be written by a much smaller number of people. 
Commands and subscriptions are great ways to specify the communication 
between layers and to allow those layers to be built and maintained 
independently but they aren't really available for that purpose as far as I 
can tell from the 0.17 documentation.

Or are there other patterns that allow the developers to agree on what 
needs to be done and get out of each others way as effectively as commands 
and subscriptions seem to do?

Mark

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-17 Thread Richard Feldman

>
> I have similar concerns about how deep down the stack Elm can go. At some 
> point, it seems like a good thing to separate business logic concerns from 
> UX logic concerns. 


This can already be done today, using plain old modules and organizing your 
data structures in a way that makes sense. Separating business logic from 
UX logic concerns does not require rearchitecting how your application is 
structured, nor should it. In this case, the way to pay heed to Dijkstra's 
advice is not to *create complexity* out of fear. :)

it could be that business logic belongs in Effects Managers. The 
> documentation around Effects Managers, however, suggests that they should 
> not be created all that often and that would be an odd stance for what 
> would be a standard part of a larger program. The second is to put the 
> business logic layer in as a wrapper around the view layer. That, however, 
> requires a rethink of commands and subscriptions to embrace something more 
> like the more general request concept with them really representing a 
> request for the next layer up to do something or provide some information. 


Nah, these are both solutions in search of a problem. I sometimes wonder 
whether the actual root issue here is that I'm saying "you should just 
build things and then divide later in response to specific pain points" but 
that's a really boring (however correct) answer to what would otherwise be 
a fun problem to try and solve. ;)

I'm not the only one saying this, by the way. Erik Lott is developing a 
large Elm SPA and his recent post 
 echoes 
the same "this is the wrong thing to spend time worrying about" sentiment 
I've been repeating.

tl;dr I hear you, but this concern doesn't materialize in practice. Elm has 
some things yet to work out (DOM APIs, how code splitting should work, 
etc), but architecture is not one of them.

We're all set on that front, so let's go build things! :)

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-17 Thread Mark Hamburg
On Aug 17, 2016, at 4:25 AM, Oliver Searle-Barnes  wrote:
> 
> e.g. I'm using websockets to communicate with the server, in my previous 
> experience I would have implemented a Store of some sort which took care of 
> communication with the server and allowed the view layer to just worry about 
> asking for information and sending mutations. 

I have similar concerns about how deep down the stack Elm can go. At some 
point, it seems like a good thing to separate business logic concerns from UX 
logic concerns. Managing complexity is one of the most important parts of doing 
software development. (Or is if you pay heed to Dijkstra.)

These concerns aren't about Elm as a language but have to do with the 
monolithic architecture that Elm encourages. Types make viable larger programs 
than would seem reasonable with JavaScript, but at some there needs to be a way 
to separate concerns.

I can see two potential answers within Elm. (There may be more but these are 
the ones that leap out.) One is that it could be that business logic belongs in 
Effects Managers. The documentation around Effects Managers, however, suggests 
that they should not be created all that often and that would be an odd stance 
for what would be a standard part of a larger program. The second is to put the 
business logic layer in as a wrapper around the view layer. That, however, 
requires a rethink of commands and subscriptions to embrace something more like 
the more general request concept with them really representing a request for 
the next layer up to do something or provide some information.

Mark

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-17 Thread OvermindDL1
On Wednesday, August 17, 2016 at 5:25:45 AM UTC-6, Oliver Searle-Barnes 
wrote:

> See elm-mdl for example, what are your thoughts on the elm-parts approach?
>

I quite like the elm-mdl/elm-parts approach, very extensible.  Do note that 
elm-mdl only uses elm-parts for parts that hold any kind of state (using 
'render' as its view function call).  If it is pure view then it does not 
use elm-parts (and uses 'view' as its view function call) in the general 
case.

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-17 Thread Oliver Searle-Barnes
Thanks, this is really practical advice.


The first three things you should reach for are, in no particular order:
>
>1. Splitting view into smaller functions (without reorganizing Model 
>or update)
>
>
>1. Splitting Model into smaller values (without reorganizing view or 
>update)
>
>
>1. Splitting update into smaller functions (without reorganizing Model
> or view)
>
>
I can see how this fits really well for building whole pages, where reuse 
isn't a concern. There are a couple of scenarios where I'm still left 
pondering though:

1) reusabled UI components

See elm-mdl for example, what are your thoughts on the elm-parts approach?

2) services 

e.g. I'm using websockets to communicate with the server, in my previous 
experience I would have implemented a Store of some sort which took care of 
communication with the server and allowed the view layer to just worry 
about asking for information and sending mutations. 

Currently I've implemented a Store as a TEA component without a view. This 
works but I'm left with this nagging doubt that I'm simply supplanting an 
ember-like approach into my new Elm app :) 

Just to add some weight to my feeling that there needs to be a layer 
between the view and the server I'm also intending to add management of 
optimistic updates --- so updates will initially be applied directly to the 
model optimistically, then once all updates have been confirmed with the 
server the optimistic state is thrown away and replaced by a version which 
has been updated with messages received only from the websocket (which is a 
mix of updates from both the local user and any other users connected to 
the same channel --- I'm using Phoenix).

Would you agree that a layer between the view and websocket makes sense 
here? If so how would you organise that? Does the approach I've taken, to 
implement it as a TEA component make sense or perhaps there's another 
approach that I haven't considered?

 

>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-17 Thread 'Rupert Smith' via Elm Discuss
On Thursday, August 11, 2016 at 2:38:45 AM UTC+1, Richard Feldman wrote:
>
> What were the cases where it was a good idea? You found some genuinely 
>> re-usable component in your code base?
>>
>
> The first example that comes to mind is when we had a "school search" 
> modal dialog on a dashboard that only displayed occasionally: once on 
> signup, and then again if you wanted to edit the school associated with 
> your account.
>
> It had a ton of self-contained logic - 20 fields in the Model, talking 
> back and forth to an Algolia API, etc - that involved a lot of code which 
> had absolutely nothing to do with the rest of the page. No matter what the 
> user did on the modal, it didn't affect any other part of the UI. So there 
> was almost nothing to communicate to the parent (pretty much just "hey, the 
> user clicked the Close button") and giving it its own separate Model, its 
> own separate View, and its own separate Update moved a lot of code out of 
> all three places for the parent.
>
> In a lot of ways, needing a lot of parent-child communication is probably 
> a red flag that these are too tightly coupled for a parent-child 
> relationship to be a good idea. :)
>

This sounds like Parna's principles of modular design and not wildly 
different to applying those principles in say OO design. If there is too 
much communication between two classes, the 'feature envy' suggests that 
the abstraction is not quite right. A better design needs to identify a 
class with enough self-contained state and/or logic to justify its 
existence. That said, in classic imperative OO design I reach for the 
modular design and re-use toolbox pretty quickly, it is almost second 
nature.

It is interesting what you are saying about not reaching for a modular 
design so quickly with elm, but to explore the other options first. For 
example, I am already finding that the View will fairly quickly throw up 
re-usable bits and pieces - perhaps a div that I wrap various UI elements 
in to give them some common look and feel. This can be abstracted out by 
writing it as a function, and if that function is particularly useful it 
can be pulled up into a ViewUtils.elm for re-use. Functional programming 
itself offers a lot of possibilities that imperative OO does not.

So I am reading your advice as 'explore what you can do with functional 
programming before you explore what you can do with modularizing the elm 
architecture'. 

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-13 Thread Rex van der Spuy
Thanks so much Richard, that's absolutely fascinating!

The way that I've been building my current generation of Elm apps has been 
modelled on the Counter/Pair example.
So it's not uncommon for me to have apps with nested M/V/U models 3 levels 
deep (For example, a "page" containing a "panel" which contains a "button" 
- that kind of structure.)
And, yup, it's a kind of a pain to manage the chain of updates through 
those nested structure and bubble up their effects.
So just having one structure to deal with sounds kind of. easy and nice 
:)

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-13 Thread Richard Feldman

>
> Are you suggesting that each self-contained Elm "app" ("page", "game" 
> etc.) should only have one Model/View/Update and avoid using nested modules 
> for sub-components?

 
Yeah - 

do you mean that something like the nested counter example from the Elm 
> Archtecture guide is a bad idea?


It's not *necessarily* a bad idea, just not the first thing you should 
reach for. Or the second thing you should reach for. Or the third thing you 
should reach for.

The first three things you should reach for are, in no particular order:

   1. Splitting view into smaller functions (without reorganizing Model or 
   update)
   2. Splitting Model into smaller values (without reorganizing view or 
   update)
   3. Splitting update into smaller functions (without reorganizing Model 
   or view)
   
Do one of these 3 things, one at a time, over and over, until either you're 
thinking "I need to split out some of this to reuse it elsewhere" (in which 
case you enter the realm of API design, and there is no one-size-fits-all 
answer to what you should do next), or you find yourself thinking "even 
after these small refactors, there is a big chunk of code that still feels 
unwieldy, and it's self-contained enough that I could separate it out into 
essentially its own little application, and have it communicate with the 
rest of the application, and that communication overhead sounds like it 
would be worth it."

As the guide says:

what happens when our code starts getting big? It would be crazy to just 
> grow your Model and update functions endlessly. This is where Elm's 
> module system comes in.


The nested counter is a demonstration of how to do this technique *once 
your code base grows crazy enough to make it seem worthwhile*, but it's 
super common to build something straightforward enough that it never needs 
this kind of nesting at all!

I get where you are coming from in saying that the update function becomes 
> essentially fifty smaller functions. Some of the questions on modularity 
> then stem from whether you ever expect someone to read through and consider 
> an entire Elm module or whether you expect that people will make changes to 
> pieces of code within a module and simply ignore the rest of it. The latter 
> is probably common no matter what. To me, it's a question of whether the 
> former should be viable or whether it's basically considered irrelevant as 
> a practice.
>

In my experience the latter hasn't been a problem, so it doesn't seem like 
looking for a solution would be a good use of anyone's time. ;) 

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-10 Thread Richard Feldman

>
> How big do the case statements in your update functions get? Or are your 
> pages just not that complex?
>
> I tend to like to keep modules in any language to a size that can be 
> reasonably read and comprehended. That doesn't always happen. I've written 
> some behemoths. But I tend to feel guilty when doing so.
>

They definitely get big, but one surprising thing I've learned is that a 
gigantic update function basically reads like a bunch of small, decoupled 
functions.

For example, here are a few cases from one of our update functions at work:

ToggleDescriptions ->
( { model | showDescriptions = not model.showDescriptions }, 
Cmd.none )

SetGradeFilterTooltipVisibility visibility ->
( { model | gradeFilterTooltipVisible = visibility }, Cmd.none )

OpenQuestionTooltip questionId ->
( { model | tooltipShowing = Just questionId }, Cmd.none )

CloseTooltips ->
( { model | tooltipShowing = Nothing, gradeFilterTooltipVisible = 
False }, Cmd.none )

One way to look at this is that it's 12 lines of code inside an update 
function.

Another way to look at it is that it's basically four one-liner functions, 
in terms of how decoupled they are and how easy it is to tell what they're 
doing.

That's what it feels like maintaining these. If I want to know what 
CloseTooltips does, I go look up its implementation. As it happens, its 
implementation lives inside a long update function, but it wouldn't have 
been any easier or harder to look up if the implementation happened to be a 
one-liner function instead. Obviously pattern matches aren't as composable 
as functions, but that doesn't make it any harder to follow what they're 
doing.

In practice a long update function feels like a lot of short, decoupled 
functions: really pleasant to maintain. :)


I took these four examples from our longest update function. It's about 600 
LoC, and its Msg is a union type with about 50 constructors.

One way to look at that is "that function is way too big by the heuristics 
I'm used to!"

Another way to look at it is "that will feel about the same as maintaining 
50 small independent functions, each an average of 12 LoC in length. Sounds 
like it'd be really easy to tell what each of them is doing!"

And so it is. :)

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-10 Thread Mark Hamburg
How big do the case statements in your update functions get? Or are your pages 
just not that complex?

I tend to like to keep modules in any language to a size that can be reasonably 
read and comprehended. That doesn't always happen. I've written some behemoths. 
But I tend to feel guilty when doing so.

Mark

> On Aug 8, 2016, at 9:42 PM, Richard Feldman  
> wrote:
> 
> We have over 36,000 lines of production Elm code that we've been running over 
> a year. Before that we had a ton of React code, although Elm has since 
> overtaken it in terms of LoC.
>  
>> Since I'm comfortable with React way to componentization, I can't understand 
>> why " flat is better than nested. " while getting big update and view 
>> functions.
>> These huge files won't hurt the maintainability (and reusability) of the 
>> project ? Someone can expand in this area ?
> 
> If the files feel too big, split them into separate files and import them. 
> That's not a big deal.
> 
> What is a big deal, and a super common beginner mistake, is to split out 
> separate state ownership when you don't need to yet.
> 
> Our React code base is full of components that each have their own local 
> state, because that's what React encourages.
> 
> Our Elm code base has very, very few components with their own local state. 
> In most cases each "page" has its own state and state is not subdivided any 
> further than that.
> 
> As far as maintainability goes, it's not remotely close. It's not just that 
> Elm code is more maintainable, it's that it is on a different planet of 
> maintainability. The gap between Elm and React is bigger than the gap between 
> React and MooTools.
> 
> tl;dr I wouldn't worry about it. :)
> -- 
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-10 Thread Sergey Skrynnikov
Oh no, just as I make a 3-deep TEA stack in my own app and start to feel 
good about finally sort of figuring it out, you have to go and post this :D
I don't think I've fallen into a trap.. yet.. but it wouldn't be a beginner 
trap if a beginner could casually avoid it, now would it?
Evan's recent video on designing a better API was very enlightening, and I 
think a lot of people would appreciate it if something like that was made 
but taking a beginner's application and explaining where the architecture 
could be improved, common traps and errors. Stuff an experienced person 
takes for granted, but not obvious for new people coming from different 
frameworks and conditioned to think in a specific way, etc. I'd be glad to 
provide my own pile of mistakes for dissection if one of our resident 
experts was willing to try something like this :) 

среда, 10 августа 2016 г., 2:54:24 UTC+3 пользователь Richard Feldman 
написал:
>
> But passing the callback down through the chain of nested components is 
>> ugly, fragile and may not even work if two components are not in the same 
>> parent-children chain. 
>>
>
> Not quite sure if that's what this is saying, but a good rule of thumb is 
> that Msg should never have a function in it, and neither should Model.
>
> Maybe I don't understand the Elm Architecture, but as far as I know every 
>> Elm module has it's own model, view and the update function.
>>
>
> For our (enormous) Elm code base at work, most pages (as in an individual 
> URL an end user can visit) have one model, one view, and one update 
> function. There is no "parent-child communication" on these pages.
>
> We had Elm in production for months before we encountered the first time 
> it was a good idea to have a "parent-child" relationship, and it was over 6 
> months (and well over 10,000 lines of Elm code) before we found the second 
> case where it was a good idea.
>
> Here is what I recommend:
>
>1. For a given page, start with one model, one view, and one update.
>2. If one of those (model, view, or update) gets too big and starts 
>feeling unwieldy, *subdivide only that thing.* For example, if view 
>feels too big, split it into some helper functions but *don't touch 
>model or update.* If update feels too big, same thing - split out 
>helper functions but don't touch the view or model. If your model feels 
> too 
>big, *reorganize only the model*. Split it from one record into some 
>nested records, but don't rearchitect update or view.
>3. Any time you find yourself thinking "I bet this will be nicer if I 
>split it into its own model/update/view" your next thought should be 
>"whoops! That's a classic beginner mistake. My code will actually be worse 
>if I do that. Glad I didn't do that!" (It's an easy trap to fall into - I 
>fell into it myself, and fell hard, as a beginner.)
>
> Basically, whenever I meet someone who is new to Elm and asking about 
> parent-child communication, what I really want to say is "a parent-child 
> relationship in an application is very rarely the right tool for the job, 
> and is almost certainly not what you want as a beginner. How can I help you 
> avoid falling into the same trap I fell into when I was just starting out?" 
> :)
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Richard Feldman

>
> Haha yeah I get your point, but when you talk about the large redink code 
> base (no doubt it's huge), I'm curious of the granularity of your 
> production Elm apps. Is your code base generally organized as one/a few 
> large single page applications (routing handled client side - data via api) 
> or is your code organized into many smaller applications, each served on a 
> single server rendered html page (routing handled server side - maybe 
> initial data is provided directly through Elm.fullscreen rather than 
> hitting an api).
>

The latter, although it's important to note that it's the same granularity 
either way. We started building our Elm code base on top of a large legacy 
non-SPA Rails app, so the way each individual page works is that Rails 
renders some JSON in a 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Erik Lott
Haha yeah I get your point, but when you talk about the large redink code 
base (no doubt it's huge), I'm curious of the granularity of your 
production Elm apps. Is your code base generally organized as one/a few 
large single page applications (routing handled client side - data via api) 
or is your code organized into many smaller applications, each served on a 
single server rendered html page (routing handled server side - maybe 
initial data is provided directly through Elm.fullscreen rather than 
hitting an api). What say you good sir?

It would be helpful to know, and would add some context to your comments. 



On Tuesday, August 9, 2016 at 10:28:33 PM UTC-4, Richard Feldman wrote:
>
> Either. :)
>
> On Tue, Aug 9, 2016, 7:20 PM Erik Lott  
> wrote:
>
>> Richard, just to clarify, when you say "pages", are you referring to 
>> server side rendered pages that each contain an Elm app, or a large Elm 
>> single page app that handles routing internally?
>>
>>
>>
>>
>>
>> On Tuesday, August 9, 2016 at 7:54:24 PM UTC-4, Richard Feldman wrote:
>>>
>>> But passing the callback down through the chain of nested components is 
 ugly, fragile and may not even work if two components are not in the same 
 parent-children chain. 

>>>
>>> Not quite sure if that's what this is saying, but a good rule of thumb 
>>> is that Msg should never have a function in it, and neither should Model.
>>>
>>> Maybe I don't understand the Elm Architecture, but as far as I know 
 every Elm module has it's own model, view and the update function.

>>>
>>> For our (enormous) Elm code base at work, most pages (as in an 
>>> individual URL an end user can visit) have one model, one view, and one 
>>> update function. There is no "parent-child communication" on these pages.
>>>
>>> We had Elm in production for months before we encountered the first time 
>>> it was a good idea to have a "parent-child" relationship, and it was over 6 
>>> months (and well over 10,000 lines of Elm code) before we found the second 
>>> case where it was a good idea.
>>>
>>> Here is what I recommend:
>>>
>>>1. For a given page, start with one model, one view, and one update.
>>>2. If one of those (model, view, or update) gets too big and starts 
>>>feeling unwieldy, *subdivide only that thing.* For example, if view 
>>>feels too big, split it into some helper functions but *don't touch 
>>>model or update.* If update feels too big, same thing - split out 
>>>helper functions but don't touch the view or model. If your model feels 
>>> too 
>>>big, *reorganize only the model*. Split it from one record into some 
>>>nested records, but don't rearchitect update or view.
>>>3. Any time you find yourself thinking "I bet this will be nicer if 
>>>I split it into its own model/update/view" your next thought should be 
>>>"whoops! That's a classic beginner mistake. My code will actually be 
>>> worse 
>>>if I do that. Glad I didn't do that!" (It's an easy trap to fall into - 
>>> I 
>>>fell into it myself, and fell hard, as a beginner.)
>>>
>>> Basically, whenever I meet someone who is new to Elm and asking about 
>>> parent-child communication, what I really want to say is "a parent-child 
>>> relationship in an application is very rarely the right tool for the job, 
>>> and is almost certainly not what you want as a beginner. How can I help you 
>>> avoid falling into the same trap I fell into when I was just starting out?" 
>>> :)
>>>
>> -- 
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "Elm Discuss" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/elm-discuss/_cfOu88oCx4/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> elm-discuss...@googlegroups.com .
>> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Erik Lott
Richard, just to clarify, when you say "pages", are you referring to server 
side rendered pages that each contain an Elm app, or a large Elm single 
page app that handles routing internally?





On Tuesday, August 9, 2016 at 7:54:24 PM UTC-4, Richard Feldman wrote:
>
> But passing the callback down through the chain of nested components is 
>> ugly, fragile and may not even work if two components are not in the same 
>> parent-children chain. 
>>
>
> Not quite sure if that's what this is saying, but a good rule of thumb is 
> that Msg should never have a function in it, and neither should Model.
>
> Maybe I don't understand the Elm Architecture, but as far as I know every 
>> Elm module has it's own model, view and the update function.
>>
>
> For our (enormous) Elm code base at work, most pages (as in an individual 
> URL an end user can visit) have one model, one view, and one update 
> function. There is no "parent-child communication" on these pages.
>
> We had Elm in production for months before we encountered the first time 
> it was a good idea to have a "parent-child" relationship, and it was over 6 
> months (and well over 10,000 lines of Elm code) before we found the second 
> case where it was a good idea.
>
> Here is what I recommend:
>
>1. For a given page, start with one model, one view, and one update.
>2. If one of those (model, view, or update) gets too big and starts 
>feeling unwieldy, *subdivide only that thing.* For example, if view 
>feels too big, split it into some helper functions but *don't touch 
>model or update.* If update feels too big, same thing - split out 
>helper functions but don't touch the view or model. If your model feels 
> too 
>big, *reorganize only the model*. Split it from one record into some 
>nested records, but don't rearchitect update or view.
>3. Any time you find yourself thinking "I bet this will be nicer if I 
>split it into its own model/update/view" your next thought should be 
>"whoops! That's a classic beginner mistake. My code will actually be worse 
>if I do that. Glad I didn't do that!" (It's an easy trap to fall into - I 
>fell into it myself, and fell hard, as a beginner.)
>
> Basically, whenever I meet someone who is new to Elm and asking about 
> parent-child communication, what I really want to say is "a parent-child 
> relationship in an application is very rarely the right tool for the job, 
> and is almost certainly not what you want as a beginner. How can I help you 
> avoid falling into the same trap I fell into when I was just starting out?" 
> :)
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Richard Feldman

>
> But passing the callback down through the chain of nested components is 
> ugly, fragile and may not even work if two components are not in the same 
> parent-children chain. 
>

Not quite sure if that's what this is saying, but a good rule of thumb is 
that Msg should never have a function in it, and neither should Model.

Maybe I don't understand the Elm Architecture, but as far as I know every 
> Elm module has it's own model, view and the update function.
>

For our (enormous) Elm code base at work, most pages (as in an individual 
URL an end user can visit) have one model, one view, and one update 
function. There is no "parent-child communication" on these pages.

We had Elm in production for months before we encountered the first time it 
was a good idea to have a "parent-child" relationship, and it was over 6 
months (and well over 10,000 lines of Elm code) before we found the second 
case where it was a good idea.

Here is what I recommend:

   1. For a given page, start with one model, one view, and one update.
   2. If one of those (model, view, or update) gets too big and starts 
   feeling unwieldy, *subdivide only that thing.* For example, if view 
   feels too big, split it into some helper functions but *don't touch 
   model or update.* If update feels too big, same thing - split out helper 
   functions but don't touch the view or model. If your model feels too big, 
*reorganize 
   only the model*. Split it from one record into some nested records, but 
   don't rearchitect update or view.
   3. Any time you find yourself thinking "I bet this will be nicer if I 
   split it into its own model/update/view" your next thought should be 
   "whoops! That's a classic beginner mistake. My code will actually be worse 
   if I do that. Glad I didn't do that!" (It's an easy trap to fall into - I 
   fell into it myself, and fell hard, as a beginner.)

Basically, whenever I meet someone who is new to Elm and asking about 
parent-child communication, what I really want to say is "a parent-child 
relationship in an application is very rarely the right tool for the job, 
and is almost certainly not what you want as a beginner. How can I help you 
avoid falling into the same trap I fell into when I was just starting out?" 
:)

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Raoul Duke
Generate updates as commands, in structs.

Add them to a list during the current frame. Current state remains
immutable.

At the end of the frame apply all commands to generate next world.

Next step starts with new world, old one is discarded.

Lather rinse repeat burmashave

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Jaroslaw Zabiello
But passing the callback down through the chain of nested components is 
ugly, fragile and may not even work if two components are not in the same 
parent-children chain. 

Maybe I don't understand the Elm Architecture, but as far as I know every 
Elm module has it's own model, view and the update function. It's all 
simple and nice if I have just a single file. But in the complex app I have 
to split my code among many files. On the other side I want to have the 
single main main model tree combined from all those smaller ones. How the 
update function of the nested module can change it's model now? It's 
aggregated to the higher place? And because Elm is immutable the model 
can't keep the reference to the object.

On Tuesday, August 9, 2016 at 11:32:39 PM UTC+1, OvermindDL1 wrote:
>
> 'How' do they need to communicate?  I've always seen such things as via 
> some callback Message lifter, which means you can just pass the parent 
> message type to it and the parent can pass it on as needed?
>
>
> On Tuesday, August 9, 2016 at 4:15:18 PM UTC-6, Jaroslaw Zabiello wrote:
>>
>> How you solve the problem with communication between two decoupled 
>> widgets? By decoupled, I mean two components which are not on the same 
>> parent-children path.
>>
>> On Tuesday, August 9, 2016 at 2:21:13 PM UTC+1, Rupert Smith wrote:
>>>
>>> On Thursday, August 4, 2016 at 11:15:53 PM UTC+1, Ryan Erb wrote:

 Got a few questions regarding the best way, or what options there are 
 for scaling up to a large site.
 If i have a site with lots of features what is the best way to orgainze 
 everything?

>>>
>>> I have been trying out the approach described here:
>>> http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html
>>>
>>> It has been useful to me, but I have too little experience to judge it 
>>> yet. 
>>>
>>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread OvermindDL1
'How' do they need to communicate?  I've always seen such things as via 
some callback Message lifter, which means you can just pass the parent 
message type to it and the parent can pass it on as needed?


On Tuesday, August 9, 2016 at 4:15:18 PM UTC-6, Jaroslaw Zabiello wrote:
>
> How you solve the problem with communication between two decoupled 
> widgets? By decoupled, I mean two components which are not on the same 
> parent-children path.
>
> On Tuesday, August 9, 2016 at 2:21:13 PM UTC+1, Rupert Smith wrote:
>>
>> On Thursday, August 4, 2016 at 11:15:53 PM UTC+1, Ryan Erb wrote:
>>>
>>> Got a few questions regarding the best way, or what options there are 
>>> for scaling up to a large site.
>>> If i have a site with lots of features what is the best way to orgainze 
>>> everything?
>>>
>>
>> I have been trying out the approach described here:
>> http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html
>>
>> It has been useful to me, but I have too little experience to judge it 
>> yet. 
>>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Jaroslaw Zabiello
How you solve the problem with communication between two decoupled widgets? 
By decoupled, I mean two components which are not on the same 
parent-children path.

On Tuesday, August 9, 2016 at 2:21:13 PM UTC+1, Rupert Smith wrote:
>
> On Thursday, August 4, 2016 at 11:15:53 PM UTC+1, Ryan Erb wrote:
>>
>> Got a few questions regarding the best way, or what options there are for 
>> scaling up to a large site.
>> If i have a site with lots of features what is the best way to orgainze 
>> everything?
>>
>
> I have been trying out the approach described here:
> http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html
>
> It has been useful to me, but I have too little experience to judge it 
> yet. 
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Wouter In t Velt
Thank you Peter for sharing the sortable table and especially the video link!
Video has a somewhat long winded exploration in accessibility in the early 
part, but I found it most helpful.

The thoughts on config and even updateConfig were really helpful. Also the idea 
to have an update take in 1 message type and output another message type is 
food for thought. Got me to rethink my own setup of child-to-parent 
communication.

I can definitely recommend both links!

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread 'Rupert Smith' via Elm Discuss
On Thursday, August 4, 2016 at 11:15:53 PM UTC+1, Ryan Erb wrote:
>
> Got a few questions regarding the best way, or what options there are for 
> scaling up to a large site.
> If i have a site with lots of features what is the best way to orgainze 
> everything?
>

I have been trying out the approach described here:
http://blog.jenkster.com/2016/04/how-i-structure-elm-apps.html

It has been useful to me, but I have too little experience to judge it yet. 

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Robert Walter
thank you Peter, I will try this approach and see how it works for my app.

On Tuesday, August 9, 2016 at 11:57:22 AM UTC+2, Peter Damoc wrote:
>
> Hi Robert, 
>
> To better understand the whole "state ownership" situation, take a look at 
> the implementation of elm-sortable-table
> https://github.com/evancz/elm-sortable-table
> and if you have the time/patience, watch this api design session 
> https://www.youtube.com/watch?v=KSuCYUqY058
>
> What I can share from my own experience is this: 
> Within a complex app, there are a series of business objects. Specific 
> locations in your app deal with these business objects and do something to 
> their data. 
>
> If you keep these business objects in one place at the top of your app and 
> you pass their information down to the components through the view, the way 
> it is done in elm-sortable-table, you end up with better code. 
>
> If you pass the business objects at init down into the components and then 
> you have to deal with the whole extraction of the information and 
> synchronization of the information you end up with more trouble than you 
> need to have. 
>
>
>
>
>
>
> On Tue, Aug 9, 2016 at 12:39 PM, Robert Walter  > wrote:
>
>> Hi Richard,
>>
>> interesting information there. For me, I'm at a much smaller scale, but 
>> the scalability of Elm certainly is the deciding factor for whether or not 
>> I want to use it in production. I'm fooling around with a small but 
>> non-trivial app to get a better feeling and understanding of how Elm 
>> behaves "over time" and how easy refactorings are. I take it that, a lot of 
>> the road bumps I hit are due to my lack of fully embracing The Elm 
>> Architecture, but I would really like to get a better sense of what you 
>> mean with "state ownership". Are there any "archetypes" or "patterns" that 
>> give a bit more guidance? I can see that are common cases in different apps 
>> that appear over and over again, where we could give some direction.
>> Not sure if my use case is actually that common, but just to give an 
>> example what I have in mind: 
>> I have an app with a "collector" and "items" (to keep it abstract for the 
>> moment). I want to have a page in my app, where I show the user an overview 
>> over all typed collections (think of a dashboard). For each item type, 
>> there are specific pages that show the user details of an item. Of course, 
>> everything is interactive. The question is, should the items become 
>> components? If yes, why? If no, why? 
>> Maybe there is no "yes of no" answer for this specific case, but I hope I 
>> was able to illustrate my idea.   
>>
>> In general, I'd prefer to work with components early on, because I feel 
>> that, the longer I wait, the bigger and more painful the refactoring will 
>> become once I have to go from monolith to components. 
>>
>> On Tuesday, August 9, 2016 at 6:42:57 AM UTC+2, Richard Feldman wrote:
>>>
>>> We have over 36,000 lines of production Elm code that we've been running 
>>> over a year. Before that we had a ton of React code, although Elm has since 
>>> overtaken it in terms of LoC.
>>>  
>>>
 Since I'm comfortable with React way to componentization, I can't 
 understand why " *flat is better than nested*. " while getting big 
 update and view functions.

>>> These huge files won't hurt the maintainability (and reusability) of the 
 project ? Someone can expand in this area ? 

>>>
>>> If the files feel too big, split them into separate files and import 
>>> them. That's not a big deal.
>>>
>>> What is a big deal, and a super common beginner mistake, is to split out 
>>> separate state ownership when you don't need to yet.
>>>
>>> Our React code base is full of components that each have their own local 
>>> state, because that's what React encourages.
>>>
>>> Our Elm code base has very, very few components with their own local 
>>> state. In most cases each "page" has its own state and state is not 
>>> subdivided any further than that.
>>>
>>> As far as maintainability goes, it's not remotely close. It's not just 
>>> that Elm code is more maintainable, it's that it is on a different planet 
>>> of maintainability. The gap between Elm and React is bigger than the gap 
>>> between React and MooTools.
>>>
>>> tl;dr I wouldn't worry about it. :)
>>>
>> -- 
>> 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 elm-discuss...@googlegroups.com .
>> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit 

Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-09 Thread Peter Damoc
Hi Robert,

To better understand the whole "state ownership" situation, take a look at
the implementation of elm-sortable-table
https://github.com/evancz/elm-sortable-table
and if you have the time/patience, watch this api design session
https://www.youtube.com/watch?v=KSuCYUqY058

What I can share from my own experience is this:
Within a complex app, there are a series of business objects. Specific
locations in your app deal with these business objects and do something to
their data.

If you keep these business objects in one place at the top of your app and
you pass their information down to the components through the view, the way
it is done in elm-sortable-table, you end up with better code.

If you pass the business objects at init down into the components and then
you have to deal with the whole extraction of the information and
synchronization of the information you end up with more trouble than you
need to have.






On Tue, Aug 9, 2016 at 12:39 PM, Robert Walter 
wrote:

> Hi Richard,
>
> interesting information there. For me, I'm at a much smaller scale, but
> the scalability of Elm certainly is the deciding factor for whether or not
> I want to use it in production. I'm fooling around with a small but
> non-trivial app to get a better feeling and understanding of how Elm
> behaves "over time" and how easy refactorings are. I take it that, a lot of
> the road bumps I hit are due to my lack of fully embracing The Elm
> Architecture, but I would really like to get a better sense of what you
> mean with "state ownership". Are there any "archetypes" or "patterns" that
> give a bit more guidance? I can see that are common cases in different apps
> that appear over and over again, where we could give some direction.
> Not sure if my use case is actually that common, but just to give an
> example what I have in mind:
> I have an app with a "collector" and "items" (to keep it abstract for the
> moment). I want to have a page in my app, where I show the user an overview
> over all typed collections (think of a dashboard). For each item type,
> there are specific pages that show the user details of an item. Of course,
> everything is interactive. The question is, should the items become
> components? If yes, why? If no, why?
> Maybe there is no "yes of no" answer for this specific case, but I hope I
> was able to illustrate my idea.
>
> In general, I'd prefer to work with components early on, because I feel
> that, the longer I wait, the bigger and more painful the refactoring will
> become once I have to go from monolith to components.
>
> On Tuesday, August 9, 2016 at 6:42:57 AM UTC+2, Richard Feldman wrote:
>>
>> We have over 36,000 lines of production Elm code that we've been running
>> over a year. Before that we had a ton of React code, although Elm has since
>> overtaken it in terms of LoC.
>>
>>
>>> Since I'm comfortable with React way to componentization, I can't
>>> understand why " *flat is better than nested*. " while getting big
>>> update and view functions.
>>>
>> These huge files won't hurt the maintainability (and reusability) of the
>>> project ? Someone can expand in this area ?
>>>
>>
>> If the files feel too big, split them into separate files and import
>> them. That's not a big deal.
>>
>> What is a big deal, and a super common beginner mistake, is to split out
>> separate state ownership when you don't need to yet.
>>
>> Our React code base is full of components that each have their own local
>> state, because that's what React encourages.
>>
>> Our Elm code base has very, very few components with their own local
>> state. In most cases each "page" has its own state and state is not
>> subdivided any further than that.
>>
>> As far as maintainability goes, it's not remotely close. It's not just
>> that Elm code is more maintainable, it's that it is on a different planet
>> of maintainability. The gap between Elm and React is bigger than the gap
>> between React and MooTools.
>>
>> tl;dr I wouldn't worry about it. :)
>>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-05 Thread Ryan Erb
Thanks all for the responses, got a lot of good information here to start 
playing with. 
Does seem the consensus is that there is one "main" elm module that will 
bubble down information to other sections and modules.

Thanks!!!

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-05 Thread OvermindDL1
I'm unsure if this is Elm'y, but it is built on prior experiences with 
other languages.

I currently have a javascript app that I am slowly converting to Elm as 
parts gets replaced, so I am using a lot of little embedded Elm apps (in a 
single file so as to not duplicate the standard large library).  Each one 
has a main section that calls to and builds up other areas.  I have a 
singular Helper that can dispatch around that I implement in each of my 
main apps like (which I understand is similar to debois/elm-parts though I 
think is more generic?)
```elm
type alias Model =
{ helpers : HelpersModel Msg
| others...

init : ProgramFlags -> Result String Location -> ( Model, Cmd Msg )
init programFlags locResult =
let
model' : Model
model' =
{ helpers = Helpers.helpers_init Helpers
, etc...


type Msg
= Helpers (HelpersMsg Msg)
| etc...


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
  case msg of
  Helpers helpersMsg ->
let
( helpersModel, helpersCmd ) =
Helpers.helpers_update Helpers helpersMsg 
model.helpers
in
( { model | helpers = helpersModel }
, helpersCmd
)


subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ helpers_subscriptions Helpers model.helpers
, etc...
```

I should probably switch to debois/elm-parts as it is an actually released 
library and so wrap my helpers into it for my project, but as it stands I 
can make new components (many counters if I want!), wrappers for a ton of 
port functionality (How about focus an element after the next rendered 
frame?  Sure!  `cmd_onNextFrame Helpers <| focusElem Helpers 
input_selector`), etc...


On Thursday, August 4, 2016 at 4:15:53 PM UTC-6, Ryan Erb wrote:
>
> Got a few questions regarding the best way, or what options there are for 
> scaling up to a large site.
> If i have a site with lots of features what is the best way to orgainze 
> everything?
>
> *One Elm page to rule them all?* With this approach you only have to deal 
> with one update happening, you can separate code into different modules, 
> but the update function would be HUGE. Guess this would be the same as a 
> single page application?
>
> *One Elm page per HTML page?* This way every page deals with only what it 
> is used for. You can write common things in reusable modules. One problem 
> might be switching to other elm pages. The only really good way right now 
> that i have is using a port to "window.locaion.href" to another elm page. 
> Then pulling all the data it requires from the server using more ports.
>
> *One Elm page per feature?* This way you can write separate apps for each 
> part of your page. One for the header menu bar, one for a sidebar, and one 
> for each main feature. This way you can mix and match and piece together 
> for a full page. BUT you might have to do a lot of port talking between 
> each section.
>
> *Some other way?*?
>
> Been searching around a cant seem to find any blogs or topics on this 
> subject. Our stack is Elm/Phoenix/Elixir/Postgres.
>
> If anyone has created a large application using Elm would happy to have 
> your input on what worked/ didn't work for you.
>
> Thanks,
>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-05 Thread Jaroslaw Zabiello
I am not sure how Elm Architecture scales for dozens or hundreds of modules 
because it's tough to pass a global context object down to all submodules 
and components. I love the way Cerebral  works. 
Every component is connected to it's part in the immutable main model. UI 
components are isolated from the state controlled by modules. A component 
register it's signals. Every signal execute a chain of actions. They are 
always sequential, sync, and asynch are executed in the order. Actions can 
be grouped in higher older factories as well as the signals. It's very 
clean and scalable. Every module has access to global context object. Every 
component has access to any part of one, global model object. Cerebral is 
like Redux-Saga but much simpler.

Did anybody try to address the issues raised by these two articles?
 
* http://www.christianalfoni.com/articles/2015_11_30_Exploring-Elm-part1
* http://www.christianalfoni.com/articles/2015_12_17_Exploring-Elm-part2


On Thursday, August 4, 2016 at 11:15:53 PM UTC+1, Ryan Erb wrote:
>
> Got a few questions regarding the best way, or what options there are for 
> scaling up to a large site.
> If i have a site with lots of features what is the best way to orgainze 
> everything?
>
> *One Elm page to rule them all?* With this approach you only have to deal 
> with one update happening, you can separate code into different modules, 
> but the update function would be HUGE. Guess this would be the same as a 
> single page application?
>
> *One Elm page per HTML page?* This way every page deals with only what it 
> is used for. You can write common things in reusable modules. One problem 
> might be switching to other elm pages. The only really good way right now 
> that i have is using a port to "window.locaion.href" to another elm page. 
> Then pulling all the data it requires from the server using more ports.
>
> *One Elm page per feature?* This way you can write separate apps for each 
> part of your page. One for the header menu bar, one for a sidebar, and one 
> for each main feature. This way you can mix and match and piece together 
> for a full page. BUT you might have to do a lot of port talking between 
> each section.
>
> *Some other way?*?
>
> Been searching around a cant seem to find any blogs or topics on this 
> subject. Our stack is Elm/Phoenix/Elixir/Postgres.
>
> If anyone has created a large application using Elm would happy to have 
> your input on what worked/ didn't work for you.
>
> Thanks,
>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Design of Large Elm apps

2016-08-05 Thread art yerkes
In my app, my elm code was structured like this (note that this is an SPA 
with no server integration ...)

/Master.elm <-- SPA host.  Hosts a header, drawer, login dialog and view 
stack
/Account/Login.elm <-- Login dialog
/Account/WorkoutEditor.elm <-- Views that can be accessed only by logging in
/Account/Share.elm ...
/Header/Header.elm <-- Header renderer
/Splash/Welcome.elm <-- Default view
/ShowCard/Search.elm <-- Views that can be accessed without logging in
/ShowCard/SearchResult.elm ...
/ShowCard/WorkoutInfo.elm ...
/ShowCard/WorkoutView.elm ...

It might seem like you'd need a big update function but I composed a bunch 
of small ones 
with http://package.elm-lang.org/packages/prozacchiwawa/effmodel/2.0.0/ 
like this:

Happily, if you do this, you can write tests that ensure that each 
sub-update implements the right state transitions.

effModelUpdate : Action -> EffModel Model Action -> EffModel Model Action

effModelUpdate action effmodel =

effmodel

|> handleMDL action

|> handleSlugUpdate action

|> handlePageAnimation action

|> handlePurposeSet action

... -- Snipped

|> handleFacebook action

|> handleSlugArgs action

|> serializeTimer action

|> handleLoginAction action

|> handleLoginProcessAction action


Each of these functions conceptually handles a self contained set of 
messages related to one feature.  Connecting the subcomponents via ports 
would be an option, but this worked ok.


I wrote about the way these are composed 
here: 
https://medium.com/@prozacchiwawa/the-i-m-stupid-elm-language-nugget-6-48229076c88e#.2fgf44mx3


For each subcomponent I had a small test main that set up some test data 
and ran the component on its own.  That's one reason I think that splitting 
up views into modules is a good idea.


On Thursday, August 4, 2016 at 3:15:53 PM UTC-7, Ryan Erb wrote:
>
> Got a few questions regarding the best way, or what options there are for 
> scaling up to a large site.
> If i have a site with lots of features what is the best way to orgainze 
> everything?
>
> *One Elm page to rule them all?* With this approach you only have to deal 
> with one update happening, you can separate code into different modules, 
> but the update function would be HUGE. Guess this would be the same as a 
> single page application?
>
> *One Elm page per HTML page?* This way every page deals with only what it 
> is used for. You can write common things in reusable modules. One problem 
> might be switching to other elm pages. The only really good way right now 
> that i have is using a port to "window.locaion.href" to another elm page. 
> Then pulling all the data it requires from the server using more ports.
>
> *One Elm page per feature?* This way you can write separate apps for each 
> part of your page. One for the header menu bar, one for a sidebar, and one 
> for each main feature. This way you can mix and match and piece together 
> for a full page. BUT you might have to do a lot of port talking between 
> each section.
>
> *Some other way?*?
>
> Been searching around a cant seem to find any blogs or topics on this 
> subject. Our stack is Elm/Phoenix/Elixir/Postgres.
>
> If anyone has created a large application using Elm would happy to have 
> your input on what worked/ didn't work for you.
>
> Thanks,
>
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-04 Thread Peter Damoc
That gist is old. For current Elm Architecture, please refer to the guide.
http://guide.elm-lang.org/

I don't know about "the best way" but I can share how my App is structured.

I have two types of pages in my app: Interactive and Informational.
The informational pages are typically generated from markdown and are
rendered all by the MainView.
The interactive pages typically live inside their own modules.
Some of the interactive pages generate actions for the entire App.
Those pages' update typically evaluate to a 3 element tuple: (Model, Cmd
Msg, Maybe OutMsg)

The recommendation I have is to keep your app one "component" as long as
you can.
Rethink the code structure in terms of smart types that can generate what
you need with simple functions.
Move to "components" as late as possible.

Yes, you might end up with quite large update and view functions but, most
of the time, *flat is better than nested*.




On Fri, Aug 5, 2016 at 1:45 AM, Ryan Erb  wrote:

> Well after a bit more searching found this
>
> https://gist.github.com/evancz/2b2ba366cae1887fe621
>
> Seems like one large Elm app divided into modules seems to be the way to
> go?
>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Design of Large Elm apps

2016-08-04 Thread Nick Hollon
That is the approach I would take. 

Don't forget that the elm website and package manager are written in elm, and 
they are open source! Recommended reading ;-)

> On Aug 4, 2016, at 6:45 PM, Ryan Erb  wrote:
> 
> Well after a bit more searching found this 
> 
> https://gist.github.com/evancz/2b2ba366cae1887fe621
> 
> Seems like one large Elm app divided into modules seems to be the way to go?
> -- 
> 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 elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.