Slide 1

Slide 1 text

co-IT.eu GmbH Creative Solutions Empower Outstanding Innovation Revenent Software Patterns @GregOnNet

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

WHY SOFTWARE PATTERN MATTER Our all day work! Find it. Implement it. Test it. “ Extracting patterns…

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

WHY SOFTWARE PATTERN MATTER Please do this at your office, too This is how you feel if you find a pattern. “

Slide 6

Slide 6 text

FACTORY VS BUILDER What I think about applying software patterns… Using the correct pattern can be tricky. “

Slide 7

Slide 7 text

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 “

Slide 8

Slide 8 text

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; } }

Slide 9

Slide 9 text

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 “

Slide 10

Slide 10 text

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); } }

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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 ?

Slide 13

Slide 13 text

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 … ;-)

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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!

Slide 16

Slide 16 text

FACTORY VS BUILDER Real Builder – Introducing Kentan Kentan used by

Slide 17

Slide 17 text

FACTORY AND BUILDER What is Kentan? Technically it is a factory that gives you a builder. :D “

Slide 18

Slide 18 text

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 “

Slide 19

Slide 19 text

Let’s dive into the code…

Slide 20

Slide 20 text

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 “

Slide 21

Slide 21 text

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"); } }

Slide 22

Slide 22 text

STRATEGY PATTERN Execute a Strategy export class Context { private strategy: Strategy; constructor(strategy: Strategy) { this.strategy = strategy; } public executeStrategy(): void { this.strategy.execute(); } }

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

STRATEGY PATTERN Benefits 1. Divide and Conquer 2. You get small modules that can be tested more easily (SRP).

Slide 26

Slide 26 text

Yes, more code! Click here to view the Code

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

WAYS TO HANDLE RESULTS OF AN API

Slide 29

Slide 29 text

The core idea OPTION TYPE export interface OptionType { match(some: (value: T) => S, none: (reason: Reason) => S): S; }

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Usage OPTION TYPE developer .isHappy(true) .match( isHappy => expect(isHappy).toBe('You rock! Never quit!’), reason => logger.warn(‘Out of coffee!’) );

Slide 33

Slide 33 text

Last demo fo today… J Click here to view the Code

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

co-IT.eu GmbH Creative Solutions Empower Outstanding Innovation Special Thanks To @FrankStrieter Frank Strieter

Slide 36

Slide 36 text

co-IT.eu GmbH Creative Solutions Empower Outstanding Innovation Thank you! @GregOnNet