Роздуми Спрощенця
241 subscribers
19 links
Канал про програмування, софт взагалі, і, найважливіше, спрощення технічного стеку.

Автор @yrashk
Download Telegram
Багато років тому, одна із сінтаксічних проблем з якою я стикався у Ерлангу (та й не тільки) полягала в тому що читати код типу f(g(h(d))) досить складно ментально, бо треба знайти власне з чого все там починається (h(d)) і читати справа наліво.

Багато мов, включаючи Elixir, так чи інакше цю проблему вирішили, чи то з чимось типу pipe operator, чи то с UFCS (Universal Function Call Syntax).

А от SQL (яким я зараз займаюсь дуже багато) — ні.

І доводиться писати и вичитувати не дуже прозорі запити типу:

 select convert_from(convert_to('Hello', 'utf-8'), 'utf-8')


Не дуже зрозуміло з чого тут все починається і чим закінчується.

А якщо ми перепишемо це отак?

select 'Hello' |> convert_to('utf-8') |> convert_from('utf-8')


Значно краще! Тут можна зрозуміти (якщо знати про що ці convert функції) що беремо текст, конвертуємо у bytea, і назад. Не дуже корисно, але це просто приклад 🥹

І мене це вже настількі достало, що так не можна, що я написав цього ранку прототип який власне це і робить за мене (див. скріншот). Я ще не знайшов нормального способу переписувати таким чином всі прямі запити до постгресу у сесії, але навіть якщо це неможливо, в мене все рівно є план написати вбудовану проксі/баунсер для постгресу. От воно ї зможе переписувати. А поки цього нема, можна переписувати запити використовуючи функцію extended_sql.

Запитання до читачів:

А які у вас є нарікання до SQL і що б ви хотіли покращити або виправити в ньому?
🔥5👍2
Дуже часто, коли розробляються нові програми, ми спочатку реалізуємо те, що виглядає простіше, аби отримати перші результати швидше. Але потім це часто призводить до того, що складні варіанти тим чи іншим чином просто не вписуються до загальної картинки, і доводиться або переписувати, або якось прикручувати, аби працювало. Або взагалі неможливі!

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

Ось приклад з поточного досвіду:

Треба побудувати систему на кшталт nixpkgs (але простіше), де можна було б збирати бінарні білди покроково в ізоляції. Є спокуса почати з простого і зробити все це на базі умовного docker/podman. Це знайомо і буде працювати на лінуксі.

А що з іншими ОС? Ну, коли ми до того дійдем, там будемо розраховувати на якійсь варіант типу Docker Desktop та віртуальною машиною.

Ну добре, а що якщо ми хотіли б мати білди для, наприклад, macOS? Хмм.

Таким чином я дійшов до того, що треба спочатку сфокусуватись на більш складних варіантах. І от тут я кілька тижнів тому трохи почитав та погрався з Virtualization Framework. І що я вам можу сказати: якщо це спрацює, решта проекту буде, напевно, як свято! Бо API та можливості там, здається, розроблено так, щоб максимально уповільнити темпи росту віртуалізаціі на маку.

Почнемо з того, що немає API для отримання IP-адреси віртуальної машини яку ти щойно запустив. Ну гаразд, це можна обійти, подивившись на таблицю раутінгу. Якщо ми встановлюємо macOS, то я не знайшов варіанту, як налаштувати будь який крок у тих величезних ipfw файлах, з яких йде інсталяція. Щоб, наприклад, вказати пароль до адміністративного акаунта. Ну, добре, тут можна створити готові нові дискові образи з готовими інсталяціямі і налаштувати все там за допомогою скрипта. Для кожної версії. Але, годі, Xcode, навіть тільки якщо попросити його встановити тільки command line tools, через ssh без GUI принципово відмовляється встановлюватись!..

Шлях непростий, але вихід (майже) завжди є. Більш того, маючи готові інструменти та досвід для Virtualization Framework, їх можна бути використати для лінуксових білдів на macOS без інсталяції власне докеру чи чогось такого.

Після цього мені й Windows не буде страшний!

А як у вас з цим? “Happy case” спочатку чи ні?
🤔4🔥3
Короткий допис сьогодні, бо я все ще подорожую і енергії не завжди вистачає 😫

Нещодавно ми намагалися скрутити разом код на Clojure з pljava, щоб можна було писати Postgres-функції (або навіть бізнес-логіку для Omnigres!) на кложі.

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

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

pljava використовує це щоб, наприклад, згенерувати SQL код для функцій які будуть експортовані в постгрес.

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

Але мені здається, що це локально нівелює той корисний факт що кложа є частиною JVM екосистеми, і такі випадки стають складними не тому що вони занадто складні, а тому що.

(“Тому що ви повинні страждати”. Ну, майже так)

Заради справедливості зазначу що я досі не повнистю розумію, де ці annotation processors запускаються в maven, gradle та інших білд-системах.

Але що робити коли це нашарування вже сталося і воно вже дуже стале?

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

Проблема ще й у тому, що майже ніколи на це часу, енергії та знаннь не вистачає.

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

Тому для себе я такий тут висновок роблю: елегантні системи, які живуть на старому фундаменті, повинні мати “escape hatches” - засоби вирватись з кайданів і зробити все ще тобі потрібно, навіть якщо це не дуже красиво. Без нових абстракцій.

Бо результати завжди потрібні тут і зараз.
👍3🔥2
Навздогін, мене часто дуже дратує коли бібліотеки ховають, наприклад, визначення типів. Типу, ось вам тип MyType, але що там всередині, це вам не можна використовувати.

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

До речі, у деяких проектах нема доступу до якихось елементів типів не тому що це погана ідея, а тому що або руки не дійшли, або не подумали. Нещодавно бачив це на прикладі libfyaml.

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

І от мені здається що libgit2 пропонує елементи досить цікавої моделі. Ви отримуєте нормальний стандартний інтерфейс, але якщо треба достукатись до певних деталей, то є .h-файли у директорії git2/sys

Ба навіть що якщо просто дати можливість вказати що так, я знаю що я тут буду лізти і використовувати щось непублічне. Якщо використовувати C як приклад:

#define LIBFOO_INTERNAL_API_V3.1 // "я знаю що я роблю, і це будуть мої проблеми"
#include <libfoo.h>


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

А як ви вирішуєте цю проблему? Чи взагалі не вважаєте проблемою?
👍2
Не писав деякий час, вибачте (багато чого відбувається!). Дуже короткий допис сьогодні, але по суті.

Коли SQL формувався, так сталось що порядок у select-а, умовно кажучи, такий: “вибери ЦЕ, ЗВІДСИ[, якщо підпадає під УМОВИ]”

Але ж це реально незручно у практиці у сьогоднішніх умовах. Якщо починаєш писати select nam, то твій редактор не має можливості зробити автокомпліт. Бо ще ж не додано інформації про це. І от виходить що пишеш select from users, потім повертаєшся до селекту і починаєш додавати поля.

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

Я не перший з цього приводу переймався, і не я останній. Але стало у якійсь момент цікаво: а власне наскільки складно було б додати такий варіант select, який б вирішував ці проблеми? Звісно, з технічної сторони – я не маю й гадки стосовно того наскільки складно щось додати до стандарту. Отже, технічно, та й до Постгресу, звісно, бо я дуже активно з ним працюю.

Виявляється, не дуже. Власне, поки що обійшлося невеличкими змінами до граматики. На додаток до класичного select ... from ..., написав правила для from ... select .... Запрацювало! (дивись картинку)

Якщо комусь цікаві деталі, мій нашвидкоруч зроблений патч.

P.S. Я спробую знайти час розібратись як додати такий синтаксис до Омнігресу без того щоб використовувати пропатчений Постгрес. Є ідеї!
🔥10👍3🤔1
Короткий допис/опитування.

У поточному проекті (Омнігрес) моя головна мета — покращення робочого досвіду (development experience, DX) роботи з базою даних. Бо будемо чесні, він трішки засів у минулому, де були великі сервери і всі зміни проводились через DBA.

Нещодавно я працював над концепцією віртуальних файлових систем для постгресу (VFS) та її використанні для розгортання DDL та функцій як локально так і на продакшн (наприклад з Git VFS).

Але сьогодні мені хотілося би порушити трохи інший аспект: інтерактивні клієнти БД. Ми маємо REPL-подібні клієнти типу psql, є багато графічних та веб клієнтів. Проте, мені здається що концептуально багато з них відображають практики та підходи минулих часів. Можливо, пора критично переглянути робочий досвід у цьому напрямку.

Отже я хотів би запитати вас:

Якими клієнтами БД ви користуєтесь, чому, і що в них дратує чи навпаки? Як ви їх використовуєте в процесі розробки?
Кілька тижнів тому я вирішив опанувати нову (для мене) мову програмування — Prolog. Чому так сталося і чи було це варто робити?

Майже з самого початку розробки Omnigres мені хотілось зробити щось корисне для розповсюдження розширень (extensions) для Postgres. Чому? Система управління розширеннями в постгресі досить обмежена: вона дає можливість знайти SQL файли для інсталяції або апгрейду/даунгрейду і робить заміну певних строк у цих файлах (типу власника, схеми чи шляху до .so-файлу). Але все, що стосується зборки та розповсюдження, – біда. Розбирайтесь самі. Найвідоміша система pgxn по суті є каталогом і мйже всі моменти стосовно залежностей майже повністю залишаються проблемою користувача. Нещодавно анонсований database.dev займається тільки TLE (trusted language extensions). Також нещодавно анонсований Trunk є трохи кращим, але досить обмеженим: runtime залежності не вирішені, і все досить сильно повʼязане наразі з докером.

Все це мене не досить влаштовувало. Я хочу фантастичного D3X (Development, Debugging and Deployment Experience): щоб все працювало на компʼютерах розробників (так, навіть на macOS і без постгресу у докері), щоб можна було інсталювати розширення із залежностями з рідних пакетів тієї дістрібуції лінукса що у вас на сервері, щоб можна було вказати залежності між розширеннями, пакетами, постгресом та ін.

Отже, я придбав цікавий домен (ще не анонсовано, але це postgres.pm) і вирішив зайнятись проблемою.

Було багато ідей як це зробити. Але всі вони були навколо того факту що якщо ми хочемо будувати розширення у невідомих обставинах, нам потрібно щось типу експертної системи. А також того, що потрібна якась проста нотація для опису пакетів. Спочатку я намагався зробити це на CLIPS, але воно працює найкраще коли всі факти відомі і треба з ними щось зробити. У нашому випадку, це не дуже практично бо для багато чого треба опитувати систему напряму. І опитати про все-все-все нереально. Отжеж, я дійшов до потреби у backward chaining, спробував його реалізувати у вигляді патча до CLIPS, але засів там надовго бо це було не дуже просто.

Тут я вирішив себе перебороти, і спробувати щось типу Prolog’у. Бо я був в курсі, але ніколи не використовував. Тим паче що там є реалізації constraints що дуже корисно для штук типу пошуку сумісних версій. Та й синтаксис мене не дуже лякав, бо я багато років на Erlang писав.

Продовження у наступному пості.

P.S. Хто вгадає мій промпт для картинки?
🔥6🤔1
Продовжуємо.

Перший день у Prolog був найважчим, адже кожні пʼять хвилин я намагався використовувати REPL (toplevel) щоб писати предикати прямо у запиті (без секції [user].). Втім, варто запам’ятати, що у цій штуці ми ставимо питання. А всі дефініції або у файлі, або

[user].

% тут щось описано

^D

Після усвідомлення цього, поїхало краще. Головна ідея, яка мені дуже подобається (принаймні, для певного класу проблем), це те, що правила описують “якщо X, то Y” і можна фокусуватись на результаті, а не на процесі його досягнення. Ми описуємо по суті відносини між речами. От простий приклад:

?- length([1,2,3], L).

L = 3.

Тут, в принципі, все просто. Дали список, отримали довжину. Але все не так просто:

?- length([1,2,3], 3).

true.

?- length([1,2,3], 4).

false.

Тут ми бачимо, що насправді ми запитали, чи є довжина списку такою, як ми вказали (просто L у прикладі – це змінна без значення). Більше того, ми можемо давати складні умови з обмеженнями:

?- use_module(library(clpfd)). % бібліотека для integer constraints

true.

?- L #< 4 #\/ L #>6 , length([1,2,3], L).

L = 3.

?- L #< 4 #\/ L #>6 , length([1,2,3,4,5,6], L).

false.

?- L #< 4 #\/ L #>6 , length([1,2,3,4,5,6,7], L).

L = 7.

Але навіть це ще не все, ми можемо згенерувати список заданої довжини:

?- length(List, 5).

List = [_, , , , ].

?- L #< 4 #\/ L #>6 , length(List, L).

L = 0,

List = [] ;

L = 1,

List = [_] ;

L = 2,

List = [_, _] ;

L = 3,

List = [_, _, _] ;

L = 7,

List = [_, _, _, _, _, _, _] ;

...

Там ще дуже багато цікавого, але в мене тут простору не вистачить 😄. Отже, це дуже цікавий інструмент для того щоб описувати складні системи. Мене дуже тішить, коли досить складні проблему описуються дуже лінійно завдяки тому що предикати можуть дати більш ніш одну відповідь (non-deterministic predicates).

Я вирішив поки що зупинитись на SWI Prolog, але є ще багато цікавих імплементацій, як відкритих, так і комерційних. SWI має багато фіч, та його досить легко додати до програм на C/Rust/т.і. програми (я навіть почав розробляти plprolog бо це буде дуже цікавий інструмент для експертних систем у постгресі). Після кількох тижнів з “чистим” прологом я перейшов на Logtalk для того щоб краще організувати мій код. Рекомендую: автор вже на протязі більш ніж 20 років працює над ним, і робить це дуже активно.

Чи варто спробувати Prolog? Так, абсолютно! Щонайменше, це дасть можливість подивитися на проблеми під іншим кутом. Власне, сама мова дуже мінімалістична і можна будувати прототипи та реальні системи досить швидко. Дуже рекомендую лекції Power of Prolog.

На скріншоті: поточна ітерація того, як виглядають описи пакетів.

Є питання? Пишіть!
👍6🤯6🔥5
Мене завжди дратував той факт, що для написання якоїсь бізнес-логіки на чомусь окрім SQL або PL/pgSQL, потрібно писати цей код всередині SQL файлу, наприклад:

create function myfunction(myarg int) returns bool language python as $$

# а отут в нас Python

$$


Бо з цього моменту нормально з редактором там вже не попрацюєш, а зовнішні інструменти взагалі не розуміють таку структуру.

Отже, сьогодні я написав фічу в Омнігресі, щоб можна було просто покласти цю функцію у .py-файл і воно його підхопить.

# SQL[[create function times_ten(a integer) returns integer]]

return a * 10


У подальшому можна поліпшити підтримку того ж Python та інших мов, зокрема, використовувати інформацію з анотацій та типів. Але наразі цей простий як пробка підхід працює будь-де (принаймні, я так думаю).

(Деталі: https://docs.omnigres.org/omni_schema/reference/#multi-language-functions)

А що ще вам заважає додавати логіку до бази даних?
🔥8
Я тут написав статтю про архітектуру разом з автором SQLPage і вона зараз на front page Hacker News. Якщо знайдете, можете завітати до коментарів 😀
👍8🔥4
Коротка новина: нарешті зробив перший реліз досить нішевого інструмента, pg_yregress

Якщо ви знаєте що таке pg_regress але вам не дуже подобається з ним працювати, запрошую спробувати pg_yregress. Дозволяє структурувати тести краще, фокусуватись на предметі тестування, підтримує більш одного постгреса під тестом, тестування бінарних кодуваннь та т.і.

Максимально корисно для тестування розширеннь для Postgres, але цікаво подивитись і на інші юзкейзи.
👍4
Хвилинка самореклами. 🤡

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

Для тих хто не пам’ятає: Omnigres це такий uber-majestic monolith. Ми взяли постгрес і робимо з нього application runtime якій вміє ну майже все. І ваша бізнес логіка з нього не вилазить. Це робить розробку простішою, latency меншим, дає транзакціональність там де її ніколи не було, дає перспективи на дуже прості edge deployments, та ще багато чого.

Не всі з цим підходом згодні, але ми працюємо для тих кому це потрібно та чекаємо коли іншим набридне платити величезні гроші за мікросервіси які могли б бути SQL запитами 🫣

Чому я зараз вирішив прорекламуватись тут? Справа у тому що ми тепер починаємо будувати founding team інженерів. Це звичайно нелегка але цікава (для певної категорії людей) робота для тих хто готовий володіти проблемами та напрямками. Добра англійська абсолютно потрібна (інтернаціональна команда).

Початкова команда буде дуже невеличкою але рухатись будемо швидко.

Отже, приходьте до нашого гітхабу, та завітайте до діскорду де ми тусуємось. Ну або пишіть мені у телеграмі @yrashk

P.S. Вибачте за перерву у постах, останні місяці були ну дуже гарячі!
🔥9👍5
Тут ось яка ідея виникла: можливо іноді шукати програмістів з прямим релевантним досвідом у галузі це може бути свого роду ледарство. Це якось очевидно та й не оптимізує інші, непрямі навички, наприклад підходи до створення дуже швидкодійного софту, вирішення складних проблем, дотримання термінів, тощо

Як приклад: я от шукаю розробників із досвідом розробки розширень для постгресу, або навіть контрібуторів до постгресу. А може потрібно шукати хардкорних C++ гейм девелоперів які б зацікавились переходом на новий, відмінний стек та вдоволення потреб бізнес-клієнтів – та й перенесли б свої навички?

Знайомий запропонував інший приклад: шукати поміж Erlang розробників, бо вони всебічно розвинені та й ерланг системи завжди треба підтримувати і це тренує працювати з клієнтами 😜

А ви як думаєте?
🔥9👍2🤔1
У мене таке питання: чи є серед вас ті, хто ненавидить відлагодження SQL запитів? А як щодо шанувальників типобезпечного програмування? Якщо намалювати Вен-діаграму цих двох аудиторій, чи не вийде просто коло?

Я от до чого, мені реально набридло, що в Postgres типи є, але їх наче немає. Ну от, якого біса ми використовуємо той самий тип цілого числа для всіх (всіх!) ID-ідентифікаторів, а потім тупимо в екран, намагаючись зрозуміти, що з цим join'ом не так?

Це ж вже було! Це ж не нова проблема. Давайте просто для кожної реляції створимо свій цілочисельний тип. І замість того, щоб розбиратися, що пішло не так і чому дані виглядають дивно, просто отримаємо помилку ще на етапі планування!

Я знайщов час написати розширення та трохи порекламувати його тут у відео (англійською).

Мене от що цікавить: у вашій практиці такі помилки часто трапляються чи це моя особиста проблема?
🔥4