Save 37% off PRO during our Black Friday Sale! »

値オブジェクト / Value Object

値オブジェクト / Value Object

フロントエンド百物語で発表した資料です。

2bedb1eb8f841cd3c3ae584600b016e0?s=128

OKUNOKENTARO

August 12, 2018
Tweet

Transcript

  1. ஋ΦϒδΣΫ τ "VH ϑϩϯ τΤϯ υඦ෺ޠ

  2. ஋ΦϒδΣΫ τͱ͸ w %%% ʢυϝΠϯۦಈઃܭʣ Ͱड़΂ΒΕΔ֓೦ w +BWB4DSJQUʹ͸TUSJOH OVNCFS CPPMFBOͱ͍͏

    ϓϦ ϛςΟ ϒܕ͕͋Δ w TUSJOH OVNCFSΛ5ZQF4DSJQUͰͦͷ··ѻΘͣ
 ஋ΦϒδΣΫ τͱͯ͠ఆٛ͢Δ͜ͱͰɺ ༷ʑͳ஋ΛࣝผՄೳʹ͢Δ
  3. ࣮ࡍͷҊ݅Ͱͷྫ w "2018/8"ͱ͍͏stringΛѻΘͣʹYearMonthܕͱ͢Δ w "-0900"ͱ͍͏stringΛѻΘͣʹTimeZoneܕͱ͢Δ w 1, 2, 3ͱ͍͏numberͰ͸ͳ͘UserIdܕͱ͢Δ w

    Observable<[number, string, number, number]>ͩͱҙຯෆ໌͕ͩ
 Observable<[UserId, TimeZone, PageNumber, DisplayCount]>
 ͱఆٛͰ͖Δ
  4. ࣮૷ྫ export abstract class Value<T> { constructor(protected value: T) {

    // } toString(): string { return this.value.toString(); } valueOf(): T { return this.value; } eq(other: Value<T>): boolean { return this.value === other.value; } }
  5. export class TimeZone extends StringValue { TimeZone: ProhibitDuckTyping; static UTC():

    TimeZone { return new TimeZone('+0000'); } /** * JST ͷ৔߹ɺ -540 Λ +0900 ʹม׵͢Δɻ */ static offsetToIsoTimeZone(offset: number): TimeZone { const min = Math.abs(offset); const isoTimeZone = [ `00${Math.floor(min / 60)}`.slice(-2), `00${min - Math.floor(min / 60) * 60}`.slice(-2), ].join(''); const sign = offset <= 0 ? '+' : '-'; return new TimeZone(`${sign}${isoTimeZone}`); } constructor(protected value: string) { super(value); assert(/^[+-]\d{4}/.test(value), `"${value}" ͸ɺλΠϜκʔϯͷϑΥʔϚοτͰ͸͋Γ·ͤΜ`); } }
  6. 1SPIJCJU%VDL5ZQJOH w Ҋ݅಺Ͱੜ·ΕͨϫʔΫΞϥ΢ϯ υ ʢ5ZQF4DSJQUͷਖ਼ࣜͳٕज़ͷ໊শͰ͸ͳ͍ʣ  w 5ZQF4DSJQU͸
 class A

    { value: string }ͱ
 class B { value: string }Λ
 ࠞಉͯ͠ѻ͏ ͜ͱ͕Ͱ͖Δ w ߏ੒͢ΔϓϩύςΟͷ໊শͱܕͱ૊Έ߹Θ͕ͤಉ͡ͳΒ͹ಉ͡ΠϯλϑΣʔεͰ
 ͋ΔͱΈͳ͞ΕΔ
  7. 1SPIJCJU%VDL5ZQJOH w class A { value: string; A: ProhibitDuckTyping; }


    class B { value: string; B: ProhibitDuckTyping; }
 ͷΑ ͏ʹ͢Ε͹ϓϩύςΟ໊͕" #ͰҟͳΔͷͰผͷܕѻ͍Ͱ͖Δ w 1SPIJCJU%VDL5ZQJOH͸࣮࣭͸
 export type ProhibitDuckTyping = void;