代码组织
代码组织
Rails 风格
在文档,示例项目和许多教程中找到的默认组织有时称为 Rails 风格。Rails 是 Ruby 编程语言的流行 Web 框架,具有定义明确的目录布局,其中每种文件类型都分组在对应的目录中。例如,您会在模型目录中找到每个模型,在控制器目录中找到每个控制器,等等。
Rails 风格方法的优势很明显。首先,这是最简单的教学策略。如果您的工作是壮大加入团队的开发人员,请说明可以在 container 目录中找到容器组件。容器调度一个动作,可以在动作目录中找到该动作,依此类推。简单性减少了新开发人员的入职时间。
这种方法的成本是可伸缩性。在示例的最末端,截止到 2017 年 4 月,Facebook 由 30,000 多个组件组成。您能想象所有这些组件都位于组件或容器目录中吗?公平地说,如果没有 Facebook 投入巨额的工具投入,那么无论应用程序架构多么周到,都很难在大型应用程序中找到任何东西。
Domain 风格
您会发现域样式或基于功能的组织的多种变体。通常,这些变体的每个目标都是将相关代码分组在一起。假设您的应用程序具有订阅工作流程以注册新客户。例如,基于域的模式不是将相关的组件,动作和缩减器分布在多个目录中,而是主张将它们全部放在一个订阅目录中。
单个容器组件可以从多个域中提取状态以在结帐过程中呈现页面的情况并不少见。例如,如果用户将商品添加到他们的购物车中,则您可能会在产品页面,标题和购物车侧栏中看到更新。您可以采取哪些措施来更好地组织共享数据?
一种可选的域样式模式是将容器和组件保留在 Rails 样式模式中,但按域组织动作和简化器。下图重构了最后一个示例以演示此模式。通过这种更改,容器不再生活在一个特定的域中,而从其他几个域中导入状态。
最大的胜利就是能够在一处找到更多您需要的东西。例如,如果您已购买了用于将新功能添加到 Header 组件的票证,则可能希望在 Header 目录中找到所需的所有内容。每当您需要添加新功能时,只需添加一个目录。如果您选择将组件和容器与域目录分开,则这种解耦可以很好地提醒您使这些组件可重复使用。
您会发现此方法仍然需要权衡取舍,并且您应该了解,并非每个应用程序都有一个答案。这种模式的潜在弱点之一是围绕构成域或特征的内容缺乏确定性或清晰度。有时您会争论一些新功能是属于现有目录还是应该创建一个新功能。在开发人员的工作中添加更多这样的决策和开销是不理想的。
Ducks
在您问之前,“Dcuks”这个名字是 Redux 最后一个音节的即兴之处。Dcuks 模式的目的是使领域式组织更进一步。该模式的作者埃里克·拉斯穆森(Erik Rasmussen)观察到,同一组导入重复出现在整个应用程序中。除了将功能的常量,Action 和 Reducer 保存在一个目录中之外,为什么不将它们全部保存在一个文件中?
const FETCH_STARTED = "parsnip/tasks/FETCH_STARTED";
const FETCH_SUCCEEDED = "parsnip/tasks/FETCH_SUCCEEDED";
const FETCH_FAILED = "parsnip/tasks/FETCH_FAILED";
const CREATE_SUCCEEDED = "parsnip/tasks/CREATE_SUCCEEDED";
const FILTER = "parsnip/tasks/FILTER";
const initialState = {
tasks: [],
isLoading: false,
error: null,
searchTerm: "",
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case FETCH_STARTED:
return { ...state, isLoading: true };
case FETCH_SUCCEEDED:
return { ...state, tasks: action.payload.tasks, isLoading: false };
case FETCH_FAILED:
return { ...state, isLoading: false, error: action.payload.error };
case CREATE_SUCCEEDED:
return { ...state, tasks: state.tasks.concat(action.payload.task) };
case FILTER:
return { ...state, searchTerm: action.searchTerm };
default:
return state;
}
}
export function fetchTasks() {
return { type: FETCH_STARTED };
}
export function createTask({ title, description, status = "Unstarted" }) {
return (dispatch) => {
api.createTask({ title, description, status }).then((resp) => {
dispatch(createTaskSucceeded(resp.data));
});
};
}
export function createTaskSucceeded(task) {
return { type: CREATE_SUCCEEDED, payload: { task } };
}
export function filterTasks(searchTerm) {
return { type: FILTER, searchTerm };
}
Dcuks 模式在可伸缩性方面是一个巨大的胜利,其原因有很多,其中最重要的一点是有意义地减少了所创建文件的数量。多个域样式模式为每个常量,化简器和动作创建者生成一个文件,而 Dcuks 模式则生成一个文件。
您会发现需要权衡的优势。其中最明显的是,根据定义,这些模块文件将比它们替换的任何单个文件大。较大的文件与 JavaScript 朝着更高的模块化趋势相反,这无疑会受到某些开发人员的关注。