Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Revenent TypeScript Patterns

Revenent TypeScript Patterns

In this talk, I speak about software patterns that I use very often on my projects.

You will see samples covering the Builder, Factory, Strategy and Option-Type Pattern.

Have fun.
Don't hesitate to ask me any question on Twitter: @GregOnNet

P.S.

If you want to check out the code samples for the strategy and option-type pattern, please have a look on:

- Strategy: https://github.com/GregOnNet/kentan-schematics/blob/master/src/lib/angular-project/angular-project.ts#L12
- Option-Type: https://github.com/GregOnNet/kentan-schematics/blob/master/src/lib/model-finder/model-finder.ts#L17

Gregor Woiwode

May 08, 2018
Tweet

More Decks by Gregor Woiwode

Other Decks in Programming

Transcript

  1. AGENDA What are we going to discuss? 1. WHY should

    we care about Software Patterns? 2. Factory vs. Builder Pattern 3. Strategy Pattern 4. Option Types
  2. WHY SOFTWARE PATTERN MATTER Our all day work! Find it.

    Implement it. Test it. “ Extracting patterns…
  3. WHY SOFTWARE PATTERN MATTER It‘s all about your happiness! 1.

    Increase Modularity 2. Increase Extensibility 3. Increase Testability A B C D E 4. Increase Reusability 4. Orchestrate Features with ease
  4. WHY SOFTWARE PATTERN MATTER Please do this at your office,

    too This is how you feel if you find a pattern. “
  5. FACTORY VS BUILDER What I think about applying software patterns…

    Using the correct pattern can be tricky. “
  6. FACTORY VS BUILDER Factory Define an interface for creating an

    object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. - GoF “
  7. FACTORY VS BUILDER Factory export namespace ProductFactory { export function

    createProduct(type: string) : AbstractProduct { if (type === "A") { return new ConcreteProductA(); } else if (type === "B") { return new ConcreteProductB(); } return null; } }
  8. FACTORY VS BUILDER Builder Separate the construction of a complex

    object from its representation so that the same construction process can create different representations. - GoF “
  9. FACTORY VS BUILDER Builder export class UserBuilder { private _address:

    string; setAddress(value: string): UserBuilder { this._address = value; return this; } get address(): string { return this._address; } build(): User { return new User(this); } }
  10. FACTORY VS BUILDER Builder const user = new UserBuilder() .setName('Jan‘)

    .setAddress('Kriegsstr. 39, Karlsruhe‘) .setAge(30) .build(); 1. Provides a fluent interface aka. method chaining 2. Configurable
  11. FACTORY VS BUILDER Use Case - Generate Test Data Effectively

    1. Project having a deeply nested data structure. 2. Tests become hard to write since complex test setups. 3. Solution needed to speedup test process Factory or Builder ?
  12. FACTORY VS BUILDER Approach - Builders export class DocumentDataBuilder {

    /* ... */ withAllBuilds(builds: LatestBuilds): DocumentDataBuilder { /* ... */ } withSuccessfulBuilds(builds: LatestSuccessfulBuilds): DocumentDataBuilder { /* ... */ } /* ... */ build(): DocumentData { return this.documentData; } } 1. We used builder first 2. We built lots of builders … ;-)
  13. FACTORY VS BUILDER 1. … hard to use with greater

    data structures 2. … difficult to maintain as the model changes Approach - Builders boforeEach(() => { document = aDocumentData() .withLatestBuilds( aDocumentLatestBuilds() .withHandout( aDocumentLatestBuild() .withStatus(Status.New) .build() ) .build() ) .build(); }); 3. Tests become hard to read 4. We break the builder pattern unintentionally not really
  14. FACTORY VS BUILDER Approach – Real Builder 1. Make creation

    process reusable 2. Handle combination of multiple models 3. Provide API to read and update data Factory and Builder!
  15. FACTORY AND BUILDER What is Kentan? Technically it is a

    factory that gives you a builder. :D “
  16. FACTORY AND BUILDER What we achieve with Kentan document =

    aDocumentData() .withLatestBuilds( aDocumentLatestBuilds() .withHandout( aDocumentLatestBuild() .withStatus(Status.New) .build() ) .build() ) .build(); document = Kentan.sketch(ForDocumentData) .set(d => d.handout.latestBuilds.status = Status.New ) .model(); AFTER BEFORE Massive code reduction arranging tests “
  17. STRATEGY PATTERN Strategies Define a family of algorithms, encapsulate each

    one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. - GoF “
  18. STRATEGY PATTERN Strategies export interface Strategy { execute(): void; }

    export class ConcreteStrategy1 implements Strategy { public execute(): void { console.log("`execute` method of ConcreteStrategy1 is being called"); } } export class ConcreteStrategy2 implements Strategy { public execute(): void { console.log("`execute` method of ConcreteStrategy2 is being called"); } }
  19. STRATEGY PATTERN Execute a Strategy export class Context { private

    strategy: Strategy; constructor(strategy: Strategy) { this.strategy = strategy; } public executeStrategy(): void { this.strategy.execute(); } }
  20. STRATEGY PATTERN When to use? 1. If you experience different

    behavior needs to be applied certain conditions 2. Practicak hint: Huge if-else-Trees or switch-case-Statements indicate different strategies Samples Product Categories, Customer Segments, Order Priorities
  21. STRATEGY PATTERN Benefits 1. Divide and Conquer 2. You get

    small modules that can be tested more easily (SRP).
  22. OPTION TYPES Provide More Guidance to your team memebers 1.

    Allow an explicit handling of nullable values 2. Provide an API for other Developers to deal with the Results of certain operations 3. Reduce state information in your classes
  23. The core idea OPTION TYPE export interface OptionType<T> { match<S>(some:

    (value: T) => S, none: (reason: Reason) => S): S; }
  24. OPTION TYPE Some export class Some<T> implements OptionType<T> { constructor(private

    readonly value: T) {} match<S>(some: (value: T) => S, _none: (reason: Reason) => S): S { return some(this.value); } }
  25. None OPTION TYPE export class None<T> implements OptionType<T> { constructor(private

    readonly reason: Reason) {} match<S>(_some: (value: T) => S, none: (reason: Reason) => S): S { return none(this.reason); } }
  26. Usage OPTION TYPE developer .isHappy(true) .match( isHappy => expect(isHappy).toBe('You rock!

    Never quit!’), reason => logger.warn(‘Out of coffee!’) );
  27. SUMMARY My learnings 1. Finding patterns is fun 2. Patterns

    help to get change requests done quicklier 3. Smaller code pieces are easy to test and composable 4. Patterns can help to build APIs developer like to reuse