ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

MoviePilot 命名规范全解:从文件、类到 message/notification 语义域的代码约定指南

MoviePilot 命名规范全解:从文件、类到 message/notification 语义域的代码约定指南 后端AI AgentMCP 服务AI 技能【免费下载链接】MoviePilotNAS媒体库自动化管理工具项目地址https://gitcode.com/gh_mirrors/mo/MoviePilot点击查看免费下载导读本文基于 MoviePilot 仓库docs/rules/07-naming-conventions.md整理而成是该开源 NAS 媒体库自动化管理工具涵盖下载、订阅、媒体服务器、消息通知、站点管理等模块内部为所有新代码制定的统一命名约定。命名一致性是代码库无需注释即可传达意图的关键手段阅读本文后你将掌握 MoviePilot 中 Python 源文件、类、函数、变量、枚举、配置项、API 端点乃至消息/通知两个易混语义域的完整命名规则理解每条约定背后的设计动机如模块创建门禁、旧路径兼容策略并能在贡献代码或二次开发时直接套用这些规范。文中所有示例与结论均可在当前仓库源码中找到对应实现。一、总则命名即沟通规范即契约MoviePilot 的命名约定遵循一条核心原则一致的命名让代码库无需注释就能传达意图Consistent naming is how the codebase communicates intent without comments。所有新代码必须遵守以下约定代码评审与架构测试以本规范为准绳。命名规范共覆盖八大维度每个维度都有明确的应用场景与反例对照文件与目录Files类Classes函数与方法Functions and Methods变量与参数Variables and Parameters枚举Enums配置与设置Configuration and SettingsAPI 端点与路由API Endpoints and Routers消息/通知语义域边界Message / Notification Domain Boundary其中「生产模块创建门禁」Production Module Creation Gate与「消息/通知语义域边界」是本规范中最具架构约束力的两条规则分别对应docs/rules/07-naming-conventions.md中的两个强制决策流程。二、文件与目录命名2.1 基础文件命名规则上下文约定示例Python 源文件snake_case.pydownload.py、qbittorrent.py、package.py规范化能力包canonical capability packages中的新文件优先使用单个小写职责名词在添加同级文件前先尝试扩展现有 ownertorrent.py、package.py、resources.py多文件能力创建同名目录包使用聚焦的单词子文件禁止展平为capability_role.py平级文件transfer/workflow.py、transfer/execution.py模块包目录snake_case/包根不重复导出宿主实现qbittorrent/、synologychat/、transfer/测试文件test_domain.pytest_download_chain.py、test_subscribe_endpoint.pyAlembic 迁移由 Alembic 自动生成不要重命名20240101_add_column.pySkill 目录kebab-case/transfer-failed-retry/、moviepilot-cli/这些约定在仓库中有大量真实对应物。例如测试目录tests/下可见 test_download_chain.py、test_subscribe_endpoint.py 等命名完全遵循test_domain.py模块目录 app/modules/qbittorrent/ 为snake_case/包而skills/目录下的 transfer-failed-retry、create-moviepilot-plugin 等则全部使用 kebab-case。2.2 生产模块创建门禁Production Module Creation Gate这是文件命名规则中最关键的一条强制决策流程。新增或拆分生产模块时必须按以下顺序决策代码评审与架构测试以此为准优先扩展当前职责 owner。只因文件变长或需要一个私有辅助类不得新建平级模块。一个能力需要第二个生产文件时必须在同一次变更中改为同名目录包禁止继续增加capability_role.py平级文件。包内子文件使用准确、可独立说明职责的单个小写名词例如dependencies/profile.py与dependencies/native.py不得使用native_dependencies.py、transfer_execution.py这类重复能力名的文件。包根__init__.py只允许包说明和确有外部契约证据的公开门面不得复制实现也不得为宿主代码重复导出子模块符号宿主必须直接导入 owner 子模块。旧路径兼容只能在确认真实插件消费者后通过app/sdk/或app/runtime/compat/做精确映射不得为假设消费者保留旧源码、通配映射或双份导出。新增文件前必须同步更新本规则对应的机器门禁若现有门禁不能表达该命名约束应在同一变更中补充 tests/test_architecture_dependencies.py。这条门禁的落地依赖架构测试对命名约束的机器化检查。例如 tests/test_chain_base_boundary.py、tests/test_architecture_dependencies.py 等测试文件就是这类机器门禁的代表它们以可执行测试的形式固化哪些模块边界、哪些命名模式是允许的防止后续变更悄悄引入违反规范的平级文件或重复导出。反例与正例对照反例Wrong正例Correcttransfer.pytransfer_execution.pytransfer/workflow.pytransfer/execution.pydependencies.pynative_dependencies.pydependencies/profile.pydependencies/native.py包根为旧路径做宿主 re-export精确的 SDK/Compat 映射宿主代码直接导入 owner 子模块三、类命名PascalCase上下文约定示例Chain 类DomainChainDownloadChain、SearchChain、SubscribeChainModule 类BackendModuleQbittorrentModule、EmbyModule、TelegramModuleOper数据访问类ModelOperSubscribeOper、SystemConfigOper、TransferHistoryOperHelper 类DomainHelperTorrentHelper、DirectoryHelper、MessageHelperPydantic schema 模型PascalCase名词聚焦MediaInfo、TorrentInfo、DownloadingTorrentSQLAlchemy 模型类PascalCase单数名词Subscribe、TransferHistory、SystemConfig枚举类PascalCaseMediaType、EventType、ModuleTypeManager 类DomainManagerModuleManager、PluginManager、EventManager通用类PascalCaseMetaInfo、Context、ChainBase3.1 源码验证三类核心类名的真实落点Chain 类DownloadChain定义于 app/chain/download/facade.pySearchChain定义于 app/chain/search/facade.pySubscribeChain定义于 app/chain/subscribe/facade.py三者均继承自ChainBase。这印证了规范中「DomainChain」的命名模式且 Chain 实现以目录包形式组织。Module 类QbittorrentModule定义于 app/modules/qbittorrent/init.pyEmbyModule定义于 app/modules/emby/init.pyTelegramModule定义于 app/modules/telegram/module.py。注意 Module 类的命名使用完整后端名Qbittorrent而非QB这正是反例表中class QBModule:被禁止的原因。Oper 类SubscribeOper定义于 app/db/oper/subscribe.pySystemConfigOper定义于 app/db/oper/systemconfig.pyTransferHistoryOper定义于 app/db/oper/transferhistory.py。它们均继承自DbOper是 MoviePilot 数据访问层的标准形态。Helper 类NotificationHelper定义于 app/application/notification.py继承自ServiceBaseHelper[NotificationConf]对应规范中DomainHelper的约定。SQLAlchemy 模型Message模型定义于 app/db/models/message.py使用PascalCase单数名词。从源码结构可以推断Chain 类以DomainChain统一后缀、Oper 类以ModelOper统一后缀、Manager 类以DomainManager统一后缀这套命名把类名即职责定位落实到极致——看到名字即可知道该类的分层归属链、模块、数据访问、帮助器、管理。四、函数与方法命名snake_case上下文约定示例所有函数与方法snake_caseget_subscribe、run_module、on_config_changed私有方法_snake_case前导下划线_submit_download_added_task、_parse_result事件处理方法on_event_name或描述性命名on_transfer_complete、handle_config_changed模块接口方法匹配_ModuleBase契约init_module、init_setting、get_name、get_type、test、stopOper 方法动词 名词get、add、update、delete、list4.1 设计要点解读事件处理方法使用on_event_name前缀是 MoviePilot 事件驱动架构的显性表达。事件处理函数必须一眼看出它响应哪个事件如on_transfer_complete响应转移完成事件。这也与docs/rules/04-design-patterns.md中事件驱动模式相呼应。模块接口方法必须严格匹配_ModuleBase契约这是各模块下载器、媒体服务器、消息渠道等可被统一调度器加载的前提。方法名是契约的一部分不得随意更改。Oper 方法采用动词 名词的极简风格get、add、update、delete、list与数据访问层的 CRUD 语义一一对应。反例def GetSubscribe():错误应为def get_subscribe():def handleConfigChanged():错误应为def on_config_changed():或def handle_config_changed():。五、变量与参数命名上下文约定示例局部变量snake_casetorrent_info、media_type、download_dir实例属性snake_caseself.download_history、self.config常量模块级UPPER_SNAKE_CASEDEFAULT_EVENT_PRIORITY、MIN_EVENT_CONSUMER_THREADS私有变量_snake_case前导下划线_instance、_lock类型变量PascalCase搭配TypeVarT TypeVar(T)反例TORRENT_info ...错误应为torrent_info ...。命名中不区分大小写混写私有性统一由前导下划线表达。六、枚举命名上下文约定示例枚举类名PascalCaseMediaType、TorrentStatus、EventType枚举成员PascalCase针对复杂枚举MediaType.MOVIE、EventType.TransferComplete字符串枚举值匹配领域语言MediaType.MOVIE 电影、TorrentStatus.TRANSFER 可转移SystemConfigKey值匹配配置键的字符串原值SystemConfigKey.RssUrls RssUrls6.1 源码验证枚举值即领域语言在 app/schemas/types.py 中可以找到规范的典型实现MessageTypeapp/schemas/types.py的成员均为PascalCase而字符串值使用中文领域语言Download 资源下载、Organize 整理入库、Subscribe 订阅、SiteMessage 站点、Manual 手动处理、Plugin 插件、Agent 智能体、Other 其它。NotificationChannelapp/schemas/types.py的成员同样遵循PascalCase字符串值为渠道领域名Wechat 微信、Feishu 飞书、Telegram Telegram、Slack Slack、Discord Discord、DingTalk 钉钉、SynologyChat SynologyChat、Web Web等。SystemConfigKeyapp/schemas/types.py定义于app/schemas/types.py中的系统配置Key字典区块其成员名使用PascalCase而值必须与持久化配置键的字符串完全一致例如Downloaders Downloaders、MediaServers MediaServers、Notifications Notifications、Directories Directories、RssSites RssSites、AIAgentConfig AIAgentConfig。这一约定的深层原因是SystemConfigKey的枚举值是持久化到数据库的配置主键一旦改名会破坏存量用户数据因此成员名可以遵循代码命名规范但值必须冻结为配置键原字符串。七、配置与设置命名上下文约定示例Settings/ConfigModel字段UPPER_SNAKE_CASEAPI_TOKEN、LLM_MODEL、QB_HOSTSystemConfigKey枚举成员PascalCaseSystemConfigKey.RssUrls、SystemConfigKey.SubscribeFilter环境变量名UPPER_SNAKE_CASEAI_AGENT_ENABLE、DB_TYPE关键实践访问配置时必须通过SystemConfigKey枚举成员而非裸字符串。反例configuration.get(RssUrls)正例configuration.get(SystemConfigKey.RssUrls)。这条规则的价值在于枚举将配置键集中管理杜绝散落各处的魔法字符串配合 IDE 的类型检查与自动补全任何配置键的拼写错误都能在编译期暴露。同时它保证了配置键的持久化值与外部协议DB、环境变量冻结的一致性。八、API 端点与路由命名上下文约定示例端点函数名snake_case动词前置get_subscribe_list、add_download、delete_historyURL 路径段kebab-case或snake_case匹配既有模式/api/v1/subscribe、/api/v1/transfer/historyRouter tags匹配资源领域名subscribe、download、media设计要点动词前置让 API 处理函数在路由注册处可读性最强get_、add_、delete_、update_前缀清晰表达 HTTP 语义与资源操作。URL 路径段允许kebab-case或snake_case但必须与项目既有模式保持一致——这是一个向后兼容优先的约定避免新旧路由风格并存造成混乱。Router tags 直接取资源领域名subscribe、download、media这使 OpenAPI 文档中相同领域的所有端点聚合在同一个 tag 下便于 API 使用者检索。九、Message / Notification 语义域边界强制规则message与notification在 MoviePilot 中是两个不同的语义域。新增或修改相关代码时必须按职责选名不得混用。这是本规范中最易踩坑、也最具业务约束力的一条规则。9.1 两个语义域的职责划分语义域职责规范命名示例notification通知渠道能力渠道枚举、渠道配置、渠道发现、渠道管理、渠道能力描述NotificationChannel、NotificationConf、NotificationHelper、NotificationChain、NotificationAction、ChannelCapabilityManager、ModuleType.Notification、channel_managemessage各渠道发送或接收的消息消息体、消息类型、消息链、消息历史、消息队列Message、MessageType、IncomingMessage、MessageChain、MessageHistoryItem、MessageOper、post_message、message_parser9.2 判断规则规则说明渠道本身用notification渠道是能力提供方如NotificationChannel枚举、NotificationConf渠道配置消息内容与收发用message消息是被传输的内容如发送体Message、接收体IncomingMessage、分类MessageType渠道 × 消息的交叉概念按主导方判断按渠道控制消息开关的NotificationSwitch属渠道能力消息历史清理MessageClearScope属消息历史旧名不在源码保留Notification、MessageChannel、NotificationType、CommingMessage等旧名仅登记在app/runtime/compat/manifest.py的SYMBOL_ALIASES新代码一律使用规范名持久化值与外部协议冻结枚举值、SystemConfigKey配置值、DB 表名、API 路径、外部平台字段如 Jellyfin 的NotificationType不随命名统一变更9.3 源码验证语义域的真实落点与旧名兼容message 域MessageChain定义于 app/chain/message.py继承ChainBaseMessageOper定义于 app/db/oper/message.pyMessage发送体与IncomingMessage接收体均定义于 app/schemas/message.pyIncomingMessage在第 96 行继承BaseModel。notification 域NotificationConf定义于 app/schemas/system.pyNotificationHelper定义于 app/application/notification.py负责渠道能力的服务化封装。旧名兼容SYMBOL_ALIASES注册表位于 app/runtime/compat/manifest.py其中_MESSAGE_NOTIFICATION_SYMBOL_ALIASESapp/runtime/compat/manifest.py专门登记了消息/通知命名统一后的旧符号映射例如MessageChannel→NotificationChannelapp.schemas.typesNotificationType→MessageTypeapp.schemas.typesNotification→Messageapp.schemas.messageCommingMessage→IncomingMessageapp.schemas.messageNotificationHistoryItem→MessageHistoryItemNotificationClearScope/ClearBefore/ClearData→MessageClearScope/ClearBefore/ClearDataChannelCapability、ChannelCapabilities、ChannelCapabilityManager→app.schemas.notification该注册表由 app/runtime/compat/imports.py 等运行时兼容层消费实现旧名可导入但指向新符号的精确映射。从源码结构可以推断这套机制是仅为真实插件消费者保留的兼容通道符合文档中旧路径兼容只能在确认真实插件消费者后通过app/sdk/或app/runtime/compat/做精确映射的约束。9.4 反例对照反例Wrong新代码中禁止正例CorrectMessageChannel.TelegramNotificationChannel.TelegramNotification(title...)Message(title...)十、反模式速查Anti-Patterns将上述全部约定浓缩为一张错误 → 正确对照表供代码评审时快速比对错误Wrong正确Correctclass downloadchain:class DownloadChain:class QBModule:class QbittorrentModule:def GetSubscribe():def get_subscribe():TORRENT_info ...torrent_info ...def handleConfigChanged():def on_config_changed():或def handle_config_changed():configuration.get(RssUrls)configuration.get(SystemConfigKey.RssUrls)class subscribe_oper:class SubscribeOper:transfer.pytransfer_execution.pytransfer/workflow.pytransfer/execution.pydependencies.pynative_dependencies.pydependencies/profile.pydependencies/native.py包根为旧路径做宿主 re-export精确的 SDK/Compat 映射宿主代码直接导入 owner 子模块MessageChannel.Telegram新代码NotificationChannel.TelegramNotification(title...)新代码Message(title...)十一、如何在贡献中落实这些规范命名先行在写第一行代码前先判断新增文件属于哪个能力域按「生产模块创建门禁」的决策顺序确定是扩展现有 owner 还是新建同名目录包。用测试固化约束若新增的命名约束无法被现有机器门禁表达应在同一变更中补充 tests/test_architecture_dependencies.py 之类的架构测试让规范可被 CI 自动校验。严格遵守语义域涉及消息/通知的代码先判断职责是渠道能力notification还是消息收发内容message再决定命名域绝不把旧名引入新代码。尊重冻结契约枚举值、SystemConfigKey配置值、DB 表名、API 路径等持久化或对外协议层面的命名不随代码重构变更旧符号兼容一律走app/runtime/compat/manifest.py的SYMBOL_ALIASES精确映射。以上规范共同构成了 MoviePilot 代码库的命名宪法——它不仅是风格的统一更是模块边界、数据访问分层、事件驱动架构与消息/通知语义域在命名层面上的制度化表达。遵循这些约定任何新代码都能被团队与自动化门禁准确理解与校验。本文依据docs/rules/07-naming-conventions.mdLast Updated: 2026-08-29整理并结合仓库源码与测试验证。规范细节以文档原文与仓库实际代码为准。赞分享后端AI AgentMCP 服务AI 技能【免费下载链接】MoviePilotNAS媒体库自动化管理工具项目地址https://gitcode.com/gh_mirrors/mo/MoviePilot点击查看免费下载相关推荐Modin 社区代码规范从命名约定到文档注释的全方位指南Modin 社区代码规范从命名约定到文档注释的全方位指南 引言 你是否在参与开源项目时因代码风格不统一而感到困扰是否曾因文档注释不清晰而难以理解函数功能本数据分析数据工程大数据MicroPython 代码规范与提交约定全指南从 Commit Message 到自动格式化MicroPython 代码规范与提交约定全指南从 Commit Message 到自动格式化 本指南完整解析 MicroPython 仓库的 CODECON嵌入式语言运行时编程语言解释器编译器物联网系统编程Ghost Downloader 代码规范与架构约定从命名词汇表到领域语言的工程实践Ghost Downloader 代码规范与架构约定从命名词汇表到领域语言的工程实践 导读 Ghost Downloader Ghost Downloade桌面应用网络上一篇ChampR终极英雄联盟助手一键生成推荐出装与符文下一篇2025 终极指南Pixyll 打造极简响应式 Jekyll 博客创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表