Меньше ветвлений!
Одно из правил Таранцова гласит: в программе не должно быть большого редко исполняющегося куска кода.
Пример. Вы пишете библиотеку, которая отправляет данные об исключениях на сервер. Чаще всего, как только исключение возникло, можно сразу обратиться к серверу, передать ему нужные данные и забыть о них. Иногда, тем не менее, Интернет или сервер оказывается недоступен.
Тут есть две альтернативы. Вариант А: попытаться отправить исключение, если не удалось, записать его в файл, минут через десять считать и попробовать заново. Вариант Б: записать исключение в файл, попробовать его отправить через пару секунд; если не удалось, повторить снова еще позже.
Представьте себе, что мы выбрали вариант А. Тогда, поскольку чаще всего сервер доступен, большой кусок кода, отвечающий за сохранение на диск, установку таймера, загрузку и пр., обычно не используется и не тестируется. А значит:
1. Увеличиваются затраты на автоматизированные тесты и на QA.
2. Рано или поздно вкрадется бага, не отловленная тестами и не пойманная вашим QA-процессом. (Например, всё рушится только под Windows Vista x64, установленной на FAT32-раздел.)
3. Продукт с этой багой вы можете поставить заказчикам и не узнаете о ней, пока заказчик с ноутбуком под Windows Vista x64 на FAT32 не запустит ваш продукт вдали от Интернета.
Сравним с вариантом Б. Исключение всегда сначала записывается, потом устанавливается таймер, он срабатывает, исключение считывается и отправляется. Нормальную (частую) и ненормальную (редкую) ситуации обрабатывает один и тот же код; если он не работает, пользователи закричат об этом сразу же.
Иногда такая «унификация» кода подсказывает дополнительные возможности. Скажем, если программа начнет генерировать тысячи исключений в секунду, отложенная на пару секунд отправка поможет реже обращаться к серверу.
Из нашего правила следуют два важных практических соображения.
Первое. Если вы взвешиваете, добавлять или не добавлять в программу новую опцию, помимо прочего подумайте и о том, сколько придется написать редко исполняющегося кода.
Второе. Когда вы пишете обработку ошибок или каких-то других особых ситуаций, всегда пытайтесь превратить эти особые ситуации в нечто, что исполняется каждый день. Вместо операций «начать» и «продолжить» делайте операцию «начатьИлиПродолжить», вместо событий «завершилось» и «прервано из-за ошибки» делайте событие «остановилось» и т. д.
8 comments:
ой. Вы намешали паттерны Адаптер, Стратегия и Отложенная инициализация и считаете что сделали правильно совершенно по неправильным мотивам.
Милый мой читатель, не всё всегда определяется низкоуровневыми паттернами уровня GoF. (Вы, например, знакомы с паттернами GRASP?) Я изложил достаточно высокоуровневую цель, критерий, если хотите.
Подход на уменьшение количества ветвлений действительно работает, Андрей. Причём, этот подход можно даже развить на постановку задачи. Если в формулировке слишком много слов "если" и "то" и "иначе", то тот, кто ставит задачу скорее всего хочет получить шнягу.
С какого перепугу автор первого коммента понёс про адаптер и всякую такую хрень, я не понял.
2Andrey Tarantsov: Спасибо, что обращаетесь к своим читателям "милый" - это так мило.
Касательно иерархии уровней. А не кажется ли Вам, что именно GRASP низкоуровневые, а уже под их эгидой строятся шаблоны GoF. Насчет моей профессиональности я бы на Вашем месте не сомневался, изучив кто оставляет комментарии.
2localstorm: "всякая такая хрень", как Вы выразились станет для Вас очень полезным багажом знаний, если сможете осилить материалы на тему шаблонов проектирования. А насчет "с какого перепугу", то если бы Вы затруднили себя построением диаграмм взаимодействия при использовании описанных выше шаблонов, то прекрасно бы поняли, что логику программы можно строить на объектах, а не только низкоуровневым ветвлением (if...else, switch и пр.)
Azazel: Я должен возразить по нескольким пунктам.
1. Хотя заголовок поста использует слово «ветвление», согласитесь, его тело не про if'ы.
2. Иногда у людей восприятие низа-верха в уровнях не совпадает, так что спорить об этом бессмысленно.
GRASP — это несколько базовых принципов; есть и другие базовые принципы, сформулированные Фаулером или же просто следующие из здравого смысла.
GoF, как и PoEAA, как и паттерны из работ одного Влиссидеса, как и более специфичные паттерны а-ля Александреску — просто кучка полезных идиом. Их отличает важная черта — они используются для микродизайна (или, если хотите, «минидизайна»).
На уровне макродизайна — GRASP, распределение обязанностей по подсистемам, Model-Driven Design (и другие более специфичные вещи макроуровня, вроде Event Sourcing).
Я полагаю, что я изложил соображение из макродизайна: требование «единого пути исполнения» накладывает ограничения на требования к подсистемам.
Вы же приводите идиомы микродизайна. Ими нельзя объяснять макрорешения. Более того — паттернами вообще нельзя объяснять решения: сначала принимаются решения, а потом находятся полезные для них паттерны.
Увы, я не изучал, кто оставляет комментарии, но если вы профессионал, то вы всё это понимаете. Полагаю, вас просто ввело в заблуждение слово «ветвление» в посте. Разумеется, если бы речь шла просто про if'ы и switch'и, то приводимые вами паттерны помогли бы от них избавиться.
Кстати, localstorm, полагаю, вполне знаком с GoF.
(Просто любопытно) :)
А насколько оправдано каждый раз сохранять файл? На это же тратится время, а операции чтения\записи из\в файл времязатратны и вообще не приятны :) Ведь ситуация когда это необходимо маловероятна, а бОльшая часть запросов должны уходить сразу...А тут "бах"..у пользователя мега интернет, с супер компьютером, у него всё работает быстрее мысли, а мы вместо того что бы моментально всё проработать потратим время на запись\чтение...пользователь огорчится и не будет пользоваться нашим проектом :( :)
ПС: А вот за саму идею(не использовать редкие ветки) - запомню и постараюсь применять, спасибо!
> А насколько оправдано каждый раз сохранять файл?
А что, когда пользователь отключен от Интернета, все должно тормозить?
Вообще, нужно практиковать brain-driven development, тогда ничего тормозить не будет.
Конечно, нет.
Да, да, про тормозить от файла - это глупости. Но мой юный мозг с настороженностью относится к выполнению не нужных в данный момент действий.
Post a Comment