themeek Posted March 4, 2008 Share Posted March 4, 2008 Long day!! :S I've been working on a mini-app that outputs lists of objects in HTML. Say, for example, we were listing items on an auction site, it should be able to display the items as a "normal" list, or as pins in a map, or as an image slideshow etc. At the same time, it should be flexible enough to display categories of items too, given the correct class to output with. The code uses $_GET vars to control the sorting, page number, items per page etc. eg. my_page.php?page=1&sort=az&show=25 My approach so far has been to use what I think is a Builder pattern... but I have a nagging feeling that I'm missing a much easier way of doing this. Here's basically how it works: I've encapsulated the checking and storage of the $_GET vars into a List_Environment_xyz class, which is subclassed as necessary for specific situations. $env = new List_Environment_Admin(); echo $env->getPage(); etc. The source (un-filtered, un-sorted) data is provided by a List_Source_xyz class. The sorting and filtering is done by a class called List_Filter_xyz, where xyz mainly depends on the object type. $source = new List_Source_AllProducts(); $filter = new List_Filter_PopularProducts( $source->getItems() ): $filteredItems = $filter->getItems(); I've produced various classes for the different types of list output, which I've called Decorators (as I think these fit the Design Pattern of the same name). Simple usage: $decorator = new List_Decorator_Normal( $items ); echo $decorator->outputHTML(); The whole thing is tied together with a List class, where details of all the required elements are provided to the constructor. I've made it verbose for the sake of clarity. $list = new List( 'List_Environment_Admin', 'List_Source_AllProducts', 'List_Filter_PopularProducts', 'List_Decorator_Normal' ); echo $list->output(); This sort of works OK-ish, but it's clunky because the Filter needs a reference to the Source and the Environment, the Decorator needs to reference the Environment and so on. Ultimately it means that there's a large amount of clunky back referencing via the List object. For instance, in the Decorator: $pageNumber = $this->list->environment->getPage(); Other problems? There's no natural home for the pagination code (in the Filter or the Decorator?) or any feasible way to validate the $_GET vars other than simple type checking/casting. So whilst I can ensure that the 'show' (items per page) value is an integer, it's tricky/impossible to check that it's an allowed value (10, 25, 50 etc.) without the Environment class having knowledge of the Decorator. Since the idea of splitting the classes in this way was to decouple them, this is a major downer. Worse still, there's no easy way to perform slight variations on a particular Decorator. For instance, inserting a number in front of each item to indicate rank in the PopularProducts example. To do this currently, I'd need to define a new Decorator with this tiny change (not very D.R.Y.). There are further complications - the List object is serialized into the session to give it some 'memory' and improve performance and the whole thing also needs to work via AJAX. <sigh> Have I just been looking at this too long?? Is this as bad to everyone else as it appears to me? ??? Perhaps there's another way of separating the constituents parts that I've completely overlooked or a refactor that makes more sense. I'm fairly new to design patterns and I'm also wary of (and prone to) over-complicating things. Let me know if I've explained anything poorly. I've got a day tomorrow working on something else, so I'm really hope you guys will be able to give me some feedback so I can approach it more cheerfully later in the week. Thanks in advance Steve ( themeek ) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.