Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/simple app: experience could be better #1717

Closed
CreaturesInUnitards opened this issue Mar 15, 2017 · 13 comments
Closed

Docs/simple app: experience could be better #1717

CreaturesInUnitards opened this issue Mar 15, 2017 · 13 comments
Labels
Area: Documentation For anything dealing mainly with the documentation itself

Comments

@CreaturesInUnitards
Copy link
Contributor

IMHO the simple app is an excellent introduction to mithril; however it falls down in some critical places for the uninitiated:

  1. Saves to the free heroku service don't always work, which could lead a noob to think — quite reasonably — that the framework itself is failing. Or that they've failed to duplicate the code properly. There is nothing that alerts the dev that saves aren't really happening. If the tutorial is intended to be the newcomer's first real experience with mithril, I would contend that this breakage in functionality is crippling to the framework's potential reach. The tutorial must be airtight.

  2. The code as it stands never updates the local cache. This is, in my experience, one of the great potential pitfalls for noobs.

  3. When we navigate to UserForm, we retrieve the User from the webservice, and not from our local cache. This enables the scenario of navigating directly to the UserForm without first viewing the list, but it means we're editing a separate object rather than the one which may already exist in our local cache (User.list).

  4. The entire list is retrieved every time we navigate to UserList.

I think the necessary concepts can be taught better and more reliably if changes are made to address the above issues. My top-of-head suggestions:

  1. Ditch the remote server, and instead make m.request calls to a local JSON file. This is server spoofage at its least complex and transparent, and can guarantee that a properly configured environment will function predictably. Move calls to actual web apis into a separate, more advanced tutorial.

  2. Changes made to the edited "user" must be reflected in User.list. Obviously there are myriad approaches; I'd suggest working directly against the cached object at first, and then later in the tutorial — or in another, more-advanced tutorial — copying the chosen object's fields into UserForm's vnode.state, and only applying them to the cached object upon saving.

  3. Once we introduce RouteResolvers and the Layout component, move the call to User.loadList into Layout.oninit, where: a) it will only happen once; and b) it has the added benefit of populating the local cache and ensuring that we're not working with a duplicate object.

I'll happily put together a PR if the braintrust agrees.

@barneycarroll
Copy link
Member

@CreaturesInUnitards good points.

Free tier Heroku apps go down for a few hours a day by design — it's a policy to discourage people from setting up production infrastructure without shelling out.

Setting up a mock server or getting the user to roll their own is the robust attitude but I dislike it for a few reasons: 1) It involves boilerplate setup which compromises what is otherwise a great example of front-end from scratch 2) Involving a mock in the first place raises issues which distract from the general focus of the guide, which I think is paramount.

I think a better approach would be to use a persistent and reliable REM server instead. I believe @spacejack (someone else on Gitter!) set one up on Gomix or Zeit… But then extending the tutorial to include a second part, involving error handling, would be a good move if the general concern is robust modelling… What do you think?

The problem with refactoring towards a holistically better model is that it's not long before we start bikeshedding about good practices. For instance, IMO it's better to quickly get a CRUD interface set up even if the HTTP access layer is arguably inefficient, rather than extending the model to include local state first, and defer POST to a later stage.

Rather than draw the reader into thinking about the perennial hot topic of good modelling practices, I think it's better to introduce them to a minimal approach that avoids these concerns. This might sound controversial, but personally I think the best way around this is to use component state for storage: this involves less moving parts, makes use of out of the box functionality, and introduces the user to another Mithril concept in one fell swoop. It also solves other problems with the model that a new user came up against last night on chat: how do we avoid race conditions with multiple request resolution and how might we extend the application to indicate loading state / stale data. I opened an issue for that at #1708.

I know storing model data in components is controversial but I see this as an Alexandrian solution to a tricky problem which somebody or other will otherwise always find fault with. For instance, I strongly dislike @lhorie's convention of using capitalised references to model objects which are not constructors, which make no a priori distinction between stateless methods and data properties — how do we extend this model to be aware of multiple users? How do we deal with persistence across sessions? We can debate and extend the introduction forever to cater for more and more opinions about modelling good practice, but I feel it's much better to lay down a system with shortcomings that's easy to reason about and extend in intuitive ways with less foreign concepts and opinions.

@CreaturesInUnitards
Copy link
Contributor Author

@barneycarroll thanks for the well-coinsidered response.

My suggestion, in terms of boilerplate setup, is to include live-server. It's a dead-simple installation and deployment, and we're already using node and NPM, so I see little downside.

I'm not suggesting we get into good modelling (2 Ls? What, are ya British? 😛 ) practices at all; I simply think the thing has to work no matter what.

I completely agree that having a persistent and reliable REM server would be better, but the Zeit instance you're referencing has exactly the same problem as heroku. It worked for me for 2-3 page loads and then simply stopped. Who will host this mythic beast? Until it's proven, I stand my my contention that says it's better to stand up a local server with 2 shell commands than to have a failing demonstration.

FWIW I honestly don't care where the model data is stored. I myself prefer the oft-reviled "God Object", but a stateful component can be perfectly serviceable. That said, my biggest real complaint with the tutorial is that we're fetching from an unreliable source.

@barneycarroll
Copy link
Member

Cool, my stuff goes way out of scope. Shall we use this as a single issue ticket for reliable HTTP? @tivac suggests https://jsonbin.org/ as an alternative to REM / mocking / build-your-own, which is a nice simple way out IMO.

@CreaturesInUnitards
Copy link
Contributor Author

@barneycarroll #1717 as reliable HTTP ticket: Excellent! Thanks.

That said: I'm not sold on jsonbin.org for the introductory tutorial, if only because 1) it has such a non-standard API, and 2) the upside isn't up enough to justify the extra hoop-jumping. I honestly don't see how we achieve less friction than:

$> npm install live-server
... (this is us watching npm install stuff)...
$> live-server

...at which point we can make local AJAX calls. The behavior is indistinguishable from an actual remote except that there is zero latency. All that changes in simple-application.md is the m.request url, the inclusion of the raw JSON, and the instruction to save it into a local .json file.

To use jsonbin.org (which, I'll repeat, is a great idea for Tutorial 2: The Quickening), each user must create an account, then in m.request include a custom header with a bearer token. This is absolutely not "Hi, welcome to Mithril.js! You can tell we care about EVERYONE, because this tutorial is so EASY!" territory. Mithril has, by far, the fastest 0-60 learning curve out there. In my considered opinion, Friction == BarrierToEntry. I think we're violating the High Order Bid.

I'm pretty firm in my belief that further exploration, including real, functioning HTTP, including all manner of CRUD, including gotchas and the stateful/stateless component debate, should be relegated to one or more subsequent tutorials. We're trying to grow the mithril community, and evangelize its merits. For first impressions, IMHO, the less friction the better.

(Full disclosure: if your suspicion is that I'm the sort of person who needs to be shouted down once my mind's made up, I'm happy to report that your suspicion is spot on. And yes, please let this serve as a formal invitation to shout me down.)

Soooo...

I'd suggest that we get an official jsbin.org boilerplate going, and begin brainstorming the scope of Tutorial 2: The Quickening.

Beers?

@barneycarroll
Copy link
Member

100% on reducing friction and relegating tangential subjects to further tutorials later down the line.

You're right about jsonbin.org requiring a bit more boilerplate. You'd need some setup and config for a foreign service, which is a distracting overhead.

Going back to your mocking idea — why not simply install REM locally? Writing and saving json files to a filesystem is a significant detour from the intended focus. REM really does address this in an admirable, batteries included way — the only problem is the remote service.

@CreaturesInUnitards
Copy link
Contributor Author

Thanks for your patience — once again, I fail to make myself clear. I'm not suggesting that we "write and save json files to a filesystem". I think CRUD is too big for Tutorial 1. I think we should just do a single read using m.request. This accomplishes 3 key goals of a first demo for noobs:

  1. exposes the HTTP syntax as simply and transparently as possible
  2. demonstrates the auto-redraw mechanism
  3. keeps the focus on Mithril, not on persistence issues

I get it: the idea of a full, round-trip CRUD app in 5 minutes is pretty cool. But I don't believe it's cool enough, in the context of Tutorial 1, to justify the dependencies. In fact, if we're going to update remote data, we then need to make sure the local cache gets updated, and all of a sudden we're writing an app with opinions about concurrency strategy, instead of writing an app about learning Mithril.

Spelling it out:

  1. the noob following Tutorial 1, along with all the other node-related activities, installs and launches live-server.
  2. they copy/paste the raw json to a shiny new file in their project folder (or download a linked file, whichever).
  3. they read in the file via m.request.

That's it for HTTP in Tutorial 1. It seems to me that we have a disagreement about the importance of performing remote CRUD operations in the very first exposure to Mithril. My contention is that, after we've used m.request once, subsequent operations will, more than anything else, take focus away from Mithril.

...

I think CRUD is for Tutorial 2: The Quickening. That's my whole thesis.

@orbitbot
Copy link
Member

TBH this is not at all a bad TLDR Mithril 1.0 documentation site: https://mithril-examples.firebaseapp.com/

@CreaturesInUnitards
Copy link
Contributor Author

@orbitbot agreed. I'd say it's more of a "quick reference card" than a tutorial/intro, though.

My entire agenda here is to evangelize; in my judgment we can take 1st-day mithril noobs from "hello world" to a simple app that uses ajax and routing in a few, easily understandable steps. I'm putting together a repo right now, and will happily invite comments/criticisms/PRs.

@CreaturesInUnitards
Copy link
Contributor Author

CreaturesInUnitards commented Mar 16, 2017

@barneycarroll @orbitbot Ok, I have a repo up with what I think is a good destination for a noob's introduction to Mithril, just before we actually need to start doing CRUD over HTTP. I'd love to hear your thoughts: mithril-tutorial. maybe.

...

To be clear: this is my thought for the final destination of Tutorial 1. Obviously the steps leading up from Hello World would need to be implemented. What I'm asking is: do you agree that we can cover a really healthy chunk of idiomatic Mithril just to get to this point, and then bring in heavier dependencies for Tutorial 2?

@cavemansspa
Copy link
Contributor

@CreaturesInUnitards -- i'd suggest taking it one step further in simplification by making it zero install and runnable right from your repo via rawgit. e.g. http://cdn.rawgit.com/lhorie/mithril.js/rewrite/examples/todomvc/index.html#!/

@dead-claudia dead-claudia added the Area: Documentation For anything dealing mainly with the documentation itself label Mar 17, 2017
@CreaturesInUnitards
Copy link
Contributor Author

@cavemansspa
Copy link
Contributor

nice @CreaturesInUnitards! seeing actual running app will definitely get more interest and people taking a closer look at code.

@smuemd
Copy link
Contributor

smuemd commented Mar 22, 2017

@CreaturesInUnitards 🙌 Thanks for putting this together. This is exactly what people who check out Mithril for the first time need. This will go a long way...

@MithrilJS MithrilJS locked and limited conversation to collaborators Jan 29, 2022
@orbitbot orbitbot converted this issue into discussion #2726 Jan 29, 2022
@dead-claudia dead-claudia moved this to Under consideration in Feature requests/Suggestions Sep 2, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
Area: Documentation For anything dealing mainly with the documentation itself
Projects
Status: Under consideration
Development

No branches or pull requests

6 participants