「世界は事実ではなく、事実の集まりです」:ウィトゲンシュタインと操作指向プログラミング

私たちのプログラムは世界をシミュレートします。 OOPの仮説を心から受け入れた人は誰でも、この方法のフレームワークでのモデリングプロセスが基本的に決定に反するという事実にすぐに遭遇します。 さらに詳しく説明します。



以下、企業の従業員を対象とした一般的な書籍の例を検討し、SIのようなものについて書きます。 PersonクラスからEmployeeクラスを継承することは、特にメモリにデータを排他的に保存する場合には素晴らしいアイデアです。SQLにはテーブル継承にいくつかの問題がありますが、それはポイントではありません。データを整理する方法。 メソッドの問題。



ビジネスロジックの各メソッドの背後には、このメソッド(多くの場合、単独ではない)がモデル化する世界の事実があります。 プログラミングファクトは操作です。これを引き続き呼び出します。 メソッドをクラスのメンバーにすることで、OOPは操作をオブジェクトにバインドする必要があります。操作はオブジェクトの相互作用であるため(2つ以上)、単項操作の場合を除き、純粋なリフレクションは不可能です。 PaySalaryメソッドは、従業員、現金、銀行口座のクラスに割り当てることができます。これらはすべて、所有権が同等です。 この方法のジレンマは開発プロセス全体に付随します。その厄介な解決は重大であり、致命的でさえあります。



プログラミングの本では、正直な著者は「オブジェクトはオブジェクトではない」と恥ずかしく認めており、OOPはコードを整理する方法であり、モデリングメカニズムではありません。 しかし、全体のポイントは「世界は物事ではなく、事実の全体である」ということです。したがって、教科書作家が必要とする形式でOOPを使用して適切なモデルを構築することは根本的に不可能です。 コードで世界をモデル化することは可能ですが、モデルの原子はオブジェクトではなく、事実である必要があることを理解することが重要です。



2年前にソフトウェア開発の世界にいましたが、私はアリストテレスがまだここに君臨していることに気がつきました。OOPは彼の哲学の直接的な結果です。 このいやらしい思想家は、化学者のためのフロギストン、物理学者のための原動力を思いついた-私は何と言うことができる! -各主要分野に付属。 ヨーロッパの進歩の歴史は、アリストテレスを克服した歴史です。 彼は科学全体に対して、聖なる審問全体よりも多くの悪を行ってきました。 科学者が彼の物理学の痕跡を消すのに2000年かかった。 OOPは、その暗い影の最後の避難所です。 ここで彼と会うとき-最も先進的な技術の中核で-私はアンティークスタイラススタイラス (牛の運転手の棒がローマで呼ばれたように)を取り、他の誰もが長い間やっているように、邪悪なギリシャ人を彼の石造りの地下室に戻したいです。



ルートヴィヒ・ヴィトゲンシュタイン(彼の格言はタイトルにあります)は、哲学の博士としてアリストテレスから2ページを読んでいなかったため、興味深いものです。これらは彼の-ウィトゲンシュタインの言葉です。 ネオポジティビズムが唯一の「機能する」哲学システムであることは驚くことではありません。実際、今日の唯一の正しい哲学です。これを支持して、例えば、科学知識の現代的方法論を開発したネオ実証主義者カール・ポッパーに言及することができます。



関数型プログラミングは、OOP星雲に対する何百万人もの開発者の直感的な反応になりました-その完全な否定。 私自身、階層的な原則を完全に放棄する理由はないと思います。それらには多くの便利さがあります。 よく知られている言語は、操作の階層を構築するための既製のツールを提供していません。その構文とキーワードがどのように聞こえるべきかを想像するのは今では困難です。 また、オブジェクトからキャッシュの操作にフォーカスを移すこともできます。よく知られているOOP言語はこれを処理できます。



まず、ビジネスロジックをデータと操作の2つのスペースに分割します。 データ空間は特別なものではありません-通常の階層に組み込まれたデータクラスです-ランダムアクセスメモリ(POJO)にのみ存在するか、状態を保存する機能(.NETエンティティ、YIIモデル)を備えています。 フレームワークの要件に応じて、データクラスに独自のメソッドを含めることができます。これらのメソッドがビジネスロジックに関連しないことが重要です。



Public Class Account { Public string accountBankName; Public string accountMfo; Public string accountNumber; } Public Class Company { Public string companyTitle; Public string companyPhone; Public Account companyAccount; } Public Class Department { Public string departmentTitle; Public Company departmentCompany; } Public Class Person { Public string personName; Public date personBirthDate; } Public Class Employee inherits Person { Public Department employeeDepartment; Public double employeeSalary; Public Account employeeAccount; }
      
      





複数の部門(Department)と従業員(Employee)があり、人々のクラス(Person)から継承された会社(Company)があります。 会社には、従業員に給与を支払うアカウント(アカウント)があります。 したがって、各従業員は給与を受け取るためのアカウントを持っています。 私たちのプログラムが次のことができると仮定します:



-従業員を仕事に連れて行く。

-従業員の給与の支払い。

-退職金のある従業員を解雇する。



従業員の雇用と解雇は、人事(スタッフ)オペレーションと呼ばれ、退職金と給与の支払い-会計(アカウンティング)オペレーションと呼ばれます。



操作ごとに、次のものが必要です。



-会社データを初期化する;

-従業員データを初期化します。

-特定のドキュメントを印刷します。



従業員を受け入れる/解雇するには、



-会社の関連部門のデータを初期化します。



これら2つのアカウンティング操作には、次のものも必要です。



-従業員と会社の銀行口座のデータを初期化します。



主なもの、つまり実際の運用スペースに移ります。 クラスの階層として実装します。各クラスは「オペレーションコンテキスト」と呼ばれます。 これらのクラスのパブリックメソッド(API)はビジネスロジック操作になり、プロパティとプライベートメソッドは抽象化の形成に役立ちます。 以前に受け入れられた分離に従って、ベースBaseOperationContextから継承されたStaffOperationContextクラスとAccountingOperationContextクラスがプログラムに表示されます。 操作の階層に補助メンバーを配置することは、オブジェクトの階層よりも簡単です。



 Public Class BaseOperationContext { //  BaseOperationContext () { InitCompanyData(); } BaseOperationContext (Employee employee) { InitEmployeeData(Employee employee); InitCompanyData(); } //     private void InitCompanyData(); private void InitEmployeeData(Employee employee); protected void PrintDocument(Document doc); } Public Class AccountingOperationContext inherits BaseOperationContext { //  AccountingOperationContext () { super(); } //     Private InitAccountData(Account account); Private BankTransfer(Account account, Double amount); //   – API  Public void PaySalary (Employee employee) //  / { // …    InitAccountData (employee.employeeAccount); // …    BankTransfer (employee. employeeAccount, salaryAmount); // …    PrintDocument (someSalaryPayDocument); } Public void PayRedundancy (Employee employee) //    { // …    InitAccountData (employee. employeeAccount); // …    BankTransfer (employee. employeeAccount, redundancyAmount); // …    PrintDocument (someRedundancyPayDocument); } } Public Class StaffOperationContext inherits BaseOperationContext { //  StaffOperationContext (Employee employee) { super(employee); } //     Private InitDepartmentData(Department department); //   – API  Public void RecruitEmployee (Person person, Department department) //   { InitDepartmentData(department); Employee employee = person; // …    PrintDocument (someRecruiteDocument); } Public void FireEmployee (Employee employee, Department department) //  { InitDepartmentData(department); // …    //  AccountingOperationContext     AccountingOperationContext accountingOC = new AccountingOperationContext (); accountingOC.PayRedundancy (employee); // ..    PrintDocument (someFireDocument); } }
      
      





このコードでは、OOPの原則を破ります。FireEmployeeメソッドは、そのクラスStaffOperationContextを「包含」ではなく「is」と呼びます。つまり、従業員の解雇は、その要素(メンバー)ではなく、人事操作(相続人)の特殊なケースになります。 報酬は常識の獲得です。 「従業員の解雇は「従業員」オブジェクトのメンバーです」という誤った記述は、正しい「従業員の解雇は人事業務です」に置き換えます。 ステートメントの正確さは、正しいモデルの構築に希望を与えます。



決定の問題(どの方法を使用するか)はデフォルトでは解決されていないようですが、解決可能です。 「Wittgensteinに従って」開発された私の唯一のアプリケーションでは、インターフェイスに依存していました。 フロントエンドに約10個の画面があるため、ロジックを操作の10のコンテキストに分割し、階層の最上部に基本コンテキストを配置しました。



操作はさまざまな方法で分類できますが、原則自体が重要です。オブジェクト指向プログラミングを操作指向プログラミングに置き換えます。 繰り返しますが、ビジネスロジック、つまりプログラムの世界についてのみ話します。 環境クラスを使用し、その子孫を生成することは何も妨げません。



幅広いIT奨学金がなければ、多くの哲学者やプログラマーがすでにそのような考えを訪れたことがあると思います。 それらはおそらくテキストの形で-独立して繰り返しも提示されたでしょう。 私自身はそのような研究に出会ったことがなく、このように自分で成功するのに2年かかった-私には思える-オブジェクト指向と関数型プログラミングの組み合わせ(外見的に)。



説明した方法で、私はこれまでの最後のプロジェクトにビジネスロジックを実装しました。 完全なリファクタリング(私が継承したプロジェクト)の結果、コードは70%削減され、すべての(非常に重要な)変更についても信じられないほどフレンドリーになりました。 この体験は成功しました。試してみることを提案します。




All Articles