A tiny Clojure framework for managing the lifecycle and dependencies of stateful software components.
Component is a Clojure library that provides a framework for managing the lifecycle and dependencies of stateful software components. It solves the problem of coordinating startup/shutdown sequences and dependency relationships in applications with runtime resources like database connections, HTTP pools, or caches. By making these relationships explicit, it enables cleaner architecture and easier testing.
Clojure developers building medium to large applications with multiple stateful resources that need coordinated lifecycle management. It's particularly useful for teams adopting REPL-driven development workflows.
Developers choose Component because it provides a simple, idiomatic Clojure pattern for dependency injection without sacrificing immutability or functional principles. Its explicit dependency graph eliminates hidden global state and makes application structure more maintainable.
Managed lifecycle of stateful objects in Clojure
Open-Awesome is built by the community, for the community. Submit a project, suggest an awesome list, or help improve the catalog on GitHub.
Components implement start/stop protocols for clean initialization and cleanup, as shown in the Database example where connections are opened and closed in order.
Dependencies are specified using 'using' functions, ensuring proper startup order and eliminating hidden global state, which makes the system more maintainable and testable.
Integrates seamlessly with tools like tools.namespace for hot code reloading, enabling rapid iteration without JVM restarts, as highlighted in the development workflow section.
Supports easy swapping of mock or stub components for testing, avoiding race conditions associated with time-dependent constructs like with-redefs, making unit tests more reliable.
The framework assumes all state is passed as arguments, making adoption painful for codebases relying on global references, as admitted in the 'Disadvantages' section.
Must manually specify all dependency relationships; the system cannot auto-discover them, adding upfront design work and potential for errors in large applications.
The resulting system object is a large, nested map with duplication, which is cumbersome to inspect visually and debug, as noted in the README.