Skip to content

Working example with detailed commit history on the "replace constructor with factory function" refactoring based on Fowler's "Refactoring" book

License

Notifications You must be signed in to change notification settings

kaiosilveira/replace-constructor-with-factory-function-refactoring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Continuous Integration

ℹ️ This repository is part of my Refactoring catalog based on Fowler's book with the same title. Please see kaiosilveira/refactoring for more details.


Replace Constructor With Factory Function

Formerly: Replace Constructor with Factory Method

Before After
leadEngineer = new Employee(document.leadEngineer, 'E');
leadEngineer = createEngineer(document.leadEngineer);

Sometimes we need more control over initialization than a constructor can possibly provide, and that's where a Factory Method comes in handy: it can hide complex initialization logic, replace the resulting instance with a proxy or decorate it with complementary behavior. This refactoring helps with moving towards this approach.

Working example

Our working example is a program that creates Employee instances based on a document input plus employee type. The Employee class is straightforward:

export class Employee {
  constructor(name, typeCode) {
    this._name = name;
    this._typeCode = typeCode;
  }

  get name() {
    return this._name;
  }

  get type() {
    return Employee.legalTypeCodes[this._typeCode];
  }

  static get legalTypeCodes() {
    return { E: 'Engineer', M: 'Manager', S: 'Salesperson' };
  }
}

And some possible usages are:

const candidateDoc = { name: 'John Doe', empType: 'E' };
const candidate = new Employee(candidateDoc.name, candidateDoc.empType);

const leadEngineerDoc = { leadEngineer: 'Jane Doe' };
const leadEngineer = new Employee(leadEngineerDoc.leadEngineer, 'E');

console.log(`Candidate: ${candidate.name}, ${candidate.type}`);
console.log(`Lead engineer: ${leadEngineer.name}, ${leadEngineer.type}`);

Our goal here is to introduce a factory function, so clients don't do new employees any longer.

Test suite

Occaecat et incididunt aliquip ex id dolore. Et excepteur et ea aute culpa fugiat consectetur veniam aliqua. Adipisicing amet reprehenderit elit qui.

describe('functionBeingRefactored', () => {
  it('should work', () => {
    expect(0).toEqual(1);
  });
});

Magna ut tempor et ut elit culpa id minim Lorem aliqua laboris aliqua dolor. Irure mollit ad in et enim consequat cillum voluptate et amet esse. Fugiat incididunt ea nulla cupidatat magna enim adipisicing consequat aliquip commodo elit et. Mollit aute irure consequat sunt. Dolor consequat elit voluptate aute duis qui eu do veniam laborum elit quis.

Steps

  • introduce createEmployee function:
diff --git top level...
+export function createEmployee(name, typeCode) {
+  return new Employee(name, typeCode);
+}
  • update callers to use createEmployee instead of initializing the class themselves:
diff --git top level...
-const candidate = new Employee(candidateDoc.name, candidateDoc.empType);
+const candidate = createEmployee(candidateDoc.name, candidateDoc.empType);
// ...
-const leadEngineer = new Employee(leadEngineerDoc.leadEngineer, 'E');
+const leadEngineer = createEmployee(leadEngineerDoc.leadEngineer, 'E');
  • rename createEmployee to createEngineer:
diff --git top level...
-const candidate = createEmployee(candidateDoc.name, candidateDoc.empType);
+const candidate = createEngineer(candidateDoc.name, candidateDoc.empType);
// ...
-const leadEngineer = createEmployee(leadEngineerDoc.leadEngineer, 'E');
+const leadEngineer = createEngineer(leadEngineerDoc.leadEngineer, 'E');
// ...
-export function createEmployee(name, typeCode) {
+export function createEngineer(name, typeCode) {
  • make employee type fixed to 'E' at createEngineer:
diff --git top level...
 export function createEngineer(name, typeCode) {
-  return new Employee(name, typeCode);
+  return new Employee(name, 'E');
  • remove typeCode argument from createEngineer:
diff --git top level...
-export function createEngineer(name, typeCode) {
+export function createEngineer(name) {

And that's it!

Commit history

Below there's the commit history for the steps detailed above.

Commit SHA Message
3ff0ba7 introduce createEmployee function
75b2e05 update callers to use createEmployee instead of initializing the class themselves
e48639d rename createEmployee to createEngineer
9886939 make employee type fixed to 'E' at createEngineer
b15df82 remove typeCode argument from createEngineer

For the full commit history for this project, check the Commit History tab.

About

Working example with detailed commit history on the "replace constructor with factory function" refactoring based on Fowler's "Refactoring" book

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published