• Без ORM. Вдогонку

    В предыдущем посте я поделился мыслями насчет преимуществ сырого SQL перед ORM. Забыл привести два следующих аргумента.

    Миграции

    Напомню, наши миграции – это SQL файлы. Специальный скрипт прогоняет их в особом порядке, оборачивая в транзакции. Преимущество в том, что я могу прогнать их самостоятельно через psql, если вдруг возникнет такая возможность.

    Пример типичной миграции:

    -- change column types
    alter table users
        alter column username type text,
        alter column username set not null;
    

    Здесь я просто меняю тип поля на text с varchar и добавляю ограничение на обязательное заполнение. Чтобы проверить миграцию, просто запускаю ее вручную:

    psql --user foo foo-dbm < resources/migrations/20161107112942-change-username.up.sql
    

    Если у вас база в Докере, то выигрыш в том, что при старте образа запускается специальный скрипт. Он автоматом прогоняет .sql-файлы из особой папки. Достаточно накидать в эту папку файлы миграций, и они выполнятся! Вот как это делается в compose-файле:

    version: '2'
    services:
      ...
      postgres:
        image: postgres
        volumes:
          - <папка с миграциями>:/docker-entrypoint-initdb.d:ro
    

    Сравните теперь с типичной Django-миграцией:

    from django.db import migrations, models
    
    class Migration(migrations.Migration):
    
        dependencies = [("migrations", "0001_initial")]
    
        operations = [
            migrations.DeleteModel("Tribble"),
            migrations.AddField("Author", "rating", models.IntegerField(default=0)),
        ]
    

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

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

    По Ричу Хики, SQL-миграция – просто, Джанго-миграция – легко. Я за простоту.

    Рекурсивные запросы

    В предыдущем проекте я столкнулся с иерархической структурой данных со ссылкой на саму себя. Это было что-то вроде структуры папок. Узел, который ссылается на родительский узел, который… и так далее, до тех пор, пока ссылка на родителя пустая. Это значит, достигнута вершина иерархии.

    При этом самые частые операции в коде были перемещение от элемента на самый вверх или на самый низ. Что сделал разработчик? Понятно, лезть в базу поштучно очень дорого, в цепочке может быть 20 узлов. Решил проблему радикально – вынимает из базы ВСЕ узлы, потом стоит иерархический словарь в памяти и перемещается по нему. Это работало, потому что в базе было мало узлов, около тысячи. Ради забавы я написал юнит-тест с 10000 узлами, код подвис секунд на пять.

    А ведь достаточно было использовать рекурсивные запросы! Они не только в Постгресе есть, но даже в SQLite! Запрос разбивается на две подчасти. Первая – инициализирующая часть, вторая – накопительная. Пример с Хабра:

    WITH RECURSIVE r AS (
       SELECT id, parent_id, name, 1 AS level
       FROM geo
       WHERE id = 4
    
       UNION ALL
    
       SELECT geo.id, geo.parent_id, geo.name, r.level + 1 AS level
       FROM geo
          JOIN r
              ON geo.parent_id = r.id
    )
    
    SELECT * FROM r;
    
     id | parent_id |      name       | level
    ----+-----------+-----------------+-------
      4 |         2 | Европа          |     1
      5 |         4 | Россия          |     2
      6 |         4 | Германия        |     2
      7 |         5 | Москва          |     3
      8 |         5 | Санкт-Петербург |     3
      9 |         6 | Берлин          |     3
    (6 rows)
    

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

    Любите SQL – прекрасный, понятный язык запросов к данным!

  • Без ORM

    UPD Продолжение

    sql

    В текущем проекте мы используем SQL. Запросы, миграции, триггеры – все это чистый скуль, написанный нами. Сперва было непривычно, за годы работы с Джангой я напрочь забыл язык запросов. Теперь, напротив, меня дико прет. Рассказываю плюсы и минусы такого подхода.

    Прежде всего, мы используем библиотеку HugSQL. Работает она любопытным образом. Вы пишете обычный .sql файл с запросами. Перед каждым запросом размещаете структурированный комментарий. В нем указываете имя функции и дополнительные директивы. Затем библиотека парсит файл и динамически создает в модуле функции с аналогичными названиями.

    Пример:

    -- :name create-user! :<!
    -- :doc creates a new user record
    INSERT INTO users
    (first_name, last_name, email, username, password, phone)
    VALUES (:first_name, :last_name, :email, :username, :password, :phone)
    RETURNING *
    
    
    (let [user (db/create-user! {:username "ivan"
                                 :email "test@test.com"
                                 :password "123"
                                 :phone "223-322"
                                 :first_name "test"
                                 :last_name "test"})])
    

    Разберу минусы данного подхода. Во-первых, приходится писать больше кода. В Джанге или Рельсах достаточно вызвать у объекта метод .save(). В зависимости от состояния объекта будет выполнен запрос вставки или обновления. В нашем случае нужно писать два отдельных запроса.

    Во-вторых, приходется потратить время на повторное изучение SQL и конкретной базы данных, в нашем случе – Постгреса. Потому что все ORM-системы превращают базу в хранилище, то есть черный ящик. Есть модели, пользуйся, а внутрь не лезь. И вообще, объекты предлагают больше синтаксического сахара.

    Плюсов, на мой взгляд, больше. Прежде всего, приходит понимание того, что происходит в БД. Как устроена структура, какие фукнции и триггеры объявлены, как связаны сущности.

    Появляется возможность свободно строить джоины, объединения. Мы активно используем триггеры чтобы нормализовать поля. Добавляем констрейнты (ограничения), чтобы предотвратить запись неверных данных.

    Если база сопровождается ORM-системой, скорее всего, работать с ней из другого языка будет невозможно. Потому что значения по-умолчанию, триггеры и авторизация пользователей, как правило, реализованы силами ORM, а другая система ничего про это не знает. У нас такое невозможно. Что Кложа, что Питон не смогут записать в базу кривые данные.

    Мы активно используем расширения Постгреса и специальные типы данных. JSON, геолокация, генерация токенов и случайных величин. Не приходится писать это в коде. Например, если из двух разных мест выполнить вставку в эту таблицу, будет сгенерирован случайый токен на уровне БД. А если делать это в коде, придется копипастить.

    В логах Постргреса я вижу написанные в своем стиле запросы. ORM, как правило, генерит адский поток, который невозможно прочесть. Если ORM-запрос содержит что-то посложней чтения или вставки, например, group by, having, join, union, приходится его дебажить. Потому что далеко не факт, что результат будет таким, как вы хотите. Например, Алхимия в Питоне не может правильно сделать union, хоть убей. А как указать, что тебе нужен именно левый джоин, а не внутренний?

    Не приходится перенастраивать мозги с одной ORM на другую. Помню, одновременно работал в двух проектах, в одном Джанга, в другом Алхимия. Так замучился запоминать особенности каждой. А чистый скуль не врет.

    Выражаясь терминами Рича Хики, ORM это легко (easy), а SQL – просто (simple). Это не синонимы. Легко значит – быстро, а просто – прозрачно. Здесь я не буду умничать, а просто советую послушать доклад.

  • Поменьше о себе, пожалуйста

    Бывает, делишься с кем-то впечатлениями о книге, статье или фильме и получаешь примерно такой ответ:

    – Я не смотрю аниме.

    – Я не посещаю этот сайт.

    – Я не читаю книги.

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

    Это нелогично

    – Зацени, какая интересная статья.

    – Я не читаю Хабр.

    Минуточку. Тебя никто не спрашивал, читаешь ты Хабр или нет. Зачем ломать линию разговора? Очевидно, полное сообщение ответной реплики звучит так: я не буду читать, потому что не посещаю этот ресурс. Но в исходном сообщении уже содержится контр-аргумент. Он звучит так: даже если ты не открываешь этот сайт, сделай это ради полезного материала! Ответ “я не делаю Х” в ответ на призыв – нелепый.

    Что отвечать, если вам советуют что-то, что вы еще не пробовали, не читали, не смотрели? Задавать открытые вопросы. Напомню, открытые – это те, что начинаются со слов что, когда, где и т.д. Если предмет беседы того стоит, собеседник внятно опишет его преимущества.

    – Чем привлекает этот фильм?

    – Какие особенности в этом языке программирования?

    – Какая главная мысль автора?

    Если слышите в ответ “да там вообще ништяк зацени”, вежливо заканчивайте разговор.

    Это эгоистично

    – В этой книге подробно описано…

    – Я не читаю книги.

    Что движит тем, кто делится информацией? Положительные чувства, эмпатия. Если это не смишные картинки, конечно. Что содержится в ответе? Ничего кроме эгоизма. Смотри какой я крутой. Я не читаю, не смотрю, это для лохов. Даже высказанный вежливым тоном, ответ содержит презрение.

    Это предубедительно

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

    Вывод

    Если вам что-то предлагают, не спешите рассказывать какой вы крутой, и что вы делаете, а что нет. Задавайте вопросы, чтобы быстро узнать суть. Вежливо отвечайте “спасибо”, чтобы не продолжать дальше. И поменьше о себе, я прошу.

  • Перенесли чат в Телеграм

    На прошлой неделе провели с коллегами оптимизацию. Вынесли общение, связанное с Глубоким рефакторингом, в Телеграм. Общаться стало проще, удобней и веселей. В первый же день случился срач про Гоу, сейчас что-то трут за Руби.

    После Фейсбука это как глоток свежего воздуха. Я не знаю, как можно сидеть в Фейсбуке. Писать что-то длиннее твитов – невозможно, комментировать – невозможно, следить за общением, искать по истории, трекать – невозможно. Это мамонт, раздавленный собственным весом.

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

    А пока что прошу зайти в канал Телеграма DeepRefactoring. В нем раньше появятся анонсы и обсуждение докладов и встреч. В Фейсубке мы стараемся теперь не общаться, будем только кросспостить анонсы.

  • Одиннадцатая встреча

    Провели одиннадцатую встречу.

    Я топил за Лисп. Рассказал историю, применение, особенности и сильные стороны. Доклад длился почти два часа. К моей радости, слушателям было интересно. Наверное, потому что Лисп – то немногое, в чем я действительно разбираюсь.

    Фрагмент записи:

    Слайды

    Второй доклад проходил в другом формате. Миша показывал с монитора в реальном времени как делать всякие крутые штуки. Генерить ХТМЛ, перемещаться по файлам, быстро искать классы и функции в проекте и т.д. Записи, к сожалению, не осталось.

    С записью вообще беда в этот раз. Сначала я по ошибке не включил запись на Маке. Два часа выступал уверенный, что все ок. Потом Миша не сохранил файл на диск. Получились эксклюзивные доклады. Не пришел на митап – теперь не догонишь.

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

    В этот раз вели трансляцию в Перископе. Батареи Айфона хватило на час. Именно оттуда удалось вытащить фрагмент доклада про Лисп. Так что не удивляйтесь странному интерфейсу поверх видео, комментариям и смайликам. На трансляции было 94 человека.

    Кстати, мы решили перенести общение в Телеграм и даже создали группу. Об этом – в отдельном посте.

    Скоро анонс двенадцатой встречи, годовой юбилей. Год, Карл! Хотите выступить? Пишите в личку.

  • Twitter Feed закрывается

    Сервис Twitterfeed объявил о скором закрытии. Предлагают переходить на Buffer или Dlvr.

    twitter-feed

    Сервис транслировал записи из РСС в социальные сети: Твиттер, Фейсбук и что-то еще. Полезно для блога: анонсы о свежих постах сами появляются в соцсетях.

    Сервис принадлежит компании Бит.ли, той самой, что владеет известной сокращалкой ссылок. Twitterfeed был побочным продуктом. Он совсем не развивался на протяжении последних лет, хотя счетчик лент на главной показывал сумашедшее количество.

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

    Словом, жаль, очень жаль.

  • Листая желтые страницы

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

    То были веселые денечки. Друпал.ру хостился черт знает где, чуть ли не на балконе, ложился под малейшей нагрузкой. Чего только не случалось на форуме. Любое техническое обсуждение сводилось к личностным вопросам. Спорили о легализации наркотиков, неравенстве рас, словом, треш и угар.

    Однажды один неадекват втерся в доверие админу, получил права супер-пользователя и положил сайт. Зачем? Хотел привлечь внимание к тому, что его троллят. Был клевый чел Анатолий, у которого Путин виноват в каждой неудаче. Работу долго не мог найти, маркетолог по образованию. Он часто создавал голосования, а я накручивал скриптом, отчего у Толи бомбило.

    Были клевые ребята, которые вели блоги, регулярно постили полезные штуки. Каждое утро я начинал с чтения их материалов. Ни про какие RSS я в то время не знал, тупо лазил по сайтам.

    С уходом с Друпал.ру читать эти блоги я перестал, а недавно вспомнил и полез проверять – что стало с ребятами? На что перешли со своего Друпала? Все-таки четыре года прошло с последнего посещения.

    Зашел, и стало грустно. Кое-кто тупо забросил блог, домены не работают. Не смогли писать в долгосрочной перспективе. Я называю это “сошли с дистанции”, это правда печально, когда подававший надежды блоггер вдруг замолчал.

    Но вторая категория еще грустней. Это те, кто так и остались сидеть на Друпале, стругая кривые сайты из готовых модулей. Печальное зрелище, потому что заниматься одной и той же деятельностью без смены инструмента – ужасно. Самые продвинутые перелезли на другую CMS, но это превозносится с таким пафосом, что песец.

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

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

    Восемь лет назад сайты на Друпале выглядели грубыми табуретками. Все кривое, косое, тема оформления натягивается с косяками, всюду мусор, ошметки непереведенного текста. Вы действительнохотите edit your comment? И сегодня все так же.

    Я к тому, что должно быть движение, развитие. Оставаться подолгу в одной среде – путь к деградации. Тут тонкая грань, либо становишься признанным гуру, либо отстаешь от процесса, и центробежная сила уводит на обочину. Поработал три года с ПХП, перелез на Питон, потом на Скалу, позанимался Хаскелем, ковырнул Эрланг. И это только языки. Впереди еще Вим с Емаксом, SICP, Латех, шифрование, протоколы. Столько возможностей!

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

  • Кнопка Пуск

    img

    Самое ужасное в Винде – кнопка Пуск. Ты нажал ее, чтобы открыть блокнот или калькулятор. В ответ система вываливает тонны лишней информации. Погода, курсы валют, новости, игры для Икс-бокса (у меня его нет), покемоны и прочий ад.

    Зачем? Где я указывал, что люблю покемонов? Почему показывают игры для консоли в рабочее время? Зачем список Форбс? Почему жирный кот из Твиттера?

    Такое обилие инфомрации страшно дезорганизует. Каждый раз, пробираясь сквозь дебри этого говна, нужно стараться не забыть: мне нужен калькулятор, мне нужен калькулятор…

    В нормальных системах делают не кнопку Пуск, а умный ввод с дополнением:

    img

  • Книга ClojureScript Unraveled

    cover

    Хорошая, годная книжка по Кложе-скрипту. Авторы коротко и по делу рассказывают о философии языка, как в нем принято решать те или иные задачи. Отдельная глава про тесты, несколько о многопоточности и сигналах. Нет долгих базаров о том, что такое Лисп и скобочки, чем грешат схожие материалы.

    Книга доступна на Гитхабе в виде сайта, но советую поддержать авторов и купить на Линпабе. Цена выбирается на усмотрение вплоть до нуля, рекомендуемая 2 доллара.

  • Десятая встреча

    Провели десятый митап, юбилей! По этому поводу перепились. Митап продолжался до закрытия заведения.

    cover

    На снимке, к сожалению, не все.

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

    В следующий раз подготовлюсь заранее.

    Как обычно, выступили два докладчика. Начал Юра о том, что творится в экосистеме Руби глазами питонщика:

    Слайды

    Продолжил Виталий на тему говнокода:

    Слайды

    Напомню, сообщество тусит в группе Фейсбука.

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

Страница 66 из 90