- •И. А. Андрианов, д. В. Кочкин, с. Ю. Ржеуцкая
- •Учебное пособие
- •Оглавление
- •1. Основы языка 8
- •1.2.2 Простые типы данных 13
- •2. Работа с памятью 73
- •3. Основы объектно-ориентированного программирования 87
- •4.Обработка исключений 114
- •5. Шаблонные функции и классы. Библиотека стандартных шаблонов 130
- •6. Паттерны проектирования 159
- •7. Антипаттерны 211
- •9. Методы отладки и оптимизации кода 242
- •1. Основы языка
- •1.1.2 Понятие проекта
- •1.2 Простые типы данных
- •1.2.1 Понятие типа
- •1.2.2 Простые типы данных
- •1.2.3 Внутреннее представление простых типов
- •1.2.4 Ключевое слово typedef. Тип size_t
- •1.3 Константы и переменные
- •1.3.1 Литералы
- •1. Числовые константы:
- •2. Символьные константы:
- •1.3.2 Переменные
- •1.3.3 Описание переменных
- •1.4. Выражения. Преобразование типов
- •1.4.1 Операнды и операции
- •1.4.2 Приоритет операций
- •1.4.3 Преобразование типов
- •1.5 Ветвления и циклы
- •1.5.2 Циклы
- •1.6 Массивы, строки
- •1.6.1 Основные понятия
- •1.6.2 Встроенные массивы
- •1.6.3 Cтроки. Обработка строк с завершающим нулём
- •1.7 Указатели и ссылки. Связь указателей и массивов. Библиотека cstring
- •1.7.1 Понятия указателя и ссылки
- •1.7.2 Связь между массивами и указателями
- •1.7.3 Библиотека cstring
- •1.8 Использование типов vector и string
- •1.8.1 Шаблонный класс vector
- •1.8.2 Класс string
- •1.9 Структуры и объединения. Битовые поля
- •1.10.1 Понятие функции
- •1.10.2 Описание функции и прототип функции
- •1.11 Параметры функции. Способы передачи параметров
- •1.11.1 Параметры функции и глобальные переменные
- •1.11.2 Способы передачи параметров в функцию
- •1.11.3 Передача массивов в функцию
- •1.11.4 Параметры-константы
- •1.11.5 Значения параметров по умолчанию
- •1.12.1 Указатель на функцию
- •1.12.2 Функции с переменным числом параметров
- •1.12.3 Перегрузка функций
- •1.12.4 Встроенные (inline) функции
- •1.13 Рекурсивные функции
- •1.14 Пространства имён
- •1.15 Директивы препроцессора. Макросы
- •2. Работа с памятью
- •2.1 Управление выделением и освобождением памяти
- •2.1.1 Статическое и динамическое выделение памяти
- •2.1.2 Способы динамического выделения и освобождения памяти
- •2.2 Динамические структуры данных
- •2.2.1 Основные понятия
- •2.2.2 Примеры реализации динамических структур на основе указателей
- •3. Основы объектно-ориентированного программирования
- •3.1 Основные понятия ооп
- •3.2.1 Описание класса
- •3.2.2 Область видимости элементов класса. Инкапсуляция
- •3.2.3 Первые примеры
- •3.3. Конструкторы и деструкторы.
- •3.4 Указатель this
- •3.5 Перегрузка операций
- •3.6 Дружественные функции и классы
- •3.7 Статические элементы класса
- •3.8 Наследование и полиморфизм
- •3.8.1. Основные понятия
- •3.8.2 Одиночное наследование
- •3.8.3 Множественное наследование
- •3.8.4 Конструкторы и деструкторы классов-потомков
- •3.9. Полиморфизм при наследовании классов
- •3.9.1 Механизмы раннего и позднего связывания
- •3.9.2 Абстрактные классы
- •4.Обработка исключений
- •4.1 Основные понятия
- •4.2 Перехват исключений
- •4.3 Поиск обработчика исключений. Раскрутка стека.
- •4.4 Повторное возбуждение исключений
- •4.5 "Аппаратные" и "программные" исключения
- •4.6 Стандартные классы исключений
- •4.7 Спецификация исключений, возбуждаемых функцией
- •4.8 Исключения в конструкторах при наследовании
- •4.9. Исключения в деструкторах
- •5. Шаблонные функции и классы. Библиотека стандартных шаблонов
- •5.1 Шаблонные функции
- •5.2 Шаблонные классы
- •5.3 Специализация шаблонов
- •5.4 Шаблонные параметры шаблонов
- •5.5 Разработка шаблонных классов с настраиваемой функциональностью
- •5.6 Использование шаблонов для вычислений на этапе компиляции
- •5.7 Библиотека стандартных шаблонов (stl) – основные понятия
- •5.8 Последовательные контейнеры. Итераторы
- •5.9. Адаптеры контейнеров
- •5.10 Ассоциативные контейнеры
- •5.11 Алгоритмы
- •6. Паттерны проектирования
- •6.1 Порождающие шаблоны
- •6.2 Структурные шаблоны
- •6.3 Шаблоны поведения
- •6.4 Шаблон "фабричный метод" (Factory method)
- •6.5 Шаблон "одиночка" (Singleton)
- •6.6 Шаблон "итератор" (Iterator)
- •6.7 Шаблон "наблюдатель" (Observer)
- •6.8 Шаблон "пул объектов" (Object pool)
- •6.9 Шаблон "команда" (Command)
- •6. 10 Шаблон "посетитель" (Visitor)
- •6.11 Дополнительные задания
- •6.11.1 Шаблон Iterator
- •6.11.2 Шаблон Observer
- •6.11.3 Шаблоны Command и Observer
- •6.11.5 Шаблон Visitor
- •6.11.5 Разработка класса − контейнера
- •6.11.6 Оценка производительности кода
- •7. Антипаттерны
- •7.1 Программирование методом копирования и вставки (Copy-Paste Programming)
- •7.2 Спагетти-код (Spaghetti code)
- •7.3 Магические числа (Magic numbers)
- •7.4 Бездумное комментирование
- •7.5 Жесткое кодирование (Hard code)
- •7.6 Мягкое кодирование (Soft code)
- •7.7 Золотой молоток (Golden hammer)
- •7.8 Слепая вера (Blind faith)
- •7.9 Ненужная сложность (Accidental complexity)
- •7.10 Божественный объект (God Object)
- •7.11 Лодочный якорь (Boat anchor)
- •7.12 Поток лавы (Lava flow)
- •7.13 Изобретение велосипеда (Reinventing the wheel)
- •7.14 Программирование перебором (Programming by permutation)
- •8.1 Выведение типов
- •8.2 Списки инициализации
- •8.3 Улучшение процесса инициализации объектов
- •8.4 Цикл for по коллекции
- •8.5 Лямбда-функции
- •8.6 Константа нулевого указателя nullptr
- •8.7 "Умные" указатели
- •9. Методы отладки и оптимизации кода
- •9.1 Отладка кода
- •9.1.1 Основные этапы отладки
- •9.1.2 Инструменты и приёмы отладки
- •9.2 Оптимизация кода
- •9.2.1 Рекомендации по выполнению оптимизации
- •9.2.2 Методики оптимизации кода
- •Заключение
- •Библиографический список
7. Антипаттерны
Антипаттернами называются плохие решения, которые принимает программист во время написания кода программы. Антипаттерн не является ошибкой в программе, программа компилируется и выполняется корректно, однако, при увеличении объема кода плохие решения (антипаттерны) будут оказывать все большее негативное влияние на качество кода.
Паттерны проектирования предназначены для снижения сложности программы и повышения её гибкости, антипаттерны же, наоборот, повышают сложность кода и препятствуют масштабированию.
В данном разделе приведено несколько антипаттернов с примерами кода и описанием того, как антипаттерны могут становиться проблемами при разработке.
7.1 Программирование методом копирования и вставки (Copy-Paste Programming)
Метод программирования копированием и вставкой знаком каждому программисту. Плюсом данного метода является скорость разработки, когда, вместо принятия решений об организации программного кода, один участок копируется и в него вносятся небольшие изменения.
При написании небольших программ, когда важна скорость разработки, данный метод может быть успешно применен. Однако, в больших программах с длительным жизненным циклом программирование методом копирования и вставки может вызвать следующие проблемы:
1. Затрудняется переиспользование программного кода. При переносе кода в другой проект потребуется найти все места, в которых располагается скопированный код, для того чтобы исключить возникновение ошибок в будущем.
2. Со временем качество кода может снижаться по причине того, что программист будет забывать вносить изменения во все участки скопированного кода. При работе в команде эта проблема только усугубится, так как другие программисты не будут знать, что данный участок кода является копией.
3. Если изначальный вариант кода содержал ошибку, эта ошибка будет скопирована во множество мест программы и для её исправления потребуется внести изменения в каждый участок скопированного кода. Если ошибка будет исправлена только в части копий, это может привести к трудно обнаруживаемым ошибкам.
4. Усложняется процедура инспекции кода (code review), так как объем кода становится больше.
5. При внесении мелких изменений в скопированные участки кода программист может по невнимательности допустить ошибки. Невнимательность в данном случае обусловлена тем, что, применяя метод копирования и вставки, программист изначально нацеливается на повышение скорости написания кода.
Помимо желания ускорить процесс разработки, программирование методом копирования и вставки может быть вызвано недостатком опыта у программиста, вследствие чего он будет использовать готовые примеры кода и модифицировать их под конкретную задачу.
Альтернативой данному антипаттерну является создание переиспользуемого кода, обобщение алгоритмов и выделение их в отдельные модули − процедуры, классы.
7.2 Спагетти-код (Spaghetti code)
Спагетти-кодом называют программный код, который очень сложно анализировать по причине его запутанности. Исторически данный термин связан с оператором goto, его применение в программе приводит к тому, что логика работы становиться запутанной и для анализа небольшой части программы приходится анализировать многие участки, в которые осуществляется безусловный переход.
Отличие оператора goto от вызова подпрограммы заключается в том, что программист не знает ничего о коде, к которому осуществляется переход. При вызове подпрограммы известно её имя и список передаваемых параметров.
Отказ от оператора goto был одним из требований структурного программирования − методологии разработки программ, предложенной Эдсгером Дейкстрой в 1970-х годах.
Исключение оператора goto не является гарантией от спагетти-кода. Сложный для анализа код может быть получен и в объектно-ориентированных программах при написании больших функций, при использовании большого числа разнотипных объектов с минимальным количеством функций в каждом или при активном использовании глобальных переменных.
Причиной появления спагетти-кода в программе может быть отсутствие должного проектирования или незнание программистом методологий разработки, таких как структурное и объектно-ориентированное программирование, а также отсутствие формального инспектирования кода.
Методом борьбы со спагетти кодом является рефакторинг, а также полное или частичное переписывание проблемного участка.
