1 changed files with 60 additions and 0 deletions
@ -0,0 +1,60 @@ |
|||||
|
作为架构审计,我对你代码的 MVC 三层划分进行了审视,结论是:**当前实现没有发生越权行为,分层基本合理,职责边界清晰。** |
||||
|
|
||||
|
下面逐层分析各自的职责与依赖关系,说明为何合规,并指出唯一需注意的模糊点及改进建议。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 1. Model 层(`Article`) |
||||
|
- 纯粹的 POJO,只包含字段、构造器、getter/setter 和 `toString`。 |
||||
|
- **未依赖 View 或 Controller**,完全符合 Model 定位。 |
||||
|
|
||||
|
### 2. View 层(`ConsoleView`) |
||||
|
- 职责明确: |
||||
|
- 从标准输入读取命令(`readLine`) |
||||
|
- 格式化输出信息(成功/错误/普通消息,带 ANSI 颜色) |
||||
|
- 显示 `Article` 列表(`display`) |
||||
|
- `display(List<Article>)` 只是以只读方式遍历并打印 Model 数据,**没有对 Model 做任何修改**。 |
||||
|
- **没有反向引用 Controller 或直接调用业务逻辑**,仅作为展示和输入通道。 |
||||
|
|
||||
|
### 3. Controller 层(`CrawlerController` + 各 `Command` 实现) |
||||
|
- `CrawlerController` 是主控制器,负责: |
||||
|
- 组装依赖(持有 `View`、`Model` 共享引用、命令注册表) |
||||
|
- 解析输入并路由到具体命令 |
||||
|
- 各个 `Command` 实现相当于**控制器内的次级调度单元**(可视为命令模式下的子控制器)。他们: |
||||
|
- 通过构造函数接收 `View` 和(如有必要)`history` 引用 |
||||
|
- 在 `execute` 中接收 `articles` 列表,对其进行业务操作,再调用 `View` 更新界面 |
||||
|
- **所有对 Model 的修改都发生在 Command 中**(虽然 `CrawlCommand` 目前是桩,但设计预期就是在此修改 `articles`)。 |
||||
|
- **View 和 Model 之间没有直接耦合**,一切交互都必须经过 Controller/Command 来发起。 |
||||
|
|
||||
|
**结论:数据流向严格遵循 `Controller → Model → View` 的链式调用,未出现跨层直接访问。** |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 唯一需要明确的“模糊点”——`HistoryCommand` 持有的 `history` 列表 |
||||
|
|
||||
|
`history` 是 `CrawlerController` 中的一个 `List<String>`,记录已执行命令的名称。`HistoryCommand` 通过构造器接收该引用,并在 `execute` 中读取/显示它。 |
||||
|
**这不属于越权**,因为: |
||||
|
- `history` 本质是控制器的内部状态,不是 Model 的一部分。 |
||||
|
- `HistoryCommand` 本身是控制器内部组件,共享这部分状态符合“命令模式”下聚合根(Controller)向命令提供必要上下文的做法。 |
||||
|
- 没有经过 View 去篡改 `history`,该列表也未暴露给 Model。 |
||||
|
|
||||
|
但如果你希望更严格地分离控制流与历史记录,**可以将历史记录职责下沉到独立的 Model(如 `CommandHistory`)**,让 `CrawlerController` 持有它并传给 `HistoryCommand`,这样更加内聚且易测试。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 其他审计发现(非越权问题,但值得注意) |
||||
|
1. **命令硬编码**:`CrawlerController` 构造器中直接注册了所有命令,且额外手动 `put("c", new CrawlCommand(view))`。这带来了两个独立 `CrawlCommand` 实例,虽然功能相同,但 `history` 记录会根据用户输入 `crawl` 或 `c` 分别记录不同名称,目前并无大碍,但若将来命令带状态可能会引起混淆。建议统一别名机制(如在 `Command` 接口增加 `getAliases()`)。 |
||||
|
2. **常量提取**:`HelpCommand.execute` 中写死了命令列表字符串,新增命令时容易忘记同步,可改为从 `CrawlerController` 动态生成帮助信息。 |
||||
|
3. **资源关闭**:`System.exit(0)` 在 `ExitCommand` 中直接终止 JVM,会跳过 finally 块和关闭钩子,在生产场景可改为设置退出标志以允许资源正常释放。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 审计总结 |
||||
|
- **MVC 分层越权行为:无** |
||||
|
- **依赖方向正确**:View ← Controller → Model |
||||
|
- **职责分离清晰**: |
||||
|
- View 只管 I/O 和渲染 |
||||
|
- Model 只管数据结构 |
||||
|
- Controller 负责协调与逻辑 |
||||
|
|
||||
|
你可以放心按当前分层继续扩展功能。如果有新增模块(如数据持久化),注意保持相同的依赖方向即可。 |
||||
Loading…
Reference in new issue