Episode Suggestion: Normalization
I've identified a tendency in myself that I feel like, if overcome, would make me a considerably better developer and produce better software. Here I'll try to characterize/analyze it:
Description: I feel like my ability to expand the way I store and represent data in a db is hampered by my ability to perceive of more complex relationships in the application layer (aka, how the heck do I set up forms and controllers for this?).
Internal Tell: I'll feel subtly unhappy about the way my models are set up, but not really know what to do about it. I'll be staring at how I've set up the schema and identify that I actually need to move a concept out of a given table to become its own thing.
Here's a pretty clear-cut example to illustrate:
I'll have a User table that stores phone numbers. Soon after, the organizations they're a part of need to store those, too. So, I might end up adding a phone_number column to both.
class User < ApplicationRecord
validates :phone_number
end
class Organization < ApplicationRecord
validates :phone_number
end
Pretty much at this point I might find myself adding a concern with the logic for phone numbers, then including that in the models that have them. Ok, the data's stored two places, but my application code can be changed in one place.
Well, guess what, I need to now validate the uniqueness of the phone numbers. So, either I've gotta write some more Ruby to validate uniqueness across all the tables, or if I'm already in production, need to worry about migrating all the data to a new phone_numbers
table so I can validate uniqueness there.
Timing: This is where the issue of timing comes into play. Breaking out a PhoneNumber
into its own model is a pretty obvious thing since it bit me in one of my first applications (like Addresses), but there are some more and subtler ones that I'm finding over time (like any time I end up needing to store a bunch of constants or abusing enums, always worth breaking those out into their own table).
Guess what I'm really talking about is normalization. But there's a dimension of timing to this:
- finding some concept that needs to be broken out immediately
- discovering a concept that will implicitly be required by the app in the future, but not actually needed yet
before/after you already have production data to worry about
The Fear: I subconsciously shy away from good normalization because dealing with fields_for
, while doable, is still confusing. Like, imagining the mapping of a form_for attribute to a database column on a model is easy. Imagining that relationship, validations, directory setup with a phone_number broken out isn't so natural yet.
So, knowing that I have a tendency towards just taking the easy path, this brings up the question: how can I add more things to that easy path? And that means, being able to phrase elements of the real world in such a way that they're well-suited for Rails.
So that's the starting point: basic discovery, jotting down some attributes onto models, setting up the relationships between them, but then - how far and how soon should I normalize? What do I need to learn more deeply to expand the easy path? (db stuff, just read through/code through variety of situations, look at how people have broken out what they have and ask why).
I've identified what I consider an issue. Is it actually an issue, or just a process I need to go through, or are there areas I need to learn? Not sure really sure what the actual problem is, just that there is one (I've tried describing it here). So I definitely don't know what a good answer to it would look like.
I often find myself needing to create form objects and other kinds of stuff that I don't feel good about, but can't put words to. So then a separation between how I'd like to store data, and how I can nicely phrase that in MVC.
Once I stumble across a situation like this, I'll write it up in this thread