2010-11-06
Debasish Ghosh さん (@debasishg ) の “sjson: Now offers Type Class based JSON Serialization in Scala ” を翻訳しました.
元記事はこちら: http://debasishg.blogspot.com/2010/07/sjson-now-offers-type-class-based-json.html
(翻訳の公開は本人より許諾済みです)
翻訳の間違い等があれば遠慮なくご指摘ください
長い間 sjson のシリアライゼーション API はリフレクションに依存するものだった.この方法の長所としては,縁の下ではリフレクションによる実装が頑張っていても API は使いやすくすることができたということだ.
しかし,JSON 構造と Scala のオブジェクトでは型情報の豊かさに大きな違いがあることを忘れてはいけない.Scala から JSON にいくときに何らかの形で型情報をシリアライゼーションプロトコルの一部として保存しないかぎり,可逆変換させるのは場合によってはとてもトリッキーで難しいことになる.特に JVM では type erasure のせいで JSON構造にシリアル化した Scala オブジェクトの中には元に戻すのがほぼ不可能なものもあるだろう.
ver 0.7 より sjson は元のものに加えリフレクションを使わない JSON シリアライゼーションプロトコルを用意した.これはユーザが任意のオブジェクトから JSON へシリアル化する自分のプロトコルを規定できるようになった.リフレクションによる JSON シリアライゼーション ではアノテーションで行っていたものをカスタムプロトコルを自分で実装することで実現することができる.
sjons の型クラスによるシリアライゼーションは David MacIver による素晴らしい sbinary (現在は Mark Harrah によりメンテ されいる) にインスパイアされており,同じプロトコルを使いまた実装レベルでも色々と盗ませてもらった.
型クラスの基礎的概念への入門,Scala での実装,そして型クラスを使ったシリアライゼーションプロトコルが Scala でどう設計できるかについては,数週間前に書いた以下の blog 記事を参照してほしい:
組み込み型の JSON シリアライゼーション
これは sjson でデフォルトのシリアライゼーションプロトコルを使った REPL セッションの一例だ…
2010-11-03
Debasish Ghosh さん (@debasishg ) の “Scala Implicits : Type Classes Here I Come ” を翻訳しました.
元記事はこちら: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
(翻訳の公開は本人より許諾済みです)
翻訳の間違い等があれば遠慮なくご指摘ください.
先日 Twitter 上で Daniel と Scala での型クラスについて論議していると,突然このトピックに関する書きかけだった記事を発見した.これを読んでもあなたは特に目新しい事を発見するわけではないが,型クラスに基づいた思考はあなたの設計の幅に価値を与えることができると思う.この記事を書き始めたのはしばらく前に設計の直交性についての記事 (原文) を公開したときのことだ.
まずは GoF の Adapter パターンから始めよう.委譲型の Adapter はよく勧められる合成(composition)というテクニック用いて抽象体(abstraction) どうしをバインドする.
設計の直交性のときと同じ例を使うと,
case class Address ( no: Int , street: String , city: String ,
state: String , zip: String )
これを LabelMaker というインターフェイスに適合させたいとする.つまり,我々は Address オブジェクトを LabelMaker として使いたい.
trait LabelMaker [ T ] {
def toLabel( value: T ) : String
}
インターフェイス変換を行うアダプターは…
// Adapter クラス
case class AddressLabelMaker extends LabelMaker [ Address ] {
def toLabel( address: Address ) = {
import address._
"%d %s, %s, %s - %s" . format( no, street, city, state, zip)
}
}
// この Adapter は Address オブジェクトに LabelMaker のインターフェイスを提供する.
AddressLabelMaker (). toLabel( Address ( 100 , "Monroe Street" , "Denver" , "CO" , "80231" ))
さて,上の設計で我々が副次的に導入してしまった複雑さはなんだろう?
2010-11-03
Debasish Ghosh さん (@debasishg ) の “Refactoring into Scala Type Classes ” を翻訳しました.
元記事はこちら: http://debasishg.blogspot.com/2010/07/refactoring-into-scala-type-classes.html
(翻訳の公開は本人より許諾済みです)
翻訳の間違い等があれば遠慮なくご指摘ください.
二週間ほど前に Scala の暗黙の(implicit)パラメータを用いた型クラスの実装 について書いた.型クラスはある抽象体(abstraction)についての直交した関心事を,抽象体そのものに直接組み込むことなくモデル化することができる.これでコアな抽象体から余計なものを取り去って,別々の独立したクラス構造に変えていくことができる.最近 Akka actor のシリアライゼーションをリファクタリングして型クラスの恩恵に関する実地的な知見を得ることができたので,ここに報告したい.
最初は継承と trait でうまくいくと思った…
… しかし,それは長続きしなかった.Jonas Boner と筆者の間で actor のシリアライゼーションに関して面白い論議があり,以下のような設計が生まれた …
trait SerializableActor extends Actor
trait StatelessSerializableActor extends SerializableActor
trait StatefulSerializerSerializableActor extends SerializableActor {
val serializer: Serializer
//..
}
trait StatefulWrappedSerializableActor extends SerializableActor {
def toBinary: Array [ Byte ]
def fromBinary( bytes: Array [ Byte ])
}
// .. 以下続く
このような trait はシリアライゼーションという関心事をコアな actor の実装と結合(couple)させすぎてしまう.様々なシリアライズ可能な actor があるため,良いクラス名が足りなくなってきていた.GoF本が教えてくれる知恵の一つにインターフェイスを用いたクラスの命名に困るとしたら,間違ったことをやっている,というものがある.関心事をより意味のある方法で分割する別のやり方を探ろう.
型クラスだ
コアの actor 抽象体からシリアライゼーションに関するコードを抜き出し,別の型クラスにした.
/**
* Actor 直列化のための型クラス定義
*/
trait FromBinary [ T <: Actor ] {
def fromBinary( bytes: Array [ Byte ], act: T ) : T
}
trait ToBinary [ T <: Actor ] {
def toBinary( t: T ) : Array [ Byte ]
}
// クライアントはそれぞれの Actor のための Format[] を実装する必要がある
trait Format [ T <: Actor ] extends FromBinary [ T ] with ToBinary [ T ]
actor をシリアライズ可能にするためにクライアントが実装する必要がある FromBinary[T <: Actor] と ToBinary[T <: Actor] という二つの型クラスを定義した.これをさらに Format[T <: Actor] という二つを合わせた trait に組み合わせた.