1. ホーム
  2. functional-programming

[解決済み】関数型プログラミングのソフトウェア工学の方法論はありますか?[クローズド]

2022-04-15 06:18:40

質問

今日教えられているソフトウェア工学は、完全にオブジェクト指向プログラミングと「自然な」オブジェクト指向の世界観に焦点を合わせています。ドメインモデルをクラスモデルに変換する方法について、いくつかのステップとユースケースダイアグラムやクラスダイアグラムのような多くの(UML)成果物を用いて説明する詳細な方法論が存在します。多くのプログラマーはこのアプローチを内面化し、ゼロからオブジェクト指向アプリケーションを設計する方法について良いアイデアを持っています。

最近の流行は関数型プログラミングで、多くの書籍やチュートリアルで教えられています。しかし、関数型ソフトウェア工学についてはどうでしょうか? LispとClojureについて読んでいるとき、2つの興味深い記述に出会いました。

  1. 関数型プログラムは、トップダウンではなくボトムアップで開発されることが多い(「Lispについて」ポール・グラハム)。

  2. 関数型プログラマはマップを使い、OOプログラマはオブジェクト/クラスを使う ('Clojure for Java Programmers', talk by Rich Hickley)。

LispやClojureで、機能的なアプリケーションを系統的に(モデルベースで)設計するための方法論は何でしょうか。一般的なステップは何か、どのような成果物を使用するか、問題空間から解決空間にどのようにそれらをマッピングするか?

どのように解決するのか?

ソフトウェア工学の人たちが、まだ関数型プログラミングを発見していないことを神に感謝したい。 ここにいくつかの類似点があります。

  • 多くのOOデザインパターンは、高階関数として捕捉されます。 例えば、Visitorパターンは関数型の世界では「フォールド」(とんがり頭の理論家なら「カタモルフィズム」)と呼ばれるものです。 関数型言語では、データ型はほとんど木かタプルであり、すべての木型はそれに関連する自然なカタモルフィズムを持っています。

    これらの高階関数には、プログラミングのある種の法則、別名「自由定理」が備わっていることが多い。

  • 関数型プログラマは、OOプログラマに比べ、ダイアグラムをあまり使用しません。 OOダイアグラムで表現されることの多くは、代わりに次のように表現されます。 タイプ あるいは、シグネチャと呼ばれるもので、モジュールの型と考えるべきでしょう。 Haskellにも"type classes"があり、これはインターフェイスの型に少し似ています。

    型を使っている関数型プログラマーは、一般に「型が正しくなれば、コードはそれだけで書ける」と考えています。

    すべての関数型言語が明示的な型を使っているわけではありませんが プログラム設計の方法 は、Scheme/Lisp/Clojureを学ぶのに最適な本で、型と密接に関連する"データ記述"に大きく依存しています。

<ブロッククオート

LispやClojureで、機能的なアプリケーションを系統的に(モデルベースで)設計するための方法論は何でしょうか?

データの抽象化に基づく設計手法であれば、どんなものでもうまくいきます。 私はたまたま、言語が明示的な型を持っていると、これが簡単になると思っているのですが、そうでなくてもうまくいくのです。 抽象的なデータ型の設計法について書かれた良い本で、関数型プログラミングに簡単に適用できます。 プログラム開発における抽象化と仕様 バーバラ・リスコフとジョン・グッタグ著の 第一 版です。 Liskovはこの作品の一部でチューリング賞を受賞した。

また、Lisp特有の設計手法として、自分が取り組んでいる問題領域でどのような言語拡張が有用かを決め、それをハイジェニックマクロで言語に追加していく方法があります。 この種の設計については、Matthew Flattの記事(英語)が参考になります。 Racketで言語を作成する . この記事は有料である可能性があります。また、この種の設計に関するより一般的な資料は、 "ドメイン固有の組み込み言語" という用語で検索すると見つかります。Matthew Flattが扱う以上の特定のアドバイスや例については、おそらくGrahamの Lispについて もしくは ANSI Common Lisp .

一般的な手順、どのような成果物を使えばいいのか?

共通のステップ

  1. プログラム内のデータとそれに対する操作を特定し、そのデータを表す抽象的なデータ型を定義する。

  2. 共通する操作や計算パターンを特定し、高階関数やマクロとして表現する。 リファクタリングの一環としてこのステップを踏むことを期待する。

  3. 型付き関数型言語を使用している場合は、早い段階で頻繁に型チェッカーを使用する。 LispやClojureを使用している場合、ユニットテストを含む関数コントラクトを最初に記述するのがベストプラクティスです。 そして、あなたのプラットフォームに移植されたQuickCheckのどのバージョンでも使いたいと思うでしょう。 ClojureCheck . これは、高階関数を使用したコードのランダムテストを構築するための非常に強力なライブラリです。