• Почему я против объектов. Часть первая, философская

    UPD: вторая часть.

    LT;DR: это очень личный взгляд на ООП, который я обдумывал довольно долго, но окончательно сформировал после прочтения книги Егора “Elegant Objects”. Если коротко, я высказываюсь против идеи представления кода в объектной модели. Некоторые аргументы почерпнуты из сторонних публикаций и адаптированы для краткости. В таких случаях я даю ссылку на оригинал.

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

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

    За последние годы мое увлечение ООП плавно сошло на нет. В одном из постов я прямо признавался, что не понимаю его принципов. Главное, что меня смущает: во время работы, если это был не строго объектный язык, а Питон, JS или PHP, то все задачи я решал простыми функциями. Каждый раз мне говорили, что просто проект легкий, что однажды наступит БОЛЬШОЙ ПРОЕКТ, где с функциями ты хлебнешь. Но время шло, БОЛЬШОЙ ПРОЕКТ так и не наступил, и, кажется, в эпоху микро-сервисов его уже не дождешься. А я все пишу на функциях и неизменяемых коллекциях. В чем же дело?

    И любой объектный код я переписывал на функциях с сокращением числа строк до двух раз. Как так?

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

    Представим, что Вася отправляет письмо Пете. На языке объектов это записывается так (опустим определения классов):

    User vasya = new User("Vasya");
    User petya = new User("Petya");
    Message msg = new Message("Hello!");
    vasya.send(msg, petya);
    

    Тут, возможно, я нарушил один из бесчисленных паттернов ООП: отвечать за отправку должен не пользователь, а само сообщение (что весьма спорно). Поэтому следующий после меня разработчик поправит код вот так:

    msg.send(from=vasya, to=petya)
    

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

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

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

    Зыбкость этого принципа порождает все новые и новые книги и статьи в блогах, где авторы доказывают, что именно их подход обеспечивает прозрачность и поддерживаемость программы, написанной в объектном стиле. Но на более приземленном уровне это выражается, простите, в срачи – бурные обсуждения в чатах, когда эмоции и мнения намного опережают опыт.

    Проблему отношений между объектами я называю “кто на ком стоял”. В самом деле, ручка пишет по бумаге pen.writeOn(paper) или бумага с помощью ручки paper.write(pen)? Каждый, кто поспешит ответом в духе “ну конечно первый (второй) вариант”, не учитывает, что это совершенно субъективно.

    Предполагаю, что именно поэтому в ООП-среде так популярен рефакторинг. Ключевая фича каждой промышленной IDE – облегчение рефакторинга: переименование и перенос методов, автоматическая адаптация кода.

    В окружающем нас реальном мире физические объекты играют далеко не решающую роль. Иными словами, не все можно выразить через объекты. Рассмотрим, например, акт рукопожатия. Следуя принципам Егора, отразить в коде это можно так:

    class User {
      private String name
    
      User(String name) {
        this.name = name;
      }
    }
    
    class Handshake {
      User user1;
      User user2;
    
      Handshare(User user1, User user2) {
        this.user1 = user1;
        this.user2 = user2;
      }
    
      void shake() {
        // ... лог в консоль или что угодно
      }
    }
    
    User user1 = new User("Ivan");
    User user2 = new User("Petr");
    Handshake hs = new Handshake(user1, user2);
    hs.shake();
    

    Но ведь физически рукопожатия не существует. Нет в нашем мире такого объекта, его нельзя купить, смастерить, поставить на полку. Это событие, акт или, выражаясь точнее, действие! А что в программировании выражает действие? Функция.

    Предположим теперь, что друзья пожали руки несколько раз с интервалом в 10 минут. Будет ли правильным вызывать у того же объекта метод .shake()? Или на каждый раз создавать новый объект?

    Если первое, не противоречит ли это принципам ООП? Ведь все это разные рукопожатия, совершенно независящие друг от друга. Что если они жали руки с перерывом в 10 лет?

    Если второе, то чем это отличается от вызова функции? Мы создаем объект, вызываем единственный метод и тут же забываем его? Зачем тогда класс и объект? Если один-два метода это все, что нам нужно от класса, не проще ли завести функцию?

    На эту тему уже неписана отличная статья “перестаньте писать классы”, изучите обязательно. Видео со слайдами, перевод на Хабре.

    Далее можно рассуждать о более сложных вещах. Рукопожатие все же имеет косвенное отношение к физическим объектам. Но такие абстрактные понятия как ненависть, симпатия, эгоизм, честность, религия выразить объектно невозможно. Я имею в виду, что не составит труда написать класс с нужным именем, который инкапсулирует другие классы. Но спрашивается, в чем здесь смысл?

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

    В книге “Elegant Objects” Егор справедливо замечает, что сегодняшнее ООП это просто структура данных с прикрепленными к ней функциями. Однако, не делается акцент на том, сколь масштабно это явление. С выходом языков Go и Rust на них перешли тысячи бывших Java и С++ разработчиков, и, похоже, сочли новые языки вполне себе объектными. А ведь и в Go и в Rust объекты – это банальные сишные структуры. И если функция принимает первым аргументом такую структуру, то вместо some_action(data, 1, "test") можно написать data.some_action(1, "test"). Вот и вся разница.

    Очевидно, сегодня для большинства вызов функции через точку кажется главным показателем объектности языка. Я не хочу никого этим обидеть. Человеку свойственно упрощать рутину: выражать код всей программы с помощью настоящих, “элегантных” объектов, как советует Егор, мне кажется неподъемным делом. А со структурам и функциями проще, и даже похоже на ООП.

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

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

    В следующий раз поговорим о технической стороне ООП.

  • Надо короче

    Удивительно, что в детских организациях, например, образовательных и спортивных школах совершенно не знают, как проводить мероприятия. Я имею в виду провести так, чтобы дети не устали от бессмысленного ожидания.

    Типичную линейку в школе ставят следующим образом. Выходит директор. Выходит завуч. Выходит сука-единорос-депутат (иногда – его представитель). Выходит ветеран. Выходит сраный министр культуры и еще кто-то в этом же роде.

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

    Всем учителям известно, как трудно удержать внимание ребенка хотя бы из-за физиологических причин. Урок подготовишки длится 25 минут, первоклассника – 30 минут, и так далее с шагом в 5 минут. Только к третьему классу урок начинает длиться стандартный академический час. Так почему же вы, учителя-завучи-директор, из года в год закатываете линейку на час с лишним?

    Соревнования в спортивных школах ничуть не лучше. Опять же парадокс – каждый тренер должен уметь организовать детей. Заставить слушаться группу из 15 человек это особый навык. Но правильно организовать соревнования никто не умеет.

    Зашли в зал и ждут. Участники на месте, судьи на месте, родители расселись. Нет, сука, чего-то ждут. Слово директору школы. Слово организатору. Гимн России. И только потом, с постоянными задержками, поломками микрофона, потерей нужных бумажек, начинаются выступления детей.

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

    А детские концерты! Выступающим по 6-8 лет, концерт длится 1 час 20 минут! Те, кто в конце, к моменту выступления становятся как мочалки. Организаторы издеваются над родителями: каждый же пришел только ради своего ребенка. Почему я должен сначала высидеть 15 номеров? Почему нельзя провести два концерта?

    Та же история с мультфильмами и представлениями. Почему нельзя поставить пьесу на 45 минут вместо полутора часов? Ну или час максимум. Это же долго! Все сцены очевидно затянуты. Ребенок теряет суть повествования. Главные идеи в детских произведениях просты, их невозможно растянуть на час без очевидных искажений.

    Откуда эта манера впихнуть в детей как можно больше? Наоборот, даже с точки зрения бизнеса короткие постановки выгодней: ребенок (и родитель) меньше устанет, значит, останется больше потенциала для потребления других услуг.

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

    Лично мне с возрастом все больше и больше книг и фильмов кажутся затянутыми. Короче надо, короче! Техническую литературу невозможно читать: одну и ту же мысль обсасывают на 10 страницах. Предложения порой столь похожи, что напоминают копипасту. Актеры в фильмах начинают конфликт из-за ничего, проблемы надуманны, сцены длятся дольше, чем нужно. Вертится мысль – а не пора бы вам свалить уже из кадра или занять зрителя чем-то поинтересней?

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

  • Итоги 2017 года

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

    Стал больше писать в блог. Написал 99 постов не считая этого. Значит, всего 100. Красиво.

    Повысил долю английского в блоге. Где-то каждый пятый пост на английском. Писать на нем медленней; порой трудно передать мысль в нужном ключе.

    В этом году блогу стукнуло 5 лет – юбилей!

    Изнемогая в Турции, опубликовал подробное руководство по переходу с PostgreSQL на Datomic. Статья выстрелила: ее разместили на кложурных ресурсах и Hacker News. В News. В течение недели в блог заходили тысячи человек из англоязычной аудитории.

    Публиковался в IndieHackers с рассказом про Queryfeed.

    Завел Телеграм-канал в параллель блогу.

    Весь год проводил митапы в нашем клубе Рефакторинга. Видосы – на нашем канале и сайте.

    Стал читать про криптовалюты. Книга Mastering Bitcoin – хороша, но больно занудна.

    Путешествовал! Ездил в Берлин на Евро-кложу и в Балтимор на юбилейную конфу. В первый раз в жизни побывал в США. По ссылкам – отчеты о городах.

    Стримил Кложу, в т.ч. и на английском. К сожалению, так и не сделал это занятие регулярным.

    Участвовал в Хайлоад-Капе! Ничего не занял, но был дикий драйв. Выгородил Кложу с ее Датомиком. Отчитался на английском.

    Написал и поддерживаю свою первую библиотеку на Кложе, которой действительно пользуются.

    Вместо с Никитой и Рахимом стал писать в блог Grumpy – это где жалуются на плохой дизайн. Изливаю там душу.

    В этом году организм сказал твердое нет долгой работе за компом: заболели шея и руки. Как выкрутился расскажу в следующем году.

    Уволился из проекта. Осталась неделя в январе, но это мелочи.

    Поставил самую большую в жизни елку.

    С праздничком!

  • Документы

    Перевожу Гугло-документы в обычный офис. Купил у Микрософта офисный пакет на год, не нарадуюсь. Работает очень быстро. Файлы открываются мгновенно, как-никак нативный C++ вместо Джаваскрипта.

    Конечно, офисный редактор на Джаваскрипте это целое искусство, но меня как пользователя это не должно волновать. Правда в том, что в нативном офисе можно открыть 10 документов и спокойно переключаться по ним в течение дня.

    В Гугловом офисе каждая вкладка живет в изолированном пространстве. Хром в произвольном порядке выгружает вкладки на диск. Казалось, 10 минут назад ты был в этом документе, переключаешься – и 5 секунд ждешь, пока вкладка подгрузится.

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

    Интерфейс Гугло-дравйва крайне убог и тоже тормозит. Создать в нем папку и скопировать файлы это целая история. Или ставь клиент Драйва для синхронизации с локальной папкой, но там тоже полная жесть.

    Случаются странные баги, например, пропадают содержания картинок. Если их подвигать на пиксель влево-вправо, они опять появляются.

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

    Личные документы (особенно финансовые) следует хранить в нативном формате. Потому что порой ищешь данные за прошлый год и нужно БЫСТРО открыть 10 документов. В Хроме это просто невозможно.

    Короче, я не против веб-приложений, которые косят под нативчик, тех же Слаки или Атома, например. Можно поиграться с ними, если время отклика не поджимает. Скажем, скорость доставки сообщений в Слаке мне вообще безразлична. А вот работа с документами это диаметрально другое. Оно стоит годовой подписки на нативную программу.

  • Егор о поездке в Воронеж

    The meetup was really good. I would say, it was one of the best events I’ve took participation in. People were very into the topics, had a lot of questions, were aggressive and friendly enough) They paid for the entire travel, we had lunch, dinner, everything. A+ experience!

    Так-то!

  • Смерть в Фейсбуке

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

    Какой плохой Фейсбук.

    Прежде всего, никакой он ей не друг. В тексте явно написано, что он комментировал и лайкал ее посты, но ни слова о том, что она читала и лайкала его. Это была однонаправленная связь: он проявлял интерес к ней, она к нему нет. Поэтому он видел ее посты, а она его — нет.

    Лично у меня нет претензий к алгоритму Фейсбука.

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

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

    Предположим, тот чел не умер, а спокойно живет дольше. Общались бы они с той дурой? Поехали бы к друг другу в гости? Нет же. Зато смерть псевдо-друга, которого ты знаешь только по лайкам, отличный повод погнать на Фейсбук, выступить перед журналистами, нагнать трафика.

    Короче, некрасиво пиариться на смерти человека, к которому не имеешь отношения.

  • Встреча с Егором. Видео

    Егор выступил в клубе Глубокого Рефакторинга:

    Особенно рекомендую второй доклад:

  • Тентакли и прокси

    Значит, купил я ноду на Digital Ocean с целью поднять на ней прокси для обхода блокировок. На LinkedIn зайти, например. Кто не знает, на Маке и Линуксе это делается командой

    ssh -D 8123 -f -C -q -N user@your.ip.address
    

    Далее, чтобы гнать не весь трафик через ноду а только часть (иначе будет тормозить) в Хром ставится расширение Proxy SwitchySharp, которое позволяет менять соединение по правилам. Например, все, что матчится на linkedin.com идет через прокси, остальное – по прямому соединению.

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

    Первая же ссылка говорила за себя: в названии было что-то про аниме, группы и тентакли. Открыл – работает.

    В то же самое время я обсуждал с заказчиком свое увольнение. Отвечая на вопрос в духе “Иван, чем вы думаете заняться после выхода из проекта”, я нажал что-то левое, и ссылка из буфера обмена уходит заказчику.

    А у него в Швейцарии нет Роскомнадзора и некому защитить его от тентаклей.

    Ясное дело, удалил эту ссылку с быстротой молнии, но сих пор не знаю, видел он или нет. Заблокирован ли тот сайт в его стране? Успела ли открыться превьюшка?

    Больше никаких таких ссылочек во время общения с заказчиком.

  • Канал в Телеграме

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

    Вступайте: https://t.me/igrishaev_blog

  • Отвечу на вопросы

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

    Какие вопросы мне задавать? Хотя бы на следующие темы:

    • программирование и разработка ПО,
    • функциональный подход,
    • Кложа, Емакс,
    • работа, в т.ч. удаленная,
    • книги, в т.ч. детские (у меня хорошая подборка книг для детей),
    • организация рабочего времени, “сделывание” задач,
    • переезд в другой город,
    • английский,
    • опен-сорс.

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

    Почта ivan@grishaev.me

Страница 43 из 79