I have a doubt with the implementation of the model and can not find a reasonable explanation for the problem.
I'll give you an example I'm working, it is an MVC implementing a blog.
I am ControllerPost which is responsible for control of reading a particular post Blog
consequently have the ModelPost
the ModelPost must contain all methods needed?
method getPost()
method getComment()
method getArchive()
or should I isolate the methods?
ModelPost
method getPost()
ModelComment
method getComment()
ModelArchive
method getArchive()
this causes me much confusion, I see examples but no proper explanation.
I hope that was clear in my doubts, otherwise try to be more explanatory
Thank all
In most projects I've worked on, we've had a model class for a database table.
Using mostly Zend MVC, that would mean extending the Zend_Db_Table classes for each entity.
So in your case, if the comment, post and archive are different tables (which I suppose they are), I'd build separate classes with get, update, insert and delete (and other similar) methods.
This might steer a bit off topic, but I suggest you look into domain driven development (DDD):
There are links to some good reading material here: Domain-driven design with Zend
Also give this a read:
http://phpmaster.com/building-a-domain-model/
http://phpmaster.com/integrating-the-data-mappers/
http://phpmaster.com/an-introduction-to-services/
The main thing about the DDD is that it switches your mindset from thinking about database tables, more towards thinking about the main logical parts of your application, and then slowly adding a persistence layer below it and the application and service layers above it.
Related
So I have been reading through From Apprentice to Artisan by Taylor Otwell, Laravel Author
And I came across this 'mantra' : HMVC usually indicates poor design.
Which is kind of true...
Also Taylor has suggested
Feel the need to call controllers from other controllers? This is often indicative of poor
application design and too much business logic in your controllers. Extract the logic into a
third class that can be injected into any controller.
And I don't seem to find such way yet..
How can I avoid HMVC and extract the logici nto a third class that can be injected to any controller?
I came up with a neat way to do it, and it seems to have helped me speed up my workflow...
I think this alternative I made can replace HMVC, as well as the conventional way of using controllers... as now controllers are but somehwere where our -what I called- 'motors' are injected.
Check out my article at coderwall where I went through the whole thing.
Read through it, and hopefully it will provide a better way of doing things, starting from the models to and finishing at controllers.
However if you wish to proceed your own way, make sure what was required to be shared between two controllters hiarchecly gets shared in a more neater way, as taylor suggested, shared through injection.
For instance, you are in AdminsController and you feel the need to call an action from UsersController, just make that action and its siblings into a third class, and in your AdminsController
//AdminsController
use ThirdClass;
public function __construct(ThirdClass $mything)
{
$this->myThirdClass = $mything;
}
public function mySharedAction()
{
$this->myThirdClass->mySharedActionFromUsersController();
}
And like so.
Update
If you have gone through my article at coderwall, the one I have mentioned above, I have made a little package that generates all of the mentioned components in there.
Check it out at github
Separation of Concerns or Single Responsibility Principle
The majority of the questions in the dropdown list of questions that "may already have your answer" only explain "theory" and are not concrete examples that answer my simple question.
What I'm trying to accomplish
I have a class named GuestbookEntry that maps to the properties that are in the database table named "guestbook". Very simple!
Originally, I had a static method named getActiveEntries() that retrieved an array of all GuestbookEntry objects that had entries in the database. Then while learning how to properly design php classes, I learned two things:
Static methods are not desirable.
Separation of Concerns
My question:
Dealing with Separation of Concerns, if the GuestbookEntry class should only be responsible for managing single guestbook entries then where should this getActiveEntries() method go? I want to learn the absolute proper way to do this.
I guess there are actually two items in the question:
As #duskwuff points out, there is nothing wrong with static methods per-se; if you know their caveats (e.g. "Late Static Binding") and limitations, they are just another tool to work with. However, the way you model the interaction with the DB does have an impact on separation of concerns and, for example, unit testing.
For different reasons there is no "absolute proper way" of doing persistence. One of the reasons is that each way of tackling it has different tradeoffs; which one is better for you project is hard to tell. The other important reason is that languages evolve, so a new language feature can improve the way frameworks handle things. So, instead of looking for the perfect way of doing it you may want to consider different ways of approaching OO persistence assuming that you want so use a relational database:
Use the Active Record pattern. What you have done so far looks like is in the Active Record style, so you may find it natural. The active record has the advantage of being simple to grasp, but tends to be tightly coupled with the DB (of course this depends on the implementation). This is bad from the separation of concerns view and may complicate testing.
Use an ORM (like Doctrine or Propel). In this case most of the hard work is done by the framework (BD mapping, foreign keys, cascade deletes, some standard queries, etc.), but you must adapt to the framework rules (e.g. I recall having a lot of problems with the way Doctrine 1 handled hierarchies in a project. AFAIK this things are solved in Doctrine 2).
Roll your own framework to suite your project needs and your programming style. This is clearly a time consuming task, but you learn a lot.
As a general rule of thumb I try to keep my domain models as independent as possible from things like DB, mainly because of unit tests. Unit tests should be running all the time while you are programming and thus they should run fast (I always keep a terminal open while I program and I'm constantly switching to it to run the whole suite after applying changes). If you have to interact with the DB then your tests will become slow (any mid-sized system will have 100 or 200 test methods, so the methods should run in the order of milliseconds to be useful).
Finally, there are different techniques to cope with objects that communicate with DBs (e.g. mock objects), but a good advise is to always have a layer between your domain model and the DB. This will make your model more flexible to changes and easier to test.
EDIT: I forgot to mention the DAO approach, also stated in #MikeSW answer.
HTH
Stop second-guessing yourself. A static method getActiveEntries() is a perfectly reasonable way to solve this problem.
The "enterprisey" solution that you're looking for would probably involve something along the lines of creating a GuestbookEntryFactory object, configuring it to fetch active entries, and executing it. This is silly. Static methods are a tool, and this is an entirely appropriate job for them.
GetActiveEntries should be a method of a repository/DAO which will return an array of GuestBookEntry. That repository of course can implement an interface so here you have easy testing.
I disagree in using a static method for this, as it's clearly a persistence access issue. The GuestBookEntry should care only about the 'business' functionality and never about db. That's why it's useful to use a repository, that object will bridge the business layer to the db layer.
Edit My php's rusty but you get the idea.
public interface IRetrieveEntries
{
function GetActiveEntries();
}
public class EntriesRepository implements IRetrieveEntries
{
private $_db;
function __constructor($db)
{
$this->_db=$db;
}
function GetActiveEntries()
{
/* use $db to retreive the actual entries
You can use an ORM, PDO whatever you want
*/
//return entries;
}
}
You'll pass the interface around everywhere you need to access the functionality i.e you don't couple the code to the actual repository. You will use it for unit testing as well. The point is that you encapsulate the real data access in the GetActiveEntries method, the rest of the app won't know about the database.
About repository pattern you can read some tutorials I've wrote (ignore the C# used, the concepts are valid in any language)
Shouldn't models just describe data that will be passed from a controller to a view? Doesn't that make models unnecessary in weakly typed languages? In PHP, they are doing DB work in models, but isn't that wrong? As I see it, models are just unnecessary in weakly typed languages...
There are some misconceptions about the term model. Microsoft's MVC3 framework has the concept of a view-model, which is simply the data you use to render your views. This isn't however what the M stands for exactly in MVC. The model includes your business entities. We have thin controllers and fat models, but very thin view models. Our controllers make calls to services that perform business logic, and the controllers never do this logic themselves. We then translate our business entities (our data models) and convert them into a lightweight view model, which can be used for rendering a view.
So to answer your question
Shouldn't model just describe data that will be passed from controller to view?
Then perhaps what you are really asking is aren't view-models unnecessary? I'm not sure why you think this. View model + view makes the result. In PHP it can be helpful to define a class with easily accessible properties on it. This is just sensible for clarifying your expectations and prevents you from calling methods with hideously long sets or arguments. In JavaScript there is no need to define a view model as such, you just push the properties onto a new object and pass it along with your view to your view rendering logic. This is more a reflection of the OO pattern these languages use and not the fact that they are weakly typed.
If you are asking if model is unnecessary, then you have missed the purpose of the MVC architecture. A big part of MVC is that you separate your concerns. Why apply any architecture to your code? I am sure you can find a better explanation of the motivation behind MVC than I can give you.
A model is a useful conceptual tool, even if it's not strictly necessary in PHP to separate it from the DB code e.g. you can have a data object associated with each table that encapsulates some business logic, or define a set of business entities that aggregate the data across tables into domain-specific objects that the controllers can then use, or just have one monster DB object that has all the access functions and returns the entities. This has definite advantages over having DB code directly in use by the controllers:
If you are defining complex data structures that run across DB tables, you don't want to do that in controller code due to the risk of duplication - far better to have a single definition that enforces consistency across the system. Although this can introduce dependencies, having one function/object that defines that data makes it easy to find out where the data is used so you can fix things.
Third party maintenance is far easier if there's one place to go to where all the data structure definitions are found.
It makes unit testing easier if you can swap out the whole model or parts of it and replace it with mock object(s) that will provide test data
It makes controllers lighter and therefore more readable and maintainable
So you could argue that it's not necessary, but it helps a lot.
I've always seen models as a tool to provide data. That means that your controller doesn't ever have to worry about the data source, and if you want to switch from using a database to XML files then you only have to swap out your model.
So long as you have some data provider abstraction. Some Models will do low level validation (tightly coupled to the storage engine - null checks etc) but the controller "should" do all of the business logic/validation.
I personally have a thin struct like class that is mapped to each table (all implementing IDataStruct). This struct, or a collection thereof, is the only thing that moves between the DomainObject and the DataProvider. I can then enforce via my interface what datastruct I should be receiving. This is not a silver bullet but I have found it to work well (Makes things like caching and unit testing quite easy)
I hope this hasn't confused the issue.
In my application design, I usually map objects to the important tables in the database. The objects then handle everything relating to that data (including linkage tables). So I for example have built an Activity object, with properties like name and due_date, methods like load() and save(), and also methods like getParent(), getContributors() and getTeam(), which return (arrays of) other objects. Is this 'bad' OOP because it violates the Single Responsibility Principle?
It depends on the situation and the exact code you have: Your design might touch multiple responsibilities and still be a pretty nice OOP and maintainable.
Do you handle load() and save() in each class with similar code? Or do you delegate the task within load() and save() to other objects that are used for this functionality in several classes? That would be half-what following SRP and still be according to your design.
If not, your code really seems a bit smelly. To check whether it covers multiple responsibilities, ask yourself: what could cause changes to my class? In your situation, I would at least try to refactor the similar code in load() and save() in different classes to reach the situation described above, so that
maintainability is greatly improved,
you still do not need to change your clients' code.
Well .. its hard to tell at this stage. You could pastbin the whole class , but ..
Yes , it looks like bad OOP. You have same class responsible for interaction with database and domain logic. This creates two, completely different reasons for class to change.
You might benefit from exploring DataMapper pattern.
Maybe I'll just kick in the dark with this (cause I'm not an expert) but:
Methods load() and save() inside domain objects is called Active Record (Another description). This is not bad (altough I dislike it) because people that will maybe work after or with you will have less problems figuring out how to persist those objects.
About other methods. It's not that bad if it's in objects domain and it represents objects behaviour. If designed well it can be very good. Domain driven design encourages using rich domain model which is opposite of anemic domain model. An anemic domain model has domain objects that only have properties and getters and setters. So as long as it's in domain of your object, putting additional methods in it is not considered bad.
This is as far as I understand those concept from the books and articles I've read..
Hope it helps..
What you describe is an ActiveRecord and it's well known that it violates SRP. Also, ActiveRecord only works well when the table rows match the object closely. Once Impedance Mismatch gets too big, it will make changes to the system more difficult later.
It's not necessarily bad OOP, but it is a form of Technical Debt because of the lack of separation between persistence logic and domain logic. Violating any of the SOLID principles will usually lead to hard to change code, fragile code, non-reusable code.
A few of those debts are not an issue. It's when those debt accumulate interest, e.g. when they start to ripple into other design decisions. In other words, when you notice that it gets more difficult to change the system, try to pay back some debts, e.g. refactor to a more maintainable solution.
I think it's important to stop thinking that Model should be only layer between logic and database. Model can work with database and with other models, all logic should be in Models.
I think there is two ways:
your Model could return array of ID's in getContributors() method, and you could create new object (Factory maybe), which will convert these ID's to objects.
your Model could return array of objects, but without using new keyword, but through the Factory or Dependencies Container (I prefer DC).
I am currently working on a little application:
The structure follows in some way the MVC pattern.
For short it has the basic things, Models, Controllers etc.
Now I am sitting here and do not know whether :
1.
The SQL database is only managed by a model through methods the programmer gives him like: "Hey we have name record so we need a getName() method".
OR
2.
The model dynamically creates the whole database and methods, using a XML file, with which even a non-programmer can design a database.
And should the model class check every/a single request whether it is a valid request e.g. getName() won't work on the houses_tbl, and if it is not valid it does not perform the query, and sends back an error message instead?
I have absolutely no idea how to handle my model class, which structure it should follow and how much the programmer should have to put into a new model so it works as he wants it to work.
Major points:
perfomance (which way saves the most perfomance)
KISS (which way is simple enough, so a second team mate can understand my logic)
extendability (can I extend the structure)
Check these Data Source Architectural Patterns: Table Data Gateway, Row Data Gateway, Active Record, Data Mapper. For code examples to these patterns in PHP, you could check Zend_DB_*.
Which pattern you should pick depends on your application. If you are doing a simple CRUD application, you might want to use Row Data Gateway. If you are building an application with a lot of business logic from a certain domain, you will likely pick a different one.
Just remember that the M in MVC is not just the Persistence layer. The model is the heart of your application. Controller and View are just an end to your application. Further reading by Rob Allen and Matthew Weier O'Phinney.
As for your major points, I suggest to just stick to general established practises. UnitTest your code, write meaningful code and document it, favor aggregation over composition, capsule and separate concerns, code against an interface, refactor, etc.
Why not statically create the objects etc. during development from the database. i.e. use some Object-Relational-Mapping ?
That way you create your Person object from (say) the database schema. It creates a getName() accessor, and the rest of your code compiles against that. If you remove/rename the name field, then the generated code changes and consequently stuff doesn't compile. Catching these errors early will save a lot of grief.
This question details some PHP/ORM options. I confess I've not checked these to see if they're entirely what you want, but hopefully they should point you in the right direction.