05 февраля 2008

Quick way or right way

Бывало ли у вас так, что можно сделать:
а) как проще
б) как правильно?

У меня - постоянно ;) Примеров - хоть отбавляй. Одна из наиболее частых ситуаций: добавление нового атрибута (member-а) к объекту.

Как это выглядит:
class Object { ... };

class ObjectUser1
{
void UseObject(Object&);
Object ReturnObject();
std::container<Object> SomeMember_;
};

class ObjectUser2...

И тут для конкретной задачи UserOfObjectUser1 требуется чтобы Object еще имел, например, и атрибут Name:
class Object
{
... здесь то, что было...

// добавляем
void SetName(NameType);
NameType Name() const;
NameType Name_;
};
Хочется думать, что Name - очень полезный атрибут для Object, и он ему совсем не помешает. Хотя предыдущим ObjectUser-ам (и user-ам этих user-ов) он вообще не нужен, но они при новой компиляции ничего и не заметят. А думать так хочется потому как альтернатива этому - такова:
class ObjectWithName : public Object
{
ObjectWithName(A a) : Object(a) {}
ObjectWithName(B b, C c) : Object(b, c) {}
ObjectWithName(D d) : Object(d) {}
...
... сколько еще там у Object конструкторов?
... и не забыть добавить сюда новый конструктор если появится у Object
...
ObjectWithName(const Object& o) : Object(o) {}

void SetName(NameType);
NameType Name() const;
NameType Name_;
};
Да еще ObjectUser1 придется делать шаблонным - чтобы мог работать как с Object, так и с ObjectWithName.

Но если сделать как проще, а не как правильно - последствия дадут знать о себе потом. Вот пример:
class File
{
string Name;
int Size;
vector DiskSectors;
void Read(...);
void Write(...);
}
Хотя файл по определению - именованная область на диске, но Name явно здесь лишнее. Точнее - лишнее все, кроме Name. Не верите? Попробуйте создать hard link ;)

Истина где-то рядом:
class DiskArea
{
int Size;
vector<int> DiskSectors;
void Read(...);
void Write(...);
};

class File
{
string Name;
shared_ptr<DiskArea> Area;

// адаптеры - расплата за правильный дизайн
void Read(...) { Area->Read(...); }
void Write(...) { Area->Write(...); }
};

1 комментарий:

Анонимный комментирует...

паттерн "мост" рулит