2

In an MVC pattern, what is the best way to describe classes which aren't exactly models, but they work on models?

For example, I have an Order model which represents a customer's order in the system. I want to have a class called Orders which amongst other things, will store a collection of Order and perform functions on those. I don't believe this belongs in the Models folder as it isn't really a model.

Another example is that the user can import orders, so I would have an Import class which handles the import.

I don't believe these are helper classes or plugins so am not really sure where these go in terms of the folder structure.

Any help appreciated!

Edit: Just to describe the point of my Orders class- currently, each Order model has a validate() function which checks an external WMS for stock. This call is VERY expensive (an old FoxPro database) and when importing orders (in which you can import multiple orders at once), rather than having 1 call to the WMS for every order, I wanted to move this validate function 1 level higher so that I can have a single call to the WMS system to get the stock levels. That is why I was going to have a class called Orders. I agree that Orders is really just a collection of Order, however I am unsure where to put this method now. As Engineer Dollery pointed out, the relationship of orders is owned by the customer (a customer has many orders), however it doesn't right to me the the function belongs on the customer.

Lock
  • 5,422
  • 14
  • 66
  • 113
  • I would call them services – Zach Spencer Jan 16 '15 at 20:36
  • That's what I'm thinking too. Just read this post (http://stackoverflow.com/a/6216013/460043) and it sounds like a service layer is the go. – Lock Jan 16 '15 at 20:42
  • Calling them "services" or "helpers" or something else in the same vein is the first step into messing up your design by basically splattering business logic all over the application. You might want to read [this question](http://programmers.stackexchange.com/questions/218011/how-accurate-is-business-logic-should-be-in-a-service-not-in-a-model) and the accepted answer. – Jon Jan 16 '15 at 20:47
  • I've downvoted your question and voted to close it as 'unclear what you're asking'. Having read your comments below @Jon's answer it's now clear that you're not asking about design patterns, but about a specific php tool's implementation of something that, according to one of Jon's comments below isn't correctly implementing MVC. – Software Engineer Jan 16 '15 at 20:48
  • @EngineerDollery: I wouldn't go so far as to say "incorrectly implementing", and I am certainly not the authority on MVC. But it's true that people will look at Phalcon's `Model` and draw the wrong conclusions. – Jon Jan 16 '15 at 20:51
  • MVC is easy to be an authority on -- it's very simple -- commands are sent from the view to the controller, in response to user initiated actions, which coordinates changes to the model which fires events that are handled by the view and which may cause the display to change. It's not very easy to implement though, so it has almost become an antipattern in web-development. – Software Engineer Jan 16 '15 at 21:01

2 Answers2

2

You sound a little confused about what a 'model' is.

A model is usually thought of as the related set of objects that describe your business domain. In your case you have a customer that has orders -- it could be said that your model has a 1-many relationship between customer and order, and that the relationship itself is called 'Orders'. If you view things this way, then the methods you describe probably belong on the owner of the relationship -- in this case, customer.

You may also have a need to represent all the orders for your company, not just for one customer. You could achieve this through navigation (loop through all customers and retrieve all orders for the customer), or you could model it as your Company has a 1-many relationship with Order -- in this case, again, you would put the methods you're describing on the Company object.

If you think about it, only a customer, or your company, can view and change orders. If you have an external 'thing' doing something with the orders you should find out what that thing is and represent it in your model. Every read or write to your data should go through your model.

Edit

You mention that 'the user can import orders', and assuming that 'user' is synonymous with 'customer', then the import method should be on the customer interface.

Now, you talk in your edit about performance issues -- the validate method being very slow -- so you want to optimise it by validating many orders simultaneously. This is actually an implementation detail, not an interface detail (at least, not in your public interface).

You point out that you have an Orders object, which sounds ok to me, but this probably shouldn't be published via your customer interface (your user doesn't need to know about it). The Orders object should be the holder of the orders collection and it should belong to a customer (customer has orders) -- and the customer implementation should delegate the validate command to the Orders object which can optimize this any way it needs to.

This means that a customer doesn't know how to validate an order (which makes sense), but that Orders (your object) does. If it weren't for your performance constraint you could implement validate on orders in the simplest of ways (iterate through orders calling validate), however you do have the constraint so you'll probably have to build some sort of validation object populated with info from the collection of orders, pass it off to your validation service, and react to the response by setting a valid flag on the individual orders.

References

I'd take a look at the book, 'Implementing Domain Driven Design' by Vaughn Vernon, which can be found on amazon.

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
  • What a great answer. You've definitely helped me think about this differently in terms of the owner of the relationship. – Lock Jan 16 '15 at 21:01
  • Thanks. I've downvoted your question though because it has mixed theory with a concrete implementation that probably isn't really MVC (because mvc isn't really possible on the web without web-sockets). If you remove the 'phalcon' tag I'll happily remove my down/close vote. – Software Engineer Jan 16 '15 at 21:04
  • Thanks. I've removed that. – Lock Jan 16 '15 at 21:10
  • I've edited my post to describe in more detail why I want to have the `Orders` class. I actually already have those navigation properties in place (well Customer->Orders). – Lock Jan 16 '15 at 21:19
1

In an MVC context the classes you describe certainly sound like models.

Keep in mind that "models" as a term is not constrained to refer to single business objects. Anything that represents an operation implementing business logic (such as an Import) is also a model.

The situation with the Orders class is less clear because that sounds simply like a collection of orders and it isn't clear why the class itself would need to perform functions on the orders (vs. just allowing clients to enumerate the orders and perform the functions themselves). I would say that it's simply a not very appropriate example for this case.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • OK, so they would be models without an underlying table? The thing is, they don't really need any of the methods that inheriting from the `BaseModel` contain, so I am a bit wary of calling them models. – Lock Jan 16 '15 at 20:38
  • @Lock: What kind of methods? A `BaseModel` should be a super generic concept. – Jon Jan 16 '15 at 20:40
  • The methods that `\Phalcon\Mvc\Model` contain, such as `findFirst` etc. Basically functions in the Phalcon framework that are for Phalcon's ORM – Lock Jan 16 '15 at 20:41
  • @Lock: Not *all* your models should inherit from Phalcon's `Model`. IMO it's very unfortunate that Phalcon has chosen to equate its abstract model (and even its abstract model interface) with "something that maps to a single business entity". – Jon Jan 16 '15 at 20:46