Unveiling the Art of Robust Model Typing: A Skill Many Developers Overlook

Unveiling the Art of Robust Model Typing: A Skill Many Developers Overlook

Introduction:

Today, we delve into a often-overlooked development practice with transformative potential: using dedicated classes rather than primitive types for attributes in database models. By illustrating this approach with code examples, we'll explore how it can significantly enhance data quality and the robustness of our applications.

1. Limitations of Primitive Types:

Primitive types, such as 'string' and 'number', may have limitations when used to represent complex data. Consider the example of a 'User' class with primitive type attributes:

class User {
  name: string;
  email: string;
  age: number;
}

Here, primitive types fail to capture the complexity of data. For instance, 'name' could hold any string without distinguishing between a person's name and other types of text.

2. Using Dedicated Classes for Precise Typing:

To enhance typing and data quality, let's use dedicated classes. Define the 'User' class using dedicated classes 'PersonNameValue', 'EmailAddressValue', and 'PersonAgeValue':

class PersonNameValue {
  value: string;
 
  constructor(value: string) {
    // Specific validation for a person's name
    if (!isValidPersonName(value)) {
      throw new Error("Invalid person's name");
    }
    this.value = value;
  }
}
 
class EmailAddressValue {
  value: string;
 
  constructor(value: string) {
    // Specific email address validation
    if (!isValidEmail(value)) {
      throw new Error("Invalid email address");
    }
    this.value = value;
  }
}
 
class PersonAgeValue {
  value: number;
 
  constructor(value: number) {
    // Specific validation for age
    if (!isValidAge(value)) {
      throw new Error("Invalid age");
    }
    this.value = value;
  }
}
 
class User {
  name: PersonNameValue;
  email: EmailAddressValue;
  age: PersonAgeValue;
 
  constructor(
    name: PersonNameValue,
    email: EmailAddressValue,
    age: PersonAgeValue
  ) {
    this.name = name;
    this.email = email;
    this.age = age;
  }
}

3. Rigorous Validation with Dedicated Classes:

Each attribute is now associated with a dedicated class encapsulating specific validation:

const userName = new PersonNameValue("John Doe");
const userEmail = new EmailAddressValue("john@example.com");
const userAge = new PersonAgeValue(25);
 
const user = new User(userName, userEmail, userAge);

Validation is applied during the creation of a 'User' instance, ensuring valid data in our model.

4. Easy Maintenance:

Maintenance is simplified as validation rules specific to each attribute are encapsulated in dedicated classes. Adjustments are made at the level of each class without impacting the rest of the model.

Conclusion:

By using dedicated classes, we maximize data quality by reinforcing typing and applying rigorous validation. This approach provides a solid foundation for future development by avoiding the limitations of primitive types.

Call to Action:

Explore this approach in your next project and share your experiences. How has this practice improved your data quality and streamlined your code maintenance? Share your thoughts and discoveries with the development community!