Дизайн класса Wrapper и внедрение зависимостей - PullRequest
0 голосов
/ 04 апреля 2019

У меня есть простой класс FTP, который заботится о загрузке и загрузке через библиотеки cURL:

class FTPClient
{
public:
    explicit FTPClient(const std::string& strIPAddress);
    virtual ~FTPClient();

    bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile);
    bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile);

private:
    static size_t WriteToFileCallBack(void *ptr, size_t size, size_t nmemb, FILE *stream);
    static size_t ReadFromFileCallback(void* ptr, size_t size, size_t nmemb, FILE *stream);

    std::string m_strUser;
    std::string m_strPass;
    std::string m_strIPAddress;
    std::string m_strPort;

    mutable CURL* m_objCurlSession;
};

Я попросил несколько советов о том, как его лучше реализовать и структурировать, поскольку он является базовым и основным.для проекта, и он будет использоваться во многих частях.Мне сказали использовать класс cURLWrapper для обертывания всех вызовов cURL (curl_easy_setopt (..)), но затем мне сказали создать интерфейс для класса FTP, cURLWrapper, который просто вызывает методы FTP итогда конкретный класс ... но он все еще слишком абстрактен для меня, и я не понимаю, как лучше его реализовать и какой путь выбрать.

Как бы вы подошли к этой небольшой структуре?

1 Ответ

0 голосов
/ 04 апреля 2019

Определите простой интерфейс для вашего класса FTP:

class IFTPClient
{
public:
    virtual ~IFTPClient();

    virtual bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile) = 0;
    virtual bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile) = 0;
};

Я предполагаю, что ваши статические методы обратного вызова обращаются к какому-то экземпляру класса, а не к одиночке? Это нормально тогда. Выведите свой класс из интерфейса:

class FTPClient:IFTPClient
{
    ...

Я заметил, что IP-адрес передан в конструктор, а другие параметры (имя пользователя, пароль, порт и т. Д.) Определены в другом месте. Это, кажется, еще не вполне соответствует. Вам необходимо провести рефакторинг, чтобы эти параметры можно было установить с помощью методов интерфейса или добавить их в методы загрузки / выгрузки.

Создайте свой FTPClient объект (ы), прежде чем он понадобится где-либо еще, а затем только передайте ("внедрите") интерфейс в объекты, которые хотят использовать FTPClient. Для модульного тестирования без использования фактического FTPClient создайте фиктивный объект, полученный из того же интерфейса, и вместо этого внедрите его в другие объекты.

Другие объекты просто используют функциональность, предоставляемую в интерфейсе, и им не нужно знать или беспокоиться о его внутренней реализации; если вы решите использовать curl или что-то еще, то полностью до FTPClient.

Это в двух словах; Возможно, вы захотите выполнить поиск внедрения зависимостей и сред в Интернете, но вам не нужна среда, которая будет следовать принципам внедрения зависимостей, и, на мой взгляд, они могут быть излишними для простых проектов.

...