Думать головой (Thinking in head). 1. Обобщение
Серия коротких заметок "Thinking in head" была задумана, как некий противовес механистическому подходу к программированию, пропагандируемому различными тиражируемыми "учебниками" шаблонов. Потому что думать надо не шаблонами, думать надо головой. Начнем с того, что кажется очевидным.
Откажитесь от термина "наследование", который искажает смысл действий. Мы обобщаем. Обобщение (наследование) реализации или интерфейсов - весьма спорный механизм в программировании, его применение требует осторожности и обоснования.
Основное правило: обобщаемые классы должны иметь сходную основную функциональность. Например, если два или более классов:
- Порождают объекты, реализующие одинаковый или близкие интерфейсы
- Занимаются отличающейся обработкой одних и тех же входных данных
- Предоставляют единый интерфейс доступа к другим данным, операциям или к сервису.
Взгляните: три примера и уже несколько шаблонов оказались ненужными: (1) - "фабричный метод" (factory method), (2) - "стратегия" (strategy), "шаблон метода" (template method) и (3) - "адаптер" (adapter). В принципе, можно для случая (1) еще "прототип" (prototype) записать: если в среде нет развитой поддержки метаинформации (reflection), то реализовать клонирование, скорее всего, придется в потомках общего предка. Далее, в большинстве случаев (если не во всех) вместо "посетитель" (visitor) можно использовать все тот же "шаблонный метод" или вызов метода через reflection (пример описан в заметке "Нешаблонное мышление"). Еще один исключаем.
Почему шаблоны "вдруг" стали ненужными? Потому что требуется только обобщение, причем в перечисленных случаях (1) - (3) необходимость операции более чем очевидна. Требования же исходят напрямую из вашей задачи. Корректно проведя обобщение вы автоматически получите структуру и код, близкую к той, что вам предлагают зазубрить и воспроизводить авторы разнообразных "учебников" шаблонов.
Одно понятие и три очень часто встречающихся на практике случая гораздо эффективнее для запоминания и использования, нежели абстрактные картинки и текст шести шаблонов.
Основная ошибка: обобщение по неосновному функциональному признаку. Например, когда обобщают сотрудников и пользователей. Или заказы на поставку и накладные на отгрузку. Или яблоки с теннисными мячиками. А что, они же желтые, круглые и продаются в магазинах...
Ошибка приводит к построению иерархии по неосновному признаку. Когда "вдруг" найдется еще один такой признак, возможно, более существенный с точки зрения прикладной задачи, то обобщить больше не удастся: придется ломать иерархию или делать заплату в виде множественного наследования, недоступного во многих объектно-ориентированных языках. Или пользоваться агрегацией/композицией, об этом в другой раз.
Не увлекайтесь обобщением. Ошибки тоже обобщаются и уже в прямом смысле этого слова наследуются. Исправление по новому требованию может привести к необходимости сноса старой иерархии, содержащей ошибки. Глубина более 2-3 уровней для моделирования объектов предметной области, как правило, говорит об ошибках проектирования.
Для построения устойчивой глобальной иерархии необходим серьезный анализ предметной области, ведь не случайно классификация - сложная научно-исследовательская работа. Но и такой работы будет недостаточно, если, например, предполагается использование модуля (библиотеки, компонента, службы) в нескольких смежных областях. Класс "Книга" для библиотеки, для магазина, для читателя - это три разных взгляда на одну и ту же сущность с разными ассоциациями и обобщениями. Еще сложнее дело обстоит с классом "человек". Поэтому не спешите наследовать "менеджера" и "охранника" от класса "сотрудник" вне рамок учета кадров, ведь они еще и материально-ответственные лица, руководители/участники проектов, контактные лица, граждане, родители своих чад, налогоплательщики, собственники, вкладчики, заемщики, автомобилисты...
Сергей Тарасов, январь 2007
- Блог пользователя Serguei_Tarassov
- Добавить комментарий
- Просмотров 1533

... до смешного один шаг...
(в смысле от Великого.. до смешного...)
"Откажитесь от термина "наследование", который искажает смысл действий" - а какой смысл действий отражают слова: мама, любовь, вчера?.. Понятно, что непонятно... Попробую пояснить. Смысл действию задает цель. Но цель - не есть действие (в лучшем случае, некое желаемое состояние... неужели мы пьем пиво ради того, чтобы глотать?).
"Мы обобщаем. Обощение (наследование) реализации или интерфейсов - весьма спорный механизм в программировании, его применение требует осторожности и обоснования" - что (Вы) вы обобщаете? Наследование - это частный случай классификации. Любая классификация основана на общности свойств (характеристик) предмета. В свою очередь, свойства (характеристики) отражают не только сам предмет, сколько точку зрения на предмет. В одном и том же предмете выделяют совершенно разные свойства, в зависимости от того, под каким ракурсом он рассматривается. При этом предмет остается самим собой, а наблюдатели (исследователи), соответственно... тоже. И что же обобщается? Если мы попытаемся "обобщить" наблюдателей... вместе с их точками зрения... то услышим много "благодарностей" :) Очевидно, вопрос не в том, чтобы обобщить множество характеристик (и, следовательно, наблюдателей)... а в том, чтобы... Что?.. (это в некотором смысле ключ... или отмычка... :) )
"Основное правило: обобщаемые классы должны иметь сходную основную функциональность" - Так ли это?.. Летать может даже кирпич, но стоит ли его обобщать с чайкой, самолетом, дирижаблем... Может быть, конечно, ответ, в выделенном Вами слове "основную"... Но оно, к сожалению (счастью?), не раскрыто... Что такое "основная" функциональность и чем она отличается от "не основной"?..
"Почему шаблоны "вдруг" стали ненужными? Потому что требуется только обобщение, причем в перечисленных случаях (1) - (3) необходимость операции более чем очевидна" Действительно?.. Почему шаблоны стали ненужными?.. Сия штука, весьма полезна.. IMHO... Другое дело, что с наследованием она никак не пересекается... То, что мы множество действий производим машинально (по шаблону) не мешает нам относится к классу Homo sapiens... Или мешает?..
"Основная ошибка: обобщение по неосновному функциональному признаку. Например, когда обобщают сотрудников и пользователей" Почему бы и нет?.. Homo и там и там... Что мешает их обобщить?.. Точка зрения, которая диктуется узостью конкретной задачи?..
"Ошибка приводит к построению иерархии по неосновному признаку" IMHO, IMHO, IMHO... Признаки определяются точкой зрения, точка зрения определяется задачей... задача ставится конкретными людьми, исходя из текущих потребностей... Отрешаемся от людей, проблем, задач, точек зрения? С чем останемся (будем медитировать?)...
"Глубина более 2-3 уровней для моделирования объектов предметной области, как правило, говорит об ошибках проектирования" Хм... По большому счету... 7 уровней достаточно, для описания мироздания :) До пяти уровней человеческий мозг может дотянуться... IMHO...
"Класс "Книга" для библиотеки, для магазина, для читателя - это три разных взгляда на одну и ту же сущность с разными ассоциациями и обобщениями" Ну, вот... это же должно было прозвучать в самом начале, хотя и в конце... неплохо... :)
"Еще сложнее дело обстоит с классом "человек". Поэтому не спешите наследовать "менеджера" и "охранника" от класса "сотрудник" вне рамок учета кадров" А в рамках учета кадров можно?.. Хм... (все насмарку... жаль... IMHO).
Все вы верно
Все вы верно написали, Александр Сергеич, но контекст не вполне подходящий.
Вот учат школьников арифметике, и пока они от натуральных чисел не перейдут к целым, то действие 3-5=? является "запрещенным". Потом доходят до квадратных уравнений: отрицателен дискриминант, значит нет корней (за скобками: действительных корней, но большинство всю жизнь будет считать, что их нет вообще).
Вот вы меня и ругаете, за то что я пишу, что нет, мол, корней в уравнении :) Во-вторых, говоря о 7 уровнях для описания мироздания, вы имеете в виду уровни структурной сложности, агрегацию. Это ортогонально наследованию реализции в классах программы.
Продолжая аналогии.
Арифметика натуральных чисел соответствует разработке "от требований заказчика". Опросили пользователей, составили "кейсы"/сценарии, закодировали. Подперли стенку костылями тестов, чтобы не сразу упала. Если что-то изменить и расширить надо - возможно, придется все переделывать. Экстремальное программирование во всей красе.
Алгебра. Требования идут от предметной области процентов на 80. Пользователи опрашиваются только для уточнения требований на уровне интерфейса и бизнес-правил. Система расширяется в рамках предметной области без проблем. Проблемы возникают при обобщении на комплексную систему, контекст. За примерами далеко ходить не надо: ERP, построенные "от бухгалтерии".
Отвечая на вопрос по поводу термина "основная функциональность" - да, в данной статье это совокупность функционала, идущая из предметной области. Мы уже отвязались от точек зрения пользователей.
Высшая математика... Сложные комплексные системы. Это то, о чем вы начали писать.
Но, все-таки, заметка рассчитана на тех, кто чувствует ограниченность "арифметики" и хочет использовать "алгебру". Поэтому предлагаю о высшей математике говорить в ином контексте. В разделе "Концепты" есть статьи на эту тему, в т.ч. и ваши, но датированные прошлым десятилетием - было бы весьма интересно почитать о сегодняшнем состоянии мысли.
Простое или сложное
Не ругаю я никого...
Возможно, что дело не в названиях: "арифметика", "алгебра"... Кто-то за "детей" решил, что абстракции они понимают хуже. Проблемы методологии или конкретного учителя переложили на детей. Образование (изучение математики, в частности) трудно ровно настолько, насколько оно неинтересно.
Сбор требований... от заказчика или от предметной области?.. Если, конечно, "предметная область" умеет говорить, если, конечно, исследователь умеет... слушать и видеть. Пока же мне не понятно, что такое требования предметной области. Самое трудное на пути к Будде... отказаться от желания стать Буддой. Возможно... самое трудное в познании предметной области отказаться от желания... описать ее. Возможно, тогда она предстанет во всей красе... возможно, но не обязательно.
Тем более, не следует думать о больших системах, что они трудны для понимания. Что труднее понять Атом или Вселенную? Риторика... IMHO... Дело не в величине систем, не в том, что большое трудно объять, дело в самих исследователях, в частности, в том самом шаблонном подходе, о котором Вы пишите. Не понять они пытаются, а втиснуть предметную область в "прокурстово ложе" шаблона... но заменив один шаблон мышления другим, чего мы добьемся? И... до смешного осталось всего полшага... IMHO, IMHO, IMHO...
"Одно понятие и
"Одно понятие и три очень часто встречающихся на практике случая гораздо эффективнее для запоминания и использования, нежели абстрактные картинки и текст шести шаблонов."
Это всё правильно. Но знание паттернов весьма полезно на этапе кодирования. Весьма удобно ввести в гугле "реализация синглтона на C++" и получить описание всех возможных граблей с примерами кода, а то и с библиотеками на шаблонах/дженериках.
Использование же паттернов при проектировании системы в голове мне лично трудно себе представить.
Иными словами
При явном разделении детального проектирования и кодирования. При автономной работе и в небольших командах такое практически не встречается. Судя по описаниям проектов в литературе - можно обойтись и в больших, если правильно организовать процесс.