「混合」言語での設計:オブジェクト指向設計または関数型プログラミング?


11

過去数年間で、私が使用したい言語はますます「機能的」になりつつあります。現在、C#、F#、Scalaなどの「ハイブリッド」言語を使用しています。ドメインオブジェクトに対応するクラスを使用してアプリケーションを設計し、これによりコーディングがより簡単に、より正確に、より安全になる機能機能を使用します(特にコレクションの操作時または関数の受け渡し時)。

ただし、パターンを設計する場合、2つの世界は「衝突」します。私が最近直面した具体的な例は、Observerパターンです。アイテムが作成または変更されたときに、プロデューサーに他のコード(「消費者/オブザーバー」、たとえばDBストレージ、ロガーなど)に通知してほしい。

私は最初に次のように「機能的に」それをしました:

producer.foo(item => { updateItemInDb(item); insertLog(item) })
// calls the function passed as argument as an item is processed

しかし、私は今、もっと「OO」アプローチを使用すべきかどうか疑問に思っています。

interface IItemObserver {
  onNotify(Item)
}
class DBObserver : IItemObserver ...
class LogObserver: IItemObserver ...

producer.addObserver(new DBObserver)
producer.addObserver(new LogObserver)
producer.foo() //calls observer in a loop

2つのアプローチの長所と短所はどれですか?かつてFPの第一人者が、デザインパターンは言語の制限のためだけにあると言ったことを聞いたことがあり、それが関数型言語にはほとんどない理由です。たぶん、これはその例でしょうか?

編集:私の特定のシナリオでは、私はそれを必要としませんが、..機能的な方法で「観測者」の削除と追加をどのように実装しますか?(つまり、パターンのすべての機能をどのように実装しますか?)たとえば、新しい関数を渡すだけですか?


アクターはどうですか?
切rit

クラスや、OOPの役に立たないものはすべて忘れてください。代わりに、モジュールの観点から考えた方がよいでしょう(インスピレーションについては、SMLおよびOCaml言語を参照してください)。
SKロジック

@Antorasアクターに基づくアプローチと比較できれば、それは歓迎です:)
ロレンツォデマテ

2
@ dema80、OCamlは完全にマルチパラダイムです。モジュールは関数型プログラミングとはまったく関係ありません。たとえば、純粋に命令的なAdaには高度なモジュールシステムがあります。そして、OOPで得られたすべての名声は、実際にはモジュールに渡されるべきです-OOPのすべての利点は、モジュールの機能をシミュレートするさまざまな形式です。すべてのクラスを完全に忘れて、OOPではなくモジュールの観点から考えて、代わりにモジュールを表現する構文を使用できます。ところで、これはMicrosoftがmscorlibで行ったこととまったく同じです。OOPはそれほど多くなく、モジュールと名前空間だけです。
SKロジック

1
より良い質問は、「FP方式で行うことで失う明確性や組織はありますか?」
djechlin

回答:


0

これは、呼び出し元オブジェクトの関心の境界外でタスクを実行するという概念を伝える2つの異なるアプローチの良い例です。

この例では機能的なアプローチを採用する必要があることは明らかですが、一般的には、呼び出されたオブジェクトが示す動作がどれほど複雑であるかに大きく依存します。本当に複雑な動作の問題であり、よく似たロジックを頻繁に再適用し、関数ジェネレーターを使用してそれを明確に表現できない場合は、おそらくクラス構成または継承に行きたいでしょう。アドホックベースで既存の動作を再利用および拡張するためのもう少しの自由があります。

しかし、私が観察したパターンの1つは、通常、開発者は最初は機能的なアプローチを採用し、よりきめ細かい動作が必要になった場合にのみクラスベースのアプローチを採用することを決定するというものです。たとえば、Djangoが機能ベースのビュー、テンプレートローダー、テストランナーからクラスベースのビューに変わったのは、メリットと要件が明らかになった後ですが、それ以前ではないことを知っています。


この答えは少し見当違いだと思います。関数型プログラミングは、関数をプログラミングするだけではありません。関数型プログラミングも抽象化を使用するため、ここで二分法はありません。
ドーバル14

「構成または継承、既存の動作を再利用および拡張するためのもう少し自由がある」あなたはこのように言っていますISNは純粋なFPの中心的な利点の1つではありません。あなたが機能的にコーディングする際にモジュール性、コンポーザとreuseabilityだけで自然に起こる、これは「OOPのもの」ではありません
サラ

@FilipDupanović私は既存のコードの再利用と拡張について言及していました。純粋な関数は、おそらくすべてのプログラミングで最も構成可能なものです。純粋に機能的な環境では複雑さを管理できないかのように書かれています。シンプルな部分をより大きく、それでもシンプルで不透明な部分に構成することで複雑さを管理することはFPのコア全体であり、多くはOOPよりもはるかに優れていると主張します。私が提唱した「問題のないVS固体OOPをスケーリングしない機能的なワンライナー」の二分法には同意しません。
サラ

コードの作成と再利用に関してFPは劣っていると言い、アプリケーションがより複雑になると、OOPは常に「より良く」なると言いました。私はこれが単に偽りであり、誤解を招くものであると主張しているので、私はそれが下票を正当化すると考えました。それは本当に「純粋主義の熱狂」ですか?コメントはこれらのような拡張された議論のためではないので、ここではこれについてさらに議論しません。
サラ

5

機能バージョンは、はるかに短く、保守しやすく、読みやすく、一般的に、考えられるほぼすべての点で非常に優れています。

すべてではありませんが、多くのパターン、オブザーバーなどのOOPの機能の不足を補うことです。これらは機能的にはるかに優れたモデルです。


私も同感です。
ロレンツォデマテ

私は同意し、同じ気持ちを持っています。しかし、私は自分の機能コードを「ごまかし」ていました。私の場合、必要なのはすべてですが、「オブザーバー」を追加および削除する必要がある場合はどうでしょうか。質問を編集しました
ロレンツォデマテ

5

あなたの「FPの第一人者」は部分的に正しいです。多くのオブジェクト指向パターンは、機能的なことを行うためのハッキングです。(これが、せいぜい疑わしいと思われるFP言語が少ない理由であるという彼の主張です。)ObserverおよびStrategyパターンは、一流の機能をエミュレートしようとしています。訪問者パターンは、パターンマッチングをシミュレートするためのハックです。あなたIItemObserverは単なる変装の機能です。アイテムを受け取る他の機能とは違うふりをしても、何も買えません。

オブジェクトはデータ抽象化の一種です。このホワイトペーパーは、そのトピックに光を当てるのに役立ちます。オブジェクトは有用ですが、すべてに適しているわけではないことを認識することが重要です。二分法はありません。適切なジョブに適切なツールを選択するだけの問題であり、関数型プログラミングではオブジェクトを放棄する必要はありません。それはさておき、関数型プログラミングは関数を使用するだけではありません。副作用と突然変異を最小限に抑えることも重要です。


+1(IMO)良い答え。また、論文へのリンクに感謝します。私は少し前にそれを読んで、それを失いました。今、私は再びそれを見つけました。
ジョルジオ14

-1

私は関数型言語が苦手なので、質問に本当に答えることはできません。しかし、私はあなたが持っているものが機能している限り、アプローチについてそれほど心配するべきではないと思います。私が理解していることから、将来リスナーを追加しないか、実行中にリスナーを変更しない限り、ここでオブザーバーパターンをスキップできます。

OO言語の「制限」をデザインパターンが補うことに同意しません。OOP機能をうまく利用するためにあります。多態性と継承は機能であり、制限ではありません。設計パターンはこれらの機能を利用して、柔軟な設計を促進します。OOで完全に非OOプログラムを作成できます。細心の注意を払って、FPを模倣した、状態を持たないオブジェクトを含むプログラム全体を作成できます。


1
「FPに似た状態を持たないオブジェクトを含むプログラム全体を細心の注意を払って作成できます。」もちろん、規律を通じて命令型言語でも同じことができます。:)一般的に、私は限界を補うものとして設計pattersに思うが、Visitorパターンの場合を考慮していない...
ロレンツォDematté

また、私はコードに関係ないです。しかし、私は(私の理解に、これはそうでなければ、私はSOの私のQを掲載しているだろう、programmers.seが何のためにあるのかである)のアプローチ上の仲間のプログラマーに直面したいと思います
ロレンツォDematté

繰り返しパターンを見つけるたびに、それはあなたの言語とモデリングフレームワークの厳しい制限を示しているに過ぎません。理想的な世界にはパターンはまったくありません。
SKロジック

@ SK-logic:残念ながら、世界は理想的ではなく、現実の世界にはパターンがあります。これはオブジェクト指向言語は、継承を持っている理由、状態を持っているagain.Real世界のオブジェクトの上にそれらのすべてを書き換えることなくrepeateableコードを実装することで、国家のパターンが存在する理由thatsの
DPD

1
@ SK-logic:一部の言語はプログラム可能であり、一部の言語では型システムからの効果を強制できることもよく知っています。私のポイントは、「OOP」のように、「パターン」は悲しいことに誤解されている用語だということです。パターンは、似ているが異なる形式で再出現し続けるものであり、均一な解決策を認めない。時々、それらの準競合を消滅させることができます-マルチメソッドは、訪問者/二重ディスパッチを冗長にします。それは、「すべてのパターンが欠陥の兆候である」ことを意味するものではありません。それは、現実の世界が欠陥を意味するからです。パターンはソフトウェアではなく、アーキテクチャに由来します。
フランク・シーラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.