Здравствуйте, zelenprog, Вы писали:
Z>Добрый день!
Z>Недавно перечитывал книгу Бертрана Мейера "Объектно-ориентированное конструирование программных систем".
Z>Там все функции классов разделяются на три категории: "конструктор", "аксессор" и "модификатор".
Z>А как же быть с функциями, которые выполняют отложенную\ленивую загрузку\инициализацию?
Z>Получается, что это "неправильные" функции?
Z>И ими нельзя пользоваться?
Да
Z>Ведь действительно, когда смотришь на название такой функции, она вводит в заблуждение.
Z>Может быть есть смысл разделить ее на две функции?
Z>И в клиентском коде везде явно вызывать две функции при необходимости:
Нет, это называется "двухшаговая инициализация" — источник многих ошибок.
Z>Хотя, так наверно тоже неправильно, потому что клиент и не должен ничего знать про "отложенную" инициализацию.
Проблема не в этом, а в том, что "инициализация", как и любое другое действие, которое может завершиться неуспехом, должно быть явно видно в исходниках.
Есть общие правила: "гет-свойства не должны бросать исключения", "конструкторы не должны бросать исключения" (в C++ это просто ошибка)
Z>Как же быть?
Z>Как лучше делать в таких случаях?
Решение простое — factory method
class C {
protected C(Widget widget) {
this.widget = widget;
}
static C? FromWidgetId(it widgetId)
{
var w = Widget.Load(widgetId);
if w != null? new C(w) : null;
}
}