Question

I am storing information about Widgets in my database, and each Widget has one (non-unique) transformation function associated with it. My problem is how to associate Widgets with their transformation function.

My first instinct was to use an enum for the transformation function. I am using sqlalchemy for my database ORM, which includes an enum type that makes it really easy to use an enum column. It takes care of validation, and I can simply have an enum in my code for the possible transformation functions, an enum column on Widgets, and then a map in my code from enum values to the actual functions.

Then I read why enums are evil. It's pretty convincing, but if I use a reference table, then I can't use a python enum object, and my map will have to be from strings to functions - which means that if I make a typo it might happen that I am mapping from a transformation that doesn't exist in the database, which is not good, and I have no way of knowing that my map is exhaustive and correct.

What's the best way to do this?

Was it helpful?

Solution

There's nothing wrong with having an enum column on your database or using enums in your program. But don't use both!

The point of enums is to limit possibilities and therefore simplify handling and/or validation, but if you're using them in multiple places, you'll have to keep both the database and the program up-to-date.

It also means you cannot update a program on a database without first having upgraded the database should you add a new possible value. And by that logic, you cannot even downgrade a program to a previous version or you risk it will explode when it attempts to load a value from the database that isn't considered by your program. There are ways of getting around this (future-proofing), but it is still not ideal.

Database approach

If you want to use the database for enum values, you should go 100%. This means any information relative to the enum that would affect behavior in your program should be directly tied to the enum field in your database. If needbe, create a separate table with only enum values and its properties to be referenced by your other tables. The program should then never really need to read the enum value to determine behavior. You may use it for descriptions or for making distinction between other records with differing types, but never for determining behavior. That information should come directly from the database.

Program approach

If you abandon a database column in exchange for keeping it in your program, it means your program determines behavior, not the database. The database can still have a column, but it should be strictly a VARCHAR field. Your program reads the value and associates it directly with an enum type in your program and your program changes behavior based on that enum value. This gives you added flexibility in your program and in your database updates. Even though your program is in theory the only thing writing this table, I would still have a backup plan for when a type value is used which doesn't exist.

Licensed under: CC-BY-SA with attribution
scroll top