シリアライズの全体例
LT;DR
シリアライザが FP と親和性があるとは限らないので、その場合はラップして使用すると良い hr.icon
シリアライズの具体例
code:fsharp
module Domain =
open System
type Person =
{ First: String50
Last: String50
Birthdate: Birthdate }
String50 と Birthdate は制約を持つ単純型 String50 や Birthdate は直接シリアライズできないので、すべてのフィールドが プリミティブ な DTO の型を作成する code:fsharp
module Dto =
open System
type Person =
{ First: string
Last: string
Birthdate: DateTime }
ヘルパ関数 toDomain と fromDomain の実装
code:fsharp
module Dto =
module Person =
let fromDomain (person: Domain.Person): Dto.Person =
let first = person.First |> String50.value
let last = person.Last |> String50.value
let birthdate = person.Birthdate |> Birthdate.value
{ First = first; Last = last; Birthdate = birthdate }
let toDomain (dto: Dto.Person): Result<Domain.Person, string> =
result {
let! first = dto.First |> String50.create "First"
let! last = dto.Last |> String50.create "Last"
let! birthdate = dto.Birthdate |> Birthdate.create
return { First = first; Last = last; Birthdate = birthdate }
}
fromDomain は常に成功する
toDomain は制約などで失敗する可能性があるので戻り値の型は Result
JSON シリアライザのラッピング
サードパーティ製の JSON や XML のシリアライザは、戻り値が Result でないなど、FP と親和性が無い場合がある e.g. .NET JSON シリアライズライブラリ(Newtonsoft.Json)
この場合、以下のようにラップすれば良い
code:fsharp
module Json =
open Newtonsoft.Json
let serialize obj =
JsonConvert.SerializeObject obj
let deserialize<'a> str =
try
JsonConvert.DeserializeObject<'a> str
|> Result.Ok
with
| ex -> Result.Error ex
シリアライズパイプラインの全体
シリアライズパイプラインは、以下のように実装できる
code:fsharp
let jsonFromDomain (person: Domain.Person) =
person
|> Dto.Person.fromDomain
|> Json.serialize
デシリアライズパイプラインは、Json.deserialize と Dto.Person.toDomain が 異なるエラー型の Result を返すので、エラー型を合わせる必要がある
code:fsharp
type DtoError =
| ValidationError of string
| DeserialiozationException of exn
let jsonToDomain jsonString : Result<Domain.Person, DtoError> =
result {
let! deserializedValue =
jsonString
|> Json.deserialize
|> Result.mapError DeserialiozationException
let! domainValue =
deserializedValue
|> Dto.Person.toDomain
|> Result.mapError ValidationError
return domainValue
}
複数バージョンのシリアライズ型を扱う
時間の経過とともに設計は進化する
ドメインイベント または DTO の定義を変更する場合、影響を受ける他のコンテキストの所有者と協議してから行う必要がある この契約を違反しないように複数バージョンの DTO を管理しなければならない場合もある