Question

I want to make it easy to create drop-down menus within my system that are populated from the database (for example, a list of user groups). I am generally following a domain-driven design approach for this system, including a slightly adapted version of the Repository pattern. (The system is in PHP.)

Since retrieving a drop-down list for a given domain-object class is a common operation, I am wondering if it would be appropriate to create getDropDownList() methods on the relevant repositories.

For example, let's say the domain object in question is called "Category". What I'm proposing is to create a CategoryRepository::getDropDownList() method that would return an associative array of category IDs and titles, ready to be used to create an HTML <select> list.

On a past project, when I created a getDropDownList() method on a repository-like class, one of the other developers said that such a method didn't belong in that class, saying it had more to do with the view than the model. But I don't see it that way because the purpose of the method is simply to return the raw data for the list. It doesn't even need to be used to create a dropdown list; it could be converted to JSON data or any other number of things.

My main questions are:

  1. Does a getDropDownList() method like the one I described belong in a repository class? If not, where should it go instead?
  2. Is this perhaps just a naming issue? Perhaps it would be better if I called it something like getSimpleList() or getArrayForList() to indicate that it's returning an array, and not already-rendered HTML?

To continue the category example, the data returned from this method would return an associative array of category IDs as the keys and category names as the values, e.g.:

array(
    1 => 'Category A',
    2 => 'Category B',
    ...
)
Was it helpful?

Solution

IMHO you should seek for a business meaning of every program element. View layer is there just for the sake of presentation of business rules/data and should be easily replaceable. Your repository on the other hand is part of the business model and should definitely follow business naming (names understandable among business people). Thus, your suggested method naming is not valid. "DropDownList", "SimpleList" and "ArrayForList" have no meaning to business heads.

I suggest the following:

  • by-the-book path (if performance is not an issue) would be method CategoryRepository::findAll()/getAll() which returns all categories in form of Category instances - this way you are dealing with strictly business elements across all layers which is very nice since you don't introduce any intermediate type. In view layer you can easily format this instances into <option/> elements
  • custom method (as you suggested) but with a name understandable by business ppl - e.g. getTitlesOfAllCategories() (@return string[] Array of category ID => title)

Another problem with getDropDownList() is that it can't be "recycled" easily because of naming issue - imagine the sudden need to list categories inside <ul><li> list - is it time to duplicate your original method with getBulletedList()?:) What about checkboxes - maybe getCheckboxList()? But, the meaning is always the same, you just want to present... ta-daaaam... all categories.

OTHER TIPS

You should do your utmost not to query your domain. Your domain should be focused around full aggregates/entities.

Rather create a separate query layer that focuses on returning data using some agnostic naming.

For instance, in C# I would have something like this:

public interface ICategoryQuery
{
    DataTable All();
}

Something like an All method isn't something you would typically find on a CategoryRepository as the domain is concerned with manipulating data (command-side). So if we ever need to perform some action on all our categories so often as to warrant an All method we probably have a design flaw. Come to think, that may indicate that we are querying our domain :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top