mardi 27 juin 2023

Is the combination of Repository and Data Mapper patterns necessarily inefficient?

There's been a variety of questions here that pop up from time to time regarding these two common design patterns for describing a persistence (data storage) layer in an object-oriented program: Repository and Data Mapper, with some wondering whether there's a difference at all.

What exactly is the difference between a data mapper and a repository?

Repository and Data Mapper pattern

and so forth. I have another, though, that none of these seem to answer. In particular, regarding the difference between the two, I've found the best answer looks to be that a Data Mapper simply does what it says on the name - its Single Responsibility is to map objects to and from a database, i.e. CRUD objects to/from the DB, so that the DB type used in the back is hidden from the higher-up logic. This makes good sense. Whereas the Repository is apparently over the Data Mappers and permits more complex querying, for example, methods like "getAllCarsWithEngineType".

Trouble is, what I'm wondering is how then does the Repository actually work. In particular, to do a query, if all it can see is Data Mapper, and all Data Mapper does is the 4 CRUD methods (with perhaps one more method to get all the keys available), then it seems the only thing Repository can do is dig up the entire database into memory as objects, and then scour them for the right ones. This seems like an awful waste of performance, especially when you can run an SQL query directly that should be far more efficient since you're then letting your DB engine handle all that search stuff and it likely has lots of tricks up its sleeve to make such things fast.

But that would seem to have no other logically possible way to happen than either to add (a likely escalating number of) query methods to the Data Mapper, which breaks the spirit and once more dissolves the distinction, or you have to have some other "thing" the Repository uses to do this, or else, Repository has to interact directly with DB, putting low level SQL (or whatever) queries and stuff directly in the Repository itself, and that sounds pretty bad (clashing high and low abstraction levels, for one) esp. given if it still relies on an injectable Data Mapper for some of the functionality you could easily mismatch the two.

So can you, and if so, how do you, build queries into a Repository/Data Mapper combo in an efficient/performant manner while maintaining the spirit of the patterns?

Aucun commentaire:

Enregistrer un commentaire