![cover-img](https://project-assets.showwcase.com/1420x/16381/1676567329424-1676567328504-maurice-williams-tPX992SVljo-unsplas.jpg?type=webp)
Code Smell 50 - Object Keys
16 February, 2023
0
0
0
Contributors
Primary keys, IDs, references. The first attribute we add to our objects. They don't exist in the real world.
TL;DR: Reference objects with objects, not ids.
Problems
- Coupling
- Accidental Implementation
- Bijection Principle Violation.
Solutions
- Reference objects to objects.
- Build a MAPPER.
- Only use keys if you need to provide an external (accidental) reference. Databases, APIs, Serializations.
- Use dark keys or GUIDs when possible.
- If you are afraid of getting a big relation graph use proxies or lazy loading.
- Don't use DTOs.
https://blog.devgenius.io/code-smell-40-dtos-ca35f5d8f7c9
Sample Code
Wrong
class Teacher {
static getByID(id) {
// go to the coupled database
}
constructor(id, fullName) {
this.id = id;
this.fullName = fullName;
}
}
class School {
static getByID(id) {
// go to the coupled database
}
constructor(id, address) {
this.id = id;
this.address = address;
}
}
class Student {
constructor(firstName, lastName, id, teacherId, schoolId) {
this.firstName = firstName;
this.lastName = lastName;
this.id = id;
this.teacherId = teacherId;
this.schoolId = schoolId;
}
school() {
return School.getById(this.schoolId);
}
teacher() {
return Teacher.getById(this.teacherId);
}
}
Right
class Teacher {
constructor(fullName) {
this.fullName = fullName;
}
}
class School {
constructor(address) {
this.address = address;
}
}
class Student {
constructor(firstName, lastName, teacher, school) {
this.firstName = firstName;
this.lastName = lastName;
this.teacher = teacher;
this.school = school;
}
}
// If we need to expose a School to an external API or a Database. Another object (not school) will keep the mapping externalId<->school and so on
Detection
This is a design policy.
We can enforce business objects to warn us if we define an attribute or function including the sequence id.
Tags
Accidental
Conclusion
Ids are not necessary for OOP. You reference objects (essential) and never ids (accidental).
In case you need to provide a reference out of your system's scope (APIs, interfaces, Serializations) use dark and meaningless IDs (GUIDs).
Relations
https://blog.devgenius.io/code-smell-20-premature-optimization-60409b7f90ec
More Info
https://codeburst.io/the-one-and-only-software-design-principle-5328420712af
https://codeburst.io/coupling-the-one-and-only-software-design-problem-869e293a9f04
Credits
Photo by Maurice Williams on Unsplash
All problems in computer science can be solved by another level of indirection.
David Wheeler
https://blog.devgenius.io/software-engineering-great-quotes-3af63cea6782
This article is part of the CodeSmell Series.
https://blog.devgenius.io/how-to-find-the-stinky-parts-of-your-code-fa8df47fc39c