2013-05-29 11 views
8

मैं सी में कोड करने के लिए कोशिश कर रहा हूँ ++ (सी ++ 11) स्वच्छ वास्तुकला अवधारणा here (चित्र के नीचे) अंकल बॉब मार्टिन द्वारा वर्णित के अनुसार एक बहुत ही सरल उदाहरण:ऐसा नहीं है स्वच्छ वास्तुकला

enter image description here

विचार कंट्रोलर द्वारा कुछ पाठ पढ़ने और इसे प्रस्तुतकर्ता द्वारा प्रिंट करना है। मैंने कुछ किया है लेकिन ऐसा लगता है कि यह स्वच्छ प्रवाह और ब्लॉग पोस्ट के DIP के बाद ऐसा नहीं लगता है।

अन्य चीजों के अलावा, मुझे लगता है कि प्रवाह गलत है, उदाहरण के लिए, IUseCaseInputPort को IUseCaseOutputPort के बारे में जानने की आवश्यकता है (पढ़ने के फ़ंक्शन में IUseCaseOutputPort इनपुट पैरामीटर के रूप में है, इस प्रकार एक और निर्भरता बना रहा है ...)।

मैं वास्तव में सराहना करता हूं अगर कोई मुझे इसे लागू करने के सर्वोत्तम तरीके के बारे में कुछ सुझाव दे सकता है। अग्रिम में बहुत धन्यवाद।

#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; 
} 

रुचि रखने वालों के लिए, मेरे सवाल का एक पूरक BЈовић ने सुझाव दिया है। बहुत सरल उदाहरण। बस इस मॉडल के प्रवाह को दिखाने के लिए।

#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 (पढ़ने समारोह इस प्रकार एक और निर्भरता बनाने, इनपुट पैरामीटर के रूप में 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

संबंधित मुद्दे