Naming conventions are poison.

I’m not referring to sensible naming conventions like “table names are always [singular|plural]” or “method names should be short but descriptive.” Those naming conventions are fine. They’re safe. They protect us from the stupidity of future generations of us (or at least uncaffeinated versions of ourselves).

Poisonous naming conventions are the naming conventions that assume something about the physical implementation of a thing. When you name an attribute DCreatedAt because it’s a date, or objAppointment because it’s an object, or even when you name a table t_Users or tbl_Permissions, you’re poisoning the world. It’s not because I shouldn’t have to worry about typing too much or reading the code – I can guarantee you that your code is shit. The poison comes from the realization that your decision is only valid for today. Nothing says that your date will remain a valid date. Nothing says that the account number will always be a number; starting tomorrow someone could add letters to the numbers and n_AccountNumber stops meaning anything.

You’ve poisoned your future self. You can’t look at a piece of code and anticipate what you’re going to find. With rigid physical naming conventions, the instant that something is changed in the model there are a limited number of choices available.

  1. Do nothing. At this point the model is suspect and we have to resort to metadata and remembering exceptions to make sure we know which columns are really integral, which are dates, and which are strings. At this point, I hate you. Forever.
  2. Change everything. Every database query that uses the column will need to change. Every use of an object’s attributes will need to change. Miles of code will be changed and tested. At this point I hate you, but not forever.

If there were no explicit reference to the underlying implementation, then I don’t need to hate you. I can just be confused that the metadata has changed and mildly annoyed that AccountNumber is now a string instead of an integer, but whatever. Some form of IntelliSense or metadata inspection is going to help me figure out what data type is living underneath that attribute. I don’t need to care – the software is caring for me.

The same thing happens when we drop down to the physical level – when I encounter a table named tbl_PileOfGoats I have to wonder what the original data modeler was thinking, or if they even were thinking. Ignoring the problem of modeling a pile of goats, there’s the problem of implementation. What constitutes a pile of goats? What if at some later date, we need to split out goat piles into multiple tables to support long term goat management technology? Logically we might end up with Goats, PilesOfGoats, and GoatsInPiles. At this point we have to replace the table tbl_PileOfGoats with a view named tbl_PileOfGoats. Suddenly, I can’t even trust tables to actually be tables in the database.

By forcing a rigid, implementation-based, naming convention on our systems we remove any notion of modeling in the true sense of modeling; we’ve removed any abstraction that we can make by forcing users and consumers to be grossly aware of the implementation details. It shouldn’t matter if CreatedAt is stored as a date, time, or milliseconds since the theatrical release date of Breakin’ 2: Electric Boogaloo, it’s just a value that is referenced to produce some sort of meaning. That meaning is separate from the implementation. In an object-oriented world, CreatedAt doesn’t even need to be a single value. C# and Java give developers the ability to create properties that hide automatic getter and setter methods – several other attributes, objects, or even external service calls can be used to provide the value of an attribute.

There’s no value in forcing a one time implementation decision into the naming conventions of your model. It limits expansion – not by imposing a physical limitation, but by imposing limitations in the mental model of the people using your system. When a few key identifiers in a system can’t be trusted to supply correct information, none of them can be trusted. A system with only a few incorrect types encoded in attribute names is as useful as a system with no types encoded in attribute names.

The next time you need to design a database, remember that you’re modeling the data and not the implementation.