Все, что вам нужно знать о чистом коде

внешний интерфейс спецификация кода
Все, что вам нужно знать о чистом коде

Программы пишутся для чтения людьми и лишь изредка выполняются компьютером. — Дональд Эрвин Кнут

последовательность

Каждый раз, когда я просматриваю код, написанный в прошлом, всегда возникает ощущение, что я не могу смотреть прямо. Я хочу улучшить свои навыки кодирования, поэтому я прочитал несколько связанных книг и сообщений в блогах, и у меня есть некоторые идеи.Теперь я разберусь с некоторыми заметками о прочитанном и личным опытом. Бросив нефрит, я надеюсь, что этот кирпич можно будет подбросить.

контур

  • код с плохим запахом
  • Цикломатическая сложность
  • рефакторинг
  • чистый код
  • Принципы кодирования и шаблоны проектирования
  • Суммировать
  • Ссылаться на

код с плохим запахом

Прежде чем вы начнете читать, вы можете быстро подумать о том, какой «образ» хорошего кода и плохого кода у всех в голове?

Если вы видите этот код, как его оценить?

if (a && d || b && c && !d || (!a || !b) && c) {
  // ...
} else {
  // ...
}

Вышеприведенный код, хотя и написан специально для примера, если вы действительно сталкиваетесь с таким кодом, каждый должен быть «неописуем». У каждого есть более или менее «впечатления» от дурно пахнущего кода, а дурно пахнущий код всегда имеет некоторые общие черты:

  • Дублированный код
  • Длинный метод
  • Большой класс
  • Длинный список параметров
  • Временное поле (сбивающее с толку временное поле)
  • Хирургия дробовика: одно изменение приводит к соответствующему изменению нескольких классов.
  • ......

Как появляется плохо пахнущий код?

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

Получив общее представление о плохо пахнущем коде, у читателя может возникнуть вопрос: существует ли какой-либо количественный стандарт для оценки качества кода? Ответ положительный.

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

Цикломатическая сложность

Цикломатическая сложность (сокращенно CC), также известная как условная сложность, является мерой сложности кода. Предложен Томасом Дж. Маккейбом-старшим в 1976 году для выражения сложности программы.

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

Мера, чтобы судить

Цикломатическую сложность можно рассчитать по графу потока управления программой по формуле:

V(G) = e + 2 - n

  • e : количество ребер в графе потока управления
  • n : количество узлов в графе потока управления

Существует простой метод расчета: цикломатическая сложность фактически равна количеству узлов решения плюс 1.

Примечание:if else,switch case,for循环,三元运算符,||,&&И т.д. все принадлежат к узлу решений.

Метрики

Сложность кода низкая, код не обязательно хороший, но сложность кода высокая, код должен быть плохим.

Цикломатическая сложность статус кода Тестируемость стоимость технического обслуживания
1 - 10 ясно и структурировано высоко Низкий
10 - 20 сложный середина середина
20 - 30 очень сложно Низкий высоко
>30 нечитаемый Непредсказуемый очень высоко

Метод определения цикломатической сложности

Правила ESLint

ESLint предоставляет правила для определения цикломатической сложности кода. Включите правило сложности в правилах и установите серьезность правила на предупреждение или ошибку для кода с цикломатической сложностью больше 0.

rules: {
    complexity: [
        'warn',
        { max: 0 }
    ]
}

CLIEngine

С помощью ESLint's CLIEngine сканируйте код локально с помощью настраиваемых правил ESLint и получайте результат сканирования.

Уменьшить цикломатическую сложность кода

Во многих случаях уменьшение цикломатической сложности может улучшить читаемость кода. Для цикломатической сложности даны некоторые предложения по улучшению с примерами:

1. Абстрактная конфигурация

Упростите сложные логические суждения с помощью абстрактной конфигурации.

before:

// ...
if (type === '扫描') {
    scan(args)
} else if (type === '删除') {
    delete(args)
} else if (type === '设置') {
    set(args)
} else {
    // ...
}

after:

const ACTION_TYPE = {
    扫描: scan,
    删除: delete,
    设置: set
}
ACTION_TYPE[type](args)

2. Функция уточнения

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

before:

function example(val) {
    if (val > MAX_VAL) {
        val = MAX_VAL
    }
    for (let i = 0; i < val; i++) {
        doSomething(i)
    }
    // ...
}

after:

function setMaxVal(val) {
    return val > MAX_VAL ? MAX_VAL : val
}

function getCircleArea(val) {
    for (let i = 0; i < val; i++) {
        doSomething(i)
    }
}
function example(val) {
    return getCircleArea(setMaxVal(val))
}

3. Обратное условие упрощает оценку состояния

Некоторые сложные условные суждения могут стать проще после обратного мышления и уменьшить вложенность.

before:

function checkAuth(user){
    if (user.auth) {
        if (user.name === 'admin') {
            // ...
        } else if (user.name === 'root') {
            // ...
        }
    }
}

after:

function checkAuth(user){
    if (!user.auth) return
    if (user.name === 'admin') {
        // ...
    } else if (user.name === 'root') {
        // ...
     }
}

4. Условия слияния упрощают оценку условий

Объедините избыточные условия, прежде чем выносить суждения.

before:

if (fruit === 'apple') {
    return true
} else if (fruit === 'cherry') {
    return true
} else if (fruit === 'peach') {
    return true
} else {
    return true
}

after:

const redFruits = ['apple', 'cherry', 'peach']
if (redFruits.includes(fruit) {
    return true
}

5. Условия извлечения упрощают оценку состояния

Выделите и семантически сложные и трудные условия.

before:

if ((age < 20 && gender === '女') || (age > 60 && gender === '男')) {
    // ...
} else {
    // ...
}

after:

function isYoungGirl(age, gender) {
    return (age < 20 && gender === '女'
}
function isOldMan(age, gender) {
    return age > 60 && gender === '男'
}
if (isYoungGirl(age, gender) || isOldMan(age, gender)) {
    // ...
} else {
    // ...
}

Более полная сводка упрощенных условных выражений будет представлена ​​позже.

рефакторинг

Слово реконструкция имеет понимание как существительного, так и глагола. имя существительное:

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

глагол:

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

Зачем проводить рефакторинг

Если вы столкнулись со следующими ситуациями, вам может потребоваться подумать о том, следует ли проводить рефакторинг:

  • Слишком много повторяющегося кода
  • Структура кода беспорядочна
  • Программа не расширяемая
  • Структура объекта Сильная связь
  • Некоторые модули имеют низкую производительность

Зачем рефакторить, не более чем следующие пункты:

  • Рефакторинг для улучшения дизайна программного обеспечения
  • Рефакторинг для облегчения понимания программного обеспечения
  • Рефакторинг помогает найти ошибки
  • Рефакторинг повышает скорость программирования

Тип рефакторинга:

  • Рефакторинг существующих проектов на уровне кода;
  • Обновите программную архитектуру и систему существующего бизнеса.

В этой статье обсуждается только первый пункт, только рефакторинг на уровне кода.

Время рефакторинга

В первый раз, когда вы делаете что-то, просто делайте это; во второй раз вы делаете что-то подобное, но вы все равно можете это сделать; в третий раз вы делаете что-то подобное, вам следует провести рефакторинг.

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

чистый код

ключевая идея

  • Код должен быть простым для понимания;
  • Код должен быть написан таким образом, чтобы свести к минимуму время, необходимое для его понимания другими.

стиль кода

Ключевые мысли: последовательный стиль важнее, чем «правильный» стиль.

в общем:

  • Используйте последовательный макет
  • Сделайте похожий код похожим
  • Сгруппируйте связанные строки кода в блоки кода

Примечания

Цель аннотации — помочь читателю узнать столько же, сколько и автору. Поэтому аннотация должна иметь высокий信息/空间Показатель.

Комментарии не требуются

  • Не комментировать ради комментария
  • Не аннотируйте плохие имена (должны быть хорошие имена)
  • Не пишите комментарии к фактам, которые можно быстро вывести из самого кода.

нужно писать заметки

  • Внутренние причины того, почему код написан так, а не так (поучительные комментарии)
  • История константы, почему это значение
  • Аннотировать неожиданное поведение для читателей
  • Используйте аннотации «глобального представления» на уровне файла/класса, чтобы объяснить, как все части работают вместе.
  • Используйте комментарии для обобщения блоков кода, чтобы читатели не терялись в деталях.
  • Максимально точно опишите поведение функции.
  • Декларируйте высокоуровневый смысл кода, а не очевидные детали
  • Проиллюстрируйте примерами ввода/вывода в комментариях
  • Дефекты в коде с использованием маркеров
отметка обычное значение
TODO: незаконченное дело
FIXME: известный код, который не работает
HACK: Дешевое решение проблемы, которую необходимо принять

имя

Основная идея: упаковать информацию в имена.

Хорошее именование — это «дешевый» способ сделать код более читабельным.

Выберите профессиональный термин

«Вложение информации в имена» включает в себя выбор очень специальных слов и избегание «пустых» слов.

слово Больше вариантов
send deliver, despatch, announce, distribute, route
find search, extract, locate, recover
start launch, create, begin, open
make create, set up, build, generate, compose, add, new

Избегайте общих имен, таких как tmp и retval.

  • Имя retval не содержит много информации
  • tmp применяется только к переменным, которые существуют в течение короткого периода времени и где темпоральность является основным фактором их существования.

Замените абстрактные имена конкретными именами.

При именовании переменной, функции или другого элемента будьте более конкретными, чем абстрактными.

Прикрепите дополнительную информацию к названию

Если читателю нужно знать что-то важное о переменной, стоит добавить к имени дополнительное «слово».

длина имени

  • Используйте короткие имена в небольших областях
  • Используйте более длинные имена для имен с большей областью действия
  • выбросить бесполезные слова

безошибочное имя

  • Используйте min и max для представления предела
  • Используйте первый и последний для обозначения инклюзивного диапазона
  • Используйте начало и конец, чтобы указать диапазоны исключения
  • Назовите логическое значение: is, has, can, should

Слова с противоположным значением должны стоять парами.

только что противоположный
add remove
create destory
insert delete
get set
increment decrement
show hide
start stop

Другие советы по именованию

  • Квалификаторы расчета в виде префикса или суффикса (Avg, Sum, Total, Min, Max)
  • Имена переменных должны точно отражать смысл вещей
  • Именованное имя функции
  • Сокращения имен переменных, старайтесь избегать необычных сокращений.

Упрощение условных выражений

Разложить условные выражения

Существует сложный условный оператор (if-then-else), который извлекает независимые функции из трех абзацев if, then и else. В соответствии с целью каждого небольшого фрагмента кода назовите новую функцию, полученную в результате декомпозиции, и измените соответствующий код в исходной функции, чтобы вызвать новую функцию, чтобы более четко выразить ее намерение. Для условной логики вы можете выделить условную логику, более четко показать, что делает каждая ветвь, и выделить причину для каждой ветви.

Комбинируйте условные выражения

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

  • Определите эти условные операторы без побочных эффектов;
  • Объедините ряд связанных условных выражений в одно, используя соответствующие логические операторы;
  • Реализуйте функцию уточнения объединенных условных выражений.

Объединить повторяющиеся условные фрагменты

В каждой ветви условного выражения есть один и тот же фрагмент кода, переместите этот повторяющийся код за пределы условного выражения.

Замените вложенные условные выражения охранниками

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

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

Условные выражения часто можно обратить, тем самым заменив вложенные условные выражения на защитные и написав более «линейный» код, чтобы избежать глубокой вложенности.

Переменные и читаемость

Проблемы с переменными:

  • Чем больше переменных, тем сложнее отслеживать их все.
  • Чем больше область действия переменной, тем дольше ее нужно отслеживать.
  • Чем чаще переменная изменяется, тем сложнее отслеживать ее текущее значение.

Встроенные временные переменные

Если есть временная переменная, она присваивается только один раз простым выражением, и все ссылки на переменную заменяются самим выражением, которое ее присваивает.

Замена временных переменных запросами

Сохраните результат выражения во временной переменной и извлеките выражение в отдельную функцию. Замените все ссылки на эту временную переменную вызовами новой функции. После этого новая функция может использоваться другими функциями.

суммарная переменная

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

Ввести объясняющие переменные

Поместите результат сложного выражения (или его часть) во временную переменную, используя имя переменной для объяснения цели выражения.

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

выгода:

  • Разделите огромные выражения на маленькие части
  • Документируйте код, описывая подвыражения с простыми именами.
  • Помогите читателю определить основные понятия в коде

Разложение временных переменных

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

Временные переменные используются по-разному:

  • переменная цикла
  • Переменная сбора результата (через работу всей функции собирается определенное значение композиции)

Если временная переменная имеет несколько функций, ее следует заменить (разложить) на несколько временных переменных, каждая из которых несет только одну функцию.

Замените Magic Number буквальной константой

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

Уменьшить переменные потока управления

let done = false;

while (condition && !done) {
    if (...) {
        done = true;
        continue;
    }
}

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

while (condition) {
    if (...) {
        break;
    }
}

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

реорганизовать функцию

Функция уточнения

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

  • Чем меньше степень детализации функции, тем выше вероятность ее повторного использования;
  • Чем меньше степень детализации функции, тем легче ее переопределить.

Является ли функция слишком длинной, чтобы быть подходящей? Длина не имеет значения, важна семантическая дистанция между именем функции и телом функции.

Отдельные функции запроса и изменения

Функция, которая возвращает значение состояния объекта и изменяет состояние объекта. Создайте две разные функции, одна из которых отвечает за запросы, а другая за модификацию.

Замените аргументы явными функциями

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

объект параметра импорта

Некоторые параметры всегда появляются естественным образом, заменяя эти параметры объектом.

Досрочный возврат из функции

Это можно сделать, обработав «особый случай» сразу и досрочно вернувшись из функции.

разделить огромные заявления

Если у вас есть трудный для чтения код, попробуйте перечислить все задачи, которые он выполняет. Некоторые из этих задач можно легко превратить в отдельные функции (или классы). Другие могут быть просто логическими «абзацами» внутри функции.

Другие предложения и идеи

уменьшить вложенность внутри циклов

В цикле метод, аналогичный раннему возврату,continue. а такжеif...return;Так же, как оператор защиты в функции,if...continue;оператор является защитным оператором внутри цикла. (Примечание: специфика forEach в JavaScript)

Закон де Моргана

Для логического выражения есть два эквивалента:

  • not (a or b or c) <=> (not a) and (not b) and (not c)
  • not (a and b and c) <=> (not a) or (not b) or (not c)

Вы можете использовать эти правила, чтобы сделать логические выражения более читабельными. Например:

// before
if (!(file_exitsts && !is_protected)) Error("sorry, could not read file.")

// after
if (!file_exists || is_protected) Error("sorry, could not read file.")

Код в начале примера можно оптимизировать с помощью соответствующих законов:

// before
if (a && d || b && c && !d || (!a || !b) && c) {
  // ...
} else {
  // ...
}

// after
if (a && d || c) {
  // ...
} else {
  // ...
}

Чтобы узнать о конкретном процессе упрощения и связанных с ним законах, см. этот твит:Вы пишете такой код, вы не боитесь, что ваши коллеги ударят вас?

Реорганизовать код

Инженерия — это разбиение больших проблем на более мелкие и объединение решений этих проблем.

Применение этого принципа к коду делает его более надежным и легким для чтения.

Активное обнаружение и извлечение нерелевантной подлогики означает:

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

превратить идеи в код

Если ты не можешь что-то объяснить своей бабушке, значит, ты действительно этого не понял. --Альберт Эйнштейн

Выполните следующие действия:

  1. Опишите, что делает код на естественном языке, как коллега
  2. Обратите внимание на ключевые слова и фразы, используемые в описании.
  3. Напишите код, соответствующий описанию

Принципы кодирования и шаблоны проектирования

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

ТВЕРДЫЕ принципы

SOLID представляет собой комбинацию аббревиатур пяти основных принципов объектно-ориентированного проектирования (ООП), предложенных Робертом К. Мартином, широко известным как «Дядя Боб», в его книге «Гибкая разработка программного обеспечения: принципы, шаблоны и практика». .

  • S (принцип одной ответственности): единственный принцип ответственности, называемый SRP
  • O (принцип открытия и закрытия): принцип открытия и закрытия, называемый OCP.
  • L (принцип замещения Лисков): принцип замещения Лисков, называемый LSP.
  • I (Interface SegregationPrinciple): принцип разделения интерфейса, называемый ISP.
  • D (принцип инверсии зависимости): принцип инверсии зависимости, сокращенно DIP

Принцип единой ответственности

A class should have only one reason to change.

У класса должна быть одна и только одна причина для его изменения.

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

преимущество:

  • Единая функция и четкие обязанности.
  • Повысьте читаемость и упростите обслуживание.

недостаток:

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

Этот закон также распространяется на принципы кодирования при организации функций.

открытый закрытый принцип

Программные сущности (классы, модули, функции и т. д.) должны быть открыты для расширения, но закрыты для модификации.

Программные сущности (такие как классы, модули, функции и т. д.) должны быть открыты для расширения и закрыты для модификации.

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

const makeSound = function( animal ) { 
    animal.sound(); 
};

const Duck = function(){}; 
Duck.prototype.sound = function(){ 
    console.log( '嘎嘎嘎' ); 
};

const Chicken = function(){}; 
Chicken.prototype.sound = function(){ 
    console.log( '咯咯咯' ); 
}; 

makeSound( new Duck() ); // 嘎嘎嘎
makeSound( new Chicken() ); // 咯咯咯

Принцип замены Лисков

Functions that use pointers to base classes must be able to useobjects of derived classes without knowing it.

Все ссылки на базовый класс должны прозрачно использовать объекты его подклассов.

Подкласс может появиться везде, где может появиться родительский класс (вы можете заменить его подклассом). И наоборот, родительский класс может не появиться там, где может появиться подкласс (подкласс имеет все свойства и поведение родительского класса, но подкласс расширяет больше функций).

Принцип разделения интерфейса

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

Клиент не должен полагаться на интерфейсы, которые ему не нужны. Замените сложные интерфейсы, состоящие из нескольких методов, несколькими детализированными интерфейсами, каждый из которых обслуживает подмодуль.

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

Принцип инверсии зависимости

High level modules should not depend on low level modules; bothshould depend on abstractions.Abstractions should not depend ondetails.Details should depend upon abstractions.

Модули высокого уровня не должны зависеть от модулей низкого уровня, оба должны зависеть от своих абстракций. Абстракции не должны зависеть от деталей, а детали должны зависеть от абстракций.

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

Обязательно ли следовать этим принципам дизайна?

  • Проектирование программного обеспечения — это пошаговый процесс оптимизации
  • Нет необходимости следовать этим принципам проектирования

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

Простые, практические принципы

Принцип LoD (Закон Деметры)

Каждый юнит должен иметь лишь ограниченные знания о других юнитах: только юниты, "близко" связанные с текущим юнитом. Разговаривайте только со своими ближайшими друзьями, не разговаривайте с незнакомцами.

Каждая логическая единица должна иметь наименьшее знание других логических единиц: то есть только близко к текущему объекту. Говорите только с прямыми (близкими) друзьями, а не с незнакомцами.

Этот принцип также известен как Закон Деметры. Проще говоря, чем меньше класс знает о классах, от которых он зависит, тем лучше. Этому классу нужно взаимодействовать только с непосредственным объектом, независимо от внутренней структуры объекта.

Например, есть объект класса B в классе A, объект класса C в классе B, а у вызывающей стороны есть объект a класса A. Если вы хотите получить доступ к свойствам объекта C, не используйте следующие способ написания:

a.getB().getC().getProperties()

Вместо этого должно быть:

a.getProperties()

Принцип KISS (Keep It Simple and Stupid)

Keep It Simple and Stupid.

Сохраняйте простоту и глупость.

  • «Простой» означает, что ваша программа может быть реализована просто и быстро;
  • «Глупый» означает, что ваши проекты должны быть достаточно простыми, чтобы их мог понять любой, то есть простота — это красота!

Принцип DRY (не повторяйтесь)

Принцип DRY (не повторяйтесь)

Не повторяйтесь.

Не дублируйте свой код, то есть сталкивайтесь с одной и той же проблемой несколько раз, абстрагируйте общее решение и не разрабатывайте одну и ту же функциональность повторно. То есть максимально повысить скорость повторного использования кода.

Существует множество способов реализации принципа DRY:

  • Инкапсуляция на уровне функций: инкапсулируйте некоторые часто используемые и повторяющиеся функции в общую функцию.
  • Абстракция на уровне класса: абстрагируйте классы с похожими функциями или поведением, абстрагируйте базовый класс и обратитесь к базовому классу для реализации методов, которые есть у этих классов.
  • Универсальный дизайн: универсальные шаблоны могут использоваться в Java для поддержки нескольких типов данных универсальными функциональными классами; в C++ можно использовать шаблоны классов или определения макросов; в Python можно использовать декораторы для устранения избыточного кода.

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

Принцип YAGNI (он вам не понадобится)

Вам это не понадобится, не внедряйте что-то, пока в этом нет необходимости.

Вам не нужно спешить, не переусердствуйте со своим классом, пока он вам не понадобится.

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

Правило трех

Правило трех называется «правилом трех», что означает, что когда функция появляется в третий раз, она снова будет абстрагироваться, то есть будет не более трех вещей, и три будут реконструированы.

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

Принцип CQS (разделение команд и запросов)

  • Запрос. Когда метод возвращает значение в ответ на вопрос, он имеет характер запроса;
  • Команда (Command): когда метод хочет изменить состояние объекта, он имеет характер команды.

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

Шаблоны проектирования

23 классических шаблона проектирования, предложенных GoF в книге «Шаблоны проектирования: основа многоразового объектно-ориентированного программного обеспечения», автора шаблонов проектирования, разделены на три категории: шаблоны создания, структурные шаблоны и поведенческие шаблоны.

Простое и изящное решение специфических задач при проектировании объектно-ориентированного программного обеспечения.

Обычно используемые шаблоны проектирования: шаблон стратегии, шаблон публикации-подписки, шаблон цепочки ответственности и т. д.

Например, сценарий, используемый шаблоном стратегии:

Шаблон стратегии: определите серию алгоритмов, инкапсулируйте их один за другим и сделайте их взаимозаменяемыми.

if (account === null || account === '') {
    alert('手机号不能为空');
    return false;
}
if (pwd === null || pwd === '') {
    alert('密码不能为空');
    return false;
}
if (!/(^1[3|4|5|7|8][0-9]{9}$)/.test(account)) {
    alert('手机号格式错误');
    return false;
}
if(pwd.length<6){
    alert('密码不能小于六位');
    return false;
}

Используйте режим стратегии:

const strategies = {
    isNonEmpty: function (value, errorMsg) {
        if (value === '' || value === null) {
            return errorMsg;
        }
    },
    isMobile: function (value, errorMsg) { // 手机号码格式
        if (!/(^1[3|4|5|7|8][0-9]{9}$)/.test(value)) {
            return errorMsg;
        }
    },
    minLength: function (value, length, errorMsg) {
        if (value.length < length) {
            return errorMsg;
        }
    }
};

const accountIsMobile = strategies.isMobile(account,'手机号格式错误');
const pwdMinLength = strategies.minLength(pwd,8,'密码不能小于8位');
const errorMsg = accountIsMobile || pwdMinLength; 
if (errorMsg) {
    alert(errorMsg);
    return false;
}

В другом примере модель публикации-подписки имеет следующие характеристики:

  • Развязка во времени
  • Развязка между объектами

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

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

Суммировать

Цинъюань Синси, мастер дзен династии Сун, предложил три сферы дзен-медитации:

В начале медитации горы — это горы, а воды — это воды; когда дзен просветлен, горы — это не горы, а воды — это не воды.

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

Наконец, я надеюсь, что со временем каждый сможет писать код, который больше не будет ненавидеть.

наконец

Это действительно последнее, я добавлю приведенный выше пример кода, когда у меня будет время. Добро пожаловать в Star & PR:Все, что вам нужно знать о чистом коде

Ссылаться на

  • «Чистый код»
  • «Искусство написания читаемого кода»
  • «Рефакторинг — улучшение дизайна существующего кода»
  • Шаблоны проектирования JavaScript и практика разработки
  • «Все знают шаблоны проектирования: понимание шаблонов проектирования из жизни: реализация Python»