Question

We have a layered application, or at least is in the process of transitioning to one, broken down as follows:

  • Interface (user-interface or application-interface, ie. webservice, etc.)
  • Business logic
  • Data access

To make the rest of this question more concrete, I'll describe a specific instance.

We have a user interface, which has a controller object behind it (the business logic layer). This controller talks to the database through another object (the data access layer).

In a given context, the user interface allows the user to pick an employee to tie the operation being done to. Since there are rules regarding which employees the user (well, any world outside of the controller really) can pick, the controller provides two things for this:

  • a readable property containing a list of available employees to choose from
  • a read/writable property containing the currently chosen employee

The user interface might read the list and use it to populate a combobox.

In version 1 of this application, the combobox contains the identifying number of the employee + the name of the employee.

All is well...

... until version 1.1, a bugfix. A user complains that he can't choose between Jimmy Olson and Jimmy Olson because the application doesn't make it easy enough for him to know which is which. He knows there is one Jimmy in the sales department, and another in the development department, so the fix for this 1.1 version is to simply tack on a slash + the department name in the combobox. In version 2 we would opt for replacing the combobox with a combobox that has column support, removing the slash, but in 1.1, this is what is chosen in order to minimize the risk of further bugs.

In other words, the combobox would contain:

  • 1 - Jimmy Olson/Sales
  • 2 - Jimmy Olson/Development
    • other people

However, the user interface code has no SQL code, or any way to get hold of that department, and thus we have to go to the controller and look at the code there. The controller doesn't need the department, and to be honest, it doesn't even need the name of the employee, the identifying number is enough, so there is nothing in the controller that asks for or does anything to the department. So we have to go down to the data access layer and change the SQL there.

This solution quite frankly smells.

If there are multiple interfaces to this controller, with different requirements, we have three possible solutions:

  1. Change the data access layer to cater for the (increasing/diverse) needs of multiple interfaces (2 layers away), which means that all the interfaces will possibly get all the data they need, but they would also get all the data required for any of the other interfaces
  2. Add something that lets the user interface tell the data access layer (still 2 layers away) what it needs
  3. Somehow make the user interface layer get hold of the required data without changing either the controller or access layer involved, this sounds like we need more data access code, somewhere.

None of the above solutions feel good.

What I'm wondering is, are we completely off course? How would you do this? Are there a fourth and fifth solution below the 3 above?

Per this question: Separation of Concerns, the accepted answer contains this quote:

The separation of concerns is keeping the code for each of these concerns separate. Changing the interface should not require changing the business logic code, and vice versa.

Does this simply mean that all the controller/data access layer should provide us with is whatever it needs to do its job (ie. the identifying numbers of employees), and then the user interface should go talk to the database and ask for more information about these specific employees?

Was it helpful?

Solution

The way I see it, you have two possibilities:

  1. Have the lower layers send up all the information they have about a person, possibly as an XML document, even though many of the consumers of that information don't need it all.
  2. Provide APIs for the higher level layers to drill down and get the information they need. So in the case you give, have a method that the interface can ask the business layer to ask the database layer for the department given the user id.

Both have trade-offs. The first one exposes a lot more information, possibly to consumers who don't have any right to that information. The second one passes a lot less information per transaction, but requires more transactions. The first one doesn't require a change to the API every time you have more information, but changes the XML. The second keeps the interface of existing APIs the same, but provides new APIs as needs change. And so on.

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