Как написать элегантный и надежный код?

JavaScript

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

Во-первых, беглость интерфейса

Хороший интерфейс гладкий и простой для понимания, он в основном отражает следующие аспекты:

  1. Простой

Для управления свойствами CSS элемента используется следующий нативный метод:

document.querySelectorAll('#id').style.color = 'red';

после инкапсуляции

function a(selector, color) {
  document.querySelectorAll(selector)[0].style.color = color
}

a('#a', 'red');

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

  1. удобочитаемость

a(‘#a’, ‘red’)Это хорошая функция, помогающая нам просто и практично изменить элемент, но здесь возникает проблема: если мы используем эту функцию впервые, это может сбить с толку. Никто не говорит ему, что такое функция. При разработке интерфейса надо знать одну вещь.Люди ленивые.От функции назначения цвета хоть и пишется меньше кода,но увеличивает затраты памяти. Каждый раз, когда вы делаете это, вам нужно иметь отношения сопоставления. а—->цвет — неважно, несколько простых, но обычно набор фреймворков имеет десятки, а то и сотни API, и увеличение стоимости маппинга приведет к краху брата программиста. Все, что нам нужно, это сделать интерфейс осмысленным.Давайте перепишем функцию a:

function letSomeElementChangeColor(selector, color) {
  document.querySelectorAll(selector, color);
}

letSomeElementChangeColor получает лингвистическое значение относительно a, любой знает, что это значит

  1. Уменьшить стоимость памяти

Функция, которую мы только что сделали, тоже похожа на эту.Она слишком длинная.Хотя letSomeElementChangeColor снижает стоимость отображения, но увеличивает затраты памяти. Вы знаете, включая Сюэба, никто не любит, когда его называют словами. API, который нативно получает dom, также имеет эту проблему: document.getElementsByClassName; Сделано в ущерб простоте. Итак, мы снова переписываем предыдущую функцию

function setColor(selector, color) {
  // ...
}

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

  1. Расширяемый

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

document.getElementById('id').style.color = 'red';

document.getElementById('id').style.fontSize = '12px';

document.getElementById('id').style.backgourdColor = 'pink';

Используя наш предыдущий метод, мы снова инкапсулируем две функции setFontSize, setbackgroundColor; и затем выполняем их setColor('id', 'red'); setFontSiez('id', '12px'); setbackgroundColor('id', 'pink') ; Очевидно, что такой подход не ленивый, элемент id нужно каждый раз заново получать, что влияет на производительность и дает сбой, каждый раз нужно добавлять новые методы и каждый раз не вызывать эти методы, или сбой. Давайте перепишем его в функцию, которая может быть расширена.Сначала мы инкапсулируем метод id в объект, а затем возвращаем объект в каждом методе объекта:

function getElement(selector) {
  this.style = document.querySelecotrAll(selector).style;
}

getElement.prototype.color = function(color) {
  this.style.color = color;
  return this;
}

getElement.prototype.background = function(bg) {
  this.style.backgroundColor = color;
  return this;
}

getElement.prototype.fontSize = function(size) {
  this.style.fontSize = size;
  return this;
}

//调用

var el = new getElement('#id')
el.color('red').background('pink').fontSize('12px');

Просто, плавно и легко читается.О том, как продолжить оптимизацию параметров, мы поговорим позже. Поэтому все предпочитают использовать API jquery.Хотя символ $ не представляет никакого практического значения, простые символы полезны для нашего использования. Он воплощает в себе многие из вышеперечисленных принципов, прост, удобен для чтения, легко запоминается, цепная запись и многопараметрическая обработка.

плохой:

document.getElementById('id').style.color = 'red';

document.getElementById('id').style.fontSize = '12px';

document.getElementById('id').style.backgourdColor = 'pink';

ожидать:

$('id').css({color:'red', fontSize:'12px', backgroundColor:'pink'})

2. Консистенция

  1. согласованность интерфейса

Связанные интерфейсы поддерживают единый стиль, а полный набор API-интерфейсов значительно снизит способность разработчиков адаптироваться к новым инструментам, если они создают ощущение знакомости и комфорта. Назовите эту вещь: будьте кратки, будьте информативны и, самое главное, будьте последовательны «В компьютерных науках есть только две головные боли: недействительность кеша и проблемы с именами» — Фил Карлтон. Выберите формулировку, которая вам нравится, а затем используйте постоянно. Выберите стиль и придерживайтесь его.

плохой:

setColor,

letBackGround

changefontSize

makedisplay

ожидать:

setColor;

setBackground;

setFontSize

set.........

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

3. Баланс

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

Сбалансированный API чувствует, что его компоненты принадлежат друг другу, и они ведут себя одинаково или дополняют друг друга для достижения цели. API также могут чувствовать себя сбалансированными по расширению, они позволяют разработчикам легко предсказывать другие API и использовать их. Как и тесты свойств Modernizr, они сбалансированы по двум параметрам: а) имена свойств соответствуют терминам HTML5 и CSS и именам API, и б) каждый тест свойств одинаково возвращает значения true или false.

  Modernizr.geolocation
  Modernizr.localstorage
  Modernizr.webworkers
  Modernizr.canvas
  Modernizr.borderradius
  Modernizr.boxshadow
  Modernizr.flexbox

Доступ к одному свойству сообщает разработчикам, какие связанные свойства им нужно знать, чтобы получить через него доступ к любому другому свойству Сила высококачественного API заключается в его простоте. Баланс также гарантирует, что код, который я пишу для взаимодействия с Modernizr, имеет одинаковый визуальный вес при каждом чтении и записи. Как выглядеть и чувствовать себя одинаково, когда я использую и получаю доступ к API, независимо от моих соглашений. С другой стороны, если Modernizr добавит API, который заполняет Canvas, новый API повлияет не только на визуальный вес библиотеки, масштаб и полезность Modernizr значительно расширится, а моя предсказуемость при взаимодействии с API повысится. также страдает ограничение.

Еще один способ найти баланс — получить предсказуемые результаты, полагаясь на знакомство разработчика с концепциями. Типичным примером является синтаксис селекторов jQuery, который сопоставляет селекторы CSS1-3 с собственным механизмом селекторов DOM:

  $("#grid") // Selects by ID
  $("ul.nav > li") // All LIs for the UL with class "nav"
  $("ul li:nth-child(2)") // Second item in each list

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

В-четвертых, обработка параметров

  1. тип параметра

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

//我们规定,color接受字符串类型
function setColor(color) {
  if(typeof color !== 'string') return;
  // ..dosomething
}
  1. Используйте метод json для передачи параметров

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

function fn(param1, param2...............paramN)

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

function fn(json) {
//为必须的参数设置默认值
  var default = extend({
    param: 'default',
    param1: 'default'
    // ...
  }, json)
}

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

5. Масштабируемость

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

Необходимо одновременно изменить шрифт и фон элемента

плохой:

function set(selector, color) {
  document.querySelectroAll(selector).style.color = color;
  document.querySelectroAll(selector).style.backgroundColor = color;
}

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

ожидать:

function set(selector, color) {
  var el = document.querySelectroAll(selector);
  el.style.color = color;
  el.style.backgroundColor = color;
  return el;
}

Необходимо установить шрифт, цвет фона и размер

function setAgain (selector, color, px) {
  var el = set(selector, color)
  el.style.fontSize = px;
  return el;
}

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

  1. использование этого

Расширяемость также включает в себя гибкое использование this и методов вызова и применения:

function sayBonjour() {
  alert(this.a)
}

obj.a = 1;
obj.say = sayBonjour;
obj.say();//1

//or
sayBonjour.call||apply(obj); //1

6. Обработка ошибок

  1. Предвидеть ошибки

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

  1. бросить ошибку

Большинство разработчиков не хотят ошибиться и должны найти соответствующий код самостоятельно, лучший способ — вывести его прямо в консоль, чтобы сообщить пользователю, что произошло. Мы можем использовать выходной API браузера: console.log/warn/error. Вы также можете сохранить некоторые серверные части для своих собственных программ: try...catch.

function error (a) {
  if(typeof a !== 'string') {
    console.error('param a must be type of string')
  }
}

function error() {
  try {
    // some code excucete here maybe throw wrong
  }catch(ex) {
    console.wran(ex);
  }
}

7. Предсказуемость

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

плохой:

function set(selector, color) {
  document.getElementById(selector).style.color = color;
}

ожидать:

zepto.init = function(selector, context) {
  var dom
  // If nothing given, return an empty Zepto collection
  if (!selector) return zepto.Z()
  // Optimize for string selectors
  else if (typeof selector == 'string') {
    selector = selector.trim()
    // If it's a html fragment, create nodes from it
    // Note: In both Chrome 21 and Firefox 15, DOM error 12
    // is thrown if the fragment doesn't begin with <
    if (selector[0] == '<' && fragmentRE.test(selector))
      dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    // If there's a context, create a collection on that context first, and select
    // nodes from there
    else if (context !== undefined) return $(context).find(selector)
    // If it's a CSS selector, use it to select nodes.
    else dom = zepto.qsa(document, selector)
  }
  // If a function is given, call it when the DOM is ready
  else if (isFunction(selector)) return $(document).ready(selector)
  // If a Zepto collection is given, just return it
  else if (zepto.isZ(selector)) return selector
  else {
    // normalize array if an array of nodes is given
    if (isArray(selector)) dom = compact(selector)
    // Wrap DOM nodes.
    else if (isObject(selector))
      dom = [selector], selector = null
    // If it's a html fragment, create nodes from it
    else if (fragmentRE.test(selector))
      dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    // If there's a context, create a collection on that context first, and select
    // nodes from there
    else if (context !== undefined) return $(context).find(selector)
    // And last but no least, if it's a CSS selector, use it to select nodes.
    else dom = zepto.qsa(document, selector)
  }
  // create a new Zepto collection from the nodes found
  return zepto.Z(dom, selector)
}

Выше приведен исходный код zepto, видно, что автор проделал большую обработку в ожидании входящих параметров. По сути, предсказуемость заключается в том, чтобы предоставить ряд записей для программы, не более чем какие-то логические суждения. Zepto использует здесь множество правильных и неправильных суждений, и в то же время приводит к многословию кода, не пригодному для чтения. Короче говоря, предсказуемость действительно требует от вас написания большего количества параметров для объектов местоположения. Измените внешнее обнаружение на внутреннее обнаружение. Да, те, кто им пользуется, довольны и довольны. На! Самое главное в том, чтобы быть мужчиной, это Хайзен.

8. Читабельность комментариев и документации

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

//注释接口,为了演示PPT用

function commentary() {
  //如果你定义一个没有字面意义的变量时,最好为它写上注释:a:没用的变量,可以删除
  var a;

  //在关键和有歧义的地方写上注释,犹如画龙点睛:路由到hash界面后将所有的数据清空结束函数
  return go.Navigate('hash', function(){
    data.clear();
  });
}

Ссылка на статью:продать барбекю

наконец

  1. Для получения дополнительной информации, пожалуйста, следуйтеМой GitHub
  2. Оригинальность не так проста, пожалуйста, лайкните.
  3. Добро пожаловать, чтобы обратить внимание на общедоступную учетную запись «Продвинутый курс по интерфейсу», чтобы серьезно изучить интерфейс и продвигаться вместе.