関数型プログラミングにおける設計パターンは必要か?


あなたがスペイン語でこの記事を読むことに興味があるならば🇪🇸, ブログ一覧にもどる
The Developer's Dungeon

導入


昨年の結末以来、私は関数型プログラミング(FP)に入ってきました.
私はいくつかの概念を非常に理解するのは難しいが、物事はまだ非常に不自然なのですが、このプロセスを通して、私たちは、オブジェクト指向プログラミング(OOP)で定期的に機能するいくつかのことに気づき始めた機能プログラミング言語で実装することはずっと簡単です、彼らはより少ないコードを必要とし、時には実装自体が言語自体が提供するデフォルトで来る.
前の記事では、私は固体の原理FPに適用する方法について話しました、あなたはそれを読むことができますGoF Book

戦略パターン


最初の定義から始めましょう.

The strategy pattern is a design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
Strategy lets the algorithm vary independently from clients that use it.


これはどんな感じですか.

OOP言語では、一般的に、共通のインターフェイスを実装する各戦略に対して別々のクラスが含まれます.これにより、実行中に1つまたは他のものを選択する可能性がある一方で、アルゴリズムの選択および戦略間の実装における相違点を分離します.
FPでは、このパターンは非常に簡単に実装し、はるかに少ないコードが必要になります、私はJavaScriptを使用するつもりですが、それは同様に完全な機能言語で実装することができます.
const strategy1 = () => {
  console.log('run strategy 1');
};

const strategy2 = () => {
  console.log('run strategy 2');
};

const consumer = (runStrategy) => {
  /*
  Do other stuff
  */

  runStrategy();
}

const selectedStrategy = condition ? strategy1 : strategy2;

consumer(selectedStrategy);
ご覧のように、FPでは、戦略パターンはパラメータとして関数を渡すのと同じくらい簡単になります.私たちが同じ機能を達成するためにクラスまたは継承に依存する必要がないので、はるかに少ないコードがあります.

ファクトリーパターン


The factory method pattern is a pattern that uses methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.


OOP言語では、これは一般的に、オブジェクトを作成するビジネスロジックをカプセル化し、実行中にどのオブジェクトを作成するかを決めることができます.これは、作成するオブジェクトに応じて、作成されたオブジェクトに特定のパラメータを設定することがしばしばあります.
fpではこのパターンは非常に簡単に実装できます.
const behavior1 = () => {
  console.log('do behavior 1');
};

const behavior2 = () => {
  console.log('do behavior 2');
};

const factory = (condition) => {
  /*
  Do other stuff
  */

  if (condition) behavior1; 

  return behavior2;
}
見ることができるように、高次の関数は単純な解決を再度行います.クラスの継承によって振る舞いを定義するのではなく、目的の動作やオブジェクトをカプセル化する関数を返すだけです.

デコレータパターン


The decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.


OOP言語では、オブジェクトを別のものにラップして、オリジナルのものが持っていなかった余分な機能を提供します、実際にその実装を変更することなく、さらに、あなたはあなたが既存のオブジェクトに加える必要がある機能を実行時に選ぶことができます.
FPで、これは達成されますComposition , FPのコアアイデアの一つは、他の動作を形成するために構成することができる小さな関数に機能を分離することであるので、ラップするクラスを持っている代わりに、あなたはLEGO ブロックと一緒に新しい行動を作成するためにそれらをピース.例を見ましょう.
const compose = (...fns) => x => fns.reduceRight ((v, f) => f(v), x);

function isBiggerThanThree(value) {
  return value > 3
}

function mapBoolToHumanOutput(value) {
  return value ? "yes": "no"
}

const biggerThanThreeAndMapOutput = compose(
  mapBoolToHumanOutput,
  isBiggerThanThree
)

biggerThanThreeAndMapOutput(3)
この例では、1つの小さなことをして、新しい振る舞いを生成するためにそれらを作成する2つの関数を定義します😄

オブザーバーパターン


The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.


このパターンは、プッシュ対プルのアイデアに依存します.別の状態が変化したかどうかを常にチェックしているオブジェクトを持つ代わりに、第2のオブジェクトは、それ自身の状態が変化したときに、他の全てに通知する.
fpでは、これはコールバック、イベント、オブザーバーの形で使われるパターンです.また、ライブラリのように非常に使用されてRX.js for Reactive Functional Programming私は、「コールバックとは何か」に対する答えを参照するつもりですスタックオーバーフロー.

シングルトンパターン


The singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance. This is useful when exactly one object is needed to coordinate actions across the system. The term comes from the mathematical concept of a singleton.


OOP言語では、インスタンス化を行わずにどこでも利用できるようにオブジェクトの静的インスタンスを作成し、誰かが再度インスタンス化しようとすると、前のインスタンスが返されます.
FPでは、このパターンは完全に不要になります.データが完全に関数から分離されているため、アプリケーション全体にさらされる必要があるグローバル状態はありません.また、すべての関数はグローバルな名前空間に存在し、常にアクセス可能です.

結論


あなたが見ることができるように、OOP世界で進化したパターンのいくつかは、それらの言語に、FPというのは、状態とデータの上でoopのような支配を特徴づけるものを失うことなく、自由に得る利益を与えるようです.
前述の例によって提案された解決策に適合したので、私が言及しなかったいくつかの他のパターンがあります.
私が機能的プログラミングへの私の旅行を続けるので、私は多分私のこの仮定に合う多くの例とケースを見つけるでしょう.あなたがこの記事が好きであるならば、私がコメントを知っているように、私は彼らを入れ続けます.
それを共有することを忘れないでください😄