I have a conceptual question, what is the best way to gather information from various models and treat them in different ways in order to return an array with the requested data, without using a "god" method?
I'll summarize the example I'm trying:
View "Payroll" is characterized by a html table that shows information of an employee, for example: base salary, every discount of the month (from the Payments table) as well as commissions from another table, so in Controller I just do $this->set($employee_info, $this->Employee->getInfo());
This method is responsible for gathering information from models that are not even related to him in some way (e.g.: Configuration Model) and at the end it returns the array required, the question is: what the best way to separate these responsibilities?
This method is responsible for gathering information from models that
are not even related to him in some way
You won't get around to call several models in this case in what you call a "god" method. The only way to get around that is to associate the data.
I would create three methods, one that fetches the data from all models, one that creates the data structure you want from that data and one that calls the two others and returns the data. I don't see a better way to separate that without having the data associated.
Related
I have an application that has only two tables: products and type - where each product can have multiple types as attributes. I decided to normalize the database and created another table where I intend to keep the relations between the products and types.
(Disclaimer: I'm relatively new to object oriented programming). I have a class for products, and a class for types. I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes? If so - what is the best way of dealing with this - should I somehow call both other classes in this third class, or keep it an independent class, and just manage the exchange of information through actual forms on the webpage, etc?
If your product_types table only holds foreign keys there is no need to map it to its own class. Since this is defining a many to many relationship between the tables you can just provide a method in your product class to get the types.
getTypes() {
// retrieve the types for this product and return
}
Then add the opposite method in the types object to get the products.
getProducts() {
// retrieve the products for this type and return
}
I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes?
Usually when you're designing a database, the first thing you need to do is create a conceptual data model. This will allow you do define your entities as well as defining relationships between them. Then you create a logical data model to characterize and refine your entities. The last step is the physical data model, which is the closest model there is to a database. Now in this model your entites are now tables, and some of them may or may not relate to your application domain.
For example you could have a travel agency application, where you'd have tables for destinations, flight companies etc... These would map directly to your application because they represent concrete classes. On the other hand you'd also have configurations, sparse data (billing...) or associative tables (like you have here). They don't map to your current application. This concept is called impedance mismatch. See this diagram I found online :
Finally to answer your question : no you don't need to map it to a class, because it has nothing to do in the application domain. Of course you still need to handle it some way (using DAO and SQL basically). You could also use an ORM, like suggested in the comments by #RobW, which can abstract and map directly your database.
I've to fetch data from different web services + my own database and combining these data before displaying in the site.
What's the best method for doing this? I prefer writing separate models for web services and database. How can I organize the model classes of different data sources in different folders?
I may add more webservices later.
EDIT: I am Really sorry, as my example below will not work, as you cannot have equally named models. You should prefix them in the subdirectories as well, like:
webservice1/ws1_products
webservice2/ws2_products
db/db_products
products
That way you will load them as
$this->load->model('webservice1/ws1_products');
$this->load->model('webservice2/ws2_products');
$this->load->model('db/db_products');
$this->load->model('products');
And use as
$x = $this->ws1_products->getAll();
$x = $this->ws2_products->getAll();
$x = $this->db_products->getAll();
$x = $this->products->getAll(); // combined result
End of edit.
To separate them in different folders simply put them in subfolders in models directory, then use common syntax $this->load->model('web_service1/products');.
I don't know the best method, as it is a matter of preference, but if I were you, I would separate them as you said in two different models and made a third one, that would combine them to one result.
So if you have to get products from 2 different services and your database, I would make 4 models:
webservice1/products
webservice2/products
db/products
products // the model that combines them to one result
That way you would have to make only one request from the controller, to the products model.
I usually do one model file per data source. Be it a DB table, web service, etc.
For combining data from 2 or more models before rendering I like to do it in the controller if there is business logic involved. If not I do it right in the model (you can now load one model from another in CI2)
I'm using codeigniter for one of my projects, and right now what I have is a table with PROJECT information, and I'm displaying all the PROJECTS in a specific view.
Now, I also want that same view to display other related information about the projects such as the number of views as well as the associated tags. But this would require multiple JOINS in the model(which would require me to alter the existing query...) but it would keep the view from having to call the model directly.
Would I get better performance if I simply break up the queries, and have 2 separate queries related to the other information in the VIEW? I find this to be more clear, but I wonder if it's slower since I'm calling the model for EACH project in a loop.
Why dont you just code both - and test using CI Profilier?
Then you will be 100% sure. Furthermore - if the results are "close" you can just go with the option that suits your programming logic better.
p.s. you could also loop the multiple calls to the model into an array (like $projects) in the controller, and pass that variable to the view, so in either scenario the "view" is NEVER calling the "MODEL" directly.
I was wondering what would be the best practices and the best way to achieve consistency while accessing your database data :
Current structure goes as follow
Data Access --> Business Logic --> Controller --> View
My data access layer is composed of a Zend_Db_Table, Zend_Db_TableRowset and a Zend_Db_TableRow for each table.
My business logic is stored in the model named based on a the table
Example of problematic query :
I want to get a specific user based on his username. To do so I have a user table and a role table (role.id is referred as role_id in the user table).
I don't want to have to use the findDependentRowset that will run additionnal queries for each row that get returned. (will get problematic in data grid that display the data as many rows can be returned).
The choices I have (getName() is used in this example to simplify, but it can be any processing) :
Make a custom join on the role table in the user table which will return an index array composed of associative array. In that case I can't call my getName() function defined in my Model_DbTable_User to build the name (first name + middle + last name). Even if I "cast" my array to a Zend_Db_Table_Rowset (or my custom table_rowset) I can't access my custom class method since I get a generic Zend_Db_Table_Row object.
Make a custom join but build the name using CONCAT() in my query at runtime, I still get an array but the name is build so I don't need the getName() method. But if I have specific logic to apply i'm stuck.
Make a view joining user and role tables in my database and create a new set of Zend_DbTable, Zend_DbTableRowset and Zend_DbTableRow. This way I can have specific logic in my database stack.
An ORM (propel or doctrine (1 or 2)), I have no experience with these, I might need more informations to make the right choice.
My alternate goal is to be sure I get consistency in my data structures
ie:
array all the way :
array(
array(row1),
array(row2)
);
object all the way
$row = $rowset->current();
$row->field;
Creating a view should be done regardless because it complements the other ideas more than it competes with them. The view will:
Abstract the database to something that you can more easily work with.
Be faster because there's no parsing.
Be accessible outside of your application.
Once you've created the views, you can choose a strategy that best solves the problem. If you're creating a form that represents a single entity, then an ORM is probably a good fit. But if you're displaying large lists of data or generating reports that contain many entities then using a declarative language like SQL is probably easier and would perform better.
i dont quite understand this pattern.
from what i have read, it looks like one model = one table (if you are using database to store data).
so if i've got a table called tags, i should have a tags model. and with a threads table i create a threads model.
then i got a tags controller and a threads controller right?
so what if i've got a tags_threads_map table for a many-to-many relationship.
should i have a tags_threads_map model eg. in which i get all threads containing a tag? should i have a tags_threads_map controller too?
would be great if someone could explain or give me a good breif tutorial on this.
the most tutorials just give a simple 1:1:1 example.
To fully understand MVC or any software design pattern, you really need to have a go at implementing it and see what your results are.
That said, MVC does not prescribe that one model = one table. In fact, a model could be backed by a number of tables, or even data originating in something other than a relational database (e.g. a web service, flat files, a key-value store or a graph database for example).
I would suggest that creating models and views that represent meaningful aggregates of related tables is probably a good approach. For example, to use the timeworn example of an Order and OrderLine table, an Order model might encapsulate operations on data that will ultiamtely end up in either the Order table or the OrderLine table.
Adhering to strict 1-to-1 mapping of table to Model, View and Controller will only result in an explosion of classes, some of which may not be doing much individually. Better to build Models and Controllers that are more focused on achieving some task identified by the business requirements, rather than just being a projection of the data model.
So the idea is less "one model = one table" and more that you don't want code that manages the data to be interleaved with code that manages the operations on data or code that handles user interaction. If you have some sort of persistance layer that handles mapping of objects to a database, that's enough to have a rudimentary model. If you have some separate code on top of that that does something algorithmic with that data, that's a controller. If you have a way of rendering the data for user consumption, that's a view.
Best example that comes to mind is a spreadsheet: the data in the spreadsheet is your model. If you have expressions in your sheet that manipulate the data, that can be seen as a controller. If you see the data in tabular form, or in a graph, those are two views. The views don't muck with the data or how it's calculated - they format it for your eyes. The controller doesn't format the data for your eyes - it creates / changes / calculates the data. The important part is separating out the concepts so you can, for example, write algorithms that don't care how data is stored, and views that don't care how data is calculated.
In my opinion, it's better to think of a model as a model of an object type, not of one specific table.
Generally, your MVC framework would handle your many-to-many relationships by definitions from within the models for tags and threads.
And you definitely don't need a controller for every model; controllers are generally more closely related to views (though there are usually multiple views to one controller).
This seems like it's too general of a question to be able to be answered to your satisfaction here.
A model can be more dynamic than that. For example, if you have a blog, and a blog has tags, your model might be called Blog and it can have a collection of Tags.
A model can be anything that stores the data. In the web app I'm working on there are several tables for contacts, their addresses which groups they belong to and so on. It's probably best to split them up by types, I should have made a group model but you don't strictly have to do this.
MVC relates to 3d games quite well, MVC is not only for information systems. Consider this:
In 3d graphics the model is map, the polygons and their positions and colours. The view is the camera from which the scene is viewed, a position, zoom and direction. The controller interprets the keyboard and mouse and manipulates both the camera(view) and scene(model).
If this were a shooter game then if:
A user pushes the forward button, the controller moves the camera forward.
A user pushes the throw grenade button, controller adds a grenade to the scene.
The view is presentation, the model is storage/structure and the controller is an in between which tells the view what to display and how to display it based on the state of the system.
Generally you put all the formatting in a view, data in models and logic into controllers.