Сообщение Re: Практики разбивки проекта на пакеты от 02.01.2024 8:30
Изменено 02.01.2024 8:31 Doom100500
Re: Практики разбивки проекта на пакеты
Здравствуйте, a9000, Вы писали:
A>Добрый день! Есть проект на Go, проект разрастается, и стало неудобно когда все файлы в IDE в одном длинном списке. Хочется разбить на папки.
A>А, насколько я понимаю, это также подразумевает разбивку на пакеты (или нет?).
Да, это подразумевает разбиение на пакеты, и, как следствие, заставляет задуматься о публичных интерфейсах, доступных снаружи, приватной имплементации. Что, в свою очередь, приведёт к тому, что публичные интерфейсы можно будет мокать в тестах. Одни прелести вобщем.
A>Сейчас есть main, содержащий глобальную структуру Application, в которой хранятся всякие общие для всего проекта сущности
A>Объект соединения с БД
A>Объект с разными настройками программы, читаемыми из конфига
A>Объект соединения с удаленным сервисом, предоставляющим данные по API
A>Объект собственного веб-сервера
A>Объект прокси
A>и т.п.
A>Есть группа файлов, которая занимается только работой с БД (выполняет запросы и возвращает массивы с результатами)
A>Есть группа файлов, которая занимается запросами к удаленному серверу с помощью его API и складыванием результатов в БД
A>Есть группа файлов, которая занимается формированием собственного веб-интерфейса; она также использует объект БД
A>Есть файлы, содержащие общие вспомогательные функции
A>Хочется все это разделить. Но к примеру база должна быть доступна всем "пакетам". Передавать ее каждый раз как аргумент?
A>Добрый день! Есть проект на Go, проект разрастается, и стало неудобно когда все файлы в IDE в одном длинном списке. Хочется разбить на папки.
A>А, насколько я понимаю, это также подразумевает разбивку на пакеты (или нет?).
Да, это подразумевает разбиение на пакеты, и, как следствие, заставляет задуматься о публичных интерфейсах, доступных снаружи, приватной имплементации. Что, в свою очередь, приведёт к тому, что публичные интерфейсы можно будет мокать в тестах. Одни прелести вобщем.
A>Сейчас есть main, содержащий глобальную структуру Application, в которой хранятся всякие общие для всего проекта сущности
A>Объект соединения с БД
A>Объект с разными настройками программы, читаемыми из конфига
A>Объект соединения с удаленным сервисом, предоставляющим данные по API
A>Объект собственного веб-сервера
A>Объект прокси
A>и т.п.
A>Есть группа файлов, которая занимается только работой с БД (выполняет запросы и возвращает массивы с результатами)
A>Есть группа файлов, которая занимается запросами к удаленному серверу с помощью его API и складыванием результатов в БД
A>Есть группа файлов, которая занимается формированием собственного веб-интерфейса; она также использует объект БД
A>Есть файлы, содержащие общие вспомогательные функции
A>Хочется все это разделить. Но к примеру база должна быть доступна всем "пакетам". Передавать ее каждый раз как аргумент?
// В поддиректории svc где-то в иерархии
// пишу без IDE, могут быть ошибки
package users
import (
"context"
"myprject/internal/database"
)
func New(db database.MyDatabase) Svc {
return &svc{db: db}
}
type Svc interface {
UserInfo(ctx context.Context, id string) (*User, error)
}
type svc struct {
db database.MyDatabase
// .....
}
func (s *svc) UserInfo(ctx context.Context, id string) (*User, error) {
u, err := s.db.GetUser(ctx, id)
if err != nil {
return nil, err
}
return s.userFromModel(u)
}
//где-то в поддиректории database:
package database
import (
"context"
"myprject/internal/model"
)
func New(connectionString string, .......) (MyDatabase, error) {
// ......
return &db{/*......*/}, nil
}
type MyDatabase interface {
GetUser() *model.User
}
type db struct {
//
}
// где-то в начале иерархии
package main
import (
"context"
"log"
"myprject/internal/database"
"myprject/internal/services/users"
)
func main() {
db, err := database.New(config.connectionString, ......)
if err != nil {
log.Fatal(err)
}
usersSvc := users.New(db)
u, err := usersSvc.UserInfo(context.TODO(), uid)
if err != nil {
log.Fatal(err)
}
log.Println(u.String())
}Re: Практики разбивки проекта на пакеты
Здравствуйте, a9000, Вы писали:
A>Добрый день! Есть проект на Go, проект разрастается, и стало неудобно когда все файлы в IDE в одном длинном списке. Хочется разбить на папки.
A>А, насколько я понимаю, это также подразумевает разбивку на пакеты (или нет?).
Да, это подразумевает разбиение на пакеты, и, как следствие, заставляет задуматься о публичных интерфейсах, доступных снаружи, приватной имплементации. Что, в свою очередь, приведёт к тому, что публичные интерфейсы можно будет мокать в тестах. Одни прелести вобщем.
A>Сейчас есть main, содержащий глобальную структуру Application, в которой хранятся всякие общие для всего проекта сущности
A>Объект соединения с БД
A>Объект с разными настройками программы, читаемыми из конфига
A>Объект соединения с удаленным сервисом, предоставляющим данные по API
A>Объект собственного веб-сервера
A>Объект прокси
A>и т.п.
A>Есть группа файлов, которая занимается только работой с БД (выполняет запросы и возвращает массивы с результатами)
A>Есть группа файлов, которая занимается запросами к удаленному серверу с помощью его API и складыванием результатов в БД
A>Есть группа файлов, которая занимается формированием собственного веб-интерфейса; она также использует объект БД
A>Есть файлы, содержащие общие вспомогательные функции
A>Хочется все это разделить. Но к примеру база должна быть доступна всем "пакетам". Передавать ее каждый раз как аргумент?
A>Добрый день! Есть проект на Go, проект разрастается, и стало неудобно когда все файлы в IDE в одном длинном списке. Хочется разбить на папки.
A>А, насколько я понимаю, это также подразумевает разбивку на пакеты (или нет?).
Да, это подразумевает разбиение на пакеты, и, как следствие, заставляет задуматься о публичных интерфейсах, доступных снаружи, приватной имплементации. Что, в свою очередь, приведёт к тому, что публичные интерфейсы можно будет мокать в тестах. Одни прелести вобщем.
A>Сейчас есть main, содержащий глобальную структуру Application, в которой хранятся всякие общие для всего проекта сущности
A>Объект соединения с БД
A>Объект с разными настройками программы, читаемыми из конфига
A>Объект соединения с удаленным сервисом, предоставляющим данные по API
A>Объект собственного веб-сервера
A>Объект прокси
A>и т.п.
A>Есть группа файлов, которая занимается только работой с БД (выполняет запросы и возвращает массивы с результатами)
A>Есть группа файлов, которая занимается запросами к удаленному серверу с помощью его API и складыванием результатов в БД
A>Есть группа файлов, которая занимается формированием собственного веб-интерфейса; она также использует объект БД
A>Есть файлы, содержащие общие вспомогательные функции
A>Хочется все это разделить. Но к примеру база должна быть доступна всем "пакетам". Передавать ее каждый раз как аргумент?
// В поддиректории svc где-то в иерархии
// пишу без IDE, могут быть ошибки
package users
import (
"context"
"myprject/internal/database"
)
func New(db database.MyDatabase) Svc {
return &svc{db: db}
}
type Svc interface {
UserInfo(ctx context.Context, id string) (*User, error)
}
type svc struct {
db database.MyDatabase
// .....
}
func (s *svc) UserInfo(ctx context.Context, id string) (*User, error) {
u, err := s.db.GetUser(ctx, id)
if err != nil {
return nil, err
}
return s.userFromModel(u)
}
//где-то в поддиректории database:
package database
import (
"context"
"myprject/internal/model"
)
func New(connectionString string, .......) (MyDatabase, error) {
// ......
return &db{/*......*/}, nil
}
type MyDatabase interface {
GetUser() (*model.User, error)
}
type db struct {
//
}
// где-то в начале иерархии
package main
import (
"context"
"log"
"myprject/internal/database"
"myprject/internal/services/users"
)
func main() {
db, err := database.New(config.connectionString, ......)
if err != nil {
log.Fatal(err)
}
usersSvc := users.New(db)
u, err := usersSvc.UserInfo(context.TODO(), uid)
if err != nil {
log.Fatal(err)
}
log.Println(u.String())
}