Записки программиста-одиночки
19 subscribers
17 photos
1 video
44 links
Фрэнк (@a_littlebitmore) о своей многострадальной профессии.

Коротко, хлёстко, жёстко, наивно.
Download Telegram
Несмотря на то, что за час обнаружил у себя провал в памяти на имена близких людей (1) и неспособность заметить код бронирования в авиабилете (2), смог порадоваться насколько же крут NodeJs.

Задача: найти в файле строки с нераспознанной кодировкой.
Решение: line.includes('�')

❤️‍🔥
Forwarded from Frank Bakulov
Всю карьеру был уверен, что оператор IN в mysql транзитивный.
Можно WHERE age IN (32,34), а можно и 32 IN (age), где age это строка "32,34". Можно, выберет для 32, а для 34 нет.
https://dev.mysql.com/doc/refman/8.4/en/replace.html

REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts. For another MySQL extension to standard SQL—that either inserts or updates—see Section 15.2.7.2, “INSERT ... ON DUPLICATE KEY UPDATE Statement”.

А думал, что DELETES, INSERTS AND UPDATES...
Хорошо, что только в одном месте кода облажался.
  let u = new URL('https://example.com/profile?intent=111&redirect_status=succeeded');
let p = Object.fromEntries(u.searchParams);
console.log(p);

Браузер, нода, не важно.
Ответ корректный, p = { intent: '111', redirect_status: 'succeeded' }


Ангулар-тайпскрипт:

[ERROR] TS2769: No overload matches this call.
Overload 1 of 2, '(entries: Iterable<readonly [PropertyKey, any]>): { [k: string]: any; }', gave the following error.
Argument of type 'URLSearchParams' is not assignable to parameter of type 'Iterable<readonly [PropertyKey, any]>'.
Property '[Symbol.iterator]' is missing in type 'URLSearchParams' but required in type 'Iterable<readonly [PropertyKey, any]>'.
Overload 2 of 2, '(entries: Iterable<readonly any[]>): any', gave the following error.
Argument of type 'URLSearchParams' is not assignable to parameter of type 'Iterable<readonly any[]>'.
Property '[Symbol.iterator]' is missing in type 'URLSearchParams' but required in type 'Iterable<readonly any[]>'. [plugin angular-compiler]

У меня всё.
https://developer.mozilla.org/en-US/docs/Web/API/Response/json

response.json() возвращает промис. Оказывается.
Ну, мог бы догадаться, раз он встречается в цепочке:

(response => response.json())
.then(...

Не очень конечно понятно зачем так сделали. От внешних программ/сети данная операция не зависит.
https://community.atlassian.com/forums/Bitbucket-questions/Invitation-not-recieved/qaq-p/3021428#U3023398

Зацените какие клоуны. Скрин прикладываю, пока не поправили.

И это если не бигтех, то около того (хотя я не знаю много ли годовой доход 4 млрд долл.)
В последнее время, поиск по всем нетривиальным вопросам, не только по программированию, ведёт на reddit. Бастион знаний, где собираются люди, владеющие письменной речью.

Последний пример:
https://www.reddit.com/r/node/comments/1kcr0wh/odd_request_coming_into_my_localhost_server_from/
У маленького бизнеса админка на drupal. Это такой РНР-фреймворк. Хостинг что-то обновил (версию РНР наверное), и сайт упал. Оказалось, из-за несовместимой версии PEAR-библиотек. Я скачал какие-то с офсайта (это не так просто сделать, всё перевели на composer, это такая уёбищная пародия на npm), сайт заработал, но письма приходили в битой кодировке. Пару часов копался с настройками почты в drupal.

Сегодня утром решил попробовать нативную mail().

Заработало.
Код почтового модуля в drupal/PEAR - 200+ кб.

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

Ни в PHP, ни в JS, не встречал фреймворков, которые бы это базовое требование выполняли.
У меня по наследственности не очень хороший слух (в прямом смысле). Поэтому я говорю громче, чем принято. Поэтому мне часто не хватает максимальной громкости беспроводных наушников.

Если разные аудио имеют разную громкость, при максимальной громкости наушников, подключённых к смартфону, то значит, что максимальная громкость, от смартфона — не максимальная.

Оказывается, есть приложение, которое громкость усиливает. И не одно. Вот бесплатное, без рекламы
https://play.google.com/store/apps/details?id=com.goodev.volume.booster

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

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

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

  let win = window.open(url, '_blank', options);
win.onload = () => {
win.onbeforeunload = function(e) {
if (this.lastEvent) return;
e.preventDefault();
e.returnValue = dict.confirm_close;
return true;
};
};


win.onbeforeunload внутри win.onload - именно так, иначе не инициализируется.

lastEvent - глобальная переменная, через которую можно реализовать логику, проверяющую, нужно ли выводить предупреждение.

return; - именно undefined, не false, не null. Этого документация не уточняет.

preventDefault, returnValue, return true - это на все случаи всех браузеров. Да, в этом функционале ещё есть разные трактовки, напоминающие о том, как тяжело было фронтэндерам 10 лет назад (а 20 лет назад - невыносимо).

Важно! Если вы открыли окно и сразу закрыли, без фокуса в документ, предупреждения не будет. И это правильно: ведь пользователь точно ничего не поменял.

Менять текст предупреждения пока нельзя. Но в будущем будет можно в returnValue.

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

https://www.reddit.com/r/AndroidQuestions/comments/1kaeydn/revert_back_to_swipe_down_for_both_notifications/
Я конечно не очень много понимаю в никсовых файловых системах, но нафига создатели функции scandir в РНР включают в результат . и .. - хз.

Стало быть,
function _scandir($dir) {
$files = [];
foreach (scandir($dir) as $f) {
$f === '.' || $f === '..' || ($files[] = $f);
}

return $files;
}
Открытие вчерашнего дня, mysql
DESCRIBE tableName

Выдаёт такую красоту.

Идеально, чтобы сравнивать структуры баз.
Открытие сегодняшнего дня,

drawWrappedText({
text = '',
fontSize,
color,
x,
y,
maxWidth,
lineHeightMultiplier = 1.2,
}) {

Деструктуризация во входных аргументах! Да ещё с дефолтами!!

Всё же очень далеко продвинулся и продолжает двигаться современный JavaScript.
Задача: подсчитать хэш всех строк столбца ср-вами mysql.
Проблема: GROUP_CONCAT имеет дефолтное ограничение 1024 символа, очевидно недостаточно.

Решение 1: SET GLOBAL group_concat_max_len = 1000000
Фиаско - требует SUPER привелегий, а SESSION вместо GLOBAL не работает

Решение 2: использовать группирующую функцию JSON_ARRAYAGG
Успех! - нет ограничений (какие-то астрономические наверное есть), а ещё не нужно делать IFNULL, ибо нулл приводится к строке "null"

https://dev.mysql.com/doc/refman/8.4/en/aggregate-functions.html#function_json-arrayagg

Как всегда в сложных случаях выручил не стэковерфлоу и всякая хуИИня, а реддит!

https://www.reddit.com/r/SQL/comments/1kg6fa6/i_dont_want_to_use_group_concat_what_other/
Xcode. Монопольный инструмент программирования под Apple.
Когда гугл не помог, а ИИ помог. Запрос в ИИ:

html input field.

If do event.preventDefault() and change field value programmatically, the value doesn't go to the field history and there's no "undo" action.

How to fix? How to put the value into field history?

Выдал два результата, один сработал:
document.execCommand('insertText', false, text);

Я не знал такой команды, полезно.

Уже в процессе написания поста зашёл на mdn проверить браузерную совместимость. А там deprecated.

И тут же пояснение как раз для моего случая:
there are still some valid use cases that do not yet have viable alternatives. For example, unlike direct DOM manipulation, modifications performed by execCommand() preserve the undo buffer (edit history). For these use cases, you can still use this method

Ну а вместо document.queryCommandSupported(), который логично тоже deprecated, поможет универсальный try catch

      try {
t.select();
document.execCommand('insertText', false, value);
} catch (_) {
t.value = value;
}