概要
JSでDDD & Clean architecture & Fluxを考えてみた。
(注意: 筆者は上記3つを正しく理解していない可能性がある)
用語
ユーザー
いわゆるユーザー。
ユーザーを識別するためのidとユーザー独自のタイムラインを持つ。
タイムライン
コメントの配列。
コメント
bodyと呼ばれる任意の文字列を持つ。
ユースケース
ユーザーのタイムラインを取得する。
実装
// Entity
interface Comment {
body(): String;
}
interface Timeline {
comments(): Array<Comment>;
}
interface User {
id();
// 非同期にtimelineを取得
timeline(onFetched: (Timeline) => void);
}
interface UserRepository {
// 同期的に取得できると想定
findById(userId): User;
}
// Use Case
class FetchUserTimelineUseCase {
constructor(userRepository) {
this.userRepository_ = userRepository;
}
execute(userId, onFetched: (Timeline) => void) {
this.userRepository_.findById(userId).timeline(onFetched);
}
}
// Action Creator
class UserActionCreator {
constructor(dispatcher, userRepository) {
this.dispatcher_ = dispatcher;
this.userRepository_ = userRepository;
}
fetchTimeline(userId) {
this.dispatcher_.dispatch({ type: ActionType.START_FETCH_TIMELINE });
new FetchUserTimelineUseCase(this.userRepository_).execute(userId, (timeline) => {
this.dispatcher_.dispatch({ type: ActionType.FINISH_FETCH_TIMELINE, userId, timeline });
});
}
}
// Store
class UserStore extends ReduceStore {
constructore(dispatcher) {
super(dispatcher);
}
getInitialState() {
return Immutable.OrderedMap();
}
reduce(state, action) {
switch (action.type) {
case ActionType.START_FETCH_TIMELINE:
return state.set('loading', true);
case ActionType.FINISH_FETCH_TIMELINE:
const userId = action.userId;
const timeline = {
comments: action.timeline.comments().map((c) => { body: c.body() })
};
return state.set('loading', false).set('timeline', timeline).set('userId', userId);
}
}