Визначаємо вартість декоратора в Golang
Привіт, мене звати Ярослав, займаюсь розробкою сервісу для збереження активів у криптовалюті в компанії ITAdviser, розробляємо на Go. У цій статті розглянемо декоратор, його вартість і чи варто використовувати його в розробці нових сервісів.
Коротко про мене
Кілька років тому почав цікавитись Go, подарував другу на день народження книжку «The Go Programming Language», сам грався задачами з LeetCode, облишив, через півроку продовжив, вийшов професійний курс від «Техносфери», передивився і цього було достатньо, щоб почати працювати як Junior Go.
Go зацікавив тестами та бенчмарками з коробки, можливістю розбиратись в коді стандартних бібліотек, які теж написані на Go. А ще в Києві хороше Go ком’юніті. В деяких мовах рішення певних задач лаконічніше та красивіше, ніж в інших. Уже вкотре зустрічаю теми, де автори описують, як бачать ідеальну мову програмування, а інші ж створюють такі мови, прикладу Ruby.
Що таке декоратор
Так, в Go зручно реалізувати патерн декоратор. Це відомий патерн, вже описаний в книжці Gang of Four «Design Patterns: Elements of Reusable Object-Oriented Software» (та початківцям краще починати з «Head First Design Patterns»).
Декоратор зручний, коли треба розширити функціональність без змін компонентів. Мені він нагадує матрьошку, якій треба розмалювати іншим кольором руки. Беремо матрьошку, обертаємо її в прозору плівку, розмальовуємо руки, плівка та малюнок і будуть декоратором. Шрек приводив у приклад цибулю.
В основному проекті ми використовуємо декорацію для запису в журнал взаємодії через API клієнти та для синхронізації.
Дуже просто покрити тестами основну логіку, а всі додаткові обгортки винести в декорацію. Але перед тим як так структурувати частину проекта через декоратори, треба довести, що його вартість мала.
Реалізація
В Go реалізувати декоратор простіше, ніж через ООП. Візьмемо штучний приклад класу на PHP з двома методами. Один треба змінити, а інший залишити, як є:
interface GeneratorInterface
{
public function increment(int $step): int;
public function stats(): Stats;
}
class GeneratorIncrementDecorator implements GeneratorInterface
{
private $source;
private $coefficient;
public function __construct(GeneratorInterface $source, int $coefficient)
{
$this->source = $source;
$this->coefficient = $coefficient;
}
public function increment(int $step): int
{
// decorated
return $this->source->increment($step * $this->coefficient);
}
public function stats(): Stats
{
// as is
return $this->source->stats();
}
}
class Stats{}
А тепер на Go:
type Generator interface {
Increment(step int) int
Stats() Stats
}
type GeneratorIncrementDecorator struct {
Generator
coefficient int
}
func NewGeneratorIncrementDecorator(source Generator, coefficient int) Generator {
return GeneratorIncrementDecorator{
Generator: source,
coefficient: coefficient,
}
}
func (d GeneratorIncrementDecorator) Increment(step int) int {
return d.Generator.Increment(step * d.coefficient)
}
type Stats struct{}
В Go декоруємо тільки потрібний метод, а метод Stats вбудовується. В офіційній документацій це називається Embedding. В PHP, як і в Java та C#, треба буде обгортати усі методи.
А тепер приклад, щоб визначити вартість. Візьмемо структуру з однаковими функціями.
type (
source interface {
increment(int) int
wrap(int) int
proxy(int) int
same(int) int
}
handler struct {
}
)
func (handler) increment(s int) int {
return s + 1
}
func (handler) wrap(s int) int {
return s + 1
}
func (handler) proxy(s int) int {
return s + 1
}
func (handler) same(s int) int {
return s + 1
}
Продекоруємо її різними методами:
type (
decorator struct {
source
}
)
func newDecorator(source source) source {
return decorator
}
func (d decorator) increment(s int) int {
return d.source.increment(s) + 1
}
func (d decorator) wrap(s int) int {
return d.source.wrap(s + 1)
}
func (d decorator) proxy(s int) int {
return d.source.proxy(s)
}
// embedding
//func (d decorator) same(s int) int {
// return d.source.same(s)
//}
Додамо benchmark на кожну функцію інтерфейсу та допоміжну тестову функцію, щоб декорувати N разів:
import "testing"
const N = 127
func BenchmarkSource(b *testing.B) {
handler := handler{}
for i := 0; i
Похожие статьи:
Ресторатор Клопотенко шукає ІТ-компанію, яка створить програму-генератор для шкільного менюУкраїнський шеф-кухар і ресторатор Євген Клопотенко шукає IT-компанію, яка могла би реалізувати проєкт із автоматизації шкільного...
Huawei Honor 5X Plus появился в базе данных GFXBench?В базе данных тестирования производительности смартфонов GFXBench появились сведения о модели Huawei ABC-UL00, которая не соотносится ни с...
26 марта, Киев — Курс «React.js: от основ до масштабируемых SPA»Курс React.js: от основ до масштабируемых SPA, будет полезен как уже работающим, так и начинающим специалистам, которые хотят освоить...
Захищаючи Україну, загинув ІТ-спеціаліст із GlobalLogic Андрій Задорожний. Йому було 35 роківНа Великдень, 20 квітня, загинув Андрій Задорожний — офіцер роти безпілотних систем 128-ї окремої гірсько-штурмової бригади. Йому...
DevOps дайджест #21: куда девопсу пойти осеньюВ выпуске: анонсы конференций, гайды, тулза месяца и новый Github Load Balancer.
На этого докладчика лучше сходить: будет, о чем...
Последние материалы Чому національна LLM досі не стартувала і що таке Дія City 2.0. Перше інтерв’ю з новим керівником Мінцифри «Податку на Google» стало більше — скільки сплатили світові компанії в Україні Революція Siri від Apple | Зарплати менеджерів | Preply — новий «єдиноріг» — DOU News #234 Зарплати менеджерів в IT: як виглядає ринок — зима 2026 Шукати роботу можна буде через Дію. У застосунок інтегрують систему «Обрій»
Анализ сайта
Яндекс директ
Аудит сайта
Оптимизация
Seo новости
Продвижение ( Статьи )
Новости IT
Советуем почитать
{source}