Pull to refresh

Основы мастерства

Reading time 6 min
Views 1.6K

Боритесь со сложностью


Как известно, мозг человека может одновременно рассматривать 7±2 элемента. Поэтому очень важно стремиться к снижению сложности ПО. Вот некоторые конкретные рекомендации:
  • Разделите систему на подсистемы на уровне архитектуры, чтобы концентрироваться в каждый конкретный момент времени на меньшей части системы.
  • Тщательно определяйте интерфейсы классов, чтобы можно было игнорировать
    внутреннее устройство классов.
  • Поддерживайте абстракцию, формируемую интерфейсом класса, чтобы не
    запоминать ненужных деталей.
  • Избегайте глобальных данных, потому что их использование значительно увеличивает процент кода, который нужно удерживать в уме в любой момент
    времени.
  • Избегайте глубоких иерархий наследования, потому что они предъявляют
    высокие требования к интеллекту.


  • Избегайте глубокой вложенности циклов и условных операторов, поскольку
    их можно заменить на более простые управляющие структуры, позволяющие
    бережнее расходовать умственные ресурсы.
  • Избегайте операторов goto, так как они вносят в программу нелинейность, за
    которой большинству людей трудно следовать.
  • Тщательное определите подход к обработке ошибок, вместо того чтобы использовать произвольную комбинацию разных методик.
  • Систематично используйте встроенный механизм исключений, поскольку он
    может стать нелинейной управляющей структурой, которую при недисциплинированном применении понять почти так же трудно, как и операторы goto.
  • Не позволяйте классам превращаться в монстров, достигающих размера целых
    программ.
  • Поддерживайте методы короткими.
  • Используйте ясные, очевидные имена переменных, чтобы не вспоминать детали вроде «xx — это индекс счета, а yy — индекс клиента или наоборот?».
  • Минимизируйте число параметров, передаваемых в метод, или, что еще важнее, передавайте только те параметры, которые нужны для поддержания абстракции, формируемой интерфейсом метода.
  • Используйте соглашения, чтобы не запоминать произвольные, несущественные различия между разными фрагментами кода.

Анализируйте процесс разработки


В проектах, реализуемых с участием более одного программиста, более важную
роль играют организационные характеристики, а не индивидуальные навыки. Даже
если у вас отличная группа, ее коллективная способность не эквивалентна сумме
способностей отдельных членов. Используемый группой процесс — вот от чего зависит, будет ли работа конкретного программиста повышать или понижать эффективность работы остальных членов группы.

Процесс разработки важен в первую очередь потому, что качество должно встраиваться в ПО с самого начала. Это притиворечит давней «мудрости», согласно которой вы можете написать сколь угодно плохой код и устранить все ошибки на этапе тестирования. Это заблуждение. Тестирование может только указать на отдельные
дефектные области программы — оно не сделает вашу программу удобнее в использовании, более быстрой, компактной, удобочитаемой или расширяемой.

Преждевременная оптимизация — еще один изъян процесса разработки. Эффективный процесс подразумевает, что вы выполняете грубую работу в начале и тонкую
в конце. Если бы вы были скульптором, вы придавали бы композиции общую форму
и только потом начинали бы работать над отдельными деталями. Преждевременно выполняя оптимизацию, вы тратите время на полирование фрагментов кода,
которые полировать не нужно. Всегда спрашивайте себя: «Делаю ли я это в правильном порядке? Что изменилось бы при изменении порядка?».

Пишите программы в первую очередь для людей и лишь во вторую — для компьютеров



Компьютерам все равно, насколько удобочитаем ваш код. Они вообще лучше читают двоичные команды, а не операторы высокоуровневых языков. Удобочитаемый код нужно писать для того, чтобы он был понятен людям. Читабельность
положительно влияет на такие аспекты программы, как:
  • понятность;
  • легкость выполнения обзоров;
  • уровень ошибок;
  • удобство отладки;
  • легкость изменения;
  • время разработки — следствие всего вышеперечисленного;
  • внешнее качество — следствие всего вышеперечисленного.


Удобочитаемый код писать ничуть не дольше, чем запутанный — по крайней мере в далекой перспективе.

Программируйте с использованием языка, а не на языке


Не ограничивайте свое мышление только теми концепциями, которые непосредственно поддерживаются языком. Самые лучшие программисты думают о том, что они хотят сделать, после чего определяют, как достичь этих целей при помощи инструментов программирования, имеющихся в их распоряжении.

Концентрируйте внимание с помощью соглашений


Общие преимущества соглашений:
  • Соглашения избавляют программистов от необходимости снова и снова отвечать на те же вопросы и принимать все те же произвольные решения.
  • Конвенция лаконично сообщает важную информацию.
  • Соглашения защищают от известных опасностей.
  • Соглашения делают более предсказуемыми низкоуровневые задачи.
  • Соглашения могут компенсировать недостатки языков.

Программируйте в терминах проблемной области


Другим специфическим методом борьбы со сложностью является работа на максимально высоком уровне абстракции. Один способ достижения этой цели заключается в работе в терминах проблемы программирования, а не ее компьютерного решения.

Высокоуровневый код не должен включать подробных сведений о файлах, стеках, очередях, массивах, символах и подобных объектах, имеющих имена вроде
i,j и k. Высокоуровневый код должен описывать решаемую проблему. Он должен
быть наполнен описательными именами классов и вызовами методов, ясно характеризующими выполняемые действия, а не подробными сведениями о том, что файл
открывается в режиме «только для чтения». Высокоуровневый код не должен быть
загроможден комментариями, гласящими, что «здесь переменная i представляет
индекс записи из файла о сотрудниках, а чуть позже она используется для индексации файла счетов клиентов».

Это неуклюжая методика программирования. На самом высоком уровне программы
не нужно знать, что данные о сотрудниках представлены в виде записей или хранятся в файле. Информацию, относящуюся к этому уровню детальности, надо скрыть. На самом высоком уровне вы не должны иметь понятия о том, как хранятся данные. Вы не должны читать комментарии, объясняющие роль переменной / и то, что она используется с двойной целью. Вместо этого вы должны видеть две переменные с выразительными именами, такими как employeelndex и clientlndex.

Разделение программы на уровни абстракции


Очевидно, что на некотором уровне надо работать и в терминах реализации, но
вы можете изолировать эти части программы от частей, разработанных в терминах проблемной области. Проектируя программу, обдумайте уровни абстракции:
  • возможности операционной системы и машинные команды;
  • структуры и средства языка программирования;
  • низкоуровневые структуры реализации;
  • низкоуровневые элементы проблемной области;
  • высокоуровневые элементы проблемной области.

Опасайтесь падающих камней


Чем бы программирование ни было — искусством, ремеслом
или инженерной дисциплиной, создание работающей программы требует изрядной
доли рассудительности. А для этого нужно обращать внимание на широкий диапазон предупреждающих знаков — тонких намеков на проблемы в вашей программе. Предупреждающие знаки в программировании указывают на возможные проблемы, но обычно они не настолько очевидны, как дорожный знак, предупреждающий о камнепадах.

Если вы хотите воспользоваться всеми преимуществами предупреждающих знаков, программируйте так, чтобы создать собственные предупреждения. Это полезно потому, что, даже если вам известны предупреждающие знаки, их на удивление легко упустить из виду.

Итерируйте, итерируйте и итерируйте


Итерация полезна на многих этапах разработки ПО. При разработке первоначальной спецификации системы вы составляете с заказчиком несколько версий требований, пока не достигнете согласия. Это итеративный процесс. Гибкий процесс разработки, предусматривающий создание и поставку системы по частям, тоже итеративен. Прототипирование, имеющее целью быструю и дешевую разработку предварительных вариантов решений, — еще одна форма итерации. Итеративная выработка требований, наверное, не менее важна, чем любой другой аспект процесса разработки ПО. Проекты завершаются неудачей потому, что разработчики приступают к решению проблемы, не изучив альтернативных вариантов. Итерация позволяет лучше узнать систему перед ее созданием.

Оценки сроков при первоначальном планировании проекта могут сильно различаться в зависимости от используемой методики оценки. Итеративный подход дает более точную оценку, чем единственная методика.

Проектирование ПО — процесс эвристический и, как все эвристические процессы, допускает итеративные ревизии и улучшения. Правильность ПО обычно проверяется, а не доказывается, а значит, оно тестируется и разрабатывается итеративно,
пока на все вопросы не будут получены правильные ответы. И высокоуровневые, и
низкоуровневые попытки проектирования следует повторять. Первая попытка может привести к работоспособному решению, но едва ли оно окажется наилучшим.
Неоднократное применение разных подходов позволяет узнать о проблеме много
такого, что ускользает при использовании единственного подхода.

Весь процесс разработки охвачен обзорами, что встраивает итерацию в любой
этап, на котором они проводятся. Цель обзора — проверка качества работы, выполненной на данный момент. Если система не проходит обзора, она возвращается на переработку. Если обзор проходит успешно, дальнейшая итерация не нужна.

Говорят, инженерное дело — это умение сделать за 10 центов то, что любой может сделать за доллар. Итерация на более поздних этапах — это трата двух долларов на то, что любой может сделать за один. Фред Брукс советует «планировать выбросить один вариант программы, потому что это придется сделать в любом случае». Хитрость разработки ПО в том, чтобы создавать выбрасываемые части как можно быстрее и дешевле — это и есть суть итерации на ранних этапах разработки.

Стив Макконнелл
Tags:
Hubs:
+24
Comments 32
Comments Comments 32

Articles