Контрольные списки из «Совершенного кода»
20.01.2018 технологии книги
Когда я похвастался прочтением этой замечательной книги, некоторые люди посетовали на то, что забывается суть некоторых тезисов, иногда забывается вообще большая часть прочитанного. К сожалению, так действительно бывает — забывается.
Поэтому, чтобы освежать в памяти действительно важные детали мастерства программирования, я нашёл в сети кем-то заботливо переписанные контрольные списки из книги «Совершенный код». Тем более, бумажную книгу уже скоро придётся отдавать.
Обязательно к прочтению
Нижеперечисленные списки могут вправить мозг большинству разработчиков. Я сам допускал очень много объективно неприятных ошибок, которых теперь не делаю потому что прочитал книгу и внимательно изучил контрольные списки. В этом блоге только то, что относится непосредственно к программированию.
- Об именовании переменных — чтобы переменные ваших программ одним своим именем уже говорили о назначении. Долой $n1, $n2, $XZ4totakoe_neponyatnoe.
- Про работу с данными — числами, строками, константами, логическими переменными, массивами.
- О выскококачественных методах (или функциях) — чтобы у вас не было универсальных функций, которые готовят кофе и приносят тапочки. Чтобы названия их были простыми и понятными, чтобы всё было лучше. Читайте.
- Про использование условных операторов — тоже тот ещё мастхэв! Я, например, раньше мог сделать в начале кучу невероятных проверок, и только в самый конец ставил код, ветвь которого исполняется с наибольшей вероятностью. Это неправильно. А как правильно? Читайте. Узнавайте больше, удивляйтесь своим глупым ошибкам.
- О циклах. Циклы используются в большинстве программ, это одна из основных конструкций в программировании. Соответственно, и ошибок в них можно много налепить…
- Про качество классов — сейчас это для меня вдвойне актуально, я уже в процессе завершения работы над своим первым классом. Изучаю ООП.
О проектировании
Выше были перечислены списки, которые полезны при непосредственной разработке кода, при его написании и проектировании отдельных методов, классов и т. п. Но перед этим обязательно должен быть процесс проектирования, это как план дома и чертежи.
Весьма желательно
Сверяться со всеми остальными контрольными списками. Хотя, кажется, на этом сайте они не все, то есть в книге их гораздо больше. Впрочем, основное и самое главное перечислено.
Но, конечно, простой просмотр контрольных списков не заменит чтения прекрасной книги Стива Макконнелла. Я, как и прежде, настоятельно рекомендую прочитать её всем, кто действительно хочет научиться хорошо программировать.
P.S. А если у вас всё хорошо с английским, то все эти списки можно прочитать на официальном сайте книги «Совершенный код». Вот здесь — cc2e.com/Page.aspx?nid=73. Только не спрашивайте у меня, почему Стив при всех своих достоинствах не додумался сделать ЧПУ :)
Комментарии
Комментирование этой статьи закрыто.
« Офисный пакет Apple iWork для Windows теперь распространяется бесплатно Качественное индексирование сайтов на CMS Wordpress »
Я знаю! Я! Стив настолько суров и совершенен, что ?nid=73 для него — ЧПУ!
ЗЫ: не, билят, уж лучше на русском, красиводизайненом сайте, чем на убогом, времён доткомов, да ещё и со съехавшим в Сафари дизом, да ещё с навязываинем регистрации.
Да уж, в юзабилити чувак не силён, это точно. И про навязывание регистрации я не знал, просто открыл список и скопировал URI. Сейчас проверил — действительно, заставляют регистрироваться. Глупо.
Но сама книга на самом деле очень хорошая, я с неё много почерпнул. Именно о программировании.
Кстати! Большинство программистов вообще не умеют разрабатывать GUI. Они умеют говорить с машиной, но с человеком вообще никак.
Про циклы и условия. Хочется отметить, что пхп позволяет писать в стиле функциональных языков, снижая тем самым количество условий
А какие основные особенности стиля функциональных языков? Можешь привести пример задачи с циклами или условиями, в котором PHP выигрывает в сравнении с каким-то другим языком?
В двух словах трудно сказать. Вот ссылка там довольно понятно все www.ibm.com/develope…
А выигрыша относительно других языков нет. Выиграть можно в выразительности кода, заменив вложенные конструкции на плоские
Могу. В ряде языков ООП навязан, да ещё — и ужасно тяжёлый ООП. Джава например, там пустой проект — уже класс с нечитаемым именем.
Евгений, прочитал статью на IBM, узнал про замыкания и лямбда-функции, довольно интересно это всё… но всё равно не понял, как это связано с сокращением условий в PHP :)
Samlowry, ой, Java мне вообще пока тёмный лес. Скорей всего я даже не буду изучать этот язык, я уже практически на 100% определился, что следующим у меня будет Ruby. Ну ещё «Эрланг» довольно интересен.
Ну, на вскидку, три вещи по «сокращению»:
«Ленивые» логические операторы – $condition && operator; (типично функционально и навевает о времени, проведенном с лиспом)
Динамические функции (классы и т.д.) – например, вызов нужной функции в зависимости от условий без полиморфизма, или, наоборот, при полиморфизме быстрая работа с пулом классов. Сюда же извороты с __call и подобным.
Ну и, соответственно, лямбда функции, которые вообще мечта для всяких там map и reduce, а не только сокращение места. Плюс, соответственно, хитрости «неймспейсов» замыканий.
Ну и samlowry, конечно, не до конца прав – в Джаве даже пустой проект класс потому что это объектное программирование, которое навязывает стиль (прежде всего, для командной и проектной работы), хоть оно и далеко от того, что рисовали нам в Смоллтоке (и сделали что-то похожее в Обжектив Си).
Я такие && не использую, потому что нифига не помню, что они значат, не могу это в голове держать. Ключевые слова типа OR гораздо лучше, на мой взгляд.
Ну, после сишных флагов приедается :)
А or тоже самое – особенно классно выглядит db_connect() or die(); %)
Да, забавно :) Только die, наверно, всё же дурной тон в скриптах писать, надо какую-то ошибку выдавать.
Тормоз, выше уже все написали про использование. Поэтому приведу пример.
If a > b {
If b < 5{ RunX() } If b > 6{ RunY() } }Можно представить так:
runner(a > b and b < 5, runX)
runner(a > b and b > 6, RunY)
Function runner(cond, func){
Return cond and func()
}
Что-то не наблюдается в этом примере особой читаемости или простоты.
Набор последовательных функций всегда лучше вложенных условий. Другой вопрос, что имена подобраны неудачно.
Мало себе представляю, как такое можно использовать (равно как и согласиться, что набор последовательных функций «лучше» или «удобнее» – отказ от условий никогда читаемости не прибавлял).
Я лучше приведу сегодняшний ночной пример.
Есть у меня на проекте (внутренняя финансовая программа небольшой организации) главная страница, которая представляет собой календарь, показывающий что произошло/произойдет в окружении сегодня (и выбранной даты). Справа виджет со списком таких событий «Новые договора», «Последние оплаты» – их много, элементов в них достаточно, чтобы сделать простыню, поэтому реализованы они через раскрывающиеся списки. Когда они закрыты мы показываем количество элементов, а рядом – количество элементов, которые мы еще не видели (сообщение, что увидели – аякс при раскрытии списка).
Такая вот штука iskariot.ru/fin1.png
Все эти списки делаются из двух таблиц, причем сильно пересекаются между собой, а отличающихся возможностей у них всего две: есть ли ссылка на полную выборку/сортировку списка, и какие дополнительную инфу о договоре/контрагенте надо нарисовать. Но в целом все похоже. Если рисовать каждый раз копипасту, получится трудноподдерживаемый и нечитаемый код.
Поэтому я делю множество списков на три подмножества: контрагенты-соискатели, джоин неархивного договора с контрагентом и архивные договора за последний период. Таким образом я собираю до ста элементов в каждом в любой элемент времени (ну, организация-то маленькая) и храню их в переменных класса, чтобы каждый раз не дергать запросы (на странице менеджера было бы 8, на админской – 40). Т.е. масштабирование мы обошли.
Но дальше мне надо рисовать эти списки однотипным образом – вводим функцию рисовки show, которая по типу рисует тот или иной список, а всю дополнительную информацию берет из поля li_add, которое мы предварительно записали на стадии сбора.
Но остается еще куча однотипных функций по коду, которые проходят по нужному им массиву и отбирают только попадающие под условия элементы, плюс заодно ведут пул id‘шников, чтобы их можно было посылать на сервер как «прочитанные» (addToPool()). И выходит такая вещь:
function map($sort, Closure $f){
$db = $this->db;
a = $this->$db;
$self = $this;
array_walk($a, $sort, function($item, $key) use($self, $f){ $el = $f($item); $self->addToPool($el); ArrayOperations::$sort($a); } );
}
И все функции приобретают вид:
$code = ‘tax’;
//инициализируем
$this->flushPool($code, self::T_CONTRACT);
//помещаем в пул только нужные
$this->map(function(&$c){ if($c[‘tax’]){ $c[‘li_dop’]=’<small>(’.maybe_price($c[‘tax’]).’ руб.)</small>’; return $c; }
});
//рисуем
$this->showPool(‘Числится <span style=«color:#900»>госпошлина</span>’,
array(‘show’=>‘active’, ‘mark’ => ‘tax’, ‘sortby’=>‘sum_credit’, ‘sort’=>‘DESC’));
И я могу легко видеть на одном экране всю функцию, а также вмешиваться в любой кусок процесса – что выборку, что вывод (там еще пара дополнительных аргументов).
Я, честно говоря, не знаю, как я мог бы добиться большего удобства, читаемости и гибкости всего на тысячу строчек класса при 30+ (100500) виджетов, которые выводятся всего один раз, но важны, как чугунный мост.
Пример не боевой, поэтому притянут за уши. Но суть должна быть понятна.
Относительно условий отмечу, что я сказал конкретно о вложенных условиях. Не знаю случаев когда раскрытие вложенных условий в последовательность функций вредило читаемости. Интересно посмотреть на пример.
Насчет того что отказ от условий не прибавляет читаемости, тоже интересно увидеть пример когда добавление условий не вредит читаемости. Со своей стороны постараюсь в ближайшее время отрефакторить код тормоза и выложу в блоге на обсуждение.
Какой именно?
Для примера хочу взять вот этот код – pastie.org/1223867
У-у-у, этот код древний уже, да ещё и с ошибкой (сейчас увидел, там неиспользуемая константа вместо переменной). Возьми лучше актуальную версию. У тебя в ящике подарочное письмо от робота, можешь скачать Daos.
Критиковать имеет смысл именно функции чтения/записи, потому что остальной код был написан фактически другим человеком :) В смысле я очень сильно изменился за последний год как программист, и почти всё теперь делаю иначе.
Заранее спасибо. Очень интересно будет увидеть твою реализацию.
P.S. Если письмо снова в «спам» попало, то напиши в ту ветку gmail, с которой у нас всё ОК было.
Спасибо, письмо дошло. Критиковать не собирался, просто некоторые приемы показать которыми сам пользуюсь.
Как это не собирался? Надо! :) Серьезно, я ж ещё только учусь, да все мы учимся. Адекватная критика помогает взглянуть на свой код с другой стороны.
Мне обидно было, когда ты писал про мой «спагетти-код», но я после этого стал гораздо лучше программировать, в том числе и потому что мне указывали на недостатки.