Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

オブジェクト指向開発におけるObject-Functional Programming

4,990 views

Published on

Published in: Technology
  • Be the first to comment

オブジェクト指向開発におけるObject-Functional Programming

  1. 1. オブジェクト指向開発における Object-Functional Programming 2014年年11⽉月14⽇日 Everforth 浅海智晴
  2. 2. 自己紹介 • 1985年年富⼠士通(株)⼊入社 • UNIXワークステーション/サーバーのOS、分散基盤、Web 基盤の開発に従事 • 2001年年9⽉月に独⽴立立 • 浅海智晴事務所を設⽴立立 • Java, XML, UMLを中⼼心に活動 • 2005年年4⽉月より2007年年3⽉月まで • 稚内北北星学園⼤大学東京サテライト校教授 • 現在 • (株) 匠BusinessPlace 取締役チーフコンサルタント • (株) Everforth 取締役CTO
  3. 3. ApparelCloud  データを一元化することで、多様な情報を、様々なメディア・デバイスを 通じて  消費者に届け、真のCRMを実現する仕組み。 http://www.apparel-cloud.com/
  4. 4. ApparelCloud 複数メディア・コンテンツを⼀一元管理理し、クオリティの統⼀一と運⽤用コストの低減を実現。 コンテンツを⼆二重三重に登録する必要もなく、データ分析などの⼀一元化も可能。 ブランド ブログ アプリ コンテンツ集計・分析 クーポン ブランドサイトオンラインスト ア ニュースブログショップ ダッシュボード
  5. 5. ApparelCloud Apparel Cloud 構成概要 ソリューション名: Apparel Cloud 提供元:apparel-‐‑‒web C社製品D社製品 B社製品 Paas 提供元:EverforthApparel Cloud プラットフォーム AWSIaaS 提供元:Amazon ブログアプリ Option機能 ショップアプリ ベーシック SaaS 提供元:apparel-‐‑‒web :パートナー企業 ・Apparel Cloud Private Project 特定企業向け型 ・Apparel Cloud テンプレート型 A社製品 5 顧客情報 Blog・ブランド・SHOP 情報 フォロー・LIKE情報 クーポン情報 商品情報 etc ブランドアプリ ベーシック ショップアプリ Option機能 ECアプリ メンバーアプリ 情報集積(PV,フォロー・ like数etc……) 各option スマートフォン・PCへの 配信情報登録 API(個々のアプリはAPI通信) PUSH配信
  6. 6. アジェンダ 背景 関数型プログラミング Monadic Programming Object-Functional Programming オブジェクト指向開発+OFP
  7. 7. 背景
  8. 8. 新しい現実 ハードウェア • メニーコア、⼤大容量量メモリ、SSD • インメモリデータベース • 並列列プログラミング クラウド・プラットフォーム • クラウド・サービス、スマート・デバイス • 故障、遅延 • ⼤大規模データ、⼤大規模演算 • ⾼高頻度度イベント、ストリーミング • ⾮非同期、並列列、分散 • NoSQL
  9. 9. アプリケーションの階層と役割 • DSLの作法に従ってビジネスロ ジックを記述 • OO、関数型のスキルは最低限 アプリケー ション • フレームワークを簡単に使⽤用する ための専⽤用⾔言語 • OO、関数型の⾼高度度なスキル DSL • ドメインの共通処理理を記述 • OO、関数型の⾼高度度なスキル フレーム ワーク
  10. 10. プログラム開発の構造
  11. 11. API vs DSL
  12. 12. オブジェクト指向開発概観 ドメイン・モデル ビジネス フロー ビジネス ユースケースユースケースサービス ビジネス・モデルシステム分析モデルシステム設計モデル
  13. 13. ApparelCloud システム構成 Scala Java Scala Scala Scala Java Scala Java
  14. 14. Everforthの開発⼿手法 Everforh Engine 開発 ビジネス・プロセス・モデル (Mindmap) アプリケーション・モデル (画面+API) ドメイン・モデル (テキストDSL) エンティティ(Scala) EverforthModeler Service (Scala) 設定 (S式, LTSV) Extension (Scala) 自動コーディング 組込みService (Scala) 組込みExtension (Scala) ScalaScala 114Kstep140Kstep
  15. 15. 関数型プログラミング
  16. 16. Scala • 強い静的型付けジェネリック型 • オブジェクト指向 • Java • 関数型 • ラムダ計算 • パターンマッチング • モナド • 型クラス • 最新のプログラミング⾔言語技術の総合技術 • いろいろな⾔言語の美点を貪欲に取り⼊入れている • DSL (Domain Specific Language) • 内部DSL, 外部DSLを⽀支援する機能が満載 • JavaVM • 安定した実⾏行行環境 • Java資産の活⽤用
  17. 17. Scala(ble) ⼩小規模 Webシス テム 中規模 業務シ ステム ⼤大規模 分散シ ステム
  18. 18. 関数型⾔言語とは • ⾼高階関数を扱える。 • 関数を値として扱える。 • 関数の引数と返却値に関数を渡せる。 • 関数リテラル(クロージャ)が記述できる。 • 数学(ラムダ計算、数理理論論理理学、圏論論など)的にプログラ ムを記述できる。
  19. 19. 関数型⾔言語の系譜 元祖関数型⾔言語 • pure Lisp • ラムダ計算 伝統的関数型 ⾔言語 • Lisp, ML, OCaml • ラムダ計算 • ⼿手続き、オブジェ クト指向で補完 • 抽象データ型 • Subtype polymorphism 新世代関数型 ⾔言語 • Haskell • Scala(+scalaz) • ラムダ計算 • 代数、圏論論 • 型クラス • 代数データ型、 モナド • Parametric polymorphism 浅海私⾒見見。 20年年ほどの空⽩白の後の⾒見見え⽅方、 あるいはOOプログラマが後追い で調べたときの⾒見見え⽅方と考えて ください。
  20. 20. 関数型⾔言語の⻑⾧長所と短所 ⻑⾧長所 • ⾼高階関数を使った技が使える • List, 関数合成(コンビネータ)など • 定理理と証明 • 証明された(動作保証された)定理理(関数)を積み上げてプログラ ムを記述できる (← 多少理理想論論も⼊入ってます) 短所 • 関数実⾏行行のオーバーヘッド • 関数オブジェクト • メモリを⼤大量量に消費する • 関数オブジェクト • データの⼤大量量複写 • スタックの使⽤用量量が読めない • 再帰
  21. 21. 関数型⾔言語の技術マップ
  22. 22. 代数的構造デザインパターン 結合律律 (associative law) • 半群 (semigroup) • モノイド (monoid) • 群 (group) 可換律律 (commutative law) • 可換半群 • 可換モノイド • 可換群(アーベル群) 分配律律 (distributive law) • 環 (ring) • 体 (field) (a + b) + c = a + (b + c) a + b = b + a a * (b + c) = a * b + a * c
  23. 23. 圏論論デザインパターン 圏 (category) • Hask圏 (Scala圏?) • クライスリ圏 (kleisli category) 射 (arrow, morphism) 関⼿手 (functor) モナド (monad) Applicative functor
  24. 24. 基本概念 • 再帰 (recursion) • ⾼高階関数 (high-order function) • 不不変データ (immutable data) • 遅延評価 (lazy evaluation) • 参照透過性 (referential transparency) • (項)書換えモデル (substitution model) • 等式推論論 (equational reasoning) • 代数的データ型 (algebraic data type) • 直積, 直和 (direct product, direct sum) • 永続データ構造 (persistent data structure) • エフェクト (effect) • 型クラス (type class) • モナド (monad)
  25. 25. A → B • 関数の基本 • 型Aの値を型Bの値に置き換える (置き換えモデル, substitution model) • 副作⽤用はないので、A→Bの関数の外側にいかなる影響も 与えない (no side effect) • 型Aの値が同じなら、いかなるタイミングで呼び出して も型Bの同じ値が返る (参照透過性, referential transparency) • 論論理理学:ならば(imply) • 圏論論:射(arrow, morphism) • Readerモナド • def f(x: A): B
  26. 26. A → B → C • 引数が2つある関数 • 「A → B」の形の関数(引数が1つ)の合成で記述 • A → (B → C) • Aを引数に取り「B→Cの関数」を返す関数 • def f(a: A, b: B): C • def f(a: A)(b: B): C • def f(a: A): B = C • val f: A = B = C
  27. 27. A → A → A • 「A → B → C」の特殊な形 • A, B, Cが同じ型 • ⼆二項演算⼦子 • 型Aがモノイドの候補 • f(x: A, y: A): A • 1 + 1 → 2 • “abc” + “xyz” → “abcxyz” • List(“abc”) ++ List(“xyz”) → List(“abc”, “xyz”)
  28. 28. A → M[B] • 「A → B」の特殊な形 • 「B」の部分が「M[B]」となっている • Mはモナド、モナドMがBをくるんでいる形 • モナドのbind演算(flatMap)で使⽤用する • Reader Transformer(Kleisli) • def flatMap[A, B](f: A = List[B])
  29. 29. その他 • A→A • Endo関数 • Monoidとして利利⽤用可 • S→S×A • Stateモナド • S→M[S×A] • State Transformer
  30. 30. 代数的データ型 • Algebraic data type • 直積 (direct product) • 論論理理学: ∧(論論理理積、かつ) • Tuple • Case class • 直和 (direct sum) • 論論理理学: ∨(論論理理和、または) • Either • sealed trait/abstract class + case class/case object
  31. 31. 代数的データ型 ケースクラスで直積を実現 case class Person(name: String, age: Int) Case class Company(name: String, phone: String) Eitherで直積の直和を実現 Either[Person, Company] sealedトレイトで直積の直和 sealed trait Party case class Person(name: String, age: Int) extends Party case class Company(name: String, phone: String) extends Party
  32. 32. 永続データ構造 • Persistent data structure • 変更更される際に変更更前のバージョンを常に保持するデータ構造で ある。このようなデータ構造は、更更新の際に元のデータ構造を書 き換えるのではなく、新たなデータ構造を⽣生成すると考えられ、 イミュータブルなデータ構造の構築に利利⽤用可能である(Wikipedia)
  33. 33. 型クラス • In computer science, a type class is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types. (Wikipedia) • ⾮非公式理理解 • OOPのクラスの関数型バージョン • OOPでも有効に使⽤用できる • OOPのクラスとの違い • コンパイル時にポリモーフィズムが解決される • 任意のクラスに後付けで設定できる • ⽂文脈によって切切り替えて使⽤用できる • Scalaでは暗黙パラメタで実現
  34. 34. 型クラスの使⽤用例例 case class Average(total: Double, count: Int) { def value = total / count def +(rhs: Average) = Average(total + rhs.total, count + rhs.count) } object Average { implicit object AverageMonoid extends Monoid[Average] { def append(lhs: Average, rhs: = Average) = lhs + rhs def zero = Average(0, 0) } }
  35. 35. object MonoidSample { import Average.AverageMonoid def concatenate[T: Monoid](xs: Vector[T]): T = { val C = implicitly[Monoid[T]] xs.foldLeft(C.zero)((z, x) = z |+| x) } def sample { val a: Int = concatenate(Vector(1, 2, 3)) assert(a == 6) val b: Average = concatenate[Average](Vector( Average(1.0, 1), Average(2.0, 2), Average(3.0, 3))) assert(b == Average(6.0, 6)) } def main(args: Array[String]) { sample } }
  36. 36. Monadic Programming
  37. 37. モナド • 計算機科学におけるモナド(Monads)とは、計算機科学者の Eugenio Moggiによって提案されたモジュール性を持たせた 表⽰示的意味論論の枠組みを⾔言う。プログラムとはクライスリ圏 の射である(a program is an arrow of a Kleisli category)、 という要請から合成規則としてクライスリトリプル(Kleisli triple)というモナドと等価なものが⽤用いられる。(Wikipedia) • In functional programming, a monad is a structure that represents computations defined as sequences of steps: a type with a monad structure defines what it means to chain operations, or nest functions of that type together. This allows the programmer to build pipelines that process data in steps, in which each action is decorated with additional processing rules provided by the monad. (Wikipedia) • ⾮非常に難しい概念念 • 使うのは(なれれば)それほど難しくない • モダンな関数型プログラミングの中核概念念
  38. 38. モナドの⾮非公式理理解 • コンテナ • コレクション(List, Vector) • 成功失敗⽂文脈(Option) • パイプライン • map, filter, collect • flatMap • コマンド・インタープリタ • Freeモナド, Operationalモナド
  39. 39. 代表的なモナド • Option • 成功/失敗状態を扱うモナド • List • オブジェクト列列を扱うモナド(シーケンシャルアクセス向け) • Vector • オブジェクト列列を扱うモナド(ランダムアクセス対応) • Stream • 遅延評価によるオブジェクト列列を扱うモナド • Try • 例例外発⽣生状態を扱うモナド • 例例外というエフェクトを隠蔽 • Future • 並列列実⾏行行を扱うモナド • 実⾏行行時間というエフェクトを隠蔽
  40. 40. モナド • 難解な概念念 • http://ja.wikibooks.org/wiki/Haskell/%E5%9C%8F%E8%AB%96 • ⾮非公式理理解 • 型安全汎⽤用フレームワーク基底クラス
  41. 41. Scalaz • https://github.com/scalaz/scalaz • キャッチフレーズ • 昔: Scalaz: Type Classes and Pure Functional Data Structures for Scala • 今: An extension to the core Scala library for functional programming. http://typelevel.org • 最新の関数型プログラミングを可能にする機能群を Scala向けに⽤用意 • 型クラス • 純粋関数型データ構造
  42. 42. Monadicプログラミングの効⽤用 Java⾵風 def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = {! val a = validateName(name) ! val b = validateAge(age) ! if (a.isSuccess b.isSuccess) { ! val a1 = a.asInstanceOf[Success[NonEmptyList[Throwable], String]].a ! val b1 = b.asInstanceOf[Success[NonEmptyList[Throwable], Int]].a ! Success((a1, b1)) ! } else if (a.isSuccess) { ! b.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else if (b.isSuccess) { ! a.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else { ! val a1 = a.asInstanceOf[Failure[NonEmptyList[Throwable], String]].e ! val b1 = b.asInstanceOf[Failure[NonEmptyList[Throwable], Int]].e ! Failure(a1 |+| b1) ! } ! }!
  43. 43. Scala (関数型プログラミング) def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = { ! validateName(name) match { ! case Success(a) = validateAge(age) match { ! case Success(b) = Success((a, b)) ! case Failure(e) = Failure(e) ! } ! case Failure(e1) = validateAge(age) match { ! case Success(b) = Failure(e1) ! case Failure(e2) = Failure(e1 |+| e2) ! } ! } ! } ! Scalaz (Monadicプログラミング) def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = { ! (validateName(name) ⊛ validateAge(age))((_, _)) ! }! URL: http://modegramming.blogspot.jp/2012/04/ scala-tips-validation-10-applicative.html
  44. 44. パイプライン・プログラミング
  45. 45. Stateモナドによるパイプライン State Monad State Funcion Function Function State Value Value Value Value Value Value
  46. 46. Stateモナドの使⽤用例例 case class Stack(stack: List[Int]) def main(args: Array[String]) { sample } def sample { val stack = Stack(Nil) val r = pipe.run(stack) assert(r == (Stack(List(10)), 10), s$r) }
  47. 47. val pipe: State[Stack, Int] = { for { a - push(10) b - push(a) c - pop } yield c } def push(x: Int) = State[Stack, Int] { s = (Stack(x :: s.stack), x) } def pop = State[Stack, Int] { s = s.stack match { case x :: xs = (Stack(xs), x) case Nil = ??? } }
  48. 48. 並列列プログラミング マルチスレッド • 共有状態 (shared mutability) • 共有状態をロック ← 伝統的⽅方法 • STM (Software Transactional Memory) アクター • 状態をアクターローカル(スレッドローカル)にする (isolating mutability) • 不不変オブジェクトによるメッセージで通信 関数プログラミング⽅方式 • 代数的データ型、永続データ構造 • 不不変オブジェクト • モナドのメカニズムを使って並列列処理理を隠蔽
  49. 49. 並列列プログラミングとモナド
  50. 50. Future case class Site(uri: String, page: String) def largestSite: Future[Site] = { for { a - future(getSite(http://www.yahoo.com)) b - future(getSite(http://www.amazon.com)) c - future(getSite(http://www.google.com)) } yield { Vector(a, b, c).maxBy(_.page.length) } } def getSite(uri: String): Site = { Site(uri, new URL(uri).asInput.string) } def main(args: Array[String]) { largestSite.onSuccess { case site = println(swin = ${site.uri}) } }
  51. 51. RxJava - Scala • Functional Reactive Programming • https://github.com/Netflix/RxJava • http://techblog.netflix.com/2013/02/rxjava-netflix-api.html def simpleComposition() { // fetch an asynchronous ObservableString // that emits 75 Strings of 'anotherValue_#' customObservableNonBlocking() // skip the first 10 .skip(10) // take the next 5 .take(5) // transform each String with the provided function .map({ stringValue - return stringValue + _transformed}) // subscribe to the sequence and print each transformed String .subscribe({ println onNext = + it}) }
  52. 52. scalaz stream • Functional Reactive Programming • https://www.chrisstucchio.com/blog/2014/ scalaz_streaming_tutorial.html for { bag - resource.managed(new FileBag()) bag2 - resource.managed(new FileBag()) bag3 - resource.managed(new FileBag()) } { Process.constant(4096).through(io.chunkR(new URL(http://scala-lang. org/).openStream)).to(bag.chunkW).run.run bag.chunksR(4096).to(bag2.chunkW).run.run bag2.linesR.map(_ + n).pipe(text.utf8Encode).to(bag3.chunkW).run.run bag.size should be (bag2.size) bag.size should be (bag3.size) }
  53. 53. Spark • RDD (Resilient Distributed Dataset) • http://www.cs.berkeley.edu/~pwendell/strataconf/api/core/ spark/RDD.html scala val textFile = sc.textFile(README.md) textFile: spark.RDD[String] = spark.MappedRDD@2ee9b6e3 scala val linesWithSpark = textFile.filter(line = line.contains(Spark)) linesWithSpark: spark.RDD[String] = spark.FilteredRDD@7dd4af09 scala textFile.filter(line = line.contains(Spark)).count() // How many lines contain Spark? res3: Long = 15
  54. 54. Object Functional Programming
  55. 55. OFP新三種の神器 トレイト (trait) • mix-in • 型安全のAOP的な運⽤用 モナド (monad) • 計算⽂文脈をカプセル化する新しい⾔言語概念念 • Monadicプログラミング 型クラス (type class) • 型安全のダブルディスパッチ(?) • Scalaでは、⽂文脈、主体、客体の組でオブジェクトを束縛
  56. 56. 関数と⼿手続き • 関数は副作⽤用なし • 副作⽤用があるものは「⼿手続き」 • 例例外も副作⽤用の⼀一種 • 厳密には例例外を発⽣生させる可能性のあるものは「⼿手続き」 • プログラミングの⼿手間を考えて例例外は特別扱いしたい • 本セッションでは「準関数」を導⼊入 要素副作⽤用なし参照透過性例例外なし 関数◯◯◯ 準関数◯◯× ⼿手続きーーー
  57. 57. OOP/FP⽐比較
  58. 58. オブジェクトと関数の連携
  59. 59. DSL (Domain Specific Language) • 固有の目的別言語 (汎⽤用⾔言語の反対) • 内部DSL • 汎⽤用⾔言語の⽂文法を拡張して実現したDSL • パーサーを書く必要がない • ホスト⾔言語の機能を使うことができる(計算式など) • 外部DSL • 専⽤用⾔言語を設計・実装 • パーサーを書く必要がある • XMLやS式のようなメタ⾔言語を使う⽅方法もある • Scala • 内部DSLとしての利利⽤用を指向
  60. 60. DSL Anorm SQL(select name from coffees where price 10.0”) Squeryl from(coffees)(s = where(s.price 10.0) select(s)) Slick coffees.filter(_.price 10.0).map(_.name)
  61. 61. DSL def transaction[T](body: = T) = { val tx = openTransaction() try { body } finally { closeTransaction(tx) } } case class Conditional[T](p: Boolean, truebody: () = T) { def myelse(falsebody: = T): T = if (p) truebody() else falsebody } def myif[T](p: Boolean)(truebody: = T): Conditional[T] = new Conditional(p, () = truebody)
  62. 62. def sample(v: Boolean): Boolean = { transaction { myif (v) { true } myelse { false } } }
  63. 63. オブジェクト指向開発+OFP
  64. 64. オブジェクト指向開発概観 ドメイン・モデル ビジネス フロー ビジネス ユースケースユースケースサービス ビジネス・モデルシステム分析モデルシステム設計モデル
  65. 65. モデル&アーキテクチャ: ⼿手続き指向
  66. 66. モデル&アーキテクチャ: オブジェクト指向
  67. 67. モデル&アーキテクチャ 関数型指向
  68. 68. データフロー • OMT v1 (1991) • Object model • Dynamic model • Functional model • データフロー • OMT v2 (2005) • Class model • Dynamic model • Interaction model • データフローでモデリングしたいもの • バッチ処理理 • BigData
  69. 69. まとめ • 関数型⾔言語の導⼊入の意義 • 開発効率率率 • DSL • Monadic Programming • 並列列・並⾏行行・分散 • Functional Reactive Programming • OFP (Object-Functional Programming) • DSL • OP : FP = 6 : 4 (体感値) • オブジェクト指向開発 + OFP • DSL • サービス • データフロー
  70. 70. END

×