Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Роберт Егоров - Уходим с Кобола современности на Go при разработке ентепрайз решений

gdg_rnd
September 17, 2017

Роберт Егоров - Уходим с Кобола современности на Go при разработке ентепрайз решений

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

GDG South DevFest 2017

gdg_rnd

September 17, 2017
Tweet

More Decks by gdg_rnd

Other Decks in Programming

Transcript

  1. темы доклада www.website.ru @telegram vkontakte facebook Роберт Егоров - РФ:

    программист, архитектор, руководитель разработки, до 2006 - Чехия: Продуктовый менеджер, продуктовый директор - Чехия/Босния/Сербия/РФ: Консультант, CTO - Чехия/РФ: Гофер, one man show, стартапы/заказная разработка ПО One man show
  2. темы доклада Целевая аудитория • Кто присматривается к Go •

    Кто уже начал использовать Go в небольших проектах • Кто еще пишет на «Коболе»
  3. темы доклада • разработка продукта • облачный • тиражируемый •

    разработка на заказ • уникальное решение • тиражируемое • аутстаффинг/аутсорсинг Виды разработки ПО Продуктовая разработка Разработка на заказ …“Добавим движок!”.. …”И так сойдет!”…
  4. темы доклада • Автоматизация отдельных бизнес процессов • Учетная система

    • Биллинг • Медицинская информационная система • Account Management/CRM/Loyalty • ERP • Другие Типичное заказное решение
  5. темы доклада • Критичность для бизнеса/SLA • Нет доступа к

    продакшн платформе • Небольшое количество одновременно работающих пользователей • Много сущностей и пользовательских форм • Разнообразие отчетных форм • Разные операционные системы • Противодействие пользователей • Некомпетентность пользователей • Некомпетентность администраторов или отсутствие на фултайм • Необходимость передавать исходные тексты Особенности enterprise решений
  6. темы доклада • Простой в изучении • Компилируемый под разные

    ОС/Архитектуры • Принцип: явное лучше неявного • Быстрая скорость компиляции • Низкий оверхед финального приложения • Единые правила форматирования кода • Встроенные средства тестирования и бенчмаркинга • Проверен в крупных проектах, используется крупнейшими мировыми компаниями Golang с точки зрения CTO И еще можно сказать про микросервисы!
  7. темы доклада • Покажите пример приложения или фреймворк • Как

    организовать main() • Как хранить параметры приложения • Каким логгером пользоваться • Какой http роутер выбрать • Как Вы работаете с базой данных… Вопросы новичков из Слака golang-ru.slack.com
  8. темы доклада • Сеть стоматологических клиник • 150 пользователей в

    рабочее время • Он-лайн кассы • Частично компьютеры с Windows XP • Отсутствие фултайм администратора • Нет специалиста для постановки технического задания. • Оставляем права себе! • 60 часов интервью • Выявление сценариев пользователей Запрос Ответ
  9. темы доклада • Google Docs • Облачная Jira • draw.io

    • Enterprise Architect (vertabelo*) • moqups.com • IDE: Gogland, LiteIDE • Система сборки Jenkins • Postgres • ReactJS Наш набор инструментов
  10. темы доклада Варианты границ ответственности База данных Сервер Go Клиент

    База данных Сервер Go Клиент База данных Клиент back front Сервер Go JSON JSON JSON
  11. темы доклада • Знает Go • Дизайн физической модель БД

    • Пишет слой доступа к данным и кэшам • Пишет ключевые конструкции приложения • Предоставляет Go методы/функции для фронтендера • Менторинг фронтендера по Go Бэкендер Фронтендер • HTML/CSS/JS по мокапам • Изучает Go! • Пишет HTTP контроллеры на Go • Вызывает Go методы backend • Меняет структуру JSON API для эффективности – Профит!
  12. темы доклада • Покажите пример приложения или фреймворк • Как

    организовать main() • Как хранить параметры приложения • Каким логгером пользоваться • Какой http роутер выбрать • Как Вы работаете с базой данных… Вопросы новичков из Слака golang-ru.slack.com
  13. темы доклада Структура проекта \project \backend \model \cmd \pos \prjsrv

    main.go \db \frontend \assets \controllers \react_app \pos \companyname \aaa \date \language \logger \ref \tracker project.go Это наша типовая структура
  14. темы доклада main.go package main import "os" func main() {

    os.Exit(realMain()) } func realMain() int { // основные действия тут return 0 } Возврат кода завершения в ОС
  15. темы доклада main.go package main import ( "fmt" "os" )

    var VersionNumber string func main() { os.Exit(realMain()) } func realMain() int { fmt.Println("Version:", VersionNumber) return 0 } Автоматически привязываем версию/uid коммита, для облегчения дальнейших разбирательств $ go build -ldflags="-X main.VersionNumber=0.1" main.go
  16. темы доклада Параметры приложения Хороший тон следовать рекомендациям 12fapp, но

    не торопимся разделять все параметры сразу • Хороший тон все параметры передавать через командную строку и/или переменные среды окружения • На практике, когда параметров больше N необходимо разделять, что будет передаваться из командной строки, что может лежать в конфигурационном файле, базе данных.
  17. темы доклада Конфигурация main.go type Config struct { Backend backend.Config

    `json:”backend”` Frontend frontend.Config`json:”frontend”` // собственные параметры } backend.go // DatabaseConfig хранит параметры подсоединения к БД. type DatabaseConfig struct { User string `json:"user"` Password string `json:"password"` Host string `json:"host"` Port int `json:"port"` DbName string `json:"dbName"` SSLMode string `json:"sslMode"` Schema string `json:"schema"` MaxOpenConns int `json:"maxOpenConns"` MaxIdleConns int `json:"maxIdleConns"` } // Config содержит параметры инициализации бэкенда. type Config struct { Db DatabaseConfig `json:"db"` Debug bool `json:"debug"` Demo bool `json:"demo"` ModelParams model.Config `json:“model"` } \project \backend backend.go \model model.go \cmd \pos \prjsrv main.go \db \frontend \assets \controllers \react_app \pos \companyname \aaa \date \language \logger \ref \tracker project.go
  18. темы доклада main.go – realMain() // Чтение параметров конфигурации в

    переменную cfg // Создание объекта logger // инициализация бэкенда. back, err := backend.New(&cfg.Backend, &cfg.Logger, logger) if err != nil { logger.Error("Ошибка инициализации бэкенда", "errmsg", err.Error()) return 2 } // инициализация фронтенда front, err := frontend.New(&cfg.Frontend, logger, back, hub) if err != nil { logger.Error("Ошибка инициализации фронтенда", "errmsg", err) return 3 } \project \backend \model backend.go \cmd \pos \prjsrv main.go \db \frontend \assets \controllers \react_app frontend.go \pos \companyname \aaa \date \language \logger \ref \tracker project.go // Backend обеспечивает бизнес логику и предоставляет единую точку входа. type Backend struct { db *sql.DB log log.Logger dbConfig DatabaseConfig Book *ref.BookCache Model *model.Model }
  19. темы доклада main.go – realMain() var wg sync.WaitGroup stop :=

    make(chan os.Signal) signal.Notify(stop, syscall.SIGINT) stop1 := make(chan struct{}) // запускаем фоновые процессы (обновления кэшей и т.д.) if err := back.Start(&wg, stop1); err != nil { logger.Error("Ошибка запуска процесса backend", "errmsg", err.Error()) return 5 } // запуск обработчиков клиентских HTTP запросов. if err := front.Start(&wg, stop1); err != nil { logger.Error("Ошибка запуска процесса frontend", "errmsg", err.Error()) return 6 } logger.Info("Приложение готово обрабатывать запросы пользователей") // ожидание сигнала SIGINT для аккуратного завершения работы приложения. <-stop logger.Info("Получен сигнал SIGINT. Ожидаем окончания работающих потоков") close(stop1) wg.Wait() log.Info("Приложение аккуратно завершило свою работу") return 0
  20. темы доклада backend.go – New() func New(cfg *Config, cfgLogger *logwriter.Config,

    l log.Logger) (*Backend, error) { var err error b := &Backend{log: l.New("layer", "backend"), dbConfig: cfg.Db} i := 0 for { err = b.connectDB() if err == nil { break } if cfg.Debug { return nil, err } i++ b.log.Warn("Ошибка подключения к БД", "attempt", i, "errmsg", err) if i < 10 { time.Sleep(time.Second) } else { time.Sleep(10 * time.Second) } } b.Model, err = model.New(b.db, b.log) if err != nil { return nil, err } b.AAA, err = aaa.New(b.Model, b.log) if err != nil { return nil, err } return b, nil } \project \backend \model model.go backend.go \cmd \pos \prjsrv main.go \db \frontend \assets \controllers \react_app frontend.go \pos \companyname \aaa \date \language \logger \ref \tracker project.go
  21. темы доклада model.go – New() func New(db *sql.DB, cfg *Config,

    l log.Logger) (*Model, error) { m := &Model{logger: l.New("component", "model"), db: db, cfg: cfg, calc: calc, cfgLogger: cfgLogger, changed: make(map[string]bool)} var ( wg sync.WaitGroup err error ) var funcs = []func(*error){ func(e *error) { m.Users, *e = NewUsers(m) }, func(e *error) { m.Roles, *e = NewRoles(m) }, func(e *error) { m.Permissions, *e = NewPermission(m) }, func(e *error) { m.Sessions, *e = NewSessions(m) }, .. .. } var arr = make([]error, len(funcs)) wg.Add(len(arr)) for i := range funcs { go func(k int) { funcs[k](&arr[k]) wg.Done() }(i) } wg.Wait() for i := range arr { if arr[i] != nil { return nil, arr[i] } } \project \backend \model model.go backend.go \cmd \pos \prjsrv main.go \db \frontend \assets \controllers \react_app frontend.go \pos \companyname \aaa \date \language \logger \ref \tracker project.go
  22. темы доклада Логгер Все пользователи врут! • Встроенный обеспечивает базовые

    функции • Много разных на гитхаб • Каждый по своему хорош • Все еще появляются новые • Идеального нет • Пишем всё • Используем log15 за собственной оберткой
  23. темы доклада http роутер Не смотрите на бенчмарки! • Встроенный

    неплох, но для растущего проекта недостаточно функционален • Много разных на гитхаб • Каждый по своему хорош • Все еще появляются новые • Идеального нет • Используем echo
  24. темы доклада Формирование отчетов Давайте объединять усилия! • Самое слабое

    звено • HTML шаблоны • Библиотека создания xlsx файлов tealeg/xlsx • Собственные наработки поверх tealeg/xlsx, которые пока стыдно выкладывать на гитхаб ☺