ЧистаВајбАрхитектура (CVA) — Комплетан водич
2025-10-16
Садржај
- Увод и TL;DR
- Речник и терминологија
- Архитектурна мапа и слојеви
- Принципи и правила
- Обрасци
- Шема података и уговори
- Посматрање
- Безбедност
- DevEx и продуктивност
- Референтни скелет (Go)
- Референтни скелет (Symfony/PHP)
- Политике еволуције
- Feature Toggles
- Визуализација
- Чек-листе имплементације
- Лиценцирање и допринос
Део 1: Увод и TL;DR
1.1 Шта је ЧистаВајбАрхитектура (CVA)
ЧистаВајбАрхитектура (ClearVibeArchitecture, CVA) је архитектурни стил за backend системе који комбинује:
- Hexagonal (Ports & Adapters) као основу за изолацију домена
- Догађаје по подразумеваном (Domain Events + Outbox/Inbox, идемпотентност)
- Посматрање по подразумеваном (трасирање, метрике, структурни логови, временска линија)
- Обавезне Feature Toggles као пресечни образац за сву нову функционалност
- Визуализацију тока (web/VR) као продуктни артефакт, а не “пријатну опцију”
Укратко: хексагонална архитектура “са батеријама” — транспарентна, посматрива, еволуционо управљива.
1.2 Које проблеме решава
- Тешко је безбедно мењати систем → feature flags + canary/blue-green
- Не види се “шта се дешава унутра” → otel-трасирање + бизнис метрике + временска линија
- Поуздана интеграција између сервиса → Outbox/Inbox + идемпотентност
- Програмери тону у инфраструктури → чист домен и уговори на границама
- Тешко објаснити бизнису понашање система → визуализатор тока захтева/догађаја
1.3 Циљеви дизајна
- Транспарентност: сваки захтев и догађај се прати кроз све слојеве
- Изолација домена: модел домена је независан од инфраструктуре
- Поуздана испорука: догађаји се публикују трансакционо (Outbox)
- Управљана еволуција: све нове гране иза feature flags са верзионисањем уговора
- Developer Experience: шаблони модула, јединствене CI/CD праксе, тестови као стандард
1.4 Нефункционални захтеви (NFR)
- Поузданост: идемпотентни handler-и, поновна покушаја, дедупликација
- Посматрање: p95-латенција, error rate, saturation као обавезне метрике
- Безбедност: Zero-Trust границе; потписивање порука; ревизија промена flags/уговора
- Перформансе: in-proc кеш одлука flags, back-pressure, I/O батчинг
- Компатибилност: SemVer за API/догађај уговоре, подршка n-1
1.5 TL;DR принципа
- Domain First: домен не зна за ORM/HTTP/broker
- Ports & Adapters: сав I/O кроз интерфејсе (in/out-портови)
- Events First: доменски догађаји су првокласни; публикација преко Outbox
- Observability First: trace_id свуда; бизнис метрике на доменским догађајима
- Feature-Toggles Everywhere: нова функционалност не живи без флага и kill-switch
- Contracts First: API/догађај шеме су верзионисане, проверљиве, компатибилне
- Visualize the Flow: обавезна визуализација путање захтева/gebeurtenaja
1.6 Област примене
- Микросервиси и велики монолити са перспективом декомпозиције
- Високо интеграционо оптерећење, чести релизи, A/B експерименти
- Тимови којима је важна транспарентност и репродукција инцидената
Није најбољи избор ако је систем изузетно једноставан, ретко се мења и не захтева телеметрију/догађаје.
1.7 Критеријуми “спремности за CVA”
- Све нове функције иза feature flags са canary и kill-switch
- Постоје Outbox/Inbox и идемпотентни handler-и
- Укључен OpenTelemetry (трасирање), структурни логови и кључне бизнис метрике
- API/догађај уговори описани шемама, CI-валидирани, води се SemVer
- Постоји web/VR визуализатор тока (минимум — web граф + временска линија)
- Шаблони/генератори модула, линтери, PR чек-листе, основни e2e тестови
1.8 Излазни артефакти
- Архитектурна мапа слојева и портова (in/out), модел домена и границе контекста
- Каталог уговора (OpenAPI/Proto/JSON-Schema/Avro) са SemVer и провера
- Outbox/Inbox библиотека/модул, FeatureGate SDK, otel-интеграција
- SLO dashboard-и и визуализатор тока (минимум — web)
- Шаблони кода (Go, Symfony/PHP), Makefile/Compose, CI-pipeline
Део 2: Речник и терминологија
2.1 Основни ентитети
- Домен — пословна област која описује пословна правила и инваријанте
- Агрегат — корени ентитет који инкапсулира стање и понашање повезаних објеката
- Догађај (Domain Event) — непроменљива чињеница забележена у домену
- Команда (Command) — намера да се промени стање (креирај, ажурирај, обриши)
- Упит (Query) — намера да се добију подаци без споредних ефеката
- Use Case — апликативна логика која повезује команду/упит и домен
2.2 Портови и адаптери
- InPort — интерфејс уласка у систем (API, UI, CLI, тест)
- OutPort — интерфејс изласка из система (база података, message broker, спољни API-ји)
- Adapter — имплементација порта за конкретну инфраструктуру
2.3 Догађајне компоненте
- Outbox — табела/складиште за поуздано публиковање догађаја са трансакцијом
- Inbox — табела/складиште за прием и дедупликацију долазних догађаја
- Saga/Process Manager — координира дуге процесе кроз секвенцу догађаја
2.4 Observability
- Trace ID — јединствени идентификатор захтева, прослеђује се кроз све слојеве
- Span — део трасе који одражава корак (нпр: SQL упит, API позив)
- Metric — мерење (латенција, error rate, бизнис метрика)
- Structured Log — лог у JSON формату са обавезним пољима (timestamp, trace_id, level, message)
2.5 Feature Toggles
- Feature Flag — бинарни прекидач или варијанта параметар који контролише доступност функционалности
- Variant — вредност варијанте флага (A/B/n-тест)
- Kill-Switch — флаг за тренутно искључивање проблематичне функције
- Exposure Event — догађај приказивања функционалности кориснику
2.6 Уговори
- API Contract — формални опис API-ја (OpenAPI, gRPC proto)
- Event Contract — опис структуре догађаја (JSON Schema, Avro)
- Backward Compatibility — нови опис не квари клијенте претходних верзија
- SemVer — верзионисање уговора по правилима Semantic Versioning
Део 3: Архитектурна мапа и слојеви
3.1 Општа шема
┌─────────────────────────────────────────────────────┐
│ Interface Layer │
│ (REST, gRPC, GraphQL, CLI, VR/AR) │
└────────────────┬────────────────────────────────────┘
│ InPorts
┌────────────────▼────────────────────────────────────┐
│ Application Layer │
│ (Commands, Queries, Handlers, Policies) │
└────────────────┬────────────────────────────────────┘
│ Domain Services
┌────────────────▼────────────────────────────────────┐
│ Domain Layer │
│ (Entities, Aggregates, Events, Value Objects) │
└─────────────────────────────────────────────────────┘
▲
│ OutPorts
┌────────────────┴────────────────────────────────────┐
│ Infrastructure Layer │
│ (DB, Brokers, Outbox/Inbox, Observability) │
└─────────────────────────────────────────────────────┘
3.2 Interface Layer
- Улаз: REST, gRPC, GraphQL, CLI, VR/AR-визуализатор
- Задаци: примање команди/упита, конверзија у DTO, прослеђивање у Application
- Карактеристике: логовање, трасирање, authN/authZ
3.3 Application Layer
- Срце апликативне логике: команде, упити, handler-и, политике
- Координација: orchestrators, saga, process managers
- Валидација и DTO мапирање
- Гаранција трансакционих граница: један use case = једна трансакција
- Сви споредни ефекти кроз Outbox
3.4 Domain Layer
- Entities, Aggregates, Value Objects
- Инваријанте, пословна правила, ubiquitous language
- Domain Events као првокласни објекти
- Domain Services — чисте функције без инфраструктуре
- Domain не зна за ORM, HTTP, broker-е
3.5 Infrastructure Layer
- Имплементација портова: репозиторијуми, broker адаптери, спољни API клијенти
- Outbox/Inbox — обавезне компоненте за публиковање/пријем догађаја
- Observability stack: otel-интеграција, логовање, метрике
- Кеширање, file складишта, интеграције са спољним сервисима
Део 4: Принципи и правила
4.1 Чисто језгро (Domain First)
- Домен је изолован од инфраструктуре
- Забрањено коришћење ORM анотација, SQL или SDK-ова спољних сервиса унутар домена
- Инваријанте се проверавају само у домену
4.2 Портови и адаптери
- Све спољне интеракције кроз интерфејсе (Ports)
- Имплементације интерфејса само у Infrastructure (Adapters)
- Application позива OutPorts, Domain не зна ништа о њима
4.3 Догађаји по подразумеваном
- Свака значајна промена се бележи као Domain Event
- Догађаји се публикују кроз Outbox са трансакцијом
- За долазне догађаје користи се Inbox са идемпотентношћу
4.4 Трансакционе границе
- Један use case = једна трансакција
- Споредни ефекти (слање у broker, интеграције) се бележе у Outbox
- Обрада Outbox је асинхрона и може се поновити
4.5 Посматрање по подразумеваном
- Сваки захтев и догађај прати trace_id
- Сви handler-и и адаптери морају да логују и мере свој рад
- Пословни догађаји постају део метрика (нпр: order.created.count)
4.6 Уговори на границама
- API и догађаји описани уговорима (OpenAPI/Proto/Avro/JSON Schema)
- Уговори су верзионисани (SemVer)
- Backward Compatibility је обавезан захтев (подршка n-1 верзија)
4.7 Feature Toggles свуда
- Свака нова функционалност имплементира се само иза флага
- Feature flag је обавезан чак и ако ће функционалност бити увек укључена касније
- Сваки флаг има власника, sunset датум и kill-switch
4.8 Визуализација тока
- Временска линија захтева и догађаја мора бити репродуктивна у визуализатору (web/VR)
- Уска грла се аутоматски истичу (heatmap)
- Визуализација је део производа, а не “додатни алат”
Део 5: Обрасци
5.1 Hexagonal / Ports & Adapters
- Основни архитектурни образац
- Домен је изолован, улазне/излазне зависности као InPorts/OutPorts
- Интеракција са спољним светом кроз адаптере
5.2 CQRS (опционално)
- Раздвајање команди (промене стања) и упита (читање података)
- Користи се тамо где се читање значајно разликује од писања
- Омогућава скалирање читања и писање оптимизованих пројекција
5.3 Outbox / Inbox
- Outbox: трансакционо бележење догађаја са променом у БД
- Inbox: регистрација и дедупликација долазних порука
- Гаранција “exactly-once delivery” на апликативном нивоу
5.4 Saga / Process Manager
- Управљање дуготрајним процесима
- Saga: ланац корака са компензацијама
- Process Manager: реагује на догађаје, координира акције више агрегата/сервиса
5.5 Feature Toggles (обавезно)
- Пресечни образац: свака нова функционалност имплементира се иза флага
- Флагови имају власника, sunset датуме, kill-switch
- Подржани процентуални rollout, сегменти корисника, A/B/n-тестови
- Сваки exposure event (чињеница коришћења флага) се логује
5.6 Observability обрасци
- Distributed Tracing: trace_id кроз све слојеве
- Structured Logging: JSON логови са кључним пољима
- Metrics & SLOs: пословне и техничке метрике; ауто-алерти
- Timeline Visualization: ток догађаја и захтева приказан у web/VR
5.7 Deployment обрасци
- Feature Flags + Canary Release: нова функционалност укључује се постепено
- Blue/Green Deployment: два паралелна окружења, брзо пребацивање
- Rollback по метрикама: аутоматско искључивање функције/верзије при деградацији
Део 6: Шема података и уговори
6.1 API уговори
- Сви јавни API-ји описани у OpenAPI или gRPC Proto
- Уговори пролазе аутоматску CI валидацију
- Строго верзионисање: SemVer (1.2.3)
- Backward compatibility: подршка n-1 верзије клијента
- Уговори објављени у артефакт репозиторијуму
6.2 Уговори догађаја
- Догађаји описани у JSON Schema, Avro или Protobuf
- Сваки догађај има: event_name, version, timestamp, trace_id, payload
- Обавезна поља: id, trace_id, source
- Догађаји пролазе валидацију шеме пре публиковања
6.3 Верзионисање
- Уговори верзионисани независно од сервиса
- Подршка више верзија догађаја: потрошачи могу читати v1 и v2 паралелно
- При прелазу: producer почиње да публикује оба формата (dual write)
6.4 Шеме база података
- Миграције управљају алатима: Liquibase/Flyway/golang-migrate/DoctrineMigrations
- Свака промена у БД прати migration script
- Подржан shadow-write/read за сложене промене шеме
- Све миграције пролазе кроз CI и тест базу
Део 7: Посматрање
7.1 Принцип “Observability by Default”
- Сваки нови сервис или модул у CVA мора имати уграђена средства за посматрање
- Метрике, логови и трасе се не додају “касније” — они су део архитектуре
- Посматрање покрива и техничке и пословне процесе
7.2 Трасе (Distributed Tracing)
- Користи се OpenTelemetry или компатибилан стандард
- Сваки захтев има јединствени trace_id
- Свака операција (SQL, RPC, спољни API) се бележи као span
- Сви догађаји (Domain Events) такође носе trace_id
- Визуализатор (web/VR) гради временску линију на основу trace_id
7.3 Логови (Structured Logging)
- Формат: JSON
- Обавезна поља: timestamp, level, trace_id, service, message
- Логови се пишу у stdout → централизовано складиште (ELK, Loki)
- Грешке и пословни догађаји бележе се подједнако структурирано
7.4 Метрике
- Техничке: латенција (p95/p99), error_rate, saturation, throughput
- Пословне: број наруџбина, конверзија, број одбијања по правилима
- Feature Flags: метрике експозиције (колико корисника види функцију), enable_rate
- Метрике доступне у Prometheus/Grafana или еквивалентима
7.5 Алерти и SLO
- Свака критична метрика има SLO (Service Level Objective)
- Кршења → алерти (PagerDuty, Slack, Email)
- Алерти морају бити акционабилни (јасно шта радити при окидању)
- За feature flags постоји ауто-rollback по SLO
Део 8: Безбедност
8.1 Zero Trust принцип
- Сваки сервис и компонента комуницира са другима само кроз проверене канале
- Нема поверења по подразумеваном чак ни унутар исте мреже
- Ауторизација и аутентификација примењују се на сваком нивоу
8.2 Аутентификација (AuthN)
- Спољни позиви: OAuth2 / OpenID Connect / mTLS
- Интерни позиви: service accounts + mTLS
- Сви захтеви морају садржати корелациони trace_id и токен ауторизације
8.3 Ауторизација (AuthZ)
- RBAC (Role-Based Access Control) или ABAC (Attribute-Based Access Control)
- Провере права извршавају се у Application Layer (policies)
- Feature Flags могу бити ограничени по улогама/сегментима
8.4 Шифровање
- У транзиту: TLS 1.3 (API, broker-и, БД)
- У мировању: шифровање дискова/табела/објеката (AES-256)
- Поверљиви подаци (PII) увек шифровани
8.5 Управљање тајнама
- Тајне се не чувају у коду или променљивима окружења
- Користи се Vault/KMS (HashiCorp Vault, AWS KMS, GCP Secret Manager)
- Приступ тајнама строго по принципу минималних права
Део 9: DevEx и продуктивност
9.1 DevEx-first принцип
- Архитектура треба да буде погодна за програмере
- Шаблони, алати и процеси уграђени у CVA
- Програмери троше минимум времена на рутину и инфраструктуру
9.2 Scaffold и генератори
- Генератори кода за ентитете, команде, догађаје, портове и адаптере
make scaffold module=Order→ креира структуру:- Domain: entity, events, value objects
- Application: commands, handlers, policies
- Infrastructure: repository, adapters
- Гаранција уједначености по пројектима
9.3 Стил кода и линтери
- Јединствени стил кода (Go, PHP, JS/TS)
- Pre-commit hooks: линтери, тестови, security scans
- Обавезна провера trace_id, логова, feature flags
9.4 CI/CD pipeline
CI проверава:
- компилацију/build
- тестове (unit, integration, e2e)
- шеме уговора (API, догађаји)
- миграције БД
- security scan
CD подржава blue/green и canary deployment
Део 10: Референтни скелет (Go)
10.1 Структура пројекта
/clearvibe
/cmd/app/main.go
/internal
/domain/order
entity.go, events.go, service.go
/app/order
commands.go, handler.go, policies.go, ports.go
/infra
/db: order_repo_pg.go
/broker: outbox.go, inbox.go
/http: server.go
/obs: tracing.go, metrics.go, logging.go
/flags: feature_gate.go
10.2 Интерфејси портова
| |
10.3 Команда и Handler
| |
Део 11: Референтни скелет (Symfony/PHP)
11.1 Структура пројекта
src/
Domain/Order/
Entity/Order.php
Event/OrderCreated.php
Application/Order/
Command/CreateOrder.php
Handler/CreateOrderHandler.php
Infrastructure/
Persistence/Doctrine/OrderRepository.php
Messaging/OutboxPublisher.php
FeatureFlags/RedisFeatureGate.php
11.2 Ентитет и догађај
| |
Део 12: Политике еволуције
12.1 Општи принцип
Еволуција је управљана и посматрива. Свака промена пролази кроз feature flags, уговоре и миграције, има власника, plan ризика и путеве за rollback.
12.2 Верзионисање уговора (API/Events)
- SemVer: MAJOR.MINOR.PATCH
- n-1 компатибилност: подржана је барем једна претходна верзија
- Dual write/read: током миграције догађаја, producer публикује vN и vN+1
- CI валидатори компатибилности: забрањују breaking-changes без MAJOR
12.3 Животни циклус функције
- Draft: флаг креиран (disabled), власник, циљ, метрике успеха, sunset датум
- Internal: укључен за dev/stage/own team
- Canary: 1% → 5% → 25% → 50% → 100% (детерминистичко bucketing)
- General Availability: флаг подразумевано on
- Sunset: флаг и мртав код уклоњени, уговори стабилизовани
12.4 Стратегије релиза
- Blue/Green: два окружења, пребацивање саобраћаја
- Canary: инкрементални rollout са ауто-чуварима по SLO
- Dark Launch: код deployan, функција искључена флагом до активације
Део 13: Feature Toggles
13.1 Принцип
Feature Toggles су обавезан и пресечни образац у CVA. Свака нова функционалност имплементира се само иза флага.
13.2 Типови флагова
- Boolean: on/off
- Percentage: проценат саобраћаја (canary rollout)
- Segment: укључивање по атрибутима (држава, ниво, улога)
- Multivariant: више варијанти за A/B/n-тестове
13.3 Складиштење
- Складиште: Postgres (извор истине) + Redis (кеш, pub/sub)
- Шема: flags(id, key, type, rules, default, owner, version, ttl, updated_at)
- Верзионисање: SemVer за уговоре флагова, подршка n-1
13.4 Метрике и посматрање
- Exposure догађаји: flag.exposed, flag.variant
- Метрике: exposure_count, enable_rate, error_rate
- Dashboard-и: поређење варијанти (A/B), корелација са пословним метрикама
- Trace_id: увек прослеђен у exposure догађајима
Део 14: Визуализација
14.1 Принцип
У CVA, визуализација није “пријатна опција” већ обавезан слој. Систем мора показати ток података и догађаја.
14.2 Временска линија
- Приказује кораке захтева хронолошки
- Примери: HTTP захтев примљен, Handler извршен, Догађај забележен у Outbox
- Сваки корак одговара span-у (трасе)
- Временска линија доступна у web интерфејсу и експортована у VR
14.3 Flow граф
- Чворови: сервиси, агрегати, адаптери
- Ивице: позиви и догађаји
- Подршка филтера: по trace_id, типу догађаја, грешкама/латенцији
14.4 Heatmap
- Истицање уских грла
- Метрике латенције/error_rate визуализоване у боји
- Црвено = проблем, зелено = нормално
14.5 VR визуализација
- Ток података може се “видети” у 3D (VR/AR)
- Чворови-сервиси у простору, линије-догађаји се крећу у реалном времену
- Корисно за обуку нових чланова тима и анализу инцидената
Део 15: Чек-листе имплементације
15.1 Општа чек-листа пројекта
- Дефинисани Bounded Contexts и Ubiquitous Language
- Формирана архитектурна мапа слојева
- Именован власник архитектуре
15.2 Domain Layer
- Сви ентитети описани као Entity/ValueObject
- Инваријанте фиксиране и покривене тестовима
- Domain Events дефинисани и документовани
- Нема зависности на ORM/HTTP/broker-е
15.3 Application Layer
- Свака акција формирана као Command/Query
- Handler за сваку команду
- Policies валидирају приступ и правила
- Трансакционе границе дефинисане
- Feature Flags интегрисани у use cases
15.4 Infrastructure Layer
- Репозиторијуми имплементирани преко OutPorts
- Повезан Outbox (обавезно)
- Повезан Inbox за долазне догађаје
- Конфигурисани адаптери за API/broker-е/БД
- Повезане observability компоненте
15.5 Feature Toggles
- Сваки нови код има feature flag
- Флагови имају власника, sunset датуме, kill-switch
- Exposure догађаји логују се
- Rollout сценарији документовани
- Тестови укључују on/off сценарије
15.6 Observability
- Сви захтеви/догађаји имају trace_id
- Логови структурирани (JSON)
- Метрике: техничке + пословне
- Dashboard-и и алерти конфигурисани
- Визуализатор повезан (временска линија/flow граф/VR)
Део 16: Лиценцирање и допринос
16.1 Лиценца
- Open Source (MIT/Apache 2.0): архитектурни принципи, чек-листе и шаблони слободно доступни
- Може се користити у комерцијалним и некомерцијалним пројектима без ограничења
- Једини захтев — одржавање помена ауторства и лиценце
16.2 Водич за допринос
Pull Request прихваћен само ако:
- Написан ADR за промене
- Прошао CI (уговори, тестови, миграције)
- Ажуриране чек-листе и документација
- Додати примери (Go/PHP SDK, миграције, метрике)
16.3 Управљање
- Maintainers: одговорни за review и издавање нових верзија CVA манифеста
- Contributors: доносе идеје, исправке грешака, додатке чек-листама и обрасцима
- Одлуке се доносе кроз RFC/ADR
Кључне разлике CVA
Од класичне Hexagonal/Clean архитектуре
Иста основа (DDD + Hexagonal), али CVA чини обавезним ствари које се обично “дорађују касније”:
- Догађаји (Domain Events + Outbox/Inbox)
- Посматрање (трасирање/метрике/структурни логови)
- Feature flags са пресечном интеграцијом
- Управљана еволуција (canary/blue-green, верзионисање уговора)
- Визуализација тока (web/VR)
Идеја: систем је иницијално “жив, транспарентан и безбедно еволуира”.
Где је CVA бољи
- Транспарентност и отклањање грешака — уграђен OpenTelemetry, пословне метрике, временска линија
- Поуздана интеграција — Outbox/Inbox, идемпотентност, поновни покушаји по подразумеваном
- Безбедни релизи — feature flags, canary rollout, kill-switch, ауто-rollback
- Управљана еволуција — SemVer, dual write/read, shadow write/read
- Developer Experience — шаблони, чек-листе, стандарди
- Разумевање за бизнис — визуализација тока, пословне метрике из кутије
- Безбедност по подразумеваном — RBAC, ревизија, zero-trust
Када изабрати CVA
- Микросервиси и интеграционо тешки системи
- Чести релизи и експерименти (growth/product тимови)
- Високи захтеви за поузданост испоруке догађаја
- Потреба за “транспарентно” објашњавање технологије бизнису
- Планирано скалирање тима и пројекта
Када остати на класичној Hexagonal
- Једноставан сервис/монолит без активне еволуције
- Мали тим, нема ресурса за телеметрију и feature flags
- Скоро нема спољних интеграција, меки SLA
Закључак
ЧистаВајбАрхитектура није само скуп образаца, већ холистички приступ изградњи модерних backend система.
CVA чини систем:
- Транспарентним — сваки захтев видљив од почетка до краја
- Поузданим — догађаји испоручени са гаранцијама
- Безбедним — промене контролисане и могу се вратити
- Разумљивим — визуализација помаже свима: од програмера до бизниса
Ово је “Hexagonal на стероидима” — скупље на почетку, али вишеструко се исплаћује на средњим и великим системима.