I'm trying to figure out how to apply composition over inheritance to a system I'm building, and tripping up when I try to apply it to my page objects.
The relevant objects are:
PageFactory
Page
Route
[Entity]Repository
(multiple)
The system is pretty straight-forward. The PageFactory
is used to build and retrieve Page
objects. Pages use repositories to retrieve data objects for use when rendering the page and setting the page's title.
Before trying to apply composition over inheritance, each different page would be a subclass of the base Page
object, and would override getData
and getTitle
functions.
I've refactored the system such that there are no longer subpage objects, but instead PageFactory
creates an instance of Page
for each type of page and sets the appropriate properties through setter functions (think view template path, route string, etc).
The problem is that each page needs to be able to retrieve data specific to that page using entity ids retrieved via route tags (like /entity/284), and also set the page's title based on the retrieved data, too.
This behavior is not easily refactored to config data. This is actual code that differs between pages.
The first approach I tried was to create an interface called iDataProvider
and then in the PageFactory
I would give each Page
instance the appropriate concrete [entity]DataProvider
object which would then have its own getData
and getTitle
functions. Page
objects would retrieve all query data and pass them to the iDataProvider
object when requesting data and title.
It works, but it feels icky, and I'm not 100% why. I think my feeling of unease may have something to do with passing all query data to the data provider and then asking it to know how to extract the important bits.
The second approach I tried was to have a single RouteDataProvider
object which accepts a Route
object, uses the Route
object to get all query data, and then based on what query tags are in that route retrieves the appropriate entities and passes them back to the page. This really doesn't feel much better.
I feel like I'm designing myself into a corner. Where did I make the wrong turn, and what would be a better way to design this part of my system?
Page
produce a HTML page? A JSON object? Start with that, try to work your way backwards.