Дэн Щербаков ⚛️
96 subscribers
20 photos
49 links
Канал для фронтенд-разработчиков о том, как развиваться и увеличивать зарплату.

Senior Frontend Developer с 6 годами опыта. За этот период увеличил зарплату почти в 7 раз.

Начинайте тут: https://yangx.top/code_lab/280
加入频道
Командная строка - Vim, Nano
...или как перестать бояться тупиков в Git и начать жить

- В редакторах Linux, в которые входит и Vim, используется навигация через CTRL + {key}. Например, CTRL + X закроет редактор.

- В подсказках CTRL обозначается как символ ^. Соответственно, Git сам объясняет, как выйти из редактора.

- Главное отличие Vim - у него есть разные режимы:
- режим команд (по-умолчанию)
- режим редактирования: войти - клавиша i, выйти - ESC или ^[
- Визуальный режим
- Режим командной строки.

- Как выйти из Vim?!!1 - вопрос миллионов.
Есть два основных выхода:
1. ^X
2. :q в режиме команд.

А выйти с сохранением можно через :wq.

#bash
Bash - управление потоками

Вывод программ можно не только выводить на экран, но и писать в файл. И наоборот. Делается это операторами:

< > >>

< - выводит на экран;
> - записывает в файл (с перезаписью)
>> - добавляет в существующий файл

Эти операции связаны с потоками ОС. Вот эти потоки:
STDIN (файловый дескриптор 0) (прием данных в процесс)
STDOUT (ф.д.1) (вывод данных из процесса)
STDERR (ф.д.2) (вывод ошибок)

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

Еще один, очень важный оператор для консольных команд - это пайп. Выглядит он как вертикальная черта: " | ".
Его задача - передавать данные из одной программы в другую на манер конвейера.
Пайп применяется, потому что, как и в NodeJS, UNIX придерживается принципа атомарности программ. Лучше соединить несколько grep пайпом, чем усложнять сам grep.

Пример:

$ grep hello | grep world // выведет все совпадения по hello и world

#bash
Структуры данных: заметки

- Двухсвязный список может быть выгоднее массива: любые операции вставки и удаления занимают в нём время О(1). Но, в зависимости от данных, можно обойтись односвязным списком или просто массивом.

- Поиск в связанном списке равен О(n), если не прибегать к дополнительному индексированию и другим трюкам.

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

- Реализовать стек можно с помощью массива или односвязного списка. Я делал и обычной строкой :)

- В деревьях есть понятие "листового узла" - это узлы, не имеющие потомков.

- Закономерность в деревьях: ребер в дереве всегда равно количеству узлов минус 1. Так получается, потому что к любому из узлов (кроме корня) ведет один указатель.

- Глубина узла дерева - это количество ребер, которое нужно пройти, чтобы добраться до узла. Например, у корня глубина - 0: на него ничего не указывает.

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

- Свойства двоичного дерева:
1. Максимальное количество узлов на уровне высоты: 2^уровень.
2. Максимальное количество узлов дерева: (2^высота дерева)-1.
3. Высота дерева по количеству узлов: log2(n+1)-1

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

- Хранить деревья в памяти можно по-разному:
1. Обычное дерево можно хранить в связанном списке.
2. Complete binary tree - дерево, в котором все узлы, кроме листовых, заполнены, и дерево расширяется слева - допустимо хранить в массиве.

#структуры_данных
Мотивация. Как двигаться вперед.

Пост не в формате канала, но касается нашей профессии не меньше нюансов программирования.

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

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

2. Работаю для людей. Когда код решает реальные задачи - он меняет мир. Когда код видят коллеги, говорят о нём, он меняет их. Я всегда в выигрыше: критика оттачивает, похвала - дает больше сил.

3. Наслаждаюсь процессом. Будущее непредсказуемо. Размышления, устарела ли технология и востребована ли профессия, - гадания на кофейной гуще. Можно без лишних эмоций анализировать, выбирать перспективные направления. А эмоции - оставить для программирования. Технологии воплощают мои идеи. Каждая строка кода приносит удовольствие, удовольствие дает силу. Это прекрасно.

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

#мотивация
React, заметки:

- React.Fragment - обертка для элементов, которая используется, когда нельзя использовать <div> - например, в списках и таблицах. Имеет коротку запись <> ... </> (пока поддерживается малым количеством инструментов, не рекомендуется).

- Жизненный цикл компонента в Реакт - это очередь событий, которые происходят с компонентом. Как и в WP, для этих событий есть хуки:

1. componentDidMount() - срабатывает, когда компонент отрендерен как ДОМ-объект.
2. componentDidUpdate() - срабатывает при обновлении состояния компонента. Используется, например, для получения данных по АПИ. Предпочтительно делать это в нём, а не в конструкторе.
3. componentWillUnmount - перед удалением ДОМ-элемента.
4. componentDidCatch() - ловит ошибку, под которую не подготовлен обработчик.

#React #жизненный_цикл
React: Error Boundaries

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

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

Что происходит с ошибкой в дереве компонентов? Она всплывает, пока не доберется до root. Error boundaries - это компоненты, в которые встроены обработчики ошибок, не дающие тем всплыть и уничтожить приложение. Для обработки используются метод жизненного цикла componentDiDCatch().

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

ComponentDidCatch работает только для методов жизненного цикла и рендеринга приложения. Ошибки в event listener-ах или асинхронных коллбеках он не ловит.

#React #обработка_ошибок #UX
React: разделение ответственности

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

Error boundaries тоже могут быть отделены от компонентов, занятых рендерингом. Для этого можно использовать props.children. В этом свойстве объекта props находится код, который написан между открывающим и закрывающим тегами компонента:

<Header>
<ChildComponent />
</Header>

Для обработки ошибок создаем компонент-обертку, которая возвращает своих "детей":

<ErrorBoundry>
<Header />
</ErrorBoundry>.

#React #паттерны #обработка_ошибок
HTML: создаем звуки

Разберем работу со звуковыми файлами в HTML. Для этого есть семантический тег HTML5 - audio. Он заменяет устаревший flash простым, встроенным в HTML механизмом.

Тег предоставляет удобное API для работы через JS. Вот некоторые методы:

.play() - запуск проигрывания файла;
.pause() - понятно, зачем.

У тега есть и масса атрибутов, включая булевы, которые, естественно, можно цеплять в JS. Например, currentTime - текущее время воспроизведения. Его можно, например, обнулять при клике, чтобы каждый раз не дожидаться конца проигрывания.

#HTML5
Git: полезные мелочи

- git status -s выводит статус версий в сокращенном виде.

- git rm <file> ожидаемо удаляет файл из индексации и в целом из проекта. Если удалить файл другим способом, он останется в системе со статусом "changed, bit not updated". Команда принимает также регулярные выражения и паттерны путей.

- git rm -f <file> удаляет файл принудительно, даже после индексации.

- git rm --cached <file> позволит отключить отслеживание файла, сохранив его в папке проекта. Палочка-выручалочка, если что-то не внес в .gitignore.

- git mv <oldname> <newname> переименовывает файл, фактически удаляя и восстанавливая. Это поведение уже нам знакомо по unix-системам.

- git log --pretty с параметром fromat задает шаблон вывода лога. Новый формат задается строкой с параметрами вывода:
$ git log --pretty=format:"%h - %an, %ar : %s"
На JS эквивалент:
`${cuttedHash} - ${nameOfCommitter}`;

- git log (параметры pretty) —graph выводит историю ветвлений в виде графа - графической схемы. Наглядно и полезно для больших проектов.

#git #bash
Git: ограничения команды log

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

#git #bash
Хуки Реакта: что, зачем и как

Что:
Хуки - это новое АПИ для модных функциональных пацанов (с), которое позволяет отказаться от компонентов-классов. Преимуществом классов была возможность использовать локальное состояние, но с хуками добавлять state можно и в функциональны компоненты. Не путать с хуками жизненного цикла!

Зачем:
1. Переиспользуемость. В классических компонентах для разделения состояния использовали, например, компоненты-обертки. С хуками все проще: пишем логику функциями в отдельном файле, импортируем, вызываем. Всё.
2. Простота. Официальный туториал утверждает: для Реакт-разработчков сложно усвоить правила работы this в JS. Мои соболезнования компаниям, где работают такие девелоперы. Тем не менее, возня с привязкой this сократилась с упрощенной до отсутствующей.

Как:
Все просто. Создаем через деструктуризацию пользовательнкую переменную и метод обновления:

const [age, setAge] = useState(42);

...И применяем, как ранее в классах. О тонкостях, типа useEffect, позже.

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

#React #хуки
Хуки Реакта-2: useEffect

Герой заголовка - useEffect - так называемый хук эффекта. Под эффектом понимают действия, которые в компонентах-классах выполняются в методах жизненного цикла.

Собственно эффект - это функция, которую и цепляет на себя хук.

Хук эффекта объединяет возможности методов жизненного цикла: componentDidMount, componentDidUpdate, componentWillUnount. Это поможет объединить похожую логику, разбитую в классах по методам жизненного цикла.

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

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

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

useEffect(() => {
document.title = `Вы нажали ${count} раз`;
}, [count]);

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

useEffect можно использовать многократно в одном компоненте. Это позволит, например, разбить эффекты на те, что должны выполняться всегда, и те, что выполняются только при изменении значения.

#React #хуки
Channel photo updated
Проект Houdini: типизация кастомных переменных

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

root: {
--my-color: #fff;
}
(нативная CSS-переменная в глобальной области видимости)

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

Проект Houdini - новое API, предоставляющее доступ ко всем стадиям обработки браузером кода - предлагает решение. Из JS мы сможем регистрировать типы переменных:

CSS.registerProperty({
name: "--my-color",
syntax: "<color>",
initialValue: "black"
});

Теперь переменная --my-color принимает только значения цветов. Считывая тип, движок может выполнять больше действий с переменной - включая анимации.

В миру эта часть проекта Houdini называется CSS Properties and Values API. К сожалению, проект страдает от избыточной сложности и слабой поддержки браузерами. В будущем он поможет строить архитектуру веб-приложений гибче и оптимизированнее, ну а пока - просто достоин внимания.

#CSS #Houdini
Тонкости let и const

- Хотя константе нельзя присвоить новое значение, само это значение менять можно:

const x = [2,4,5];
x[0] = 6;
// массив в константе x изменится на [6, 4 ,5]

- Дважды объявить через let переменную с одинаковым именем в одной области видимости нельзя, а в разных - можно:

let x = 10;
const z = () => {
let x = 20;
console.log(x)
}
z()
// выведет 20

- Существует феномен Temporal Dead Zone - "временная мёртвая зона", появляющаяся, когда поток входит в лексическую область видимости, содержащую переменную, но еще не доходит до неё. Попытка обратиться к переменной в мёртвой зоне вызовет ошибку - в отличие от var, которая поднимается в самое начало блока и выводит undefined, если обратиться к ней до привязки.

const x = () => {
console.log(typeof z);
let z = 10;
}
x()
// выбросит ошибку

Любопытно, что обращение к let-переменной в более высокой области видимости до её инициализации с операцией typeof выведет undefined.

- При объявлении в глобальной области видимости var становится свойством глобального объекта window. Это небезопасное поведение изменили в ES6: let и const не связаны с глобальным объектом.

#JS
Английский язык: слова и грамматика

- to expand (гл.): расширять.
- warm-up (сущ.) - разминка.
- tense: время. Не путать с time: tense - концепция грамматики.
- expresses: выражает, высказывает.

Simple tenses имеют общий принцип: simple present говорит о чем-либо повторяющемся, постоянном, past и fututre - о конкретном, единственном случае.

Пример simple present:
"Pavel makes holywars about frameworks every day" - "каждый день Павел (обычно, постоянно, как правило) разжигает холивары про фреймворки".

А вот simple future:
"I'll make delicious jQuery pasta for you tomorrow, sweetheart" (завтра я приготовлю тебе аппетитную лапшичку на жиквреи, милая).

#english
Интернет-маркетинг: UTM-метки

UTM-метки - удобный инструмент аналитики трафика. Они прописываются в URI и состоят из пар ключ-значение:
utm_source=google

Ключей бывает всего пять:
utm_параметр. Значения могут быть произвольными и либо прописываются руками (в конструкторе URL), либо генерируются на стороне рекламной кампании.

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

Другой пример. Google Analytics воспринимает трафик из приложений как прямые заходы. UTM-метки отмечают этот трафик, и аналитик получает верную картину.

UTM-метки должны располагаться до "якоря" (#).

#аналитика #utm
Плагины Wordpress: лучшие практики

- Префиксы. Чтобы не было конфликтов имен, добавляем префикс - например, в виде названия плагина - везде, куда только можем.

- Проверяем наличие переменных, функций, классов и т.д. Используем if ( isset( $variable )) {}.

- Определяем переменные по возможности внутри функций.

- Правильно группируем файлы. В папке плагина в идеале должны быть два файла - plugin.php, uninstall.php. Остальное раскладывается по папкам languages, includes, admin->js,css,images (админка), public->js,css,images (фронт).

- Код, используемый в админке и во фронтенде, разделяем. Используем if ( is_admin() ) {}
SQL, манипуляция данными. Часть 1.

БД можно представить трехмерной фигурой из двухмерных слоев-таблиц, наподобие листов Excel. Сами слои состоят из ячеек. В ячейках - числа или строки.

SQL - язык гибкого взаимодействия с этой фигурой.

Пример простых взаимодействий с БД - выборка данных (SELECT) и вставка (INSERT). К слову, капслок в операторах - не более чем условность для простоты разделения операторов и оперндов. Сам я её соблюдаю, но и в lowercase все работает.

Сейчас рассмотрим выборку.

#SQL
SQL, манипуляция данными. Часть 2.

Возьмем пример выборки:

SELECT login, post_count FROM wp_logs WHERE post_count NOT BETWEEN 5 AND 9;

- SELECT: оператор, указывающий, что операция будет по выборке (а не вставке и др.).

- login, post_count: названия столбцов таблицы, которыми будет ограничена выборка.

- WHERE: условный ограничитель по значениям в таблице. В примере ограничены значения для столбца post_count.

- NOT BETWEEN: комбинация операторов NOT и BETWEEN. Без отрицательной частицы BETWEEN выбирает данные внутри множества, с ней - вне неё:

1) BETWEEN 5 AND 10 = {5...10}
2) NOT BETWEEN 5 AND 10: {∞...5} и {10...∞}

- AND: просто "И". Аналог && в си-подобных языках.

#SQL
SQL, манипуляция данными. Часть 3.

Числовые операторы SQL:

- стандартные нумерические операторы. != и т.п.
- (NOT) BETWEEN ... AND ... .
- (NOT) IN (...). В скобках листинг значений для выборки, в том числе отрицательной.


Строковые операторы:

=: точное совпадение, аналог ===.

!= или <>: отрицательное точное совпадение.

(NOT) LIKE: нечувствительное к регистру совпадение.

%: аналог *. в регулярных выражениях. Иначе говоря - выборка неорганиченного множества символов до или после операнда. Используется только с LIKE.

_ (нижнее подчеркивание): аналог *, или указатель одного любого символа. Только с LIKE.

[]: диапазон символов или последовательность.

[^]: исключающий диапазон.

(NOT) IN: то же, что с числами, но для строк.

Строковые аргументы обязательно обязательно заключаются в двойные кавычки: "mozilla".

#SQL