Mithril.js: Model layer architeture doubts - Mithril 1.x

Created on 15 Mar 2017  路  10Comments  路  Source: MithrilJS/mithril.js

I'm creating a new application and would like to use Mithril 1.x, however, I have some doubts about the architecture.

Which of the following architectures would be most appropriate?

1-
/model
user.js



    var model = {
        getUsers: function() {
            return m.request...
        }
    }

/views
user.js


    var state = {
        users: []
    }

    var user = {
        oninit: function(vnode) {
            model.getUsers().then(function(users){
                state.users = users
            })
        },
        view: function(vnode) {
            return m("div", [
                state.users.map(function(user){
                    return m("p", user.name)
                })
            ])
        }
    }

2-
/model
user.js

    var model = {
        users: [],
        getUsers: function() {
            return m.request().then(function(users) {
                              model.users = users
                        })
        }
    }

/views
user.js

    var user = {
        oninit: function(vnode) {
            model.getUsers()
        },
        view: function(vnode) {
            return m("div", [
                model.users.map(function(user){
                    return m("p", user.name)
                })
            ])
        }
    }
Question

Most helpful comment

I'm a fan of 2. I have several apps in production which all use a global state object coupled with stateless components.

All 10 comments

I'm a fan of 2. I have several apps in production which all use a global state object coupled with stateless components.

Considering you can reuse the already fetched users in others components I would stay with 2.

I do 2 myself

I'd vote against both of them. In both 1 and 2 modelis a singleton. While component being a singleton is OK in a lot of situations, making model a singleton will make tests much more complex. You will have to mock server requests. Some tests will require one response, others will require another. You will have to modify parts of model in every tests you will write. This will inevitable cause problems.

Why not to pass the model instance via vnode.state?

While component being a singleton is OK in a lot of situations, making model a singleton will make tests much more complex

It really depends on what type of tests you want to write. A singleton model/state makes it very easy to write Acceptance Tests [1], which are really the critical tests for an end-user app. Unit Tests [1] are better for a deliverable library or app internals that has explicit API contracts that cannot regress. A singleton model makes Unit testing more challenging since there's less purity/isolation and more side-effects. All arguments I encounter seem to miss this distinction. As always, the answer depends on what you're building and for whom.

[1] http://softwaretestingfundamentals.com/acceptance-testing/

@chebum thank you for the reply!
I could not understand very well, could you give me an example?

@leeoniya good point. Did you mean that overriding model is basically simpler when it's a singleton? Why not to make it a factory ("virtual" function) that creates a model and injects it into components. It will be almost as easy to override for end-to-end tests while still allow writing unit tests. What do you think?

@marciomunhoz for tests you will need to override the model like that:

model.getUsers = function() {
    return [1,2,3];  //Fake collection to prevent server request
}

There are several problems with this approach when writing unit tests:

  • The fake collection we're returning here will change from test to test.
  • getUsers method may have important side effects that we will need to replicate in test overloads.
  • You may forget to restore the component state and thus break other tests in the suite. The same may happen due to the side effects of getUsers method.
  • There may be several singleton components which will make mocks even harder to write.

@marciomunhoz did this help? Please close it out if this isn't generating useful discussion.

@tivac ok! thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

volnei picture volnei  路  3Comments

barneycarroll picture barneycarroll  路  3Comments

omenking picture omenking  路  3Comments

StephanHoyer picture StephanHoyer  路  4Comments

mikejav picture mikejav  路  3Comments