views:

56

answers:

3

I have a situation where I have a bunch of rows in a database. For example, let say we have a table called ReportRendererType.

Rows might be:

  • Line Graph
  • Bar Graph
  • Grid

etc.

I can use the database to store how particular users want to view particular reports. Eg. Frank likes the Profit Report displayed as a Bar Graph. It would be lovely if I could associate code with the entry in the db. In other words, it would be great if the LineGraphRenderer class knew that it was associated with row 1 in the ReportRenderType table. One trivial example of why this would be useful is that you could populate a dropdown list of ReportRenderType options, and then select a value and a Manager class could easily figure out how to display the report given the value selected from the dropdownlist. The question is then - how do you make the association between the db and that chunk of code.

There are lots of options:

A. When you make the LineGraphRenderer class, you could have a property ReportRendererType which returned the primary key of the associated row.

B. You could have a LineGraphRenderer return an enumeration which had a value of the primary key (C# allows you to do this by setting the hash code value explicitly) this gives static typing, and a single location for all the db entries.

C. You could have a ReportRendererType property on LineGraphRenderer which returned the primary key but retrieved the value for the associated row from a settings file. This would facilitate creating the associations, especially if someone else has different primary key values. For example, Company A might have LineGraph stored in row 1, but Company B might have LineGraph stored in row 2.

Unfortuanately all these ways also seem to have drawbacks. I'm wondering how this problem has been tackled by others, and if they've found some great ways of doing things that I'm missing.

A: 

I had a similar problem.

You could define an interface for the Renderer Class. Then you implement a Base Renderer (Line Graphe maybe) and all your other Renderer Classes. The you have a RendererFactory which has GetRenderer. Then you give that Factory Parameter and the Factory cann look at the DB which Renderer to use. If the Factory found nothing use Default Renderer.

Maybe somthing like this is an idea.

Richard
+1  A: 

I suggest that you not associate code with database rows! This is quite contrary to separation of concerns.

To be honest, this is not quite the silliest idea I've ever heard; but it's pretty close.

John Saunders
Upped. Silly might not be the right word, it's an anti-pattern though.
marr75
I used to have ideas like that. When I was much younger, and had stayed up until 3am on sugar and caffeine. I grew out of it, though, and came to be able to see boundaries between things.
John Saunders
So if you wanted to represent something (like how you should display a graph), you would need to store some information in the database. At some point you need to figure out what code is going to run based off that information. What would be a better approach? You need at some point to associate that row with code, would you not?
Daniel
Yes, and that place is in the presentation code, not in the database. The database is for saving the information. Let the Presentation layer decide how to display it. In particular, I suggest you store more abstract descriptions in the database, and let the code interpret it. You can then more easily change how it appears.
John Saunders
Note also that the T-SQL language has no means of storing behavior in a database at all. I'm not even sure that full (and unimplemented) ANSI SQL has any way to do this. At best, this would require an OODBMS.
John Saunders
When you say 'more abstract descriptions in the database' what would be an example? If there was no need to store the user preference, I would definitely not what to make the connection. However if we do, what would a 'more abastract description' look like, and wouldn't it just ultimately boil down to connecting that abstract description with a piece of code? It could be a special name rather than a primary key, but wouldn't that still end up being the same thing. A special string used in the that is associated with code?
Daniel
Or is the problem with the very idea of storing this type of user preference? Given the requirement to store the preference, I'm definitely searching for a way that doesn't feel (as I you aptly put and with which I agree) silly!
Daniel
I don't see the problem. In my case the application is database-based (if there is such a phrase) and therefore this type of coupling is not an issue. Ultimately you need to store this in the db eventually and as nice small numeric ID seems a good way of doing this. It comes back to how you deal with this in the UI and to me a Enum seems a reasonable way of making it easy for the developer. It's still up to the app code to provide the necessary behaviour, not the db.
Simon
This is a problem you don't seem to have reached yet. If you went all the way in terms of storing the code, you could wind up storing all the code necessary to generate exactly the kind of display the user just asked for. This would work well as long as the user used the same version of your program. Another version might have stored something different for the same choices. I suggested storing {"PieChart", 3D, rotation 30 degrees} rather than the code to generate that display.
John Saunders
@Simon: it is an issue. Even if you're database based, you still should keep your display decoupled from the data storage. Otherwise, you'll need to version them together. Remember, "separation of concerns" because it reduces your concerns.
John Saunders
@John: Sorry, perhaps I just misunderstood you or you originally misunderstood me. I'm just storing the users preference in the db, not any code. In my code I have a manager that takes a object (ActiveRecord representation of the user setting - ReportRenderType) and then sends the request to a class that knows how to do that kind of rendering. All that is stored in the db is the a name "BarGraph" and then a primary key.
Daniel
@unknown: I think you're right that I misunderstood your use of the word "code". Correct me if I've still got it wrong: You just want to associate an enum value with the value from a lookup table. You want to associate the enum either by the text or by the integer value, where both would be stored in the lookup table.
John Saunders
+1  A: 

I use option B extensively. This relies on two things:

  1. The values are not subject to frequent change (this requires a code edit and re-build)
  2. The database is properly normalised so that you enumerate the primary key of, for example, ReportRendererType which is used within the database as a foreign key (in your Customer table for example).

This works very well as you can reference the enumerated values directly in database queries and updates. If you plan ahead a bit you can also create the enumerated type names so that they can be easily displayed in a UI by splitting the text by capital letter. 'BarGraph' becomes 'Bar Graph' for example.

Depends whether you want your code that tightly coupled to your database or not. Personally I'm comfortable with it but others may not be.

Simon