лекции. Лекции по дисциплине _Разработка программных модулей_. Лекции на специальности спо базовой подготовки 09. 02. 07 Информационные системы и программирование 2 Содержание
Скачать 0.77 Mb.
|
Тема 9 Конструирование ПО Рефакторинг. Определение, причины и цели. Приемы рефакторинга Рефакторинг — это контролируемый процесс улучшения кода, без написания новой функциональности. Результат рефакторинга — это чистый код и простой дизайн. 46 Грязный код является не только результатом лени и невежества, но и побочным продуктом частых изменений в процессе разработки. Чистый код — это код, который просто читать, понимать и поддерживать. Чистый код улучшает предсказуемость разработки и повышает качество продукта. Приёмы рефакторинга Составление методов Рефакторинги этой группы призваны уменьшить сложность внутри метода, убрать дублирование кода и облегчить последующую работу с ним. Перемещение функций между объектами Рефакторинги этой группы показывают как безопасно перемещать функциональность из одних классов в другие, создавать новые классы, а также скрывать детали реализации из публичного доступа. Организация данных Рефакторинги этой группы призваны облегчить работу с данными, заменив работу с примитивными типами богатыми функциональностью классами. Кроме того, важным моментом является уменьшение связанности между классами, что улучшает переносимость классов и шансы их повторного использования. Упрощение условных выражений Логика условного выполнения имеет тенденцию становиться сложной, поэтому ряд рефакторингов направлен на то, чтобы упростить ее. Упрощение вызовов методов Эти рефакторинги делают вызовы методов проще и яснее для понимания. Это, в свою очередь, упрощает интерфейсы взаимодействия между классами. Решение задач обобщения Обобщение порождает собственную группу рефакторингов, в основном связанных с перемещением функциональности по иерархии наследования классов, создания новых классов и интерфейсов, а также замены наследования делегированием и наоборот. 47 Составление методов. Рефакторинги этой группы призваны уменьшить сложность внутри метода, убрать дублирование кода и облегчить последующую работу с ним. Извлечение метода Проблема: У вас есть фрагмент кода, который можно сгруппировать. Решение: Выделите участок кода в новый метод (или функцию) и вызовите этот метод вместо старого кода. Встраивание метода Проблема: Стоит использовать в том случае, когда тело метода очевиднее самого метода. Решение: Замените вызовы метода его содержимым и удалите сам метод. Извлечение переменной Проблема: У вас есть сложное для понимания выражение. Решение: Поместите результат выражения или его части в отдельные переменные, поясняющие суть выражения. Встраивание переменной Проблема: У вас есть временная переменная, которой присваивается результат простого выражения (и больше ничего). Решение: Замените обращения к переменной этим выражением. Замена переменной вызовом метода Проблема: Вы помещаете результат какого-то выражения в локальную переменную, чтобы использовать её далее в коде. Решение: Выделите все выражение в отдельный метод и возвращайте результат из него. Замените использование вашей переменной вызовом метода. Новый метод может быть использован и в других методах. Расщепление переменной Проблема: У вас есть локальная переменная, которая используется для хранения разных промежуточных значений внутри метода (за исключением переменных циклов). 48 Решение: Используйте разные переменные для разных значений. Каждая переменная должна отвечать только за одну определённую вещь. Удаление присваиваний параметрам Проблема: Параметру метода присваивается какое-то значение. Решение: Вместо параметра воспользуйтесь новой локальной переменной. Замена метода объектом методов Проблема: У вас есть длинный метод, в котором локальные переменные так сильно переплетены, что это делает невозможным применение «извлечения метода». Решение: Преобразуйте метод в отдельный класс так, чтобы локальные переменные стали полями этого класса. После этого можно без труда разделить метод на части. Замена алгоритма Проблема: Вы хотите заменить существующий алгоритм другим? Решение: Замените тело метода, реализующего старый алгоритм, новым алгоритмом. Перемещение функций между объектами Если вы разместили функциональность по классам не самым удачным образом — это еще не повод отчаиваться. Рефакторинги этой группы показывают как безопасно перемещать функциональность из одних классов в другие, создавать новые классы, а также скрывать детали реализации из публичного доступа. Перемещение метода Проблема: Метод используется в другом классе больше, чем в собственном. Решение: Создайте новый метод в классе, который использует его больше других, и перенесите туда код из старого метода. Код оригинального метода превратите в обращение к новому методу в другом классе либо уберите его вообще. Перемещение поля 49 Проблема: Поле используется в другом классе больше, чем в собственном. Решение: Создайте поле в новом классе и перенаправьте к нему всех пользователей старого поля. Извлечение класса Проблема: Один класс работает за двоих. Решение: Создайте новый класс, переместите в него поля и методы, отвечающие за определённую функциональность. Встраивание класса Проблема: Класс почти ничего не делает, ни за что не отвечает, и никакой ответственности для этого класса не планируется. Решение: Переместите все фичи из описанного класса в другой. Сокрытие делегирования Проблема: Клиент получает объект B из поля или метода объекта А. Затем клиент вызывает какой-то метод объекта B. Решение: Создайте новый метод в классе А, который бы делегировал вызов объекту B. Таким образом, клиент перестанет знать о классе В и зависеть от него. Удаление посредника Проблема: Класс имеет слишком много методов, которые просто делегируют работу другим объектам. Решение: Удалите эти методы и заставьте клиента вызывать конечные методы напрямую. Введение внешнего метода Проблема: Служебный класс не содержит метода, который вам нужен, при этом у вас нет возможности добавить метод в этот класс. Решение: Добавьте метод в клиентский класс и передавайте в него объект служебного класса в качестве аргумента. Введение локального расширения Проблема: В служебном классе отсутствуют некоторые методы, которые вам нужны. При этом добавить их в этот класс вы не можете. 50 Решение: Создайте новый класс, который бы содержал эти методы, и сделайте его наследником служебного класса, либо его обёрткой. Организация данных. Рефакторинги этой группы призваны облегчить работу с данными, заменив работу с примитивными типами богатыми функциональностью классами. Кроме того, важным моментом является уменьшение связанности между классами, что улучшает переносимость классов и шансы их повторного использования. Самоинкапсуляция поля Проблема: Вы используете прямой доступ к приватным полями внутри класса. Решение: Создайте геттер и сеттер для поля, и пользуйтесь для доступа к полю только ими. Замена простого поля объектом Проблема: В классе (или группе классов) есть поле простого типа. У этого поля есть своё поведение и связанные данные. Решение: Создайте новый класс, поместите в него старое поле и его поведения, храните объект этого класса в исходном классе. Замена значения ссылкой Проблема: Есть много одинаковых экземпляров одного класса, которые можно заменить одним объектом. Решение: Превратите одинаковые объекты в один объект-ссылку. Замена ссылки значением Проблема: У вас есть объект-ссылка, который слишком маленький и неизменяемый, чтобы оправдать сложности по управлению его жизненным циклом. Решение: Превратите его в объект-значение. Замена поля-массива объектом Проблема: У вас есть массив, в котором хранятся разнотипные данные. 51 Решение: Замените массив объектом, который будет иметь отдельные поля для каждого элемента. Дублирование видимых данных Проблема: Данные предметной области программы хранятся в классах, отвечающих за пользовательский интерфейс (GUI). Решение: Имеет смысл выделить данные предметной области в отдельные классы и, таким образом, обеспечить связь и синхронизацию между классом предметной области и GUI. Замена однонаправленной связи двунаправленной Проблема: У вас есть два класса, которым нужно использовать фичи друг друга, но между ними существует только односторонняя связь. Решение: Добавьте недостающую связь в класс, в котором она отсутствует. Замена двунаправленной связи однонаправленной Проблема: У вас есть двухсторонняя связь между классами, но один из классов больше не использует фичи другого. Решение: Уберите неиспользуемую связь. Замена магического числа символьной константой Проблема: В коде используется число, которое несёт какой-то определённый смысл. Решение: Замените это число константой с человеко-читаемым названием, объясняющим смысл этого числа. Инкапсуляция поля Проблема: У вас есть публичное поле. Решение: Сделайте поле приватным и создайте для него методы доступа. Инкапсуляция коллекции Проблема: Класс содержит поле-коллекцию и простой геттер и сеттер для работы с этой коллекцией. Решение: Сделайте возвращаемое геттером значение доступным только для чтения и создайте методы добавления/удаления элементов этой коллекции. 52 Замена кодирования типа классом Проблема: В классе есть поле, содержащее кодирование типа. Значения этого типа не используются в условных операторах и не влияют на поведение программы. Решение: Создайте новый класс и применяйте его объекты вместо значений закодированного типа. Замена кодирования типа подклассами Проблема: У вас есть закодированный тип, который непосредственно влияет на поведение программы (основываясь на значениях этого поля, в условных операторах выполняется различный код). Решение: Для каждого значения закодированного типа, создайте подклассы. А затем, вынесите соответствующие поведения из исходного класса в эти подклассы. Управляющий код замените полиморфизмом. Замена кодирования типа состоянием/стратегией Проблема: У вас есть закодированный тип, который влияет на поведение, но вы не можете использовать подклассы, чтобы избавиться от него. Решение: Замените кодирование типа объектом-состоянием. При необходимости заменить значение поля с кодированием типа, в него подставляется другой объект-состояние. Замена подкласса полями Проблема: У вас есть подклассы, которые отличаются только методами, возвращающими данные-константы. Решение: Замените методы полями в родительском классе и удалите подклассы. Упрощение условных выражений Логика условного выполнения имеет тенденцию становиться сложной, поэтому ряд рефакторингов направлен на то, чтобы упростить ее. Разбиение условного оператора Проблема: У вас есть сложный условный оператор (if-then/else или switch). 53 Решение: Выделите в отдельные методы все сложные части оператора: условие, then и else. Объединение условных операторов Проблема: У вас есть несколько условных операторов, ведущих к одинаковому результату или действию. Решение: Объедините все условия в одном условном операторе. Объединение дублирующихся фрагментов в условных операторах Проблема: Одинаковый фрагмент кода находится во всех ветках условного оператора. Решение: Вынесите его за рамки оператора. Удаление управляющего флага Проблема: У вас есть булевская переменная, которая играет роль управляющего флага для нескольких булевских выражений. Решение: Используйте break, continue и return вместо этой переменной. Замена вложенных условных операторов граничным оператором Проблема: У вас есть группа вложенных условных операторов, среди которых сложно выделить нормальный ход выполнения кода. Решение: Выделите все проверки специальных или граничных случаев выполнения в отдельные условия и поместите их перед основными проверками. В идеале, вы должны получить «плоский» список условных операторов, идущих один за другим. Замена условного оператора полиморфизмом Проблема: У вас есть условный оператор, который, в зависимости от типа или свойств объекта, выполняет различные действия. Решение: Создайте подклассы, которым соответствуют ветки условного оператора. В них создайте общий метод и переместите в него код из соответствующей ветки условного оператора. Впоследствии замените условный оператор на вызов этого метода. Таким образом, нужная реализация будет выбираться через полиморфизм в зависимости от класса объекта. 54 Введение Null-объекта Проблема: Из-за того, что некоторые методы возвращают null вместо реальных объектов, у вас в коде присутствует множество проверок на null. Решение: Вместо null возвращайте Null-объект, который предоставляет поведение по умолчанию. Введение проверки утверждения Проблема: Корректная работа участка кода предполагает наличие каких-то определённых условий или значений. Решение: Замените эти предположения конкретными проверками. Упрощение вызовов методов. Эти рефакторинги делают вызовы методов проще и яснее для понимания. Это, в свою очередь, упрощает интерфейсы взаимодействия между классами. Переименование метода Проблема: Название метода не раскрывает суть того, что он делает. Решение: Измените название метода. Добавление параметра Проблема: Методу не хватает данных для осуществления каких-то действий. Решение: Создайте новый параметр, чтобы передать эти данные. Удаление параметра Проблема: Параметр не используется в теле метода. Решение: Удалите неиспользуемый параметр. Разделение запроса и модификатора Проблема: У вас есть метод, который возвращает какое-то значение, но при этом в процессе работы он изменяет что-то внутри объекта. Решение: Разделите метод на два разных метода. Один из них пускай возвращает значение, а второй модифицирует объект. Параметризация метода 55 Проблема: Несколько методов выполняют похожие действия, которые отличаются только какими-то внутренними значениями, числами или операциями. Решение: Объедините все эти методы в один с параметром, в который будет передаваться отличающееся значение. Замена параметра набором специализированных методов Проблема: Метод разбит на части, каждая из которых выполняется в зависимости от значения какого-то параметра. Решение: Извлеките отдельные части метода в собственные методы и вызывайте их вместо оригинального метода. Передача всего объекта Проблема: Вы получаете несколько значений из объекта, а затем передаёте их в метод как параметры. Решение: Вместо этого передавайте весь объект. Замена параметра вызовом метода Проблема: Вызываем метод и передаем его результаты как параметры другого метода. При этом значение параметров могли бы быть получены и внутри вызываемого метода. Решение: Вместо передачи значения через параметры метода, попробуйте переместить код получения значения внутрь самого метода. Замена параметров объектом Проблема: В ваших методах встречается повторяющаяся группа параметров. Решение: Замените эти параметры объектом. Удаление сеттера Проблема: Значение поля должно быть установлено только в момент создания и больше никогда не меняться. Решение: Удалите методы, устанавливающие значение этого поля. Сокрытие метода Проблема: Метод не используется другими классами либо используется только внутри своей иерархии классов. 56 Решение: Сделайте метод приватным или защищённым. Замена конструктора фабричным методом Проблема: У вас есть сложный конструктор, делающий нечто большее, чем простая установка значений полей объекта. Решение: Создайте фабричный метод и замените им вызовы конструктора. Замена кода ошибки исключением Проблема: Метод возвращает определенное значение, которое будет сигнализировать об ошибке. Решение: Вместо этого следует выбрасывать исключение. Замена исключения проверкой условия Проблема: Вы выбрасываете исключение там, где можно было бы обойтись простой проверкой условия. Решение: Замените выбрасывание исключения проверкой этого условия. Решение задач обобщения Обобщение порождает собственную группу рефакторингов, в основном связанных с перемещением функциональности по иерархии наследования классов, создания новых классов и интерфейсов, а также замены наследования делегированием и наоборот. Подъём поля Проблема: Два класса имеют одно и то же поле. Решение: Переместите поле в суперкласс, убрав его из подклассов. Подъём метода Проблема: Подклассы имеют методы, которые делают схожую работу. Решение: В этом случае нужно сделать методы идентичными, а затем переместить их в суперкласс. Подъём тела конструктора Проблема: Подклассы имеют конструкторы с преимущественно одинаковым кодом. 57 Решение: Создайте конструктор в суперклассе и вынесите в него общий для подклассов код. Вызывайте конструктор суперкласса в конструкторах подкласса. Спуск метода Проблема: Поведение, реализованное в суперклассе, используется только одним или несколькими подклассами. Решение: Переместите это поведение в подклассы. Спуск поля Проблема: Поле используется только в некоторых подклассах. Решение: Переместите поле в эти подклассы. Извлечение подкласса Проблема: Класс имеет фичи, которые используются только в определённых случаях. Решение: Создайте подкласс и используйте его в этих случаях. Извлечение суперкласса Проблема: У вас есть два класса с общими полями и методами. Решение: Создайте для них общий суперкласс и перенесите туда одинаковые поля и методы. Извлечение интерфейса Проблема: Несколько клиентов пользуются одной и той же частью интерфейса класса. Либо в двух классах часть интерфейса оказалась общей. Решение: Выделите эту общую часть в свой собственный интерфейс. Свёртывание иерархии Проблема: У вас есть некая иерархия классов, в которой подкласс мало чем отличается от суперкласса. Решение: Слейте подкласс и суперкласс воедино. Создание шаблонного метода Проблема: В подклассах реализованы алгоритмы, содержащие похожие шаги и одинаковый порядок выполнения этих шагов. 58 Решение: Вынесите структуру алгоритма и одинаковые шаги в суперкласс, а в подклассах оставьте реализацию отличающихся шагов. Замена наследования делегированием Проблема: У вас есть подкласс, который использует только часть методов суперкласса или не хочет наследовать его данные. Решение: Создайте поле и поместите в него объект суперкласса, делегируйте выполнение методов объекту-суперклассу, уберите наследование. Замена делегирования наследованием Проблема: Класс содержит множество простых делегирующих методов ко всем методам другого класса. Решение: Сделайте класс наследником делегата, после чего делегирующие методы потеряют смысл. Экстремальное программирование Экстремальное программирование или XP, eXtreme Programming — гибкая методология разработки программного обеспечения. Как и у других agile- методологий, у нее есть особенные инструменты, процессы и роли. Автор методики — американский разработчик Кент Бек. В конце 90-х годов он руководил проектом Chrysler Comprehensive Compensation System и там впервые применил практики экстремального программирования. Свой опыт и созданную концепцию он описал в книге Extreme Programming Explained, опубликованной в 1999 году. Цель методики XP — справиться с постоянно меняющимися требованиями к программному продукту и повысить качество разработки. Поэтому XP хорошо подходит для сложных и неопределенных проектов. Методология XP строится вокруг четырех процессов: кодирования, тестирования, дизайна и слушания. Кроме того, экстремальное программирование имеет ценности: простоту, коммуникацию, обратную связь, смелость и уважение. 59 Тестирование. Виды, задачи Качество программного продукта характеризуется набором свойств, определяющих, насколько продукт «хорош» с точки зрения заинтересованных сторон, таких как заказчик продукта, спонсор, конечный пользователь, разработчики и тестировщики продукта, инженеры поддержки, сотрудники отделов маркетинга, обучения и продаж. Каждый из участников может иметь различное представление о продукте и том, насколько он хорош или плох, то есть о том, насколько высоко качество продукта. Таким образом, постановка задачи обеспечения качества продукта выливается в задачу определения заинтересованных лиц, их критериев качества и затем нахождения оптимального решения, удовлетворяющего этим критериям. Тестирование является одним из наиболее устоявшихся способов обеспечения качества разработки программного обеспечения и входит в набор эффективных средств современной системы обеспечения качества программного продукта. С технической точки зрения тестирование заключается в выполнении приложения на некотором множестве исходных данных м сверке получаемых результатов с заранее известными (эталонными) с целью установить соответствие различных свойств и характеристик приложения заказанным свойствам. Отладка(debug, debugging) - процесс поиска, локализации и исправления ошибок в программе. Термин «отладка» в отечественной литературе используется двояко: для обозначения активности по поиску ошибок (собственно тестирование), по нахождению причин их появления и исправлению, или активности по локализации и исправлению ошибок. Тестирование - это процесс выполнения ПО системы или компонента в условиях анализа или записи получаемых результатов с целью проверки (оценки) некоторых свойств тестируемого объекта. Тестирование - это процесс анализа пункта требований к ПО с целью фиксации различий между существующим состоянием ПО и требуемым (что 60 свидетельствует о проявлении ошибки) при экспериментальной проверке соответствующего пункта требований. Тестирование - это контролируемое выполнение программы на конечном множестве тестовых данных и анализ результатов этого выполнения для поиска ошибок. Целью проектирования тестовых вариантов является систематическое обнаружение различных классов ошибок при минимальных затратах времени и стоимости. Тестирование обеспечивает: • Обнаружение ошибок. • Демонстрацию соответствия функций программы ее назначению. • Демонстрацию реализации требований к характеристикам программы. • Отображение надежности как индикатора качества программы. Тестирование не может показать отсутствие дефектов (оно может показывать только присутствие дефектов). Важно помнить это утверждение при проведении тестирования. Тестирование - важная часть любой программы контроля качества, а зачастую и единственная. Это печально, так как разнообразные методики совместной разработки позволяют находить больше ошибок, чем тестирование, и в то же время обходятся более чем вдвое дешевле в расчете на одну обнаруженную ошибку. Каждый из отдельных этапов тестирования (блочное тестирование, тестирование компонентов и интеграционное тестирование) обычно позволяют найти менее 50% ошибок. Комбинация этапов тестирования часто приводит к обнаружению менее 60% ошибок. Модульные тесты. Интеграционные тесты. Компонентное (модульное) тестирование (Component or Unit Testing) – это тестирование программы на уровне отдельно взятых модулей, функций или классов. Цель компонентного тестирования: выявление локализованных в модуле ошибок в реализации алгоритмов, а также определение степени 61 готовности системы к переходу на следующий уровень разработки и тестирования. При компонентном тестировании проводятся unit-тесты. Unit-тесты - тесты, проверяющие корректность работы отдельных модулей программы Интеграционное тестирование проверяет интерфейсы между компонентами, взаимодействие различных частей системы, таких как операционная системы, файловая система, аппаратное обеспечение, и интерфейсы между системами. Интеграционные тесты - тесты, проверяющие корректность взаимодействия отдельных модулей друг с другом. Уровни интеграционного тестирования: Компонентный интеграционный уровень (Component Integration testing) проверяется взаимодействие между компонентами системы после проведения компонентного тестирования. Системный интеграционный уровень (System Integration Testing) - проверяется взаимодействие между разными системами после проведения системного тестирования Подходы к интеграционному тестированию ● Снизу вверх (Bottom Up Integration) Все низкоуровневые модули, процедуры или функции собираются воедино и затем тестируются. После чего собирается следующий уровень модулей для проведения интеграционного тестирования. Данный подход считается полезным, если все или практически все модули, разрабатываемого уровня, готовы. ● Сверху вниз (Top Down Integration) Вначале тестируются все высокоуровневые модули, и постепенно один за другим добавляются низкоуровневые. Все модули более низкого уровня симулируются заглушками с аналогичной функциональностью, затем по мере готовности они заменяются реальными активными компонентами. ● Большой взрыв (“Big Bang” Integration) 62 Все или практически все разработанные модули собираются вместе в виде законченной системы или ее основной части, и затем проводится интеграционное тестирование. Подход “Big Bang” очень хорош для экономии времени. Но в тоже время при таком подходе довольно тяжело локализовывать ошибки. Регрессионное тестирование. Нагрузочное тестирование. Регрессионное тестирование (Regression Testing) - это вид тестирования направленный на проверку изменений, сделанных в приложении или окружающей среде (починка дефекта, слияние кода, миграция на другую операционную систему, базу данных, веб-сервер или сервер приложения), для подтверждения того факта, что существующая ранее функциональность работает как и прежде. Регрессионное тестирование может выполняться на всех уровнях тестирования и включает функциональное, нефункциональное и структурное тестирование. Цель регрессионного тестирования – удостовериться в том, что существующая функциональность не была затронута изменениями в коде. А также, регрессионное тестирование нацелено на обнаружение ошибок, вызванных недавними изменениями в системе. В первую очередь надо проводить регрессионное тестирование: ● функций с высокой степенью риска; ● функций, которые чаще всего используются. Когда эти две категории проверены, можно проверять остальные функции и пути приложения. Нагрузочное тестирование или тестирование производительности - это автоматизированное тестирование, имитирующее работу определенного количества бизнес пользователей на каком-либо общем (разделяемом ими) ресурсе. Основные виды нагрузочного тестирования: 63 Тестирование производительности (Performance testing) Задачей тестирования производительности является определение масштабируемости приложения под нагрузкой, при этом происходит: измерение времени выполнения выбранных операций при определенных интенсивностях выполнения этих операций определение количества пользователей, одновременно работающих с приложением определение границ приемлемой производительности при увеличении нагрузки (при увеличении интенсивности выполнения этих операций) исследование производительности на высоких, предельных, стрессовых нагрузках Стрессовое тестирование (Stress Testing) ое тестирование позволяет проверить насколько приложение и система в целом работоспособны в условиях стресса и также оценить способность системы к регенерации, т.е. к возвращению к нормальному состоянию после прекращения воздействия стресса. Стрессом в данном контексте может быть повышение интенсивности выполнения операций до очень высоких значений или аварийное изменение конфигурации сервера. Также одной из задач при стрессовом тестировании может быть оценка деградации производительности, таким образом цели стрессового тестирования могут пересекаться с целями тестирования производительности. Объемное тестирование (Volume Testing). Задачей объемного тестирования является получение оценки производительности при увеличении объемов данных в базе данных приложения, при этом происходит: измерение времени выполнения выбранных операций при определенных интенсивностях выполнения этих операций определение количества пользователей, одновременно работающих с приложением Тестирование стабильности или надежности (Stability / Reliability Testing). Задачей тестирования стабильности (надежности) является проверка 64 работоспособности приложения при длительном (многочасовом) тестировании со средним уровнем нагрузки. Время выполнения операций может играть в данном виде тестирования второстепенную роль. При этом на первое место выходит отсутствие утечек памяти, перезапусков серверов под нагрузкой и другие аспекты влияющие именно на стабильность работы. Стандарты оформления кода PEP 8 - руководство по написанию кода на Python. Этот документ описывает соглашение о том, как писать код для языка python, включая стандартную библиотеку, входящую в состав python. Используйте 4 пробела на каждый уровень отступа. Пробелы - самый предпочтительный метод отступов. Табуляция должна использоваться только для поддержки кода, написанного с отступами с помощью табуляции. Ограничьте длину строки максимум 79 символами. Предпочтительный способ переноса длинных строк является использование подразумеваемых продолжений строк Python внутри круглых, квадратных и фигурных скобок. Длинные строки могут быть разбиты на несколько строк, обернутые в скобки. Это предпочтительнее использования обратной косой черты для продолжения строки. Отделяйте функции верхнего уровня и определения классов двумя пустыми строками. Определения методов внутри класса разделяются одной пустой строкой. Дополнительные пустые строки возможно использовать для разделения различных групп похожих функций. В стандартной библиотеке, нестандартные кодировки должны использоваться только для целей тестирования, либо когда комментарий или строка документации требует упомянуть имя автора, содержащего не ASCII символы; в остальных случаях использование \x, \u, \U или \N - наиболее предпочтительный способ включить не ASCII символы в строковых литералах. В стандартной библиотеке действует следующее 65 соглашение: все идентификаторы обязаны содержать только ASCII символы, и означать английские слова везде, где это возможно (во многих случаях используются сокращения или неанглийские технические термины). Авторы, чьи имена основаны не на латинском алфавите, должны транслитерировать свои имена в латиницу. Каждый импорт, как правило, должен быть на отдельной строке. Импорты должны быть сгруппированы в следующем порядке: 1. импорты из стандартной библиотеки 2. импорты сторонних библиотек 3. импорты модулей текущего проекта Указывайте спецификации __all__ после импортов. Всегда окружайте эти бинарные операторы одним пробелом с каждой стороны: присваивания (=, +=, -= и другие), сравнения (==, <, >, !=, <>, <=, >=, in, not in, is, is not), логические (and, or, not). Если используются операторы с разными приоритетами, попробуйте добавить пробелы вокруг операторов с самым низким приоритетом. Комментарии должны являться законченными предложениями. Блок комментариев обычно объясняет код (весь, или только некоторую часть), идущий после блока, и должен иметь тот же отступ, что и сам код. Каждая строчка такого блока должна начинаться с символа # и одного пробела после него (если только сам текст комментария не имеет отступа). Абзацы внутри блока комментариев разделяются строкой, состоящей из одного символа #. Имена, которые видны пользователю как часть общественного API должны следовать конвенциям, которые отражают использование, а не реализацию. Модули должны иметь короткие имена, состоящие из маленьких букв. Можно использовать символы подчеркивания, если это улучшает читабельность. То же самое относится и к именам пакетов, однако в именах пакетов не рекомендуется использовать символ подчёркивания. |