Дивовижний світ веброзробки – Telegram
Дивовижний світ веброзробки
2.91K subscribers
83 photos
7 videos
1 file
183 links
Дивовижний світ веброзробки — тепер і в твоєму телеграмі. Анонси відео з YouTube-каналу «Сергій Бабіч та Дивовижний світ веброзробки», стріми, авторські статті та цікаві знахідки.

youtube.com/@babichweb

Реклами та інтеграції обговоримо
Download Telegram
Що ж це за задача, рішення якої принесло мені днями стільки задоволення, що я аж цілий допис написав про це відчуття?

Ось вона — на ілюстрації до допису. Треба було зробити картку з динамічним лейаутом, де ширина першого елемента дорівнює найширшому з усіх, а висота самої картки — динамічна. Картки мають тягатися драг-н-дропом, при цьому використовуються наші внутрішні компоненти з дизайн-системи, які додають кілька обгорток, а сам вміст вставляється вже вглиб.

Очевидно, що таблиця не підійде (але я б її не взяв і так). Тому вибір очевидний — CSS Grid.

Отут постає кілька вимог, які дещо можуть завадити швидкій та наївній імплементації:
ширина першої колонки — спільна, бо там номер картки;
висота — довільна, однак grid за замовчуванням має однакові рядки;

І тут я згадав про subgrid:
.container {
display: grid;
grid-template-columns: min-content 1fr;
}

.card {
display: grid;
grid-template-columns: subgrid;
}


Тут нюанс — якщо між головною сіткою і "наслідувачем" є обгортки, їм усім треба так само “прокинути” цю сітку:
:where(.wrapper-1, .wrapper-2, …, .wrapper-n, .card) {
display: grid;
grid-template-columns: subgrid;
}


І тоді сітка буде спільна для усіх елементів, незалежно, як вони між собою вкладені. Але лишається ще одне — динамічна висота картки. Тут мені трошки довелося подумати, але рішення виявилося настільки ж елегантним, як і простим:
.card {
height: max-content;
}


Voila! — картки в сітці кожна має свою власну висоту!

І от коли все стало на свої місця, клацнуло як останні детальки LEGO, от тоді я й відчув ту мимолітну ейфорію, про яку писав.

Адже задоволення можна отримати не лише, якщо займатися тривалим, кхм, кодингом, а й тоді, коли вдається вирішити задачу в простий, проте елегантний спосіб, замість городити складне заради самої складности, рішення.

🔔 Тим часом розіграш квитка на DOU Day усього за 500 грн відбудеться уже сьогодні ввечері! Тож не зволікайте, аби не впустити таку нагоду!

@babichdev

.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥498👏8
Розіграш завершено!

(оновлено о 18:02)

Друзі, банку розбито, переможця визначено, і квиточок сьогодні вже буде у нього.

Дякую усім, хто долучився, разом ми зібрали і наблизили збір до завершення ще на 25 642 гривні!

Гарного усім вечора!
🔥12
#цього_тижня

Зазирнули по той бік ViewTransition у React і зʼясували, що це всього-на-всього обгортка над браузерним View Transition API.

— Познайомилися з атрибутом inert, який дозволяє зробити елемент видимим для ока, але невидимим для всього іншого.

— Розібрали, чим корисний метод Element.matches() і чим він відрізняється від Element.closest().

— Я поділився, які маленькі речі приносять мені справжнє задоволення в коді.

— А наступного дня показав, який саме код надихнув мене на попередній допис.

А ще — разом з вами ми зібрали 25 642 грн на користь ЗСУ!

Який із дописів цього тижня сподобався вам найбільше? Напишіть у коментарях 👇

👍@babichdev

.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥266👏4
Що приховують три крапки?
Вітаю, друзі! Сьогодні розповім вам про деякі неочевидні підводні камені так званого spread-оператора. Я сподіваюсь, ви вже в курсі, для чого він існує, тож перейду відразу до прихованих нюансів.

Порядок важливий
Коли ви "підмішуєте" обʼєкт, то значення будуть застосуватись в порядку додавання в новий обʼєкт:
{ a: 1, b: 2, ...{ b: 3 } } // { a: 1, b: 3 }

{ ...{ b: 3 }, a: 1, b: 2 } // { a: 1, b: 2 }


Останнє входження ключа перезаписує попереднє. Spread — це не злиття, а послідовне копіювання полів з обʼєктів у новий.

undefined в масивах і обʼєктах
Ви спокійно можете розгорнути той же undefined або null в обʼєкт, а от з масивом такий трюк не пройде.
{ ...undefined } // {}

[...undefined] // 💥 TypeError


Усе через те, що масив вимагає, аби вхідний обʼєкт був Iterable, тобто такий, яким можна пройтися з Symbol.iterator, і nullish значення, очевидно такими не є. А от звичайний обʼєкт не такий вибагливий, і йому достатньо будь-якого значення, до якого можна застосувати Object.keys. У випадку з null та undefined цей метод просто поверне порожній список.

Object ⇄ Array? Ні.
Рівно з тієї самої причини ми можемо розмазати масив в обʼєкт, але не можемо зробити навпаки:
[...{ a: 1 }] // 💥 TypeError: object is not iterable

{ ...[1, 2] } // { 0: 1, 1: 2 }


Spread у масиві очікує ітерабельність — тобто наявність Symbol.iterator. Обʼєкти цього не мають (за замовчуванням), тому розгортання летить з помилкою.

Натомість spread в обʼєкті потребує лише перелічуваних властивостей. А масив — це просто обʼєкт із числовими ключами, які чудово підходять під це визначення.

... не любить порожнечі
const a = [1, , , , 5]; // [1, empty × 3, 5]
const b = [...a]; // [1, undefined, undefined, undefined, 5]

console.log(1 in a); // false
console.log(1 in b); // true


Spread-оператор не просто “копіює” масив — він перетворює його дірки на явно присутні undefined.

У масиві a на індексах 1, 2, 3 немає значень — це так звані дірки (sparse elements). Але при ...a вони ущільнюються: JavaScript вставляє на їхнє місце undefined, і ці індекси стають реально присутніми в структурі масиву.

... не копіює вміст обʼєкта
Технічно. Він поверхнево копіює перший рівень масива або обʼєкта. І якщо там примітивні значення, то можна сказати, це "копія". Але якщо є вкладеності, то ... скопіює посилання на них, а не зробить клоновані копії.
const original = {
value: 1,
nested: { deep: true },
};
const copy = { ...original };

copy.nested.deep = false;
console.log(original.nested.deep); // false


А ще ... копіює виключно перший видимий рівень. Тобто прототип, неперелічувані властивості, символи — усе піде під ніж, і ви отримаєте стерильну копію.

***
Якщо дізналися щось нове — напишіть у коментарях, що саме здивувало чи стало у пригоді.

А далі — обирати вам! Про що буде наступний допис?


🔥 — Дірки в масивах: як вони зʼявляються і що ламають
❤️ — Symbol.iterator: ітерабельність під капотом
🤔 — Чи настільки різні масиви та обʼєкти?

@babichdev
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6043🤔23👏2
Порожнеча дивиться на тебе.

Масиви в JavaScript мають одну цікаву особливість — вони можуть бути "дірявими". Якщо дуже коротко — ми можемо явно присвоїти значення будь-якому індексу, і якщо цей індекс не є наступним після останнього значення, то утвориться розрив.
let arr = ['one', , 'three'];
// ['one', empty, 'three'];

arr[100] = 'value';
// ['one', empty, 'three', empty × 97, 'value']


Дірка — не undefined! Хоча при звертанні до "дірки" вам і поверне undefined, насправді в самому масиві його не буде. Дірка означає повну відсутність значення за індексом, він просто не ініціалізований. Це випливає з того, що масив — це підвид обʼєкту, просто з певним інтерфейсом для впорядкування ключів.

По факту, масив з діркою, наприклад той самий ['one', ,'three'], у обʼєктному записі виглядатиме так:
{ 0: 'one', 2: 'three' }

Індекс 1? Його просто немає.

Дірява поведінка
Дірки поводяться по своєму, і не завжди передбачувано. Візьмемо до прикладу масив [1, , 3] та порахуємо квадрати його значень:
[1, , 3].map(x => x * x) // [1, empty, 9]


А тепер точнісінько такий масив, але замінимо дірку явним undefined:
[1, undefined, 3].map(x => x * x) // [1, NaN, 9]


Помітили різницю? Так от, map, forEach, filter, reduce, every, some просто ігнорують дірки, перестрибують їх. А for...of, for навпаки — зазирнуть у кожну дірочку.

А JSON.stringify взагалі перетворює дірки в масиві на… null.

До речі, як визначити, що це саме дірка, а не просто undefined? Перевірити наявність індекса в масиві. Якщо ключа немає, то це — дірка:
const arr = ['one', , 'three'];
1 in arr; // false


Дірка як палиця в колесі.
Така поведінка, очікувано, може призводити до багатьох дивних ситуацій, особливо при клонуванні чи порівнянні масивів. Ще більше збиватиму з пантелику той факт, що [].length віддає не фактичну кількість ключів, а "найбільший індекс + 1", що теж не додає впевнености при роботі з дірявими масивами.

Також JavaScript рушії не дуже полюбляють діряві масиви, бо робота з ними вимагає відмови від багатьох оптимізацій, які можна застосувати до безпереревних масивів. Я не буду вдаватися в деталі, лише зазначу, що це дійсно впливає і на споживання памʼяті, і на внутрішню швидкодію. Звичайно, ви не помітите різниці на масиві з десятком дірок, але якщо їх 100 000, 1 000 000, то втрати будуть відчутні.

Заштопати всі дірки!
Найочевидніша порада — не допускайте дірок. Якщо вам потрібна подібна структура, краще використати обʼєкт з власним ітератором. Якщо ж в руки потрапив такий масив, то його краще ущільнити: чи то зібрати лише реальні значення в інший масив, чи то заповнити дірки явним undefined — у будь-якому разі рушій вам подякує, а потім подякуєте і ви собі.

💬 А ви стикались із дірками в проді?
Чи, може, самі колись ненароком залишили? Поділіться досвідом у коментарях!
І якщо було цікаво — не забудьте поширити допис або кинути лінк колезі.


🔗 @babichdev
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7118👏3🤔2
Виграти квиток на JavaScript fwdays'25 усього за сто гривень? Та легко!

Товариство, хто ще не придбав квиток на конференцію, але дуже хочe туди потрапити? Маєте шалену нагоду виграти один з двох Full Ticket квиточків та відвідати цю чудову подію і зустрітися з, до прикладу, Іллєю Климовим, чи Юрієм Артюхом. Ну і я десь там пробігатиму.

Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.

Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.

Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u

Номер картки банки
4441111125077309

Переможців оберу наступної середи, 20 травня, рандомом від monobank.

@babichdev

в коментарях є фото листа-прохання
🔥64
Синьйор мусить знати все!
Ні. Не все.

Радше так: синьйор не має знати напамʼять увесь MDN. Як і мідл. Як і джун. Як і техлід. Взагалі, розробник не має знати всього напамʼять — це не показник експертности.

Розробка — це не контрольна робота. Це не про “знаєш або не знаєш”. Це про вміння орієнтуватися, коли стикаєшся з новим. Про вміння формулювати запит, знайти джерело, зрозуміти, перевірити, застосувати. Це — робота з невизначеністю.

Так, є база, без якої нікуди, і яка постійно змінюється. Є зони відповідальности. Є глибина, яку справедливо очікують від розробника певного рівня. Але навіть у синьйора в голові не вміщається весь Intl API, увесь Grid, або всі edge-кейси WebRTC. І це — нормально.

Найкращі розробники, з якими я працював — не ті, хто “все памʼятає”. А ті, хто не втрачає холодної голови, коли чогось не знає. Хто знає, як і де шукати. Хто не боїться питати. І хто не знецінює себе за пробіл — бо знає, що пробіл не означає порожнечу.

Коли я не знаю щось на співбесіді — це не провал. Це точка росту. Коли забуваю щось на етері — це не соромно. Це звичайний обсяг людської памʼяті, а не причина знецінювати себе.

Знання — це не інвентар, який мусить бути повним.
Це навичка працювати з невідомим.
Уміння рухатись уперед, навіть коли карти в голові ще не розкладені.

Між “я не знаю, як дізнатися” і “я не знаю, але розберусь” — ціла прірва. І справжній фахівець — це той, хто цю прірву давно перейшов.

Ти не мусиш усе знати.
Ти мусиш вміти дізнатися.


💬 А ви як ставитеся до моментів, коли чогось не знаєте?
Чи було таке відчуття, що «мусив же це знати!» — і що з ним робили?

P.S. На fwdays за 100 гривень?! Це можливо взагалі? Я кажу — так!

🔗 @babichdev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11237👏6
А сьогодні я на DOU Day ) Тож хто тут ще є — підходьте, будем робить селфіки і обмінюватись контактами ;)
🔥6411
Навіщо ходити на конференції та мітапи?
Хтось скаже — там обовʼязково треба слухати доповіді й набиратись нових знань. Хтось — що доповіді не важливі, а треба виключно нетворкатись. Хтось узагалі мовчки лутає мерч зі стендів партнерів.

А я вам скажу — на конференціях треба займатись усім! Якщо вас не дуже приваблює тема доповіді — сміливо йдіть пити каву та знайомитись. Втомились від розмов — ласкаво просимо до зали, там якраз виступає Бабіч. І не забудьте пробігтись партнерськими “будками” — там, окрім стікерів, шкарпеток та іншого дрібʼязку, іноді розігрують класні подарунки в обмін на ваші повні контакти, включно зі скрином з Дії. Але без жартів: саме на стендах я познайомився з багатьма HR, PR та рекрутерами, з якими досі спілкуємось. Одне таке знайомство навіть принесло мені роботу.

Спікер не образиться, якщо ви не прийдете на його доповідь (хіба скажете йому це в очі). Ба більше, я й сам відвідую від сили третину виступів своїх колег (включно зі своїм, свій ще жодного разу не пропускав). А решту часу — спілкуюсь, тусуюсь, обношу будки, з радістю фоткаюсь з учасниками.

До речі, ніколи не соромтесь зловити спікера й поставити питання (ну хіба він стрімко мчить до вбиральні й уже по виду ясно, що тисне на очі). Ми для того й виступаємо — щоб зацікавити. Якщо щось незрозуміло, або маєш свою точку зору — навіть протилежну — спікер з радістю приділить тобі хвильку.

Просто ми всі — енергетичні вампіри. Харчуємось вашими позитивними емоціями, а конференції для нас — це гастрономічні фестивалі.

Жартую (чи ні). Беріть від таких подій максимум: дізнавайтесь нове, знайомтесь, тусіть — і, по можливості, завжди потрапляйте на неофіційні пре- та афтепаті (але носіть із собою бетаргін).

Хто з вас був на моїй доповіді на DOU Day? Діліться відгуками в коментарях!

@babichdev

***
До речі, вже цієї суботи я виступатиму на JavaScript fwdays’25, і у вас є шанс виграти один із двох квитків на цю подію. Що треба зробити? Задонатити від 100 гривень та покластися на удачу!
51🔥21👏4
Чи готові ви читати серії пов'язаних постів протягом, наприклад, кількох тижнів, замість різних "випадкових" фактів, чи вам краще таке прочитати за один раз у вигляді великої статті?
(хочу розповісти про Goog Enough Code, тему мого иступу на DOU Day)
Anonymous Poll
80%
Так
13%
Так, якщо пости не поспіль
7%
Ні
8
Good Enough Code. ч.1
Код на відчепись, чи відчепіться від мого коду?


У кожного був цей момент: задачу закрито, ревʼю пройдено, усе працює — але щось свербить. Може, ще трохи підчистити? Перейменувати функцію? Винести шматок у модуль? Просто, щоб було "красивіше".

Так ось це і є зіткнення перфекціонізму з "достатністю" — і саме тут починається наша розмова про Good Enough Code.

Good Enough Code — це не "аби працювало". Це не код "на відчепись". Це підхід, у якому рішення достатньо хороше, щоб працювати, не створювати надмірний технічний борг і не витрачати зайві дні на причесування уже робочого коду. Це про точку, за якою зусилля на покращення вже не виправдані вигодою.

У реальності більшість задач — це не архітектурні шедеври, а практичні компроміси. І намагання зробити "ідеально" часто шкодить більше, ніж допомагає. Час іде на дрібниці, фідбек затримується, команда буксує в ревʼю. Продукт стоїть. Користувач чекає.

Парадоксально, але заради якості ми нерідко жертвуємо користю. І саме підхід GEC повертає фокус туди, де він має бути — на цінність.

Хороший код — це той, що вирішує задачу по суті, читається та підтримується без пояснювальної бригади, не ламається при зміні й дозволяє рухатися далі. Не ідеальний, а достатньо хороший, щоб не зупиняти розробку.

В той же час це не виправдання ліні. Це усвідомлений вибір, коли ти розумієш, де точка diminishing returns, що вигідніше бізнесу, і куди справді варто спрямувати свою енергію.

Бо в щоденній розробці виграє не той, хто пише красиво. А той, хто доставляє результат — і вміє вчасно зупинитись.

Зацікавило? Тоді ставте вподобайки і діліться з друзями!


І якщо цей допис набере понад 150 реакцій та 1000 переглядів, то у наступних дописах ми з вами обовʼязково розглянемо:
– Як відрізнити достатній код від халтури?
– Які критерії “good enough”?
– Чому перфекціонізм — це теж технічний борг?
– Як впровадити цей підхід у команду й не перетворити все на безконтрольну лінь?


#good_enough_code #мислення_розробника

100 гривень на РЕБ — квиток на fwdays

@babichdev
200🔥49🤔4👏3
Друзі, у вас лишається лише доба на те, аби взяти участь у розіграші одного з двох Full Ticket квитків на JavaScript fwdays'25!

Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.

Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.

Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u

Номер картки банки
4441111125077309

Переможців обиратиму уже завтра, 21 травня, рандомом від monobank.

@babichdev
🔥9
То null це обʼєкт чи не обʼєкт?!
Певен, ви не раз натрапляли на чергову добірку "приколів" в дусі "ха-ха, JavaScript тупий", в якій точно була згадка про те, що typeof null === 'object'. Хоча насправді null не object. Правда, тупо?

На перший погляд. Але якщо копнути глибше, виявиться, що null це null, а причина такої поведінки typeof захована у глибині віків.

У ранній реалізації JavaScript оператор typeof не мав окремої перевірки на null. Він просто дивився: чи значення схоже на обʼєкт — тобто, чи є посиланням у памʼяті (pointer). А null тоді представлявся як 0x00 — класичний null pointer. Не буквальний, як у C, але концептуально споріднений: “порожнє місце”, що колись мало би бути посиланням.

І через те, що typeof не заглиблювався в перевірку, а лише умовно питав: «Чи це посилання?», то 0x00 сприймалося як “так” — і typeof null повертав "object".

Цю поведінку закріпили в ECMA-262, і пізніше вже не змогли виправити — занадто багато коду залежало від цього “багу”. А Брендан Айк прямо назвав таку поведінку помилкою: (1)

I said typeof null == “object” was a mistake because code that condition guards must null-test before dereferencing


***
Ну а тепер — “ок, а нашо це нам?”. А ось навіщо: ця поведінка лишається актуальною. І банальна перевірка:
if (typeof x === 'object') {
x.foo();
}


…пропустить null. І при звертанні до foo зловите класичний Uncaught TypeError: Cannot read properties of null.

Тому при перевірці на обʼєкт варто додавати й перевірку на "не null":
typeof x === 'object' && x !== null


Ось такий цікавий "баг"-стандарт, що старіший за більшість сучасних веброзробників.

А ви стикалися з ним на практиці? Скільки ночей коштував вам пошук, чому код постійно падає від "Uncaught TypeError…"? Діліться в коментарях!

P.S. Так, так я знаю про оператор ?. і сам активно ним користуюсь. От набере цей допис 101 вподобайку, тоді й розглянемо, чи є цей оператор панацеєю від усіх null.

***
Останній шанс виграти один з двох Full Ticket квитків на JS fwdays'25! Долучайся, донать 100 гривень і вигравай!

@babichdev
155🔥31🤔7👏5
Вітаю переможців розіграшу!

А також дякую усім, хто долучилися до цього збору. Разом ми зібрали 22 728 гривень!

Дякую ще раз, і до зустрічі уже цієї суботи!

З переможцями звʼяжусь щойно отримаю контакти.
24
Good Enough Code. ч.2
GEC ≠ халтура

[ч.1 | ч.3]

Часто можна почути: мовляв, “достатньо хороший код” — це просто красива назва для того, щоб зробити абияк. Проте, це не так.

Good Enough Code — це не про недбалість. Це про свідомий, зважений вибір з розумінням наслідків та прийняттям відповідальности за ці наслідки.


Халтурний код — це той, що погано читається, складний для змін, не має тестів і не витримує навіть базових вимог до якості. Він створює ризики, накопичує технічний борг і гальмує команду та продукт.

Good Enough Code, навпаки, спирається на здоровий інженерний розрахунок. Це рішення, яке працює на користь продукту: виконує свою задачу, не створює проблем у майбутньому й дозволяє рухатися далі. Без надмірної витрати часу на деталі, що не принесуть суттєвої додаткової цінності.

Як відрізнити достатній код від халтури?
Ключ — у мотивації та наслідках. Халтура — це “аби відчепилися”, без розуміння впливу. GEC — це “зроблено достатньо добре для цієї задачі”, з розрахунком на підтримку, ризики й фокус на результат.

І ось тут треба зрозуміти найголовніше: "достатньо добре" не існує без контексту.

GEC це не універсальний стандарт якості, це про відповідність якості обставинам:

– Якщо це скрипт, який разово пройде по CSV-шці для маркетологів — “достатньо” може означати “працює, не падає, зроблено за 20 хвилин”.

– Якщо це MVP — enough це коли ви можете за дві хвилини показати користувачеві цінність.

– Якщо ж ви пишете код для кардіостимулятора — “достатньо” означає верифікацію, сертифікацію та бездоганність.

Good Enough Code — це не компроміс заради компромісу. Це розуміння, де саме пролягає межа між "ще треба доробити" та "вже не має сенсу".

Цей підхід не про зменшення відповідальності, навпаки, він про її збільшення. Він про конкретний фокус в конкретний момент, але при цьому і про усвідомлення ширшої картини та розуміння, де так як можна зрізати кути, а де — не можна у жодному разі.

#good_enough_code #мислення_розробника

***
Наступного разу ми поговоримо про найбільшого ворога розробника — diminishing returns та чому більше часу далеко не завжди значить більше якості.

@babichdev
.
🔥7021🤔4👏2
Тим часом вирушаю до Києва, аби зустрітися з вами на JavaScript fwdays'25 та розповісти вам про таємничі сигнали з космосу )

І так, завтра буде препаті ;)
78🔥20👏5
This media is not supported in your browser
VIEW IN TELEGRAM
На неймовірно ламповій та затишній конференції JavaScript fwdays'25 розповідав про сигнали, що це таке, кому вони треба, і чому ми маємо знати про них вже.

Дякую глядачам за неймовірно теплий прийом )

P.S. Велика стаття про сигнали встала в чергу ;)
85👏10
27 травня, Львів. Атляс. 19:00.
Жива дискусія про якість і швидкість у розробці.

Я — за Good Enough Code. Роман Марінський — за Clean Code. За філіжанкою (не)кави шукатимемо істину та обговоримо переваги й недоліки обох підходів.

Квиточки: https://secure.wayforpay.com/payment/cctd_vs_gec

Усі гривні — на ЗСУ.

Чекатиму на вас.

@babichdev
🔥246
Symbol, на мою особисту думку — найзагадковіший тип даних у JavaScript. Механізм його роботи не схожий на інші примітиви, а суть існування стає ясною лише після переходу на наступний енергетичний рівень буття.

Що таке Symbol? Для чого він? Які задачі вирішує? Гайда розбиратися.

Символи — це особливі примітиви, які гарантують максимальну унікальність значення. Настільки максимальну, що Symbol('foo') !== Symbol('foo'). Оця текстова мітка — по суті просто ваша примітка до змінної, а не частина самого значення.

Символи дозволяють уникати конфліктів у ключах обʼєкта. Навіть якщо у вас символздєсь і символздєсь — це завжди різні значення. Ви можете абсолютно спокійно робити таке (тільки от нашо?):

const object = {
[Symbol("підпиздєсь")]: "foo",
[Symbol("підпиздєсь")]: "bar"
};


А доступитися до конкретної властивості, захованої за символом, можна тільки маючи посилання на сам символ.

Symbol — це єдиний примітив, який можна використовувати як ключ до обʼєкта без перетворення на рядок. Інші примітиви, як-от числа чи булеві значення, автоматично зводяться до рядків.


Найскладніше в роботі з Symbol — це прийняти, що вони поводяться інакше, ніж звичні примітиви. Рядки, числа, логічні значення — змінюються, копіюються, порівнюються напряму. Символи ж — щось з квантової механіки, коли це ніби і примітив, а водночас і значення за посиланням. І якщо загубити його — то вже не знайти, бо створити такий самий буде неможливо (ну майже).

Символи неперелічувані — їх не видно в Object.keys, for...in, JSON.stringify. Але можна дістати через Object.getOwnPropertySymbols(obj) або Object.getOwnPropertyDenoscriptors(obj).

Це тому, що символи створені не для приватности як такої, а, радше, для прихованости та запобіганню випадкових перевизначень. Тобто часткової приватности.

До речі, про унікальність. Існує API Symbol.for(), яке дозволяє створювати загальнодоступні символи з єдиною ідентичністю, які зберігаються в глобальному реєстрі військовозобовʼязаних:

const here = Symbol.for('підпиздєсь');
const there = Symbol.for('підпиздєсь');

console.log(here === there); // true


Також існують так звані well-known Symbols, які працюють як API-хуки: ті ж Symbol.iterator, Symbol.toStringTag, які дозволяють описувати власні імплементації для певних поведінок. Наприклад, описавши метод [Symbol.iterator] у класі або обʼєкті, ми зробимо такий обʼєкт Iterable.

Швидше за все, ви не будете стикатися з ними щодня. Хіба ви розробляєте якусь бібліотеку або рішення, в якому надзвичайно важлива інкапсуляція на рівні обʼєктів.

🔗 MDN

Зізнавайтесь, хоч трошки зрозуміли, що таке Symbol? І обовʼязково поділіться своїм досвідом роботи з ним в коментарях (навіть якщо й не зрозуміли)!

@babichdev

Вподобайки, поширення — я про це вже не мав би вам нагадувать ;)

***
📣 Нагадую, що завтра (27.05) чекатиму вас на затишній
дискусії про Clean Code vs Good Enough Code у Львові! Приходьте самі та запрошуйте колег!
74🔥20🤔9
Good Enough Code, ч.3 — Diminishing returns
[ч.2] | [ч.4]

Що найбільше заважає нам у розробці? Звісно, ми самі. Але сьогодні мова про більш конкретного ворога — diminishing returns.

До прикладу, вам до рук потрапляє якийсь модуль, який вам за першу ітерацію вдається оптимізувати, припустимо, на 50% — з 400мс до 200мс. Наступні дві ітерації дають ще 10% — з 200мс до 180, потім ще 10%, вже до 162. Але зусиль — утричі більше.

Вигода, очевидно, занадто мала, тенденція ж — очевидна. А якщо рахувати загальну вигоду, то від початкового стану ви виграли за першу ітерацію цілих 50%, а за усі три ітерації разом — 59,5%. Тобто в результаті додаткових зусиль ви не виграли й десяти відсотків.

Звісно, цей приклад досить спрощений, однак чудово ілюструє принцип diminishing returns. Ви вкладаєте усе більше часу, отримуючи усе менше реального результату. Ба більше, на практиці часто якраз ось ці додаткові зусилля привносять ще й нестабільність до системи, збільшуючи її схильність до помилок та вартість подальшої підтримки.

Як зловити себе? Ви витрачаєте непомірно більше часу на удосконалення рішення, аніж на саме рішення. Більш явна ознака — команда не розуміє доцільність вашого затягування (це вже навіть не дзвіночок, це великодній дзвін). Або ж ви просто не можете зупинитись і починаєте полірувати заради самого полірування — впадаючи в азарт, попри мізерний ефект.

Ось тут вперше й прозвучить головна ідея усієї концепції Good Enough Code:
"Час від часу випускайте на волю свого внутрішнього Януковича, який казатиме вам “АСТАНАВІТЄСЬ“".

Вкрай важливо розуміти, коли ваше пакращення уже не буде пакращенням. Якщо ви намагаєтесь досягти прискорення вашого алгоритму на 2мс у фінансовому застосунку — це абсолютно виправдано. Там це може означати втрачені мільйони. Але якщо ви третій тиждень поліруєте форму на п’ять полів, щоб кнопка Submit спрацьовувала на 20мс швидше — це марно згаяний час. Користувач не помітить різниці.

Оцінюючи diminishing returns надзвичайно важливо брати до уваги не лише конкретні цифри, метрики й показники, а й доцільність покращень. Доречність витрати часу. Не кожне покращення — виправдане. Однак кожна зайва складність має ціну.

Не все потребує покращення. Я знаю, цю думку складно прийняти. Ще раз: не все потребує покращення. Але усе потребує стабільности. Про що ми й поговоримо наступного разу.

Якщо вам дуже сподобався цей допис, звичайно.

@babichdev

Дуже цікаво дізнатися вашу думку щодо diminishing returns — згодні, не згодні, вважаєте це проблемою чи вигадкою? Ласкаво прошу до дискусії!

#good_enough_code
🔥7319👏1