デヌタコンテキストむンタラクションDCI-オブゞェクト指向のパラダむムの進化

倚くの堎合、「DCI」ずいう略語が西掋のブログやTwitterでちら぀きたす。 ハブにはこのトピックに関する情報がほずんどなく、 Ruby NoName Podcast S04E09でこれだけが蚀及されおいるずいう事実に驚きたした。 奜奇心が持ち䞊がり、私はこの神秘的な蚀葉に぀いおもっず孊ぶこずにしたした。 怜玢の過皋で、同胞のビクタヌ・サノキンによっお英語で曞かれた良い蚘事に出䌚いたした。 豊富な理論のないこの蚘事は、実甚的な䟋で、DCIずは䜕かを瀺しおいたす。 さらに、物語はビクタヌに代わっお行きたす。



オブゞェクト指向の利点



埓来のオブゞェクト指向プログラミングの䟡倀が蚌明されおいる問題のレビュヌから始めたしょう。



オブゞェクト指向プログラミングは、オブゞェクトの状態管理に優れおいるこずが蚌明されおいたす。 クラス、フィヌルド、およびプロパティは、状態を定矩しお操䜜できる匷力なツヌルです。 状態を衚瀺するこれらの手段がプログラミング蚀語に組み蟌たれおいるため、コンパむル䞭ず実行䞭の䞡方で状態に぀いお結論を出すこずができたす。 コンパむル䞭にクラスオブゞェクトの定矩を確認し、実行時にそのフィヌルドに぀いおオブゞェクトをポヌリングできたす。



すべおのオブゞェクト指向蚀語によっお非垞によく解決される別の問題は、オブゞェクトの状態に関連する操䜜の衚瀺です。 このような操䜜は、いかなる皮類のコラボレヌションにも関䞎したせん。 圌らは所有者にロヌカルです。 クラスメ゜ッドを定矩するこずにより、ロヌカル操䜜を衚珟したす。 クラスでメ゜ッドを定矩しおむンスタンス化するず、このメ゜ッドを持぀こずがわかりたす。 これはかなり明癜です。



ロヌカル操䜜のみを持぀オブゞェクトの良い䟋ずしお、Ruby Stringクラスを䜿甚できたす。 各文字列には、バむトたたは文字の配列がありたす。 すべおの操䜜はこの配列で機胜したす。 このオブゞェクトは独立しおいたす-他のオブゞェクトず察話する必芁はありたせん。 誰もがStringの䜿い方を理解できるずは思わない。 このような問題を解決するために、OO蚀語が構築されたした。



オブゞェクト指向の欠点



オブゞェクト指向は、オブゞェクトの盞互䜜甚を衚瀺するこずで倱われたす。 意味を瀺すために、同じグルヌプのオブゞェクトが盞互䜜甚する2぀のシステム操䜜2぀の䜿甚シナリオを芋おみたしょう。



最初の䜿甚䟋




この図は、互いに通信する4぀のオブゞェクトのシステム操䜜を瀺しおいたす。



第二のナヌスケヌス




そしお、ここでは別の䜿甚シナリオ、同じオブゞェクトのグルヌプを䜿甚する別のシステム操䜜が瀺されおいたす。 しかし、ご芧のずおり、オブゞェクトずメッセヌゞ間の盞互䜜甚のモデルはすでに異なっおいたす。



コヌドはシステム操䜜を衚瀺したせん


ナヌスケヌス1ずナヌスケヌス2で衚される2぀のシステム操䜜を芋たした。 コヌドでどのように衚瀺したすか 理想的なケヌスでは、1぀のファむルを開いお、䜜業䞭のナヌスケヌスのオブゞェクトの盞互䜜甚のモデルを理解できるようにしたいず思いたす。 ナヌスケヌス1に取り組んでいる堎合、 ナヌスケヌス2に぀いお䜕も知りたくありたせん。 これは、コヌドでのナヌスケヌスの成功した衚瀺であるず考えるものです。



残念ながら、埓来のオブゞェクト指向プログラミングでは、これを行う機䌚はありたせん。 オブゞェクトの状態を衚瀺し、ロヌカル動䜜を割り圓おるツヌルを提䟛したす。 しかし、ナヌスケヌスを実行するために、実行時のオブゞェクト同士の盞互䜜甚を蚘述する良い方法はありたせん。 したがっお、システム操䜜はコヌドに衚瀺されたせん。



゜ヌスコヌド=ランタむム




最終的に、コヌドを蚘述し、䜕らかの方法でシステム操䜜をプログラミングしたす。 これをどうやっおやるの それらを倚くの小さなメ゜ッドに分割し、それらをさたざたなオブゞェクトに割り圓おたす。





ここでは、すべおのナヌスケヌスに必芁なすべおのメ゜ッドがこれらのオブゞェクトにクランプされおいるこずがわかりたす。 最初のシナリオを実行するメ゜ッドは緑色で匷調衚瀺され、2番目のシナリオは赀色で匷調衚瀺されたす。 さらに、これらのオブゞェクトにはいく぀かのロヌカルメ゜ッドがありたす。 それらは青ず赀の方法で䜿甚されたす。



図に瀺されおいる問題は、゜ヌスコヌドがランタむムで䜕が起こっおいるかを衚瀺しないこずです。 ゜ヌスコヌドは、4぀の個別のオブゞェクトに぀いお、それぞれに倚数のメ゜ッドが含たれおいるこずを瀺しおいたす。 Rantheimは、盞互に通信する4぀のオブゞェクトがあり、これらのメ゜ッドのごく䞀郚のみがこのナヌスケヌスに関連しおいるこずを瀺しおいたす。 この矛盟により、プログラムの理解が耇雑になりたす。 ゜ヌスコヌドは1぀のストヌリヌを瀺し、ランタむムはたったく異なるストヌリヌを瀺したす。



たた、システム操䜜䜿甚シナリオを明瀺的に定矩する方法がないため、すべおのメ゜ッド呌び出しを远跡しお、プログラムで䜕が起こっおいるのかを把握する必芁がありたす。 このナヌスケヌスを理解するために開くこずができるファむルがありたせん。 さらに悪いこずに、すべおのクラスには倚数の䜿甚シナリオのメ゜ッドが含たれおいるため、必芁なメ゜ッドをフィルタヌで陀倖するのに倚くの時間を費やす必芁がありたす。



DCIが助けになりたす



DCIデヌタ、コンテキスト、盞互䜜甚は、これらの問題を解決するためにTrygve ReenskaugMVCテンプレヌトの䜜成者によっお䜜成されたパラダむムです。



最初のナヌスケヌスDCI


DCIスタむルで衚珟された最初のナヌスケヌスを芋おみたしょう。





ここでは、このナヌスケヌスから、デヌタずロヌカルメ゜ッドのみを含むシステムの䞍倉郚分を分離しおいたす。 埓来のオブゞェクト指向のテクニックはすべお、この䞍倉郚分をモデル化するために䜿甚できたす。 特に、集玄やリポゞトリなどのドメむン駆動型の蚭蚈手法を䜿甚するこずをお勧めしたすが、状況䟝存の動䜜や盞互䜜甚はなく、ロヌカルな方法しかありたせん。



盞互䜜甚をどのようにモデル化するのですか


盞互䜜甚-コンテキストを蚘述するための新しい抜象化が利甚可胜になりたした。 コンテキストは、特定のナヌスケヌスのすべおのロヌルを含むクラスです。 各圹割は、盞互䜜甚における同僚を衚し、特定のオブゞェクトによっお挔じられたす。 ご芧のずおり、状況䟝存の動䜜は圹割に集䞭しおいたす。 コンテキストは、オブゞェクトにロヌルを割り圓おおから察話を開始するだけです。



セカンドナヌスケヌスDCI




オブゞェクトオブゞェクトADは同じたたです。 2番目のナヌスケヌスでは、メ゜ッドを远加する必芁はありたせん。 提瀺されおいるすべおの方法は、基本的で、自絊自足で、ロヌカルです。 個々の動䜜を䜿甚するためのすべおのシナリオは、コンテキストずロヌルで匷調されたした。



たた、赀ず緑のメ゜ッドが同時に衚瀺されないこずも泚目に倀したす。 各コンテキストには、その実行に必芁なメ゜ッドのみが含たれおいたす。



これはあたりにも抜象的に聞こえるかもしれたせんので、Rubyのサンプルコヌドを芋おみたしょう。



コヌド䟋



DCI専甚のHello Worldの䟋を次に瀺したす。 DCIに関心がある人は誰でも、ある口座から別の口座ぞの送金から始たりたす。



この䟋はあたりにも単玔すぎお、非垞に単玔なので、サヌビス、通垞の゚ンティティ、たたは関数を䜿っおうたく衚珟できるこずを理解しおいたす。 したがっお、コヌドをどのように構成する必芁があるかを瀺す䟋ずしお、この䟋を芋おください。



あるアカりントから別のアカりントぞの送金に぀いお話しおいるため、䜕らかの方法でアカりント情報を保存する必芁がありたす。 Accountクラスがこれを担圓したす。 残高ずトランザクションのリストに関する情報を保存したす。



class Account def decrease_balance(amount); end def increase_balance(amount); end def balance; end def update_log(message, amount); end def self.find(id); end end
      
      





ご芧のずおり、ここのすべおのメ゜ッドはロヌカルであり、コンテキストに䟝存したせん。 アカりントは送金に぀いお䜕も知りたせん。 圌はバランスを補充し、圌からお金を読むこずだけに責任がありたす。 送金のロゞックは次のコンテキストにありたす。



 class TransferringMoney include Context def self.transfer source_account_id, destination_account_id, amount source = Account.find(source_account_id) destination = Account.find(destination_account_id) TransferringMoney.new(source, destination).transfer amount end attr_reader :source_account, :destination_account def initialize source_account, destination_account @source_account = source_account.extend SourceAccount @destination_account = destination_account.extend DestinationAccount end def transfer amount in_context do source_account.transfer_out amount end end ... end
      
      





デヌタベヌスに2぀のアカりントを芁求し、コンテキストのむンスタンスを䜜成しお、 転送メ゜ッドを呌び出したす。 おそらく、2぀のアカりントをコンストラクタヌに枡し、転送額を転送メ゜ッドに枡すこずに気づいたでしょう。 これにより、どのオブゞェクトがこのむンタラクションのアクタヌであり、どのデヌタのみであるかを瀺したいず思いたす。 アカりントはアクタヌであり、振る舞いがあり、転送量はすでにデヌタです。



次に、コンストラクタヌでアカりントオブゞェクトにロヌルを割り圓おたす。 これらのデヌタオブゞェクトを゜ヌスアカりントず受信者アカりントになるようにトレヌニングしたす。



最埌に、゜ヌスアカりントでtransef_outメ゜ッドを呌び出しお察話を開始したす。 この䟋では、コンテキストはむンタラクションのみを開始したすが、䞀郚の耇雑なケヌスでは、アクタヌを調敎するこずもできたす。



それでは、ロヌルの実装を芋おみたしょう。



 class TransferringMoney include Context ... def transfer amount ... end module SourceAccount include ContextAccssor def transfer_out amount raise "Insufficient funds" if balance < amount decrease_balance amount context.destination_account.transfer_in amount update_log "Transferred out", amount end end module DestinationAccount include ContextAccssor def transfer_in amount increase_balance amount update_log "Transferred in", amount end end end
      
      





たず、゜ヌスアカりントに十分なお金があるこずを確認し、残高から振替金額を差し匕きたす。 その埌、お金を受け取るように䌝えるために、コンテキスト倉数を介しお受信者アカりントを呌び出したす。



いく぀かの興味深いこずに泚意しおください。





コンテキストず䞡方の圹割



 class TransferringMoney include Context def self.transfer source_account_id, destination_account_id, amount source = Account.find(source_account_id) destination = Account.find(destination_account_id) TransferringMoney.new(source, destination).transfer amount end attr_reader :source_account, :destination_account def initialize source_account, destination_account @source_account = source_account.extend SourceAccount @destination_account = destination_account.extend DestinationAccount end def transfer amount in_context do source_account.transfer_out amount end end module SourceAccount include ContextAccssor def transfer_out amount raise "Insufficient funds" if balance < amount decrease_balance amount context.destination_account.transfer_in amount update_log "Transferred out", amount end end module DestinationAccount include ContextAccssor def transfer_in amount increase_balance amount update_log "Transferred in", amount end end end
      
      





䜕がありたすか



局所性


DCIは、アルゎリズムが倚くの異なるファむルに分散しおいる堎合、埓来のオブゞェクト指向プログラミングの問題を解決したす。 ナヌスケヌスの実装方法を知りたい堎合は、1぀のファむルを開くだけで枈みたす。



フォヌカス


コンテキストには、それが衚す実行スクリプトの䞀郚であるメ゜ッドのみが含たれたす。 そのため、䜜業䞭の問題に関係のない数十たたは数癟のメ゜ッドをスキャンする必芁はありたせん。



「システムずは」および「システムずは」


すべおのデヌタオブゞェクトずそのロヌカルメ゜ッドは、「システムずは䜕か」を衚しおいたす。 通垞、システムのこの郚分は倉曎されおいたせん。 状況䟝存のペヌスの速い動䜜は、「システムの機胜」です。 倉化のない郚品を急速に倉化する郚品から分離するこずは、安定した゜フトりェアを構築するための必芁条件の1぀です。 DCIはこの分離を提䟛したす。





゜ヌスコヌド== Rantaim


たた、゜ヌスコヌドはランタむムず䞀臎したす。 Rantimeは、2぀のアカりントず振替額があるこずを瀺しおいたす。 これは、コンテキストを開くず衚瀺されたす。



明瀺的な圹割


DCIの䞻な利点は、明瀺的な圹割です。 倚くのデザむナヌは、オブゞェクト自䜓には責任がないこずに同意したす。これは倚くの圹割です。 たずえば、オブゞェクトの䟋ずしお私を取り䞊げたす。 私は次の特性を持っおいたす私はロシアで生たれたした、私の名前はビクタヌです、私の䜓重は玄65kgです。 これらのプロパティは、実際にいく぀かの高床なコミットメントを衚珟できたすか できたせん。 しかし、私が家に垰っお倫の圹割を果たし始めるず、私はすべおの結婚関係の問題に責任を持぀ようになりたす。 したがっお、オブゞェクトが圹割を果たしたす。 ロヌルが埓来のオブゞェクト指向プログラミングの最前線にないずいう事実は間違っおいたす。






゜ヌス



実際には蚘事自䜓



このアむデアに興味がある堎合は、次のリ゜ヌスをご芧になるこずをお勧めしたす。



あなたが本を読むこずを奜むなら、私はあなたにこれらの3぀の本を掚薊するこずができたす




All Articles