diff --git a/doc/~$模板:软件需求规格说明书.docx b/doc/~$模板:软件需求规格说明书.docx deleted file mode 100644 index 5e61389..0000000 Binary files a/doc/~$模板:软件需求规格说明书.docx and /dev/null differ diff --git a/doc/”基于多 Agent 协同的军事 Python 代码合规性检查系统“软件设计规格说明书 .doc b/doc/”基于多 Agent 协同的军事 Python 代码合规性检查系统“软件设计规格说明书 .doc new file mode 100644 index 0000000..97bace1 Binary files /dev/null and b/doc/”基于多 Agent 协同的军事 Python 代码合规性检查系统“软件设计规格说明书 .doc differ diff --git a/软件用例设计文档.md b/软件用例设计文档.md new file mode 100644 index 0000000..28e5181 --- /dev/null +++ b/软件用例设计文档.md @@ -0,0 +1,310 @@ +# 3.3 用例设计 + +## 3.3.1 "执行代码检测"用例实现的设计方案 + +"执行代码检测"功能的实现主要是通过"ToolManager"对象提供的服务,调用多个代码质量检测工具(Bandit、Flake8、Pylint)对用户上传的Python代码文件进行分析,从而生成详细的检测报告。具体实现过程见图3.3.1 所描述的用例实现顺序图。 + +**图3.3.1 "执行代码检测"用例实现的顺序图** + +```plantuml +@startuml +title 图3.3.1 "执行代码检测"用例实现的顺序图 + +actor 用户 +participant "<>\nDashboardView" as LoginUI +participant "<>\nBackendService" as LoginManager +participant "<>\nFileStorageManager" as UserLibrary +participant "<>\nDetectionTask" as DetectionTask +participant "<>\nToolManager" as ToolManager +participant "<>\nCodeAnalysisEngine" as ExtTool +participant "<>\nReportGenerator" as ReportGenerator + +用户 -> LoginUI: 1. 输入账号和密码 +用户 -> LoginUI: 2. 选择代码文件并上传 +用户 -> LoginUI: 3. 选择检测工具 +用户 -> LoginUI: 4. 点击"开始检查"按钮 + +LoginUI -> LoginManager: 5. handleCodeCheck(file, tools) +activate LoginManager + +LoginManager -> LoginManager: 6. 验证请求参数 +LoginManager -> UserLibrary: 7. saveUploadedFile(file) +activate UserLibrary +UserLibrary -> UserLibrary: 8. isFileValid(file) +UserLibrary --> LoginManager: 9. VerificationResult (文件路径) +deactivate UserLibrary + +LoginManager -> DetectionTask: 10. new DetectionTask(filePath, fileName, tools) +activate DetectionTask +DetectionTask -> DetectionTask: 11. 初始化任务属性\n(生成taskId, 设置status=Pending) +DetectionTask --> LoginManager: 12. 返回任务对象 +deactivate DetectionTask + +LoginManager -> DetectionTask: 13. start() +activate DetectionTask +DetectionTask -> DetectionTask: 14. 设置status=Running\n记录startTime +deactivate DetectionTask + +loop 遍历每个选中的工具 + LoginManager -> ToolManager: 15. runTool(toolName, filePath) + activate ToolManager + ToolManager -> ToolManager: 16. generateCommand(toolName, filePath) + ToolManager -> ExtTool: 17. executeCommand(command) + activate ExtTool + ExtTool -> ExtTool: 18. 分析代码文件 + ExtTool --> ToolManager: 19. 返回原始输出 (stdout) + deactivate ExtTool + ToolManager -> ToolManager: 20. parseToolOutput(toolName, stdout) + ToolManager --> LoginManager: 21. 返回结构化结果 + deactivate ToolManager + + LoginManager -> DetectionTask: 22. addResult(toolName, result) + activate DetectionTask + DetectionTask -> DetectionTask: 23. 添加结果到results数组 + deactivate DetectionTask +end + +LoginManager -> ReportGenerator: 24. generateReport(results, filename) +activate ReportGenerator +ReportGenerator -> ReportGenerator: 25. formatToolResult(toolResult) +ReportGenerator --> LoginManager: 26. 返回报告内容 +deactivate ReportGenerator + +LoginManager -> UserLibrary: 27. saveReport(reportContent, filename) +activate UserLibrary +UserLibrary -> UserLibrary: 28. 保存报告到输出目录 +UserLibrary --> LoginManager: 29. 返回报告路径 +deactivate UserLibrary + +LoginManager -> DetectionTask: 30. complete() +activate DetectionTask +DetectionTask -> DetectionTask: 31. 设置status=Completed\n记录endTime +DetectionTask --> LoginManager: 32. 返回任务结果 +deactivate DetectionTask + +LoginManager --> LoginUI: 33. CheckResult (检测结果和报告路径) +deactivate LoginManager + +LoginUI -> LoginUI: 34. 更新界面显示\n(进度、结果列表) +LoginUI -> 用户: 35. 展示检测结果 + +@enduml +``` + +首先,用户通过边界类"DashboardView"对象选择并上传Python代码文件,选择要使用的检测工具(Bandit、Flake8、Pylint),随后该对象向控制类"BackendService"对象发消息"handleCodeCheck(file, tools)",以请求执行代码检测。接收到消息后,"BackendService"对象首先调用实体类"FileStorageManager"对象的方法"saveUploadedFile(file)"以保存上传的文件到临时目录,"FileStorageManager"对象通过自身内部的方法"isFileValid(file)"来判断文件是否有效,并将验证的结果"VerificationResult"返回给"BackendService"对象。 + +"BackendService"对象收到文件保存成功后,创建实体类"DetectionTask"对象以封装检测任务信息,并调用其"start()"方法将任务状态设置为"Running"。随后,"BackendService"对象遍历用户选中的检测工具,向控制类"ToolManager"对象发消息"runTool(toolName, filePath)"以执行代码检测。"ToolManager"对象通过自身内部的方法"generateCommand(toolName, filePath)"生成命令行命令,并向实体类"CodeAnalysisEngine"对象发消息"executeCommand(command)"以执行代码分析。"CodeAnalysisEngine"对象接收到消息后,根据命令类型调用对应的检测工具(Bandit、Flake8或Pylint)执行代码分析。检测工具完成分析后,"CodeAnalysisEngine"对象返回原始输出结果给"ToolManager"对象,"ToolManager"对象通过"parseToolOutput(toolName, stdout)"方法解析原始输出,将其转换为结构化的检测结果,并返回给"BackendService"对象。 + +"BackendService"对象将每个工具的检测结果添加到"DetectionTask"对象的results数组中。所有工具执行完成后,"BackendService"对象向控制类"ReportGenerator"对象发消息"generateReport(results, filename)"以生成检测报告。"ReportGenerator"对象通过自身内部的方法"formatToolResult(toolResult)"格式化每个工具的检测结果,生成Markdown格式的报告内容,并返回给"BackendService"对象。 + +随后,"BackendService"对象调用"FileStorageManager"对象的方法"saveReport(reportContent, filename)"保存报告到输出目录,并调用"DetectionTask"对象的"complete()"方法将任务状态设置为"Completed"。"BackendService"对象将包含检测结果和报告路径的"CheckResult"返回给"DashboardView"对象,"DashboardView"对象更新界面显示检测结果列表和统计信息,用户可以在界面上查看详细的检测结果。一旦检测完成,系统将检测结果以列表形式展示给用户,用户可以通过筛选功能查看不同类型的问题(错误、警告、信息)。 + +## 3.3.2 "创建项目"用例实现的设计方案 + +"创建项目"功能的实现主要是通过"BackendService"对象提供的服务,创建新的代码检查项目记录,并根据项目来源类型(GitHub、Gitee或文件上传)保存相应的项目信息,从而使用户能够对不同类型的代码进行分类管理和检查。具体实现过程见图3.3.2 所描述的用例实现顺序图。 + +**图3.3.2 "创建项目"用例实现的顺序图** + +```plantuml +@startuml +title 图3.3.2 "创建项目"用例实现的顺序图 + +actor 用户 +participant "<>\nProjectManagementView" as SettingUI +participant "<>\nBackendService" as SettingManager +participant "<>\nFileStorageManager" as FileStorage +participant "<>\nProject" as Project + +用户 -> SettingUI: 1. 点击"新建项目"按钮 +SettingUI -> SettingUI: 2. 显示新建项目对话框 +用户 -> SettingUI: 3. 输入项目信息\n(名称、描述) +用户 -> SettingUI: 4. 选择项目来源类型 + +alt 项目来源为GitHub或Gitee + 用户 -> SettingUI: 5. 输入Git URL + SettingUI -> SettingManager: 6. startSetting() + activate SettingManager + SettingManager -> SettingManager: 7. 验证项目信息 + SettingManager -> Project: 8. new Project(name, description, sourceType, sourceUrl) + activate Project + Project -> Project: 9. 初始化项目属性\n(生成projectId, 设置创建时间) + Project --> SettingManager: 10. 返回项目对象 + deactivate Project + SettingManager -> SettingManager: 11. 保存项目记录 + SettingManager --> SettingUI: 12. CreateProjectResult (项目ID和基本信息) + deactivate SettingManager +else 项目来源为文件上传 + 用户 -> SettingUI: 7. 选择文件或文件夹 + SettingUI -> SettingManager: 8. startSetting() + activate SettingManager + SettingManager -> SettingManager: 9. 验证项目信息 + SettingManager -> Project: 10. new Project(name, description, sourceType) + activate Project + Project -> Project: 11. 初始化项目属性\n(生成projectId, 设置创建时间) + Project --> SettingManager: 12. 返回项目对象 + deactivate Project + SettingManager -> SettingManager: 13. 保存项目记录 + SettingManager --> SettingUI: 14. CreateProjectResult (项目ID) + deactivate SettingManager + + SettingUI -> SettingManager: 15. uploadProjectFiles(projectId, files) + activate SettingManager + loop 遍历每个文件 + SettingManager -> FileStorage: 16. saveUploadedFile(file, projectPath) + activate FileStorage + FileStorage -> FileStorage: 17. 保存文件到项目目录 + FileStorage --> SettingManager: 18. 返回文件路径 + deactivate FileStorage + end + SettingManager --> SettingUI: 19. UploadResult (上传文件数量) + deactivate SettingManager +endif + +SettingUI -> SettingUI: 20. 刷新项目列表 +SettingUI -> 用户: 21. 显示新创建的项目 + +@enduml +``` + +边界类"ProjectManagementView"对象基于用户输入的项目信息(如项目名称、描述、来源类型等),向控制类"BackendService"对象发消息"startSetting()"以进行项目创建的初始化工作;"BackendService"对象接收到消息后,首先验证用户输入的项目信息是否有效,随后创建实体类"Project"对象并初始化项目属性(生成projectId、设置创建时间等),至此项目创建的初始化工作已经完成。 + +如果项目来源类型为GitHub或Gitee,用户需要输入Git仓库的URL,"BackendService"对象将Git URL信息保存到"Project"对象中,并返回创建结果给"ProjectManagementView"对象。如果项目来源类型为文件上传,用户需要选择本地文件或文件夹,"BackendService"对象创建项目记录后,"ProjectManagementView"对象通过消息"uploadProjectFiles(projectId, files)"将文件上传请求发送给"BackendService"对象,随后"BackendService"对象将文件上传请求转发给实体类"FileStorageManager"对象,请求保存文件到项目的专用目录。"FileStorageManager"对象接收到文件后,将文件保存到对应项目的目录中,并返回文件保存结果。 + +一旦项目创建任务完成,"BackendService"对象将通过消息"CreateProjectResult"将项目创建结果信息反馈给边界类"ProjectManagementView"对象,"ProjectManagementView"对象刷新项目列表并显示新创建的项目,用户可以在项目管理界面中看到新创建的项目。 + +## 3.3.3 "查看检测结果"用例实现的设计方案 + +根据用户选择要查看的检测记录,"ProjectDetailView"对象将向"BackendService"对象请求加载检测结果详情,"BackendService"对象从"DetectionTask"对象中获取存储的检测结果,并通过"ReportGenerator"对象格式化结果数据,最终将详细的检测结果展示给用户,具体实现过程见图3.3.3 所描述的用例实现顺序图。 + +**图3.3.3 "查看检测结果"用例实现的顺序图** + +```plantuml +@startuml +title 图3.3.3 "查看检测结果"用例实现的顺序图 + +actor 用户 +participant "<>\nProjectDetailView" as SettingUI +participant "<>\nBackendService" as SettingManager +participant "<>\nDetectionTask" as DetectionTask +participant "<>\nReportGenerator" as ReportGenerator +participant "<>\nFileStorageManager" as FileStorage + +用户 -> SettingUI: 1. 进入检测结果查看界面 +SettingUI -> SettingManager: 2. getCheckHistory(projectId) +activate SettingManager +SettingManager -> SettingManager: 3. 查询检测历史记录 +SettingManager --> SettingUI: 4. CheckHistoryList (检测历史列表) +deactivate SettingManager + +SettingUI -> SettingUI: 5. 显示检测历史列表 +用户 -> SettingUI: 6. 选择要查看的检测记录 + +SettingUI -> SettingManager: 7. getCheckResult(projectId, checkId) +activate SettingManager +SettingManager -> DetectionTask: 8. getResults(checkId) +activate DetectionTask +DetectionTask -> DetectionTask: 9. 查询检测结果数据 +DetectionTask --> SettingManager: 10. 返回检测结果 +deactivate DetectionTask + +SettingManager -> ReportGenerator: 11. formatResults(results) +activate ReportGenerator +ReportGenerator -> ReportGenerator: 12. 格式化结果数据\n(按类型分类、排序) +ReportGenerator --> SettingManager: 13. 返回格式化后的结果 +deactivate ReportGenerator + +SettingManager --> SettingUI: 14. CheckResult (问题列表、统计信息) +deactivate SettingManager + +SettingUI -> SettingUI: 15. 显示检测结果摘要\n(错误数、警告数等) +SettingUI -> SettingUI: 16. 显示问题列表 + +用户 -> SettingUI: 17. 选择筛选类型\n(全部/错误/警告/信息) +SettingUI -> SettingUI: 18. 根据类型筛选问题列表 + +用户 -> SettingUI: 19. 点击问题查看详情 +SettingUI -> SettingUI: 20. 显示问题详情和修复建议 + +用户 -> SettingUI: 21. 点击下载报告按钮 +SettingUI -> SettingManager: 22. downloadReport(reportId) +activate SettingManager +SettingManager -> FileStorage: 23. readFile(reportPath) +activate FileStorage +FileStorage -> FileStorage: 24. 读取报告文件内容 +FileStorage --> SettingManager: 25. 返回报告内容 +deactivate FileStorage +SettingManager --> SettingUI: 26. 返回报告文件 +deactivate SettingManager + +SettingUI -> 用户: 27. 触发文件下载 + +@enduml +``` + +边界类"ProjectDetailView"对象首先向控制类"BackendService"对象发消息"getCheckHistory(projectId)"以获取项目的检测历史记录列表,"BackendService"对象查询数据库中存储的检测任务记录,并将检测历史列表"CheckHistoryList"返回给"ProjectDetailView"对象,"ProjectDetailView"对象在界面上显示检测历史列表供用户选择。 + +用户选择要查看的检测记录后,"ProjectDetailView"对象向"BackendService"对象发消息"getCheckResult(projectId, checkId)"以请求加载详细的检测结果。"BackendService"对象接收到消息后,向实体类"DetectionTask"对象发消息"getResults(checkId)"以获取存储的检测结果数据。"DetectionTask"对象从其results属性中查询对应的检测结果,并将结果返回给"BackendService"对象。 + +"BackendService"对象接收到检测结果后,向控制类"ReportGenerator"对象发消息"formatResults(results)"以格式化结果数据。"ReportGenerator"对象通过自身内部的方法对检测结果进行格式化处理,包括按问题类型(错误、警告、信息)进行分类、按严重程度排序等,并将格式化后的结果返回给"BackendService"对象。 + +"BackendService"对象将包含问题列表和统计信息的"CheckResult"返回给"ProjectDetailView"对象,"ProjectDetailView"对象在界面上显示检测结果摘要(错误数、警告数、信息数等)和详细的问题列表。用户可以通过筛选功能选择查看特定类型的问题,"ProjectDetailView"对象根据用户选择的筛选类型过滤问题列表并更新显示。 + +如果用户需要下载检测报告,"ProjectDetailView"对象向"BackendService"对象发消息"downloadReport(reportId)"以请求下载报告文件。"BackendService"对象调用实体类"FileStorageManager"对象的方法"readFile(reportPath)"读取报告文件内容,并将报告文件返回给"ProjectDetailView"对象,"ProjectDetailView"对象触发浏览器下载文件,用户可以将检测报告保存到本地。 + +## 3.3.4 "上传规则文件"用例实现的设计方案 + +"上传规则文件"功能的实现主要是通过"BackendService"对象提供的服务,接收用户上传的规则配置文件,验证文件格式的有效性,并将文件保存到规则集目录中,从而使用户能够自定义代码检测规则以满足不同项目或团队的要求。具体实现过程见图3.3.4 所描述的用例实现顺序图。 + +**图3.3.4 "上传规则文件"用例实现的顺序图** + +```plantuml +@startuml +title 图3.3.4 "上传规则文件"用例实现的顺序图 + +actor 用户 +participant "<>\nRuleSetManagementView" as SettingUI +participant "<>\nBackendService" as SettingManager +participant "<>\nFileStorageManager" as FileStorage +participant "<>\nRuleSet" as RuleSet + +用户 -> SettingUI: 1. 点击"上传规则文件"按钮 +SettingUI -> SettingUI: 2. 打开文件选择对话框 +用户 -> SettingUI: 3. 选择规则文件\n(如setup.cfg) +用户 -> SettingUI: 4. 选择规则类型\n(Pylint/Flake8) + +SettingUI -> SettingManager: 5. uploadRuleFile(file, ruleType) +activate SettingManager +SettingManager -> SettingManager: 6. 验证文件格式 +SettingManager -> SettingManager: 7. isFileValid(file, ruleType) + +alt 文件格式有效 + SettingManager -> FileStorage: 8. saveRuleFile(file, ruleType) + activate FileStorage + FileStorage -> FileStorage: 9. 保存文件到规则集目录 + FileStorage --> SettingManager: 10. 返回文件路径 + deactivate FileStorage + + SettingManager -> RuleSet: 11. new RuleSet(fileName, filePath, ruleType) + activate RuleSet + RuleSet -> RuleSet: 12. 初始化规则文件属性\n(生成ruleId, 设置更新时间) + RuleSet --> SettingManager: 13. 返回规则对象 + deactivate RuleSet + + SettingManager -> SettingManager: 14. 保存规则文件元数据 + SettingManager --> SettingUI: 15. UploadRuleResult (规则ID和基本信息) +else 文件格式无效 + SettingManager --> SettingUI: 16. UploadRuleResult (错误信息) +endif +deactivate SettingManager + +SettingUI -> SettingUI: 17. 刷新规则文件列表 +SettingUI -> 用户: 18. 显示新上传的规则文件 + +@enduml +``` + +边界类"RuleSetManagementView"对象基于用户选择的规则文件和规则类型(如Pylint的.pylintrc文件或Flake8的setup.cfg文件),向控制类"BackendService"对象发消息"uploadRuleFile(file, ruleType)"以请求上传规则文件;"BackendService"对象接收到消息后,首先通过自身内部的方法"isFileValid(file, ruleType)"验证文件格式是否符合对应的规则类型要求,如果文件格式有效,则向实体类"FileStorageManager"对象发消息"saveRuleFile(file, ruleType)"以保存规则文件到规则集目录。 + +"FileStorageManager"对象接收到消息后,将规则文件保存到对应的规则集目录中(如Pylint规则文件保存到pylint_rules目录,Flake8规则文件保存到flake8_rules目录),并返回文件保存路径给"BackendService"对象。"BackendService"对象收到文件保存成功后,创建实体类"RuleSet"对象以封装规则文件信息,调用其构造函数"new RuleSet(fileName, filePath, ruleType)"初始化规则文件属性(生成ruleId、记录文件大小、设置更新时间等),并将规则文件元数据保存到系统中。 + +一旦规则文件上传任务完成,"BackendService"对象将通过消息"UploadRuleResult"将上传结果信息反馈给边界类"RuleSetManagementView"对象,如果上传成功则返回规则ID和基本信息,如果上传失败则返回错误信息。"RuleSetManagementView"对象刷新规则文件列表并显示新上传的规则文件,用户可以在规则集管理界面中看到新上传的规则文件,并可以对其进行编辑、下载或删除操作。上传的规则文件可以在后续的代码检测中使用,"ToolManager"对象在执行检测时会自动读取并使用相应的规则配置文件。 diff --git a/软件类设计文档.md b/软件类设计文档.md new file mode 100644 index 0000000..5ee1822 --- /dev/null +++ b/软件类设计文档.md @@ -0,0 +1,525 @@ +# 3.4 类设计 + +## (1)精化类间的关系 + +在分析类图中有一组分析类,BackendService、ToolManager、ReportGenerator、FileStorageManager、DetectionTask。在软件设计阶段,这些类仍然有意义,将成为软件设计模型中的关键设计类。针对这些设计类间关系的精化设计描述如下,具体见图3.4.1。 + +BackendService 类负责协调整个代码检测流程。在具体实现时,BackendService 类通过调用 ToolManager 执行代码检测,通过 FileStorageManager 管理文件存储,通过 ReportGenerator 生成检测报告,因而 BackendService 类与 ToolManager、FileStorageManager、ReportGenerator 类之间的语义关系表现为一般的关联关系。DetectionTask 是封装检测任务信息的实体类,因而 BackendService 与 DetectionTask 之间的语义关系表现为组合关系。 + +BackendService 类需要创建和管理一个或者多个 DetectionTask 类对象,每个 DetectionTask 类对象只能交由一个 BackendService 类对象进行处理,因而 BackendService 类与 DetectionTask 类之间存在一对多的关系。 + +**图3.4.1 精化核心业务类间以及它们与"BackendService"类间的关系** + +```plantuml +@startuml +title 图3.4.1 精化核心业务类间以及它们与"BackendService"类间的关系 + +class BackendService { + - app: Express + - PORT: Number + - upload: Multer + - TOOL_CONFIG: Object + + constructor() + + start() + + handleHealthCheck(req, res) + + handleCodeCheck(req, res) +} + +class ToolManager { + - toolConfig: Object + - results: Array + + constructor() + + runTool(toolName, filePath): Promise + + parseToolOutput(toolName, stdout): Object +} + +class ReportGenerator { + - reportTemplate: String + - outputDir: String + + constructor(outputDir) + + generateReport(results, filename): String + + saveReport(reportContent, filename): String +} + +class FileStorageManager { + - tempDir: String + - outputDir: String + - uploadConfig: Object + + constructor(tempDir, outputDir) + + saveUploadedFile(file): String + + readFile(filePath): String + + saveReport(reportContent, filename): void +} + +class DetectionTask { + - taskId: String + - status: String + - filePath: String + - fileName: String + - selectedTools: Array + - results: Array + + constructor(filePath, fileName, selectedTools) + + start(): void + + addResult(toolName, result): void + + complete(): void + + fail(error): void +} + +BackendService "1" -- "1" ToolManager : 关联 (调用) +BackendService "1" -- "1" FileStorageManager : 关联 (调用) +BackendService "1" -- "1" ReportGenerator : 关联 (调用) +BackendService "1" -- "*" DetectionTask : 组合 (创建和管理) + +@enduml +``` + +## (2)精化用户界面类间的关系 + +根据§3.2 节的用户界面设计,本系统在Web端包含 DashboardView、ProjectManagementView、ProjectDetailView 和 RuleSetManagementView 等一组界面以支持用户的操作。显然这些用户界面类之间具有如图3.4.2 所描述的关联关系。 + +**图3.4.2 精化用户界面类间的关系** + +```plantuml +@startuml +title 图3.4.2 精化用户界面类间的关系 + +class DashboardView { + + displayStats() + + handleFileUpload() + + startCheck() + + stopCheck() +} + +class ProjectManagementView { + + displayProjectList() + + createProject() + + searchProject() + + deleteProject() +} + +class ProjectDetailView { + + displayProjectInfo() + + displayCheckHistory() + + viewCodeFile() + + viewCheckResult() +} + +class RuleSetManagementView { + + uploadRuleFile() + + displayRuleList() + + editRule() + + deleteRule() +} + +DashboardView --> ProjectManagementView : 导航到 +DashboardView --> RuleSetManagementView : 导航到 +ProjectManagementView --> ProjectDetailView : 查看详情 +ProjectDetailView --> DashboardView : 返回 + +@enduml +``` + +## (3)精化关键设计类间的关系 + +根据§3.3 节的用例设计,"执行代码检测"用例是本系统的核心用例。该用例涉及 BackendService、FileStorageManager、ToolManager、ReportGenerator 和 DetectionTask 五个关键设计类。根据§3.3 所描述的顺序图中五个类间的交互, BackendService 类与 FileStorageManager 类之间具有直接关联关系,BackendService 类与 ToolManager 类之间具有直接关联关系,ToolManager 类与 ReportGenerator 类之间是依赖关系,这些类的关系精化如图3.4.3所示。 + +**图3.4.3 精化"执行代码检测"用例中类间的关系** + +```plantuml +@startuml +title 图3.4.3 精化"执行代码检测"用例中类间的关系 + +class BackendService { + + handleCodeCheck(req, res) +} + +class FileStorageManager { + + saveUploadedFile(file): String + + saveReport(reportContent, filename): void +} + +class ToolManager { + + runTool(toolName, filePath): Promise + + parseToolOutput(toolName, stdout): Object +} + +class ReportGenerator { + + generateReport(results, filename): String +} + +class DetectionTask { + + constructor(filePath, fileName, selectedTools) + + start(): void + + addResult(toolName, result): void + + complete(): void +} + +BackendService "1" -- "1" FileStorageManager : 关联 (保存文件) +BackendService "1" -- "1" ToolManager : 关联 (调度工具) +BackendService "1" -- "1" DetectionTask : 关联 (创建/管理任务) +ToolManager ..> ReportGenerator : 依赖 (生成报告) +FileStorageManager ..> DetectionTask : 依赖 (存储任务相关文件) + +@enduml +``` + +## (4)精化DetectionTask 类属性的设计 + +DetectionTask 类属性的精化设计描述如下。 + +1)有六项基本属性:任务ID"`taskId`"、文件路径"`filePath`"、文件名"`fileName`"、选中的工具"`selectedTools`"、任务状态"`status`"和检测结果"`results`"。它们的类型分别为`String`、`String`、`String`、`Array`、`String`和`Array`。 + +2)这些属性是任务的核心标识和状态信息,对外部其他类不可见,这六项属性的可见范围为"`private`"。 + +3)`taskId` 在构造时自动生成,`status` 初始值为`"Pending"`,`results` 初始值为空数组,其他属性在构造时传入。 + +## (5)精化DashboardView 类属性的设计 + +在用户界面设计中,有"DashboardView"界面用于支持用户上传代码文件并启动代码检测,具体见图3.2.1 所示。"DashboardView"界面类属性的精化设计描述如下。 + +-有一组属性分别对应于界面中的静态元素、用户输入元素和命令界面元素,具体包括:"logo"为界面标识图标,其类型为静态元素,如图标;"uploadArea"为文件上传区域,其类型为用户输入元素,如文件选择框;"fileInput"为用户选择的文件,其类型为用户输入元素,如文件输入框;"startCheckBtn"旨在开始代码检测,其类型为命令界面元素,如按钮;"stopCheckBtn"旨在停止代码检测,其类型为命令界面元素,如按钮;"progressContainer"旨在显示检测进度,其类型为静态元素,如进度条;"resultsSection"旨在显示检测结果,其类型为静态元素,如结果列表。 + +-这些属性对外部其他类均不可见,它们的可见范围设置为"`private`"。 + +-"startCheckBtn"和"stopCheckBtn"二个属性的初始值不为空,需要将其预先设置为相应界面的按钮元素。 + +## (6)精化ToolManager 类属性的设计 + +ToolManager 是"代码检测服务"子系统中的一个重要控制类。根据该子系统中用例实现的交互图,ToolManager 类至少有二项基本属性:"toolConfig"以表示工具配置映射表、"results"以表示工具执行结果集合。具体的,ToolManager 类属性的精化设计描述如下。 + +-`private Object toolConfig`,表示工具配置映射表,包含每个工具的命令、参数生成函数和结果解析器 + +-`private Array results`,表示工具执行结果集合,用于临时存储各工具的原始输出 + +-这些属性对外部其他类均不可见,它们的可见范围设置为"`private`"。 + +-`toolConfig` 在构造时根据预设配置初始化,`results` 初始值为空数组。 + +## (7)精化"代码检测服务"子系统中部分类方法的设计 + +根据控制类 BackendService 的职责,它有一个 `public` 方法 `handleCodeCheck(req, res)` 用于处理代码检测请求。此外,为了在代码检测之前检查上传文件的合法性,它有一个 `private` 方法 `validateFile(req)`,专门用于判断上传的文件是否满足相关的规范和要求。 + +该方法的主要功能是要依据用户上传的文件和选中的工具判断是否可以启动检测任务,为此可以设计一个 `private` 的方法 `validateRequest(req)`,专门用于判断请求的合法性。 + +ToolManager 实体类负责管理系统中的代码检测工具,它有一系列的 `public` 方法以实现对工具的管理,包括 `runTool(toolName, filePath)` 方法实现执行指定的代码检测工具,`parseToolOutput(toolName, stdout)` 方法实现解析工具的原始输出,`getAvailableTools()` 方法实现获取所有可用的工具列表,`validateTool(toolName)` 方法以判断工具名称是否有效。此外,ToolManager 类还具有创建方法 `constructor()` 和初始化方法 `initToolConfig()` 以便建立工具配置。 + +**图3.4.4 精化设计BackendService、ToolManager、ReportGenerator 等类的方法** + +```plantuml +@startuml +title 图3.4.4 精化设计BackendService、ToolManager、ReportGenerator 等类的方法 + +class BackendService { + - app: Express + - PORT: Number = 3000 + - upload: Multer + - TOOL_CONFIG: Object + + constructor() + - configureCORS() + - configureUpload() + - setupRoutes() + + start() + + handleHealthCheck(req, res) + + handleCodeCheck(req, res) + - validateFile(req): Boolean + - validateRequest(req): Boolean +} + +class ToolManager { + - toolConfig: Object + - results: Array + + constructor() + + initToolConfig() + + runTool(toolName, filePath): Promise + + parseToolOutput(toolName, stdout): Object + + getAvailableTools(): Array + + validateTool(toolName): Boolean +} + +class ReportGenerator { + - reportTemplate: String + - outputDir: String + + constructor(outputDir) + + generateReport(results, filename): String + + saveReport(reportContent, filename): String + - formatToolResult(toolResult): String + - ensureOutputDir() +} + +class FileStorageManager { + - tempDir: String + - outputDir: String + - uploadConfig: Object + + constructor(tempDir, outputDir) + + saveUploadedFile(file): String + + readFile(filePath): String + + saveReport(reportContent, filename): void + + deleteTempFile(filePath): void + - ensureDirectory(dirPath) +} + +@enduml +``` + +## (8)精化"代码检测服务"子系统(CodeCheckService)中部分类方法的设计 + +**图3.4.5 "CodeCheckService"子系统的设计类图** + +图3.4.5 描述了"代码检测服务"子系统中实现代码检测的一组对象类。根据该子系统的用例实现交互图,可以对子系统中 ToolManager 和 DetectionTask 两个类的方法进行精化设计。首先,针对 DetectionTask 类的六个属性,分别设计相关的方法以设置和获取六个属性的取值;其次,针对 ToolManager 类的方法,详细设计其参数信息。 + +-`public void setTaskId(String taskId)`,设置任务的唯一标识符 + +-`public void setStatus(String status)`,设置任务的当前状态 + +-`public void setFilePath(String filePath)`,设置待检测文件的路径 + +-`public void setFileName(String fileName)`,设置原始文件名 + +-`public void setSelectedTools(Array selectedTools)`,设置选中的检测工具列表 + +-`public void addResult(String toolName, Object result)`,添加工具的检测结果 + +-`public String getTaskId()`,获取任务的唯一标识符 + +-`public String getStatus()`,获取任务的当前状态 + +-`public String getFilePath()`,获取待检测文件的路径 + +-`public String getFileName()`,获取原始文件名 + +-`public Array getSelectedTools()`,获取选中的检测工具列表 + +-`public Array getResults()`,获取所有检测结果 + +-ToolManager 类的方法 `runTool(toolName, filePath)` 精化如下: `public Promise runTool(String toolName, String filePath, Object config)` + +```plantuml +@startuml +title 图3.4.5 "CodeCheckService"子系统的设计类图 + +class DetectionTask { + - taskId: String + - status: String + - filePath: String + - fileName: String + - selectedTools: Array + - results: Array + + constructor(filePath, fileName, selectedTools) + + setTaskId(taskId) + + setStatus(status) + + setFilePath(filePath) + + setFileName(fileName) + + setSelectedTools(selectedTools) + + addResult(toolName, result) + + getTaskId(): String + + getStatus(): String + + getFilePath(): String + + getFileName(): String + + getSelectedTools(): Array + + getResults(): Array +} + +class ToolManager { + - toolConfig: Object + - results: Array + + constructor() + + runTool(toolName, filePath, config): Promise + + parseToolOutput(toolName, stdout): Object +} + +DetectionTask --> ToolManager : 调用 + +@enduml +``` + +## (9)精化BackendService 类中"handleCodeCheck()"方法的实现算法设计 + +图3.4.6 用UML 活动图描述了 BackendService 类中 `handleCodeCheck()` 方法的精化设计,它定义了该方法的接口 `public handleCodeCheck(req, res)`,描述了其内部的实现算法:首先判断上传文件和检测参数二个输入的参数是否为空,如果为空则返回错误;如果不为空,则调用 FileStorageManager 对象的方法 `saveUploadedFile()` 以保存上传的文件,如果保存成功则创建 DetectionTask 对象并调用 ToolManager 对象的方法 `runTool()` 以执行代码检测,如果检测成功则调用 ReportGenerator 对象的方法 `generateReport()` 以生成检测报告,否则返回检测失败。 + +**图3.4.6 精化BackendService 类中handleCodeCheck()方法的详细设计** + +```plantuml +@startuml +title 图3.4.6 精化BackendService 类中handleCodeCheck()方法的详细设计 + +start +:接收HTTP请求 (req, res); +:获取上传文件和检测参数; +if (文件为空?) then (是) + :返回错误响应 (400 Bad Request); + stop +else (否) + if (检测参数为空?) then (是) + :返回错误响应 (400 Bad Request); + stop + else (否) + :调用FileStorageManager.saveUploadedFile()保存文件; + if (文件保存成功?) then (是) + :创建DetectionTask对象; + :调用DetectionTask.start()启动任务; + :调用ToolManager.runTool()执行检测; + if (检测执行成功?) then (是) + :收集所有工具的检测结果; + :调用ReportGenerator.generateReport()生成报告; + :调用FileStorageManager.saveReport()保存报告; + :更新DetectionTask状态为Completed; + :返回成功响应 (报告路径); + else (否) + :更新DetectionTask状态为Failed; + :返回失败响应 (错误信息); + endif + else (否) + :返回文件保存失败响应; + endif + endif +endif +stop + +@enduml +``` + +## (10)精化ToolManager 类中"runTool()"方法的实现算法设计 + +图3.4.7用UML 的活动图描述了 ToolManager 类中 `runTool()` 方法的详细设计,它定义了该方法的接口 `public Promise runTool(toolName, filePath)`,描述了其内部的实现算法:首先根据工具名称获取工具配置,如果找不到配置则返回错误;如果找到配置,则根据工具类型和文件路径生成命令行命令,接着执行外部命令行工具进行检测,在命令执行过程中捕获标准输出和标准错误,并在命令执行完成后解析原始输出,如果解析成功则返回结构化结果,否则返回解析错误。 + +**图3.4.7 精化ToolManager 类中runTool()方法的详细设计** + +```plantuml +@startuml +title 图3.4.7 精化ToolManager 类中runTool()方法的详细设计 + +start +:接收工具名称 (toolName) 和文件路径 (filePath); +:根据toolName获取工具配置 (toolConfig); +if (找到工具配置?) then (否) + :返回错误 ("不支持的工具"); + stop +else (是) + :根据工具配置生成命令行命令; + if (工具是flake8?) then (是) + :创建本地文件副本; + :使用本地文件路径; + endif + :执行外部命令行工具; + :捕获标准输出和标准错误; + if (命令执行成功?) then (是) + :调用parseToolOutput()解析原始输出; + if (解析成功?) then (是) + :构造结构化结果对象; + :返回检测结果; + else (否) + :返回解析失败错误; + endif + else (否) + :返回工具执行失败错误; + endif +endif +stop + +@enduml +``` + +## (11)构造类的状态图和活动图 + +### 图3.4.8 DetectionTask 类对象的状态图 + +如果一个类的对象具有较为复杂的状态,在其生命周期中需要针对外部和内部事件实施一系列的活动以变迁其状态,那么可以考虑构造和绘制类的状态图。DetectionTask 类对象具有较为复杂的状态,它创建时将处于空闲状态"Pending",一旦开始执行代码检测时将处于运行状态"Running"以执行检测工具,如果所有工具执行成功则进入到完成状态"Completed",如果检测失败则进入到失败状态"Failed",图3.4.8 描述了 DetectionTask 类对象的状态图。 + +**图3.4.8 DetectionTask 类对象的状态图** + +```plantuml +@startuml +title 图3.4.8 DetectionTask 类对象的状态图 + +state "Pending\n(待处理)" as Pending +state "Running\n(运行中)" as Running +state "Completed\n(已完成)" as Completed +state "Failed\n(失败)" as Failed + +[*] --> Pending : 创建任务 +Pending --> Running : start()\n开始检测 +Running --> Completed : complete()\n所有工具执行成功 +Running --> Failed : fail()\n检测失败 +Completed --> [*] : 任务归档 +Failed --> [*] : 任务归档 + +@enduml +``` + +### 图3.4.9 用户代码检测流程的活动图 + +如果某个类在实现其职责过程中需要执行一系列的方法、与其他的对象进行诸多的交互,那么可以考虑构造和绘制针对该类某些职责的活动图。图3.4.9用UML 的活动图及泳道机制描述了 DashboardView、BackendService、FileStorageManager、ToolManager、ReportGenerator 和 DetectionTask 六个类对象之间如何通过交互和协作来实现用户代码检测的功能。 + +**图3.4.9 用户代码检测流程的活动图** + +```plantuml +@startuml +title 图3.4.9 用户代码检测流程的活动图 + +|用户| +start +:上传代码文件; +:选择检测工具; +:点击"开始检查"按钮; + +|DashboardView| +:收集文件和参数; +:发送检测请求 (HTTP POST); + +|BackendService| +:接收HTTP请求; +:调用FileStorageManager.saveUploadedFile(); + +|FileStorageManager| +:保存文件到本地临时目录; +:返回文件路径; + +|BackendService| +:创建DetectionTask对象; +:设置任务状态为Pending; +:调用DetectionTask.start(); +:更新任务状态为Running; + +|BackendService| +:遍历选中的工具; +while (还有工具未执行?) is (是) + |ToolManager| + :调用ToolManager.runTool(); + :执行外部命令行工具; + :解析工具输出; + :返回结构化结果; + |BackendService| + :调用DetectionTask.addResult(); + :添加工具检测结果; +endwhile (否) + +|BackendService| +:调用ReportGenerator.generateReport(); + +|ReportGenerator| +:生成Markdown格式报告; +:返回报告内容; + +|BackendService| +:调用FileStorageManager.saveReport(); + +|FileStorageManager| +:保存报告到输出目录; +:返回报告路径; + +|BackendService| +:调用DetectionTask.complete(); +:更新任务状态为Completed; +:返回检测结果和报告路径; + +|DashboardView| +:接收检测结果; +:更新界面显示 (进度、结果列表); +:提供下载报告链接; + +|用户| +:查看检测报告; +stop + +@enduml +```