Skip to content

Instantly share code, notes, and snippets.

@trikitrok
Last active March 21, 2025 00:31
Show Gist options
  • Save trikitrok/17258c4d3abd03b3b92fe4d5fc8e64ba to your computer and use it in GitHub Desktop.
Save trikitrok/17258c4d3abd03b3b92fe4d5fc8e64ba to your computer and use it in GitHub Desktop.
class FileTransactionsRepository implements TransactionsRepository {
public getAll(): Transaction[] {
let transactions: Transaction[] = [];
// read the transactions from some file...
return transactions;
}
}
class Account {
private transactions: Transaction[];
constructor() {
const transactionsRepository = new FileTransactionsRepository();
this.transactions = transactionsRepository.getAll(); // <- side effect in a constructor!! x(
}
// more code...
}
//////////////////////////////////////////////
// After extracting the factory method,
// you can apply Subclass & Override Method
class Account {
private transactions: Transaction[];
constructor() {
// extracted a factory method
this.transactions = this.getAllTransactions();
}
// factory method <- now apply Subclass & Override Method here
protected getAllTransactions(): Transaction[] {
return new FileTransactionsRepository().getAll();
}
// more code...
}
//////////////////////////////////////////////
// After applying Subclass & Override Method
class Account {
private transactions: Transaction[];
constructor() {
this.transactions = this.getAllTransactions();
}
// made protected for testing :(
protected getAllTransactions(): Transaction[] {
return new FileTransactionsRepository().getAll();
}
// more code...
}
//////////////////////////////////////////////
// For some test we override the protected method to avoid the side effect in the constructor
class ForTestingAccount extends Account {
private static transactions: Transaction[];
public static create(someTransactions: Transaction[]): Account {
// The field transactions and its initialization need to be static
// so that the field gets initialized before the super class constructor is called
ForTestingAccount.transactions = someTransactions;
return new ForTestingAccount();
}
private constructor() {
super();
}
protected override getAllTransactions(): Transaction[] {
return ForTestingAccount.transactions;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment