5

刚用 NestJS 完成一个项目,开发体验一般, JS 模块添加依赖注入,个人感觉必要性不强

 2 years ago
source link: https://www.v2ex.com/t/866056
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Node.js

刚用 NestJS 完成一个项目,开发体验一般, JS 模块添加依赖注入,个人感觉必要性不强

  newghost · 12 小时 6 分钟前 · 1598 次点击
JAVA 里用依赖注入因为定义的都是 class ,想要共享实例只能注入。但 JS 模块导入即单例与 JAVA 机制完全不同,个人感觉必要性不强。
比如在文件开头的 import 语句,其实可以已经体现了依赖关系,这时你完全可以把 service/controller/dao 实例或方法 import 进来,其实已经可以算作完成了依赖声明,为什么还要 module 中重新注入一次依赖关系?
其次在构造函数中把 service/dao 实例变成参数传进来,个人感觉复杂了不少,可维护性降低。

大家觉得用 typescript + express 再分层会不会更简洁一些?
20 条回复    2022-07-14 16:58:56 +08:00
lovedebug

lovedebug      12 小时 4 分钟前

JS 没有自省,没办法。
Nest.js 在 Node 工程化上的探索还是不错的。
newghost

newghost      12 小时 1 分钟前

@lovedebug
Nest.JS 还一个不好的点是调用一个 serivce 依赖,test case 也要更新,更个接口之间偶合度太高,维护性起来体验感比较差。
doommm

doommm      11 小时 58 分钟前 via Android

我个人理解,模块可以拿来做单例,但不是好的实践。IOC 可以做的事情更多
newghost

newghost      11 小时 58 分钟前

@wunonglin
嗯,一处依赖要在 module/import/构造函数弄三次声明,跟以前写 java 的感觉一模一样。
doommm

doommm      11 小时 57 分钟前 via Android

@doommm 应该说是 DI
newghost

newghost      11 小时 57 分钟前

@doommm
构架看上去不高级,体现不出水平倒是真的
lovedebug

lovedebug      11 小时 56 分钟前

@newghost 嗯,是的。Nestjs 基本理念来自 Angular 和 Spring ,这些问题两者都有。目前就是在工程化上的妥协,不引入框架,项目代码真的比较难以维护,就怕放飞自我。
mxT52CRuqR6o5

mxT52CRuqR6o5      11 小时 55 分钟前 via Android

虽然说在 js 上搞依赖注入可能看上去有点多此一举,但做成接近 spring 的方案可以减少学习成本啊
newghost

newghost      11 小时 53 分钟前

@mxT52CRuqR6o5
有点道理,NG,Spring 过来一看,太亲切了,太熟悉了
doommm

doommm      11 小时 46 分钟前 via Android

@newghost 个人理解,单例应该是基于 app 应用生命周期的,而不是基于模块的。在 app 只会有一个实例的情况下,使用 DI 看起来会显得多余,但我认为这是明确代码职责的一种方式
walpurgis

walpurgis      11 小时 8 分钟前

为什么要在 module 里定义依赖关系,因为依赖的是接口而不是实现,只不过一般图省事直接把实现类作为接口传进去了,就像 Spring 里面依赖项直接写了某个类而不是接口一样
可以看下这章 https://docs.nestjs.com/fundamentals/custom-providers ,providers: [CatsService] 只是 providers: [
{
provide: CatsService,
useClass: CatsService,
},
] 的简写,provide 属性是 IoC 容器用于寻找实例的 key ,不一定是一个具体的类,碰到需要多个实现的场景,一般定义个抽象类作为 provide ,useClass 就可以根据情况注入不同的实现类了

本质是要把依赖交给容器管理,让使用方不知道用的是哪个实现,如果直接 import 进来用就绑死了具体的实现了
dudubaba

dudubaba      11 小时 7 分钟前

强约束性,比其他框架 service 满天飞好多了
lzgshsj

lzgshsj      10 小时 44 分钟前   ❤️ 1

就像 #12 说的一样,大多数人是跳过了写接口这个阶段,直接依赖的实现类。所以看着的结果就是同一个东西在 module 和 import 里重复导入。
providers: [CatsService] 也可以写成
providers: [{provide: AnimalsService, useClass: CatsService}]
这里的 AnimalsService 就可以是个接口,而 useClass 又可以改成 useValue ,useFactory ,useExisting...等等灵活的实现。
这种做法可能在很多 orm 测试用例里会见到,因为测试往往用的不是真的数据,如果要 mock 的话,这时就可以使用 MockService 作为实现。
mxT52CRuqR6o5

mxT52CRuqR6o5      10 小时 24 分钟前

@walpurgis 但其实 99.99%的业务代码用到倒闭也不会有替换 Service 的需求,也就测试时这个不绑死实现的特性有点用,但在 node 里也提供了能力去对 require 的结果进行 hook ,像 jest 不需要依赖注入一样可以替换 requre 、import 的东西
newghost

newghost      8 小时 18 分钟前

@walpurgis
@lzgshsj
我们使用的就是接口,这玩意更不实用,只有一个类,都用接口代替,平白多了 一层。而且 DEBUG 时很麻烦,点击方法都跑到了接口文件,每次还要手动去搜这个类。

TS 原写模块一般都会有一个 index 文件,只需要改用接口类型声明,如果真有类替换,在 index 中替换掉这个 modlue 的 export 实例即可,不更简单?
wu67

wu67      8 小时 11 分钟前

强约束性, 前端仔表示, 看了一周文档, 看不下去, 跑了.

自己写个破接口 mock 一下, express 真香.
lzgshsj

lzgshsj      7 小时 57 分钟前

@newghost #16
1.实际情况是 99.99%的项目都不需要接口,所以你直接使用类也完全 ok ,框架也很灵活没有限制死,甚至 provider 就是默认你不写接口模式了。说到 debug 跳转,至少我用的 webstorm 是可以跳转到接口实现类的,没有要搜索的情况。

2.index.ts 的确是一个好东西,在 ng 里叫做 barrel files 。但是使用不当可能会造成循环应用。https://docs.nestjs.com/fundamentals/circular-dependency#circular-dependency

3.如果你想的是通过修改 index.ts 的 export ,来修改对应导出,那就是完全硬编码的方式了。还不如一步到位把所有你可能用到的 provider 全部 export 来得更方便?

4.技术没有银弹,本质上 nest.js 这套还是学的 ng 和 spring ,关于过度设计接口抽象的话题网上比比皆是。我的看法是,结合自身和团队情况,程序不报错,那条条大路通罗马。
pengtdyd

pengtdyd      7 小时 26 分钟前

nestjs 最大的好处就是可以不招后端,只招前端就可以了,人力成本省了一大笔,这对于创业公司或者新项目是巨大的收益
newghost

newghost      4 小时 57 分钟前

@wu67

NestJS 的 Controller 其实设计的不错,可以省掉每个 url 的前辍像 /api/v2 这种,还能省掉 app.get/app.post 重复定义。如果只用 express ,controller 代码看上去有点脏

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK