最新要闻
- 当前热门:加速颠覆燃油车!汉、唐冠军版上市:双车20.98万起
- 全球快看:从小吃到大的腌菜 竟是“垃圾堆”生产?被315暴击的进来
- 当前快看:群友们的表情包《九十期》
- 每日视点!男子镜头前嗨舞被羊顶翻 网友看完大笑:做人不能太狂浪
- 每日头条!自媒体捏造董明珠和王自如恋情!龚文祥公开致歉:希望取得原谅
- 今日快看!Win11最新正式版闯大祸:SSD性能不忍直视
- 天天即时看!微软签署第四份《使命召唤》十年协议:索尼仍不愿妥协
- 【天天聚看点】男孩长蛀牙爸爸用电钻钻牙止痛 被网友疯狂指责:太危险了
- 全球讯息:20.98万元起 2023款比亚迪唐DM-i上市:全系升级铝合金悬架
- 热点聚焦:冲击百万销量!比亚迪汉DM-i、DM-p补贴10000元现金
- 当前关注:双拖布+超大吸力!小米米家扫拖机器人3S发售:千元旗舰
- 世界视点!特斯拉一体化压铸工艺被质疑增加修车成本 一个小碰撞可能要修11万
- 精彩看点:追上Intel AMD锐龙7000处理器终于用上192GB内存:频率满血
- 环球看热讯:315全景观察:深情主播“连哄带骗” 爸妈的钱就没了
- 最新:无解了!微软将推出基于GPT-4的Office 365服务 实用性拉满
- 【焦点热闻】北京通州区汽车消费券活动时间是什么时候?
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
NodeJS 实战系列:模块设计与文件分类
我们从一个最简单的需求开始,来探索我们应该从哪些方面思考模块设计,以及如何将不同的文件分类。之所以说“思考”,是因为我在这篇文章里更多的是提供一类解决问题的范式,而非统一的标准答案,能够为你提供一丁点的启发就好
【资料图】
实战系列来自个人开发以及运维site2share网站过程中的经验
需求很简单:当用户访问列表页面时,我们需要展示列表数据。为了便于接下来的演示,我们不如把这里的“数据”具象化,以 site2share网站为例,列表即代表了每用户创建的文件夹下的内容,如下图所示
Service层很重要
在获取数据的过程中我们至少需要做这么几件事:
- 获取列表数据
- 获取列表文件夹元数据,如创建人、创建时间
- 判断访问者是否有权限修改列表
我们可以想象这三类数据如果使用 SQL进行存储的话,它们会属于不同的数据库表,所以在这次数据访问中我们至少要对三张表进行读操作。但是应该直接把三者的数据库读操作语句糅合在一个函数里吗?缺少封装问题不是最大的问题,这么做会导致代码的维护性会大大增加,因为可能有多个功能用例都需要“获取文件夹元数据”,这样一来同样的一组代码就难免会散落在代码库各个地方(可能是多行代码),如果有一天表结构发生了更改需要修改语句,你会面临散弹式修改的风险。
所以你至少应该以 service视角将同类型操作封装起来。比如把所有和用户有关的操作都归类到 UserService.js文件中
什么是 service?如上图所示,如果我们把最外层大圆圈定义为正在被开发的应用的话,那么service层处于应用的最外层边界上,与它接壤的是各种类型访问方式,例如网络请求可以访问这个应用,通过CLI也可以访问这个应用。无论访问方式是什么,外部永远无法跨越 service层调用应用内部的接口。service封装了常见的应用业务逻辑,你甚至可以理解为用户用例
在 service层之下你还看到有 domain层和 data source层,在 NodeJS中可以不追求一模一样的抽象,但 service层是至少需要保证的。
注意 service与 model并非一一对应
例如我们有一个关于文件夹的服务层模块 FolderService.js,“Folder”意味着的是它服务于“Folder”,而非只能访问和 "Folder"有关的数据。在模块内部可以有一个方法名为 GetFolderByUserId,这个时候它可能为了在结果中带上用户信息,而需要访问用户数据库。甚至它还需要请求应用外的数据,比如用户数据存储在 Auth0的话
优先按照功能给文件分类
除了 FolderService.js以外,我们可能还有数据层访问模块 FolderModel.js,以及专门响应与文件有关请求的路由 FolderRouter.js。关于如何组织这些文件这里有两个思路
按照功能(与文件或者用户有关)将这些文件组织在一起(前者),和按照角色(与路由或者服务有关)将文件组织在一起(后者)
├── Folder| ├── FolerService.js| ├── FolderModel.js├── User| ├── UserService.js| ├── UserModel.js
├── Services| ├── FolerService.js| └── UserService.js├── Models| ├── FolderModel.js| └── UserModel.js
后者是我们最常见的组织文件方式,但实际上前者更有利于我们开发
日常开发工作都是围绕某个特定的功能展开的,例如需求“新增 API 用于前端获取访问量最多的前十文件夹 id“,在开发这个功能的过程中我们修改的路由、在 service 和 model 中新增的方法,都只和 Folder 有关,我们需要反复在有关文件之间切换并且做出修改。按照功能组织文件,便于我们聚焦我们开发的功能
这其实和前端开发中使用 duck文件分类法 是类似。
甚至我建议你的测试文件也应该和功能放在一起(大部分项目的测试文件都会单独放在测试文件夹中)。当然是否应该这么做部分取决于你是如何制定你的测试策略的。在拥有 service模块的前提下,我建议大部分精力应该对 service进行测试,对 service测试一方面间接测试了 service以下的其他模块代码,另一方面也直接对用户用例进行了测试。测试还有一个颇为重要的功能是,它可以作为被测试模块的说明书,通过测试用例我们可以知道模块能做什么以及不能做什么
最小知识原则
项目中还有相当多的文件是无法与具体业务相关联的技术代码。例如我们通常会把常量,公共函数提取到单独的文件中。代码不是为了分类而被分类,所有的行为背后都是为提高代码维护性服务的。在我的经验看来代码分类的一个重要原则是确保程序员以最小的成本展开工作。
文件的命名和划分应该符合程序员的默契。例如我们看到 src文件夹就应该知道它是用于存放源码文件的,如果你把源码文件命名为 src的全称 source会让不少人要理解好一会。
之所以说是默契,是因为这类规则并不是明文写在什么开发制度里的,而是当我们经历了10个代码库并且每个代码库都是这么做的时候,我们也就会认为这么做是对的,并且之后的编码工作把相同的规则传递下去。例如以下关键词常常被作为默契使用:
- util/utility:公共代码
- libs:第三方类库
- common:公共文件目录
- constant:常量
- test/ut(united test):测试相关
- client/provider:第三方服务访问类
- docs:文档相关
- dist/build:打包目录
- public/assets:静态文件
- *.md:markdown格式的文件通常为文档
- *.spec:带有 spec字样的文件通常为测试文件
- tool/scripts:与代码无关的工具文件,比如创建数据库的 shell脚本
这些还只是文件命名上的潜规则。默契可以提升我们的开发效率,例如当你第一次接触某个代码库想看看它说明文档时,你想当然的会去搜寻 markdown类型的文件;又或者你创建了一个函数觉得后期对其他团队成员也有帮助时,你下意识的会存储在 util.js的文件中
“最小知识”的另一个方面是,当需要维护某个模块时,我们应该尽可能避免其他模块带来的干扰,这也是模块划分的本质意义。行数巨大的文件或者函数虽然是一个经典反例,但是在当下可能已经不常见。有一些其他类型的陷阱在这里分享出来。
package.json 就是一个例子,目前 jest, babel,nodemon等等都允许将配置信息编写在 package.json中,甚至一些开发工具还允许我们将 eslint的配置也放置其内。但我不认为这是一个好的实践。例如当我们需要修改 jest配置时,只专注于 jest.config.js的修改能够让我们更快定位到文件和代码,以降低对其他配置破坏的可能性。
下面截图是 site2share项目中所需要的各类配置文件,想象一下如果把它们所有内容都塞入 package.json其中,诞生的超级配置文件是怎样一种灾难。
就像我在文章开头说的,所有的问题无法一概而论。例如对于多个团队共用一个代码库的 monorepo 类型项目来说,全局共享的单一常量文件注定是无法解决问题的。对于类似问题我无法一一作出解答,但是把你自己放到将来的项目中去,围绕可维护性去思考一定是正确的方向
你可能也会喜欢:
- NodeJS 实战系列:DevOps 尚未解决的问题
- NodeJS 实战系列:如何设计 try catch
- 做一个能对标阿里云的前端APM工具(下)
- 做一个能对标阿里云的前端APM工具(上)
- 小心 Serverless
- SQL Server 查询语句优化入门
- 利用Node.js+express框实现图片上传
- 一篇来自前端同学对后端接口的吐槽
- 关于Node.js后端架构的一点后知后觉
- 在Node.js中搭建缓存管理模块"
关键词:
NodeJS 实战系列:模块设计与文件分类
环球新动态:计算,存储,网络虚拟化区别
当前热门:加速颠覆燃油车!汉、唐冠军版上市:双车20.98万起
全球快看:从小吃到大的腌菜 竟是“垃圾堆”生产?被315暴击的进来
即时看!MyBatis
当前快看:群友们的表情包《九十期》
每日视点!男子镜头前嗨舞被羊顶翻 网友看完大笑:做人不能太狂浪
每日头条!自媒体捏造董明珠和王自如恋情!龚文祥公开致歉:希望取得原谅
今日快看!Win11最新正式版闯大祸:SSD性能不忍直视
新动态:设计一款可扩展和基于windows系统的一键处理表格小工具思路
天天即时看!微软签署第四份《使命召唤》十年协议:索尼仍不愿妥协
【天天聚看点】男孩长蛀牙爸爸用电钻钻牙止痛 被网友疯狂指责:太危险了
全球讯息:20.98万元起 2023款比亚迪唐DM-i上市:全系升级铝合金悬架
热点聚焦:冲击百万销量!比亚迪汉DM-i、DM-p补贴10000元现金
世界观速讯丨点积、内积、外积、叉积、张量积——概念区分
day05-Lombok、SpringInitializer
【世界聚看点】国家推出稳定2023年大豆生产一揽子支持政策
当前关注:双拖布+超大吸力!小米米家扫拖机器人3S发售:千元旗舰
世界视点!特斯拉一体化压铸工艺被质疑增加修车成本 一个小碰撞可能要修11万
精彩看点:追上Intel AMD锐龙7000处理器终于用上192GB内存:频率满血
环球看热讯:315全景观察:深情主播“连哄带骗” 爸妈的钱就没了
最新:无解了!微软将推出基于GPT-4的Office 365服务 实用性拉满
【焦点热闻】北京通州区汽车消费券活动时间是什么时候?
Redis监控
sed文本处理工具常见用法
每日看点!Prometheus 监控系统1
Java中的NIO
环球快报:带你全方面了解字节 A/B 实验的文化与工具
世界新资讯:【金融街发布】交易商协会发布企业资产证券化基础性制度
【世界播资讯】重庆龙凤胎熊猫宝宝取名“渝可”“渝爱”
速看:《小美人鱼》剧照还原动画经典场景:就是肤色不太对
头条焦点:中国制造!索尼第四代降噪豆XM5佩戴/音质/快充全面升级:AirPods Pro2劲敌
老人墓中藏13万现金全部霉变 专业能手全力抢救:官方科普纸钞如何保管
海底捞部分门店取消免费美甲:只能付费购买穿戴甲
视讯!SQLMap 源码阅读
今日观点!abc285G
环球精选!JVM -Xss
【高端访谈·城市力量】“双碳”背景下农商银行如何“点绿”成金?——访秦农银行党委书记、董事长李彬
今热点:五菱电动“吉姆尼” 宝骏悦也续航里程公布:能跑303公里
董明珠要玩大的?格力成立房地产新公司 投资数亿元
东方甄选称被骗了 虾品供应商发声:不认可甩锅行为
热点在线丨百度文心一言申请页被挤爆:预约1小时涌入3万企业
环球快讯:现实版GTA!美劫匪偷直升机因操作失误当场坠毁:一地碎片
国宝大熊猫的视频_国宝大熊猫的故事
66.类型转换
快讯:【0基础学爬虫】爬虫基础之抓包工具的使用
天天热头条丨制作学生信息管理系统
文心一言正式对标GPT-4,是青铜还是王者?
全球播报:恒生指数16日收跌1.72% 互联网科技股集体走低
每日速看!铁匠用30年给猫和老鼠做铠甲:一套比一套帅!
戴尔推出了灵越14 ARM版:骁龙8cx Gen 2、16小时长续航
世界播报:卡布达归来!《铁甲小宝》高清修复版将至:已开通B站账号
两败俱伤:比亚迪海豹街头铲翻宝马X5
块级元素和行内元素
天天实时:SublimeREPL设置详解——实现代码传递(Eval in REPL)
天天观速讯丨JavaScript 实现异步任务循环顺序执行
自定义 Spring 通用日志注解
精彩看点:日债市场继续消化欧美银行风险扰动 收益率曲线陡峭化下移
即时焦点:【财经分析】债市利空反应钝化 后市操作存分歧
每日快报!【新华500】新华500指数(989001)16日跌1.29%
【环球时快讯】小伙爆改特斯拉Model 3:加装120寸轮毂、增加“逆天”功能
【新要闻】百度文心一言问答测试为视频演示 李彦宏:为保证效果提前录制
全球实时:深蓝SL03车主联合声明:长安雇水军打压车主 要求车辆终身质保加补偿
国内首款天玑9000旗舰平板!OPPO Pad 2官宣:下周发布
【世界时快讯】曾投资一亿美元:马斯克痛批OpenAI成为营利组织
冰墩墩钥匙扣(冰墩墩多少钱一只)
最新消息:76.qt qml-QianWindow开源炫酷界面框架(支持白色暗黑渐变自定义控件均以适配)
今热点:Markdown用法解析
世界微动态丨得物从0到1自研客服IM系统的技术实践之路
天天看热讯:性能优化搞得好,Tomcat少不了。| 博学谷狂野架构师
世界观天下!笔记本水冷改造记录
世界球精选!创维造车:主打座舱养生续命、碰撞测试0分!真是讽刺他妈给讽刺开门
环球即时:反转!国内油价明晚大概率下跌 预计下调0.07元/升
《暗黑4》本周末开测 世界BOSS刷新时间公布
天天关注:巴奴火锅下架富硒土豆!消费者可获赠500元储值卡:领取有条件
天天热推荐:百度发布文心一言AI模型:可实现文字、图片与视频智能生成
喝的人越来越少!星巴克向中国三四线城市进军:30多一杯咖啡县城青年能爱多久
麦芒11什么时候上市的?麦芒11手机参数配置
华为电视怎么投屏?华为电视怎么下载第三方软件?
孙海洋是湖北哪里人?
鲶鱼效应是什么意思?鲶鱼效应的经典案例是什么?
首店经济是什么意思?首店经济是谁提出的?
快报:权志龙演唱会门票多少钱2020_权志龙演唱会门票多少钱
环球讯息:用图技术搞定附近好友、时空交集等 7 个典型社交网络应用
GPT-4测评,大家先别急,图片输入还没来
全球时讯:C#使用ObjectPool提高StringBuilder性能
今头条!RTX 40笔记本新品翻车?别急 先升级NVIDIA新驱动再说
每日精选:官宣!《炉石传说》被移出杭州亚运会项目:职业选手难过
环球快消息!360发布年度手机安全报告:受骗男性占七成 女性三成
天天最资讯丨800V电气架构打造 全新起亚EV9发布:二三排可面对面乘坐
扣上的安全带会自动打开?本田在美国召回近45万辆汽车
【独家焦点】虹科案例|虹科Visokio商业智能平台在疫后帮酒店业打好翻身仗!
环球今热点:python 二分法查找
环球实时:面试问题-密码
Fortran语言在线代码运行编译工具推荐
Scrapy中的response对象的属性及方法,附加mate属性的使用方法
每日短讯:强冷空气来袭!河南三门峡3月下雪:厚厚一层一夜回冬
环球要闻:爱立信CEO:印度是全球推出5G速度最快的国家之一
上映25周年纪念:3D重制版《泰坦尼克号》国内定档
真凉了!暴雪网易闹掰 《炉石传说》或被移出杭州亚运会项目