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

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

Я обнаружил, что я объясняю клиенту сложные селекторы, как будто они состоят из предмета – вещи, в которой мы фактически заинтересованы – и его условий. Например:

div.sidebar .login-box input.btn span {
}

В этом сложном селекторе предметом является span, а его условиями — IF (внутри .btn) AND IF (в input) AND IF (внутри .login-box) AND IF (внутри .sidebar) AND IF (в div).

@if exists(span) {

  @if is-inside(.btn) {

    @if is-on(input) {

      @if is-inside(.login-box) {

        @if is-inside(.sidebar) {

          @if is-on(div) {

            # Do this.
          }
        }
      }
    }
  }
}


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

@if exists(.btn-text) {
  # Do this.
}

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

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


В программировании цикломатическая сложность – это показатель, который относится к количеству «движущихся частей» в коде. Эти движущиеся части обычно являются точками в определенном потоке управления (if, else, while, и пр.), и чем больше из них мы найдем, тем больше будет наша цикломатическая сложность. На самом деле нам нужно, чтобы цикломатическая сложность была как можно меньше, так как большая сложность означает, кроме прочего, что:

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

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

Поэтому, вместо того, чтобы привязываться к span внутри .btn (и так далее), нам лучше создать новый класс .btn-text, к которому мы и будем привязываться. Это более прямой способ, а также более лаконичный и рациональный (большое количество @if приводит к созданию хрупких селекторов, которые с большей вероятностью могут выйти из строя).

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

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

Цикломатическая сложность – это довольно интересный принцип, который можно использовать в CSS, но если мы смотрим на это только как на принцип, мы сможем начать визуализировать и даже измерять сложность в «логике» и, основываясь на этом, начать принимать лучшие решения.

Несколько правил:
• Относитесь к селекторам как к мини-программам: каждый раз, когда вы что-то вводите или определяете, вы добавляете один оператор if; проговаривайте вслух все эти if, чтобы сохранить селекторы простыми.
• Старайтесь сохранить минимальную цикломатическую сложность: используйте инструмент вроде Parker, чтобы следить за показателями ваших селекторов с точки зрения цикломатической сложности.
• Сведите использование вложенных селекторов к минимуму: иногда вложение в CSS необходимо, но в большинстве случаев — нет. Отличная статья на эту тему.
• Начните рассматривать селекторы справа налево: начните с элемента, в необходимости которого вы уверены, а потом напишите минимум дополнительного CSS, чтобы добиться правильного соответствия.
• Доработайте назначение селектора: убедитесь, что вы пишете селекторы, которые вы хотите, а не только те, которые оказались рабочими.

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

Комментарии (4)


  1. js605451
    02.05.2015 09:03

    На протяжении многих лет мы утверждали, что в CSS нет логики.

    В CSS нет логики в том смысле, что «дизайн CSS не очень логичный».

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

    Википедия учит нас:
    В императивном программировании порядок выполнения (порядок исполнения, порядок вычислений) — это способ упорядочения инструкций программы в процессе ее выполнения.

    Очевидно что CSS — это декларативное, а не императивное программирование.


  1. monolithed
    02.05.2015 17:49
    +1

    Зачем вы спамите?



  1. coll3ctor
    04.05.2015 09:06
    +1

    deleted