2013-05-29 10 views
8

私はおじさんボブ・マーティンhere(下図)で説明したクリーン・アーキテクチャの概念に従ってC++(C++ 11)に非常に単純な例を記述しようとしている:それほどきれいなアーキテクチャ

enter image description here

コントローラーでテキストを読み込んでプレゼンターで印刷することを考えています。 私は何かしたことがありますが、ブログ投稿のクリーンな流れとDIPに従っているようには見えません。

IUseCaseInputPortがIUseCaseOutputPortについて知っておく必要がある(例えば、read関数が入力パラメータとしてIUseCaseOutputPortを持ち、別の依存関係を作成するなど)、フローが間違っていると思います。

これを実装する最善の方法についてのヒントを教えていただけたら本当にありがたいです。 事前に感謝します。興味のある方、BЈовићによって示唆されているように私の質問を補完するために

#include <iostream> 
#include <string> 
#include <memory> 

class IUseCaseOutputPort { 
public: 
    virtual void print(std::string message) = 0; 
    virtual ~IUseCaseOutputPort() {}; 
}; 

// 2 Presenters 
class HtmlPresenter: public IUseCaseOutputPort { 
public: 
    void print(std::string message) { 
     std::cout << "<p>" << message << "</p>" << std::endl; 
    } 
}; 

class TextPresenter: public IUseCaseOutputPort { 
public: 
    void print(std::string message) { 
     std::cout << message << std::endl; 
    } 
}; 

// 
class IUseCaseInputPort { 
public: 
    virtual void read(std::shared_ptr<IUseCaseOutputPort> output) = 0; 
    virtual ~IUseCaseInputPort(){}; 
}; 

// specific UseCaseInteractor 
class UseCaseInteractorForInputFromStdIn: public IUseCaseInputPort { 
public: 
    void read(std::shared_ptr<IUseCaseOutputPort> output) { 
     std::string message; 
     std::cout << "Please input some text!"; 
     std::getline(std::cin, message); 
     output->print(message); 
    } 
}; 

// Controller 
class ControllerToDisplayHtml { 
public: 
    void displayInHtmlSomethingFromStdIn() { 
     input = std::make_shared<UseCaseInteractorForInputFromStdIn>(); 
     std::shared_ptr<HtmlPresenter> output = 
       std::make_shared<HtmlPresenter>(); 
     input->read(output); 
    } 
private: 
    std::shared_ptr<IUseCaseInputPort> input; 
}; 

int main() { 
    ControllerToDisplayHtml c; 
    c.displayInHtmlSomethingFromStdIn(); 
    return 0; 
} 

。非常に単純な例。このモデルの流れを表示するだけです。とりわけ

#include <iostream> 
#include <string> 
#include <memory> 
#include <fstream> 

class IUseCaseOutputPort { 
public: 
    virtual void print(std::string message) = 0; 
    virtual ~IUseCaseOutputPort() {}; 
}; 

// 2 Presenters 
class HtmlPresenter: public IUseCaseOutputPort { 
public: 
    void print(std::string message) { 
     std::cout << "<p>" << message << "</p>" << std::endl; 
    } 
}; 

class TextPresenter: public IUseCaseOutputPort { 
public: 
    void print(std::string message) { 
     std::cout << message << std::endl; 
    } 
}; 

// 
class IUseCaseInputPort { 
public: 
    virtual std::string read() = 0; 
    virtual ~IUseCaseInputPort(){}; 
}; 

// specific UseCaseInteractor for reading text from the stdin 
class UseCaseInteractorForInputFromStdIn: public IUseCaseInputPort { 
public: 
    std::string read() { 
     std::string message; 
     std::cout << "Please input some text!" << std::endl; 
     std::getline(std::cin, message); 
     return message; 
    } 
}; 

// specific UseCaseInteractor for reading text from a dummy file 
class UseCaseInteractorForInputFromDummyFile: public IUseCaseInputPort { 
public: 
    std::string read() { 
     const std::string filename = "/proc/meminfo"; 
     std::string message = readFile(filename); 
     return message; 
    } 
private: 
    std::string readFile(const std::string filename) { 
     std::string line; 
     std::string lines; 
     std::ifstream myfile(filename); 
     if (myfile.is_open()) { 
      while (myfile.good()) { 
       getline(myfile, line); 
       lines += line + '\n'; 
      } 
      myfile.close(); 
     } else { 
      lines = "Unable to open file"; 
     } 
     return lines; 
    } 
}; 

// Controller 
class ControllerForReading { 
public: 
    std::string readFromStdIn() { 
     input = std::make_shared<UseCaseInteractorForInputFromStdIn>(); 
     std::string out = "This text was read from the stdin:\n"; 
     out += input->read(); 
     return out; 
    } 
    std::string readFromFile() { 
     input = std::make_shared<UseCaseInteractorForInputFromDummyFile>(); 
     std::string out = "This text was read from the a file:\n"; 
     out += input->read(); 
     return out; 
    } 
private: 
    std::shared_ptr<IUseCaseInputPort> input; 
}; 

// main represents the outer shell 
int main() { 
    std::cout << "Main started!" << std::endl; 

    ControllerForReading c; 
    const std::string textFromStdin = c.readFromStdIn(); 
    const std::string textFromFile = c.readFromFile(); 

    auto output = std::make_shared<HtmlPresenter>(); 
    output->print(textFromStdin); 
    output->print(textFromFile); 

    auto output2 = std::make_shared<TextPresenter>(); 
    output2->print(textFromStdin); 
    output2->print(textFromFile); 

    std::cout << "Main ended!" << std::endl; 
    return 0; 
} 
+3

質問が本当にバグではなくコードスタイルに関するものであれば、http://codereview.stackexchange.comで質問してください。 –

+0

ありがとうございます。バグやコードスタイルのようには見えません...私が導入した余分な依存関係を避けたいだけです。返信がない場合は、提案した場所に投稿します。 – RicLeal

答えて

4

、私は例えば、IUseCaseInputPortは(read関数は、このように別の依存関係を作成し、入力パラメータとしてIUseCaseOutputPortを持ってIUseCaseOutputPortについて知っている必要があり、通りの流れが間違っていると思います... )。

はい、これは間違いです。データを取得する方法では、何が行われているのかを知るべきではありません。

修正は非常に簡単です。結果を返すようにIUseCaseInputPort::read方法を変更し、代わりにIUseCaseOutputPortのメソッド呼び出し:

// 
class IUseCaseInputPort { 
public: 
    virtual std::string read() = 0; 
    virtual ~IUseCaseInputPort(){}; 
}; 

// specific UseCaseInteractor 
class UseCaseInteractorForInputFromStdIn: public IUseCaseInputPort { 
public: 
    std::string read() { 
     std::string message; 
     std::cout << "Please input some text!"; 
     std::getline(std::cin, message); 
     return message; 
    } 
}; 

// Controller 
class ControllerToDisplayHtml { 
public: 
    void displayInHtmlSomethingFromStdIn() { 
     input = std::make_shared<UseCaseInteractorForInputFromStdIn>(); 
     std::shared_ptr<HtmlPresenter> output = 
       std::make_shared<HtmlPresenter>(); 

     const std::string messageToOutput(input->read()); 
     output->print(messageToOutput); 
    } 
private: 
    std::shared_ptr<IUseCaseInputPort> input; 
}; 

もう一つを。 displayInHtmlSomethingFromStdIn()メソッドで入力オブジェクトと出力オブジェクトを作成しないでください。代わりに、何らかの依存性注入を使用する必要があります。つまり、これらのオブジェクトを外部に作成し、ControllerToDisplayHtmlオブジェクトへのポインタまたは参照を介して渡します。

+0

ありがとう!今ははるかに良い! – RicLeal

+0

チップをありがとう。これは単なるテストに過ぎませんでした。私は私の質問の下に適切な例を掲示します。 – RicLeal

関連する問題