Skip to content

Instantly share code, notes, and snippets.

@ghsyeung
Last active January 4, 2017 04:43
Show Gist options
  • Save ghsyeung/44598be056fec830ee296ddb422db9bb to your computer and use it in GitHub Desktop.
Save ghsyeung/44598be056fec830ee296ddb422db9bb to your computer and use it in GitHub Desktop.
Dependency Injection Distilled
class Foo {
constructor(private _bar: Bar) {}
}
class Bar {}
const bar = new Bar();
const foo = new Foo(bar);
// Do the above for like 500 lines...finally you can use it
foo.doSomething();
class FooModel {}
class BarModel {}
class DBModule {
public fooModel: FooModel;
public barModel: BarModel;
constructor() {
this.fooModel = new FooModel();
this.barModel = new BarModel();
}
}
class BarStatisticsModule {
public barStatisticsCalculator: BarStatisticsCalculator;
construtor(dbModule:DBModule) {
this.barStatisticsCalculator = new BarStatisticsCalculator(dbModule.barModel);
}
}
const dbModule = new DBModule();
const barStatisticsModule = new BarStatisticsModule(dbModule);
// To Use
barStatisticsModule.barStatisticsCalculator.doSomething();
// Let's define functions as a type
type F0<R> = () => R;
type F1<A1, R> = (a: A1) => R;
type F2<A1, A2, R> = (a1: A1, a2: A2) => R;
type ReportType = 'FancyReport' | 'ConsoleReport';
interface BarStatistics extends Statistics {}
// The Typescript syntax is a bit archaic (you need to repeat it twice) but bare with me
function BarStatisticsReport({ getBars, generateStatistics, getReportWriter, generateReportFromStatistics }:{
// Here are my dependencies
getBar: F1<BarID[], Bar[]>,
generateStatistics: F1<Bar[], BarStatistics>,
getReportWriter: F1<ReportType, ReportWriter<ReportType>>,
generateReportFromStatistics: F2<BarStatistics, ReportWriter<ReportType>, Report>
}):F2<BarID[], ReportType, Report> {
// Here I am returning the constructed function
return (barIds: BarID[], reportType:ReportType) => {
const bars = getBar(barIds);
const stats = generateStatistics(bars);
const reportWriter = getReportWriter(reportType);
return generateReportFromStatistics(stats, reportWriter);
};
}
// Here's the dependency injection
const fn_barStatisticsReport = BarStatisticsReport({
// I am assuming all the following functions are already created similar to this
getBars: getBars,
generateStatistics: generateStatistics,
getReportWriter: (type:ReportType) => reportWriterRepo.get(type),
generateReportFromStatistics: generateReportFromStatistics,
});
// To use
const fancyReport = fn_barStatisticsReport([ 'bar1', 'bar2', 'bar3' ], 'FancyReport');
/**
* If you haven't read the benefit analysis portion, I challenge you to think about the following question
* Which approach do you think would be easier to write test for? Or are they the same?
* 1) for Isolation tests
* 2) for Integration tests
* 3) for E2E tests
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment