banner
yono

yono

哈喽~欢迎光临
follow
github

初めてのプログラミングデザイン

前言#

作者はソフトウェアの専門家ではないため、これまでプログラミングの設計を積極的または受動的に学んできたわけではなく、観察と実践に基づく経験主義です。

また、組み込みシステムはこれらにあまり関心を持たず、主に RAM/ROM の使用量、実行速度、ビジネスロジックが要件を満たしているかどうかを評価します。これにより、特定の製品に特化した成果物が多く生まれるという深刻な問題が生じます。

ここには二つの議論があります。

  1. 本当にリソースが制限された MCU 上で再利用可能なコードを使用することはできないのでしょうか?私は否定的だと思います。その理由については後で議論します。
  2. このようにカスタマイズされたソフトウェアコードのアーカイブは、ほとんどコメントがなく説明もほとんどないため、本当にソフトウェア資産と呼べるのでしょうか?私個人としては否定的です。私の認識では、初学者が 8 時間以内に無指導で使用できるソフトウェアモジュールでない限り、合格とは言えません。

最近、真のソフトウェア資産を生み出す方法を考えたいと思い、基本的なプログラミング設計を理解する必要があります。そのため、10 分で完全に理解しました。

以下は、これらの設計についての机上の空論です。笑って流してください。私もこれらのことを実際にどれだけ実践したかはわかりません。

オブジェクト指向プログラミング#

オブジェクト指向は使い古された言葉ですが、私はその専門用語を完全に理解しているわけではありません。

私の見解では、オブジェクト指向の本質は、ある事物の定義に向けられています。つまり、ある事象がどのような機能、変数、定量を含むかを定義することです。例えば、キーボードを定義すると、104 個のキーという定量と、「A を押す」「B を押す」という機能があります。

しかし、そうではありません。市場には奇形のさまざまなキーボードが存在します。これはいわゆる「継承」に関係しており、奇形のキーボードは標準キーボードクラスのいくつかの要素を再定義したものです。例えば、テンキーの「1 を押す」機能を無効にしたり、定量を 88 個のキーと再定義したりします。

オブジェクト指向の世界では、すべてがオブジェクトとして定義され、その後、オブジェクトを定義し、そのオブジェクトのイメージを固定し、継承して拡張することでモジュールを実現します。そして、複数のオブジェクトを組み合わせてプロジェクトを実現します。

私は、移植の難易度と機能のバランスを考慮した場合、オブジェクト指向プログラミングはモジュール化の最良の実現方法であると考えています(現時点ではそう思っています)。

しかし、プロジェクトの観点から見ると、オブジェクト指向は非常に不親切です。プロジェクトの進行中に、あるオブジェクトの事象の定義が変わった場合、システム全体が大きく変わり、問題の原因を特定するのが難しくなります。各オブジェクトの使用において中間層を追加して隔離する場合、それは完全に無駄で新たな定義を生むことになります。要するに、定義の変化があまりにも大きく、実際にはメンテナンス担当者にとって不親切です。

私たちは実際に快適さを求めており、前後を考え、レベルが異なり、混沌とした状態では快適ではありません。

関数型プログラミング#

主に参考にしたのは1.7. 范畴论入门 (*) - 香蕉空间で、この参考資料は数学の知識を紹介するもので、プログラミングには関与していません。

これは実際には難解ではなく、すべては関数です。しかし、すべてが関数でありながらビジネス機能を実現できるというのは、非常に不思議です。

関数型プログラミングには、最も重要な二つのルールがあります(私の見解です)。

  1. すべての関数には入力と出力が必要です。
  2. すべての関数は、どんな状況でも同じ入力に対して同じ出力を持ちます。

私の見解では、関数型の本質は副作用のない確定的な機能を持つ関数を得ることです。

以下の図では、各矢印が関数を示し、各点が入力でもあり出力でもあります。例えば、左から最初の矢印は、最初の点がこの関数に入力され、出力は第二の点になります。そして、第二の点は二つの関数を通じて別の二つの点に変わることができます。ここでの点は何でもあり得ます。もちろん、この思考方法においては何でも関数であり、実数値は固定出力の関数であり、変数を取るのは単位射です1

画像は関数型プログラミング入門チュートリアル - 阮一峰のネットログから盗用しました。

例えば、CRC16 アルゴリズムの実装やさまざまな古典的暗号アルゴリズムの実装は必ず関数型プログラミングです。一組の検証値 / 平文が関数を通じて必ず一組の検証値 / 暗号文を出力します。その検証プロセスや解析も同様に関数型であるため、これら二つのシナリオでは入力と出力が同型です2

私たちは、すべての純粋な数学の問題において、関数型プログラミングを使用することで簡単に解決できることに気づきます。数学が世界を記述できるということを否定しないでください。

しかし、実際のエンジニアリングでは、すべての状態は単純に定義できるわけではなく、大きな入力と出力が関与し、関数の作成も困難です。また、関数の数も決して少なくないと思います。問題を分解すると、関数の数は膨大になります。

実際、関数型プログラミングは工業的思考に適合しています。確定的な動作は確定的なフィードバックをもたらし、特定の有限の状況に対するビジネスロジックには関数型プログラミングを使用でき、相対的に管理が難しい状態機械を使用する必要はありません。

ここで前言の「議論 1:本当にリソースが制限された MCU 上で再利用可能なコードを使用できないのでしょうか?」に戻りますが、明らかに関数型プログラミングはどんな状況でも消費するリソースが似ています。私たちは範疇 3を縮小し、不要な関数を削除して再利用を実現できます。

私の見解は、関数型で数学に関連する関数を書くことは良いカプセル化ですが、この思考をエンジニアリングやビジネスに持ち込む必要はなく、作業量は純粋に指数関数的に増加します。

おそらく命令生成も良い関数型の方向性であり、改造の機会があるかもしれません。

手続き型プログラミング#

上記の二つのプログラミング方法は、関数 / メソッドの副作用を減らし、異なるシステムでほぼ同じ機能を得ることを目的としています。手続き型は異なります。手続き型の本質は、副作用を使用して望む機能を得ることであり、入力値 / 出力値をさまざまな関数 / メソッドで行き来して得ることではありません。

手続き型は、人が解決策を考える際に最も適したプログラミング方式です。詳しくは述べませんが、皆さんは理解していると思います。

まとめ#

要するに、ソフトウェア資産の層構造において、最下層は関数型プログラミングによって形成されたコンポーネントモジュールであり、機能モジュールはオブジェクト指向プログラミングを採用し、関数型コンポーネントを呼び出すというのが私の考えです。

私たちは最も古典的なケース、「象を冷蔵庫に入れる」を考えます。

オブジェクト指向プログラミングでは、象オブジェクトの定義、冷蔵庫の定義(ストレージスペース、入れる方法、取り出す方法を含む)を実現し、二つのオブジェクトをインスタンス化し、その後冷蔵庫の入れる方法を使用します。

関数型プログラミングでは、事前に三つの物件 —— 空の物件、冷蔵庫、象、象を入れた冷蔵庫を定義し、関数 1 は「空の物件」を入力として「冷蔵庫と象」を出力し、関数 2 は「冷蔵庫と象」を入力として「象を入れた冷蔵庫」を出力します。

手続き型プログラミングでは、象を捕まえる関数(副作用は象を生成する)、冷蔵庫を購入する関数(副作用は冷蔵庫を生成する)、象を冷蔵庫に詰める関数(副作用は冷蔵庫を象を入れた冷蔵庫に変更する)です。

この記事は Mix Space によって xLog に同期更新されました。
元のリンクは https://www.yono233.cn/posts/novel/25_4_25_coder です。


Footnotes#

  1. すべての X に対して、単位射 id~X~:XX (または 1~X~ と記述) が存在し、これを X単位射(identity morphism)と呼びます。

  2. C を一つの範疇とし、物件 X,Y と射 f:XY を与えます。もし射 g:YX が存在し、gf=1~X~, fg=1~Y~ であれば、f同型と呼ばれます。この条件を満たす g を一般に f−1 と記述し、f逆射と呼びます。物件 XY の間に同型があれば、XY は同型であると呼び、XY と記述します。

  3. すべての物件、射、集合の定義を含む

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。