Как заставить разработчика сделать что-то - PullRequest
2 голосов
/ 03 ноября 2010

Предположим, у меня есть следующие классы:

class X;
class Y;

class Collection
{
   public:
      virtual void AddItemX(X*) = 0;
      virtual void AddItemY(Y*) = 0;
      //So on...
};

class Collector
{
   public:
      virtual void Fill(Collection&) = 0;
};

Есть ли способ гарантировать, что реализация класса Collector заполнит все необходимые элементы в переданном классе Collection?

Ответы [ 6 ]

3 голосов
/ 03 ноября 2010

Один метод, учитывая известное количество вызовов AddItemX (), состоит в том, чтобы переместить эти функции AddItem () в защищенные и иметь класс Collection, отслеживающий добавления и число, например:

(на самом деле яне нравится это решение, лол, но, учитывая ваш дизайн, этого будет достаточно:)

class X;
class Y;

class Collection
{
private:
    int m_nItems;
    int m_nItemsAdded;

protected:
    virtual void AddItemXImpl(X&) = 0;
    virtual void AddItemYImpl(Y&) = 0;

public:
    Collection() : m_nItems(2), m_nItemsAdded(0){};

    void AddItemX(X& _x) {m_nMethodsAdded++; AddItemXImpl(_x); };
    void AddItemY(Y& _y) {m_nMethodsAdded++; AddItemYImpl(_y); };

    // function to find out if we're filled
    bool isFilled() const {return(m_nItemsAdded == m_nItems); };
}; // eo class Collection

РЕДАКТИРОВАТЬ: Для пояснения, ваш коллектор может быть реализован таким образом:

class Collector
{
protected:
    virtual void FillImpl(Collection& _collection) = 0;

public:
    void Fill(Collection& _collection)
    {
        FillImpl(_collection);
        if(!_collection.isFilled())
            throw(std::exception("Not filled dammit!"));
    };
}; // eo class Collector
2 голосов
/ 03 ноября 2010

Да, написать модульный тест для коллекционера с макетом коллекции.

Обеспечение времени компиляции? Нет.

Обеспечение исполнения? Да, с большими накладными расходами в классе Collection.

1 голос
/ 03 ноября 2010

Одна из вещей, от которых вы отказываетесь, оставляя метод для будущих разработчиков, - это контроль над тем, как они это делают. Вы можете добавить комментарий с вашими рекомендациями, но именно они должны делать то, что подходит для их подкласса. В конце концов, вы никогда не сможете быть уверенным, как будет использоваться ваш класс в будущем.

1 голос
/ 03 ноября 2010

утверждения assert могут быть хорошим способом документировать и проверять, что что-то соответствует вашим предположениям в подобных случаях.

1 голос
/ 03 ноября 2010

Вы упускаете что-то выше, что вызывает Collector :: Fill ()?Именно там вам нужно проверить, что Коллекция заполнена ...

РЕДАКТИРОВАТЬ: У вас есть контроль над тем, откуда вызывается Collector :: Fill ()?Это единственное место, где вы можете проверить, правильно ли заполнена Коллекция.Еще один вариант - вы передаете все по значению, а в конструкторе копирования (или присваивании) вы проверяете ..

0 голосов
/ 03 ноября 2010

Вы можете изменить определения классов, чтобы поощрять правильное использование, проверив Collection допустимость в Collector время создания и запретив построение по умолчанию Collector или модификацию инкапсулированного Collection.Пусть конструктор Collector проверит Collector с помощью чисто виртуального метода.

Это не гарантирует правильности - Collection разработчики могут все еще обманывать, допуская неправильно сформированные подклассы - но поддерживают это, выражая то, что вы хотите более четко.

class X;
class Y;

class Collection
{
   public:
      virtual void AddItemX(X*) = 0;
      virtual void AddItemY(Y*) = 0;
      //So on...

      virtual bool ensureValid() = 0;
};

class Collector
{
   public:
      Collector (const Collection coll&) : _coll(coll)
      {
         if (!coll.ensureValid())
         {
           // throw an error
         }
      }

   private:
      Collector();

   protected:
      const Collection _coll;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...