2022'den beri Node.js ve Express ile backend geliştiriyorum. Bu yıl C# ve .NET Core öğrenmeye başladım; piyasada .NET talebinin Türkiye'de ne kadar yaygın olduğunu görünce bu tarafa ağırlık vermeye karar verdim. Bu yazıda henüz bu yolun başındayken, Node.js'ten gelen birinin gözünden neyin tanıdık, neyin farklı geldiğini anlatıyorum. Bir karşılaştırma rehberi değil, bir öğrenme günlüğü.
Tanıdık gelen: katmanlı mimari
Node/Express'te route → controller → service → repository gibi bir katman ayrımını elle kuruyorsun, bu bir kütüphane değil, bir alışkanlık. ASP.NET Core'da bu ayrım Controller-Service-Repository olarak dile daha yerleşik geliyor, ama mantık aynı: HTTP isteğini karşılayan katman, iş kuralını yürüten katman ve veritabanına konuşan katman birbirinden ayrı.
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderService _orderService;
public OrdersController(IOrderService orderService)
{
_orderService = orderService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetOrder(string id)
{
var order = await _orderService.GetByIdAsync(id);
return order is null ? NotFound() : Ok(order);
}
}Express'teki bir route handler'la neredeyse birebir aynı şekilde okunuyor: bir istek geliyor, bir servise devrediliyor, bir yanıt dönüyor.
Farklı gelen: dependency injection baştan var
Node'da dependency injection istersen kendi elinle kuruyorsun (ya da hiç kurmuyorsun, require ile doğrudan import ediyorsun). ASP.NET Core'da DI framework'ün bir parçası; yukarıdaki OrdersController örneğinde IOrderService'i constructor'a yazman yeterli, hangi somut sınıfın enjekte edileceğini Program.cs'te bir kere tanımlıyorsun:
builder.Services.AddScoped<IOrderService, OrderService>();Bunun faydasını test yazarken görüyorum: OrderService'i test ederken gerçek bir repository yerine sahte (mock) bir tane veriyorum, kontrolörün kendisi hiç değişmiyor. Node'da aynı şeyi yapmak için ya bir DI kütüphanesi (Awilix, InversifyJS gibi) kurman ya da kendi enjeksiyon mekanizmanı yazman gerekiyor.
Farklı gelen: derleme zamanı hataları
TypeScript kullansam bile Node'da bazı hatalar sadece çalışma zamanında (runtime) ortaya çıkıyor, özellikle any tipiyle gevşetilmiş yerlerde. C#'ta tip sistemi daha katı ve derleme zamanında (compile time) çok daha fazla şeyi yakalıyor: yanlış tipte bir parametre, null olabilecek bir referansı kontrol etmeden kullanmak gibi hatalar kod çalışmadan önce derleyicide patlıyor. Başta bunu yavaşlatıcı buldum, "neden bu kadar çok kural var" dedim, ama artık derleyicinin bulduğu her hatanın production'da bulmayacağım bir hata olduğunu düşünüyorum.
Tanıdık gelen: ORM mantığı
Prisma ile Entity Framework Core arasında kavramsal fark yok: ikisi de modeli kod tarafında tanımlıyor, ikisi de migration üretiyor, ikisi de ilişkili veriyi include/Include ile tek sorguda getiriyor.
public class Order
{
public string Id { get; set; } = default!;
public string UserId { get; set; } = default!;
public User User { get; set; } = default!;
public List<OrderItem> Items { get; set; } = new();
}Prisma'daki schema.prisma dosyasının yaptığını burada C# sınıfları üstündeki öznitelikler (attribute) ve DbContext yapılandırması yapıyor. Syntax farklı, çözdüğü problem aynı.
Henüz netleşmeyen: hangi işlerde .NET tercih ediliyor
Bu kısımda dürüst olmak istiyorum: henüz bu yolun başındayım, Commencis'in ücretsiz mentorluklu bootcamp'ine katılıyorum ve gerçek bir .NET projesini üretime çıkarmadım. Node.js tarafında üç yıla yakın üretim deneyimim var, .NET tarafında ise haftalar var. Bu yazıda "hangisi daha iyi" gibi bir sonuca varmıyorum çünkü henüz böyle bir karşılaştırma yapacak deneyimim yok; sadece geçiş sürecinde neyin kolay, neyin zor geldiğini paylaşıyorum.
Sonuç
Node'dan .NET Core'a geçerken en çok zorlandığım yer C#'ın tip sistemine alışmak oldu, en tanıdık gelen yer ise katmanlı mimari ve ORM kullanım şekliydi. Bu geçiş sürecini ilerledikçe burada güncellemeye devam edeceğim.