From "Refactoring"
🎧 Listen to Summary
Free 10-min PreviewStructuring and Naming Data Entities
Key Insight
Field names within data structures are critical for understanding software, especially when these structures are widely used. Clear, descriptive names are essential as understanding evolves during software development. The 'Rename Field' refactoring addresses situations where a field's name needs updating to reflect an improved understanding of its purpose. This principle extends to classes, where getter and setter methods effectively act as field names for class users, making their renaming equally important. If a record has limited scope, renaming all accesses and testing suffices. For widely used records, 'Encapsulate Record (162)' is typically the first step. Then, the private field inside the object is renamed, internal methods are adjusted, and 'Change Function Declaration (124)' is applied to the constructor if it uses the name. Finally, 'Rename Function (124)' is applied to the accessors. An example demonstrates changing a 'name' field to 'title' in an 'organization' object, first by encapsulating it into a class and then systematically updating the internal field, constructor, and accessors.
When nesting objects, an inner object can be treated as a reference or a value. As a reference, updates modify the existing inner object; as a value, updates replace the entire inner object with a new one containing the desired property. 'Change Reference to Value (252)' allows an inner object to become a Value Object, which are generally immutable and easier to reason about, especially in distributed and concurrent systems, as they can be safely passed around without concerns about unexpected changes or memory links. This refactoring is suitable when an object does not need to be shared and modified across multiple collaborators. The process involves ensuring the candidate class is or can become immutable, applying 'Remove Setting Method (331)' for each setter, and providing a value-based equality method that compares field values. An example transforms a mutable 'TelephoneNumber' object nested within a 'Person' object into an immutable value object by modifying its constructor and converting setter calls to reassignment of a new 'TelephoneNumber' instance, along with implementing an 'equals' method for value-based comparison.
Conversely, 'Change Value to Reference (256)' addresses situations where multiple data structures (values) represent the same logical entity, leading to data duplication and potential inconsistencies if the entity needs to be updated. For instance, multiple orders might contain separate copies of the same customer data. If this shared data needs to be modified, updating all copies becomes problematic. This refactoring consolidates these copies into a single reference, ensuring that any change to the shared object is visible across all collaborators (e.g., all orders referring to the same customer). This typically involves creating a repository to store and retrieve unique instances of the related object, then changing the constructors for the host object to use this repository to obtain the correct, shared instance, rather than creating new value copies. An example shows an 'Order' constructor that initially creates a new 'Customer' object from 'data.customer' being refactored to use a global repository's 'registerCustomer' function, thereby ensuring all orders referencing the same customer ID link to the identical 'Customer' object.
📚 Continue Your Learning Journey — No Payment Required
Access the complete Refactoring summary with audio narration, key takeaways, and actionable insights from Martin Fowler, Kent Beck.