Implement a Redux architecture in Syndesis UI
See original GitHub issueIn order to make state management easier in Syndesis UI, while reducing the code boilerplate existing on each component to handle state and digest data back to the data layers on each UI interaction, embracing an architectural pattern such as Redux seems the way to go. This would allow for leaner component and service implementations, less code and a centralized source of truth for all things that impact the overall application state.
After reviewing the entire codebase, I finally managed to come up with a plan for implementing Redux-driven stores in the application, leveraging the excellent @ngrx library (another monorepo, yay!), which has become a de-facto standard in the Angular arena. My major concerns here were, bearing in mind that this is a live application that we still need to grow and maintain in the interim, and that most of those changes tap into architectural calls, how to make everything work while we keep building other features and no feature toggles support is available. The idea would be to build the foundation for Redux in a way that operates in parallel to the rest of the app and then go switching the state implementation for each group of component groups, one group at a time. I figured out the steps required and put them together in an issues list named The Path to a Redux Architecture, (yes, it’s a cheesy name and I’ll burn in hell for the rest of my life because of this).
The Path to a Redux Architecture (15 issues)
- Build our own
HttpClient
wrapper + tests - Strip WebSocket Client implementation out from
store/entity/events.service
to its own service provider + tests - Strip EventSource Client implementation out from
store/entity/events.service
to its own service provider + tests - Implement
EventServiceFactory
wrapping our newWebSocketService
andEventSourceService
and expose it as an Observable events emitter from@syndesis/ui/core
(read below about @syndesis/ui packages) - Implement support for
@ngrx
v4.* plus Side Effect Events modeller and Store Dev Tools. - Port ACTIONS state management to a local store, managed by a set of typed Actions handled by reducers.
- Wire all events emitted by
EventService
and all HTTP calls required by ACTIONS into streams piped to middleware Effects triggering Redux actions. - Hook up all ACTIONS components with data selectors pointing to the Store. Bind UI events to action dispatchers.
- Repeat the above steps with CONNECTIONS
- Repeat the above steps with CONNECTORS
- Repeat the above steps with ENTITIES
- Repeat the above steps with INTEGRATIONS
- Repeat the above steps with OAuth USER GRAPH
- Phase out Restangular in favor of our own
HttpClient
wrapper - Phase out all entities in
src/app/store
in favor of our new implementations for Effects-driven HTTP calls
While this is pretty ideal, problem is that Redux requires A LOT of new files to be created per each entity, and in order to swap references later seamlessly we need a better project layout in regards of filesystem design, folder names and locations, etc. I also need a better tooling to track down errors and debug stuff and this makes a good case to centralize settings ina centralized service so we can strip URLs and stuff out from services and components. So I put together all the steps required and defined a set of packages that will summarize the application architecture, just by embracing the industry conventions for large Angular applications. For the record, this is not a big application, but it will likely become one upon time. Once this architecture is implemented, the different packages will allow for better refactoring operations and will help repurposing our components’ data implementation more easily. The resulting to-do list looks as follows:
The Path to an Angular 5/6 Architecture (12 Issues)
- Upgrade Angular to v5.x and Angular CLI to v1.5.x
- Create
@syndesis/ui/*
alias as a symlink toui/src/app/*
to better manage code refactorings and module reshuffling based on façades (this is done fromtsconfig.json
). - Wrap aplication models, Redux constructs (when available) and abstract service classes into separate contexts exposed from
@syndesis/ui/platform
- Wrap common-use components, directives and pipes in a new SharedModule exposed from
@syndesis/ui/shared
- Wrap application-wide service providers mapped to platform abstract service classes into new CoreModule exposed from
@syndesis/ui/core
- Move connections, customizations, dashboard, integrations, settings (and templates?) to
@syndesis/ui/web
- Remove hardcoded references to services/URLs/ENV variable and expose it from a centralized settings service in exposed from
@syndesis/ui/core
- Implement custom global application error handler wired to Angular’s
ErrorHandler
provider - Wrap vendor libraries in
@syndesis/ui/vendor
abstracting their APIs through our own façade (mostly logging operations). - Introduce
yarn
DEBUG MODE command and log messages in console when triggered. Do not log anything otherwise - Rename files and folders according to Angular’s Official Styleguide
- OPTIONAL - Transition from Angular CLI to Webpack v3 + Rollup w/ AOT compilation support.
Summary
The idea here is to port the application to a proper Angular 5/6 environment first and then implement Redux afterwards, as a follow up EPIC.
Just to summarize, this is the final set of packages proposed:
@syndesis/ui/platform
: Application model types, abstract services, Redux entities (when available), and routing guards.@syndesis/ui/core
: Actual implementations of platform abstract services as injectable providers.@syndesis/ui/shared
: Application shared components, directives and pipes, consumed from all routed modules, lazy loaded or not. Additionally, we will expose here all static functions such as application helpers and TypeScript decorators.@syndesis/ui/web
: All our UI components, grouped by contexts exposing a routed feature module each.@syndesis/ui/vendor
: All our 3rd party libraries, plus our own façade services for them,@syndesis/ui/debug
: Initially a no-op NgModule, but a future home for debug components and directives, and feature toggles.
Issue Analytics
- State:
- Created 6 years ago
- Comments:10 (9 by maintainers)
Top GitHub Comments
Done!
Good thing I moved off of Windows, I think this should be okay 😃
I definitely like the idea behind this one. Would we do this for third-party components or just APIs? The main one I have in mind is the dynamic forms library, we use the API from that. And then there’s ng-patternfly which has components that we use and some API services, would we facade that stuff too?
+1 and I’m actually not a fan of our current logger, I kinda want something that’s as easy to use as
console.log