オブジェクト指向言語での非オブジェクト指向プログラミング[非公開]


15

最近、オブジェクト指向プログラミングを使用して、関数の加算、減算、乗算、除算、およびパワーを備えた計算機を作成するタスクを割り当てられました。このタスクを正常に完了しました。しかし、その後、オブジェクト指向のテクニック/メソッドを使用せずにプログラム全体を再プログラミングしました。

私が気づいたのは、コードの長さが大幅に短縮され、非常に理解しやすいことでした。ここでの私の質問は、オブジェクト指向プログラミングをいつ使用する必要があるかということです。オブジェクト指向言語でオブジェクト指向のないプログラムを作成しても大丈夫ですか?これで私を親切に助けてください。

PS:ここでは、手続き型プログラミングよりもオブジェクト指向プログラミングのメリットを教えてほしいとは思っていません。


12
必要に応じて異なる手法を適用することを避ける理由はまったくありません。プログラマーとしてのあなたは、ケースバイケースで長所と短所を比較検討する必要があります。かなり頻繁に個人的なスタイルになります。
ChaosPandion 14

3
問題になったことは一度もありません。この言語は、ほとんどの場合、チームや他のアーキテクチャを考慮して、規定されたツールでした。


8
オブジェクト指向技術を使用して、または使用せずに同じプログラムを実装することは、何かを学ぶのに良い練習です。しかし、あなたの質問の問題は、それがすでに異なる形式でここで複数回尋ねられていることです。そして、あなたはそれを否定しています、手続き型プログラミングよりもオブジェクト指向プログラミングのメリットについて尋ねています。C ++はオブジェクト指向言語ではなく、ハイブリッド言語です。
Doc Brown 14

3
入力した数式を表示する機能を追加し、次に平方根関数を追加します(最初にこれを行わないでください、これは不正行為です)。ご意見をお聞かせください。
ジェフ14

回答:


25

C ++は「単なる」オブジェクト指向言語ではなく、マルチパラダイム言語です。そのため、オブジェクト指向プログラミングの賛成または反対を決定したり、両方を混在させることができます。オブジェクト指向の手法を使用すると、プログラムに構造が追加され、プログラムが特定のサイズまたは複雑さに達すると、そこから恩恵を受けます。ただし、この追加の構造は、追加のコード行の代価を伴います。したがって、「小さな」プログラムの最善の方法は、多くの場合、最初に非OOスタイルで実装し、その後プログラムが長年にわたって成長し始めたときにOOテクニックを追加することです(おそらく「運動」 「プログラムですが、多くのビジネスプログラムの典型的なライフサイクルです)。

トリッキーな部分は、プログラムの複雑さがより多くの構造を必要とするサイズに達する時点を見逃さないことです。そうでなければ、スパゲッティコードの巨大な山になってしまいます。


単純な「運動」プログラムが進化し始めた場合、最善の方法は、後でリファクタリングできるように実装することです。それを共有していただきありがとうございます:) +1
FaizanRabbani 14

@CarlSmith:絶対に。しかし、答えを書いたとき、実際の質問のポイントと規模に焦点を当てようとしました。
Doc Brown

10

プロのプログラマーは、OOPに行くかどうかをどのように判断するのですか?それは私にとって本当に役立つでしょう。

私にとって、2つの決定ポイントがあります。最初に、最初は明らかな場合があります。実装の詳細が大きく異なる共通のメソッドをすべて共有する同様のタイプが多数あります。たとえば、ワークフローシステムを構築していて、任意のタスクを実装する機能が必要でした。タスクを実行するために、Execute()抽象メソッドを使用して、各タスクが継承する基本クラスを実装しました。継承クラスは実装を提供しましたが、ワークフローシステムは、実行されているタスクの種類について何も知らずに実行を開始できました。

しかし、ほとんどのプロジェクトはそれほど明確ではありません。2番目の決定ポイントは、プロジェクトのサブセットがif-thenステートメントまたはswitch-caseステートメントの巨大な絡み合いに成長したとき、特にそれらのif-thenステートメントが正しく実行するために多くのセットアップコードを必要とするときです。私は自分が達成しようとしていることの論理を失い始めているように感じ、コードは脆弱に感じ始めます。その時点で、通常は特定の実装を使用してコードを基本クラスにリファクタリングするときが来たという兆候です。

機能的なスタイルではなくオブジェクト指向のスタイルに切り替えることの大きな部分は、if-thenステートメントを「このアクションを実行する」ステートメントに変換することです。if-thenステートメントの膨大なセットの代わりに、コードにアクションを実行するよう指示するだけです。実際に実行されるアクションは、指定した実装によって異なります。

たとえば、C#スタイルの擬似コードの機能スタイルは次のとおりです。

if ( action == "email" ) { 
    callEmailFunction(userInfo);
}
else if ( action == "sms" ) { 
    callSmsFunction(userInfo);
}
else if ( action == "web" ) { 
    endpoint = "http://127.0.0.1/confirm";
    confirmWeb(endpoint, userinfo);
} 
...

ただし、次のように書き換えることができます。

interface IConfirmable {
    void Confirm(UserInfo userinfo);
}

public class ConfirmEmail : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmSms : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmWeb : IConfirmable { 
    // this is a constructor
    public ConfirmWeb(string endpoint) { 
        ...
    }

    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via web
    }
} 

そして、コード自体:

// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();

// get the userinfo however you get it, 
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;

// perform the action.
confirmer.Confirm(userinfo);

さて、if-then内に非常に小さなコードがある場合、これは利益を得るための多くの作業のように見えます。そして、if-thenに非常に小さなコードがある場合、それは正しいです。それは、理解するのが難しいコードの多くの作業です。

しかし、オブジェクト指向スタイルは、Confirm()実行する必要があるメソッドだけでなく、複数のアクションがある場合に本当に輝いています。初期化ルーチン、実行可能な3つ以上のアクションメソッド、およびメソッドがある場合がありますCleanup()。基本アルゴリズムは同一ですが、共通の基本クラスを実装する適切なオブジェクトを呼び出します。さて、あなたは、オブジェクト指向のスタイルに真のメリットを見始める:基本アルゴリズムがあるくらい、それは方法のあらゆるステップでのif-then文をチェックしていた場合よりも読みやすいです。


詳細な分析のために+1。:)私はこれについてほとんど考えていません。
FaizanRabbani 14

1
余談:すべての回答に「ありがとう」のコメントを投稿しないでください。ディスカッションではなく、質問と回答だけに集中することを好みます。
フィリップケンドール14

5
その例は、機能的というよりも必須です。
OrangeDog 14


1
ただ、注意してください、if / elseまたはswitchステートメントの束に傾倒しているとき、それは常に一種のlookuptテーブルを考慮するオプションです。それを書き換えるための別の方法は、の線に沿って行くのでvar dict = new Dictionary<string,Action<UserInfo>{ { "email", callEmailFunction }, { "sms", callSmsFunction } }; dict[ action ]( userInfo );(dictのは、静的な、エラーを省略取り扱い可能)
stijn

3

はい、プロジェクトの範囲が広く知られているか、制限されている限り、古いスタイルのコードを使用することはまったく普通です。プログラムまたはプロジェクトの拡張を計画している場合、OOPは1つの方法です。コードをシームレスに維持および拡張できるためです。一方で、計画していて、拡張性を計画しないという結論に達した場合作成するプロジェクトは、OOPなしでコードを記述すれば十分です。OOP以外のアプローチを使用する場合、プロジェクトをアップグレードできないという意味ではありませんが、それは面倒な作業になります。OOPは、私たちの概念を実際の生物であるかのように視覚化するのに役立ちます。何よりもそれらをよく理解しているからです。


1
「OOP以外のアプローチを使用する場合、プロジェクトをアップグレードできないという意味ではありませんが、それは面倒な作業になります。」:OOPは、ほとんどの拡張機能に新しいクラスの追加が含まれる場合(たとえば、 GUI)。ほとんどの拡張機能に新しい操作の追加が含まれる場合、手続き型設計の方が効果的です。
ジョルジオ

1
「オブジェクト指向ではない」が「古いスタイル」と呼ばれるのはいつですか?
ダニエルサンク14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.