System¶
Ранее мы познакомились к компонентами. Я упоминал, что компоненты объединяются в систему. Подробнее о системах.
Мы уже сделали достаточно, чтобы собрать полноценную систему и провести демонстрацию.
(defn build []
(component/system-map
:binding-map (->BindingMap nil)
:seed (component/using (->Seed nil) [:binding-map])
:handler (component/using (handler/build) [:binding-map])
:jetty (component/using (jetty/build {:port 4445}) [:binding-map :handler])))
Наша система состоит из 4-х компонентов:
binding-map
- содержит реализации абстракций вместе с их состояниемseed
- компонент без состояния, который добавляет в хранилище начальные данныеhandler
- компонент без состояния, оборачивающий ring handlerjetty
- веб-сервер
Эта система используется для разработки, но вы можете развертывать ее на тестовых серверах, для демонстрации промежуточного результата. Эта система использует фейки, хранящие данные в памяти, поэтому вы можете легко поднимать тестовое окружение на каждую фичу.
Файлы для разработки хранятся в директории web/dev .
(ns system
(:require
[com.stuartsierra.component :as component]
[publicator.web.components.jetty :as jetty]
[publicator.web.components.handler :as handler]
[publicator.use-cases.test.factories :as factories]
[publicator.use-cases.test.fakes.storage :as storage]
[publicator.use-cases.test.fakes.user-queries :as user-q]
[publicator.use-cases.test.fakes.post-queries :as post-q]
[publicator.domain.test.fakes.id-generator :as id-generator]
[publicator.domain.test.fakes.password-hasher :as password-hasher]))
(defrecord BindingMap [val]
component/Lifecycle
(start [this]
(let [db (storage/build-db)]
(assoc this :val
(merge (storage/binding-map db)
(user-q/binding-map db)
(post-q/binding-map db)
(id-generator/binding-map)
(password-hasher/binding-map)))))
(stop [this] this))
(defrecord Seed [binding-map]
component/Lifecycle
(start [this]
(with-bindings (:val binding-map)
(let [post1 (factories/create-post)
user1 (factories/create-user {:login "user1"
:password "12345678"
:full-name "User1"
:posts-ids #{(:id post1)}})
post2 (factories/create-post)
user2 (factories/create-user {:login "user2"
:password "12345678"
:full-name "User2"
:posts-ids #{(:id post2)}})]))
this)
(stop [this]
this))
(defn build []
(component/system-map
:binding-map (->BindingMap nil)
:seed (component/using (->Seed nil)
[:binding-map])
:handler (component/using (handler/build)
[:binding-map])
:jetty (component/using (jetty/build {:port 4445})
[:binding-map :handler])))
(ns user
(:require
[com.stuartsierra.component :as component]
[system]))
(def system (system/build))
(defn start []
(alter-var-root #'system component/start))
(defn stop []
(alter-var-root #'system component/stop))
Таким образом набрав в repl (start)
вы запустите приложение.