Русский
Русский
English
Статистика
Реклама

Стили

Визуальное сравнение 13 CSS-фреймворков

27.07.2020 10:17:57 | Автор: admin


Доброго времени суток, друзья!

Предлагаю Вашему вниманию результаты небольшого исследования визуального сравнения 13 CSS-фреймворков.

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

В исследовании представлены следующие фреймворки:


Использовались следующие версии стилей:



В тестовой разметке представлены основные элементы веб-страницы с акцентом на семантические теги:

<header>    <figure>        <figcaption>logo</figcaption>        <img src="logo.png" alt="logo">    </figure>    <nav>        <a href="#">link1</a>        <a href="#">link2</a>        <a href="#">link3</a>    </nav></header><hr><main>    <h1>main title</h1>    <aside>        <h4>aside title</h4>        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium, quibusdam.</p>    </aside>    <section>        <h2>section title</h2>        <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Odit, illum.</p>        <ul>            <li>item1</li>            <li>item2</li>            <li>item3</li>        </ul>        <table>            <caption>table</caption>            <tr>                <th>1</th>                <th>2</th>                <th>3</th>            </tr>            <tr>                <td>1</td>                <td>2</td>                <td>3</td>            </tr>            <tr>                <td>4</td>                <td>5</td>                <td>6</td>            </tr>        </table>        <dl>            <dt>term</dt>            <dd>Lorem <strong>ipsum</strong>, dolor sit <em>amet</em> consectetur adipisicing elit. <mark>Accusamus</mark>, obcaecati?</dd>        </dl>        <details open>            <summary>summary</summary>            <p><small>Lorem dolor sit amet ipsum, consectetur adipisicing elit. Explicabo, repellat?</small></p>        </details>        <button>button</button>    </section>    <article>        <h3>article title</h3>        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam, architecto?</p>        <blockquote>Lorem ipsum dolor, sit amet <cite>consectetur adipisicing elit.</cite> Ipsam, ad!</blockquote>        <code>            console.log('hello world')        </code>    </article></main><hr><footer>    <form action="#">        <fieldset>            <legend>form</legend>            <label>name:                <input type="text">            </label>            <label>email:                <input type="email">            </label>            <input type="submit" value="subscribe">        </fieldset>    </form>    <p> 2020.</p></footer>

Вот как это выглядит:




Поиграть с кодом можно здесь:



Песочница не позволяет работать с тегом head, поэтому милости прошу на GitHub Pages.

Код проекта находится здесь.

Результаты исследования вполне ожидаемы: первое место Bootstrap, второе Materialize.

Materialize, судя по всему, следует концепции mobile first, из-за чего проигрывает Bootstrap, когда дело касается широких экранов. Также Materialize проигрывает в плане функциональности, но это другая история.

Перспективными мне показались Skeleton и Picnic.

Благодарю за внимание.
Подробнее..

Перевод Доступный toggle

14.05.2021 14:06:19 | Автор: admin

Перевод подготовлен в рамках онлайн-курса"HTML/CSS".

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


Toggles (или их еще называют "тумблеры"/"переключатели") широко используются в современных интерфейсах. Они, как правило, относительно просты, и их можно рассматривать как простые флажки (checkbox). Тем не менее, их часто делают недоступными тем или иным способом.

В этой статье я покажу небольшую имплементацию доступного toggle на HTML + CSS, которую вы можете применить в своих проектах и доработать по своему усмотрению.

  • Разметка

  • Стилизация

  • Контейнер

  • The toggle и дескриптор handle

  • Стили для фокуса

  • Проверенное состояние

  • Отключенное состояние

  • Поддержка право-лево

  • Иконки

  • Вариант кнопки

  • Завершение

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

Разметка

Как всегда, давайте начнем с HTML. В данном случае мы начнем с самых основ, а именно с правильно обозначенного флажка. Это input с <label>, с правильными атрибутами и видимой меткой.

Если toggle вызывает немедленное действие (например, переключение темы) и поэтому зависит от JavaScript, то вместо него следует использовать <button>. Обратитесь к варианту кнопки для получения дополнительной информации о разметке - стили, по сути, одинаковы. Спасибо Adrian Roselli за то, что он обратил наше внимание на это!

<label class="Toggle" for="toggle">  <input type="checkbox" name="toggle" id="toggle" class="Toggle__input" />  This is the label</label>

Стоит отметить, что это не единственный способ разметки такого компонента интерфейса. Например, вместо него можно использовать 2 radio inputs. Sara Soueidan более подробно рассказывает о проектировании и создании toggle.

Теперь нам понадобится немного больше. Чтобы не передавать статус флажка, полагаясь только на цвет (Критерий успеха WCAG 1.4.1 "Использование цвета"), мы собираемся использовать пару иконок.

Мы будем использовать небольшой контейнер между вводом данных и текстовой меткой, который будет содержать 2 иконки: галочку и крестик (взяты из иконок Material UI). Затем мы создадим toggle handle с псевдоэлементом, который будет охватывать одну из иконок за раз.

<label class="Toggle" for="toggle">  <input type="checkbox" name="toggle" id="toggle" class="Toggle__input" />  <span class="Toggle__display" hidden>    <svg      aria-hidden="true"      focusable="false"      class="Toggle__icon Toggle__icon--checkmark"      width="18"      height="14"      viewBox="0 0 18 14"      fill="none"      xmlns="http://personeltest.ru/away/www.w3.org/2000/svg"    >      <path        d="M6.08471 10.6237L2.29164 6.83059L1 8.11313L6.08471 13.1978L17 2.28255L15.7175 1L6.08471 10.6237Z"        fill="currentcolor"        stroke="currentcolor"      />    </svg>    <svg      aria-hidden="true"      focusable="false"      class="Toggle__icon Toggle__icon--cross"      width="13"      height="13"      viewBox="0 0 13 13"      fill="none"      xmlns="http://personeltest.ru/away/www.w3.org/2000/svg"    >      <path        d="M11.167 0L6.5 4.667L1.833 0L0 1.833L4.667 6.5L0 11.167L1.833 13L6.5 8.333L11.167 13L13 11.167L8.333 6.5L13 1.833L11.167 0Z"        fill="currentcolor"      />    </svg>  </span>  This is the label</label>

Следует отметить несколько моментов, связанных с нашей разметкой:

  • Мы используем aria-hidden="true" для наших SVG, потому что они не должны обнаруживаться вспомогательными технологиями, так как являются сугубо декоративными.

  • Мы также используем focusable="false" для наших SVG, чтобы избежать проблем с Internet Explorer, где SVG по умолчанию фокусируются.

  • Мы используем hidden для контейнера .Toggle__display , чтобы скрыть его, когда CSS недоступен, поскольку он должен вернуться к базовому флажку. Его значение отображения будет переопределено в CSS.

Стили

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

  • Контейнер - это обертка <label>, которая содержит как toggle, так и текстовую метку (.Toggle).

  • Toggle - это визуальный тумблер, зеленый или красный в зависимости от статуса, с 2 иконками (.Toggle__display).

  • Handle - это круглый диск, охватывающий одну из иконок и перемещающийся влево и вправо при взаимодействии с toggle (.Toggle__display::before).

  • Input - Вход - это HTML <input>, который визуально скрыт, но остается доступным и фокусируемым (.Toggle__input).

Контейнер

Давайте начнем с базовых стилей для нашего контейнера.

/** * 1. Vertically center the toggle and the label. `flex` could be used if a  *    block-level display is preferred. * 2. Make sure the toggle remains clean and functional even if the label is *    too wide to fit on one line. Thanks @jouni_kantola for the heads up! * 3. Grant a position context for the visually hidden and absolutely *    positioned input. * 4. Provide spacing between the toggle and the text regardless of layout *    direction. If browser support is considered insufficient, use *    a right margin on `.Toggle__display` in LTR, and left margin in RTL. *    See: https://caniuse.com/flexbox-gap */.Toggle {  display: inline-flex; /* 1 */  align-items: center; /* 1 */  flex-wrap: wrap; /* 2 */  position: relative; /* 3 */  gap: 1ch; /* 4 */}

Toggle и handle

Затем - наш toggle. Чтобы облегчить настройку его стилей, мы используем некоторые пользовательские свойства CSS для перемещения вокруг handle и его диаметра.

/** * 1. Vertically center the icons and space them evenly in the available  *    horizontal space, essentially giving something like: [   ] * 2. Size the display according to the size of the handle. `box-sizing` *    could use `border-box` but the border would have to be considered *    in the `width` computation. Either way works. * 3. For the toggle to be visible in Windows High-Contrast Mode, we apply a *    thin semi-transparent (or fully transparent) border. *    Kind thanks to Adrian Roselli for the tip: *    https://twitter.com/aardrian/status/1379786724222631938?s=20 * 4. Grant a position context for the pseudo-element making the handle. * 5. Give a pill-like shape with rounded corners, regardless of the size. * 6. The default state is considered unchecked, hence why this pale red is *    used as a background color. */.Toggle__display {  --offset: 0.25em;  --diameter: 1.8em;  display: inline-flex; /* 1 */  align-items: center; /* 1 */  justify-content: space-around; /* 1 */  width: calc(var(--diameter) * 2 + var(--offset) * 2); /* 2 */  height: calc(var(--diameter) + var(--offset) * 2); /* 2 */  box-sizing: content-box; /* 2 */  border: 0.1em solid rgb(0 0 0 / 0.2); /* 3 */  position: relative; /* 4 */  border-radius: 100vw; /* 5 */  background-color: #fbe4e2; /* 6 */  transition: 250ms;  cursor: pointer;}/** * 1. Size the round handle according to the diameter custom property. * 2. For the handle to be visible in Windows High-Contrast Mode, we apply a *    thin semi-transparent (or fully transparent) border. *    Kind thanks to Adrian Roselli for the tip: *    https://twitter.com/aardrian/status/1379786724222631938?s=20 * 3. Absolutely position the handle on top of the icons, vertically centered *    within the container and offset by the spacing amount on the left. * 4. Give the handle a solid background to hide the icon underneath. This *    could be dark in a dark mode theme, as long as its solid. */.Toggle__display::before {  content: '';  width: var(--diameter); /* 1 */  height: var(--diameter); /* 1 */  border-radius: 50%; /* 1 */  box-sizing: border-box; /* 2 */  border: 0.1 solid rgb(0 0 0 / 0.2); /* 2 */  position: absolute; /* 3 */  z-index: 2; /* 3 */  top: 50%; /* 3 */  left: var(--offset); /* 3 */  transform: translate(0, -50%); /* 3 */  background-color: #fff; /* 4 */  transition: inherit;}

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

@media (prefers-reduced-motion: reduce) {  .Toggle__display {    transition-duration: 0ms;  }}

Стили для фокуса

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

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

/** * 1. When the input is focused, provide the display the default outline *    styles from the browser to mimic a native control. This can be *    customised to have a custom focus outline. */.Toggle__input:focus + .Toggle__display {  outline: 1px dotted #212121; /* 1 */  outline: 1px auto -webkit-focus-ring-color; /* 1 */}

Я заметил одну интересную вещь: при нажатии на родной флажок или его метку контур фокуса не появляется. Это происходит только при фокусировке флажка с помощью клавиатуры. Мы можем имитировать это поведение, удалив стили, которые мы только что применили, когда селектор :focus-visible не подходит.

/** * 1. When the toggle is interacted with with a mouse click (and therefore *    the focus does not have to be visible as per browsers heuristics), *    remove the focus outline. This is the native checkboxs behaviour where *    the focus is not visible when clicking it. */.Toggle__input:focus:not(:focus-visible) + .Toggle__display {  outline: 0; /* 1 */}

Проверенное состояние

Затем нам нужно разобраться с проверенным состоянием. В этом случае мы хотим сделать две вещи: обновить цвет фона toggle с красного на зеленый и сдвинуть handle вправо, чтобы он закрыл крестик и показал галочку (100% собственной ширины).

/** * 1. When the input is checked, change the display background color to a *    pale green instead.  */.Toggle__input:checked + .Toggle__display {  background-color: #e3f5eb; /* 1 */}/** * 1. When the input is checked, slide the handle to the right so it covers *    the cross icon instead of the checkmark one. */.Toggle__input:checked + .Toggle__display::before {  transform: translate(100%, -50%); /* 1 */}

Adrian Roselli справедливо заметил, что эта схема не учитывает возможное "смешанное" (или "неопределенное" состояние). Это справедливо для простоты, поскольку большинство флажков/тумблеров не нуждаются в таком состоянии, но его следует учитывать, когда это необходимо.

Отключенное состояние

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

/** * 1. When the input is disabled, tweak the toggle styles so it looks dimmed  *    with less sharp colors, softer opacity and a relevant cursor. */.Toggle__input:disabled + .Toggle__display {  opacity: 0.6; /* 1 */  filter: grayscale(40%); /* 1 */  cursor: not-allowed; /* 1 */}

Поддержка право-лево

Изначально я забыл о поддержке право-лево, и Adrian Roselli был достаточно любезен, чтобы указать мне на это, поэтому я обновил код. В идеале мы должны использовать псевдо-класс :dir() , но, к сожалению, на данный момент браузеры поддерживают его довольно плохо, поэтому нам приходится полагаться на селектор атрибута [dir].

Нам нужно настроить все, что в настоящее время направлено так, чтобы было исходное и проверенное положение handle.

/** * 1. Flip the original position of the unchecked toggle in RTL. */[dir='rtl'] .Toggle__display::before {  left: auto; /* 1 */  right: var(--offset); /* 1 */}/** * 1. Move the handle in the correct direction in RTL. */[dir='rtl'] .Toggle__input:checked + .Toggle__display::before {  transform: translate(-100%, -50%); /* 1 */}

Иконки

Наконец, мы применим некоторые стили к нашим иконкам, как рекомендует Florens Verschelde в своем фантастическом руководстве по SVG-иконкам:

.Toggle__icon {  display: inline-block;  width: 1em;  height: 1em;  color: inherit;  fill: currentcolor;  vertical-align: middle;}/** * 1. The cross looks visually bigger than the checkmark so we adjust its *    size. This might not be needed depending on the icons. */.Toggle__icon--cross {  color: #e74c3c;  font-size: 85%; /* 1 */}.Toggle__icon--checkmark {  color: #1fb978;}

Вариант кнопки

Как упоминалось ранее, использование флажка не обязательно является наиболее подходящей разметкой. Если toggle имеет немедленный эффект (и поэтому полагается на JavaScript), и если он не может иметь неопределенное состояние, то вместо него следует использовать элемент <button> с атрибутом aria-pressed.

Adrian Roselli в своем материале о toggles предлагает дерево решений для выбора между флажком и кнопкой.

К счастью, наш код легко адаптировать, чтобы он работал так же, как и кнопка. Во-первых, мы изменим HTML таким образом, что <label> станет <button>, а <input> будет удален.

<button class="Toggle" type="button" aria-pressed="false">  <span class="Toggle__display" hidden>    <!-- The toggle does not change at all -->  </span>  This is the label</button>

Затем нам нужно убедиться, что <button> не похожа на саму кнопку. Для этого мы сбросим стили кнопки по умолчанию, включая контур фокуса, поскольку он применяется при toggle (переключении).

/** * 1. Reset default <button> styles. */button.Toggle {  border: 0; /* 1 */  padding: 0; /* 1 */  background: transparent; /* 1 */  font: inherit; /* 1 */}/** * 1. The focus styles are applied on the toggle instead of the container, so *    the default focus outline can be safely removed. */.Toggle:focus {  outline: 0; /* 1 */}

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

+ .Toggle:focus .Toggle__display,.Toggle__input:focus + .Toggle__display {  /*  */}+ .Toggle:focus:not(:focus-visible) .Toggle__display,.Toggle__input:focus:not(:focus-visible) + .Toggle__display {  /*  */}+ .Toggle[aria-pressed="true"] .Toggle__display::before,.Toggle__input:checked + .Toggle__display::before {  /*  */}+ .Toggle[disabled] .Toggle__display,.Toggle__input:disabled + .Toggle__display {  /*  */}+ [dir="rtl"] .Toggle[aria-pressed="true"] + .Toggle__display::before,[dir="rtl"] .Toggle__input:checked + .Toggle__display::before {  /*  */}

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

Заключение

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

  • Мы используем реальный элемент формы флажка, который мы стилизуем под toggle.

  • Он передает свой статус с помощью иконографии и цвета.

  • Он не оставляет артефактов, когда CSS недоступен.

  • Он имеет собственные стили по фокусу и может быть настроен.

  • У него есть отключенное состояние.

  • При необходимости он имеет поддержку право-лево.

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

Здорово! Не стесняйтесь играть с кодом на CodePen, и я надеюсь, что это поможет вам сделать ваши toggles доступными. А также, я рекомендую прочитать эти статьи, чтобы продвинуться дальше:

Примечание

Dion упоминает, что toggle может выглядеть наоборот, и это мнение поддерживает Rawrmonstar, а Mikael Kundert упоминает, что использование флажков обычно проще.


Узнать подробнее о курсе"HTML/CSS"

Смотреть открытый урокCSS Reset ненужный артефакт или спасательный круг

Подробнее..

5 подходов к стилизации React-компонентов на примере одного приложения

16.02.2021 12:20:24 | Автор: admin


Доброго времени суток, друзья!

Сегодня я хочу поговорить с вами о стилизации в React.

Почему данный вопрос является актуальным? Почему в React существуют разные подходы к работе со стилями?

Когда дело касается разметки (HTML), то React предоставляет в наше распоряжение JSX (JavaScript и XML). JSX позволяет писать разметку в JS-файлах данную технику можно назвать HTML-в-JS.

Однако, когда речь идет о стилях, то React не предоставляет каких-либо специальных инструментов (JSC?). Поэтому каждый разработчик волен выбирать такие инструменты по своему вкусу.

Всего можно выделить 5 подходов к стилизации React-компонентов:

  • Глобальные стили все стили содержатся в одном файле (например, index.css)
  • Нативные CSS-модули для каждого компонента создается отдельный файл со стилями (например, в директории css); затем эти файлы импортируются в главный CSS-файл (тот же index.css) с помощью директивы "@import"
  • Реактивные CSS-модули (данная техника используется не только в React-проектах; реактивными я назвал их потому, что библиотека css-modules в настоящее время интегрирована в React, т.е. не требует отдельной установки, по крайней мере, при использовании create-react-app) для каждого компонента создается файл Component.module.css, где Component название соответствующего компонента (обычно, такой файл размещается рядом с компонентом); затем стили импортируются в JS-файл в виде объекта, свойства которого соответствуют селекторам класса (например: import styles from './Button.module.css'; <button style={styles.button}>Нажми на меня</button>)
  • Встроенные (инлайновые) стили элементы стилизуются с помощью атрибутов style со значениями в виде объектов со стилями (например, <button style={{ borderRadius: '6px'; } }>Нажми на меня</button>)
  • CSS-в-JS библиотеки, позволяющие писать CSS в JS-файлах; одной из таких библиотек является styled-components: import styled from 'styled-components'; const Button = styled`какой-то css`; <Button>Нажми на меня</Button>

На мой взгляд, лучшим решением является последний подход, т.е. CSS-в-JS. Он выглядит самым логичным с точки зрения описания структуры (разметки), внешнего вида (стилей) и логики (скрипта) компонента в одном файле получаем нечто вроде Все-в-JS.

Шпаргалку по использованию библиотеки styled-components можно найти здесь. Возможно, вам также интересно будет взглянуть на шпаргалку по хукам.

Ну, а худшим подходом, по моему мнению, являются встроенные стили. Стоит, однако, отметить, что определение объектов со стилями перед определением компонента и последующее использование этих объектов напоминает CSS-в-JS, но остаются camelCase-стиль, атрибуты style и сами встроенные стили, которые затрудняют инспектирование DOM.

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

Исходный код GitHub.

Песочница:


Выглядит приложение так:



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

Структура проекта следующая:

|--public  |--index.html|--src  |--components    |--Control      |--Control.js      |--Control.module.css      |--package.json      |--styles.js    |--Counter      |--Counter.js      |--Control.module.css      |--package.json      |--styles.js    |--Title      |--Title.js      |--Title.module.css      |--package.json    |--index.js  |--css    |--control.css    |--counter.css    |--title.css  |--App.js  |--global.css  |--index.js  |--nativeModules.css  |--reactModules.css...

Пройдемся по некоторым файлам, находящимся в директории src:

  • index.js входная точка JavaScript (в терминологии бандлеров), где импортируются глобальные стили и рендерится компонент App
  • App.js основной компонент, где импортируются и объединяются компоненты Control, Counter и Title
  • global.css глобальные стили, т.е. стили всех компонентов в одном файле
  • nativeModules.css файл, где импортируются и объединяются нативные CSS-модули из директории css (control.css, counter.css и title.css)
  • reactModules.css глобальные стили для реактивных CSS-модулей
  • components/Control/Control.js три реализации компонента Control (с глобальными стилями/нативными CSS-модулями, c реактивными CSS-модулями и стилизованными компонентами), а также пример объекта со встроенными стилями
  • components/Control/Control.module.css реактивный CSS-модуль для компонента Control
  • components/Control/styles.js стилизованные компоненты для компонента Control (когда стилизованных компонентов много, я предпочитаю выносить их в отдельный файл)
  • components/Control/package.json файл с main: "./Control", облегчающий импорт компонента (вместо import Control from './Control/Control' можно использовать import Control from './Control'
  • components/index.js повторный экспорт, позволяющий разом импортировать все компоненты в App.js

Как всегда, буду рад любой форме обратной связи.

Благодарю за внимание и хорошего дня.
Подробнее..

Перевод Хватит организовывать код по типу файлов

06.06.2021 12:22:20 | Автор: admin

Какой самый популярный стиль организации кода вы встречали в корпоративных кодовых базах? Лично я чаще всего видел решение, подразумевающее группировку всех файлов по их типу. Таким образом, к примеру, в системе MVC все контроллеры, все сервисы, все репозитории, все POJO и так далее находятся вместе. Давайте назовем такое решение "стековым" стилем организации кода.

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

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

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

Неправильная абстракция

Люди не читают код по назначению файлов и классов. Никто никогда не говорит: "покажите мне весь API проекта" или "продемонстрируйте мне все запросы, отправляемые решением". Люди читают код, полагаясь на его смысл и роль. Как в системе управления гостиницами, например, люди отдельно думают о номерах, гостях, ценах и так далее.

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

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

Нарушения связи

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

Проблема этого аргумента в том, что он фокусируется на разделении, но полностью игнорирует потребность в связи между определёнными структурами. Допуская, что все файлы и классы определённого типа в такой системе расположены вместе, справедливо ли будет сказать, что их взаимная связь, как структур одинакового назначения, но разного смысла, нас устраивает? Положено ли все же, к примеру, контроллерам, находиться отдельно от своих классов и репозиториев? Можем ли мы позволить, скажем, всем репозиториям быть сильно зависимыми друг от друга, но отделенными от уровня сервисов? Очевидный ответ - НЕТ! Такой код стал бы хрестоматийным куском г*вна. Рефакторинг такой системы на более мелкие решения был бы абсолютным кошмаром, потому что вам пришлось бы отделить друг от друга все классы на каждом уровне стека. Это убивает основную цель использования стиля MVC.

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

Трудно менять

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

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

Ограничивает выбор дизайна

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

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


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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru