- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
The Programmers Stone (Программистский камень) - Alan Carter
Шрифт:
Интервал:
Закладка:
Инспектирование кода, организованное таким образом и совмещенное с индивидуальной пошаговой проверкой имеет свое назначение, и маловероятно, что оно деградирует до маразма религиозных войн по поводу стиля комментариев, на которые сейчас тратят свое время многие высокооплачиваемые программисты.
Стандарты кодирования и руководства по стилю
Стандарты кодирования и руководства по стилю уже несколько раз появлялись в этой работе, и уже сказанное могло сильно отличаться от общепринятых убеждений. Будет полезно изучить эти различия и понять в точности, о чем мы говорим.
Мы показали, что индустрия программирования часто пытается расположиться между двумя очень различными взглядами на мир. Паковщиков выдрессировали структурировать свои доводы и рассуждения вокруг идентификации ситуации с заученными ответами, а затем исполнения того действия, которое та предписывает. Их поведение в мире основано на том, чтобы делать правильные вещи. На работе им говорят, что делать. Картостроители стремятся получить общее понимание ситуации, применяя известные паттерны там, где они применимы, и создавая новые там, где их нет. Картостроители, если им задана цель, в своих действиях руководствуются своими картами. На работе они понимают проблему и находят оптимальное решение. Мы также увидели, что картостроительный подход — это то, как создается новое программное обеспечение, и его нельзя создать паковкой.
Поэтому стандарты кодирования отражают частично мотивацию картостроителей, частично мотивацию паковщиков, и в результате цели создателей стандартов перепутываются. Проявляется коммуникационный барьер между картостроителями и паковщиками, поэтому картостроители рвут на себе волосы, поскольку паковщики растирают сложность, пока она не станет невидимой на каждой отдельной странице, цитируя Пакет Знаний 47684 (Ясность Это Хорошо) и в то же самое время вытирая ясность из работы.
Если мы примем, что картостроение и TQM — основы хорошего программирования, и что суть картостроения и TQM — понимание и управление (контроль), мы можем посмотреть на цели и увидеть, что мы можем сделать для улучшения стандартов кодирования и руководств по стилю.
Сначала о ясности. Есть идея, что использование синтаксического богатства языка — это Плохая Вещь, поскольку это «сложно». Ни когда составной синтаксис образует идиому. Ни даже когда эта идиома вводится и обсуждается в документации. И вообще не нужна ни при каких условиях. Когда Ньютон писал «Принципы» (Newton's Principia), то написал их словами, хотя мог использовать алгебраические символы, поскольку был сооткрывателем флюксий, или исчислений. В наше время мы решили, что в математике лучше иметь дело с алгебраической нотацией даже при описании. Сейчас то, что потребовало бы нескольких страниц текста, в алгебраической нотации займет всего страницу, и хотя при этом скорость чтения страницы снижается, общее время чтения стопки текста больше, поскольку в стопке текста гораздо труднее проследить мысль. Итак, следует ли нашим программам быть более похожими на прозу по концентрации сложности на страницу или на выражение, либо им следует быть ближе к математике? Мы предполагаем, что если человек — новичок в языке, то лучше, если он сможет отчетливо увидеть всю структуру и тратить на каждую страницу несколько минут, чем читать каждую идиотскую строчку и не понимать, для чего это написано! Как часто нам приходится видеть напряженных людей, сидящих перед стопкой кода, не имеющих понятия, с чего начать, и думающих, что это их вина.
Второй момент — соглашения. Прежде чем принять соглашение, убедитесь в том, что оно даст больше, чем будет стоить. Мы приводили ранее пример, в котором если кто-то не знает назначение переменной, то он ничего не получит от знания ее типа[15]. Но это не просто вклад в перегрузку мозга соглашениями, которые, как предполагается, «хорошие» программисты должны хранить в виде пакетов знаний, что само по себе проблема. Дело еще и в том, что наличие слишком большого количества соглашений делает код некрасивым и даже уродливым. Если стремиться к красоте минимального кода, то этого сложнее достичь постоянно натыкаясь на обвешанных мусором уродцев типа gzw_upSaDaisies. Никогда не делайте того, что подавляет стремление команды создать великий продукт. Было место, где думали, что соглашения — Хорошая Вещь. Несколько людей были назначены Создавать Правила, и они делали это должным образом. Один из них объявил, что длина имен переменных должна ограничиваться 31 символом. Очень разумно — многие компиляторы могут различать имена не длиннее указанного. Другой объявил, что переменные, описанные в подсистеме, должны начинаться с трехбуквенного альфа-кода подсистемы. Любая переменная, даже если никто не использует ее глобально. (Еще один предложил помечать глобальные переменные.) Еще один произвел причудливую схему типов, параллельную собственным составным типам языка, и потребовал включения информации об этих типах в имена. Зачем — мы не знаем. Еще один опубликовал список сокращений имен модулей кода, известных менеджеру конфигурации и сказал, что это тоже необходимо включить в каждое имя переменной. И т. д. Наступило настоящее веселье, когда оказалось, что все эти обязательные штучки плюс пометка типа «указатель на функцию, возвращающую указатель на запись» превысили 31 символ. Создатели Законов просто сказали, эта конструкция очень сложна и ее не следует использовать, хотя это было главным для архитектуры, и топтались вокруг описывания промежуточных переменных и приведения типов во время присваивания им значений, что совершенно не помогало ни ясности ни эффективности. Поэтому, наконец, пузырь лопнул и мы разработали некоторые прагматические стандарты, которые хорошо выглядели и говорили нам, как с помощью словаря проекта быстро образовать имя и некоторые разумные сокращения. Если посмотреть с точки зрения картостроитель/паковщик, мы видим, что ситуация развивалась подобным образом потому, что Создатели Законов были Объявителями Полезных Правил, что Хорошая Вещь, но цена, цена…
Третий момент — о природе строительных кирпичей. Для целей сохранения хорошего порядка руководство по стилю, содержащее многослойный винегрет из соглашений об именовании, идиом и примеров модулей для разработчиков будет служить служить вам лучше, чем коллекция императивных (обязательных к исполнению) инструкций, ограничивающих способность программиста искать элегантность самостоятельно. Если вы не можете доверить команде самостоятельно решить, когда заключать блок в скобки, а когда нет, как вы можете доверить ей написать ваш суперпроект?
Четвертый момент — об этих императивах. Есть некоторые средства, которые вообще не стоило изобретать, например scanf() и gets()в UNIX. Указания никогда не использовать их в разрабатываемом коде разумны. Но есть цели, которых просто невозможно безопасно достичь другим, лучшим путем. И всегда остается проблема баланса ясности. Мы рассмотрим два конкретных примера, из которых станет видно, что в Си все же существует хороший повод для использования goto — хотя вам могли говорить, что таких поводов нет.
Вот первый, здесь нет другого способа. Представьте рекурсивный обход двоичного дерева:
void Walk(NODE *Node) { // Do whatever we came here to do… // Shall we recurse left? if(Node->Left) Walk(Node->Left); // Shall we recurse right? if(Node->Right) Walk(Node->Right); }
По мере обхода дерева, мы начинаем делаем вызовы, ведущие нас влево, влево, влево, влево… и так до самого низа. Затем просматриваем каждую комбинацию влево, влево, вправо, вправо, влево… и т. д., до тех пор, пока не просмотрим все ветви, и не проделаем все возвраты из нашего последнего визита, который был вправо, вправо, вправо, вправо….
Каждый шаг влево или вправо включает в себя открытие нового кадра стека, копирование аргумента в этот кадр стека, выполнение вызова и возврат. Для некоторых задач с многочисленной навигацией, но небольшой обработкой в узле, эти накладные расходы могут оказаться чрезмерными. Но посмотрите на такую мощную идиому, известную как устранение хвостовой рекурсии:
void Walk(NODE *Node) { Label:// Do whatever we came here to do… // Shall we recurse left? if(Node->Left) Walk(Node->Left); // Shall we recurse right? if(Node->Right) { // Tail recursion elimination used for efficiency Node = Node->Right; goto Label; } }
Мы используем стек для отслеживания того, куда мы попали слева, но после того, как мы обошли левую часть, переход на правую ветвь не требует хранения положения. Поэтому мы устраняем 50 % вызовов и накладные расходы на возвраты. Это может изменить ситуацию при выборе между реализацией на Си или добавлением ассемблерного модуля. Чтобы увидеть другой пример, посмотрите на конструкцию Даффа (Duff's Device) в книге Страуструпа «Язык программирования C++» (Stroustrup's The C++ Programming Language).
Второй пример касается чистоты стиля — вообще нет необходимости применять язык ассемблера. Помните, что когда Дейкстра посчитал goto вредным, он имел в виду привычку использовать goto для организации управления в неструктурированном коде 60-х годов. Идея заключалась в том, что меньше используя goto мы могли бы улучшить ясность. Идея не состояла в жертвовании ясностью избегая goto любой ценой. Представьте программу, которой нужно открыть порт, инициализировать его, инициализировать модем, установить соединение, зарегистрироваться (logon) и загрузить файл (download). Если что-то не так, в любом месте, нам нужно вернуться обратно в самое начало. Доморощенный структуралист мог бы написать нечто вроде:

