статья:Практика разработки|О задачах сложения, вычитания, умножения и деления в пределах 100 к существующим ошибкам, с которыми сталкиваются клиенты на сайте Комментарий: В данной статье в основном рассказывается авторский процесс решения задачи анализа данных на площадке заказчика. Клиент обнаружил, что сумма процентов на круговой диаграмме не равна 100 % из-за потери точности данных и округления. Анализируя источники данных и сравнивая различные методы обработки, автор наконец принял алгоритм компенсации: при последнем процентном расчете вычитается сумма всех предыдущих процентов, чтобы гарантировать, что общая сумма равна 100%. Автор резюмирует проблемы с точностью, которые могут возникнуть при отображении данных в виде круговой диаграммы, подчеркивает важность устранения неполадок данных, оптимизации конфигураций инструментов и достижения компромиссов с клиентами, а также выражает свой опыт обучения общению с клиентами при решении проблем.
ты поддерживаешь Go
Как выглядит архитектура кода проекта? Шестиугольная архитектура? Или луковая архитектура? Или, может быть, DDD
?несмотря ни на чтопроект Какая архитектура используется?,Основные цели должны быть одинаковыми: сделать код простым для понимания, тестирования и сопровождения.
Эта статья начнется с Bob
дяди Чистая архитектура(Clean Architecture
)Отправляться,Кратко проанализируйте его основные идеи.,и объединить go-clean-arch
Склад, подробный обзор того, как Go
Эта архитектурная концепция реализована в проекте.
Вы готовы? Возьмите чашку любимого кофе или чая и узнайте, прочитав эту статью.
Чистая архитектура(Clean Architecture
)да Bob
Концепция проектирования архитектуры программного обеспечения, предложенная Дядюшкой, целью которой является упрощение понимания, тестирования и обслуживания программных систем за счет иерархических структур и четких правил зависимостей. Основная идея состоит в том, чтобы разделить фокус наточка,Обеспечить основную бизнес-логику в системе(Use Cases
)Не зависит от деталей реализации(как рамка、база данных и др.).
Clean Architecture
Основная идея заключается в том, независимость:
Gin
、GRPC
ждать). Фреймворки должны быть инструментами, а не ядром архитектуры.UI
:Пользовательский интерфейс можетк Легко изменить,не затрагивая другие части системы. Например,Web UI
Можно заменить на консоль. UI
,Нет необходимости изменять бизнес-правила.MySQL
Заменить на MongoDB
),не затрагивая основную бизнес-логику.Как показано на картинке,Clean Architecture
к концентрические круги описывается таким образом, что каждый уровень представляет собой различную ответственность системы:
Entities
)Use Cases
/ Service
)Interface Adapters
)
- Местоположение: на один уровень дальше снаружи
- Обязанности: Отвечает за передачу данных из внешних систем (таких как пользовательский интерфейс, база данных и т. д.) в формат, понятный внутреннему уровню, а также используется для преобразования основной бизнес-логики в форму, пригодную для использования внешними системами.
Например: будет HTTP
Запрошенные данные преобразуются во внутреннюю модель (например, класс или структуру), либо пользователю отображаются выходные данные по варианту использования.
- компоненты:Включает контроллер、шлюз(Gateways
)、Presenter
ждать.Frameworks & Drivers
)UI
、Ожидание очереди сообщений.go-clean-arch
это осознать Чистая архитектура(Clean Architecture
)один из Go
Примерпроект。Долженпроект Существует четыре доменных слоя.(Domain Layer
):
Models Layer
слой моделиEntities
)。package domain
import (
"time"
)
type Article struct {
ID int64 `json:"id"`
Title string `json:"title" validate:"required"`
Content string `json:"content" validate:"required"`
Author Author `json:"author"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
Repository Layer
слой храненияFrameworks & Drivers
)。package mysql
import (
"context"
"database/sql"
"fmt"
"github.com/sirupsen/logrus"
"github.com/bxcodec/go-clean-arch/domain"
"github.com/bxcodec/go-clean-arch/internal/repository"
)
type ArticleRepository struct {
Conn *sql.DB
}
// NewArticleRepository will create an object that represent the article.Repository interface
func NewArticleRepository(conn *sql.DB) *ArticleRepository {
return &ArticleRepository{conn}
}
func (m *ArticleRepository) fetch(ctx context.Context, query string, args ...interface{}) (result []domain.Article, err error) {
rows, err := m.Conn.QueryContext(ctx, query, args...)
if err != nil {
logrus.Error(err)
return nil, err
}
defer func() {
errRow := rows.Close()
if errRow != nil {
logrus.Error(errRow)
}
}()
result = make([]domain.Article, 0)
for rows.Next() {
t := domain.Article{}
authorID := int64(0)
err = rows.Scan(
&t.ID,
&t.Title,
&t.Content,
&authorID,
&t.UpdatedAt,
&t.CreatedAt,
)
if err != nil {
logrus.Error(err)
return nil, err
}
t.Author = domain.Author{
ID: authorID,
}
result = append(result, t)
}
return result, nil
}
func (m *ArticleRepository) GetByID(ctx context.Context, id int64) (res domain.Article, err error) {
query := `SELECT id,title,content, author_id, updated_at, created_at
FROM article WHERE ID = ?`
list, err := m.fetch(ctx, query, id)
if err != nil {
return domain.Article{}, err
}
if len(list) > 0 {
res = list[0]
} else {
return res, domain.ErrNotFound
}
return
}
Usecase/Service Layer
Вариант использования/уровень обслуживанияUse Cases
/ Service
)。package article
import (
"context"
"time"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"github.com/bxcodec/go-clean-arch/domain"
)
type ArticleRepository interface {
GetByID(ctx context.Context, id int64) (domain.Article, error)
}
type AuthorRepository interface {
GetByID(ctx context.Context, id int64) (domain.Author, error)
}
type Service struct {
articleRepo ArticleRepository
authorRepo AuthorRepository
}
func NewService(a ArticleRepository, ar AuthorRepository) *Service {
return &Service{
articleRepo: a,
authorRepo: ar,
}
}
func (a *Service) GetByID(ctx context.Context, id int64) (res domain.Article, err error) {
res, err = a.articleRepo.GetByID(ctx, id)
if err != nil {
return
}
resAuthor, err := a.authorRepo.GetByID(ctx, res.Author.ID)
if err != nil {
return domain.Article{}, err
}
res.Author = resAuthor
return
}
Delivery Layer
уровень доставкиHTTP
клиент или CLI
пользователь).Interface Adapters
)。package rest
import (
"context"
"net/http"
"strconv"
"github.com/bxcodec/go-clean-arch/domain"
)
type ResponseError struct {
Message string `json:"message"`
}
type ArticleService interface {
GetByID(ctx context.Context, id int64) (domain.Article, error)
}
// ArticleHandler represent the httphandler for article
type ArticleHandler struct {
Service ArticleService
}
func NewArticleHandler(e *echo.Echo, svc ArticleService) {
handler := &ArticleHandler{
Service: svc,
}
e.GET("/articles/:id", handler.GetByID)
}
func (a *ArticleHandler) GetByID(c echo.Context) error {
idP, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusNotFound, domain.ErrNotFound.Error())
}
id := int64(idP)
ctx := c.Request().Context()
art, err := a.Service.GetByID(ctx, id)
if err != nil {
return c.JSON(getStatusCode(err), ResponseError{Message: err.Error()})
}
return c.JSON(http.StatusOK, art)
}
go-clean-arch
Общая архитектура кода проекта выглядит следующим образом:
go-clean-arch/
├── internal/
│ ├── rest/
│ │ └── article.go # Delivery Layer уровень доставки
│ ├── repository/
│ │ ├── mysql/
│ │ │ └── article.go # Repository Layer слой хранения
├── article/
│ └── service.go # Usecase/Service Layer Вариант использования/уровень обслуживания
├── domain/
│ └── article.go # Models Layer слой модели
существовать go-clean-arch
В проекте зависимости между каждым слоем следующие:
Usecase/Service
зависимость слоя Repository
интерфейс, но не знает деталей реализации интерфейса.Repository
Уровень реализует интерфейс, но это внешний компонент, который зависит от Domain
объект слоя.Delivery
слой (например, REST Handler
)вызов Usecase/Service
уровень, отвечающий за преобразование внешних запросов в вызовы бизнес-логики.Эта конструкция соответствует принципу инверсии зависимостей, гарантируя, что основная бизнес-логика не зависит от деталей внешней реализации и имеет более высокую тестируемость и гибкость.
Эта статья объединяет Bob
дяди Чистая архитектура(Clean Architecture) и go-clean-arch
Пример проекта, объясняет, как существовать Go
Реализация в проекте Clean архитектура. Четкое разделение фокусов посредством иерархических структур, таких как основные сущности, варианты использования, адаптеры интерфейса и внешние структуры. наточка,Сделать основную бизнес-логику системы(Use Cases
)с деталями внешней реализации(как рамка、база данных) развязка.
go-clean-arch
В структуре проекта используется иерархический подход к организации кода с четкими обязанностями на каждом уровне:
Это всего лишь пример проекта,Конкретный архитектурный дизайн проекта должен гибко корректироваться в соответствии с фактическими потребностями, привычками команды и спецификациями. Основная цель — сохранить принцип многоуровневого подхода.,Убедитесь, что код легко понять, протестировать и поддерживать.,В то же время он поддерживает долгосрочное расширение и развитие системы.
Здравствуйте, я Чэнь Мингён, разработчик, который любит технологии и готов ими делиться, а также энтузиаст открытого исходного кода.
Путь к успеху не переполнен. Вы заинтересованы в поиске партнера?
Следуйте за мной, добавляйте меня в друзья, учитесь и совершенствуйтесь вместе!