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

欲乱又大又粗

欲乱又大又粗Автор делится собственным опытом, не стоит ожидать от статьи технического материала.
В данной статье рассматривается проявление синдрома самозванца таким, какой он был у автора.
Спасибо за понимание.

欲乱又大又粗У всех разработчиков была ситуация, когда вы смотрите код на StackOverflow и понимаете, как бы было бы хорошо, если бы такое решение сразу же пришло в голову вам. С годами, я думаю, что всё сильнее выпадаю из разработки. Всё началось с того момента, когда мне на вакансию джуна пришлось учить алгоритмы, а там я встретил первую проблему с числами: я не понимал как работают нетривиальные циклы. Все мои друзья по разработке начали говорить что я просто далеко полез, и накрутил лишнего. Я их слушать не стал, ибо во мне есть чертовски плохая черта: я должен понимать как процесс работает полностью и сразу, иначе я начинаю корить себя, что не знаю этой вещи, а все другие наверняка поняли её сразу.

Всё зашло настолько далеко, что я начал разбираться в сложении. Всё в сложении легко, я проходил в тренирочных приложениях на смартфоне сложные упражнения на ментальный счёт за неплохое время, только я не понимал как я это делаю. Всех нас учили считать с детства, мы делаем это не думая. У меня не было проблем в возведением в степень, умножением, делением, логарифмированием. Вопрос, который не давал мне жить: "С какого элемента начинается счёт суммы? C текущего, или с элемента, который на 1 больше него?". Я корил себя день и ночь, эта мысль преследовала меня везде, где бы я ни был. 欲乱又大又粗 после долгого обдумывания и многократного просмотра роликов для детей (Я писал фронт-энд, изучал принципы ООП и вскоре собирался приступать к функциональному программированию, а счёта не понимал. Думаю, это лучшее описание синдрома самозванца) я наконец-то понял что счёт (сложение) производится со следущего элемента, после текущего. Затем около 2 дней ушло на вычитание (чтобы понять, что вычитание ведётся с последнего элемента, а не элемента на 1 меньше по индексу, чем он), затем ещё несколько дней для работы со временем.

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

欲乱又大又粗

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

Бродя по просторам интернета нашёл следующее:

"use strict" var bind = Function.prototype.call.bind(Function.prototype.bind);

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

Понял как работает call, bind, однако не понял почему мы должны подвязать пространство имён для call из bind.

Спросив в чате, мне сказали что всё проще чем я думаю, и вообще я себя накручиваю. Эта фраза прозвучала второй раз и тут я задумался, что что-то не так.

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

Я корил себя всё это время, потому что думал, что все люди всё понимают, у них не бывает проблем, и всё сказанное понимается с первого раза. Я думал, что все люди считают обдуманно, что все сочетания методов воспринимаются ими мгновенно.

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

ссылка на оригинал статьи https://habr.com/ru/post/508098/

Язык программирования Mash


http://mash-project.org
https://github.com/RoPi0n/mash-lang

Mash?

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

Интересно? Тогда под кат! ?

Насколько завершен проект?


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

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

В качестве среды выполнения языка используется стековая виртуальная машина (ВМ), поддерживающая многопоточность, сборку мусора (Reference Counting).
Реализован транслятор языка (с построением AST, все как по книжкам) в абстрактный код для ВМ и в перспективе в другие языки (но из-за сложности языка — это пока только планы на будущее).
Для удобства в ознакомлении с языком и работе с ним реализована небольшая IDE (FPC + SynEdit).

Встраиваемость

ВМ языка имеет API, функционал языка можно расширять путем написания библиотек для ВМ на любом нативном языке (FPC, Delphi, C/C++, Rust и т.д.),
также язык можно встроить в любой ваш проект, при этом получить в свое распоряжение весь функционал Mash’a и его нативных библиотек.

Debug?

У ВМ предусмотрена возможность работы в связке с отладчиком (который пока что очень сырой).
Язык поддерживает трассировку исключений.

Поддержка платформ

Язык полностью написан на Free Pascal, который в свою очередь поддерживает огромный список платформ, под которые может быть собран Mash.
Зависимости от каких-либо библиотек отсутствуют.

Проект уже собирал ранее и тестировал на Windows, Linux и Android.

На что Mash способен уже сейчас?

На данный момент я работаю над реализацией стандартного набора библиотек для работы с файлами, математикой, I/O, многопоточностью, GUI, сетью, базами данных, криптографией и т.д.


В репозитории проекта (и в Pre-Release сборке) можно найти небольшие демо-приложения.
На Mash написана змейка, асинхронный веб сервер/фреймворк (по типу Flask’a), отрисовка графиков в декартовой и полярных системах координат, Аттрактор Лоренца, вращение простых 3D моделек по типу кубика, а так же версия транслятора Mash’a, написанная на Mash’e.

Что дальше?

Над проектом работаю пока один в рамках хобби, так что его будущее все ещё остается не определенным (+вуз, +разные неопределенные сложности и релиз может отложиться на долго).
В данной статье представлен промежуточный результат работы, все ещё далекий от конечной цели.
В разработке, помимо библиотек для ВМ, находится JIT компилятор по типу HotSpot.

Дочитали до конца?

Спасибо за внимание ?

ссылка на оригинал статьи https://habr.com/ru/post/508096/

Как верстать веб-интерфейсы быстро, качественно и интересно

欲乱又大又粗

Всем привет! Давно хотел и наконец написал небольшую книжку — бодрое пособие по своей профессиональной области: актуальным подходам к разметке интерфейсов, экранному дизайну и доступности. Она о моем оригинальном подходе к созданию GUI, препроцессорам CSS (для объективности, немного и об альтернативных подходах), и его эффективном практическом использовании с javascript и популярными реактивными компонентными фреймворками Vue и React. Материал представлен аккуратно последовательно, но безумно интенсивно и динамично — ничего лишнего или даже слишком подробного — для того чтобы увлеченный и подготовленный читатель не потерял интереса и ?проглотил на одном дыхании?. С другой стороны, текст, достаточно сложный ближе к концу, и на всем протяжении — густо насыщенный идеями, ссылками на технологии и подходы — поэтому, очевидно, будет ?на вырост? начинающим. Но, в любом случае, как и если вы только начали интересоваться данной тематикой, так и если уже давно занимаетесь веб-дизайном, версткой и программированием фронтенда — вам может быть полезно на него взглянуть.

Мотивация

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

Начну с некоторого огульно обобщающего и, поэтому, несколько провокационного наблюдения, ?вброса?: большинство, не только начинающих, но даже опытных программистов испытывают своеобразное предубеждение-стереотип о некой ?несерьезности? верстки интерфейса как отрасли деятельности в веб-индустрии — ?верстка это не программирование!?. Очень многие считают что заниматься разметкой ?некруто и скучно? для ?серьезного? специалиста. И как следствие — уделяют предмету мало своего внимания и времени, имеют мало реального релевантного опыта. Проще говоря, большинство разработчиков не любит и не умеет верстать. И уже и как причина и как следствие — зачастую сами подходы, технологии и архитектура используемые для организации GUI даже на серьезных коммерческих проектах — отставляют желать лучшего, не отвечают реалиям современной веб-индустрии, устарели и недостаточно эффективны. Неудачные, якобы временные, слабые решения и дальнейшие бесконечные быстрые ?фиксы?, кривые ?кряки? наслаиваются друг-на-друга, кодовая база неоправданно распухает и становится все менее связной и контролируемой. Шаблоны, или ныне — в эру компонентных фреймворков — компоненты, стили и логика для них часто и закономерно превращаются в невнятную и крайне излишнюю по сути ?свалку?, ?густой лес?, ?джунгли? с очевидно неподъемной ценой рефакторинга и масштабирования. Очевидно, что такое состояние системы может легко приводить к серьезным затруднениям, снижению темпов или даже срыву сроков и, ирония как раз в том, что в реальной коммерческой ситуации, авторам подобной громоздкой и неуклюжей системы, все равно придется потратить еще больше времени на то, чтобы, по крайней мере, исправить все оплошности и несовершенства разметки, оформления и логики для них, но делать это придется в изначально плохо организованном коде, по замкнутому кругу — только увеличивая беспорядок и вероятность сбоев. С того момента как вы перестаете быть ?джуном?, ваша ответственность состоит не только в том чтобы закрыть все ?баги? на трекере и навернуть как можно скорее ?фичи?, любой ценой. Надежная и легко поддерживаемая система — продукт который вы продаете бизнесу.

Реальный жизненный кейс: будучи начинающим специалистом я работал удаленно в одном приятном стартапе. Когда проект запустили, после презентации многие присутствовавшие на ней высказались о том, что кегль основного текста и полей ввода в интерфейсе — мелковат. Получив задачу в трекере, я потратил всего пару минут, поправив одну переменную своей системы — чтобы поднять кегль на всех нужных полях и контролах, и еще 15 минут чтобы удостовериться что ничего действительно не сломалось ни на одном шаблоне. Ваша система изначально должна быть написана так, и только так, чтобы ее было можно легко скорректировать и улучшить, поддерживать и расширять. По-настоящему лаконичный и выразительный качественный код — невероятно мощно экономит время и нервы даже если вы работаете с проектом в одиночку. Кроме того, уважаемые авторитеты в коммерческом программировании утверждают [см. Роберт Мартин — ?Чистая архитектура?] что ?то что сделано изначально плохо? — в реальности, не только ?никогда не будет переписано?, но и приводит к постоянному крутому росту стоимости дальнейшей доставки нового функционала, а в перспективе способно полностью блокировать прогресс по проекту!

Хорошее понимание возможностей и ограничений современных браузерных технологий очень желательно и полезно не только для веб-разработчиков, но и для гуманитариев-дизайнеров проектирующих GUI. Часто даже востребованный специалист, выдающий приятный стиль и не делающих серьезных ошибок по UХ, не может внятно ответить на простейшие технические вопросы о своем дизайне при сдаче макета на верстку, то есть — ?не понимает что рисует?.

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

Кому будет полезен текст?

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

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

Дизайнерам. Вы веб-дизайнер, но хотите начать верстать.

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

Препроцессор

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

Препроцессор, JavaScript и фреймворки

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

Левон Гамбарян.
Июнь 2020 года.

Препроцессор


Простейший пример плохого кода

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

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

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

Давайте посмотрим на самый простейший пример плохого кода на CSS:

/* Примитивнейший пример обычного плохого кода на CSS *//* Где-нибудь в файлах стилей: */.selector--1 { width: 200px; height: 200px; border: 1px solid #ADADAD; border-radius: 3px; /* ... и дальше еще огромное количество самых разных правил */ }.selector--2 { width: 200px; height: 400px; border: 1px solid #ADADAD; border-radius: 3px; /* ... и дальше еще огромное количество самых разных правил */ }

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

А как надо?

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

Справедливости ради, нужно упомянуть, что последние годы, в связи с стремительным ростом популярности компонентных js-фреймворков и их подходов, все больше сторонников набирают также различные ?CSS-in-JS?-реализации (например: Styled Components). Скоро, вероятно, можно будет спокойно использовать переменные в самом CSS (CSS Custom Properties). Тема холиварная, существуют контексты и ситуации когда подобный CSS-in-JS подход может оказаться более оправданным и изящным, без сомнения. И даже существует масса реалистичных кейсов когда проще всего будет действительно обойтись несколькими наборами правил на CSS, а любое его расширение будет излишним. Но в общем случае, в реальной коммерческой практике, имхо, для верстки сложных дизайнов и интерфейсов удобнее и эффективнее всего сейчас использовать любой препроцессор, и, шок — даже с компонентным фреймворком, дальше я планирую показать ?как именно это лучше всего делать?. Препроцессоры дают максимум возможностей и позволяют стремиться к максимальной выразительности и переиспользуемости. Вот во что превратился бы ?плохой код? выше в SCSS-синтаксисе, наверное — самого популярного на сегодняшний день препроцессора — Sass:

// В @/src/scss/utils/_variables.scss:$colors__border: #adadad;$border-radius: 3px;// В @/src/scss/utils/_placeholders.scss: %border-block { border: 1px solid $colors__border; border-radius: $border-radius; }// В @/src/scss/utils/_mixins.scss: @mixin size($width, $height) { width: $width; height: $height; }// В любом месте проекта: .selector { $selector--1__size: 200px; $selector--2__width: 200px; $selector--2__height: 400px;&--1, &--2 { @extend %border-block; /* ... включение других сущностей препроцессора и специфическиих правил общих для селекторов */ }&--1 { @include size($selector--1__size, $selector--1__size); /* ... включение других сущностей препроцессора и специфических правил уникальных для селектора */ }&--2 { @include size($selector--2__width, $selector--2__height); /* ... включение других сущностей препроцессора и специфических правил уникальных для селектора */ } }

Точно тоже самое легко сделать и на, кажется, недооцененном, но очень удачном Stylus — совершенно не важно какой именно расширенный синтаксис вы используете, главное как и зачем. Очень много раз мне приходилось видеть плохой чужой код написанный якобы для препроцессора, видимо, ?потому что так сейчас модно?, но, на самом деле, практически ничем не отличающийся от кода CSS. Не делайте так! Препроцессор дает нам крайне ценную возможность абстрагировать общие качества гайдлайна, стиль и основанные на нем частные стили, организовать их намного более выразительно и лаконично, легко модифицировать и переиспользовать при необходимости.

В данном, вырванном из контекста, но, при этом, вполне жизненном примере, кажется, что кода препроцессора — сильно больше. Он еще и раскидан по нескольким разным файлам, что, как будто, еще все усложняет. Зачем так напрягаться, а? Прежде всего, привычка начинать писать разметку с переменных и обобщений — очевидно грамотная. Перестаньте плодить изолированные глухие кряки с магическими числами, начните применять абстракцию! Делайте хорошо сразу, потому что вы почти никогда и ничего не переделаете ?потом?, на самом деле. ?Когда наш стартап наконец взлетит?, и как раз во многом из-за такого отношения он может и не взлететь, в результате. Чем детализированнее и сложнее ваш интерфейс, его дизайн, тем больше строк и времени вы будете ?экономить? просто оптимизируя общие наборы правил, переиспользуя стили. Кроме того, поддерживать код и, тем более, вносить серьезные изменения будет на порядок проще.

Первый пример демонстрирует что на начальных этапах развития проекта хорошо продуманного кода препроцессора может быть даже визуально несколько больше, чем неорганизованного, внутренне плоского, скучного CSS. Но давайте разберем очень часто встречающийся кейс, в котором мы очевидно сразу сильно экономим много трафика и явно оптимизируем возможную поддержку. Такое очень часто встречается: нам нужно создать большое количество, предположим — 20 штук — модификаторов одного селектора — квадратной иконки размеров в 100 пикселей — и поставить в них нужные картинки в бекграунд. В Sass мы можем написать цикл с интерполяцией для создания селектора модификатора и указания пути до ресурса. И хотя такая синтаксическая возможность не является чем-то идейно решающе важным — на практике она экономит кучу времени и повышает качество жизни на работе:

// В @/src/scss/utils/_variables.scss:// Paths $images__path--root: "../../assets/images/";// Sizes$icons__size: 100px;// Views $icons: 20;// В любом месте проекта (в папке В @/src/scss/project/): .icon { // корректируем путь до картинок $image-path: $image_path--root + "icons/";@include size($icons__size, $icons__size); // эта примесь уже создана выше@for $i from 1 through $icons { &.icon--#{$i} { background: url("#{$image-path}icon--#{$i}.svg") center center no-repeat; } } }

Пример предполагает что в вашем проекте следующая структура:

. └─ src├─ assets│└─ images│ ├─ icon--1.svg│ ├─ icon--2.svg│ └─ ...└─ sscs ├─ project │└─ ... └─ utils├─ _mixins.scss└─ _variables.scss

Теперь в шаблонах мы можем использовать:

<div class="icon icon--1"></div>

Если вы желаете чтобы картинки были с осмысленными именами — можете перебирать список:

.icon { $image-path: $image_path--root + "icons/"; $images: "name1", "name2", "name3"; // Список имен@include size($icons__size, $icons__size);@each $image in $images { &.icon--#{$image} { background: url("#{$image-path}#{$image}.svg") center center no-repeat; } } }

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

.selector { $width: 100px;width: calc(100vw - #{$width}); }

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

Абстрагируй все!

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

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

// В @/src/stylus/utils/variables.styl:$colors = { mint: #44c6a8, // ... другие конкретные значения цветов }// Создаем "основной цвет", абстрагируясь от конкретного цвета $colors['primary'] = $colors.mint // ... другие "функциональные" цвета

Любое имеющее глобальное значение и потенциально переиспользуемое качество гайдлайна и дизайна должно быть отражено в файле переменных препроцессора. Теперь в любом месте где потребуется предоставить основной ?брендовый? цвет:

.selector color $colors.primary

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

Структура и стилевая база препроцессора

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

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

Но давайте уже организуем препроцессор, если с SCSS:

. └─ src└─ sscs ├─ core // обшие и компилируемые сущности препроцессора │├─ _animations.scss // keyframes │├─ _base.scss // минимальная нормализация основных HTML-элементов │├─ _grid.scss // сетки │├─ _typography.scss // типографика │└─ _utilities.scss // быстрые удобные классы-утилиты для включения прямо в разметку ├─ libraries // папка с файлами стилизаций сторонних модулей │└─ _modal.scss - например какая-нибудь готовая модаль ├─ project // стили конкретного проекта │├─ _elements.scss // отдельные простые элементы-компоненты │├─ _fixes.scss // этот файл всегда должен быть практически пустой, и предназначен только для редких общеизвестных "собственных проблем браузеров" │├─ _layout.scss - стили общей для всех страниц GUI-обертки над контентом интерфейса │└─ _widgets.scss - сложные составные комбинации простых элементов-компонентов ├─ utils // обшие и некомпилируемые основные сущности препроцессора │├─ _functions.scss // на практике нужны крайне редко │├─ _mixins.scss // параметризируемые и способные принимать контент примеси-микстуры │├─ _placeholders.scss // повторяющиеся наборы правил - растворы │└─ _variables.scss // самый важный файл с переменными ) ├─ _main.scss // точка сборки всех стилей препроцессора └─ _stylebase.scss // стилевая база

То есть, на самом деле — порядок сборки всей кухни имеет значение, конечно же:

// В @/src/scss/_stylebase.scss: // Stylebase ////////////////////////////////////////////////////// //////////////////////////////////////////////////////// Uncompiled kitchen @import "./utils/_functions"; @import "./utils/_variables"; @import "./utils/_mixins"; @import "./utils/_placeholders";// Core base normal style and common utils @import "./core/_animations"; @import "./core/_typography"; @import "./core/_base"; @import "./core/_grid"; @import "./core/_utilities";// В @/src/scss/_main.scss: // Project styles ////////////////////////////////////////////////////// //////////////////////////////////////////////////////// Stylebase for components @import "_stylebase";// App styles @import "./project/_fixes"; @import "./project/_elements"; @import "./project/_widgets"; @import "./project/_layout";/* External libraries customization */ @import "./libraries/_modal";

Итак, ?стилевой базой? мы будем называть некое основное ядро стилей, доступный всем остальным компонентам системы общий код препроцессора. Более детально, он состоит из условно двух разных видов файлов:

  1. Растворяемые при компиляции инструменты-помощники, сущности позволяющие генерировать лаконичный, оптимальный, связный код:

    1. функции
    2. переменные
    3. параметризуемые примеси
    4. включения-плейсхолдеры

  2. Компилируемые глобальные стили:

    1. анимации keyframes
    2. типографика
    3. базовая нормализация основных HTML-элементов
    4. сетки
    5. утилитарные классы-помощники для разметки

В папки @/src/scss/project и @/src/scss/libraries вы можете добавлять файлы по необходимости.

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

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

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

ссылка на оригинал статьи https://habr.com/ru/post/508064/

Code review в Gitlab CE: если Merge request approvals нет, но очень хочется

Одной из самых нужных функций, которой нет в бесплатной версии GitLab, является возможность голосования против обнуления репозитория контролировать Merge request (MR), используя обязательный code review.

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

Зачем это вообще?

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

В итоге приходится:

  • либо совсем запрещать Merge в защищенные ветки для части разработчиков, но тогда разработчики, имеющие право на Merge, получают конфликты при слиянии чужих MR как бонус;
  • либо давать возможность делать бесконтрольные слияния с вашей мастер-веткой без code review, даже если это Junior, устроившийся только вчера.

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

Общая схема работы

В качестве примера настроим Merge request approvals на тестовом репозитории myapp:

  1. Создадим токен для доступа к API GitLab (через него будем получать информацию о количестве голосов ?за? и ?против?)
  2. Добавим токен в переменные GitLab
  3. Запретим Merge при ошибках в пайплайне (если голосов ?за? недостаточно)
  4. Настроим проверку голосов как часть пайплайна CI/CD
  5. Запретим делать коммиты в защищенные ветки, все изменения проводим только через MR
  6. Проверим, что получилось в итоге

1. Создаем токен для доступа к API

Заходим в Настройки пользователя → Токены доступа и записываем токен:

Учетная запись для получения токена
Доступ к API позволяет делать практически все с вашими репозиториями, поэтому советую создать отдельную учетную запись Gitlab, дать ей минимальные права на ваши репозтории (например, Reporter) и получить токен для этой учетной записи.

2. Добавляем токен в переменные Gitlab

Например, на предыдущем шаге мы получили токен QmN2Y0NOUFlfeXhvd21ZS01aQzgK

Открываем Настройки → CI/CD → Переменные → Добавить переменную → GITLAB_TOKEN_FOR_CI

В итоге получим:

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

3. Ставим запрет на Merge, если не получены одобрения коллег после проведенного code review

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

Заходим в Настройки → Основные → Запросы на слияние → Проверки слияния и включаем опцию Сборочные линии должны успешно выполниться.

4. Настраиваем пайплайн

Если вы еще не делали CI/CD конвейер для вашего приложения
Создаем в корне репозитория файл .gitlab-ci.yml с простейшим содержанием:
stages: - build - testvariables: NEED_VOTES: 1include: - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"run-myapp: stage: build script: echo "Hello world" 

Отдельный репозиторий для конфигурации CI/CD
Я бы рекомендовал сделать отдельный репозиторий, в котором необходимо создать файл myapp.gitlab-ci.yml для настройки конвейера. Так вы сможете лучше контролировать доступ участников, которые могут изменить конвейер сборки и получить токен доступа.

Расположение нового файла конвейера нужно будет указать, зайдя в репозиторий myapp — Настройки — CI/CD — Сборочные линии — Пользовательский путь конфигурации CI — указать новый файл, например myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci

Совет: используйте линтер для внесения изменений в файлы GitLab CI
Даже если вы работаете один, хорошим помощником выступит работа через MR, прогоняя все ваши изменения файлов пайплайна через линтер. Если вы ошибетесь в синтаксисе YAML-файла, это не даст вам сломать рабочий конвейер, а просто заблокирует Merge.

Пример контейнеров с линтерами, которые вы можете встроить в ваш пайплайн:

hub.docker.com/r/gableroux/gitlab-ci-lint
hub.docker.com/r/sebiwi/gitlab-ci-validate

И пример стадии проверки:

stages: - lintlint: image: sebiwi/gitlab-ci-validate:1.3.0 variables: GITLAB_HOST: https://gitlab.com script: - CI_FILES=(./*.yml) - for f in "${CI_FILES[@]}"; do gitlab-ci-validate $f; done; 

Осталось добавить в ваш пайплайн несколько параметров, чтобы все заработало:

stages:
- test

variables:
NEED_VOTES: 1

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

Переменная NEED_VOTES определяет сколько ?пальцев вверх? должно быть у MR, чтобы был доступен Merge. Значение, равное единице, означает, что вы сами можете одобрить свой MR, ?лайкнув? его.

include подключает стадию test, проверяющую количество ?лайков?.

Простейший пайплайн на примере myapp.gitlab-ci.yml
stages:
- build
- test

variables:
NEED_VOTES: 0

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

run-myapp:
stage: build
image: openjdk
script:
- echo CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- java HelloWorld.java

Содержание check-approve.gitlab-ci.yml
ci-mr:
stage: test
script:
- echo ${CI_API_V4_URL}
- echo "CI_PROJECT_ID ${CI_PROJECT_ID}"
- echo "CI_COMMIT_SHA ${CI_COMMIT_SHA}"
- "export MR_ID=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .id else {} end\" | grep --invert-match {})"
- "export MR_TITLE=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .title else {} end\" | grep --invert-match {})"
- "export MR_WIP=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .work_in_progress else {} end\" | grep --invert-match {})"
- "export MR_UPVOTES=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .upvotes else {} end\" | grep --invert-match {})"
- "export MR_DOWNVOTES=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .downvotes else {} end\" | grep --invert-match {})"
- MR_VOTES=$(expr ${MR_UPVOTES} - ${MR_DOWNVOTES})
- NEED_VOTES_REAL=${NEED_VOTES:-1}
- echo "MR_ID ${MR_ID} MR_TITLE ${MR_TITLE} MR_WIP ${MR_WIP} MR_UPVOTES ${MR_UPVOTES} MR_DOWNVOTES ${MR_DOWNVOTES}"
- echo "MR_VOTES ${MR_VOTES} Up vote = 1, down vote = -1, MR OK if votes >=${NEED_VOTES_REAL}"
- if [ "${MR_VOTES}" -ge "$(expr ${NEED_VOTES_REAL})" ];
then
echo "MR OK";
else
echo "MR ERROR Need more votes";
exit 1;
fi
image: laptevss/gitlab-api-util
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release\/.*$/'

Подробнее о том, что происходит при проверке:

  • установлено ограничение, что проверка будет только при создании MR в ветки master или release/*
  • используя API GitLab, получаем количество ?лайков? и ?дизлайков?
  • вычисляем разность между положительными и отрицательными откликами
  • если разность меньше заданного нами значения в NEED_VOTES, то блокируем возможность сделать слияние

5. Запрещаем коммиты в защищенные ветки

Определяем ветки, для которых мы должны проводить code review и указываем, что работать с ними можно только через MR.

Для этого заходим в Настройки → Репозиторий → Protected Branches:

6. Проверяем

Зададим NEED_VOTES: 0

Делаем MR и ставим ?дизлайк?.

В логах сборки:

Теперь ставим ?лайк? и запускаем повторную проверку:

ссылка на оригинал статьи https://habr.com/ru/post/488296/

2.07 онлайн-митап про микросервисы и Unit-тесты

В четверг 2 июля собираемся обсудить очередной опыт распила монолита и рассказать, как Unit-тестирование сокращает время разработки. Старт в 16:00 мск, в 17:00 по Ижевску.

Участие бесплатно, нужна регистрация.

?Упрощаем себе жизнь с помощью Unit-тестирования?

Юнит-тесты повышают скорость разработки согласны?

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

?Как отпилить часть монолита и не сойти с ума?

Я расскажу о нашем опыте отделения части функциональности сервиса в отдельный ?микросервис?:

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

?Вход? свободный, не забудьте зарегистрироваться, чтобы получить ссылку. Если не хватило вводных — welcome в комментарии.

А ещё смотрите там же на сайте анонс митапа по управлению проектами 9 июля.

И приходите, будем рады!

ссылка на оригинал статьи https://habr.com/ru/company/directum/blog/508068/