関数型プログラミングの芳点からのコマンドおよび戊略パタヌン

関数型プログラミングを勉匷した結果、私の頭にいく぀かの考えが浮かびたした。



蚭蚈パタヌンず関数型プログラミング これはどのように関連しおいたすか



オブゞェクト指向のパラダむムに慣れおいる倚くの開発者の心の䞭では、゜フトりェア蚭蚈自䜓はOOPず密接に関連しおおり、他のすべおは異端であるようです。 䞻にOOPに焊点を合わせたUMLは、蚭蚈のための普遍的な蚀語ずしお䜿甚されおいたすが、そうではありたせん。 そしお、オブゞェクト指向プログラミングの䞖界が埐々に犯眪リ゚ンゞニアリングの深intoに突入しおいるこずがわかりたす1。

このため、倚くの堎合、プログラミングパラダむムを遞択するずいう問題は提起されたせん。 それにもかかわらず、この質問は非垞に重芁であり、倚くの堎合、正しい答えは倧きな利点を提䟛したす3。 䞀般的に蚀っお、これは私たちがデザむンず呌んでいたものを超えおいたす-これは建築の分野からの質問です。



叙情的な䜙談アヌキテクチャ、蚭蚈、実装の違い


少し前に、非垞に興味深い研究に出䌚いたした-2。 非公匏に最もよく䜿甚される「アヌキテクチャ」、「蚭蚈」、「実装」の抂念を圢匏化するタスクを考慮したす。 そしお、著者は非垞に興味深い基準を掚定するこずができたすIntension / Locality基準です。 哲孊を深く掘り䞋げるこずはせず、基準この郚分は実際には翻蚳ですの簡単な説明ずそれからの結論を述べたす。

Intensionプロパティは、特定の゚ンティティが無限数のオブゞェクトを蚘述する胜力を意味したす。たずえば、玠数の抂念です。 拡匵性の特性はそれずは反察です-本質はオブゞェクトの有限セットを説明したす。たずえば、囜の抂念はNATOのメンバヌです。

局所性プロパティ-゚ンティティは、システムの別の郚分にのみ圱響したす。 したがっお、グロヌバル性-本質はシステム党䜓に圱響したす。

したがっお、これらの2぀の特性を考慮しお、この研究の著者はそのような衚を線集したす。

画像

これを䜿甚するず、アヌキテクチャのレベルに関連するもの、および蚭蚈のレベルに関連するものを簡単に刀断できたす。 そしお、ここに私の結論がありたす。プログラミングパラダむム、プラットフォヌム、および蚀語の遞択は、アヌキテクチャレベルでの決定です。 この遞択は、グロヌバルシステムのすべおの郚分に圱響およびむンテンシブパラダむムが無限の数のタスクを解決する方法を決定したすです。



しかし、そのようなグロヌバルな問題を解決するために適切なパラダむムを遞択するための基準を芋぀けるために私はただ䜙裕がありたせん。 したがっお、既存の2぀のクラスの問題を遞択し、倚くのOOの通垞のアプロヌチではなく、最近圓然人気が高たっおいる機胜的なアプロヌチを䜿甚する䟡倀があるこずを瀺すこずにしたした。

異垞な方法でタスクのクラスを遞択したした-2぀のオブゞェクト指向蚭蚈パタヌンを䜿甚し、それらが実際に関数型プログラミングの分野の抂念の限定的な実装である-高次関数以䞋FVPであるこずを瀺したした。 仮説は、パタヌンは特定の問題に察する十分に確立された解決策であり、問題ずその十分に確立された解決策があるため、明らかに克服しなければならないいく぀かの匱点ず欠点があるずいうこずでした。 考慮されたパタヌンに぀いおは、これは確かにそうです。

ちなみに、同様のアプロヌチが5ず6で䜿甚されたした。 6では、ほずんどのパタヌンを眮き換える可胜性が䞀般的に瀺されたしたが、各パタヌンの詳现な分析は行われたせんでした。 5では、指揮ず戊略に぀いおのより詳现な怜蚎がありたしたが、わずかに異なる偎面がありたした。 6よりも実甚的で、5ずは異なるアクセントで䜕かをするこずにしたした。 それでは始めたしょう。



高階関数



䜕らかの圢のほが党員がこの考えに粟通しおいるず思いたす。

高階関数は、匕数ずしお受け取るか、結果ずしお別の関数を返す関数です。

これは、関数型プログラミングの基本抂念によっお可胜になりたす。関数は倀です。 関数型プログラミングの関数ず倀が数孊の同様の抂念に完党に察応しおいるず蚀うずき、正確に完党に察応しおいるこずを意味したす。 それはたったく同じです。 数孊で広く普及しおいるFVPの䟋は、埮分、統合、および合成の挔算子です䞀般的に、これは機胜分析からの挔算子の抂念に近い。 合成挔算子は、機胜的なパラダむムをサポヌトするほずんどの蚀語で盎接衚珟されたす。 Fの䟋



let f = (+) 10 let g = (*) 2 let composition = f << g printfn "%i" <| g 15 printfn "%i" <| f 30 printfn "%i" <| composition 15
      
      





結論



 30 40 40
      
      





明らかに、f << gずいう衚蚘は、fgxたたはF○Gずいう衚蚘に察応したす。

これをよりよく理解するために、構成挔算子のタむプに泚意するこずをお勧めしたす。



 ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
      
      





括匧内の関数の皮類の説明の郚分も関数の皮類です。 ぀たり、匕数ずしお受け取る関数です。

  • ゞェネリック型の倀を匕数ずしお受け取り、ゞェネリック型の倀を返す関数b
  • ゞェネリック型の倀を匕数ずしお受け取り、ゞェネリック型の倀を返す関数
  • タむプ 'cの倀


タむプ 'bの倀を返したす。 実際には、匕数ずしお型 'cの倀を取り、型' bの倀を返す関数、぀たり タむプは次のように曞き換えるこずができたす。



 ('a -> 'b) -> ('c -> 'a) -> ('c -> 'b)
      
      





FVP は、䞀般的な動䜜を区別するこずができたす 。 これにより、コヌドの再利甚性が向䞊したす。

これはさたざたな目的に䜿甚できたす-たずえば、䟋倖を凊理するために。 特定の䟋倖セットを匕き起こす可胜性のあるコヌドが倚数あるずしたす。 ゚ラヌを起こしやすいコヌド自䜓を、䟋倖を凊理する別の関数にパラメヌタヌずしお枡す関数の圢匏で蚘述するこずができたす。 Cの䟋



 private void CalculateAdditionalQuantityToIncreaseGain() { //  var unitPrice = ExtractDecimal(gainUnitPriceEdit); var quantityReleased = ExtractDecimal(gainQuantityEdit); ... }
      
      







䟋倖を凊理するFEPは次のずおりです。



 private static void ExecuteErrorProneCode(Action procedure) { try { procedure(); //      } catch (WrongDecimalInputInTextBoxException ex) { MessageBox.Show(ex.Message, "  "); } catch (Exception ex) { MessageBox.Show(ex.Message, ""); } }
      
      





次に、関数によっお匕き起こされた䟋倖を凊理するには、次のように蚘述するだけで十分です。



 ExecuteErrorProneCode(CalculateAdditionalQuantityToIncreaseGain);
      
      





これにより、同じ方法で凊理する必芁がある䟋倖をスロヌできる䟋倖ハンドラヌや関数が倚数ある堎合、コヌドが倧幅に削枛されたす。

たた、䞀般的な動䜜を匷調する兞型的な䟋は、゜ヌトのための高階関数の䜿甚です。 明らかに、䞊べ替えには、䞊べ替えられたコレクションの芁玠を互いに比范できる必芁がありたす。 ゜ヌト関数に匕数ずしお枡される関数は、そのような「コンパレヌタ」ずしお機胜したす-したがっお、゜ヌト関数は普遍性を確保するためにFVPでなければなりたせん。 䞀般に、FEPを䜜成する機胜は、 抜象的な䞀般化アルゎリズムの䜜成を目的ずした䞀連のアクションの重芁なリンクです 。

ずころで、FVPは他の関数ず同様に倀であるため、デヌタを衚すために䜿甚できたす。 これに぀いおは、教䌚のパフォヌマンスに関する蚘事を参照しおください。



コマンドパタヌン



戊略のようなコマンドデザむンパタヌンは、 動䜜デザむンパタヌンを指したす。 その䞻な圹割は、特定の機胜のカプセル化です。 このパタヌンには倚くの甚途がありたすが、ほずんどの堎合、次のこずを行うために䜿甚されたす。

  • 別の受信者にリク゚ストを送信する
  • チヌムの線成、ログの保持、リク゚ストのキャンセル
  • 単玔なものから耇雑な操䜜を䜜成する
  • 元に戻す最埌のアクションを元に戻すおよびやり盎し最埌に元に戻したアクションを繰り返すコマンドを実装する


䞀般的に、次のようになりたす。



画像



元に戻すずやり盎しの実装の䟋を怜蚎したす 。この機胜の実装のクリヌンなオブゞェクト指向バヌゞョンをここで芋るこずができたす 。

この図の圹割の分垃



画像



ここで、 FilterはReceiver 'y、 LoggingInvoker - Invoker ' y、 IFilterCommand - ICommandに察応したす。 これは、オペレヌションを呌び出す方法ですLoggingInvoker 'sのExecute()



メ゜ッドにパラメヌタヌずしお枡すコマンドず、 LoggingInvoker ' e自䜓でコマンドを䜜成できたす-遞択は特定の状況によっお異なりたす。



画像



そしお、ここにそれらをキャンセルする方法がありたす



画像



performOpsおよびundoneOpsは、実行およびキャンセルされたチヌムを栌玍するスタックです。

ただし、FEPを怜蚎した埌、遞択した蚀語がこの機胜をサポヌトしおいれば、このすべおの動䜜をFEPの圢匏で実装できるこずは明らかです。 実際、 InvokerオブゞェクトはFPFに眮き換えるこずができたす。FPFは 、特定の操䜜に察応する関数を匕数ずしお受け取りたす。関数自䜓は倀であるため、 Commandオブゞェクトは䞍芁になりたした。 その機胜は、機胜的パラダむムをサポヌトする蚀語の皮類のシステムによっお実行されたす。

このパタヌンを、同じ機胜を実行できる機胜的パラダむムのデザむンで眮き換える図を次に瀺したす。



画像



擬䌌コヌドFに觊発されたでは、察応する機胜実装は次のようになりたす。



 //      //    -       type OpType = (DataType -> DataType) * DataType //      let performedOps = Stack<OpType>() let undoneOps = Stack<OpType>() // LoggingInvoker -  let execute operation data = let res = operation data //  performedOps.Push(operation, data) //       res //    let undo () = if performedOps.Count > 0 then //          undoneOps.Push(performedOps.Pop()) //      Some (snd undoneOps.Peek()) //     'a option, . (5)  (7) else None // let OperationOne data = ... let OperationTwo data = ... //  OperationOne let mutable a = execute OperationOne data //  let b <- undo ()
      
      





実行する関数FVP execute



を枡したす。 execute



関数は、完了した操䜜のスタックをリヌドし、操䜜を実行し、その実行結果を返したす。 元に戻す機胜は、最埌に実行された操䜜をキャンセルしたす。



このアプロヌチには、コマンドパタヌンを䜿甚するよりもいく぀かの利点がありたす。

  1. 結果のコヌドは、より自然で、短く、シンプルです。
  2. コンポゞションたたはパむプラむン凊理を䜿甚しお、マクロず耇雑な操䜜を簡単に䜜成できたすパむプラむン凊理に぀いおは、5たたは7を参照簡単な操䜜
  3. メニュヌを動的に䜜成するなどの操䜜を含む耇雑なデヌタ構造を䜜成できたす。


さらに、マルチパラダむム蚀語を䜿甚する堎合、コマンドパタヌンず、ここで瀺すアプロヌチをオブゞェクト指向のさたざたな割合で組み合わせるこずができたす。

珟代の倚くの蚀語は、AFPをある皋床サポヌトしおいたす。 たずえば、Cにはデリゲヌトメカニズムがありたす。 デリゲヌトを䜿甚しお取り消しを䜜成する問題を解決する䟋は、4にありたす。



戊略パタヌン



戊略パタヌンは、クラむアントが問題を解決するためのいく぀かの可胜な方法の1぀を遞択できるように蚭蚈されおいたす。 OOPでは、このために次の構造が䜜成されたす。



画像



コンテキストは、 IStrategyむンタヌフェむスの実装の1 ぀ぞのリンクを保存したす;必芁に応じお、この保存されたオブゞェクトのメ゜ッドを䜿甚しお特定の操䜜を実行したす。 オブゞェクトの倉曎-メ゜ッドの倉曎。

たた、機胜的なスタむルに簡単に倉換できたす。 今回は、機胜のリストを䜿甚しお可胜な戊略を保存できたす。



画像



擬䌌コヌド



 let strategyA data = ... let strategyB data = ... let useStrategy strategy data = ... strategy data ... useStrategy strategyA data
      
      





関数strategyA



、 strategyB



、...は、可胜な戊略を実装する関数です。 高次関数useStrategy



は、遞択された戊略をデヌタに適甚したす。 戊略は、単に匕数ずしおuseStrategy



関数にuseStrategy



たす。

コヌドを倧幅に簡玠化および短瞮するこずに加えお、このアプロヌチには远加の利点がありたす-耇数の戊略によっおパラメヌタヌ化された関数を䞀床に簡単に䜜成できるため、通垞のオブゞェクト指向アプロヌチでは非垞に耇雑なプログラム構造になりたす。 実装が十分に簡単な堎合、匿名関数などの機䌚を利甚しお、戊略に個別の名前を指定する必芁はたったくないかもしれたせん。 たずえば、FIのデヌタを䞊べ替えるには、FVP䞊べ替えを䜿甚し、OOPで行われおいるように比范メ゜ッドを実装するIComparerむンタヌフェむスを実装する型ではなく、比范操䜜自䜓を枡すこずができたす。



 let a = sort (<) data
      
      





結論



1.解決する問題のクラスに応じたパラダむムの正しい遞択は、倚くの堎合、その゜リュヌションの成功のための重芁な芁因ずなりたす。 タスクがいわゆるクラスに属しおいる堎合 行動䞭心の堎合は、機胜的なアプロヌチの䜿甚を怜蚎する必芁がありたす。

2.コマンドおよび戊略パタヌンは、高次関数の限定的な実装です

3. FWPを䜿甚した゜リュヌションを掻甚するために、玔粋に機胜的な蚀語に切り替える必芁はありたせん。最新の䞻流蚀語のほずんどは、ある皋床FWPをサポヌトしおいたす。



最近、オブゞェクト指向ず機胜的パラダむムを同等に組み合わせた倚数の蚀語が登堎したした;倚くのオブゞェクト指向蚀語は、機胜的な胜力を獲埗し始めたした。 この蚘事が、誰かがお気に入りのプログラミング蚀語の新機胜をよりよく䜿甚するのに圹立぀こずを願っおいたす。 頑匵っおください



゜ヌス



1. 犯眪のオヌバヌ゚ンゞニアリング

2. アヌキテクチャ、蚭蚈、実装 。 アムノンH.゚デン、リックカズマン。 ポヌトランドB.Sc.2003。第25回゜フトりェア工孊囜際䌚議-ICSE

3. 銀行䌚瀟は関数型蚀語を䜿甚しお開発を50加速したす。 マむクロ゜フトのケヌススタディ。 2010幎3月

4.ビショップ、ゞュディス。 C3.0デザむンパタヌン。 カリフォルニア州セバストポル2008幎オラむリヌ

5.トヌマス・ペトリチェック、ゞョン・スキヌト。 珟実䞖界の関数型プログラミング。 b.m。Manning Publications、2010幎。

6. Gabriel、Richard P. オブゞェクトはスラむドに倱敗したした DreamSongs.com。

7.スミス、クリス。 プログラミングF。 カリフォルニア州セバストポルO'Reilly、2010幎。



UDP

alexeyromは非垞に有甚なコメントを曞いたが、圌の同意を埗お、それを芋るこずができるように投皿の本文に入れた。



「ノルりィグは 、1996幎にLispずDylanのパタヌンを芋たした 。 実際、結果は䌌おいたすが倚くのパタヌンは簡単になり、倧幅に単玔化されたす、より豊かな玠材になりたす。



All Articles