2009-08-17 13 views
1

すべてのあなたの実用的なオブジェクト指向の人のための簡単な質問。 OO標準に同意するために、「プロセッサ」や「xxxxHandler」のようなクラスを避けるために何度も読んでいます。システムコードの理解のための良い尺度だと思います。OOスタイル - 簡単な質問

いくつかのファイル構造をスキャンするソフトウェアがあるとしましょう。具体的には特定のCSVファイルを考えてみましょう。 CsvParserという独立したモジュールがあるとしましょう。

class CsvParser { 
    public string GetToken(int position) { .. } 
    public bool ReadLine() { .. } 
} 

class MyCsvFile { 
    public string FullPath { get; } 

    public void Scan() { 
     CsvParser csvp(FullPath); 
     while (csvp.ReadLine()) 
     { 
      /* Parse the file that this class represents */ 
     } 
    } 
} 

これは、 "FileScanner"クラス(プロセッサタイプのクラス)を節約します。収集するものには、ディレクトリからのファイルの束があり、それぞれをスキャンします。

class MyFileScan { 
    public string[] Files { get; set; } 

    public void GetFiles() { this.Files = Directory.GetFiles(..); } 

    public void ScanFiles() { 
     foreach (string thisFilePath in Files) 
     { 
      CsvParser csvp(thisFilePath); 
      /* ... */ 
     } 
    } 
} 

OOのアプローチでは、MyCsvFileクラスを指定し、次にそのオブジェクトに対する操作を表すメソッドを指定します。

どのような考えですか?あなたはプログラマーが何を考えますか?

+0

このコミュニティのウィキはありませんか? (私はこの質問をした人の一人になったとは信じられません) – Imagist

答えて

1

私は、オブジェクトが自分自身だけを必要とする操作を処理する必要があることを説明していると思いますが、これは一般的には従うのが良い規則です。いくつかの異なる(しかし関連する)ものを「処理」する限り、「プロセッサ」クラスには何も問題はありません。しかし、CSVパーサだけがCSVを解析するようなものを処理するクラスがあると、プロセッサが処理しないことが本当にありません。

ただし、このルールを破棄する一般的な理由があります。通常は、行う必要はないことです。たとえば、CSVクラスでは、最初のセルが「Bob」で、その行の3番目の列(つまり、Bobの生年月日)を取得するCSVの行を見つけるだけであれば、ファイル全体を読み込み、構文解析して、作成した素敵なデータ構造を検索したいと思っています。特に、CSVに100K行があり、ボブのエントリが5行目にある場合は、非効率です。

あなたは、 CSVクラスでは、次の行にスキップして最初のセルを取得するなど、CSVの小規模な操作を行うことができます。しかし、今はあなたがCSVを持っていると言っていない方法を実装しています。 CSVは行を読み込まず、それらを保存します。彼らは細胞を見つけず、ただ持っているだけです。さらに、CSV全体を読み込み、最初のセルで行を並べ替えるなどの大規模な操作を行う場合は、ファイル全体を読み込み、解析して作成したデータ構造全体あなたは同じクラスで両方を行うことができますが、今はあなたのクラスは本当に2つの異なる目的のために2つのクラスです。あなたのクラスは結束を失い、作成するクラスのインスタンスは2倍の手荷物を持ちますが、その半分しか使用しない可能性があります。

この場合、CSVの高レベル抽象化(大規模操作の場合)と低レベル操作の場合の「プロセッサー」クラスを持つことが理にかなっています。 (私は、C#を知っているよりも、それがよく知っているので、以下はJavaで書かれている):

public class CSV 
{ 
    final private String filename; 
    private String[][] data; 
    private boolean loaded; 

    public CSV(String filename) { ... } 

    public boolean isLoaded() { ... } 
    public void load() { ... } 
    public void saveChanges() { ... } 
    public void insertRowAt(int rowIndex, String[] row) { ... } 
    public void sortRowsByColumn(int columnIndex) { ... } 

    ... 
} 

public class CSVReader 
{ 
    /* 
    * This kind of thing is reasonably implemented as a subclassable singleton 
    * because it doesn't hold state but you might want to subclass it, perhaps with 
    * a processor class for another tabular file format. 
    */ 
    protected CSVReader(); 
    protected static class SingletonHolder 
    { 
     final public static CSVReader instance = new CSVReader(); 
    } 

    public static CSVReader getInstance() 
    { 
     return SingletonHolder.instance; 
    } 

    public String getCell(String filename, int row, int column) { ... } 
    public String searchRelative(String filename, 
     String searchValue, 
     int searchColumn, 
     int returnColumn) 
    { ... } 

    ... 
} 

本の類似の周知の例では、SAXおよびDOMあります。 SAXは低レベルのきめ細かいアクセスですが、DOMは高レベルの抽象化です。

+0

これは私の目を少し開いたのでこれを選ぶ必要がありました。私はCSVParserをどのように抽象化できるかを少し疑問に思いました。現時点では、ファイルに対しては読み取り専用操作しか行われませんが、最終的には要件が変更されます。私はsipwizのアドバイスを取って、必要なものをオブジェクトにさせます。みんなありがとう。 –

3

私はあなたの哲学に同意しますが、私の場合はおそらく、クラスCsvFileを呼び出し、スキャン方法に加えてParseメソッドを持っています。オブジェクト指向プログラミングでは、クラスを "物"(英語の名詞)を表現することが常に望ましいです。

あなたのコードを維持するように依頼された場合を除き、私はCsvParserクラスが何をしているのか把握していましたが、MyFileScanは私を怒りに陥らせ、コードを読まなければなりませんでした。

+0

また、 "MyX"という名前を付けると私は狂ってしまいます。 MyObjectやMyClassのような非常に一般的な説明の例を書いているなら、その罰金はあります(ただし、この場合、メタ合成変数foo、bar、baz、qux、quux、corge、grault、garly、waldo、fred、 plugh、xyzzy、thud)。しかし、あなたが何かのためにクラスを使用するつもりなら、私はMyCSVではないCSVを見たいと思っています。このCSVは誰に、なぜ彼らは所有権を主張していますか? – Imagist

+0

確かに正しいと私は完全に同意する。ここでは例として「My」を使用しています。私はfoo、barなどを使わずにここに自分のドメインに行きたいと思っていました。良い点。 –

1

これは問題ドメイン対ソリューションドメイン設計です。

問題を解決するために、私たちは問題ドメインに従ったプログラムである実生活オブジェクトをモデル化するようにクラスを設計することができます。

もう1つのプログラミング方法は、Solution Domainに基づいた設計です。

たとえば、Flight管理エキスパートのためにフライト予約システムを設計している場合、フライト旅行を「ルート」、「時間」、「角度」(私は本当にその言葉を思い出すことはできません)と記述します。これらのモデルに従って設計すれば、問題ドメインに従った設計と呼ばれます。

座標系(x、y、z)を使用して設計することもできます。プログラマとして、これらをより効率的に処理できると感じているからです。これはSolution Domainの設計です。

ソリューションドメインの問題は、プロジェクトの世界では、一定であるものが - 変更!要件は常に変化します!要件が変更されている場合は、プログラムを再設計する必要があります。

しかし、クラスを実際のオブジェクトとしてモデル化すると、実際のオブジェクトがほとんど変更されないため、変更の影響を受けにくくなります。

「プロセッサ」と「xxxxHandler」< - これはソリューションドメインに対する設計です。

Domain Driven Design --- DDDを見てみることができます。

+0

私が見ているように、私は確かにそれを調べます - 私が話すように "ウィキペディアディング"。あなたはこれが思考プロセスと関係があると思うと思うのですが、私たちは物事をどのようにモデル化するのですか?基本的には、オブジェクトをどのように使用するかは、オブジェクト自体よりも変化する可能性が高いと言っていますか?または私は誤解しています。 ありがとう –

+0

私は、顧客からの要求は常に変わると言います。実生活モデルに基づいてクラスを設計すると、要件の変更が免除されます。 – janetsmith