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

Хайп Go пришелся где-то на 2014ый год, когда авторы приложений имевших от силы 1000RPM (requests per minute) вдруг как один решили, что им срочно нужен concurrency, потому что вот-вот их 1000RPM превратиться в 1000RPS (что тоже не так много, на самом деле).

Результатом хайпа стало то, что к Go приобщилось много людей, привыкших к MVC архитектуре приложения, буть то Spring, Django или Ruby on Rails. И эту архитектуру, как сову на глобус, они стали натягивать на Go. Так появились кадавры вроде Beego и Revel. Revel благополучно сдох, хотя его и пытаются все еще откачать. А вот о Beego хочется поговорить отдельно.

Немалый вклад в продвижение Beego среди масс вложил Richard Eng своим циклом статей «A word the Beegoist». Практически «Евангелие от Ричарда». Иронично, что не смотря на то, что Ричард оголтело продвигает Go, сам он на нем не пишет.

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

Давайте разберем несколько основных аспектов Beego, и почему они противоречат различным best practices в Go, да и в индустрии в целом.

Структура папок


Robert C. Martin, более известный как Uncle Bob, неоднократно озвучивал идею, что структура приложения должна передавать его суть. Он крайне любит приводить пример с кафедральным собором, на который можно посмотреть сверху, и сразу понять, что это кафедральный собор.

Роберт неоднократно критиковал Ruby on Rails за его структуру папок — controllers, models, views, вот этого всего. Проблема такого подхода заключается в том, что приложение по продаже носков «сверху» будет выглядеть точно так же, как приложение для заказа еды. И для того, чтобы понять суть приложения, нужно будет забраться в какую-нибудь папку models, и посмотреть, а с какими же сущностями мы в итоге имеем дело.

Именно это больное поведение Beego и копирует. В то время как тот же Spring ушел в сторону Domain Driven Design и структуры папок передающей суть, Beego навязывает использование структуры, ставшей уже antipattern'ом.

Но проблема даже серьезней. Для Go нет разделения между структурой папок и структурой пакетов (package'ей). Потому в Beego и UsersController и OrdersController будут под одним package'ем — controllers. А если у вас controller'ы двух типов, те, что сервят UI и те, что используются для API, причем последние в приличном обществе принято версионировать? Тогда будьте готовы к уродцам вроде apiv1.

ORM


Довольно странно, что Beego, будучи неудачным клоном Ruby on Rails, при этом не использует ActiveRecord pattern. Его ORM представляет собой крайне странное зрелище. Если для совсем базовых операций, вроде прочесть строку/записать строку, он еще годится, то вот, к примеру, как выглядит простенькая выборка (здесь и далее примеры взяты напрямую из документации):

qs.Filter("profile__age__gte", 18) // WHERE profile.age >= 18

Но основная проблема с Beego ORM даже не в том, что нужно бороться с proprietary языком, а в том, что он использует все худшие практики Go, будь то import sideffect'ов:

import (
    _ "github.com/go-sql-driver/mysql"
    _ "github.com/lib/pq"
    _ "github.com/mattn/go-sqlite3"
)

Или регистрация моделей в init():

func init(){
    orm.RegisterModel(new(User))
}

Сделайте себе одолжение, даже если вы все же решите по какой-то необъяснимой причине работать с Beego, не используйте Beego ORM. Если вам без ORM жизнь не мила (а что вы делаете в мире Go, милейший?), пользуйтесь GORM. Он хотя бы поддерживается. Иначе, «database/sql» вам в помощь.

Bee tool


Из Ruby on Rails скопирован так же command line tool, который зовется просто Bee. Вот только если в мире RoR был rails и был rake, то bee — это такая мусорка для всего. Он и MVC приложение за'boostrap'ит, и миграции прогонит, и file watcher запустит. В последнем и кроется еще одна проблема. Ведь в чем одно из основных достоинств Go? То, что запускается локально, максимально близко к тому, что запустится в production'е. Если вы не используете bee, конечно.

Automatic routing


Go — строго типизированный язык, который при этом не поддерживает ни generics, ни annotations. Как на таком слепить MVC фреймворк? Путем чтения комментов и генерации файлов, конечно.

Выглядит это примерно так:


// @Param   body        body    models.Object   true        "The object content"
// @Success 200 {string} models.Object.Id
// @Failure 403 body is empty
// @router / [post]
func (this *ObjectController) Post() {
    var ob models.Object
    json.Unmarshal(this.Ctx.Input.RequestBody, &ob)
    objectid := models.AddOne(ob)
    this.Data["json"] = map[string]string{"ObjectId": objectid}
    this.ServeJson()
}

Очевидность, как можно видеть, — нулевая. Функция Post() вообще ничего не получает и не возвращает. http.Request? Нет, не слышали.

Ну, а как работает весь routing? При запуске пресловутого bee генерируется еще один файл, commentsRouter_controllers.go, который содержит пример такого замечательного кода:

func init() {
    beego.GlobalControllerRouter["github.com/../../controllers:ObjectController"] = append(beego.GlobalControllerRouter["github.com/../../controllers:ObjectController"],
        beego.ControllerComments{
            Method: "Post",
            Router: `/`,
            AllowHTTPMethods: []string{"post"},
            MethodParams: param.Make(),
            Filters: nil,
            Params: nil})
...
}

Смотрите, не забудьте перегенерировать и за'commit'ить этот файл после каждого изменения. До последнего времени ситуация была еще печальней, и во время тестов этот файл генерировался автоматически, так что о проблемах вы узнавали уже в production'е. Кажется в последних версиях это странное поведение было исправлено.

Component testing


И так мы подходим к теме тестирования. Go, в отличие от большинства других языков программирования, приходит с тестовым фреймворком «из коробки». В целом, философия Go в том, что тест должен сидеть рядом с тестируемым файлом. Но мы же в мире MVC, плевать на философию Go, верно? Потому будьте добры все свои тесты разместить в папочке /test, как завещал нам DHH.

И это не такая уж мелочь, потому что, напомню, в Go package == folder. И если тест находящийся в том же package'е может вызвать private method, то тест находящийся в другом package — уже нет.

Но ладно бы все ограничивалось структурой папок. Код Beego в принципе очень сложно тестировать, поскольку в нем все на свете — это side effect.

Вот так Beego запрашивает routers:

import (
	_ "github.com/../../routers"
)

Та же история и с middleware'ами, и с controller'ами, которые я уже упоминал раньше.

Документация


Это для меня как software architect'а вишенка на торте. Документация в BeeGo хороша настолько, насколько хорош ваш китайский. Нет, от комментов на китайском внутри кода за последние года два уже вроде избавились.

Теперь на китайском остались только некоторые pull request'ы:

image

И в особенности в issues:



Вместо заключения


Если у вас есть команда написателей кода на Ruby/PHP/Python, и вы срочно хотите перевести их на Go, худшее, что вы можете для них сделать — это заставить их перейти на MVC фреймворк на Go. MVC в целом так себе архитектурный паттерн, а в Go он вообще не к месту. Либо, если вы уж совсем уверены, что ничто кроме Go вас не спасет, пусть переучиваются и пишут так, как в Go принято — максимально плоско и explicit. Либо, быть может им видней, при помощи какого инструмента решать поставленные им задачи?

Комментарии (53)


  1. epishman
    16.03.2019 20:49
    +3

    Ничего не знаю про BEE, но поддерживаю мысль автора, что паттерны MVC и ORM — это красивые абстракции для своего времени, но они разбились о сложность реального мира, и более неактуальны. Предметную область надо нарезать не вдоль (модели, контроллеры, презентеры и прочие технологически-обусловленные сущности), а поперек — то есть объекты или аспекты реального мира, по сути DDD. Строго мое Имхо.


    1. symbix
      16.03.2019 22:48

      MVC это вообще не паттерн, а обобщенный принцип, реализацию которого каждый видит по-своему. Есть, конечно, его описание еще из 80-х, но оно имеет очень отдаленное отношение к реализации в Rails-подобных фреймворках. Я предпочитаю избегать этого термина вообще и использовать более конкретные (скажем, hexagonal architecture).


      А вот с термином ORM все нормально, просто надо вспомнить, как он определен у того же Фаулера. Active Record (или Data Mapper) — это способы реализации ORM. Вручную написанный (скажем, с SQL запросами и Reflection-ом) маппер для конкретной сущности — это тоже ORM.


      По вопросу нарезки согласен: тут из DDD важно одно из ключевых его понятий "Bounded Context".


      1. epishman
        17.03.2019 11:15

        Ну да, я не спец в терминологии, суть в том, что самое живучее оказывается простое и легковесное, а не тяжелое и унифицированное, как большинство фреймворков, поэтому чистый go — это конечно прорыв, и старые унифицированные подходы тута незачем тащить, иначе получим еще одну Джаву.
        PS
        ОRМ не уважаю категорически, когда нужна производительность и отлаживаемость — пишу SQL только вручную, и не разу за 25 лет не пожалел.


        1. tyderh
          17.03.2019 19:29

          ОRМ не уважаю категорически, когда нужна производительность и отлаживаемость — пишу SQL только вручную, и не разу за 25 лет не пожалел.

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


          1. khim
            17.03.2019 19:56

            Уж как минимум нужно использовать prepared statements. Без них как-то вообще грустно.


        1. symbix
          17.03.2019 19:34

          ОRМ не уважаю категорически, когда нужна производительность и отлаживаемость — пишу SQL только вручную

          Еще раз повторюсь: вручную написанный SQL и ORM вполне совместимы.


          Вот на условном псевдокоде:


          class MyEntity {
              constructor(public final id: int, public final title: string);
          }
          
          interface MyEntityMapper {
               findById(id: int) -> MyEntity;
               persist(myEntity: MyEntity);
          }
          
          MyEntityMysqlMapper.findById(id: int) -> MyEntity = {
              row := db.query("select id, title from my_table where id = $1", id).fetchOneOrFail();
              return MyEntity(row.id, row.title);
          }
          
          MyEntityMysqlMapper.persist(myEntity: MyEntity) = {
              db.query("insert into t (id, title) values ($1, $2) on duplicate key update set title=$2", myEntity.id, myEntity.title);
          }

          Это тоже ORM.


      1. arturpanteleev
        17.03.2019 16:49

        Интересно, а есть успешные кейсы следования идеям DDD при написании приложух на go?
        Я чаще всего пока слышу такую точку зрения, что один микросервис на go == Bounded context и получается что код в рамках сервиса уже сам по себе сгруппирован по предметной области.
        Ну и прикрываясь этим в project structure самого проекта творится лютая дичь с папками вроде controllers, dbQuery, services и т.д Чего только стоят официальные рекомендации на этот счет.
        Т.е внутри микросервиса файлы группируются по технологическим признакам, т.к считается что вся кодовая база одного сервиса обслуживает небольшую узкую часть предметной области


        1. AlexeySoshin Автор
          17.03.2019 16:53
          +1

          У GoKit неплохие примеры на эту тему:
          github.com/go-kit/kit/tree/master/examples/shipping

          Тут вопрос, насколько узка область сущностей.


    1. shm-vadim
      17.03.2019 08:00

      они разбились о сложность
      реального мира, и более неактуальны.


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

      В конце концов, MVC — это всего навсего способ организации обработки http запроса, и он нисколько не противоречит DDD. А, наоборот, чаще всего с ним сочетается.

      Если MVC — это неправильная архитектура организации приложения, то как тогда в go надо? Чем он так принципиально отличается от всего остального back-end мира?


      1. Q2W
        17.03.2019 09:13
        +3

        MVC — это всего навсего способ организации обработки http запроса

        MVC к HTTP не имеет отношения.


        1. TheShock
          17.03.2019 15:37

          Я так понял, что автор комментария имеет ввиду «MVC в контексте бекенда web-приложения — это всего навсего способ организации обработки http запроса»


      1. epishman
        17.03.2019 11:24
        -2

        На мой взгляд в новых ЯП надо возвращать старинный способ объектного моделирования сущностей реального мира — класс инкапсулирует в себе все 3 аспекта — данные, логику и представление (вплоть до куска HTML со стилями и скриптами). Это соответствует тренду к микро-сервисным архитектурам. Это соответствует самой жизни, ведь человек умудряется носить с собой свое вью и контроллер внутри одного черепа, если макияж не считать. Принудительно разрезать реальный объект на три уровня MVC — это создавать себе проблемы на ровном месте, пытаясь вместо классического наследования применять композицию, да еще и такую негибкую.


        1. shm-vadim
          17.03.2019 13:28

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


          1. epishman
            18.03.2019 11:09

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


  1. Q2W
    16.03.2019 22:58
    -1

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

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

    И работодателю очень сильно кажется, что как раз такие люди для него особенно эффективны. А они ещё и не шибко дороги.

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

    Я всё это к чему. Если миллион мух делает что-то ужасное, это совершенно не значит, что что-то в этом мире не так. Главное, не работать с этими мухами вместе, чтобы не приходилось иметь дело с тем же, что и они.


    1. symbix
      16.03.2019 23:03

      ООП нисколько не устарело. Устарело то понимание ООП, которому учат студентов (при этом в основном учат те, кто сам толком не понимает ООП).


      Модный ныне DDD — это по сути и есть реализация принципов SOLID. Давно уже модные микросервисы — тоже, по сути, ООП: если каждый микросервис рассматривать как объект, получается 1 в 1 определение Алана Кея.


      1. epishman
        17.03.2019 11:26

        Тысячу раз да. ООП — это самый лучший паттерн из мне известных, и даже Go его поддерживает :)


  1. untilx
    17.03.2019 01:36

    И это не такая уж мелочь, потому что, напомню, в Go package == folder. И если тест находящийся в том же package'е может вызвать private method, то тест находящийся в другом package — уже нет.

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


    1. AlexeySoshin Автор
      17.03.2019 13:26

      В Go в целом нет такой вещи, как private method, все package private.


    1. a1ien_n3t
      17.03.2019 19:19
      +1

      С чего вы взяли что тестирование приватных методов это моветон.


      1. Lailore
        17.03.2019 20:03

        Наверно исходя из того, что тестировать надо поведение и результат, а не «внутренности». Иначе, тест будет по сути тем же, что и тестируемое… только написано сложнее и корявее :)


        1. a1ien_n3t
          17.03.2019 21:38

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


        1. khim
          17.03.2019 21:54
          +1

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

          </sarcasm>

          Тестировать нужно на всех уровнях: через API делаются инеграционные тесты, а через внутренние методы — низкоуровневые тесты. И они друг друга нифига не заменяют.


  1. mrobespierre
    17.03.2019 08:23

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


    1. nile1
      17.03.2019 09:16
      +1

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


      Как пример — библиотека логирования glog регистрирует глобальные флаги командной строки при импорте, и требует парсинга этих флагов. Переименовать флаги нельзя, при конфликте возникает panic. Чтобы решить проблемы с glog в Kubernetes, ее в итоге форкнули в https://github.com/kubernetes/klog/blob/master/README.md


      Пример описания проблем с glog: https://github.com/kubernetes/kubernetes/issues/61006


      1. kmansoft
        17.03.2019 11:03
        +1

        Простите но импорт вот конкретно драйверов баз данных делается именно так.


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


        С другой, они используются через рефлексию, имя драйвера задаётся в connect string. Обычный импорт будет ошибкой компиляции.


        И да это так устроена стандартная библиотека sql.


      1. creker
        17.03.2019 14:59

        Глобальное состояние в целом не зло, особенно в Go, где правила несколько изменились и повсеместное применение глобальных package-level переменных и прочего работает и проблем не создает в большинстве случаев. Все таки это идиоматичный Go, а не какая-то редкая практика. Единичные примеры тут мало что значат и говорят, в первую очередь, о странно написанном glog. Либа, которая лезет во флаги командной строки — вот где проблема, а не в глобальном состоянии.


    1. AlexeySoshin Автор
      17.03.2019 13:26

      То, что так сделано в стандартной библиотеке — не значит, что это хорошая практика.


      1. youROCK
        17.03.2019 14:13

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


        1. AlexeySoshin Автор
          17.03.2019 15:57

          Писать fullstack приложения на Go, как это предлагает делать Beego, явно не стоит.


        1. symbix
          17.03.2019 22:18

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


          1. khim
            17.03.2019 22:36

            Я бы даже сказал сильнее: на языке, где в стандартной библиотеке все «прямо и красиво» ничего писать не стоит. Потому что вариантов ровно два:
            1. Эту библиотеку постоянно меняют и ломают совместимость (см. D).
            2. Язык ещё невероятно молодой и на нём мало чего написано, отчего и непонятно — что именно сделано криво в стандартной библиотеке (см. 100500 новых и новейших языков).


          1. youROCK
            17.03.2019 23:01

            Ну Go не такой молодой язык, чтобы ему требовалось из соображений совместимости что-то оставлять :). Не думаю, что авторы языка считают "_" импорт ради побочных эффектов за плохую практику.


            1. TonyLorencio
              17.03.2019 23:38

              Обычно импорт "_" делается либо для того, чтобы сработал init() пакета, либо чтобы достать что-то импортированное через рефлексию.


              Сомневаюсь, что в общем случае это хорошая идея.


              1. youROCK
                17.03.2019 23:42

                Да, я собственно про вариант с init() и говорил :).


      1. creker
        17.03.2019 14:56

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


  1. ZurgInq
    17.03.2019 10:05
    -1

    Достаточно надуманная критика, которая явно исходит из личных предпочтений и своего взгляда на best practics. И ещё есть постоянные болезненные отсылки к RoR.
    Я ни разу не пользователь beego, и на go уже достаточно давно ничего не писал, но могу отметить, что большая часть пунктов притянута за уши.

    >Структура папок

    Сильная субъективщина на несколько абзацов текста. Либо фрэймворк позволяет создать свою структуру приложения (пусть даже подпакетами внутри controllers\models\view и т.д.), либо нет. Маловероятно, что в beego есть жесткий лок на структуру директорий.

    >ORM
    >Но основная проблема с Beego ORM даже не в том, что нужно бороться с proprietary языком, а в том, что он использует все худшие практики Go, будь то import sideffect'ов

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

    >Bee tool
    >Вот только если в мире RoR был rails и был rake, то bee — это такая мусорка для всего

    Неправда. Если я правильно помню, в RoR5 команды «rails command» полностью заменяют rake, а в RoR4 почти всё было через rake. Да и в целом разделение не принципиальное. И непонятно, где у автора проблема с filewatcher возникла.

    >Automatic routing
    >Ну, а как работает весь routing? При запуске пресловутого bee генерируется еще один файл, commentsRouter_controllers.go

    Тут можно согласиться, что аннотации в go выглядят несколько странно. Но вот генерация дополнительно файла (от кодогенератора) — так делают все кодогенераторы в go.

    >Component testing
    >И если тест находящийся в том же package'е может вызвать private method, то тест находящийся в другом package — уже нет.

    Если вы хотите постоянно тестировать приватные методы, то у вас более крупные проблемы, чем война с beego.


    1. abmanimenja
      18.03.2019 03:35

      Если вы хотите постоянно тестировать приватные методы, то у вас более крупные проблемы


      Не могли бы вы пояснить свою мысль.


  1. Nick_Maverick
    17.03.2019 11:19

    Мне вот как то наоборот, BeeGo приятен.
    По моему опыту, я использовал его — от middleware до back-end. По бек скажу за MVC — как раз благодаря этому, сначала пренес логику с Java на Beego, ну и потом еще раз логику с обычного контейнера на AWS Lambda

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

    Да в общем то по бизнес логике, это практически одинаковые процессы, отличающиеся нюансами предметной области.
    Тогда будьте готовы к уродцам вроде apiv1

    И в чем проблема в поддержании версий апи живыми? Очень похоже реализована версионность в AWS
    А насчет кодогенерации, то что есть в Beego гораздо помягче Dagger'a


    1. AlexeySoshin Автор
      17.03.2019 13:32

      это практически одинаковые процессы, отличающиеся нюансами предметной области

      Так предметную область и надо выставлять на показ.

      И в чем проблема в поддержании версий апи живыми?

      Проблема не в поддержании API, проблема в том, что теряется вся семантика.

      А насчет кодогенерации, то что есть в Beego гораздо помягче Dagger'a

      С Dagger не работал. Там тоже приходится сгенерированный код коммитить?


      1. c4boomb
        17.03.2019 17:13
        +1

        С Dagger не работал. Там тоже приходится сгенерированный код коммитить?

        Я не работал с Go и Beego, но работал с многими системами где было много кодогенерации. Весь этот процесс успешно встраивался в Build.
        То есть генерируемый файл не коммитился в репозиторий, а генерировался в процессе создания Build-а в Bamboo, который впоследствии деплоился на сервер.


        Чем вызвана нужда генерировать файл локально?


      1. TonyLorencio
        17.03.2019 20:34

        Там тоже приходится сгенерированный код коммитить?

        В Go, насколько я помню, принято коммитить сгенерированный код


        1. TheShock
          17.03.2019 21:12

          О! Еще одна глупость в гоу. Которая полностью паскудит статистику и делает менее юзабельными дифы.


          1. Hixon10
            18.03.2019 00:15

            Зачем строить статистику по сгенерированному коду? Зачем смотреть диффы по сгенерированнмоу коду?


            1. TheShock
              18.03.2019 00:31
              -1

              Я тоже не понимаю зачем. Зачем она коммитится и, в результате, строится автоматически?


      1. Nick_Maverick
        17.03.2019 23:00

        Так предметную область и надо выставлять на показ.

        Вот тут можно подробней. На мой взгляд, достоинство систем с солид -подходом (mvc, IMHO, это проекция Single Responsibility Principle с выделением отображений. Просто логичный способ разделения логики приложения) это то что их просто изменять и рефакторить. Вот как тут более на показ выставить предметную область?
        проблема в том, что теряется вся семантика

        Вот тут можно подробней. У себя я семантику апи реализовывал как json на вход. Ну если не лень, можно и полный GraphQL распарсить.
        ну и чтоб два раза не вставать,
        эту архитектуру, как сову на глобус, они стали натягивать на Go

        mvc, IMHO, это проекция Single Responsibility Principle на вот это все с отображением. Просто логичный способ разделения логики приложения. И как то без разницы, на каком языке.


        1. AlexeySoshin Автор
          18.03.2019 12:09

          Вот как тут более на показ выставить предметную область?

          Вместо:
          root/
          --controllers/
          ----userController
          ----orderController
          --models/
          ----user
          ----order
          --views/
          ----user.view
          ----order.view


          Можно иметь
          root/
          --user/
          ----user
          ----userController
          ----user.view
          --order/
          ----order
          ----orderController
          ----order.view


          У себя я семантику апи реализовывал как json на вход

          А как быть с семантикой внутри приложения? В том же JavaScript'е хотя бы namespacing при импорте нормальный:
          import { UsersController } from './api/v1/usersController.js'

          В Go так не выйдет.


          1. TheShock
            19.03.2019 04:10

            Можно иметь
            И если в order.view используется user.model, а в user.view — order.model, то у нас получается спагетти. С классическим разделением контроллеров-вьюшек-моделей такая проблема проблема проявляется значительно меньше.


  1. arturpanteleev
    17.03.2019 16:59

    как в Go принято — максимально плоско и explicit

    Это верно подмечено, иначе просто не получится. Да и вообще понравились мысли в заключении. Я вот перехожу с java like языков на golang ну идеологически ахереваю переход дается очень тяжело.
    При написании кода складывается ощущение что вернулся лет на 5 назад — ни нормального ddd, grasp, rich domain models, hexagonal architecture — ничего из этого не требуется, и более того, порицается со словами «это не go way»
    Вообще я вижу go как язык с довольно узкой нишей(в которой он чертовски хорош). И очень грустно от того, что все почему то увидели в нем серебряную пулю, способную заменить enterprise языки. Из за попыток таких замен и получаются такие недоразумения как фреймворк, которому посвящена статья.


    1. AlexeySoshin Автор
      17.03.2019 17:04
      -1

      Go очень легко продавать менеджменту — «низкий порог входа, нанимаем джунов, concurrency, 100K RPS, все дела».


    1. iago
      17.03.2019 20:25

      а в какой нише он чертовски хорош? Просто не в теме, интересно


  1. vmpartner
    17.03.2019 18:10

    Использую Beego постоянно, про DDD и ORM согласен, ужас ужасный.
    Но не всё так плохо, изучал другие фреймворки, во многих разработка вообще встала 3-4 года назад.
    В Beego мне нравится роутинг, шаблоны, получение параметров запроса, файлов запроса и тп, контроллеры содержат кучу полезных мелочей для облегчения разработки, получается не думать про организацию и работу кода, а сосредоточится только на реализации, при том вес фреймворка маленький.
    Для примера переписал свой средний сайт с аудиофайлами, личный кабинет полностью, управление файлами, панель администратора, весь фронт — за 2 недели (вечерами от основной работы) и сайт весит теперь 10Мб RAM против ~500Мб на php (+ memcache столько же), ну а скорость работы просто самолёт )) Поэтому можно закрыть глаза на временное отсутствие нормальных DDD фреймворков.


  1. kuftachev
    18.03.2019 03:31
    +1

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


    Главная проблема в современном программировании, что большинство читает всяких Фаулеров и Мартинов, но почти никто не читает Таненбаума, Кернигана и других умных людей, которые реально учёные и инженеры, а не "консультанты".


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