День триста двадцать четвёртый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
15. Программируйте Осознанно
Попытка обосновать правильность кода вручную приводит к формальному доказательству, которое длиннее кода и с большей вероятностью содержит ошибки. Автоматизированные инструменты предпочтительнее, но не всегда возможны. Далее описано промежуточное решение: полуформальное определение правильности кода.
Основная идея в том, чтобы разделить весь рассматриваемый код на короткие секции - от одной строки, например, вызова функции, до блоков длиной менее 10 строк - и аргументировать их правильность. Аргументы должны быть достаточно убедительными, например, для коллеги-программиста, который будет играть роль вашего оппонента.
Блок должен быть выбран так, чтобы:
1. В каждой конечной точке состояние программы (счетчик программы и состояния всех «живых» объектов) удовлетворяло легко описываемому свойству.
2. Функциональность этого блока (преобразование состояния программы) можно легко описать как одну задачу.
Эти рекомендации упростят процесс обоснования правильности. Эти свойства конечных точек обобщают такие понятия, как пред- и постусловия для функций и инварианты для тел циклов и экземпляров классов. Стремление к тому, чтобы блоки были максимально независимы друг от друга, упрощает обоснование их правильности и необходимо для лёгкого изменения этих блоков.
Многие из хороших практик кодирования, которые хорошо известны (хотя, возможно, не так хорошо соблюдаются), облегчают обоснование правильности. Следовательно, просто попытавшись обосновать правильность своего кода, вы уже начинаете двигаться к хорошему стилю и структуре кода. Неудивительно, что большинство из этих практик могут быть проверены статическими анализаторами кода:
1. Избегайте операторов goto, так как они делают удаленные друг от друга блоки сильно связанными.
2. Избегайте изменяемых глобальных переменных, поскольку они делают все блоки, которые их используют, зависимыми.
3. Каждая переменная должна иметь наименьшую возможную область видимости. Например, локальный объект может быть объявлен непосредственно перед его первым использованием.
4. Делайте объекты неизменяемыми, когда это уместно.
5. Делайте код читаемым, используя отступы (как горизонтальные, так и вертикальные), например, выравнивая связанные структуры и используя пустую строку для разделения блоков.
6. Делайте код самодокументируемым, выбрав описательные (но относительно короткие) имена для объектов, типов, методов и т. д.
7. Если вам нужен вложенный блок, сделайте его методом.
8. Делайте свои функции короткими и сфокусированными на одной задаче. Старый лимит в 24 строки всё ещё актуален. Хотя размер экрана и разрешение изменились с 1960-х годов, способность человека воспринимать информацию осталась той же.
9. Функции должны иметь ограниченное число параметров (четыре - хорошая верхняя граница). Это не ограничивает количество данных, передаваемых функциям: группируйте связанные параметры в единый объект, что упростит понимание их связанности и согласованности.
10. В более общем смысле каждая единица кода, от блока до библиотеки, должна иметь минимальный интерфейс. Чем меньше связей блока с другими блоками, тем меньше требуется обосновывать правильность его работы. Это означает, что аксессоры (get) свойств объекта увеличивают его сложность. Не запрашивайте информацию у объекта для её обработки. Вместо этого попросите объект обработать уже имеющуюся у него информацию. Инкапсуляция – лучшее средство для минимализации интерфейсов.
11. Чтобы сохранить инварианты класса, не рекомендуется использовать мутаторы (set). Они, как правило, допускают нарушение инвариантов, управляющих состоянием объекта.
Помимо доказательства его правильности, в принципе любые обсуждения вашего кода помогут вам лучше его понимать. Обменивайтесь информацией, которую вы получаете, для пользы всех.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Yechiel Kimchi
Post #381
975