This is hints toward improper representation. In this particular case,
apiRootUrl has no business being a
Maybe. If that
Url.fromString evaluates to a
Nothing the app should not start. You can have a
FatalError page if you want and that page could be used for such contexts. The alternative would be to make your app unresponsive by using a default url.
This is a matter of personal preferences at this point. If you want inspiration, check the elm-spa-example. That app presents a lot of good practices. Richard is one of the core team members and he has spent a lot of time thinking about the layout of the files and the splitting of that app.
The way I would split it is different and more in line with the original version of
elm-spa-example (the current version is the second incarnation).
The way I would split your code would be like this:
- Create a
Data.elm file and move there the business objects (
Lyric) and their decoders.
- Change the
Api.elm and move all the api calls there. The functions exposed by this module should take in a
Context record (where I would put the
apiRootUrl and the
Key), some kind of arguments (e.g. search string) and a
toMsg: Result Http.Error SomePayload -> msg function that would allow you to have each function return
Cmd msg. This module would import from
Data. This would be the only module importing
- Create a
Route.elm that would hold the
Route custom data type and all the functionality around routing. I would only use the
Nav module functions in this module and expose an API that deals with
Route values instead of raw
These things should already clean your code considerably. Moving on, as the project develops, I would have a
Ui.elm with all kinds of small view functions (the equivalent of components from other languages). Most likely a
Pages folder would be the next split and move there, the code of each page (model, update, view) on a one page = one module structure.
As the project grows, it might be required to split modules by sections. So,
Api.elm could keep some of the more used functions but a new
Api folder could be created next to it and move there code dealing with only a particular section e.g.
module Api.Lyrics. This would be an overkill at the current stage. The same with
Data.elm, you could have a
Data folder with
module Data.Artist but it would again be an overkill in the current scenario. (I do have one of these
Data files that already has some 800 LOC). The
Ui.elm could also get a
Ui folder for very complex widgets.