Backend geliştirme sürecinde, fonksiyonların gereksinim duyduğu verileri sürekli olarak parametre olarak iletmek yaygın bir yaklaşımdır. Ancak bu yöntem, özellikle uygulama karmaşıklaştıkça ciddi sorunlara neden olabilir. Bu makalede, request scoped context kavramını ve Node.js’in async_hooks modülünden esinlenen AsyncLocalStorage kullanımını inceleyeceğiz. Bu teknik sayesinde, verileri fonksiyonlar arasında iletmek yerine, talep bazında yöneterek temiz ve bakımı kolay bir kod yapısı oluşturabilirsiniz.
Fonksiyonlara Parametre Aktarımı: Basit Başlar, Karmaşıklaşır
Geçmişte backend projelerinde, kullanıcıya ait bilgileri fonksiyonlara parametre olarak iletmek standart bir uygulama yöntemiydi. Örneğin, bir sipariş kimliğinin (orderId) her fonksiyona iletilmesi, basit ve doğrudan bir yaklaşım olarak görülüyordu. Bu yöntem, küçük projelerde etkili olabilse de, uygulama büyüdükçe sorunlar ortaya çıkmaya başladı.
Daha karmaşık bir uygulama olan kıyafet kiralama sisteminde bu yaklaşımın sınırları hızla anlaşıldı. orderId, başlangıçta sadece sipariş işlemlerinde kullanılırken, sistem genişledikçe fiyatlandırma hesaplayıcısından, log kayıtlarına kadar birçok fonksiyonun parametresi haline geldi. Hatta bazı fonksiyonlar, orderId'yi doğrudan kullanmasalar bile, sadece diğer fonksiyonlara iletmek için parametre listesinde yer alıyordu. Bu durum, parametre kirliliği olarak adlandırılan bir soruna yol açtı: fonksiyonlar, gerçekte kullanmadıkları verileri iletmek zorunda kalıyordu.
Sık Değişen Gereksinimler ve Bağlantı Sorunları
Uygulama geliştirme sürecinde, yeni bir bilginin sisteme eklenmesi gerektiğinde, bu durum ciddi bir sorun haline geldi. Örneğin, log kayıtlarına userId eklemek istendiğinde, tüm fonksiyon zincirine bu parametrenin eklenmesi gerekiyordu. Bu yaklaşım, sıkı bağlılık (tight coupling) sorununu ortaya çıkardı: bir fonksiyonun imzasını değiştirmek, zincirdeki tüm fonksiyonları etkiliyordu. Bu da bakım maliyetini artırıyor ve kodun esnekliğini azaltıyordu.
Loglama sürecinde de benzer bir problem yaşandı. Her log kaydına orderId eklemek için, bu değeri tüm fonksiyonlara iletmek gerekiyordu. Bu durum, gereksiz yere tekrarlanan kodlara ve artan karmaşıklığa neden oldu. Kod tekrarı, sadece verimsiz olmakla kalmıyor, aynı zamanda okunabilirliği de azaltıyordu.
Request Scoped Context: Temiz ve Odaklı Fonksiyonlar İçin Çözüm
Bu sorunlarla karşılaştıktan sonra, verileri fonksiyonlara iletmek yerine, talep bazında yönetme fikri ortaya çıktı. Node.js’in async_hooks modülünde yer alan AsyncLocalStorage, bu ihtiyacı karşılamak için ideal bir çözüm sundu. AsyncLocalStorage, her bir HTTP talebine özel bir saklama alanı oluşturur. Bu sayede, verileri sadece talebin başında tanımlamak ve ardından tüm fonksiyon zincirinde doğrudan erişmek mümkün hale gelir.
AsyncLocalStorage’un çalışma prensibi oldukça basittir. Node.js, her bir asenkron işlem için özel bir bağlam (context) oluşturur. AsyncLocalStorage.run() metoduyla başlatılan bir bağlam, tüm asenkron fonksiyonlar tarafından erişilebilir hale gelir. Bu sayede, orderId gibi veriler, fonksiyonlara parametre olarak iletilmek yerine, doğrudan bağlamdan okunabilir.
AsyncLocalStorage Kullanımı: Adım Adım
AsyncLocalStorage kullanmaya başlamak için öncelikle modülü projenize dahil etmek gerekir. Ardından, talebin başında bağlamı başlatmak ve fonksiyon zinciri boyunca kullanmak için aşağıdaki adımları izleyebilirsiniz:
import { AsyncLocalStorage } from "async_hooks";
// Bağlam saklama alanı oluştur
const requestContext = new AsyncLocalStorage();
// Bağlamı başlat ve fonksiyon zincirini çalıştır
export function runWithContext(context, fn) {
return requestContext.run(context, fn);
}
// Bağlamdan veri okuma
export function getContext() {
return requestContext.getStore() || {};
}Bu fonksiyonlar, talebin başında çağrılmalıdır. Örneğin, bir Express.js middleware’inde ya da rota işleyicisinde:
app.use((req, res, next) => {
// Talep başında bağlamı başlat
const context = {
orderId: req.headers['x-order-id'],
userId: req.user?.id
};
runWithContext(context, next);
});Ardından, bağlamdaki veriler herhangi bir fonksiyondan doğrudan okunabilir:
function logOrderActivity() {
const context = getContext();
console.log(`Sipariş Aktivitesi: orderId=${context.orderId}`);
}
function calculatePricing() {
const context = getContext();
// Fiyatlandırma hesaplaması
}Bu yaklaşım sayesinde, fonksiyonlar sadece yapmaları gereken işe odaklanabilir hale gelir. Gereksiz parametrelerin iletilmesi ve fonksiyon imzalarının karmaşıklaşması önlenmiş olur.
Küçük Projelerden Büyük Uygulamalara: Ne Zaman Kullanmalısınız?
AsyncLocalStorage gibi request scoped context yöntemleri, özellikle küçük projelerde gereksiz görünebilir. Ancak uygulama karmaşıklaştıkça ve fonksiyon zincirleri uzadıkça, bu tekniklerin avantajları açıkça ortaya çıkar. Eğer aşağıdaki durumlardan herhangi biri sizin için geçerliyse, bu yaklaşımı denemek iyi bir fikir olabilir:
- Fonksiyonlara iletilen parametreler, zincirdeki birçok fonksiyon tarafından kullanılmıyor.
- Yeni bir parametre eklemek, tüm fonksiyon imzalarını değiştirmeyi gerektiriyor.
- Log kayıtlarına ek veriler eklemek için gereksiz yere fonksiyon zincirini değiştirmek zorunda kalıyorsunuz.
- Fonksiyonlarınızın imzaları giderek karmaşıklaşıyor ve bakımı zorlaşıyor.
Bu teknikler, kodunuzun temiz, odaklı ve bakımı kolay olmasını sağlar. Fonksiyonlar, sadece yapmaları gereken işe odaklanırken, gereksiz parametrelerin iletilmesi ve fonksiyon imzalarının karmaşıklaşması önlenmiş olur.
Sonuç: Daha İyi Kod İçin Daha İyi Yaklaşımlar
Parametre aktarımı ve fonksiyon imzaları, backend geliştirmenin temel unsurlarından biri olsa da, bu yaklaşımın sınırları olduğunu kabul etmek önemlidir. Özellikle karmaşık uygulamalarda, verileri talebe özel olarak yönetmek, kodun temizliğini ve bakımını önemli ölçüde artırır.
AsyncLocalStorage gibi teknikler, Node.js geliştiricileri için güçlü bir araç sunar. Bu teknikleri erken benimsemek, gelecekte karşılaşabileceğiniz sorunları önlemenin yanı sıra, kodunuzun daha esnek ve bakımı kolay olmasını sağlar. Küçük projelerde gereksiz görünebilir, ancak uygulama büyüdükçe, bu tekniklerin avantajları hızla ortaya çıkar. Kodunuzun temiz ve odaklı kalmasını sağlamak için, request scoped context kullanımını değerlendirmeniz önerilir.
Yapay zeka özeti
Node.js uygulamalarında parametre kirliliğini önlemek için request scoped context ve AsyncLocalStorage kullanımını öğrenin. Temiz kod ve bakım kolaylığı için pratik rehber.