Quick background: I'm programming in PHP, I have a domain model with a separate data access layer (DAO classes) that are responsible for fetching data from the DB and creating domain classes.
Let's say I have a DAO class responsible for creating group and groupList objects. You can imagine the groups as a component of a social network; although it doesn't really matter what they are for this question.
I need to be able to ask the DAO to make me various groupList objects based on various different criteria:
- the most recently added groups
- the most popular groups
- groups identified as "featured" by an administrator
- groups tagged with a certain tag
- groups matching a certain keyword
- groups within a certain category
- groups created by a certain person
- groups created on a certain day
Some of these I don't actually need right now, but I can kind of imagine I'll need them before the project's done. Now I started off with a nice simple DAO method: createList. This worked great. You can think of the pseudo code as:
find out how many groups
create SQL query to fetch group details
loop through results
{
create group object
add to group list object
}
As my application progressed, I then created a new method createFeaturedList. This worked great. But it was actually very very similar to createList, with a slightly different query. A lot of the rest of the ~ 150 lines of code were identical.
So... what should I do about all the slightly different cases I need? Most of the time I really just want to filter and sort the list based on certain criteria. The question is this -- should I:
a) create lots of focused creational method like:
- createList()
- createCategoryList( categoryObject )
- createUsersList ( userObject )
- createTagList ( tag )
- createPopularList ()
or
b) create one BIG method that can do everything: - createList ( searchString, orderBy, filterByCategoryObject=null, filterByUserObject=null )
I quite like the idea of (a) because my DAO interface is simpler and less likely to need to change (eg: adding another parameter when I suddenly need to pass in a date to compare against) The difficulty comes when you have stuff like search keywords which you want to be able to combine with other parameters; eg: searched category list, searched popular list, searched tag list etc... (a) is kind of what I've started off with.
I've had a flirt with refactoring to (b) but I can see my method getting very large and very complex pretty quick, lots of "if"s and "select"s to deal with the different cases when building the SQL, and lots of parameters that are fed into the method. But at least it's all in one place. And you can combine things; eg: a user's groups, tagged with blah, matching keywords blah.