Category
Moving Features between Objects
Techniques that relocate methods, fields and whole classes so each responsibility lives next to the data it uses.
What these techniques solve
Code ends up in the wrong place. A method uses another class's fields more than its own, a class has grown two unrelated jobs, or callers walk long chains of getters to reach what they need. These techniques move behavior and data across class boundaries, or redraw the boundaries themselves.
Put each piece of behavior where the data it reads lives, and hide how objects are connected from the code that uses them.
Members
- Move Method: move a method to the class it uses most and leave a delegate or update callers.
- Move Field: move a field to the class whose methods actually read and write it.
- Extract Class: split a class that does two jobs into two classes.
- Inline Class: fold a class that does almost nothing into the class that uses it.
- Hide Delegate: add a method on the server so clients stop reaching through it to a delegate.
- Remove Middle Man: let clients call the delegate directly when a class only forwards calls.
- Introduce Foreign Method: add a helper in your code that takes an instance of a library class you can't edit.
- Introduce Local Extension: create a subclass or wrapper of a library class to hold several missing methods.
How to choose within this category
- A method reads another object's data more than its own: Move Method. If only part of the method envies the other class, extract that part first.
- A class has fields and methods that cluster into two groups: Extract Class. The opposite case, a class too thin to justify itself, calls for Inline Class.
- Callers write
a.getB().getC().doThing(): Hide Delegate. If the server then becomes all forwarding methods, go the other way with Remove Middle Man. The right balance shifts as code changes, so expect to move between them. - A library class lacks one method: Introduce Foreign Method. In Kotlin, C# or Swift, an extension function does this natively. In TypeScript, Python and Go, a module-level function is the idiomatic form.
- A library class lacks several methods: Introduce Local Extension. Prefer a wrapper over a subclass when the library class is final or its constructor is complex.
- A field is used mostly by another class: Move Field, usually before moving the methods that use it.
Move one member at a time and run tests after each move. Cross-class moves are where silent behavior changes hide, especially with inheritance and overrides.
See also
- Composing MethodsTechniques that split, merge and reshape method bodies so each method does one readable thing and local variables stop blocking change.
- Organizing DataTechniques that turn raw fields, magic values, arrays and type codes into objects and types that carry meaning and protect their own invariants.
- Feature EnvyA method reads and computes on another object's data more than its own. Move the logic to where the data lives.
- Large ClassA class with too many fields, methods or responsibilities, so every change risks breaking something unrelated inside it.
- Message ChainsClient code walks a chain like a.getB().getC().getD() to reach what it needs, coupling itself to every link in the path.
- Middle ManA class mostly forwards calls to another object and adds nothing. Let clients talk to the real object or fold the wrapper away.
Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.