I'd just like to get some clarification in the MVC pattern as to what belongs in Models, specifically the contents of the Models folder in MVC3, versus repositories and objects.
Right now, in my current MVC3 Solution, I have 4 projects:
A Project called "Objects", which holds information about all the core objects in my application.
A Project called "Data" which holds information information about the Data Context and repositories for each of the objects (created using MVC3 scaffolding)
The Web project, which holds the Controllers, Views, and -- the subject of this question -- Models
A Unit Testing project
What I really would like to get clarification about is the difference between what should go in the Objects project vs. what goes in the Models folder of the web project. Right now I'm only using the Models folder for holding what I'd call "View Models", which typically contain combinations of the core objects. Should the files in this folder only contain definitions defining the model contents, or should it contain other code that the controller may call?
I think that I have a pretty good understanding of both controllers and repositories, but sometimes I get confused as to whether certain code should go in one or the other. Are there any specific guidelines or limitations out there as to what absolutely should NOT go in a controller but should go in either a repository or a model instead?
Thanks as always.
We do something very similar except that the Objects and Data are combined in a Core library which is referenced by all projects. The models folder in the MVC project is strictly for View Models.
If your controller require additional classes, it really depends on what it needs as to where it goes. I will typically include a Helpers folder with subfolders for HtmlHelpers, Attributes and Filters. If it's a dependency that makes sense to exist outside the MVC project (common classes which are used across all projects) I'll add it to Core.
Related
I have a WP7 project, which will invoke a REST web service in Azure (MVC4 WebApi).
My WP7 project has models that it serializes to JSON and then sends to the web service.
The web service deserializes the data sent from WP7 and instantiates the models again before saving them to Azure Table Storage.
How can I share the Model classes between the projects? Right now I'm just copying the cs files over, and I have to update both sets if I make a change to the models. I was hoping a simple class library project would be able to be referenced from both projects, but WP7 couldn't handle that.
What should I do?
Thanks!
There are many solutions for this issue:
You could use a T4 template to read the entity and generate a class your WP7 project that only contains the properties of the object without reference to the Table Storage specifics (like TableStorageEntity): http://weblogs.asp.net/cibrax/archive/2009/03/11/code-generation-with-t4-an-entities-to-dto-example.aspx
You could split your entity over 2 files, one with the TableStorage specifics like TableStorageEntity and one file containing only the properties of the entity (use partial classes for this). Then you can add the file containing only the properties in your WP7 project as a link.
Create a DTO (or whatever you call it) class manually and use something like AutoMapper to map between the DTO and the TableStorage entity. Store the DTO in a portable library so it can be used by every kind of project. In my opinion this is the best solution since you don't want to completely expose your entities to "the outside world". An example would be a list of users. You wouldn't want to return all fields including password, hash... and other sensitive info. It would be better to have a separate class that only contains the info you want to expose externally.
I have been doing a lot of research on MVC and file structure. Mainly I've been looking at how to start a new layout. I have downloaded a few open source applications to take a look at file structure and how files are developed.
In the first application it was set up to use the standard way (at least the way it seems to me) of putting all the controllers, models and views each in their respective folders. This is the way that all the books say to do it.
In the second application, all folders are in a modules_core or modules folder where each controller (at least what I would assume to be controllers) are in a folder in there that contain three folders: controller, model, view.
Which of the two versions is accepted as standard and common practice? Are the two applications different because of versions of Codeigniter?
The standard of Code Igniter is to use those three folders:
Controllers
Models
Views
You can also create sub folders to better separate your files.
Searching a bit, I found that MyClientBase use something called codeigniter-modular-extensions-hmvc that is like a extension for CI.
Modular Extensions makes the CodeIgniter PHP framework modular.
Modules are groups of independent components, typically model,
controller and view, arranged in an application modules sub-directory,
that can be dropped into other CodeIgniter applications.
HMVC stands for Hierarchical Model View Controller.
I don't have experience with hmvc so I cannot tell you what is better. For the standard CI structure, try to separate well in sub-folders (controllers, views and models) related files and try to use helpers to better reuse your code when you need to use functions in more than one place.
I think MyClientBase (which seems to be far from the "standard" exemple), seems to be using HMVC more then MVC.
I've been reading and learning about Object-Oriented programming (Head First Object-Oriented Analysis and Design and Code Complete: A Practical Handbook of Software Construction – thanks to suggestions found on StackOverflow). I've also been learning how to use a couple PHP MVC frameworks (specifically Codeigniter and Kohana).
Some of the principals of Object-Oriented that I've read about are handled differently by the MVC frameworks. I think I've managed to understand the differences and why the decisions were made (complete and easy to use solution), but I wanted to test my assumptions...so if you'll humour me...please comment or correct.
Assumption #1:
Thinking about the right abstraction for a web application, the directory containing the library of classes should be located outside of the directory containing the presentation files. This organization adheres to the DRY ("Don't Repeat Yourself") principal allowing for multiple presentation folders (www.domain.com, management.domain.com, api.domain.com, etc.) to work with the same objects.
Assumption #2:
If all your classes are located outside of your presentation folders, then the models in your MVC implementation just use instances of those classes. If that's true, then the MVC framework is just a presentation class (the controller) that helps to manage the input (GET & POST requests), the response (models or instances) and output (views or templates).
Assumption #3:
If the MVC framework is just a presentation class, then the database class that the controller instance initializes breaks the abstraction of the controller class. A model (of the controller instance) shouldn't have a ("has a") database, it should have a thing (user, product) from the library of classes and that thing should have a database.
Assumption #4:
Furthermore, if the MVC framework is just a presentation class, the database class that the controller instance initializes is too tightly coupled with the controller class. Changing from one method of storage to another requires re-factoring of all the models.
Assumption #5:
With a HMVC framework, the issues with the controller containing the database is worse, because your models are more module (more models, more re-factoring).
UPDATE:
Sorry, I may have used the terms controller and model a little loosely...maybe that speaks to the tight coupling. The source of my confusion stems from the database class syntax.
With a model, shouldn't it be:
$user = new User($id);
$data['name'] = $user->getName();
$data['title'] = $user->getTitle();
return $data
Instead of:
$query = $this->db->get_where('user', array('id' => $id), 1, 0);
$row = $query->row_array();
$data['name'] = $row['name'];
$data['title'] = $row['title'];
return $data
Assumption #1: Thinking about the right abstraction for a web
application, the directory containing
the library of classes should be
located outside of the directory
containing the presentation files.
This organization adheres to the DRY
("Don't Repeat Yourself") principal
allowing for multiple presentation
folders (www.domain.com,
management.domain.com, api.domain.com,
etc.) to work with the same objects.
This is correct in the sense that libraries are not used for presentation (i.e. not views). They are modules that will be used across multiple controllers. Usually they should not use persistent data since they are not models but in some cases do (codeigniter sessions for example).
Assumption #2:
If all your classes are located
outside of your presentation folders,
then the models in your MVC
implementation just use instances of
those classes. If that's true, then
the MVC framework is just a
presentation class (the controller)
that helps to manage the input (GET &
POST requests), the response (models
or instances) and output (views or
templates).
This is a little confusing to me. You are correct the the controller is just used for orchestration of GET and POST request but becareful about calling then the "presentation class". the controller is responsible for the orchestration of models (persistent data) and views (presentation of data).
Assumption #3:
If the MVC framework is just a
presentation class, then the database
class that the controller instance
initializes breaks the abstraction of
the controller class. A model (of the
controller instance) shouldn't have a
("has a") database, it should have a
thing (user, product) from the library
of classes and that thing should have
a database.
This is very confusing and I don't really understand what you're saying here. MVC is a just a "presentation class", a model doesnt have a "database", the framework may hold a connection to a database and models are abstractions of the database (object like user, product).
Assumption #4:
Furthermore, if the MVC framework is
just a presentation class, the
database class that the controller
instance initializes is too tightly
coupled with the controller class.
Changing from one method of storage to
another requires re-factoring of all
the models.
The controller doesn't initialize the database, the framework usually handles controllers only access the abstraction of the database (models). If the database system is replaced by anything only the implementation of the models interface is re-factored.
Assumption #5:
With a HMVC framework, the issues with
the controller containing the database
is worse, because your models are more
module (more models, more
re-factoring).
HMVC doesn't necessarily mean more models. Using HMVC allows for portable modules from a project that can be access across multiple controllers. Often you will see Libraries doing this in non HMVC frameworks ie Library that doesn't some db/templating.
UPDATE: Just wanted to answer/comment on my confused question.
Kohana provides a Modules folder that addresses my earlier concerns.
For example, if you were to setup a domain, with a subdomain, using Plesk, the folder structure would be the following.
httpdocs
subdomains
+--management
+--httpdocs
If you want to share code between the domain and subdomain, using Kohana's modules, you could setup your file system like this:
modules
system
httpdocs
+--application
+--index.php
subdomains
+--management
+--httpdocs
+--application
+--index.php
Where httpdocs/index.php and subdomains/management/httpdocs/index.php has the following:
$application = 'application';
$modules = '/root/pathto/modules';
$system = '/root/pathto/system';
Any objects that are used in both the domain and the subdomain can be placed in the modules folder to be used by the application.
Hope that helps.
In MVC, do controllers belong with an application, or can they go into a shared library? For example:
//this is a shared library
LibShared
//these are two apps
appA ->LibShared
appB ->LibShared
Shouldn't each app implement its own MVC and use any shared libraries as perhaps part of the app's logical model or simply another library reference (utilities)?
Also, is there ever a situation in which an MVC Controller is stuck in a shared library? I thought Controllers needed specific views located in a specific app. Meaning, the Controller must go in that app?
Or can Controllers be generic (i.e. shared library)? Doesn't that mean they are no longer Controllers?
I would advise that you should only be separating out your controllers into their own module/package/library (herein referred to as modules) if you have a requirement to do so (i.e. immediate re-use). If no such requirement exists at present then I would defer the decision to when it is required, it sounds in your case you are about to unnecessarily over-engineer. It should in theory be possible to refactor later to a separate modules without much hindrance, however be careful regarding coupling, separating out to different modules doesn't reduce the coupling, look carefully at your dependencies at how much the controller is orientated to one style of view.
one liners answers to your question to your application is
YES, YOU CAN MOVE YOUR CONTROLLER TO A SEPARATE LIBRARY WITHOUT A SINGLE LINE CODE CHANGES.
I suppose any code can go anywhere, what would drive us to put something in a shared library or keep it with the app?
I would consider two things:
1). What's the rate of change? When we change the app overall is this likely to change.
2). Could anything else need to use it? If so when I realease a new version would the other client immediately
Typically a controller would be strongly associated with the application and hence not of much interest to any other app, and it's probably fundamental to the app changing as the app changes. Hence packaging with the app makes sense.
Now if the conroller is somehow more generic, perhaps configuration driven then shared library makes sense.
Controllers does not necessarily needs to be even in the same operating system. You could have a view in Windows, a Controller in Unix and your Model in a Sparc. Remember MVC is just a pattern, a way you could do something which is more robust and easier to modify.
Your controller could be a shared library. Does your controller should be aware of your views? Not necessarily. That depends on how you handle the communication between modules. On a good MVC implementation, modules simply interchange messages or events. So, a View send an event to the Controller, the Controller decides what to do and send a message back. The response of the controller could be something like "Show Window X". Be advised that "Window X" could be interpret by the View module, if the View is an a Web module, then the View just put the proper aspx page. If you have another view who happens to be a web application the renders Form X.
At least in CakePHP and in the architecture that Mike McShaffry explains in his Game Coding Complete book the controller does belong to the application.
However, in both cases the architecture is such that the application inherits the basic functionality of a model, view, and a controller from the framework.
Eg.:
// "super" controller of all applications using this framework
class Controller
// uses basic libraries that allows the inheriting applications to work minimally
class AppController extends Controller
// mainly uses the parent class's methods but can also substitute to using
// additional libraries
By framework here I mean the system that encapsulates the use of libraries. In CakePHP this encapsulation in turn is done by using libraries in the respecting models, views, and controllers. So neither of those components is free from attachment to libraries.
In Mike McShaffry's architecture however, only the controllers and views use libraries. So the models are left uncoupled and are thus highly portable to different applications.
I continue with a MVC Web App, and now I'm between the concepts of DRY (dont repeat yourself) and decoupling (be independent).
I divided my big Web Site in diferent projects within a Solution, and as you may already know in MVC the Validations are done in the Model or Service Layer, that in my case its in a diferent project than the one holding the App_GLobalResources, and here is the thing:
How can i access the GLobalResources from a different project, so I can access the strings to set the errors on the model in the service layer?
So far i created a new project like stand-alone resx files and complied them to set the reference to the DLL but it doesnt work, because the main resx files are internals or privates.
I tried one of those custom tools to make resx files public (cross assembly avaiblable) but it didn't work either, because it throws:
No matching culture found
The best aproach so far is to create a resx file just for the Model Project and it works good, but I'm repeating the same strings twice, one for the Views (to set the jQuery string validation errors on client side) and another one for the Model Validations (server side), these give me the benefit of decoupling, but what happen with DRY in this case?
Any advise or tips?
Well i have decided to follow two separetes resx (for strings), one for the Views & Controllers and another for the Model->Service layer, Im using a service layer for validation, so i isolate that layer, in that way i can reuse the layer "Service" or (BLL), in a way that i can reuse it later in somthing like a WPF app, with out any reference to the resx of the Views or Controller. SO decoupling won here ... =)