Архив недели @kirjs
Вторник
Всем привет, с вами @kirjs!
Я редко пишу в твиттер, и почти никогда на русском. Рад что есть возможность попробовать сделать все наоборот :)
Поговорим про:
🐜 Дебаггинг
🤯 Хорошие объяснения
🎤 Митапы и в разных странах,
🛠Инструменты для разработки
Я сейчас в Аэропорту, жду самолет в Львов 🇺🇦
Там я и мой коллега - Tyler Crowe выступим на митапе @GDGLviv.
🎤 Я расскажу что нового в Firebase
🎤 Тайлер расскажет как настроить оплату с stripe и firebase
meetup.com/GDG-Lviv/event…
Среда
Hey, everyone! The full #hacktoberfest site is now live and REGISTRATION for Hacktoberfest 2019 is OPEN! 📝 This year’s event is brought to you by @digitalocean and @ThePracticalDev! 💙 hacktoberfest.digitalocean.com 🔗
🔥Октябрь - время #Hacktoberfest 🔥
Можно получить футболку с лого 👕, создав в течение октября 5 PR в участвующие проекты!
Отличное время сделать первый (или не не первый) вклад в Open Source!
Кто уже участвовал? Кто будет участвовать?
В треде посмотрю какие issues есть... twitter.com/hacktoberfest/…
Начнем с нажатия большой фиолетовой кнопки, которая залогинит нас в гитхабе.
Ура, теперь я тоже участник #hacktoberfest!

И вот я уже в личном кабинете!
Поправка от @jabher, как видно на скрине, можно контрибьютить совсем в любые проекты, лишь бы на гитхабе.
У меня уже есть один PR и 20%, хотя по датам сделано в Сентябре

🐞Debugging🐞
Начну с консоли:
Есть мнение, дебажить с помощью консоли/console.log - "не круто", т.к. есть дебаггер.
На самом деле, это очень полезный инструмент, решающий многие задачи не хуже дебаггера.
Хорошее понимание консоли в сочетании с дебаггером - ключ к успеху
Вот примеры ситуаций где консоль очень полезна:
🦋 Простая ошибка - все понятно, надо быстро подтвердить
🦋 Ошибка в функции которая вызывается много раз, а ломается только один
🦋 Race conditions
🦋 Много рекурсий
🦋 Нужно одновременно следить за большим количеством частей кода
Посмотрим что умеет консоль. На странице в браузере нажимаем F12.
Про Console.log много писать не буду
Есть интересный прием: если вам важно знать, что именно выведено в консоль, вместо добавления второго аргумента, заверните первый в скобки:
console.log({a});

При дебаге массивов с большим количеством объектов:
сonsole.log(list) показывает массив в свернутом виде.
console.log(…list) отобразит все элементы, но при большом количестве будет очень тормозить.
Чаще всего лучший вариант - console.table()

Еще console.log не умеет показывать, какие свойства есть у функции. зато есть console.dir
function Camille(){ // code }
Camille.name = ‘Saint-Saëns’;
console.log(Camille); // ƒ Camille(){ // code }
console.dir(Camille); //

В некоторых проектах консоль - как мусорка
В консоли гибкая система фильтров:
⛔️ Hide Network - прячет сетевые ошибки
⛔️ Selected context only - прячет ошибки из расширений и других фреймов
⛔️ Нажав правой кнопкой на лог можно спрятать все логи файла (Hide message from...)

Чтобы отследить откуда именно была вызвана функция с определенными параметрами, можно использовать console.trace().
Из-за размеров стека современных приложений полезно совместить с console.groupCollapsed()
console.groupCollapsed();
console.trace('lol');
console.groupEnd();

В случае когда функция запускается много-много раз, а ломается только один, можно использовать:
console.assert(a, b);
Фактически это более короткий аналог
if(a){
console.error(b)
}

console.log поддерживает оформление вывода с помощью CSS:
console.log(‘%c Hi’, ‘color: red’); // Выведет Hi красным цветом
voidcanvas.com/make-console-l…
Интересно, как они ограничили доступные стили, интересные темы вроде position: fixed не работают.


Про консоль хватит, хотя там есть еще очень много крутого.
Домашнее задание: console.log(console) и посмотреть что еще там есть :)
Или developers.google.com/web/tools/chro…
Присылайте так же свои способы дебага (но только то, что можно вывести написав в коде, всякие $0 и $$ будут отдельно)
Тред (@kirjs)
Четверг
Спасибо за дополнение,
Если я правильно понимаю, TypeScript 3.7 не добавляет новую функцию assert, а позволяет существующим работать более эффективно.
Еще характерная черта - console.assert не кидает ошибку, и выполнение продолжается.
devblogs.microsoft.com/typescript/ann… twitter.com/geek_timofey/s…
@jsunderhood Вот для отладки race conditions я бы трижды поостерёгся использовать console. Он ооочень медленный и вносит огромный эффект наблюдателя. Лучше иметь на такой случай простейший логгер, который просто push'ит в глобальный массив по ходу сценария ошибки, а потом отдаёт его целиком.
Вот это интересный коммент, в целом похоже на правду, с другой стороны я не попадал в ситуацию где любой из этих факторов играл бы значимую роль.
Было бы круто, если у вас есть какая-нибудь история/пример на эту тему. twitter.com/shaukote/statu…
Продолжим тему дебага историей из реальной жизни.
Это случилось на проекте с Ангуларом, но самого Ангулара вы не увидите, и все техники используемые тут могут быть применены на любом проекте.
Можете попробовать воспроизвести тут:
github.com/codelab-fun/co…

При запуске тестов на проекте (на котором тесты не запускались очень давно), выпадала странная ошибка:
> npm test feedback
:ERROR [config]: File ./libs/feedback/karma.conf.js does not exist!
При этом сам файл существовал, например cat выводил его содержимое.

@jsunderhood У меня был другой баг. Писал тестовое. Подсчет показов. Взял с ли.ру js код. С ОТКРЫТОЙ консолью считало 2 раза показ потому что ...бой барабанов... не было favicon.ico. запрос был виден только на бекенде дополнительный в логах.
О да, прикольный баг 🔥 twitter.com/dmiboyko/statu…
Тут важно понимать, что (почти) все что, что запускается из npm, это обычный JavaScript, а значит код скорее всего лежит в папке node_modules.
Попробуем найти код отвечающий за это сообщение по части сообщения в папке node_modules

Нам повезло: результаты довольно однозначные, поэтому мы просто добавляем "debugger" перед выведением ошибки.
Когда мы запустим наше приложение в дебаг режиме, дебаггер остановится в этом месте и мы сможем разобраться - что именно тут происходит.

Пришло время взять в руки дебаггер! C node.js это немного посложнее чем с браузером, но ничего невозможного. Чтобы запустить node в дебаг-режиме, нам нужно добраться до .js файла, который запускается под капотом.
В package.json мы видим что "npm test" просто запускает "ng test"

Локальный бинарник ng лежит в папке node_modules/.bin, и это просто javascript файл.
Это значит что мы просто можем запустить:
node node_modules/.bin/ng test feedback
И получить тот же самый результат!

Добавим --inspect-brk, чтобы запустить nodejs в дебаг режиме:
$ node --inspect-brk node_modules/.bin/ng test feedback
При запуске nodejs остановится и подождет, пока мы присоединимся к нему дебаггером

Дебаггеры бывают разные, мы используем Chrome Dev Tools: в Chrome заходим по адресу: chrome://inspect/#devices
И видим снизу наш node процесс, нажав на который мы попадем наконец-то в дебаггер!

На самом деле есть альтернатива (Но еще не очень стабильная) всем этим сложным махинациям, можно использовать npmjs.com/package/ndb
npm i -g ndb
ndb npm test feedback
Так или иначе, мы уже в дебаггере. Теперь разберемся как он поможет нам починить баг.

На этой драматической ноте я пойду посплю, потому что болею, и у меня по ходу температура 😫
Когда я вернусь расскажу почему карма выдает такое странное сообщение и как это можно починить.
Пятница
Ок, посмотрим что тут происходит:
Мы находимся файла config в karma.js
Функция в которой мы сейчас - parseConfig - получает конфиг для тестов
Карма пытается получить (require) fileConfigPath. По ходу будет выброшена ошибка, которая будет соответствовать двум критериям:

Тип ошибки - MODULE_NOT_FOUND
В сообщении ошибки - fileConfigPath - путь файла который мы пытаемся получить.

В образовательных целях давайте попробуем поймать эту ошибку.
Для этого нам нужно остановиться ДО require(...). Чтобы это сделать:
Поставим точку останова (breakpoint) на строке 351
Перезапустим скрипт из терминала

Убедимся что все гуд:
Мы Остановились на нужной строчке
до require()
Теперь:
3) Включим остановку при выбрасывании ошибки
4) Поставим галку, чтобы мы остановились даже если ошибка внутри try/catch
5) Поехали!

Вот наша первая остановка 🔥
Мы где-то внутри cjs (closure js) загрузщика модулей node.js. Глубоко!
Ошибка "Cannot find module '../../karma.conf", не совсем то, что мы ожидали
Код подходит под ожидание
Прежде чем мы посмотрим message, глянем в стэк вызовов:

Мы пришли сюда из кармы, parseConfig, как и ожидалось.
Также мы видим в стеке вызовов karma.conf.js, по ходу это и есть наш "Несуществующий файл"
Заглянем туда, нажав на соответствующий вызов

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

Ок, вернувшись в начала мы:
Убедимся что это та же самая ошибка.
Вроде код и сообщение совпадают.
Единственно что не понятно, как получилось так, что e.message содержит в себе имя файла?
Давайте посмотрим на e.message

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

Возвращаемся в код загрузчика и видим что стек добавляется в сообщение вручную.

резюме:
Карма ловит ошибку при загрузке конфига и делает две проверки:
code === MODULE_NOT_FOUND
✅ Верна для всех вложенных ненайденых модулей
message.includes(configFilePath)
✅Верна для всех вложенных ненайденых модулей, т.к. configFilePath в стеке вызовов

Что делать дальше?
В целом понятно как починить это локально - убрать сломанный require
Это 100% баг кармы, надо починить и там, чтобы сэкономить время другим людям. В тот момент я выбрал создать issue а не PR, т.к. не было времени. Вот оно: github.com/karma-runner/k…
Через пару недель кто-то сделал PR (github.com/karma-runner/k…).
Вместо добавления новых условий они просто убрали существующие и стали выводить непосредственно ошибку:

На этом детективная история со счастливым финалом закончена!
Спасибо всем кто прочитал до конца 🔥🔥🔥
У меня заняло примерно в 5 раз больше времени написать про этот баг чем починить :)
Тред (@kirjs)
Напоминаю всем, что в вашей операционной системе скорее всего есть emoji picker, который можно вызвать с клавиатуры:
🦋 На маке - control + ⌘ + space
🦋 На винде: Win + ,
🦋 Ubuntu - right click + insert emoji

🤯 Про хорошие объяснения 🤯
Хорошо объяснять очень сложно.
Хорошо объяснить как хорошо объяснять - еще сложнее.
Для хороших два главных правила:
Подготовиться заранее
Много тестов на людях
В этот раз придется импровизировать, так как времени не очень много
Почему именно я рассказываю про хорошие объяснения?
Все мое детство я ненавидел школу потому что никто не мог ничего нормально объяснить. Все объясняли как, но не "зачем".
Я любил математику и всегда получал плохие ошибки, и мне всегда очень хотелось как-то исправить ситуацию
Поэтому я трачу много времени на объяснения:
🦋 3 года преподавал в школе основы программирования
🦋 При выступлениях делаю упор именно на объяснения
🦋 Провожу много времени, объясняя друзьям всякие сложные концепты.
В целом, я не профессиональный объяснятель, но опыт есть
Мне кажется, при объяснении, важно четко знать ответ на три вопроса:
Что я хочу
Что хочет тот (те) кому я объясняю
Как именно воплотить наши желания в реальность
Вот (очень-очень грубый) пример того, что возможно могло бы происходить в школе:
Препод - хочет получить зарплату, и чтобы не напрягало
Ученик - хочет играть в компьютерные игры
Как это решается сейчас многие видели в школах, хорошие объяснения не нужна
Вот тут мы изменим одну переменную:
Препод - хочет получить зарплату, и чтобы не напрягало
Ученик - хочет выучить предмет
Ученику придется учиться (иногда с помощью препода, иногда самому/самой)
Школы бывают разные, есть неплохая книга - amazon.com/Case-against-E… - которая о том, что школы не обязательно об обучении и знаниях
Но, возвращаясь к хорошим объяснениям - они могут случиться только когда они в интересах обоих сторон
Возьмем другой пример: Call For Proposals на конференции.
Люди отправляют краткое описание выступления, которое они готовы предложить конференции.
Организаторы выбирают наиболее интересные.
Выступающие получают билет на конфу, возможность выступить (часто оплаченную поездку)
Это в принципе квинтэссенция объяснений: надо вместить (полу)часовое выступление в несколько строчек.
Организаторы конфы хотят:
🦋 Знать что тема интересная и релевантная
🦋 Будет рассказана хорошо
🦋 При этом они затратят минимальное количество времени (там еще 999 пропоузалов)
Потенциальные выступающие хотят... много чего, но из общего скорее всего:
🦋 Попасть на конфу
🦋 Поделиться важной для них темой
Вот пример структуры proposal, который соответствует ожиданиям:
Глоканье куздр используется в 98 из топ 100 сайтов (почему это важно)
Я глокал куздр еще до того как это было модно.
(Почему вы)
В этом выступлении я покажу как глокать еще ште́кей
с помощью бокра
(чего ждать)
Если вам нужно объяснить то же вашей бабушке, то скорее всего она просто хочет убедиться что у вас в жизни все в порядке и вы заняты чем-то полезным и ей вы скажете что-то вроде:
"Я расскажу о технологии которая называется Глоканье которую используют везде в интернете"
Если вам нужно написать твит про это, то важно понимать кто ваша аудитория, если 80% ваших твитов про глоканье, скорее всего вы напишете что-то вроде:
"🔥🔥🔥 Приходите посмотрите, как на конфе ХХХ я буду глокать с помощью бокра!! "
Я столько про это пишу, потому что зачастую вижу, что люди которые выступают просто не задаются этими тремя вопросами.
Просто фигачат как подготовились не глядя на контекст и окружение, а это важно.
Если нам повезло: мы хотим объяснить, а другая сторона хочет понят. время самого интересного
Тут важно понимать, что хорошее объяснение - только часть успеха.
🦋Человек может все понять и забить на выученное
🦋Или непонять ничего, но разобраться в дома и этому свою жизнь
Тред (@kirjs)
🔥Правило хороших объяснений #1: 🔥
Начинайте сразу с интересного.
Для презентаций есть так называемое "правило одной минуты" - в течении минуты должно понять о чем речь и что нас ожидает.
Бывают презентации, где после минуты знаешь что выступающий любит путешествовать
В следующий раз когда будете смотреть техническую презентацию, рекомендую обратить внимание на первую минуту.
Я в своих презентациях вообще не представляюсь и перехожу сразу к делу (хотя это оверкилл и не помогает создать раппорт).
Вот пример не технического выступления (не связанного с объяснением, но очень рекомендую).
youtube.com/watch?v=-vZXgA…
С первых секунд начинается релевантная история и интересно смотреть дальше.
Вот пример, тут видео всего 4 минуты, но ни секунды не потрачено:
youtube.com/watch?v=u9m8ku…
А вот первое видео, которое мне посоветовал youtube:
В течении минуты мы не узнали ничего чего бы не было в описании.
youtube.com/watch?v=d_m5cs…
Наверняка это отличное выступление, но правило первой минуты оно не прошло
Вот пример из другой вселенной и формата:
Объяснения Hello world на с++
Из 8 строк релевантна только одна, остальные 7 наводят ужас на начинающих, и для первого примера могли бы быть пропущены.
Тем не менее автор показывает их и пытается объяснить часть из них:

Тред (@kirjs)
🔥Правило хороших объяснений #2: 🔥
Не учите пользователя решать задачи которых у пользователя нет
Очень часто вижу презентации, в которых много отличных и умных решений, но непонятно зачем они нужны
Такое очень часто происходит в школах и универах: на ученика просто вываливается куча знаний без каких либо попыток объяснить зачем это нужно.
Если у пользователя уже есть задача - помогите ее решить, если нету - создайте, заинтересуйте и уже после этого предлагайте решение
Под горячую руку попался @matvi3nko, он только что выложил свои слайды с @Heapconf (slideshare.net/NikolayMatvien…)
на первом же слайде после интро описывается проблема:
Serverless очень популярен
Не все умеют его готовить и иногда приходится платить больше
Дальше - решение

🇵🇱🇵🇱I just landed in Warsaw airport 🇵🇱🇵🇱 I have 18 hour layover and 0 plans. Probably going to just go see the city Anybody's not busy and wants to hang out?
🇵🇱🇵🇱 Я только что приземлился в аэропорту Варшавы🇵🇱🇵🇱
У меня пересадка на 18 часов и никаких планов, скорее всего просто пойду посмотрю город.
Если кто-нить на занят и хочет пообщаться - пишите! twitter.com/kirjs/status/1…
Суббота
Мы, человеки, тоже представляем набор API.
Только он плохо документирован, на идемпотентен, не всегда работает и постоянно меняется.
🦋Минутка истории🦋
В далеком 2007 (ЖЖ!), Леонид Каганов выложил в блоге личностный тест Виконт
Ответив на на несколько вопросов, можно было получить результат как на картинке.
Быть лидером (в отличии от большинства) - приятно.
Тысячи выложили результат в своих журналах

Однако не все было так просто.
С помощью cookies, сервер отдавал картинку из первого поста только автору журнала.
Всем же остальным отправлялась совсем другая картинка:

В результате весь рунет пестрел картинками "Я лох", что провоцировало еще больше юзеров выложить свои "позитивные результаты"
Вот статья от автора:
lleo.me/dnevnik/2007/0…
Техническое описание:
lleo.me/dnevnik/2007/1…
Воскресенье
Ок, я вроде все
Это был очень крутой опыт, всем спасибо за коменты, я сам много нового узнал.
Отдельное спасибо:
@amel_true - За активность и знания
@_vovakulikov - За поддержку :)
@slowcfg - За линк на "Плач математика"
@aslushnikov - За то что залез в код dev-tools
✨Как поймать всплывающее окошко в Dev Tools ✨
Использовать горячую клавишу (F8) для остановки выполнения JS ⏸
🥔В ролях: Психованная картошка (@PavukSenya)

Казалось бы, вы успешны в своей профессии, но все равно не уверены в себе, и чувствуете, что недостаточно хороши, а все вокруг умнее вас?
🦋Знайте что синдром самозванца реален: meduza.io/cards/pochemu-…
🦋Не стесняйтесь обратиться за помощью к специалисту (даже в России)

Вы успешны в своей профессии, уверены в себе, может даже слишком хороши, и у вас некогда не было синдрома самозванца?
🦋Задумайтесь, возможно вы просто не выходите из зоны комфорта?
🦋(С другой стороны здоровая доза самоуверенности это хорошо, может у вас реально все 🔥)

🔥Хочу быть ментором 🔥
Ищу кого-нибудь, у кого есть:
🦋 Несколько часов свободного времени в неделю
🦋 Желание сделать первый (или не первый) вклад в Open Source
🦋 И чутка (или дофига) понимания Angular/TypeScript + интерес углубить знания?
Со своей стороны:
🦋 Найду issues разной сложности на своем проекте
🦋 Объясню issues и помогу начать писать код
🦋 Проведу code-review разной степени жесткости
🦋 Попробуем сделать из этого выступление на локальном митапе
Я скэйлюсь не оч хорошо 👫Ищу 2х человек (3 макс)
@jsunderhood Так это обычная работа опенсорс ментейнера - помечать issues лейблами, в issue понятно описывать требования и отвечать на вопросы. Code review пулл реквестов в любом случае придётся делать - неважно менторите или нет. Я бы RxJS подтянул.
В целом да, кроме того, что не с каждым open source мейнтейнером можно можно обсудить issue лично. twitter.com/alteregor_/sta…
🔥Хочу быть ментором 🔥 Ищу кого-нибудь, у кого есть: 🦋 Несколько часов свободного времени в неделю 🦋 Желание сделать первый (или не первый) вклад в Open Source 🦋 И чутка (или дофига) понимания Angular/TypeScript + интерес углубить знания?
🔥Нужны менторы 🔥
Ок, хелп! Уже шесть человек ответило на мой пост, меня на столько не хватит.
Если вы работаете с Angular в Open Source, и можете помочь 1-2 человеку начать контрибьютить, напишите в комменты пожалуйста.
twitter.com/jsunderhood/st…
✨Кому c++ ментора? ✨
Понедельник
Эту неделю с вами был @kirjs 😀 Не забываем что @jsunderhood это коллективный аккаунт и моя неделя подошла к концу, буду рад видеть вас у себя ;)