I just read a blog post that explains MVC with a banking analogy. I have a few months of experience with web application development with an MVC framework (CakePHP), so I get the basics, but I began to see a theme that made me think I'm taking a flawed approach to where I put my logic:
Fat models, skinny controllers
Keep as much business logic in the models as possible
In my app, models are anorexic and controllers are obese. I have all business logic in the controllers and nothing besides associations and validation rules in the models.
Scanning through my controllers, I can now identify a lot of logic that should probably go in a model:
The app has lists, which contain items, and the items can be ranked. The sorting logic which puts the list in ranked order is in a controller.
Similarly, items (Item model) also have images (Image model). Each item may have a default image (designated by image_id in the items table). When an item is displayed with its images, the default image should appear first. I have the logic that does this in a controller.
When a list is displayed, related lists are displayed in the sidebar. The logic to determine which lists are related is in a controller.
Now to my questions:
With the examples I gave above, am I on the right track in thinking that those are instances of logic presently in a controller that belongs in a model?
What are some other areas of logic, common to web apps, that should go into models?
I'm sure identifying this problem and changing my design pattern is half the battle, but even if I decide to take those examples I gave above and try to move that logic to a model, I wouldn't know where to begin. Can anyone point me in the right direction by posting some code here, or linking to some good learning resources? CakePHP specific help would be great, but I'm sure anything MVC will suffice.
It's a bit tough to give you the "right" answers, since some of them deal with the specifics of the framework (regardless of the ones you are working with).
At least in terms of CakePHP:
Yes
Anything that deals with data or data manipulation should be in a model. In terms of CakePHP what about a simple find() method? ... If there is a chance that it will do something "special" (i.e. recall a specific set of 'condition'), which you might need elsewhere, that's a good excuse to wrap inside a model's method.
Unfortunately there is never an easy answer, and refactoring of the code is a natural process. Sometimes you just wake up an go: "holy macaroni... that should be in the model!" (well maybe you don't do that, but I have :))
I'm using at least these two 'tests' to check if my logic is in the right place:
1) If I write a unittest, is is easy to only create the one 'real' object to do the test on (= the object that you are using in production) and not include lots of others, except for maybe some value objects. Needing both an actual model object and an actual controller object to do a test could be a signal you need to move functionality.
2) Ask myself the question: what if I added another way to use these classes, would I need to duplicate functionality in a way that is nearly copy-paste? ... That's also probably a good reason to move that functionality.
also interesting: http://www.martinfowler.com/bliki/AnemicDomainModel.html
Related
I'm scratching the surface with Angularjs, and thought I'd run a conceptual question past the fine folks of SO. This is a newbie question from a seasoned developer.
The application has dashboard requirements... a single page that surfaces stuff from many parts of the application. Different user types get different dashboards. We already have a legacy back end, so the first task is to build the dashboard to show many bits from it's new RESTful service layer.
I'm wondering how I should conceptually think about the controllers needed to support this?
The first question is... should they be model-centric or view-centric? In other words, should they be "view-centric" controllers that have the word "Dashboard" in them? Or should they be more focused on the model elements they represent, like "Tasks", "Contacts", "Notifications". Or should there be both where the dashboard controllers work with model-centric controllers?
The next question is... what level of granularity should the controllers represent? If view-centric "Dashboards" controllers, should they be "ManagerDashboardController" and "WorkerDashboardController"? If model-centric controllers, should there be controllers such as "LateTasks" & "OnTimeTasks" since I need to display them on different sections of the dashboard, with slightly different data?
I'm looking for tangible advice based on real-world experience and/or references to great links I've yet to find.
Here are my views from developing business applications in Angular for the past 6 months:
Role of a Controller
Initialization (loading initial data, setting options)
Exposing variables and functions to the template through the $scope
Application flow (through exposure of functions that can change state, or $watches)
I have found that, much like in traditional MVC frameworks, the controllers in an Angular app should really be super slim. Little if any business logic should be in the controllers, and should be instead be encapsulated in your models. I came to this conclusion after hearing the follow line from a presentation by Miško Hevery: "the purpose of the scope is to refer to the model and not be the model." That was the most valuable and enlightening line I got from that presentation (though I recommend to watch the whole video); that line directly resulted in me slimming down my controllers by almost 50%-70%.
For example, my company has a concept of an Order. I created a model that encapsulated all the properties of this business object, as well as its behaviours and injected them into the controllers. One business rule we had was the ability to add a Booking (another business object) to the Order. Originally in my controller, I had a $scope.addBooking function that first created a new Booking, then took the order and did a $scope.order.bookings.push(newBooking). Instead, I moved this business logic (addBooking function) directly into my Order model, and in the template I could then do something like <button ng-click="order.addBooking()">Add Booking</button> without adding a single line of code into my controller.
A lot of the code I put in my controllers when I was first starting off with angular, I found could be stripped out and placed either in my models, directives, or services (mostly the first two in my case). The remainder of the code left in my controllers almost all fell into one of the above 3 roles I listed above. It was either initialization code (e.g. firing an AJAX request to fetch data of the relevant business objects), scope assignment of objects, or scope assignment of functions that dealt with application flow (e.g. $scope.save or $scope.cancel that might send you back to a different page).
Should controllers be model-centric or view-centric?
This is an interesting question, one that I haven't thought about before. When I hear view-centric, I think of a controller that deals primarily with the view and how things are displayed. I feel there shouldn't be any controllers that are purely view-centric, the reason being it seems a view-centric controller can probably be transformed into a directive. You mentioned view-centric controllers as being like a Dashboard controller, which sounds like something that could definitely be made into a generic directive. Your directives should encapsulate most of your view logic, while your controllers focus on simply exposing your models to the view for consumption (back to the role of the controller). This has me thinking that controllers should more often be model-centric.
I think really the only conclusion I can come to is if a controller starts becoming too view-centric (with many variables and functions that deal primarily with the view and UI behaviour) then that is a sign that parts of your controller can be pulled out into a directive, making your controller slimmer.
This is very subjective but here is my answer to your questions
should controllers be model-centric or view-centric?
It depends (as always), I always try to have small controllers for the different parts of the page.
Some parts of the page are very view-centric (typically the ones that are shared among the different views). I usually have a menuCtrl, a headerCtrl and footerCtrl. This ctrls are very coupled to those parts of the page so a make them view-centric.
The other parts of the view, the ones that are business related are much more coupled to the business rules and in extension to the model so I make those ctrls model-centric. On an account´s business app, I would probably have an accountCtrl, an ownerCtrl, and so on. By doing so I can reuse them on different views if needed (and are much easier to test)
what level of granularity should the controllers represent?
The smallest as possible. Try to have small controllers that prepare the model for different parts of the page. If you have a big controller it will be hard to test, maintain and you will probably be forced to duplicate code on different parts of your application.
advices and recomentations with controllers
Keep them small.
Avoid DOM manipulation inside of them (use directives instead).
Use the controllers just to prepare the model. whenever possible delegate all the logic of your app to services. If you do so, it won´t really matter that much if your controller is view-centric or model-centric.
As I said before this is a very subjective matter and I´m sure many people will disagree with me.
I hope this could help you.
Basic Idea
So I'm actually in the process of migrating a legacy code base over to a restful based web service architecture utilizing AngularJs
Controllers are responsible for managing the data that is consumed by the view aka the webpage. My personal preference is that there is a one to one relationship between the controller and the view that it is serving. So, based on the question, Angular controllers should be more view centric. I'm sure that there are plenty of people who will disagree with me though.
If you are worried about the extensibility of this pattern, you should place your business logic and data access within Angular Services as described here. This offers you a tremendous amount of reuse of business logic operations as well as unit testability.
TLDR;
The specifications for Angular are changing all the time and with each new version there will be a new standard. A more view centric architecture looks appropriate for this application.
For some more complete reading on the subject I recommend checking out:
3 Tips To Building Enterprise Grade Angular/Node Applications
Lessons Learned: A Year with a Large AngularJS Project
Should methods that manipulate the Model class members be implemented in the Model or in the Controller? Does it depend on how "heavy" this manipulation is ?
By "manipulation" I mean:
get a class member
make a long calculation based upon this class member
return another value which relates to this class
For example, a Board class which hold a cell matrix member.
Now I want to implement a method which returns all the surrounding cells according to specific cell location.
Is the model or view responsible to for implementing the above ?
If this question belongs to another Stack Exchange QA site I will welcome the recommendation to move my post to that site.
Keep your controllers thin, don't let them do much, this aligns with the Single Responsibility Principle in SOLID for Object Oriented Design. If you have fat controllers, they become hard to test and maintain.
As for the models, I used to have dumb models before that did nothing but to map to database tables and that was inspired by most of the sample applications that you see on the web, but now I don't do that.
I (try to) follow the principles from Domain Driven Design, where models (entities in DDD terms) are at the center of the application, they are expected to encapsulate behaviour related to the entity, they are smart models (so yes, the logic related to an object will live with it in that case). DDD is a much bigger topic and it is not related directly to MVC, but the principles behind it helps you better design your applications, there is a lot of materials and sample apps available if you google DDD.
Additionally, Ruby On Rails community - which seems to inspire most of MVC frameworks - also seems to have a hype around having Fat Models and Skinny Controllers.
On top of that, you can add View Models to your mix which I find helpful. In this case, you can have a ViewModel to represent a dumb subset of your model(s) just to use for generating the view, it makes your life easier and further separate your Views from your Models so that they don't affect your design decisions unnecessarily.
What you call "model" is are actually domain objects. The actual model in MVC is just a layer, not concrete thing.
In your particular example, the Board should have a method that returns this list. I assume, that you are actually acquiring it because you then need to do further interaction with those cells.
This is where the services within the model layer comes in to play. If you use them, they are the outer part of model layer and contain the application logic - interaction between different domain objects and the interaction between the persistence (usually either data mappers or units of work) and domain objects.
Let's say you are making a game, and you and player performs and AoE attack. Controller takes a hold of service, which is responsible for this functionality and sends a command: this player aimed AoE in this direction, perform it.
Service instantiates Board and asks for surrounding cells of the target location. Then it performs "damage" on every cell in the collection that it acquired. After the logic is done, it tell the Unit of Work instance to commit all the changes, that happened on the Board.
Controller does not care about the details of what service does. And it should not receive any feedback. When execution gets to the view, it request from model layer the latest changes and modifies the UI. As the added benefit - services let you stop the business logic from leaking in the presentation layer (mostly made up from views an controllers).
The domain object should contain only methods, that deal with their state.
I think this has little to do with MVC, and a lot more to do with regular software engineering.
I personally wouldn't hesitate to stick trivial calculations in a model, but would be extremely wary of fat models.
Now, the fact that MVC stands for Model View Controller doesn't necessarily mean that everything should be either a view, a model or a controller. If you feel the need to move responsibilities to a separate class that doesn't really qualify as an M, a V or a C, I don't see why you shouldn't do it.
The way you implement it is up to you. You could either use this separate class as a "top level" (for lack of a better term) object, or make a method of the model delegate to it, so as to hide the fact that you're using it. I would probably go for the latter.
Everything is debatable, though. Everybody and their sister seem to have a different opinion on how to do MVC right.
Me, I just consider it a guideline. Sure, it's a great idea because it leads you to a better separation of concern, but in the end—as it always happens—there's no one-size-fits-all way to apply it, and you should not be overly constrained by it, to the point where everything has to be either a view, a model or a controller.
As per best practice we should use properties for Calculated fields with get access only. example public double TotalCost {
get
{
return this.Role.Cost * TotalHour;
}
}
I have another programmer who I'm trying to explain why it is that a UI component should not also be a data-structure.
For instance say that you get a data-structure that contains a record-set from the "database", and you wish to display that record-set in a UI component within your application.
According to this programmer (who will remain nameless, he's young and I'm teaching him...), we should subclass the data-structure into a class that will draw the UI component within our application!!!!!!
And thus according to this logic, the record-set should manage the drawing of the UI.
******Head Desk*****
I know that asking a record-set to draw itself is wrong, because, if you wish to render the same data-structure on more than one type of component on your UI, you are going to have a real mess on your hands; you'll need to extend yet another class for each and every UI component that you render from the base-class of your record-set;
I am well aware of the "cleanliness" of the of the MVC pattern (and by that what I really mean is you don't confuse your data (the Model) with your UI (the view) or the actions that take place on the data (the Controller more or less...okay not really the API should really handle that...and the Controller should just make as few calls to it as it can, telling it which view to render)) But it's certainly alot cleaner than using data-structures to render UI components!
Is there any other advice I could send his way other than the example above? I understand that when you first learn OOP you go through "a stage" where you where just want to extend everything.
Followed by a stage when you think that Design Patterns are the solution every single problem...which isn't entirely correct either...thanks Jeff.
Is there a way that I can gently nudge this kid in the right direction? Do you have any more examples that might help explain my point to him?
Have you heard of Martin Fowler?
Separating User Interface
Code
Anyway, if he wants to go further in that direction of adding render methods to his data controls, have him look at "loose coupling". It's okay to create some generic type of interface that gets him halfway there, but the UI component should take it the rest of the way.
This boils down to functional vs. non-functional responsibilities. What the data structure does and how it's visualized are two completely separate things -- essentially the root of the MVC pattern.
There's also a notion of circular dependencies here. Since the UI must know about the data structures, if you allow the data structures to then depend on the UI, you've got yourself a nice little ball of mud.
Generally on the point of decoupling:
Not only can there be different components of the UI rendering the same data structure. You may even have completely different UIs (Web, Desktop Application, ...) Now of course, you could subclass Person with WebPerson and DesktopPerson (this already sounds wrong, doesn't it? The naming is simply not about the kind of Person - it's about something else).
Each UI could work on different kinds of Persons, e.g. Teacher and Student. So we get WebPerson, WebTeacher, WebStudent, DesktopPerson, DesktopTeacher and DesktopStudent.
Now let's say, WebPerson defines the method "drawAddressFields()" to draw a web version of the address fields. But since WebTeacher has to derive from Teacher to use the additional data field "salary" (and let's assume single inheritance), it must implement "drawAddressFields()" once again!
So maybe the argument of "this will cause much more work" will help to create some motivation :-)
BTW, it will automatically lead to creating some delegate that implements the code of drawAddressField(), which will then evolve to creating a component that does the drawing separately from the data structure.
I am writing a GUI based application where I read a string of values from serial port every few seconds and I need to display most of the values in some type graphical indicator(I was thinking of QprogressBar maybe) that displays the range and the value. Some of the other data that I am parsing from the string are the date and fault codes. Also, the data is hierarchical.
I wanted to use the model/view architecture of Qt because I have been interested in MVC stuff for a while but have never quite wrapped my brain around how to implement it very well.
As of now, I have subclassed QAbstractItemModel and in the model I read the serial port and wrap the items parsed from the string in a Tree data structure. I can view all of the data in a QtreeView with no issues.
I have also began to subclass QAbstractItemView to build my custom view with all of the Graphical Indicators and such. This is where I am getting stuck. It seems to me that in order for me to design a view that knows how to display my custom model the view needs to know exactly how all of the data in the model is organized. Doesn't that defeat the purpose of Model/View? The QTreeView I tested the model with is basically just displaying the model as it is setup in the Tree structure but I don't want to do that because the data is not all of the same type. Is the type of data or the way you would like to present it to the user a determining factor in whether or not you should use this architecture? I always assumed it was just always better to design in an MVC style.
It seems to me like it might have been better to just subclass QWidget and then read in from the serial port and update all of subwidgets(graphical indicators, labels, etc...) from the subclass. Essentially, do everything in one class.
Does anybody understand this issue that can explain to me either what I am missing or why I shouldn't be doing it this way. As of now I am a little confused.
Thanks so much for any help!
** ** - Is this a situation where Qt Model/View architecture is not useful?
I"m going to say not necessarily - end edit
I'm not sure I fully understand your question, but let me try.
First, let's talk about MVC display pattern. This pattern is all about breaking the program into separate (and hopefully testable) sections that have their own areas of concerns.
The model is data structures that describe your data. I'm sure that there is some statistical data is also present. It is important that the model not know anything about how the data is going to be displayed to the user.
The View is how information is presented to user. It is not suppose to care about how the data is presented for displaying. It is important for this layer to be unaware of how the model gets the data for display.
The control logic is the "glue" to connects the first two items together. This is the layer that holds all the "messy" stuff to make to good user experience. EDIT - Most of what QT calls a "view item" I would probably put in the controller layer.
But if you do this, then the model and controller layers become very testable.
With that being said, many of your points are not really related to MVC pattern. You seem to be discussing what is the optimum way to display the data. This is always a problem. And without seeing your app, I'm not really going to try to tell you what is going to look good.
But by following good MVC pattern design, you can make pretty significant revision to the display without effecting the underling code.
This being said, I'm dealing with this exact issue right now and this pattern is working well form me. If you go to codeplex.com and search for mvvm (model-view-viewmodel, term used in WPF), you will see a number of projects that use it that you can use to get more information.
If this is not enough, let me know and I may be able to give you a better answer.
Question number three in my quest to properly understand MVC before I implement it:
I have two cases in mind:
The primary application
window needs to launch the
preferences window. (One View
invoking another View.)
The primary Model for an application
needs to access a property
in the preferences Model. (One Model
accessing another Model.)
These questions are related in that they both involve communication across Model-View-Controller triplets, a topic that I haven't found much discussion of in my Googling.
The obvious way to fix this is to wrap everything in a top-level "application" object that handles transactions between Models and allows Controllers to invoke one another's methods. I have seen this implemented, but I'm not convinced its a good idea. I can also see possibilities involving Controllers observing more than one Model and responding to more than one View, but this seems like its going to become very cluttered and difficult to follow.
Suggestions on how best to implement this sort of cross-talk? I feel like its a very obvious question, but I've been unable to find a well-documented solution.
On a broader note, if anyone has a link that shows typical approaches to these sorts of MVC issues, I would love to see it. I haven't had much luck finding solid, non-trivial references. Examples in Python would be lovely, but I'll gladly read anything.
Edit 1:
I see some pretty interesting things being said below and in general no-one seems to have a problem with the approach I've described. It is already almost a lazy form of the FrontController design that Vincent is describing. I certainly don't foresee any problems in implementing that pattern, however, it doesn't seem that anyone has really addressed the question in regards to communication amongst Models. All the answers seem to be addressing communication among objects in a single Model. I'm more interested in maintaining separate Models for separate components of the application, so that I'm not stuffing fifty state properties into a single Model class. Should I be maintaining them as sub-Models instead?
With respect to (1), views don't invoke other views. They invoke controller actions that may result in other views being rendered. In your case, the primary application window contains a user interface element (button, link) that invokes a controller action to display the preferences window.
With respect to (3), model components certainly could be related to one another. This isn't unexpected nor to be avoided, necessarily. For instance your Customer model may have an associated set of Orders. It would be perfectly natural to access the customer's orders via a method in the Customer class.
You might want to take a look at the MVC page on wikipedia for an overview.
You may want to consider looking up the Front Controller design pattern.
The Front Controller pattern defines a single component that is responsible for processing application requests. A front controller centralizes functions such as view selection, security, and templating, and applies them consistently across all pages or views. Consequently, when the behavior of these functions need to change, only a small part of the application needs to be changed: the controller and its helper classes.
This way all requests from the view goes to the FrontController who then decides which specific action (controller) to invoke. Sometimes, it could forward straight to another view as in your first case.
There is no problem with multiple objects in the model talking to each other. In fact that will be very common. The way I see it, all the objects in the Model act like one component to represent the data and operations on the data.
This article might help. And this one.
Model does not mean a single model object. The model is the subset of the entirety of your domain model which is directly related to the controller actions and the views in question.