Models - an after thought?


#1

I recently discovered Astronomy (a package to set up models for you data). Just wondered if, having someone else developed a solution for this, if this is an afterthought i Meteor. For example, models provide one true source of state if you like. So, in Meteor we have client-side Mongo and React components, each of which have state, but there is no where to link the two so that either can reference a model to adjust and save in, or to read from it. Am I missing somehting or is this quite important to have?


#2

So far in the Meteor Guide we have taken a position that your server-side data should mostly be interacted with via plain objects and method calls, rather than with model-style calls where you set properties and then call save(). So it’s a pretty intentional choice, but it’s great that there is flexibility to use a model approach as well!


#3

I prefer the Astronomy model approach, that way my validations have one true source of truth.


#4

This is definatley a Sashko question… if you had one source of truth, which was updated via GraphQL then surely you wouldn’t need miniMongo (which essentially acts as a model container doesn’t it?).
Surely having this one source would also mean that Meteor could concentrate on observing only these for diffs rather than having a soupy mess of Tracker insertions (?)


#5

That’s right. Apollo doesn’t have minimongo and deals with only plain objects. But it would be pretty easy to build in model support if that’s something people need!


#6

Big fan of Astronomy! I can do cool stuff with it like if (x instanceof SomeAstroClass), not to mention transient fields which can be calculated upon the retrieval of a document. Event hooks, methods, etc…the list goes on.


#7

But who says that you can’t use models within your method calls? I’m using methods for adding or updating user input data and validating all data against my Astronomy model. The other way would be using SimpleSchema, but why should I use SimpleSchema for updating a database document while having a database model which represents the valid structure?


#8

I’ve implemented my own model classes, because this was before Astronomy was out. I’m also using EJSON to be able to pass these objects from client to server and back. In principle, I like this model approach, because custom methods and getters/setters can make your life easier in many cases and you can validate your data better. I also like the Astronomy concept.

But after a while, I also noticed a big drawback with this: Having model classes and passing those around between client and server typically means that you pass around a lot of unnecessary data. Let’s say, you’d just need a couple of properties of an object in a server method. If you pass the whole object, there’s quite an overhead involved, depending on the total number of properties. If you’ve got a broadband connection, this won’t matter. But on mobile devices it counts. Of course, you could also extract the properties you want from the object and only pass those to the server side. But in this case you somewhat lose the benefits of model classes.


#9

Yeah, I’m also not sending the whole model object, because this wouldn’t work with a plain Node app connected over DDP (because Astronomy is only available for Meteor). My methods expect a normal JSON oject and then I do something like this:

'posting.update': function(doc) {

updateDoc = _.pick(doc,['text','title']);

var post = Posting.findOne(doc.postingId);
    post.set(updateDoc);

if(post.validate()) {
   post.save();
 } else {
   //Throw validation error
 }

}

In my case this works fine and much simpler than with SimpleSchema.


#10

Yes, definately support for models.This should tie in nicely with the schema functionality that MDG had mentioned they were looking at.Use a schemas to create test data and to create models and to validate against (will have knock-on effect for Migrations though as well).


#11

Thanks for post.

What we did was create a model similar to Astronomy but using deep-diff (https://github.com/flitbit/diff).

Our challenge is that deeper fields can change (e.g. obj1.obj2.obj3[4]). Then our Model triggers an Event where one listener simply runs collection.update({id:model.id},{$set:{‘obj1.obj2.obj3.4’: value_from_event}})

This avoided sending huge chunks of data towards the MiniMongo pipe, just the exact field that changed.

That being said, not sure why Astronomy sends more data than expected if it’s using a similar diff algorithm.


#12

People from Java background would tell you that model approach has its pros and cons. I had written my share of these getters and setters and hate them with a passion. They provide no real encapsulation rather makes your classes cumbersome. I personally do not prefer model approach as it makes coding too verbose and tends to get on my nerves with all the getters and setters. People tend to start writing getters and setters even for simple things. I would rather validate against a schema and just go about without getters and setters. They are a pain as the project becomes big.


#13

The reason we use models is that we can trigger events based on minute state changes. So it’s not a data object, but a ‘reactive’ source for objects that depend on it to alter their behavior based on changes to its state.


#14

But that would mean that models has nothing to do with database or representing schema of your objects rather you are using it for state management. State management would become cumbersome with model based approach for a larger app. The reason being events are not just based on a single change in object but rather a combination of changes most of the time.

We use Redux for our state management as it really makes it simple to debug and reason with. As i said i would rather use plain JS objects and just use models to enforce a schema before i save it to database.


#15

The point of MVC is that the Model is used to control the View state. It’s not just data. How you go about it is up to you. This is not unsimilar to Redux, but Redux has a lot more under the hood.