Биго Больше Не Го

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

Менее смешно, когда ты непосредственно в этом участвуешь.

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

.

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

Вот как трупы любят Биго и Ревель .

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

Но о Биго я хочу поговорить отдельно.

Ричард Энг внес значительный вклад в продвижение Биго в массы своей серией статей.

«Слово пчелоист» .

Почти «Евангелие от Ричарда».

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



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

Роберт К.

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

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

Роберт неоднократно критиковал Ruby on Rails за структуру папок — контроллеры, модели, представления и все.

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

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

Именно это болезненное поведение копирует Биго.

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

Но проблема еще серьезнее.

В Go нет разделения между структурой папок и структурой пакета.

Поэтому в Beego и UsersController, и OrdersController будут находиться в одном пакете — контроллерах.

Что делать, если у вас есть два типа контроллеров, те, которые обслуживают UI, и те, которые используются для API, и в приличном обществе принято версионировать последние? Тогда будьте готовы к уродам вроде apiv1.

ОРМ

Довольно странно, что Beego, будучи неудачным клоном Ruby on Rails, не использует паттерн ActiveRecord. Его ОРМ представляет собой крайне странное зрелище.

Если для совсем базовых операций, вроде чтения/записи строки, он еще годится, то вот, например, так выглядит простой образец (здесь и далее примеры взяты непосредственно из документации):

  
  
  
  
  
   

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

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

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, дорогой?), используйте ГОРМ .

По крайней мере, это поддерживается.

В противном случае, "база данных/sql" чтобы помочь вам.



Пчелиный инструмент

Инструмент командной строки, который называется просто, тоже был скопирован из Ruby on Rails Пчела .

Но если в мире РоР были рельсы и были грабли, то пчела - это такая помойка для всего.

Он «ускорит» приложение MVC, запустит миграцию и запустит средство наблюдения за файлами.

В последнем заключается еще одна проблема.

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

Если вы не используете пчелу, конечно.



Автоматическая маршрутизация

Go — строго типизированный язык, который не поддерживает ни дженерики, ни аннотации.

Как создать структуру 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.Запрос? Нет, мы не слышали.

Ну и как вся маршрутизация работает? При запуске пресловутой пчелки генерируется еще один файл, commentRouter_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}) .

}

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

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

Кажется, это странное поведение исправлено в последних версиях.



Тестирование компонентов

И вот мы подошли к теме тестирования.

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

В целом философия Go заключается в том, что тест должен находиться рядом с тестируемым файлом.

Но мы находимся в мире MVC, и нас не волнует философия Go, верно? Поэтому, пожалуйста, поместите все ваши тесты в папку /test, как вы нам завещали.

ДХХ .

И это не такая уж мелочь, ведь, напомню, в папке Go package ==.

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

Код Beego в принципе очень сложно тестировать, так как все в нем — побочный эффект. Вот как Beego запрашивает маршрутизаторы:

import (

Теги: #программирование #Go #golang #framework #ruby onrails #beego

Вместе с данным постом часто просматривают: