Refactoring Rates: From Foreign Keys to Enums in Reimpact Platform
In the Reimpact platform, we're constantly striving for a cleaner, more maintainable codebase. Recently, we tackled an area involving rates and their association with different modules within the system.
The Problem: Priority Products and Foreign Keys
Originally, rates were tied to "priority products" using a foreign key relationship. This approach, while seemingly straightforward, introduced unnecessary complexity. The core issue was that "priority products" were essentially acting as schema prefixes, and the foreign key relationship enforced an inflexible structure.
The Solution: Embracing Enums for Module Definition
To address this, we opted for a more streamlined and explicit approach: replacing the priority_product_id foreign key with a module enum. Here's how we did it:
-
Database Migration: The migration involved dropping the
priority_product_idcolumn and adding amodulecolumn. Themodulecolumn defaults topackaging.Schema::table('rates', function (Blueprint $table) { $table->dropForeign(['priority_product_id']); $table->dropColumn('priority_product_id'); $table->string('module')->default('packaging'); }); -
Enum Implementation: A
FeatureEnumwas created to define the possible values for themodulecolumn. This ensures type safety and provides a clear list of valid module options.enum FeatureEnum: string { case PACKAGING = 'packaging'; case SHIPPING = 'shipping'; case BILLING = 'billing'; } -
Code Cleanup: We removed all references to
priority_product_idin the seeders, Rate model, factory, and import jobs. -
Filament Integration: The RateResource in Filament was updated to use a select field for the
module, allowing administrators to easily choose the appropriate module for each rate. A filter was also added for easy filtering.Select::make('module') ->options(FeatureEnum::class) ->searchable() ->required(),
The Benefits
- Simplified Schema: Removing the foreign key constraint simplified the database schema and eliminated an unnecessary dependency.
- Increased Flexibility: Using an enum allows for easier addition of new modules without requiring database schema changes.
- Improved Code Clarity: The code became more explicit and easier to understand, as the relationship between rates and modules is now clearly defined by the
modulecolumn.
The Takeaway
Don't be afraid to re-evaluate existing database relationships. Sometimes, seemingly straightforward foreign key relationships can introduce unnecessary complexity. Consider using enums or other more explicit approaches to improve schema clarity and flexibility, especially when dealing with categorical data. Take a look at your project and identify areas where foreign keys might be replaced with enums for a cleaner and more maintainable design.