NestJS — Basit Olsun, Aptalca

Feb 25 2023
Yapılandırma Modülünü kullanmak için bir alternatif
Düşünün, bu sabah yeni bir iş arkadaşınız işe başlıyor ve tek yapması gereken Nest uygulamanızda bir ortam değişkeni kullanmak. Neyse ki, süreç yoluyla basitçe bir değişken çıkarmak için görevi yapmayı kabul ediyor.

Düşünün, bu sabah yeni bir iş arkadaşınız işe başlıyor ve tek yapması gereken Nest uygulamanızda bir ortam değişkeni kullanmak. Mutlu bir şekilde görevi yapmayı, basitçe bir değişkeni process.env. process.envBirisi ona söyleyene kadar doğrudan erişim sağlamayız , bunun yerine Yapılandırma Modülünü kullanırız .

Geçtiğimiz yıllarda NestJS projelerinde birden fazla ekibe rehberlik ettim ve çoğu NestJS belgelerini takip etti, neden ile başlamadılar .

“Yaptığımız şeyi neden yapıyoruz?”

Ama çerçevenin iyi, kötü ve hatta çirkin taraflarıyla yüzleştim . Ve kendi kendime “Nest bizimle mi yoksa bize karşı mı?” diye sormaya başladım. . Ve şaşırtıcı bir şekilde Nest'in bazı bölümlerinin aslında bize karşı çalıştığı sonucuna vardım.

Düşmanımızla yüzleşmek

Beni yanlış anlama, Nest'i hala seviyorum. Ama aslında Nest'in Konfigürasyon bölümünün kutudan çıktığı gibi gelmemesine çok sevindim . Aslında, @nestjs/config , ayrı olarak kurabileceğiniz Nest'in temel bir modülüdür - yani yalnızca ihtiyacınız varsa. İşin komik yanı, çalıştığım hemen hemen her projede, Yapılandırma Modülü aşağıdaki nedenlerle uygulandı:

  • Yapılandırma modülü Nest'e girmenin yolu gibi geliyor .
  • Oldukça fazla sayıda belge mevcut ( ve açıkça gerekli ).
  • Aynı görüşlü yapıyı takip eder.
  • Doğrulama ile genişletilebilir ( çoktan azına gördüğüm en iyi uygulama )

Config Modülünün eksikleri

1 kelimeyle, basitlik . Bir ortam değişkenine erişim, gün içinde en sık yapılan görevlerden biridir ve bu nedenle olabildiğince kolay olmalıdır. Yani Config Modülü bize karşı değil, bizden önce çalışmalı.

fooÖrnek vermek gerekirse, namespace'deki özelliğe erişmek appbizi aşağıdaki gibi bir şey uygulamaya zorlar.

// app.config.ts
const appConfig = register('app', () => ({
  foo: process.env.APP_FOO
}))

// app.module.ts
ConfigModule.forRoot({
  load: [
     appConfig,
   ],
  }),
]);

// MyService.ts
class MyService {
 constructor(
   private configService: ConfigService 
 )

 myMethod(){
   // now we can finally get the env var
   const foo = this.configService.get<string>('app.foo')
 }
}

Yanıtın bir olacağını varsayıyoruz string, ancak bunu yalnızca çalışma zamanında bileceğiz. Gerçekten var olup olmadığını doğrulamak için editörümüzü veya IDE'yi kullanamayız app.foo. Bir yazım hatası bir saniyede yapılabilir ve dakikalarca (veya saatlerce) hata ayıklamayla sonuçlanır. Ve acı verici sonuç şu ki, aslında istediğimiz şey mülke erişmekti app.foo. Ama sonunda sözde goril-muz-orman sorunuyla karşılaştık .

“… Çünkü nesne yönelimli dillerin sorunu, yanlarında taşıdıkları tüm bu örtük ortama sahip olmalarıdır. Bir muz istedin ama elinde muzu ve tüm ormanı tutan bir goril oldu. “

— Joe Armstrong, Erlang programlama dilinin yaratıcısı

Nest, bir options nesnesini ileterek çalışma zamanında bir özelliğin türünü doğrulayabilmek için bir tür geçici çözüm getirdi.

const foo = this.configService.get<string>('app.foo', { infer: true })

  • gerçekten var olan bir özelliği hedef aldığımızı;
  • IDE'mizdeki astarlama ve kod vurgulama vb. sadece çalışır;
  • özelliğin tipinin referansla çıkarıldığı ;
  • ve ortam değişkenini Nest kapsamı dışında kullanabileceğimizi.

Bir mühendis olarak, her zaman bir adım geri atmalı ve Basit tut, aptal kısaltmasını hala uygulayıp uygulamadığımızı düşünmeliyiz . Ve şimdi gördüğümüz gibi, Yapılandırma Modülü bu yasayı açıkça çiğniyor.

Başka bir yaklaşım getirmezsem kötümser gibi görünsem de. Daha uygun bir tane. Hâlâ tartışılacak, ancak daha önce bahsedilen sorunları da ele alan bir yaklaşım. Küçük arkadaşıma merhaba deyin :

export const appConfig = {
  foo: process.env.APP_FOO
}

// and consume it elsewhere...
const foo = appConfig.foo

Ve daha büyük uygulamalarda bile benzer bir şey uygulayabiliriz. configYine de , şuna benzer bir dizin yapısına ayrı bir dizin eklemek yararlı olacaktır :

├── src
│   ├── foo-module
│   │   ├── foo.controller.ts
│   │   ├── foo.service.ts
│   │   └── foo.module.ts
│   │
│   └── config
│       ├── appConfig.ts
│       └── dbConfig.ts
│   
├── package.json
└── nest-cli.json

Bir mühendis olarak her zaman neden ile başlamalıyız . Kendimizi kutunun içinde düşünmeye devam etmek yerine kutunun dışında düşünmeye zorlamalıyız. Bu, NestJS gibi üzerinde düşünülmüş bir çerçeveyi kısmen terk edeceğimiz anlamına gelse bile.

Ünlü bir alıntıyla bitirmek için: “Erişim ortamı değişkenlerini yeniden harika hale getirelim” . Ormandaki gorillere değil, muzlara odaklanın.