SitePoint Sponsor

User Tag List

Page 2 of 2 FirstFirst 12
Results 26 to 38 of 38
  1. #26
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    Uuhh... Yeah I think we all know that. I've done paged result sets many many times, as I'm sure everyone else here has as well.
    Not implying you don't know. Simply stating the obvious, being explicit for the sake of the less experienced, etc.

    Quote Originally Posted by Czaries View Post
    I don't see how there would be all the overhead you claim or any extra queries with an intelligently designed data mapper? The way I look at it, there would pretty much always have to be 2 queries...
    A mapper doesn't necessarily have a one-to-one relationship with a query. The domain model shouldn't be artificially restricted by this constraint. In other words, it won't always be 2 queries. Perhaps it will be for a lot of apps, and for those that type of setup is fine, but when you start getting more queries involved, concurrency issues will rear their heads, as will the obvious overhead of additional queries per domain object.

    Injecting the mapper into a separate Pager object seems like the way to go to me (for simplification), but it also seems like there would need to be some built-in methods for adding the modifications to the query in the mapper itself, so they can be passed on to the adapter to put the query together. That integration point is what I would like to figure out.
    I'd nuke the idea of a mapper and use a straight up associative array or a clever datasource that implements Iterator. A DataGridController or some such thing would incorporate paging, sorting, exporting, etc. This controller would then export a data transfer object to be rendered by a dumb template. The template would probably use a DataGridHtmlHelper for generating headers, links, etc., although that would be entirely optional.

    Again, the reason I suggest getting rid of the mapper is because the typical use case is for read only applications. You show some dumb data in a grid. Maybe even in editable fields, but even then the intent isn't to update the model, so why bother loading all of those objects, setting up the rules, etc., before you actually need them?

    Lastly, something to consider when implementing the SELECT COUNT(*), SELECT ... LIMIT x, y functionality is read consistency. You obviously want to be sure the total COUNT() doesn't change between the two queries. This should help, assuming you're using MySQL -- http://dev.mysql.com/doc/refman/5.0/...tent-read.html

  2. #27
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cuberoot View Post
    Again, the reason I suggest getting rid of the mapper is because the typical use case is for read only applications.
    I very strongly disagree. The purpose of a data mapper is for mapping data back and forth between the database and objects. That means both reading AND writing. It's essentially a translation layer. I use a data mapper every day that reads and writes, and it works great.

    The data mapper is a layer that sits in between the individual row object and the database, It's not what you make it out to be.

    Quote Originally Posted by cuberoot View Post
    ... the intent isn't to update the model, so why bother loading all of those objects, setting up the rules, etc., before you actually need them?
    A data mapper doesn't have do that - my data mapper makes dumb value objects for the rows, and the rules are only applied to the row by the mapper when saving, inserting and updating. This ensures that SELECT queries are always fast, use little memory, and are as light as possible. Remember - any object saved to the database has to go through the mapper to do so - "$dataMapper->save($rowObject)", so all the processing happens there. I'm not sure what data mapper you've been using, but we obviously have two very different ideas on how it should work.

  3. #28
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    I very strongly disagree. The purpose of a data mapper is for mapping data back and forth between the database and objects. That means both reading AND writing.
    Not talking about the mapper there, but the paging of records. You only do that for viewing purposes, i.e., read-only.

    The data mapper is a layer that sits in between the individual row object and the database, It's not what you make it out to be.
    What you describe there is only one potential mapping. Technically, you could draw a single domain object together from a number of tables. You can even save that object across several different databases. The whole idea of a mapper is to encapsulate those details. There's nothing that says there must be a one-to-one correspondence between a domain object and a table row. That would actually defeat the purpose.

  4. #29
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cuberoot View Post
    What you describe there is only one potential mapping. Technically, you could draw a single domain object together from a number of tables. You can even save that object across several different databases. The whole idea of a mapper is to encapsulate those details. There's nothing that says there must be a one-to-one correspondence between a domain object and a table row. That would actually defeat the purpose.
    What I describe is using one mapper per table, which gets and saves data to and from the table. This does not defeat the purpose, and is a quite common application for a data mapper. I described one application for the data mapper - obviously the term is more generic and can have many other applications.

    And while the data mapper can support saves across multiple tables and databases for relational records, each table will generally still have it's own mapper that is used for the saves on that table instead of having one mapper try to handle it all.

  5. #30
    SitePoint Addict webaddictz's Avatar
    Join Date
    Feb 2006
    Location
    Netherlands
    Posts
    295
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    What I describe is using one mapper per table, which gets and saves data to and from the table. This does not defeat the purpose, and is a quite common application for a data mapper. I described one application for the data mapper - obviously the term is more generic and can have many other applications.
    Actually, you're using the name of a design pattern, so I can see why cuberoot assumes that you're speaking of an implementation of that design pattern. If you mean something else, perhaps it's easier to use a different name for it considering using a the name of design pattern for something else is rather confusing for other people.

    Quote Originally Posted by Czaries View Post
    And while the data mapper can support saves across multiple tables and databases for relational records, each table will generally still have it's own mapper that is used for the saves on that table instead of having one mapper try to handle it all.
    Obviously, I do have multiple Data Mappers, but there is not a one-to-one correspondence between the tables and the Data Mappers. The purpose of a Data Mapper according to Fowler has the intention to encapsulate the details of the datamodel, and even the database. In a well normalised database, it would be more common to select from more than one table to compose a single Domain Object than it would composing an object from the data of one single table. Having a one-to-one correspondence between tables and datamappers does imply knowlegde of the datamodel to your application, so I can see why cuberoot tells you that would defeat it's purpose. I tend to agree.
    Last edited by webaddictz; Oct 8, 2008 at 01:25. Reason: typo's

  6. #31
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree that the terminology we use when discussing patterns is very important. After all, the fundamental purpose of design patterns is communication.

    Fowler calls "one mapper per table, which gets and saves data to and from the table" a Table Data Gateway. A Data Mapper may use one or more Table Data Gateways to do its thing, although PoEAA only recommends doing that if you've got some metadata rigged up to drive the gateways, since creating them manually would be rather labor intensive.

  7. #32
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well then I suppose we agree that the specific implementation I am using is more along the lines of a Table Data Gateway. I almost threw in this term as well in my previous post, and I guess I should have, as it would have made things more clear. I am aware that data mapper is a generic term and what it can encompass.

    Anyways, we're going way off topic now. The point was that I was trying to find the best way to implement paging in a generic enough way that it could be as automated as possible. Not requiring me to manually write the query, making it portable across multiple projects, etc. I never got any feedback on my vision of the Pager class and what it's function should be. That's where the comments and criticisms here should be directed.

  8. #33
    SitePoint Addict webaddictz's Avatar
    Join Date
    Feb 2006
    Location
    Netherlands
    Posts
    295
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    Well then I suppose we agree that the specific implementation I am using is more along the lines of a Table Data Gateway. I almost threw in this term as well in my previous post, and I guess I should have, as it would have made things more clear.
    I agree on that, can't speak for cuberoot, obviously.

    Quote Originally Posted by Czaries View Post
    I am aware that data mapper is a generic term and what it can encompass.
    Well, I was actually trying to convince you it's a very specific term. Mapper is rather generic, but a Data Mapper has well defined responsibilities.

    Quote Originally Posted by Czaries View Post
    I never got any feedback on my vision of the Pager class and what it's function should be. That's where the comments and criticisms here should be directed.
    Just like cuberoot, I don't like the thought of having the tie between the Pager and the Mapper. Sure, you could enforce the existance of certain methods (such as setLimit( $limit, $offset )) on that Mapper, but why would you? In my humble opinion, it'd be easier to just pass the current page, the resultset and the total number of entries. I wouldn't be uncomfortable with this.

    Nevertheless, there might be even better solutions.

  9. #34
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by webaddictz View Post
    Well, I was actually trying to convince you it's a very specific term. Mapper is rather generic, but a Data Mapper has well defined responsibilities.
    The scope is limited and the role is clearly defined, but it's still a generic term because the actual implementation can vary widely, hence the confusion in our posts.

    Fowler defines it as:
    A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.
    So at least to me, that is still fairly generic. All it's saying is that the data mapper is a translation layer between objects and the database.

  10. #35
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    I never got any feedback on my vision of the Pager class and what it's function should be. That's where the comments and criticisms here should be directed.
    To be honest, I thought snajt's example was good. The big difference between all of our approaches is how and where exactly to limit the results. I think the pager should recieve a page number from the client, and translate that into limit/offset to pass to a given datasource (my data mapper, call it what you will).

    Quote Originally Posted by cuberoot
    I'd nuke the idea of a mapper and use a straight up associative array or a clever datasource that implements Iterator
    I would be fine with an object that implemented a limit/offset interface and lazy loaded a call to a mapper (I think this was mentioned before). That way you could call any number of conditions on the mapper, and still page from that end result set. Either way though, the mapper needs some sort of interface to limit what it returns, since I don't agree with pulling the whole resultset into memory. I'd rather just do two queries.

    Cuberoot: I'm curious-- would you just use straight-up SQL when you are displaying data? And then load objects into memory only when you're modifying them? I've found I much prefer to work with objects, even when I'm only displaying data. Especially with mappers, since I can keep all the SQL in one class and test it separate from everything else.

  11. #36
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cuberoot View Post
    I agree that the terminology we use when discussing patterns is very important. After all, the fundamental purpose of design patterns is communication.

    Fowler calls "one mapper per table, which gets and saves data to and from the table" a Table Data Gateway. A Data Mapper may use one or more Table Data Gateways to do its thing, although PoEAA only recommends doing that if you've got some metadata rigged up to drive the gateways, since creating them manually would be rather labor intensive.
    Your definition of a data mapper sounds more like a repository from DDD to me... In my understanding, a data mapper and a table data gateway are two interchangeable ways of approaching the problem, and data mappers don't generally use gateways.

    I don't have PoEAA, but if I remember correctly from when I read it, the biggest difference between a data mapper and a table data gateway was that an object was passed to a data mapper, while only its properties would be passed to a table data gateway:

    PHP Code:
    $mapper->save ($post);
    $gateway->save ($title$body$author_id); 
    In addition, I'm pretty sure data mappers can be used with a single table, and a table data gateway can span multiple tables. (I believe fowler specifies a table OR a view).

    Correct me if I'm wrong.

  12. #37
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In my understanding, a data mapper and a table data gateway are two interchangeable ways of approaching the problem, and data mappers don't generally use gateways.
    Table Data Gateway: An object that acts as a Gateway (466) to a database table. One instance handles all the rows in the table.

    Data Mapper: A layer of Mappers (473) that moves data between objects and a database while keeping them independent of each other and the mapper itself.

    First difference is emphasized in those definitions -- Gateway and Mapper. When it comes to decoupling parts of a system, you're right that it's basically one or the other. Gateway provides a thin wrapper around some functionality, whereas Mapper has knowledge of multiple subsystems and provides a way to translate their input and output.

    Second difference is that a Table Data Gateway isn't really used with the Domain Model approach. It's better suited to Table Modules and Transaction Scripts. Generally speaking, Domain Model will use a Data Mapper, although a Data Mapper may in fact use a Table Data Gateway.

    "Interestingly, it often makes sense to have the Data Mappers (165) talk to the database via Table Data Gateways. Although this isn't useful when everything is handcoded, it can be very effective if you want to use metadata for the Table Data Gateways, but prefer handcoding for the actual mapping to the domain objects." -- PoEAA, p. 146

    I'm pretty sure data mappers can be used with a single table, and a table data gateway can span multiple tables. (I believe fowler specifies a table OR a view).
    Fowler does say it's possible to access a view or a hairy query with a Table Data Gateway, but also hints that this is often used for read-only access.

    A Data Mapper can obviously write to a single table since it basically has kingly power over the database. It can write to one table today, but then choose to write to three or four tomorrow.

    Your definition of a data mapper sounds more like a repository from DDD to me.
    Repository: Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

    Here's the key thing about a Repository -- it has nothing to do with databases whatsoever. You can have an array sitting behind a repository, a database, or even an XML file.

    Another thing about Repositories is that they speak in the language of domain objects exclusively, usually allowing clients to ask for stuff in a declarative fashion. Code looks like this --

    PHP Code:
    $cars App::carsRepository();
    $cars->add(new Car('Toyota''Corolla'2008));
    foreach (
    $cars->matching(eq(Car::MODEL'Ford')) as $car) {
        
    // $car is an Aggregate Root, i.e., the sole
        // access point for Car Aggregates
        // Aggregate is defined as a cluster of associated objects
        // that we treat as a unit for data changes
        // see Coarse-Grained Lock in PoEAA for discussion
        
    $cars->remove($car);


  13. #38
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's the key thing about a Repository -- it has nothing to do with databases whatsoever. You can have an array sitting behind a repository, a database, or even an XML file.

    Another thing about Repositories is that they speak in the language of domain objects exclusively, usually allowing clients to ask for stuff in a declarative fashion. [/quote]

    From my knowledge, while repositories have an interface in the domain, they generally delegate to DAO's... I generally think of data mappers as executing their own queries on the database. I had not seen the part about data mappers delegating to table data gateways.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •