
- •1. Предпосылки возникновения методологии структурного программирования. Основные принципы структурного программирования. Теорема Бёма-Якопини.
- •2. Структурное программирование. Проектирование сверху вниз. Модульное программирование. Структурное кодирование
- •4. Функции. Компактность. Правило одной операции. Опасность смешения уровней абстракции
- •5. Функции. Правило понижения. Паттерн «Абстрактная фабрика» и использование оператора switch
- •6. Аргументы функций. Приемлемое количество и качество аргументов. Побочные эффекты в функциях. Примеры
- •7. Комментарии. Основные правила написания хороших комментариев. Комментарии todo.
- •8. Комментарии. Основные признаки плохих комментариев. Примеры.
- •9. Форматирование исходного кода. Цель форматирования. Вертикальное разделение концепций, вертикальное сжатие. Вертикальное расстояние
- •10. Форматирование исходного кода. Цель форматирования. Горизонтальное форматирование. Горизонтальное разделение и сжатие. Отступы
- •11. Объекты и структуры данных. Отличия процедурного и объектно-ориентированного кода. Случаи применения
- •12. Закон Деметры. Опасность построения гибридов объектов и структур данных. Объекты передачи данных и активные записи
- •13. Обработка ошибок. Исключения и коды ошибок. Использование паттерна «Особый случай».
- •14. Использование стороннего программного кода. Учебные тесты как инструмент исследования и анализа граничного кода.
- •15. Проблемы использования стороннего программного кода. Применение паттерна «Адаптер» для организации взаимодействия с недоступным кодом.
- •16. Класс. Размеры класса. Принцип единой ответственности (srp).
- •17. Понятие связности класса. Влияние связности на размер классов.
- •18. Структурирование класса с учетом его изменений. Принципы проектирования классов в ооп.
- •19. Понятие эффективности программы. Выбор между эффективностью и удобочитаемостью. Оптимизирующие компиляторы.
- •20. Методология разработки через тестирование (tdd). Последовательность этапов разработки при использовании методологии tdd. Три закона tdd.
- •21. Тестирование как важный этап процесса разработки по. Чистота тестов. Тесты как средство обеспечения изменений. Правило «одна концепция на тест».
- •22. Экономические аспекты процесса тестирования. Тестирование методами «черного» и «белого» ящика. Невозможность исчерпывающего тестирования.
- •23. Основные принципы тестирования программного обеспечения.
- •24. Понятие отладки. Отличие между отладкой и тестированием. Средства отладки. Защитное программирование
- •25. Понятие отладки. Основные принципы отладки. Принципы локализации ошибок. Принципы устранения ошибок.
- •26. Понятие отладки. Основные подходы к отладке программ. Методы «грубой силы», индуктивная отладка, дедуктивная отладка, обратная трассировка, отладка тестированием.
- •27. Проблема ограниченности вычислительных систем. Возможности преодоления некоторых типов ограничений.
- •28. Понятие правильности программ. Доказательство правильности программ. Правильность программ
- •29. Типы разложения вычислений (сочленение, выбор, повторение).
- •If условие then оператор 1 else оператор 2
- •30. Неоднозначность определения программы. Проблема сравнения программ.
- •32. Понятие рефакторинга. Рефакторинги «Согласование различий», «Миграция данных», «Выделение метода».
- •33. Понятие рефакторинга. Рефакторинги «Встраивание метода», «Выделение интерфейса», «Перемещение метода».
- •Inline method (встраивание метода)
- •34. Понятие рефакторинга. Рефакторинги «Метод в объект», «Добавление параметра», «Параметр метода в параметр конструктора».
30. Неоднозначность определения программы. Проблема сравнения программ.
О СРАВНЕНИИ ПРОГРАММ
Повседневная практика программирования показывает, что если задана проблема, которую нужно решить заданным алгоритмом, то программа для заданной машины определяется далеко не однозначно. При проектировании вычислительного процесса программист должен производить выбор из различных альтернатив. Даже имея правильную программу, он часто будет испытывать побуждение изменить ее; мотивом к этому может служить, например, ощущение, что другая программа оказалась бы более выигрышной с точки зрения требований, связанных с реализацией вычислений при помощи имеющихся ресурсов оборудования.
В связи с этим возникает проблема эквивалентности программ: даются две программы и ставится вопрос, вызывают ли они вычисления, приводящие к одинаковым результатам. После надлежащей формализации (как способа задания программ, так и машины, которая выполняет вычисления, вызываемые этими программами, а также "результатов" вычислений) можно, по-видимому, свести нашу проблему к корректно сформулированной задаче абстрактной математики. Однако я не собираюсь рассматривать эту проблему в такой общей форме. Напротив, вместо того чтобы начинать с двух произвольных заданных программ (например независимо придуманных двумя различными авторами), я интересуюсь различными программами, которые могут считаться изобретениями одного и того же разума; при этом возникает вопрос: как нам задумать (и структурно организовать) такие две различные программы, с тем чтобы облегчить работу по их сравнению.
Я проделал много экспериментов, и могу следующим образом подытожить накопленный мною опыт. Две программы, которые вызывают вычисления, приводящие к одинаковым результатам, эквивалентны именно в этом смысле и заведомо ни в каком другом. Если мы хотим сравнивать программы с целью сравнения соответствующих им вычислений, то основной вывод состоит в следующем. Это невозможно (или бесполезно, непривлекательно, или ужасно трудно, или подберите любой другой отрицательный эпитет), если по-разному организовано следование по двум программам, которые мы пытаемся сравнить. Точнее говоря, сравнивать две программы и вычисления, которые могли бы быть ими вызваны, имеет смысл только тогда, когда удается разложить сопоставляемые вычисления на временную последовательность действий, которые допускают взаимное отображение, причем соответствующие тексты программ могут быть точно так же разложены на инструкции, каждая из которых соответствует одному из таких действий. Это очень сильное ограничение. Сейчас я приведу первый пример.
Исключая побочный эффект логической проверки и предполагая значение "В2" постоянным (т. е. не изменяемым при выполнении как "S1", так и "S2"), мы можем установить эквивалентность следующих двух программ:
if B2 then
begin while B1 do S1 end
else
begin while Bl do S2 end (1)
и
while B1 do
begin if B2 then S1 else S2 end (2)
В первой конструкции следование на первом уровне управляется заголовком выбора, а во второй конструкции — заголовком повторения. Я могу доказать эквивалентность результатов вычислений, однако я не могу считать эти программы эквивалентными при какой- либо другой полезной интерпретации понятия эквивалентности. Я вынужден был прийти к заключению, что "трудно сравнивать" программы (1) и (2). Сначала такой вывод весьма удручал меня. Однако со временем я смирился с тем, что такая несравнимость является реальным фактом; в этом одна из основных причин того, что выбор между (1) и (2) приходится рассматривать как волевое решение, которое должно приниматься с учетом детального изучения вариантов. Именно кажущаяся тривиальность выбора побуждает меня придавать особое значение изучению, которое должно влиять на такой выбор. Это изучение вариантов программ выходит за рамки данного раздела, но я собираюсь вернуться к нему в дальнейшем.