Написание качественного и поддерживаемого кода: оптимизация логических суждений

JavaScript React.js
Написание качественного и поддерживаемого кода: оптимизация логических суждений

Это 64-я оригинальная статья без воды. Если вы хотите получить больше оригинальных статей, пожалуйста, ищите публичный аккаунт и следуйте за нами ~ Эта статья была впервые опубликована в блоге Front-End Zhengcai Cloud:Написание высококачественного поддерживаемого кода: логическое суждение

предисловие

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

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

Ниже мы поделимся некоторыми методами оптимизации в двух аспектах: синтаксис JavaScript и синтаксис React JSX.

Синтаксис JavaScript

Вложенная иерархическая оптимизация

function supply(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
  // 条件 1: 水果存在
  if (fruit) {
    // 条件 2: 属于红色水果
    if (redFruits.includes(fruit)) {
      console.log('红色水果');
      // 条件 3: 水果数量大于 10 个
      if (quantity > 10) {
        console.log('数量大于 10 个');
      }
    }
  } else {
    throw new Error('没有水果啦!');
  }
}

Анализируя приведенное выше условное суждение, можно выделить три уровня вложенности условия if.

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

function supply(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
  if (!fruit) throw new Error('没有水果啦'); // 条件 1: 当 fruit 无效时,提前处理错误
  if (!redFruits.includes(fruit)) return; // 条件 2: 当不是红色水果时,提前 return
  
  console.log('红色水果');
  
  // 条件 3: 水果数量大于 10 个
  if (quantity > 10) {
    console.log('数量大于 10 个');
  }
}

Оптимизированная обработка нескольких условных ветвей

Когда значение перечисления требуется для обработки другой логики бизнес-ветвей, первой реакцией является запись if else ? Давайте взглянем:

function pick(color) {
  // 根据颜色选择水果
  if(color === 'red') {
      return ['apple', 'strawberry']; 
  } else if (color === 'yellow') {
      return ['banana', 'pineapple'];
  } else if (color === 'purple') {
      return ['grape', 'plum'];
  } else {
      return [];
  }
}

В приведенной выше реализации:

  • слишком много if else ветвей
  • if else больше подходит для оценки условного интервала, тогда как switch case больше подходит для оценки ветвления конкретных значений перечисления

После оптимизации приведенного выше кода с помощью переключателя:

function pick(color) {
  // 根据颜色选择水果
  switch (color) {
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}

Код после оптимизации switch case выглядит аккуратно и понятно, но все равно очень многословно. Продолжайте оптимизировать:

  • С помощью структуры Object {key: value} мы можем перечислить все случаи в Object, а затем использовать ключ в качестве индекса для получения содержимого напрямую через Object.key или Object[key]
const fruitColor = {
  red: ['apple', 'strawberry'],
  yellow: ['banana', 'pineapple'],
  purple: ['grape', 'plum'],
};
function pick(color) {
  return fruitColor[color] || [];
}
  • Используйте структуру данных Map, истинную (ключ, значение) структуру пары ключ-значение;
const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);

function pick(color) {
  return fruitColor.get(color) || [];
}

После оптимизации код становится чище и его легче расширять.

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

const fruits = [
  { name: 'apple', color: 'red' }, 
  { name: 'strawberry', color: 'red' }, 
  { name: 'banana', color: 'yellow' }, 
  { name: 'pineapple', color: 'yellow' }, 
  { name: 'grape', color: 'purple' }, 
  { name: 'plum', color: 'purple' }
];

function pick(color) {
  return fruits.filter(f => f.color === color);
}

Упростите логическое суждение с новыми функциями массивов

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

решение с несколькими условиями

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

function judge(fruit) {
  if (fruit === 'apple' || fruit === 'strawberry' || fruit === 'cherry' || fruit === 'cranberries' ) {
    console.log('red');
  }
}

Но когда в будущем число типов достигнет 10 или более, можем ли мы продолжать добавлять || только для поддержки кода?

пытатьсяArray.includes ~

// 将判断条件抽取成一个数组
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
function judge(fruit) {
  if (redFruits.includes(fruit)) {
      console.log('red');
   }
}

Проверить, удовлетворяют ли все элементы массива определенному условию

const fruits = [
  { name: 'apple', color: 'red' },
  { name: 'banana', color: 'yellow' },
  { name: 'grape', color: 'purple' }
];

function match() {
  let isAllRed = true;

  // 判断条件:所有的水果都必须是红色
  for (let f of fruits) {
    if (!isAllRed) break;
    isAllRed = (f.color === 'red');
  }

  console.log(isAllRed); // false
}

В приведенной выше реализации в основном выполняется обработка, чтобы все элементы в массиве соответствовали условиям.

использоватьArray.everyЭту логику можно легко реализовать:

const fruits = [
  { name: 'apple', color: 'red' },
  { name: 'banana', color: 'yellow' },
  { name: 'grape', color: 'purple' }
];

function match() {
  // 条件:所有水果都必须是红色
  const isAllRed = fruits.every(f => f.color === 'red');

  console.log(isAllRed); // false
}

Проверить, удовлетворяет ли элемент массива условию

Array.some, который в основном касается сценария оценки того, удовлетворяет ли элемент массива условию.

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

const fruits = [
  { name: 'apple', color: 'red' },
  { name: 'banana', color: 'yellow' },
  { name: 'grape', color: 'purple' }
];

// 条件:是否有红色水果 
const isAnyRed = fruits.some(f => f.color == 'red');

Существует много других новых функций массива, таких как Array.find, Array.slice, Array.findIndex, Array.reduce, Array.splice и т. д., которые можно выбирать и использовать в соответствии с реальными потребностями.

значение функции по умолчанию

Использовать параметры по умолчанию

const buyFruit = (fruit,amount) => {
 if(!fruit){
	return
  }
  amount = amount || 1;
  console.log(amount)
}

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

const buyFruit = (fruit,amount = 1) => {
 if(!fruit){
		return
  }
  console.log(amount,'amount')
}

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

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

Результаты теста следующие:

buyFruit('apple','');  // amount
buyFruit('apple',null);  //null amount
buyFruit('apple');  //1 amount

Поэтому в случае использования параметров по умолчанию нам нужно обратить внимание на параметры по умолчанию.amount=1не эквивалентенamount || 1.

Использование деструктуризации с параметрами по умолчанию

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

Before:

const buyFruit = (fruit,amount) => {
  fruit = fruit || {};
  if(!fruit.name || !fruit.price){
      return;
  }
  ...
  amount = amount || 1;
  console.log(amount)
}

After:

const buyFruit = ({ name,price }={},amount) => {
  if(!name || !prices){
  	return;
  }
  console.log(amount)
}

Деконструкция сложных данных

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

const oneComplexObj = {
  firstLevel: {
    secondLevel: [{
      name: '',
      price: '',
    }],
  },
};

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

const {
  firstLevel: {
    secondLevel: [{ name, price }] = [],
  } = {},
} = oneComplexObj;

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

В этом случае, если вы используете библиотеку lodash в своем проекте, вы можете использовать в ней методы lodash/get.

import lodashGet from 'lodash/get';

const { name,price } = lodashGet(oneComplexObj,'firstLevel.secondLevel[0]',{});

Режим стратегии оптимизирует обработку логики перехода

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

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

Before:

const TYPE = {
  JUICE: 'juice',
  SALAD: 'salad',
  JAM: 'jam',
};
function enjoy({ type = TYPE.JUICE, fruits }) {
  if (!fruits || !fruits.length) {
    console.log('请先采购水果!');
    return;
  }
  if (type === TYPE.JUICE) {
    console.log('榨果汁中...');
    return '果汁';
  }
  if (type === TYPE.SALAD) {
    console.log('做沙拉中...');
    return '拉沙';
  }
  if (type === TYPE.JAM) {
    console.log('做果酱中...');
    return '果酱';
  }
}

enjoy({ type: 'juice', fruits });

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

После:

const TYPE = {
  JUICE: 'juice',
  SALAD: 'salad',
  JAM: 'jam',
};

const strategies = {
  [TYPE.JUICE](fruits) {
    console.log('榨果汁中...');
    return '果汁';
  },
  [TYPE.SALAD](fruits) {
    console.log('做沙拉中...');
    return '沙拉';
  },
  [TYPE.JAM](fruits) {
    console.log('做果酱中...');
    return '果酱';
  },
};

function enjoy({ type = TYPE.JUICE, fruits }) {
  if (!type) {
    console.log('请直接享用!');
    return;
  }
  if (!fruits || !fruits.length) {
    console.log('请先采购水果!');
    return;
  }
  return strategies[type](fruits);
}

enjoy({ type: 'juice', fruits });

Глава Framework React JSX Logic Оценка Оптимизация

JSX — это расширение синтаксиса JavaScript, очень похожее на XML. Как правило, JSX используется в React для описания информации об интерфейсе, а ReactDOM.render() отображает информацию об интерфейсе JSX на странице.

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

С таким количеством выражений JavaScript, написанных на JSX, код в целом может выглядеть немного загроможденным. Попробуйте оптимизировать!

JSX-Control-Statements

JSX-Control-StatementsЭто плагин Babel, который расширяет возможности JSX и поддерживает обработку условных суждений и циклов в виде тегов.

Если тег

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

Before:

{ condition() ? 'Hello World!' : null }   

After:

<If condition={ condition() }>Hello World!</If>   

Примечание. Устаревшие сложные условные суждения могут использовать теги.

Выберите ярлык

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

Содержимое метки будет отображаться только тогда, когда условие истинно, что эквивалентно ветви условного суждения if.

Метка эквивалентна последней ветке ELSE.

Before:

{ test1 ? <span>IfBlock1</span> : test2 ? <span>IfBlock2</span> : <span>ElseBlock</span> }

After:

<Choose>
  <When condition={ test1 }>
    <span>IfBlock1</span>
  </When>
  <When condition={ test2 }>
    <span>IfBlock2</span>
  </When>
  <Otherwise>
    <span>ElseBlock</span>
  </Otherwise>
</Choose>

Для этикетки

Метки должны объявлять и каждый атрибут.

of принимает объекты, к которым можно получить доступ с помощью итератора.

каждый представляет текущий указанный элемент при доступе к итератору.

Before:

{
  (this.props.items || []).map(item => {
      return <span key={ item.id }>{ item.title }</span>
  })
}

After:

<For each="item" of={ this.props.items }>
   <span key={ item.id }>{ item.title }</span>
</For>

Примечание. Метки не могут быть корневыми элементами.

С тегом

Метки обеспечивают функцию передачи переменных параметров.

Before:

renderFoo = (foo) => {
    return <span>{ foo }</span>;
}

// JSX 中表达式调用
{
    this.renderFoo(47)
}

After:

<With foo={ 47 }>
  <span>{ foo }</span>
</With>

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

Примечание. Чтобы узнать об использовании конкретного плагина babel-plugin-jsx-control-statements, см. третью справочную статью; платформа Vue уже поддерживает v-if, v-else-if, v-else, v-show, slot, и т.п. в виде инструкции.

Суммировать

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

использованная литература

Рекомендуемое чтение

Научите вас построить личный репозиторий NPM уровня предприятия в минутах

Любимый список обработки исключений Git

Карьера

ZooTeam, молодая, увлеченная и творческая команда, связанная с отделом исследований и разработок продукции Zhengcaiyun, базируется в живописном Ханчжоу. В настоящее время в команде более 50 фронтенд-партнеров, средний возраст которых составляет 27 лет, и почти 30% из них — инженеры с полным стеком, настоящая молодежная штурмовая группа. В состав членов входят «ветераны» солдат из Ali и NetEase, а также первокурсники из Чжэцзянского университета, Университета науки и технологий Китая, Университета Хандянь и других школ. В дополнение к ежедневным деловым связям, команда также проводит технические исследования и фактические боевые действия в области системы материалов, инженерной платформы, строительной платформы, производительности, облачных приложений, анализа и визуализации данных, а также продвигает и внедряет ряд внутренних технологий. Откройте для себя новые горизонты передовых технологических систем.

Если вы хотите измениться, вас забрасывают вещами, и вы надеетесь начать их бросать; если вы хотите измениться, вам сказали, что вам нужно больше идей, но вы не можете сломать игру; если вы хотите изменить , у вас есть возможность добиться этого результата, но вы не нужны; если вы хотите изменить то, чего хотите достичь, вам нужна команда для поддержки, но вам некуда вести людей; если вы хотите изменить установившийся ритм, это будет "5 лет рабочего времени и 3 года стажа работы"; если вы хотите изменить исходный Понимание хорошее, но всегда есть размытие того слоя оконной бумаги.. , Если вы верите в силу веры, верьте, что обычные люди могут достичь необыкновенных вещей, и верьте, что они могут встретить лучшего себя. Если вы хотите участвовать в процессе становления бизнеса и лично способствовать росту фронтенд-команды с глубоким пониманием бизнеса, надежной технической системой, технологиями, создающими ценность, и побочным влиянием, я думаю, что мы должны говорить. В любое время, ожидая, пока вы что-нибудь напишете, отправьте это наZooTeam@cai-inc.com