Ваш улюблений design pattern

Всім привіт.
Я Сергій Моренець, технічний письменник, спікер, проводжу вебінари та тренінги з розробки.
Нещодавно з’явилася ідея зробити вебінар з патернів, але кількість патернів зростає з кожним днем, тому вирішив поцікавитися, а які патерни зараз найбільш затребувані та популярні.
Це можуть бути і GoF патерни, enterprise, мікросервісні, загалом усе, що є в арсеналі розробника.
Тому напишіть будь ласка який патерн ви найчастіше використовуєте (найкраще знаєте) у роботі, і якщо нескладно, то чому.

👍НравитсяПонравилось1
В избранноеВ избранном0
LinkedIn

Лучшие комментарии пропустить

Мой любимый паттерн — отсутствие в коде паттернов только ради паттернов

что значит любимый паттен? их по любви используют, а не по потребности ?

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Паб-саб ще дуже помічний

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

Не піду на тренінг

в эту компанию так и просится WTF

RYTTJ — reassign your task to a junior (if you can)

Structure-event-based programming. Найближче до реального світу.

Омг. Точно. Туду лист. dou.ua/...​rums/topic/35472/#2279775

Следите за руками. Доменная модель

    {
          "Todos": [{"Task": "Test", "Description":"Test"}]
    }

и Шарп код

   Client.SetDefaultCollection("Todos")
                  .OpenForm(1);

Отрисовывается скрин с гридом, в котором можно добавлять редактировать и удалять строки.
Все сохраняется в джисон.
Время девелопа проекта: 54 секунды 123 миллисекунд

В этот говнокод вошли Орм, Маппер, Дто, Рест, База данных, Хранимки, Джанго фреймворк, CRUD репозиторий
аоп меджик.

DRUDOM
Development and Research Under Deficit Of Materials

Все эти перечисленные паттерны ООП внизу это вчерашний день, по сравннеию с тем что может предложить АОП. Я вам приведу пример. Представьте вы строите систему. Вы ее собираете со своими обычными паттернами как конструктор. Здесь добавили компоненту чтобы рисовать контролы, здесь ходить в базу, здесь строить графики и так далее. У вас этот конструктор работает как сборная солянка. Каждая компонента имеет свою апишечку, в которой четко прописан контракт что она умеет делать. А теперь представьте что система у вас построена с применением паттерна АОП. Тоесть когда вы добавляете новую компоненту, например логирование, у вас начинает логироваться абсолютно все, даже если компоненты которые вы использовали никогда не были расчитаны на это. Потом вы добавили секурити и у вас это свойство распространилось глобально, на все, как волна. Пагинация, кеширование, локализация, хранение данных, транзакции .... АОП строит систему так, что каждая новая компонента распространяет свои свойства «на всех» даже если все остальные компоненты не были на это расчитаны. Такая система не собирается как набор угловатых кубиков, она собирается как многомерный куб. Новые требования заказчиков, которые раньше приводили к полному переписыванию системы, как попытка прогнулть ломиком закостенелый каркас из ваших любимых ООП патернов, залетают туда к обеду, в рантайме, даже без перезагрузки системы.

Если под АОП имеется в виду — aspect-oriented-programming, спасибо но нет. В результате получаетчя солюшн который непонятно как работает без сакрального знания.
AOP хорошо подходит для реализации NFR, типа того же логирования/локализации, но никак не бизнес-логики

Так осталось разобраться что есть бизнесс логика. Потому что бизнесс логика на 95% (а может и больше) состоит из аспектов. Но это еще половина дела, самое интересное то, что именно аспектные вещи добавляются в обычную систему наиболее болезненно. Именно они являются причиной говнокода. Например если строилась система и у нее не было никакого кеширования, секурити, мультизадачности, пагинации и локализации, а потом а вдруг оказалось что это все надо ... то это фактически приговор к полному переписыванию приложения. А сам код приложения будет крайне нетривиален, потому что любое смешивание аспектов традиционным способом в одной плоскости ведет к жутчайшему говнокоду.

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

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

мультизадачности

Не совсем понимаю как aop поможет с «мультизадачностью» (может многопоточностью?)

пагинации

То же самое — не совсем понимаю как aop поможет

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

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

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

кеширования, секурити, мультизадачности, пагинации и локализации

нужно разрушать фундамент, то я могу только сказатать, что как раз в твоем случае собирали POC, которое нужно переписать.

Не совсем понимаю как aop поможет с «мультизадачностью» (может многопоточностью?)

Элементарно. Мальтизадачность внезапно это тоже аспект. Это всеголишь новое свойство системы, которое говорит, что теперь эти задачи могут выполнятся параллельно.
Вообще я думаю что вас путает термин АОП, к которому вы уже привыкли как всякие там атрибуты классов в джаве или шарпе. То что сейчас реализовано под флагами АОП, на 90% маркетинг и на 10% пользы. А должно быть наоборот.

пагинации
То же самое — не совсем понимаю как aop поможет

Пагинация это тоже аспект. Этот аспект говорит что теперь мы не все данные подгружаем, а показываем порциями. Тоесть еще раз. Если систему правильно разложить на аспекты, настоящей бизнесс логики останется совсем чуть-чуть. А читать ее сможет даже 5ти летний ребенок.

Підхід в OpenMP наприклад досить близький до аспектного

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

В этом и прелесть аспектов. Аспект строится по принципу
«Если чтото крякает как утка, летает как утка и ходит как утка то это и есть утка».
Другими словами если чтото выглядит как пароль (например длинный хеш) то это и есть пароль и он мылится автоматически. А вот в обычном коде вполне можно провтыкать замылить еще одно из 100500 мест в коде.

Другими словами если чтото выглядит как пароль (например длинный хеш) то это и есть пароль и он мылится автоматически.

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

Да, аспекты линзируют друг друга. Это сквозная логика которая наслаивается друг на друга. Каждый аспект дает принципиально новое свойство системе.

Но чтобы написать новый аспект, нужно:
1) Понимать, как система работает в целом, со всеми существующими поддерживаемыми аспектами
2) Обновить уже существующие аспекты, чтобы они правильно себя вели, когда включат наш новый аспект
3) Предусмотреть, какие новые аспекты в будущем могут добавить, чтобы им было куда вставить хуки в код аспекта, который мы сейчас разрабатываем
И вот тут сложность и связность (coupling) зашкаливает. Куда тем плагинам.

На самом деле нет. Чтобы все аспекты работали сообща, они всеголишь должни иметь общий знаменатель. Приведу пример. В теме субд строительные верфи я говорил о субд и сначала было очевидно что аспекты хорошо применяются на фундаментальном уровне, на уровне хранения данных (кеширование, транзакционность, логирование, секурити и тд). Потом мне нужно было построить упрощенную такую же субд, но для фронта. И я начал писать свой фронт фреимворк. В какойто момент стало понятно, что нет никакой принципальной разницы между отрисовкой контрола (верхняя точка) и транзакционностью и хранением данных (нижняя точка). Все это аспекты. Я добавил системе свойство пейджинг и оно распротранилось не только на гриды, но и на деревья и даже на группы контролов. Добавил кнопку поиск фулл текст серч, наподобии как в настройках хрома и теперь поиск работает по всем контролам везде, а выдача еще и пейджируется. Добавил локализацию и все распространилось от нижней точки до верхней. Кеширование тоже самое. Больше 20 самых разных аспектов.

Короче весь бекенд Доу (это две группы юзеров, админы и пользователи, апрув тем, добавление темы, мой профайл, древовидное дерево, лайки, редактирование тем, визард по регистрации пользователя, визард по созданию темы и тд) я собрал за месяц. Но, месяц я по сути фиксил баги в нетривиальном движке, реально весь бекенд Доу (ну или пускай будет 80% доу) со всей логикой это 200 совершенно тривиальных строк кода, которые можно было набрать за 30-40 минут. 80% ф-сти вообще накликано мышкой как часть конфигурации. А новые фичи типа забаненных юзеров или подгрузки дерева комментариев до определенной вложенности туда залетают за минуты. Каждый Аспект дает новое глобальное свойство системе. А сама система программируется, больше похоже на Эксель где ты забиваешь где и что ты хочешь видеть прямо на юае.

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

А базируется система на чем? На Джанго? Или каком-то более мощном фреймворке?
Хотелось бы увидеть эти 200 строк кода, описывающих форум. Подозреваю, что в движке весь форум почти готов, а 200 строк — это просто конфиг движка.
У нас в телефонии внутри роутера было больше сотни настроек, а с учетом массивов (несколько учеток, к примеру) конфиг вполне мог до 200 строк дорасти.

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

private void OpenArticles()
        {
            Client.SetDefaultCollection("Articles")
                  .GetWhere(new { IsApproved = true })
                  .OpenForm();
        }

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

Ну так ты написал фреймворк для форумов, и в нем куча кода. А 200 строк — это конфиг пайплайнов на DSL. Призываю Кожаева!

Ну во-первых я вообще писал базу данных которая хранит документы. Единица хранения для базы данных это джисон. Я не думаю что такая структура данных как джисон, заточена под форум доу.

На сегодня я уже выделил 43 аспекта (я их называнию dimension или измерение). Они описывают почти все, от транзакционности, как хранить данные, где хранить данные, как их синхронизировать, локализировать, типизировать, конвертировать, шифровать, отрисовывать, валидировать, высчитывать и так далее.

Ну во-первых я вообще писал базу данных которая хранит документы. Единица хранения для базы данных это джисон. Я не думаю что такая структура данных как джисон, заточена под форум доу.

DocumentDB и json — это несколько разные вещи, просто часто используются вместе. В целом как раз документные базы для форумов очень даже и подходят — так как strong consistency тут не требуется. А в чем хранить — json просто удобен чтобы избегать дополнительных преобразований

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

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

Кстате что еще интересно. Как побочный эффект я получил по настоящему правильную микросервисную архитектуру. Хотя все эти «микросервисы» и живут в едином монолите, но у каждого такого сервиса есть важные свойства. 1. Сервис почти не имеет перекрестных связей с другими сервисами. Он изолирован. 2. Каждый сервис имеет свою микро базу данных, часто она состоит всего из одного джисон файла который его конфигуррирует, но не обязательно. 3. Все микросервисы могут присоединятся и отсоединятся в рантайме (без рефлексии!). Привет деплой на лету без остановки монолита.
4. И наконец самое главное. Микросервисы строят правильный фрактал, в центре которого документ, а вокруг аспекты наделяющего его поведением в разных измерениях.
Стоит ли говорить, что фрактал это настолько фундаментальная структура, которой можно описать практически все. Эта штука которая повторяется от микро мира до макро мира. Поэтому я вдвойне уверен что это будет работать.

. 3. Все микросервисы могут присоединятся и отсоединятся в рантайме (без рефлексии!). Привет деплой на лету без остановки монолита.

Поздравляю, ты только что изобрел en.wikipedia.org/wiki/OSGi

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

Ну смотри. OpenForm() это разве база? Или джейсон? Что этот код делает?

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

Теперь живите с этим знанием :)

Так вот к 200 строкам надо добавить количество строк в этом фронт фреймворке.
200 строк это DSL.
А код фронт фреймворка — это и есть реальный код проекта для написания форума.

Так вот к 200 строкам надо добавить количество строк в этом фронт фреймворке.

Это уже не фреймворк. Это уже ближе к платформе (поскольку там своя субд свой транспорт и фронт фреймворк), а может и к новой парадигме программирования. На самом деле, ниодин из аспектов не относится напрямую к Доу функциональности или к форумам. Другими словами если я захочу написать второй Гитлаб, или Атлассиан, или СРМ для продажи товаров, мне пригодятся все уже написанные однажды дименшины. Я переиспользую визард там где нужен визард, пагинацию там где нужна пагинация, кеширование там где нужна скорость и секурити там где нужно разделение прав. И будет все тоже самое. Вы можете предложить какуюто новую идею для приложения, я попробую ее провалидировать, насколько ее тяжело описать на существующем функционале (с поправкой конечно, что я не пишу высокотехнологичные вещи вроде архиваторов или кодеков например, видео игрушек и тд).

Document = 0,
Index = 1,
History = 2,
Sync = 3,
ExtendedStorage = 4,
Pagination = 5,
Wizard = 6,
Security = 7,
Encryption = 8,
Handlers = 9,
Profiler = 10,
Transaction = 11,
Parallel = 12,
OperationLog = 13,
Note = 14,
Learn = 15,
Version = 16,
Cache = 17,
Language = 18,
SelfTest = 19,
Undo = 20,
UI = 21,
AutoComplete = 22,
Event = 23,
Filter = 24,
Validation = 25,
Progress = 26,
Suggest = 27,
Auth = 28,
Computed = 29,
Debug = 30,
Log = 31,
AutoRevert = 32,
Convert = 33,
Timer = 34,
LastAccess = 35,
LifeTime = 36,
Sort = 37,
Patch = 38,
Menu = 39,
REST = 40,
ToolTip = 41,
Modify = 42,
Default = 43

Ну так ты пишешь свой Джанго. На нем тоже сайты делаются в несколько сот строк, вроде.

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

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

Да и как на Джанго написать аналог Доу за 40 минут честно говоря не представляю. Я честно говоря когда вижу скрины кода, меня уже начинает подташнивать. Похоже я уже получил этот сдвиг и увидел как на самом деле можно строить системы и мозг не хочет обратно возвращатся в этот мезозойский век. Где приложение которое ровно нихера не делает, имеет под 20 скринов кода какихто «патернов».

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

Идеи ?
Сегодня валидировал кстате идею в уме своего интернет провайдера. Есть тарифные планы. Есть пользователи и админы. Каждый месяц высчитывается баланс. Пользователи могут приостановить интернет и баланс должен замораживаться.
Интересная задача, но недостаточно сложная чтобы ее не написать максимум за 1 час, конечно при условии что вся платформа уже хорошо работает (на самом деле нет, еще много работы).

Есть тарифные планы. Есть пользователи и админы. Каждый месяц высчитывается баланс. Пользователи могут приостановить интернет

Это в лучшем случае 5% от интернет-провайдера :))))

Это в лучшем случае 5% от интернет-провайдера :))))

А что там еще ? Остальное наверное с хардвар связано, роутеры там всякие маршрутизаторы, это я не покрываю. Точней я не готов строить планы настолько далеко.

чтото выглядит как пароль (например длинный хеш)

Кроме паролей есть еще масса другой персональной информации.
ИНН/SSN, номера кредиток/паспортов, да и те же телефоны/e-mailы. До фига видов уток получается

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

патерн ви найчастіше використовуєте (найкраще знаєте) у роботі, і якщо нескладно, то чому.

Ловлю себя на мысли, что чаще всего использую chain of responsibility и observer.

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

Область применения — чаще всего, когда есть с одной стороны одна логика, с разными направлениями реализации. К примеру, есть транскодинг медиа файлов, но есть аудио файлы, и есть видео файлы, и для транскодинга каждого типа нужен свой набор сервисов и нам надо как минимум 2 входных точки для аудио и видео транскодинга.

Другой это Observer, но в симфони благодаря ивентам и подписчикам из коробки, писать как бы и нечего по этому поводу :)

VIPER.
Кроме меня в этом п****це никто сразу не разберётся.

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

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

И это правильно. Но и количество персонала стремится к 1, притом не полная нагрузка. Но сам факт, что обычно под ковром столько мусора, что всей командой месяц работать, чтобы его разгрести. Но если не разгребать — ценность проекта падает в 2-4 раза, а затраты на саппорт прошибают днище, притом не только у саппорта.

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

Поймал себя на мысли, что давно уже не задумывался над

який патерн ви найчастіше використовуєте (найкраще знаєте) у роботі

Поскольку почти все мои проекты Spring-based, то все соответствующие паттерны, явно или неявно — фреймворк ставит в определенные рамки

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

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

Паттерны — это то, что именно ты пользуешь, чтобы твой код был читабельным

Когда как: github.com/...​FizzBuzzEnterpriseEdition :)

Я имел виду, что если ты используешь Спринг-проекты, у тебя автоматически появляются синглтоны, MVC/фасады, репозитории (Spring Data), EIP (Spring Integration) и т.д. Надо очень и очень сильно постараться, чтобы их не использовать

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

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

Как же до слёз знакомо выглядит этот FizzBuzzEnterpriseEdition — и ведь не шутка ж ни разу, оно реально так работает, и люди, которые его творят, свято верят что это лучший в мире способ писать понятный код.

Один из главых плюсов юнит-тестов, которого много кто не понимает — не цифра покрытия в процентах, а то, что они если они пишутся с трудом — явная индикация что с кодом что-то не так.

Как раз наоборот. Если код сложно поддаётся написанию тестов (которые тем не менее просты для чтения), значи он весьма самодостаточен и компактен. Такой нет смысла покрывать «процентами», но имеет смысл иметь тест-поинты в самом коде.

Абсолютное большинство покрытий тестами — кроют исключительно мусор. Грубо говоря, контроль, что никто в дальнейшем не внесёт случайно опечаток. Сама логика чаще всего не тестируется — это ж сложнее.

Как раз наоборот. Если код сложно поддаётся написанию тестов (которые тем не менее просты для чтения), значи он весьма самодостаточен и компактен. Такой нет смысла покрывать «процентами», но имеет смысл иметь тест-поинты в самом коде.

защитное программирование... Ничего общего с юнит тестами у него нет

Защитное программирование — это немного другое, это сильно дороже и с мозгами надо делать, а не паттерны зубрить и на литкод онанировать. Тесты дешевле. Хотя и результат хуже.

Разумеется, юнит-тесты призваны тестировать юниты, а не покрывать строки кода. Но поди докажи это бюрократам.

имеет смысл иметь тест-поинты в самом коде

это одна из его частей

Я тут якраз досить цікавий блог знайшов про зв’язок патернів та теорії категорій. blog.ploeh.dk/...​terns-to-category-theory
Тому рекомендую.

То щось лише для математиків.
В патернів суть була в тому, що вони простою мовою пояснюють як, коли та навіщо може стати в нагоді певне рішення.

У тому і справа, що не для математиків. Це може перший ресурс що я знайшов, який пояснює теорію категорій мовою, зрозумілою ООП програмістам. А на теорії категорій базується доволі багато сучасних засобів у різних мовах програмування та бібліотеках. Наприклад багато змін у сучасній java ведеться для кращої підтримки алгебраїчних типів. Наприклад це records, sealed types, pattern matching for switch.

Ну от я її не вчив, і спокійно собі програмую на С++ (й часом на Пітоні). Тому вважаю, що коли мова програмування потребує знання математики — то вона не буде загальновживаною.

то вона не буде загальновживаною.

тому що
(нещодавна поповнив свою копілку)

Evgeny Kobzev в FB рассказывает

Мы тут решали задачу прогнозирования сроков создания платёжек для клиентов. У нас были данные за несколько месяцев, напустили на них ML, получили точность под 60% в первом подходе. Потом я вспомнил, что в универе нам на тервере говорили, что распределение Пуассона это число людей в очереди, взяли формулы оттуда, выкинули ML, сходу получили точность под 90%.
Забавно, что максимально тупой классификатор типа «если поставлено в первой половине дня, то будет сделано через 3 часа, а если во второй, то завтра» (немного утрирую), давал такую же точность 😂 Мы там, конечно, людей поднавалили, чтобы платёжки делались побыстрее, но в целом это учит тому, что многие вещи решаются просто.

Помню я только закончил универ и делал проект, где нужно было отрисовать диаграмму Ганта в вебе, это год 2001 был, из доступных средств рисования — можно было картинку размером в пиксель бахнуть. Ну я сразу конечно понял, что точками можно любую линию нарисовать, для этого есть специальный алгоритм — алгоритм Брезенхема и реализовал его. На больших диаграммах это тормозило. Мой коллега, выпускник технического вуза, с мозгом не замутнённым алгоритмами, заметил, что все линии, которые надо рисовать, строго горизонтальные или вертикальные. И можно этого добиться бахнув прямоугольный пустой блок, у которого 2 нужные границы включены. Всё сразу залетало, моего Брезенхема оставили для рисования заострённого конца у стрелочки 😂

Потом мы начали проверять, что диаграмма не содержит циклов. Хранилось всё в базе данных и мы средствами базы реализовали поиск циклов, просто поиск в глубину через рекурсию, который вызывался при каждом изменении базы в триггере. Однажды клиент сделал в диаграмме более 32 связей и ms sql написал ему: я не буду поддерживать рекурсию глубиной вложенности больше 32. Я тогда придумал как переписать это через поиск в ширину на sql, хранить во временной таблице волновой фронт и строить в другой временной таблице следующий фронт. Очень этим гордился))) А потом коллега из технического вуза опять заметил, что если предыдущий шаг в диаграмме Ганта всегда заканчивается раньше, чем начинается следующий, то циклов возникнуть не может. И нужно просто всё выкинуть и делать вот такую простую и понятную проверку дат шагов. Мы, люди, склонны усложнять, а «многознание уму не научает» 😂

Недавно меня спрашивали какой из продвинутых алгоритмов, которые я в универе изучал, пригодился мне в реальной работе. Так вот — я Брезенхемом птичку в конце стрелочки рисовал!))

Як на мене це дуже вдалий приклад як знання математики (розподілу Пуассона) допомагає вирішувати реальні задачі.

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

якби сам не викидав математику, то приклади б не наводив.

у ціх прикладах як в тому анекдоті
— ми тут не фізиків теоретиків готуємо, а інженерів. Кицька не може рухатись більш швидкості звука. тому вона повинна сидіти! (щоб прив’язана до хвоста банка з консерви не гриміла)

математика дає — загальне рішення. а інженеру треба — конкретне, якє враховує конкретні обмеження. якщо у «формулі» є ці обмеження — то математика дасть

як яскраво це видко з проблемами з теорією струн
все так круто, аж дух спирає
але кількість прогнозованих ландшафтів 10^100, а ймовірніше 10^500, не виключено, що їх взагалі нескінченне число
а ми маємо конкретний Всесвіт, і повне мовчання теорії чому і як реалізувався цей варіант

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

звісно що
подумати заздалегіть про весь маршрут — корисно
і як щось надихає у роботі — то теж корисно, наприклад гра в джаз бенд: Алан Кей починав як джазовий музикант, викладав гру на гітарі, працював композитором, а знаємо його як автора Smalltalk
так само й теоркат, надихає — круто! але чи є він обов’язковим?

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

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

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

математика корисна для аналізу вже готового рішення: «круто! а давай ка ми порахуємо... ох йоб»
ось круто виглядає рішення! а давай ка встановимо складність... ох O(n!)

але безсила — для знаходшення цього рішення
а навіть у самому примітивному программуванні — треба знайти рішення :)

...часте питання від дітей яких вчу программуванню
— а на смарт потім мою гру можна буде залити?
— а в тебе вже є гра?

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

Це дуже залежить від складності задач, які ви розв’язуєте. Чим вище складність, тим вищий рівень абстракції вона потребує.

зависокі рівні абстракції непрактичні:
вони не гнучкі, а от когнитивне навантаження збільшують

ну і сам природа складності буває різною

типово ентерпрайзна
є код який описує оту бізнес логіку, яка й не логіка, а набір тез від бізнеса та бі-аналітика, які якось-накось узагальнені.
і з часом — з’являются ще тези, які треба всунути в вже неакутальне узальнення, та ще й так, щоб
1. не переписувати все з нуля
2. персистентні данні — не переконвертувати

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

От вже не думав що доведеться програмістам доводити, що математика існує :)

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

Все це досить складні речі, які важко збагнути одній людині. Без абстракцій і композиції все це було б просто неможливо зробити. Тільки завдяки абстракції і композиції ви можете використовувати у своїх програмах те, що зроблено іншими програмістами. Які до речі знають математику, але абстрагують її для вас до такого рівня, щоб вам вона здавалась «неіснуючою».

От вже не думав що доведеться програмістам доводити, що математика існує :)

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

Бо жодний язик програмування був би неможливим без математики

а так да, у нас у шлунку ціли екосистеми бактерій.
і що, для перетравлювання їжі треба бути біологом? гастроентерологом?

а от ви пишите українською — маєте філологічну освіту? чи лінгвіст?

Все це досить складні речі, які важко збагнути одній людині.

звісно що так.

Без абстракцій і композиції все це було б просто неможливо зробити

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

ви можете використовувати у своїх програмах те, що зроблено іншими програмістами

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

люблю брати за приклад «вебмайстра на Wordpress».
він як використовує зроблене іншими програмістами?
builtwith.com:
WordPress Usage Statistics
Top 1m 35.05%
Total Live 30,462,105

щоб вам вона здавалась «неіснуючою».

вона й для вас «не існує» :)

поясню
якщо по якості типового программного кода двох прорамістів не можна встановити хто з них фанат рок музики, а хто взагалі ніяку музику не слухає, то казати про вплив музики на якість кода — можна чи ні?
якщо ні — то «рок музики не існує»

Які до речі знають математику, але абстрагують її для вас до такого рівня

це ще велике питання, знають вони її чи ні :)
з опису роботи програміста над Oracle DB що нашумів пару років тому на HN — якось те знання математики не видко :)
звісно, він думаю дещо краще знає її аніж «вебмайстер на Wordpress».
я теж логаріфми люблю використовувати. дуже зручно м’яко зрізати топові значення у виборках.

Double dispatch

Синглтон и Сервис Локатор!

Не паттерн, але ValueObject — дуже не дооцінють. Рідко коли можна побачити його, але він однозначно спрощує дизайн систем.
І в ту ж копілку недооцінених — cтара, добра Factory . Особливо починаєш її цінувати при якому-не-якому Layered Design (для початку і це було б непогано, не те, що DDD) та при написанні UnitTest.

І в ту ж копілку недооцінених — cтара, добра Factory

Помогите разобраться. Допустим фабричный метод генерирует 3 разных класса. У каждого класса есть по 4-5 зависимостей в конструкторе. Как эти зависимости туда пробросить при инстанцировании?

КМК обычно эти зависимости статические. Например, что-то ОС- или платформенно-спацифическое. Вот в начале main() парсятся там ключики командной строки, конфиг и другая хрень. Эта вся хрень превращается в (глобальные) настройки запуска программы. Все настройки пишутся в глобальный объект настроек. Потом этот объект валидирует себя на самосогласованность ключиков. Если проблема — то main() матюкается и выходит. Если провалидировался — мы можем изнутри фабрики запрашивать в этом глобальном объекте настроек те самые ключики, которые нам нужны, чтобы сконструировать модули в соответствии со спецификой режима, в котором запустили систему.
Это если я правильно понял вопрос.

«Talk is cheap. Show me the code.»

namespace Example
{
    interface IExecutableTransaction
    {
        public void Execute();
        public enum TransactionOperation
        {
            Deposit,
            Withdraw
        }
    }

    class DepositTransaction: IExecutableTransaction
    {
        //...
        public DepositTransaction(
            WalletId _id,
            MoneyValueObject money, 
            IDbContext db,
            IStatusManager statusManager
            //...
        ) {
            //...
        }

        public void Execute()
        {
            //do something
        }
    }
    
    class WithdrawTransaction: IExecutableTransaction
    {
        //...
        public WithdrawTransaction(
            WalletId _id,
            MoneyValueObject money, 
            IDbContext db,
            IStatusManager statusManager
            //...
        ) {
            //...
        }

        public void Execute()
        {
            //do something
        }
    }

    interface ITransactionFactory
    {
        public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money,
            IExecutableTransaction.TransactionOperation operation);
    }

    class TransactionFactory: ITransactionFactory
    {
        private readonly ITransactionFactory _depositTransactionFactory;
        public readonly ITransactionFactory _withdrawTransactionFactory;

        public TransactionFactory(
            ITransactionFactory depositTransactionFactory,
            ITransactionFactory withdrawTransactionFactory
            //..
        ) {
            _depositTransactionFactory = depositTransactionFactory;
            WithdrawTransactionFactory = withdrawTransactionFactory;
        }

        public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money, IExecutableTransaction.TransactionOperation operation)
        {
            if (operation.Equals(IExecutableTransaction.TransactionOperation.Deposit))
            {
                return _depositTransactionFactory.Create(walletId, money);
            }
            
            if (operation.Equals(IExecutableTransaction.TransactionOperation.Withdraw))
            {
                return _depositTransactionFactory.Create(walletId, money);
            }

            throw new ArgumentException($"Transaction {operation} is not supported");
        }
    }

    class DepositTransactionFactory: ITransactionFactory
    {
        private readonly IDbContext _db;
        private readonly IStatusManager _statusManager;

        public DepositTransactionFactory(
            IDbContext db,
            IStatusManager statusManager
            //...
        )
        {
            _db = db;
            _statusManager = statusManager;
        }

        public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money,
            IExecutableTransaction.TransactionOperation operation)
        {
            return new DepositTransaction(_db, _statusManager, walletId, money);
        }
    }
    
    class WithdrawTransactionFactory: ITransactionFactory
    {
        private readonly IDbContext _db;
        private readonly IStatusManager _statusManager;

        public WithdrawTransactionFactory(
            IDbContext db,
            IStatusManager statusManager
            //...
        ) {
            _db = db;
            _statusManager = statusManager;
        }

        public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money,
            IExecutableTransaction.TransactionOperation operation)
        {
            return new WithdrawTransaction(_db, _statusManager, walletId, money);
        }
    }
    
    class WalletAggreagate
    {
        private readonly WalletId _id;
        private readonly ITransactionFactory _transactionFactory;

        public WalletAggreagate(WalletId id, ITransactionFactory transactionFactory)
        {
            _id = id;
            _transactionFactory = transactionFactory;
        }

        public void Deposit(MoneyValueObject money)
        {
            var transaction = _transactionFactory.Create(_id, money, IExecutableTransaction.TransactionOperation.Deposit);

            transaction.Execute();
        }
        
        public void Withdraw(MoneyValueObject money)
        {
            var transaction = _transactionFactory.Create(_id, money, IExecutableTransaction.TransactionOperation.Withdraw);

            transaction.Execute();
        }
    }
}

Таким чином, в нас є аггрегат (агрегат створюється фабрикою, звісно ж), в котрому є фабрика, котра генерує різні транзакції. Можна піти далі і розбити RDM Wallet на дві: IDepositableWallet, IWithdrawableWallet і в залежності від нашого UseCase констуювати ту чи іншу RDM з відповідного UseCase:

class DepositHandler
    {
        private readonly IDepositableWalletFactory _factory;
        private readonly IWalletStorage _storage;

        public DepositHandler(IWalletStorage storage, IDepositableWalletFactory factory)
        {
            _storage = storage;
            _factory = factory;
        }

        public Wallet Handle(DepositCommand command)
        {
            var wallet = _factory.Create(command.WalletId);

            wallet.Deposit(command.Money);
            
            _storage.Store(wallet);

            return wallet;
        }
    }

І, наприклад ось так викликав би з UI layer:

class WalletController
    {
        private readonly IMediator _mediator;
        private readonly IMapper _mapper;

        public WalletController(IMediator mediator, IMapper mapper)
        {
            _mediator = mediator;
            _mapper = mapper;
        }
        
        public async Task<IActionResult> Deposit([FromBody] DepositRequest request)
        {
            var command = _mapper.Map<DepositCommand>(request);
            var wallet = await _mediator.Send(command, HttpContext.RequestAborted);

            var response = _mapper.Map<WalletResponse>(wallet);
            var url = Url.Link("FindWalletById", new { id = wallet.Id });

            return Ok(url, response);
        }
        
        public async Task<IActionResult> Withdraw([FromBody] WithdrawRequest request)
        {
            var command = _mapper.Map<WithdrawCommand>(request);
            var wallet = await _mediator.Send(command, HttpContext.RequestAborted);

            var response = _mapper.Map<WalletResponse>(wallet);
            var url = Url.Link("FindWalletById", new { id = wallet.Id });

            return Ok(url, response);
        }
    }
Приклад спрощений. Звісно, вручну все збирати не потрібно, для цього є DI. Та і приклад видуманий... Хоча, мабуть цілком реальний.

refactoring.guru/...​n-patterns/factory-method
refactoring.guru/...​patterns/abstract-factory

public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money, IExecutableTransaction.TransactionOperation operation)

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

То есть выйдет public IExecutableTransaction Create(dep1, dep2, dep3, ..., dep20)

ЗЫ. Ага. Понял. Распихать зависимости по DepositTransactionFactory/WithdrawTransactionFactory и молиться чтобы они были статические.

Якщо ваші dependency — сервіси, то як я показав ось тут

<blockquote>
        public DepositTransactionFactory(
            IDbContext db,
            IStatusManager statusManager
            //...
        )
        {
            _db = db;
            _statusManager = statusManager;
        }</blockquote>

можемо зібрати DI при створенні фабрики, а аргументи, котрі ми не можемо зібратиб так передемо в неї. Тут, як бачите, передаються тільки ті аргументи, котрі, ми не можемо отримати від неї

public IExecutableTransaction Create(WalletId walletId, MoneyValueObject money, IExecutableTransaction.TransactionOperation operation)

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

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

Его уже лет 5 как задепрекейтили (5 том POSA). Обоснование: статей о том, как правильно готовить синглтон, чтобы он не стрелял в ноги, в разы больше, чем описания самого синглтона.

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

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

в скляній тарі :)

до речі — дуже непоганий :)

Как был он, так и есть. И как темплейт, навсегда останется. Здесь суть в понимании, ЧТО ТАКОЕ есть сами темплейты. Внезапно, это просто термины. Обычные слова естественного языка — такие же темплейты, и точно так же кастятся мозгом, как и шаблоны проектирования, каждый день записывая и стирая их десятками.

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

Куда более правильно — никогда это дерьмо не спрашивать. А если больше нечего спросить — так ничего не спрашивать, просто дать код и попросить его прочитать. Но важно — код должен быть писан не тем, кто спрашивает, и если и читался, то редко. Иначе будет когнитивное искажение и неверная оценка, каждый-то по себе судит. Это как ездить на велосипеде — просто, но сложно, но это не значит, что нужно проводить десятки собесов и искать велогонщика — надо просто дать велосипед и сказать «Поехали!»

Обычные слова естественного языка — такие же темплейты, и точно так же кастятся мозгом, как и шаблоны проектирования, каждый день записывая и стирая их десятками.

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

но цитирование Пушкина не сделает тебя поэтом :)
Банда 4ех как литературные критики — отрефлексировали что чаще всего используется
Пока не можешь сам ходить — бери костыли.

загуглил, и во второй же ссылке
«Шаблоны проектирования» часто хвалят не за инновации, а за консолидацию терминов. Она служит нам проводником в том языке, который используется нами для понимания и обсуждения разных методов решения проблем. Она дала названия общепринятым шаблонам, чтобы мы могли продуктивнее общаться друг с другом
(конец цитаты)

филологи не создают языки.
языки создают те кто на них пишет, и вворачивает новые обороты а то и слова.
а филологи фиксируют — о, вот еще паттерн!

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

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

Ага, «консолидация». Бюрократический термин. Я человек попроще, скажу «помойка».

А на практике — говнокод, который требуется вызубрить, потому что иным способом вы это не запомните, потому что говнокод

говнокод — потому что вызубрено, а не понято :)
в этом плане качественных отличий между выпускником говнокурсов и профильного вуза обычно нет. у второго просто шансов больше понять — ввиду того что времени обучения больше: делая стопицотую лабу и надцатый курсач — шансов воскликнуть Эврика! больше.

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

Я человек попроще, скажу «помойка».

я бы сказал — сленг. чтобы не «возьми ту ху-ну, и ипани по той хреновине»

но да, с этого можно сделать магический культ — возьми эту книгу с заклинаниями, и прочти с выражением номер 14, для вызова архангела Михаила! Но помни, перепутав слово, ты вызовешь Вельзевула!!
и вот адепт, читает заклинание, написанное на коптском, которого он не знает, и трепещет — как бы это не перепутать произношение...

p.s.
вспомнил, рассказ одного узко известного

Математики не разговаривают между собой формулами. Они говорят на интересном жаргоне, который оставляет всю эту строгость за скобками. Например, походя брошенное «эта функция быстро растет» — означает, что она обладает асимптотикой экспоненты. И все такое.

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

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

В этот момент ты становишься гуманитарием. Освобождаешься от оков «строгости». И начинаешь, наконец, познавать мир.

Математика — это неплохая тренировка ума. Но мир так интересен и разноообразен :). Его описывает не она. Искусство. Только оно способно кратко и точно донести всю правду о мире.
(конец цитаты)

с паттернами ООП — тоже самое.
поэтому... а надо их спрашивать на собесах :)
чтобы выяснить — зазубрено ИЛИ понято?

“The Best Code is No Code At All”

Это да, у меня на клаве тоже первыми стираются Ctrl, С, V

Мой любимый паттерн — отсутствие в коде паттернов только ради паттернов

Но на собесе надо утверждать строго обратное :) :)
Потому что есть паттерны собесов. Отличное описанные на эротическо-итальянском сайте.

Хах, точно) А потом когда приходишь на проект, то из-за того что классы, функции итд называются именами паттернов не понимаешь вообще а что вообще разрабатывают — паттерны, или продукт ?

DI, VIPER, многомодульная архитектура в стиле АОП.

Лямда-функція. Елегантно, як самурайський меч, екстермінує все це ооп непорозуміння яке зветься патернами.

event-based lambda chains? А як їх читати та дебажити, коли там хоча б з десяток кроків?

Нє, нормальні лямбди а не маркетингове ололо від амазону.
en.wikipedia.org/wiki/Anonymous_function

Яке відношення колбек хел має до лямбда-функцій? Це одне з тисяч використань.
І то, існує «патерн» монада, яка дозволяє акуратно причесати отой код в лінійний вигляд.

О, розкажи за монаду. Я не чув.
А лямбди читаємості часто не додають, коли їх стає десь більше 10% від коду. IMO.

монада це якраз з теорії категорій.

Тоді зрозуміло, чому я про це не знаю.
Часто використовуєте їх на практиці?

На java та c# та тим більше у функціональних мовах програмування вони складають частину стандартної бібліотеки, тому повз них важко пройти. Лямбди також. С++ мабуть досить низькорівнева мова для такого типу абстракцій, тому не дивно, що ви не чули. Можливо у rust щось таке є або з’явиться

Можливо, вони просто інакше звуться — без магії

Ну ви казали, що ви Python ще знаєте, то якщо вам зрозуміло, що робить цей код:

list(map(str,[1,2,3,4,5]))
[’1′, ’2′, ’3′, ’4′, ’5′]

то ви мабуть теж працювали з монадами

О, знайшов і на С++ бібліотеку, що базована на монадах:

github.com/ReactiveX/RxCpp

Щось воно дуже схоже на звичайні пайплайни (та той же юнікс шелл)

в анонимных функциях
множатся контексты
не убрать их
плачет самурай
память потерявший

Ваш улюблений design pattern

Что может звучать еще более по задротнее =)

что значит любимый паттен? их по любви используют, а не по потребности ?

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

а, ну тогда ответ никакой) использую по потребности

что значит любимый паттен? их по любви используют, а не по потребности ?

Суют везде где только можно

Обычно самые рьяные сователи буду совать как раз куда не нужно)

Мое отношение к паттернам как к хакам: если не можешь красиво написать через ООП, то вспомни паттерны. Может получиться сложнее, но будет работать. Если решение с паттернами ощущается красивым, и легко кодится. Если нет — надо дальше думать головой, пока не поймешь, как сделать правильно.

если не можешь красиво написать через ООП, то вспомни паттерны.

«Если не можешь грызть гранит науки, то хотя бы полижи его»

Ваш улюблений design pattern

Excel

Це на ентерпрайз солюшинах корисне?

Та усюди воно є — якщо не хочеш залежати від сторонніх бібліотек, чи ОС.
Себто, коли проект розрахований на життя роками, а не написали й викинули.
Ось до чого адаптер розвинувся з роками alistair.cockburn.us/hexagonal-architecture

Я думав коли від ліб відмежовуєшся то це Facade.

Та неважливо як назвати.
Фасад — то коли маєш лапшу, і тобі оцю лапшу потрібно сховать від свого коду. Наприклад, можна за фасад сховать процедурну роботу з лінуксовими сокетами чи файлами, написавши клас-перехідник з ООП (типу як клас файлу в пітоні).
Адаптер — то коли ти не хочеш залежати від чужої бібліотеки, бо вона може виявитись недостатньо надійною для твого продукту. І може тобі вже після зовнішнього релізу потрібно буде шукать (чи писать самому) іншу більш трушну бібліотеку. На цьому ж базується гексагоналка (лінк зверху). От щоб не переписувати весь код, ти чужу бібліотеку обгортаєш своїм власним інтерфейсом, і як треба буде ті лібу замінити — то головний код майже не помітить, бо він юзає твій інтерфейс, а що там той твій інтерфейс викликає — то ніхто не знає.
Або, як варіант, адаптер мютексу, котрий надасть єдиний інтерфейс для мютексів на Лінуксі та на Віндовс. Щоб код біг де схоче. Оте QT виконує роль адаптерів до операційної системи — ти пишеш віконця в Qt, котрий адаптує рідні вікна операційної системи до свого власного інтерфейсу, що ним користується твій код.

Насчет сторонней либы это кажется прокси паттерн :-) Но они все сами по себе модификации фасада/декоратор.
Можно почитать еще тут обсуждения
stackoverflow.com/...​decorator-design-patterns
stackoverflow.com/...​nd-bridge-patterns-differ

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

Прокси полностью дублирует контракт/интерфейс скрываемого объекта. В этом его главная суть.

Спорить не буду, это все читал очень давно, перед собесами :-)

Layers вообще-то самый частый

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

Layered architecture — це все-таки архітектурний, а не design патерн, мені це поки що не потрібно.

Без розуміння архітектурних щось казати за дизайн патерни — то стріляти слухачам в ноги

Чому ж? От до прикладу якщо знаєш як правильно створювати елементи класу, як їх іменувати, які рівні доступу і т.д. то це вже хороша працююча річ виходить.

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

то це вже хороша працююча річ виходить.

А що цей клас має робити? І чому саме це і саме отак?

От є проекти на 10К рядків — там пофіг як зробиш. Є на 100К+ і там вже треба думать. І от коли треба думать — то починаються усі ті (архітектурні) Layers, Pipes and Filters, Actors, Blackboard (communication via database), багатопоточніть та інша різномаїтна хрєнь. Щоб воно не загнулось від нових побажань та від кількості користувачів та якщо котрась з чужих ліб, що ти взяв за основу, буде глючною, і її треба буде замінить на іншу.

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

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

З першого тому POSA. Взагалі-то архітектурний патерн, але між архітектурними та дизайн межа слабка.
dzone.com/...​-5-patterns-you-need-to-k
www.dfpug.de/...​98\02_OOP\E_LAY/E_LAY.HTM
www.oreilly.com/...​s/9781491971437/ch01.html

Два кита, на которых держится всё программирование: паттерны helper и manager.

У нас в дотнет мире все есть Service. Даже если это хелпер, то все равно будет HelperService. И будет еще валяться бесполезный нахрен никому не упавший интрефейс в той же папке IHelperService.

У нас в дотнет мире все есть Service

Жистокая голактека.
Если у вас все Service, то должен быть и ServiceService. С интерфейсом IServiceService.

однажды собственными глазами видел IDataDataProvider

Я тут видел ...HelperHelper()

IDataDataServiceServiceHelperHelperDataServiceHelper.

А еще говорите что в джаве классы длинные :-З

projects.haykranen.nl/java

ServiceConsumerPrinterReponseTagAuthenticationProccesorOrderListenerIterator

Звучить як заклинання із Наруто.

От я старався писати апі ап по трушному, Clean Architecture, REST стандарти як от правильний роутинг, структура запиту і респонсу. А мене кікнули, бо один фулстякер що на фронті сидів почав указувати мені якусь фігню робити на апі, і ще не читав дев гілку де я обговорював покращення мейн фічі, і весь такий крутий показував себе. Я йому написав що про нього думаю, і все. Ну то черговий нищенський стартап то не страшно. Але сумно. Доки я парю собі голову як зробили правильно, інші гівнокодять і вішають собі лички. Пора ставати сіньйором. От поборю свої па і обовязково піду на галеру на 3к дутим сіньйором!

Або ж тепер мав змогу оцінити творчість якогось там ліда. Перепис старого апу з нет 4.8 на нет 6. Це такий трешак з іфами на два екрани, звязаністю компонентів, один метод робить безліч речей, відсутністю тестів, та навіть міграції не налаштовані. Закоменчені бо там ахінея написана і конектиться ап напряму до дб і робить запити як я зрозумів не чепез Entity Framework а всюди через SqlConnection. Взагалі бозна які патерни там використані, напевно патерн ГівнокодЯкЗнаю.

Це звісно фріланс. В компаніях же краще?

На галєрах таке ж.
В продуктах або усі поспішають (стартап — сам бачив щойно), або легасі, там основний патерн Big Ball of Mud www.laputan.org/mud

Ого, крута стаття. Поки всю не осилив.

У фрілансі ніколи не працював, не скажу.
А в enterprise розробці були різні випадки. Якось працював у продуктовій конторі, там жорстко стежили за якістю продукту, включаючи якість коду. Вони ж собі писали продукт, на якому планували розбагатіти.
Але все було без фанатизму. Якщо deadline — пиши який завгодно код, аби працювало, доробиш після.

Якщо deadline — пиши який завгодно код, аби працювало, доробиш після.

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

Це коли нема обмежень (багато проца, оперативи, юзери не поспішають). Коли обмеження — потрібно одразу розуміть, що з нього буде.
Переписування — то коли за рік роботи над продуктом: з одного боку, починаєш розуміти домен — себто, реквайрменти обростають подробицями, і оті подробиці увесь початковий план ламають. З іншого боку — з’являються нові реквайрменти що ні в які ворота не влазять.
В результаті — ти планував зробить крокодила, заточив під нього архітектуру, а виявилось — що треба стрекозу. Архітектура від крокодила якось витримує навантаження від крил, але літає воно низенько, й смердить болотом. Отут і час переписати усе нафіг, якщо гроші за це платять.

Коли обмеження

"Сказ про один байт" ©

А в мене воно реально було.
Коротше, купили найдешевші залізки під перехідник з USB до телефонного шнурка. Там 8КБ оперативи. Під сам код мало потрібно, а от виявилось, що в роутері, до котрого воно через USB має підключатися, ядро блокується десь під час логування подій. Пару моделей роутерів народ підфіксив, а в інших все одно кількадесят мілісекунд усе мертве. Відповідно, оці мілісекунди звуку треба мати закешованими, бо поки ядро заблоковане — USB шина мертва, а в шнурок голос має відсилатись юзеру, і те, що із шнрка вилазить — теж зберігати десь. Інакше голос тріщатиме, чи обриви будуть.
От, буферизація, значиться. 2 аналогових шнурка, rx/tx черги на кожному, по 7 пакетів 20 мс на пакет. І не влазить в 8кб оперативи на якіхось кілька байтів. Коротше, я ці байти вигриз із padding між юнітами компіляції — за дефолтом під ARM воно компілювало з вирівнюванням статичних змінних в кожному сорці на 4 байта. А там в сорці наприклад 1 чи 2 bool змінних, кожна по 1 байту. І пару байтів чисто на вирівнювання лінкування. Зробив uniti build, коли в один .с файл інклюдяться кілька .с файлів — себто, шматок проекта компілиться як один сорс файл замість того, щоб скомпілитись в різні об’єктники а потім лінкуватись. Допомогло — вистачило оперативи на буфера під зав’язку. Але згадував тоді оту байку про останній байт.

Доки я парю собі голову як зробили правильно, інші гівнокодять і вішають собі лички.

Более точного описания карьер на галерах я еще не читал.

піду на галеру на 3к дутим сіньйором

пфф, дутые синьеры это 10К сейчас, вот буквально сегодня мне в ЛС пришло:
ищем хорошего middle Frontend Developer
Вилка — up to 5k net

А мне недавно приходило от Люксофта up to 3.5k

типовые ооп патерны давно не в моде.

А що тодi у трендi ?

враховуючи, що значна частина (або увесь?) вхідного коду в українському аутсорсі — це "хуерга, древнегреческие механизмы, шлак писаный обезьяной и глистами"©, найбільш вживаними шаблонами на теренах неньки стали проксі і декоратор :D

Ну тоді треба ще facade додати цей список

Цепочка обязанностей, но я бы на твоём месте писал от себя, а не опирался на любимые паттерны других людей, потому что применение моему любимому паттерну очень специфическое и можно сделать хуже, а притулить его можно в очень многих случаях

Мрію добре вивчити десятки патернів, різні принципи, бест практіс, щоб потім приходити на проекти і страждати від антипатернів, велосипедів і гівнокоду.

Станьте засновником нових проектів і у вас ніколи не буде нічого подібного

Потім інші деви писатимуть по своєму і проект скотиться.

Що означає по-своєму? А code review на що? Під час code review якраз і контролюється, щоб розробники писали так, як потрібно, а не так, як їм хочеться

Тобто треба бути лідом або шукати команду з хорошим лідом.

Я выигрывал в этой борьбе, но был побочный эффект — за пределами команды меня «боялись» и искренне ненавидили :) вне команды нравился я только тех директору т.к. моя команда была единственной где не было срыва сроков за два года, которые я был на проекте. и за все время лишь один баг выехал на прод в новом функционале, который, соответственно, особо ничего не заимпактил и хотфикс был на следующий день. Повторять ни сил, ни желания нет, да и должность не та

Не зовсім зрозумів, за що вас боялися та ненавиділи, якщо ви постачали якісний продукт?

я бы сказал за нетолерантность к подходу ляп-ляп и в продакшен, когда очень хочется

Напевно напрягав людей своїм задротством. А у людей дім, жінка, плейстешн.

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

тем более это касалось только тех кто вне моей команды, со своими проблем не было, даже те кто послабее всегда все успевали, без потогонки, дефолтная задача была круд написать, 3-4 дня срок, модель разбита удобно, полное описание всего, несколько человек, которые могли подробно описать что нужно и подсказать если что-то не получается, технический долг около 5 человекодней, при размере кодовой базы ~1млн строк, по сонару так вообще пара человекочасов. митингов и прочих активностей на 3-4 часа в неделю. по-моему очень демократично, нет?

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

часто девов из других команд пытались снарядить «помочь», наш архитект дотнет полгода использовал в жизни и тоже любил помочь, база была одна на много приложений с кучей всякой ерунды вроде триггеров и добавить в нее что-то такое чтобы ее отрефакторить потом нельзя было тоже многим хотелось. кто-то свои штуки с фронта хотел в бекенд скинуть, типа там «вы нам локализуйте сообщения в исключениях чтобы мы их сразу показывали» и плевать что есть требования к формату и тексту сообщений и куча других клиентских приложений

кто-то свои штуки с фронта хотел в бекенд скинуть

поубивал бы за это.

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

Тобі недостаньо того що патерни та принципи один з одним не дружать? А деякі так узагалі жіноча логіка.

Так не треба все підряд брати. Лише те що підходить під мову, фреймворк і завдання.

Так більшість треба забути як поганий сон на історичну тематику. А не робити із того бюрократичну релігію та кар′єрні бар′єри.

Большая тройка FDD/HDD/RDD — Fun-/Hype-/Resume-Driven Development.

SSD (Гітлер едішен)

Нещодавно з’явилася ідея зробити вебінар з патернів

вам стоит начать с опредления — что вы считаете «паттерном», потому как

але кількість патернів зростає з кожним днем

получается ровно потому, что в «паттерны» записывают все подряд, не имея каких-либо четких критериев.

Вероятно, вам будет полезнее собрать список «часто решаемых/типовых проблем», и сделать обзор, «часто используемых/типовых решений».

Я в заголовку чітко зазначив, що тема про design patterns.

вам стоит начать с опредления — что вы считаете «паттерном»

Вас забанили в Google, що ви не можете відкрити браузер і прочитати, що це таке?

en.wikipedia.org/...​i/Software_design_pattern

для джавіста паттерн — це базове/первинне поняття (як точка в евклідовий геометрії), відповідно його визначення надати не можна

Design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design

Х*як, х*як и в продакшен

Це deployment pattern, а не design pattern.

Не, это первые два шага это дизайн паттерн, а последний — деплоймент паттерн

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

Автори «GOF патернів» напевно зараз кусають лікті, що не включили ваші патерни до своєї книги

CCP

Common Close Packing?
Common Compensatory Pattern?

KISS + ПишиКодБлджад

(вставте кому)

Ваш улюблений design pattern
Тому напишіть будь ласка який патерн ви найчастіше використовуєте (найкраще знаєте) у роботі

3 принципово різних запитання і жодне з них не має сенсу для зрілого спеціаліста.
Патерн — це типове вирішення типової проблеми.
Їх треба використовувати під проблему. До чого тут «найкраще знаєте»? Чи улюблений? Найчастіше теж не має сенсу для людей, що не застрягли в однотипних задачах.

Їх треба використовувати під проблему

Краще не використовувати
Вирішити проблему оптимально, а потім ретроспективно визначити паттерн і забути про нього

Краще не використовувати (1)
Вирішити проблему оптимально (2), а потім ретроспективно визначити паттерн (3) і забути про нього (4)

Швидке досягнення 2 суперечить 1. Власне суть існування патернів — це зменшити час на досягнення 2.
Незрозуміло для чого 3, особливо, якщо потім йде 4.

Швидке досягнення 2 суперечить 1.

Nope
Коли в контексті вирішення задачі ви згадуєте паттерни, замість вирішення задачі починається втуляння паттернів.

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

Якщо вам платять за підбор паттернів для рішення задач, то ок
www.youtube.com/watch?v=baY3SaIhfl0
Тільки не всім пощастило

Гнучкі рішення не потрібні в більшості випадків
Коли вони дійсно потрібні — має бути жорсткий набір обмежень

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

Себто, Ви живете без Layers, Strategy та адаптерів?
Чи просто підсвідомо їх використовуєте?

От, а я знаю, як вони звуться.
І там ще дофіга різних, менш очевидних та відомих. І коли десь треба буде думать, як зробить — то хороший вибір інструментів (не робить, як всі, підсвідомо).
Коли думаєш і щось робиш по-своєму — все одно створиш набір старих патернів, просто ти про них не чув. Я отак гексагоналку придумав років 10 тому. А прочитав про неї 2 чи 3 роки назад. alistair.cockburn.us/hexagonal-architecture

Я отак гексагоналку придумав років 10 тому

Як ви це придумали?

Вирішення якої проблеми воно спростило?

Перехід з стандарту DECT GAP на новий стандарт DECT CAT-iq 2. В новому стандарті купа сценаріїв з паралельними дзвінками, і трохи незручні corner cases. Система була написана як Actors. От для нових сценаріїв для того, щоб надіслати слухавці відповідь, потрібно було знати стан кількох акторів. А це вже — оркестрація чи хореографія, і нафіг таке пхати в залізку з 2 кіловордами оперативи. Та й не чув про це ніхто тоді в ембедеді.
От щоб розрулити, довелось кожного актора, що мав справу з залізом, поділити навпіл. Нижні половини акторів (інтерфейс до заліза) стали незалежними, а верхні — зліпили докупи в одного великого актора. В результаті уся логіка обробки запитів стала синхронною (і залишилась неблокуючою), завдяки синхронності можна зібрати докупи усю потрібну інформацію і відповісти на запит так, як це вимагає новий стандарт.
Але по суті — вийшов рефакторинг з акторів у гексагоналку. З усякими додатковими патернами як Half-Object Plus Protocol, Half-Async/Half-Async, Proactor, Event Channel та інший зоопарк про котрий ніхто з нас і чутки не чув тоді. Тому так, як подумати і знайти рішення — то потім виявиться, що не ти перший такий розумний, і твоє новітнє рішення вже давно хтось описав, назвав та класифікував. А ти — селюк недосвідчений, що книжки не читаєш.

По тому що я зрозумів — це задача про черги і обробників
(Це вже паттерн чи ще ні?)

В результаті уся логіка обробки запитів стала синхронною

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

Тому так, як подумати і знайти рішення — то потім виявиться, що не ти перший такий розумний, і твоє новітнє рішення вже давно хтось описав

Тому краще ніколи не називати своє рішення новітнім — хай інші це роблять

В задачі не було обмежень по часу відповіді?
Чи відрефакторена синхронність стала швидше попередньої асинхронності?

(Це вже паттерн чи ще ні?)

Це десь в Enterprise Integration Patterns почали класифікувати, здається. До того — такі системи знали як Actors чи Channels, але Actor завше був занадто складним та різнобарвним, щоб його описати одним патерном.

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

Логіка не висить в очікуванні — це неблокуючий Proactor. Прийшов запит з одного боку — змінили стан — виплюнули запит в інший бік.

В задачі не було обмежень по часу відповіді?

Були — це телефонія. Soft real-time. Якщо швидко не обробиш — юзери будуть матюкатись на увесь інтернет.

Чи відрефакторена синхронність стала швидше попередньої асинхронності?

Відрефакторена синхронність мала б бути трохи швидшою — менше меседжингу. Коли цікаво — отут детальніше розписав dou.ua/...​cles/telecom-application

Себто, Ви живете без Layers, Strategy та адаптерів?

Кто-то из мира npm или go, как часто у вас используется перечисленное?

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

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

Тому напишіть будь ласка який патерн ви найчастіше використовуєте

паттерн
х&х -> p

Можна вважати камін-аутом?

Anemic domain model (если это паттерн вообще)
Transaction Script

DDD — Davay Davay Deploy

Если грамотно разбито на регионы, в соответствии с заранее документированными правилами, то хоть весь проект пиши в одном классе. В пределах разумного конечно.

Тру дзен сеньорства это умение применять не только лишь паттерны, но и анти-паттерны! :-)

Головне потім не отримати анти-зарплату

Значит дзен не познан. Анти-зарплату у нас еще нужно постараться получить, кроме шараг где лишь ждуны и интерны.

Подписаться на комментарии