--
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.
--
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+unsubscribe@googlegroups.com.
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.
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 ?
--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
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?
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!
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
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.
Either. :)
--
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.
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).
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.
What were the cases where it was a good idea? You found some genuinely re-usable component in your code base?
--
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.
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.
- For a given page, start with one model, one view, and one update.
- 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.
- 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?" :)
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?
do you mean that something like the nested counter example from the Elm Archtecture guide is a bad idea?
what happens when our code starts getting big? It would be crazy to just grow yourModel
andupdate
functions endlessly. This is where Elm's module system comes in.
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.
The first three things you should reach for are, in no particular order:
- Splitting view into smaller functions (without reorganizing Model or update)
- Splitting Model into smaller values (without reorganizing view or update)
- Splitting update into smaller functions (without reorganizing Model or view)
See elm-mdl for example, what are your thoughts on the elm-parts approach?
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 componentsSee elm-mdl for example, what are your thoughts on the elm-parts approach?
2) servicese.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 :)
Would you agree that a layer between the view and websocket makes sense here?
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.
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.
Richard's definition of large application (36,000 lines) and my definition (Photoshop, Lightroom, ...) are rather different in scale
Richard's definition of large application (36,000 lines) and my definition (Photoshop, Lightroom, ...) are rather different in scaleOP 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. :)
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.
some scaling issues arrive the moment you would like to have two people work on something
--
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+unsubscribe@googlegroups.com.
On Aug 25, 2016, at 2:51 PM, Richard Feldman <richard....@gmail.com> wrote:Richard's definition of large application (36,000 lines) and my definition (Photoshop, Lightroom, ...) are rather different in scaleOP 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.
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+unsubscribe@googlegroups.com.
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.
requestQueue : Dict RequestId { order : Int, request : Task Never Msg }
| CancelRequest RequestId
type AppCommand msg= Immediate (Cmd msg)| Queued Int (Cmd Msg)| Batch (List (AppCommand msg))
--
| Queued Int (Cmd msg)
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
if you wanted to subdivide some of the major sections into sub-modules, would you have them stop using Platform.Cmd to communicate upward
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?
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?Because everyone who reads the Elm guide will have learned that the way to make an HTTP request is to construct a Task and convert it into a Cmd and return that in the second part of the update result. So, I'm looking for a way to say "same routing pattern, different call to create the prioritized request". Keeping code to the same code flow keeps different programmers from finding different ways to update the priority queue in the root model with their request. Instead, they just code mostly like they would otherwise and the root model takes care of the actual priority queue management.
Keeping code to the same code flow keeps different programmers from finding different ways to update the priority queue in the root model with their request.
| PostMessage (Error -> clientMsg) (() -> clientMsg) ForumId String
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.clientMsg -> clientModel -> (clientModel, ClientCommand clientMsg)
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.
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?
--
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. :)
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
--
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.
--
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.
So, maybe components sound too much like objects and should be avoided but what are needed are patterns of partitioning and coordination.
P.S. We also need performance-oriented patterns. For example, I'm concerned that a complex model — regardless of how it is partitioned or not — could require many subscriptions and if these are re-computed and effects managers are updated on every change to the model, there is likely to be a lot of repeated busy work. Are there patterns for managing subscriptions that avoid that?
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
module API exposing(addForum, deleteForum, postMessage)
addForum: String -> Task Http.Error Forum
// code here...
deleteForum: String -> Task Http.Error Never
// code here
etc
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.
(:>) (model, Batchable ops)-> (model -> (model, Batchable ops))-> (model, Batchable ops)
(model, Batchable.none):> firstUpdate:> secondUpdate
(:>) (model, Batchable op)-> (model -> (model, Batchable op))-> (model, Batchable op)(:>) (oldModel, oldOps) update =let(newModel, newOps) = update oldModelin(newModel, Batchable.batch [oldOps, newOps])
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
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
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,
type ClientCommand msg= Batch (List (ClientCommand msg))| PlatformCmd (Platform.Cmd msg)| APIFromClient (APICommand msg)
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.
update : Msg -> Model -> (Model, Cmd)
update : Msg -> Model -> (Model, ClientCommand)