Плюс таких игр в высочайшей реиграбельности: в первый раз можно просто пробежать основной квест и узнать сюжет часов за 20, во второй раз взять часть сайд квестов, и, если очень захочется, уже в третий-четвертый раз пройти всё.
Fallout 4 несколько раз прошел, каждый раз что-то новое видел.
Ну наверное если описали интерфейс, то где-то будет переменная такого типа, иначе зачем описывали? И наверняка будет больше одной реализации этого интерфейса, иначе можно было бы обойтись просто ссылкой на структуру.
А если есть переменная типа интерфейс и 2 реализации интерфейса, то это уже добавляет гибкость. В переменную можно записать либо указатель на первую структуру, которая реализует интерфейс либо на вторую.
Немного неправильно написал. В коде это легко написать плохо, продублировав все функции. Сложно сделать хорошо. Примеры как можно сделать лучше:
Можно поднапрячься, избавиться от хитрых запросов и использовать ORM
Написать всё по-максимуму на чистом SQL и сделать базовую реализацию для всех СУБД и только небольшую часть продублировать и оптимизировать для разных.
Еще что-то можно придумать, например, написать библиотеку общих кусков запросов, которая будет использоваться и в реализации для Oracle и для PostgreSQL. Ну к примеру есть набор условий, что пользователь активен, можно сделать функцию applyUserActiveFilter(query).
Часть логики перенести в базу и написать в виде функций и триггеров в базе.
Да, все решения будут выглядеть не очень круто, но зато смогут сэкономить много усилий и сберечь от багов, когда в одном месте поменяли а во втором - забыли.
Знания о конкретной БД в домен не протекают, но реализация настолько объемная, что просто так, "чтобы было" никто не будет поддерживать вторую СУБД.
Я не говорю, что это нельзя сделать, это вообще такая простая и базовая вещь с точки того, как это можно написать в коде, что её наверное на 5й день изучения программирования изучают. Это есть везде, но делается по-разному. В C и ассемблере это указатели на функции (и структуры с набором указателей на функции), в C++ - наследование и виртуальные функции, в Java и Go - интерфейсы. Я не понимаю, зачем этот подход преподносить как какую-то чудесную хитрость чистой архитектуры от дядюшки Боба, это используется уже лет 50 точно в программах чуть сложнее Hello world.
Проблема не в том, что это сложно написать в коде, а в том, что количество кода, который реализует доступ к базе обычно большое и если этот код продублировать, то это потребует почти в 2 раза больше усилий на добаботку функций по работе с базой, поддержку этого кода и тестирование.
Вы сейчас называете опыт программистов накопленный десятилетиями просто каким-то развлечением? Или вы не знаете как примеры из книжки применять на реальные проекты?
В реальном проекте он может и не понадобиться, а может и понадобиться (санкции? Пожелание заказчика? Ещё что-то?). И темболее сначала вы говорили что просто не верите, теперь вот не верите, а если поверите оно и не нужно вообще.
Так оно применяется в других случаях, не в тех, что описаны в статье, когда надо данные информационной системы где-то хранить и для доступа к этим данным нужно 1000 функций.
Пример где это необходимо - игра, у каждого игрового объекта должно быть реализованы 3 функции: draw(...), move(...), checkCollision(). В игре одновременно присутствуют объекты разных типов их удобно хранить в одном массиве и обрабатывать похожим образом. Почему тут это работает? Потому что в интерфейсе 3 функции а не 1000. (Ну ладно, в реальной игре будет 50 а не 3, но никак не 1000)
Еще пример - линукс поддерживает разные файловые системы, конечно было бы круто все данные на ext4 хранить, но реальность такова, что кто-то может в компьютер воткнуть карту памяти из фотоаппарата с файловой системой exFat.
Ну и, вот так сходу, принижать то чего вы даже не знали, как-то так себе.
Вы представляете репозиторий как любой доступ к базе или что? Помоему репозиторий это обёртка в которой данные пришедшие от бд преобразуются во внутренний программный объект?
Ну да, примерно это
А для чего ещё интерфейсы нужны, если не реализовывать их? Чтобы всем рассказывать что у нас DDD? Или чистая архитектура...
В статье написано, что при плохой структуре кода замена базы потребует 200 изменений в коде, а при хорошей - 10. Далее идет картинка Гибкость замены компонентов, на которой нарисовано, как PostgreSQL меняется на MongoDB. И это я хочу оспорить.
Если в реальности будет такая задача стоять, то возможно 2 варианта, либо данные очень простые и их можно где угодно хранить, но если данные сложные, то скорее всего вместо PostgreSQL потребудется поддержать другую реляционную СУБД, Oracle или MSSQL. Это будет делаться исключетельно по просьбе крупного клиента за большие деньги. И скорее всего это не будет полная реализация всех функций репозитория для обоих баз.
Либо будет доступ к базе через ORM, либо будет базовая реализация 990 функций репозитория на стандартном SQL и различная реализация с оптимизациями и кастомными фичами Postgres и Oracle оставшихся 10 функций. Но все 1000 функций 2 раза писать - это жесть.
Я имею ввиду в реальном проекте, а не в примере TodoList из книжки. Потому что нет никакой потребности в возможности хранить одно и тоже либо в монге либо в постгресе и переключаться между ними опцией в конфиге.
Для какого-то набора объектов будет нужна согласованность данных и нормальная поддержка транзакций - в постгресе это доступно из коробки на высочайшем уровне, в MongoDB замучаетесь писать костыли и всё-равно не будет нормально работать. Возможно получится обособить часть объектов, для которых будет важна масштабируемость, но структура и правила работы с ними будут проще - тогда их можно будет хранить в MongoDB.
То есть не делают несколько реализаций одного интерфейса, делают 2 адаптера с разным набором функций каждый из которых ходит в свою систему хранения данных.
Да, есть, конечно, примеры, когда ваш паттерн "мост" необходимо использовать, но это точно не реализация основного репозитория.
Ни за что не поверю, что введением какого-то "правильного слоя" можно будет легко переключаться между постгресом, MongoDB и SQLite в реальном проекте. Вот там на картинке нарисована одна стрелка между "Порты" и "Postgres" а на самом деле там должно быть нарисовано 1000 стрелок. Поддерживать, тестировать и оптимизировать коммерческий облачный проект под разные системы никто не будет. В лучшем случае можно будет между похожими базами переключаться - постгрес, MSSQL, Oracle.
Этот подход сработает исключительно в тех случаях, где интерфейс крайне простой и небольшой. Пример - объектное хранилище. Там всего 3 метода: создать, прочитать, удалить. Это можно конечно реализовать и для локальной ФС, чтоб на машинах разработчиков запускать и in-memory для тестов и для прода через S3.
Почему же? Просто эта тема автору интересна, он считает, что надо про нее рассказать на хабре. В статье много хороших мыслей, на мой взгляд.
По поводу голословных выкриков: посчастливилось работать в команде Acronis Storage, которая с нуля разработала отказоустойчивое хранилище, аналог CEPH, сделали S3 поверх него (я правда присоединился поздно и ничего полезного там не смог сделать, нечем похвастать). Так вот, в этой команде было человек 5 в среднем, никаким скрамом и эджайлом там не пахло, даже код ревью в привычном виде не было. Просто были люди, которые осознавали всю ответственность и работали на совесть. И это в такой области где риски потерять данные пользователей огромны.
Я тоже немного ощутил, то, что описывает автор. В числе первых людей начал работу над проектом, 2 года работал максимально эффективно, за первые 2 года сделал 2000 коммитов, при этом год работал тимлидом команды из 4 человек, приходилось и менеджерскими задачами заниматься. И в какой-то момент начальство решило настроить процессы, началось вот это "нельзя делать задачи не из спринта", желание работать пропало мгновенно, ушел оттуда через полгода.
В озоне из за рекомендательных алгоритмов в топе оказывается один товар. И надо иметь очень большую смелость, чтобы купить что-то другое, особенно без отзывов. По сути оказались в ситуации, что выбора нет.
Мне не нужна лучшая колбаса, мне нужна достаточно хорошая.
Я не хочу выбирать из 100 сортов колбасы, потом из 100 сортов чая, потом из 100 сортов молока и.т.д. меня полностью устраивает ситуация, когда сотрудники пятерочки отобрали для меня из 100 сортов 5, среди которых найдется достаточно хорошая, которая меня устраивает.
Меня полностью устраивают пятёрочка рядом с домом и вкусвилл. А Ашан не устраивает, потому что на закупку продуктов в пятёрочке я трачу 10 минут и абсолютно не трачу умственных усилий. А в Ашане я провожу час чтобы купить то же самое, но приезжаю оттуда как выжатый лимон
У меня принтер уже лет 5, печатаю раз в неделю всякую бытовую мелочь, из последнего: крюки для того, чтоб гладильную доску в шкаф вешать, органайзер-стакан в шкаф над раковиной в ванной, шаблоны, чтоб фрезером выпилить ручки в фасадах ящиков. Сейчас вот крепления для фонарей детям на велосипеды надо сделать.
Я бы как раз посоветовал начинать с изучения как чертить 3Д модели. 3D принтер вообще нет смысла покупать для того, чтобы готовое с сайта печатать - проще просто в магазине купить. Смысл как раз в том, чтобы не тратить время на поиски какой-то непонятной штуки, которая тебе понадобилась вот прямо сейчас и обязательно под конкретные размеры. Вот к примеру в прошлом году надо было проверить слив конденсата кондиционеров, нужна была воронка - нарисовал за 5 минут, напечатал за 3 часа и даже идти никуда не надо. Очень выручает 3D принтер в таких случаях.
Для моделирования Компас3D бы посоветовал, домашняя версия стоит около 1500 в год, и там есть простой и понятный tutorial, основам можно часов за 6 научиться, и этого хватит, чтобы что угодно для 3Д печати нарисовать.
6 лет уже в такой прикладной области работаю и только 2 раза оказалось "место, на которое никто не думал". Один раз была таблица с большим количеством партиций и планировщик постгреса не мог с ней справиться нормально, зависал на пару секунд а второй раз оказалось что что-то с мапами намудрили и как раз слишком много вычислений было. В остальном за 6 лет такой практики всегда было понятно, куда смотреть в первую очередь.
Ну и у нас AMP сейчас настроен, так что высокоуровневые трейсы он показывает, хорошо помогает.
Но конечно я верю что есть проекты, где более интересные проблемы с перфомансом возникают )
2 слоя хоть как-то можно понять, а когда делают 4 слоя а потом еще и оказывается что у нас-то микросервисная архитектура, а давайте у нас будет этот сервис по gRPC ручки выставлять и будет отдельный интеграционный сервис, который по gRPC всю инфу собирает, аггрегирует и отдает по HTTP и в этом итгрегационном сервисе еще 3-4 стоя - это уже чересчур. 8 слоев (и 8 мапперов на каждый объект) чтобы json из базы выдать выглядит не очень оптимальной схемой.
Но не все такие игры, GTA V мне такой нудной показалась, еле дошел до конца.
Плюс таких игр в высочайшей реиграбельности: в первый раз можно просто пробежать основной квест и узнать сюжет часов за 20, во второй раз взять часть сайд квестов, и, если очень захочется, уже в третий-четвертый раз пройти всё.
Fallout 4 несколько раз прошел, каждый раз что-то новое видел.
А чем отличается проект с гибкой архитектурой от проекта с негибкой архитектурой?
Ну наверное если описали интерфейс, то где-то будет переменная такого типа, иначе зачем описывали? И наверняка будет больше одной реализации этого интерфейса, иначе можно было бы обойтись просто ссылкой на структуру.
А если есть переменная типа интерфейс и 2 реализации интерфейса, то это уже добавляет гибкость. В переменную можно записать либо указатель на первую структуру, которая реализует интерфейс либо на вторую.
Немного неправильно написал. В коде это легко написать плохо, продублировав все функции. Сложно сделать хорошо. Примеры как можно сделать лучше:
Можно поднапрячься, избавиться от хитрых запросов и использовать ORM
Написать всё по-максимуму на чистом SQL и сделать базовую реализацию для всех СУБД и только небольшую часть продублировать и оптимизировать для разных.
Еще что-то можно придумать, например, написать библиотеку общих кусков запросов, которая будет использоваться и в реализации для Oracle и для PostgreSQL. Ну к примеру есть набор условий, что пользователь активен, можно сделать функцию
applyUserActiveFilter(query)
.Часть логики перенести в базу и написать в виде функций и триггеров в базе.
Да, все решения будут выглядеть не очень круто, но зато смогут сэкономить много усилий и сберечь от багов, когда в одном месте поменяли а во втором - забыли.
Знания о конкретной БД в домен не протекают, но реализация настолько объемная, что просто так, "чтобы было" никто не будет поддерживать вторую СУБД.
Я не говорю, что это нельзя сделать, это вообще такая простая и базовая вещь с точки того, как это можно написать в коде, что её наверное на 5й день изучения программирования изучают. Это есть везде, но делается по-разному. В C и ассемблере это указатели на функции (и структуры с набором указателей на функции), в C++ - наследование и виртуальные функции, в Java и Go - интерфейсы. Я не понимаю, зачем этот подход преподносить как какую-то чудесную хитрость чистой архитектуры от дядюшки Боба, это используется уже лет 50 точно в программах чуть сложнее Hello world.
Проблема не в том, что это сложно написать в коде, а в том, что количество кода, который реализует доступ к базе обычно большое и если этот код продублировать, то это потребует почти в 2 раза больше усилий на добаботку функций по работе с базой, поддержку этого кода и тестирование.
Ну а как это сделано? Абсолютно все запросы продублированы для обоих СУБД или все-таки есть общая часть?
Так оно применяется в других случаях, не в тех, что описаны в статье, когда надо данные информационной системы где-то хранить и для доступа к этим данным нужно 1000 функций.
Пример где это необходимо - игра, у каждого игрового объекта должно быть реализованы 3 функции:
draw(...)
,move(...)
,checkCollision()
. В игре одновременно присутствуют объекты разных типов их удобно хранить в одном массиве и обрабатывать похожим образом. Почему тут это работает? Потому что в интерфейсе 3 функции а не 1000. (Ну ладно, в реальной игре будет 50 а не 3, но никак не 1000)Еще пример - линукс поддерживает разные файловые системы, конечно было бы круто все данные на ext4 хранить, но реальность такова, что кто-то может в компьютер воткнуть карту памяти из фотоаппарата с файловой системой exFat.
Статья про Golang написана, там это называется "interface", https://go.dev/tour/methods/9
Ну да, примерно это
В статье написано, что при плохой структуре кода замена базы потребует 200 изменений в коде, а при хорошей - 10. Далее идет картинка Гибкость замены компонентов, на которой нарисовано, как PostgreSQL меняется на MongoDB. И это я хочу оспорить.
Если в реальности будет такая задача стоять, то возможно 2 варианта, либо данные очень простые и их можно где угодно хранить, но если данные сложные, то скорее всего вместо PostgreSQL потребудется поддержать другую реляционную СУБД, Oracle или MSSQL. Это будет делаться исключетельно по просьбе крупного клиента за большие деньги. И скорее всего это не будет полная реализация всех функций репозитория для обоих баз.
Либо будет доступ к базе через ORM, либо будет базовая реализация 990 функций репозитория на стандартном SQL и различная реализация с оптимизациями и кастомными фичами Postgres и Oracle оставшихся 10 функций. Но все 1000 функций 2 раза писать - это жесть.
Я имею ввиду в реальном проекте, а не в примере TodoList из книжки. Потому что нет никакой потребности в возможности хранить одно и тоже либо в монге либо в постгресе и переключаться между ними опцией в конфиге.
Для какого-то набора объектов будет нужна согласованность данных и нормальная поддержка транзакций - в постгресе это доступно из коробки на высочайшем уровне, в MongoDB замучаетесь писать костыли и всё-равно не будет нормально работать. Возможно получится обособить часть объектов, для которых будет важна масштабируемость, но структура и правила работы с ними будут проще - тогда их можно будет хранить в MongoDB.
То есть не делают несколько реализаций одного интерфейса, делают 2 адаптера с разным набором функций каждый из которых ходит в свою систему хранения данных.
Да, есть, конечно, примеры, когда ваш паттерн "мост" необходимо использовать, но это точно не реализация основного репозитория.
Ни за что не поверю, что введением какого-то "правильного слоя" можно будет легко переключаться между постгресом, MongoDB и SQLite в реальном проекте. Вот там на картинке нарисована одна стрелка между "Порты" и "Postgres" а на самом деле там должно быть нарисовано 1000 стрелок. Поддерживать, тестировать и оптимизировать коммерческий облачный проект под разные системы никто не будет. В лучшем случае можно будет между похожими базами переключаться - постгрес, MSSQL, Oracle.
Этот подход сработает исключительно в тех случаях, где интерфейс крайне простой и небольшой. Пример - объектное хранилище. Там всего 3 метода: создать, прочитать, удалить. Это можно конечно реализовать и для локальной ФС, чтоб на машинах разработчиков запускать и in-memory для тестов и для прода через S3.
Почему же? Просто эта тема автору интересна, он считает, что надо про нее рассказать на хабре. В статье много хороших мыслей, на мой взгляд.
По поводу голословных выкриков: посчастливилось работать в команде Acronis Storage, которая с нуля разработала отказоустойчивое хранилище, аналог CEPH, сделали S3 поверх него (я правда присоединился поздно и ничего полезного там не смог сделать, нечем похвастать). Так вот, в этой команде было человек 5 в среднем, никаким скрамом и эджайлом там не пахло, даже код ревью в привычном виде не было. Просто были люди, которые осознавали всю ответственность и работали на совесть. И это в такой области где риски потерять данные пользователей огромны.
Я тоже немного ощутил, то, что описывает автор. В числе первых людей начал работу над проектом, 2 года работал максимально эффективно, за первые 2 года сделал 2000 коммитов, при этом год работал тимлидом команды из 4 человек, приходилось и менеджерскими задачами заниматься. И в какой-то момент начальство решило настроить процессы, началось вот это "нельзя делать задачи не из спринта", желание работать пропало мгновенно, ушел оттуда через полгода.
Ну хорошо, я просто похожие делал в детскую, сильно качались, уголками сзади пришлось усиливать и всё-равно неидельно в итоге получилось.
Такой стол будет качаться. Обязательно надо делать заднюю стенку.
В озоне из за рекомендательных алгоритмов в топе оказывается один товар. И надо иметь очень большую смелость, чтобы купить что-то другое, особенно без отзывов. По сути оказались в ситуации, что выбора нет.
Мне не нужна лучшая колбаса, мне нужна достаточно хорошая.
Я не хочу выбирать из 100 сортов колбасы, потом из 100 сортов чая, потом из 100 сортов молока и.т.д. меня полностью устраивает ситуация, когда сотрудники пятерочки отобрали для меня из 100 сортов 5, среди которых найдется достаточно хорошая, которая меня устраивает.
Меня полностью устраивают пятёрочка рядом с домом и вкусвилл. А Ашан не устраивает, потому что на закупку продуктов в пятёрочке я трачу 10 минут и абсолютно не трачу умственных усилий. А в Ашане я провожу час чтобы купить то же самое, но приезжаю оттуда как выжатый лимон
У меня принтер уже лет 5, печатаю раз в неделю всякую бытовую мелочь, из последнего: крюки для того, чтоб гладильную доску в шкаф вешать, органайзер-стакан в шкаф над раковиной в ванной, шаблоны, чтоб фрезером выпилить ручки в фасадах ящиков. Сейчас вот крепления для фонарей детям на велосипеды надо сделать.
Я бы как раз посоветовал начинать с изучения как чертить 3Д модели. 3D принтер вообще нет смысла покупать для того, чтобы готовое с сайта печатать - проще просто в магазине купить. Смысл как раз в том, чтобы не тратить время на поиски какой-то непонятной штуки, которая тебе понадобилась вот прямо сейчас и обязательно под конкретные размеры. Вот к примеру в прошлом году надо было проверить слив конденсата кондиционеров, нужна была воронка - нарисовал за 5 минут, напечатал за 3 часа и даже идти никуда не надо. Очень выручает 3D принтер в таких случаях.
Для моделирования Компас3D бы посоветовал, домашняя версия стоит около 1500 в год, и там есть простой и понятный tutorial, основам можно часов за 6 научиться, и этого хватит, чтобы что угодно для 3Д печати нарисовать.
6 лет уже в такой прикладной области работаю и только 2 раза оказалось "место, на которое никто не думал". Один раз была таблица с большим количеством партиций и планировщик постгреса не мог с ней справиться нормально, зависал на пару секунд а второй раз оказалось что что-то с мапами намудрили и как раз слишком много вычислений было. В остальном за 6 лет такой практики всегда было понятно, куда смотреть в первую очередь.
Ну и у нас AMP сейчас настроен, так что высокоуровневые трейсы он показывает, хорошо помогает.
Но конечно я верю что есть проекты, где более интересные проблемы с перфомансом возникают )
А на каком языке предлагаете писать? :)
Ну и VK HR Tek - это все-таки больше не система учета а корпоративный портал теперь, но требований заказчиков приходится много реализовывать, да.
В целом на Go довольно удобно получается, особенно с тех пор как дженерики появились.
Крутая книга конечно, все очень понятно объясняется и воды вообще нет, все только по делу написано. Вошла в пятерку лучших книг, которые я прочитал!
2 слоя хоть как-то можно понять, а когда делают 4 слоя а потом еще и оказывается что у нас-то микросервисная архитектура, а давайте у нас будет этот сервис по gRPC ручки выставлять и будет отдельный интеграционный сервис, который по gRPC всю инфу собирает, аггрегирует и отдает по HTTP и в этом итгрегационном сервисе еще 3-4 стоя - это уже чересчур. 8 слоев (и 8 мапперов на каждый объект) чтобы json из базы выдать выглядит не очень оптимальной схемой.