読者です 読者をやめる 読者になる 読者になる

Summary of the layered architecture for karen-irc’s client-side

architecture

This is the summary overview of karen-irc's client-side architecture. The history of my thought are wrote in the issue. I may talk about more details in somewhere.

And I deployed the simplified design of this to my main work code. Perhaps I or my co-worker may write about it in someplace.

CAUTION: karen-irc's code is refactoring still now, so there are some legacy part

Basic Principle

  • I wrote the summary as slide
  • Use many terminologies from Flux, because we started this design from the thought of Flux pattern.
    • But Flux pattern is just a design pattern, not an architecture. There are some missing peaces.

Key Components

The concept tree will be:

  • adapter
    • includes driver & adapter roles
  • domain
    • includes domain models (entity, value object, and etc)
  • intent
    • includes action & dispatcher roles.
      • this 'action' naming is derived from Flux, we may rename this role.
    • I feel this role is very similar to WPF (Windows Presentation Foundation)'s command. Should we change this name to command?
  • context
    • This is a unit of view content area and has a lifecycle itself. This terminology is inspired by Android's Activity.
    • only provides lifecycle.
  • output
    • viewmodel
      • This role has a responsibility of the state of view.
      • This transforms a data to other data structure which is more suitable for a corresponded view.
      • This name may confuse me with MVVM pattern's View Model... I thought it provides very similarity role, but I don't have concrete confidence...
    • view
      • This role has a responsibility of the representation of view.
      • We mixed composite this layer with using React.js and raw dom manipulation.
  • application
    • This is a base layer of an application.
    • This layer provides a base routing context, managing dependencies, initializing flow, and etc.
    • This layer should be rewritten to fulfill the requirement for each application.

Data Flow

A data flow should be represented as Rx's Observable, except a part of perf sensitive code.

Some of My Thought

Intent

Flux's ActionCreator and Dispatcher makes some misleading. By naming & grouping, we feel they are separated materials. But It's mistake. ActionCreator provides an abstraction to call Dispatcher without pass an event type enum. Thus ActionCreator is a function which is named as materialized intent. ActionCreator and Dispatcher should be tightly coupled.

Context

context is a unit of a view content area and has a lifecycle itself. An active context ensure that you have an ownership of the view content area under the given mount point, so you can render something to the mount point if you are called. This terminology is inspired by Android's Activity and Windows' UWP app lifecycle. This interface is here:

trait ViewContext {
  fn on_activated(&self, mountpoint: Element);
  fn on_destroy(&self, mountpoint: Element);

  fn on_resume(&self, mountpoint: Element);
  fn on_suspend(&self, mountpoint: Element);
} 

Each lifecycle method should return a Promise/Future if we need implement moving in/out transition. karen-irc does not need it yet. Therefore the return value is still simplified.

This only provide a lifecycle of view context, does not manage any dependencies. Dependencies are managed by an application layer for each application as most suitable style. So this does not provide any magic system like other react.js meta frameworks because their choice should be freely from our architecture. Each contexts are separated. Theoretically, you can use a raw dom manipulation in the context A, use React.js in context the B, and use Angular2 in the context C.

This does not correspond to a html:body element. context is a unit of view content area which is divided-and-ruled.

Adapter for RPC

I write my roughly thought about RPC adapter.

We can express this layer by some functions and some classes, as same as the relationship of between action and dispatcher in intent.

The key points is that We can materialize a RPC call concretely with giving a named function returning a Promise/Future/Observable

All RPC call is composited from:

  • protocol
  • address of endpoint
  • type definition of input/output

These 3 key components are very similar to "ABC" of WCF (Windows Communication Foundation) which is called as "Indigo" in Longhorn era.

And RPC client/service should manage connections sessions dispatched by self. Then they can create a returned response value for each requests. This means that: you can get a result as a Promise/Future/Observable even if the request is one way to a service, and you can transform a event stream by flatmapping the result value.

Why don't split out a generic framework part as a new package?

I don't like it :)

I agree it would be valuable thing to split out a generic data structure to reuse it. Because almost data structure represents data structure and there are not any architectural design. They are usually "non-political" code.

As a generalization, it will be very harder than imagine that to create a generic framework. I doubt the value to create a generic framework which can be used for all situations from this project. Even if we achieve to create some framework which looks like “generic”, it would need to spend a more times to make it a truly “generic. It comes to nothing!

The most important thing is reuse the philosophy. It is meaningless to reuse the code base to other applications which has significantly different requirements.