Proaktif Hata Yakalama: Bölüm I

Kısmi Derlenen ve Taşınan Uygulamalarda Öngörülemeyen Hataları Engelleme

Rifat Aricanli
VakıfBank Teknoloji
4 min readOct 15, 2021

--

Photo by Markus Spiske on Unsplash

Birbirine bağımlı modülere ait tüm birim testlerin başarılı sonuçlanmasına, Test, PreProd ve UAT ortamlarında hata alınmadan kullanıcı testlerinin yapılmasına rağmen üretim ortamında modüllerin birbirleriyle olan bağımlılıklarının uyumsuzluğundan kaynaklı hatalar oluşabilmektedir.

Sözgelimi A ve B modülleri birbirlerine bağımlı olsunlar. A’nın testleri öğlen 14:00'da başarılı tamamlansın ve üretim ortamına taşınması planlansın; B modülünün testlerinde fark edilen bir eksiklik sebebiyle ise A modülünden çağrılan M metodunun imzasında dikkatsizce bir değişiklik yapılsın ve bu şekilde birim testlerinden saat 15:00'da başarıyla geçsin. Her değişiklikte tüm sistem tekrar derlenmediği, modüller dinamik olarak birbirine bağlandığı ve A’nın testleri de tamamlandığı için bu değişiklik üretim ortamında A’dan B’ye yapılacak M metodu çağrısında MissingMethodException hatasına sebep olacaktır.

Modüllerin kullanım amacına bağlı olarak bu türdeki sorunlar üretim ortamına geçişten saatler sonra bile ortaya çıkabilecektir. Okuyacağınız yazıda bu gibi durumların önüne geçmek için uygulanabilecek bir yöntemden bahsedeceğiz.

Uygulama nasıl çalışıyor?

Bir istek geldiğinde sunucu isteği ilgili modüle yönlendirir ve oradaki bir handler metoda çağrım yapılır. Bu metodun başka modüllere bağımlılığı olabilir, ve hatta dış modüllere yapılan çağrımlar koşullu olabilir. Bu gibi durumlarda dış modül dll’i bu anda dinamik olarak AppDomain’e yüklenir ve metod çağrımı yapılır. Metod imzaları aynıysa sistem doğal olarak sorunsuz çalışır. Ta ki…

Uygulama niçin çalışmıyor?

…dış modülde var olmayan bir metod çağrılana dek. Yukarıdaki örnekte bahsedilen M metodu hakkındaki bilgi, A ve B modüllerinde farklı duruma düşmüştür. B modülünde bulunan metod değişmiştir, fakat A’nın bundan haberi yoktur, çünkü B değiştikten sonra A derlenmemiş ve üretim ortamına kadar taşınmıştır.

Aslında bu sorun tüm uygulamayı değil, sadece bulunamayan metodların çağrıldığı yerleri etkilemektedir. Fakat bu hatayla çok kritik modüllerde de karşılaşılma olasılığı bulunduğundan mümkün olduğunca önlenmesi gerekmektedir.

Nasıl önleyebiliriz?

Bu sorunun kök çözümü aslında oldukça basit: modülleri tekrar derlemek. Fakat üretim ortamına taşınması planlanan dll’ler ile bunlara ait kodların bire bir aynı olduğu garanti edilemiyorsa farklı bir yöntem izlemek gerekecektir. Bu da taşınması planlanan tüm dll’leri decompile edip tekrar derlemek olacak. Bahsettiğimiz uygulama .NET ile yazıldığı için bu işlem ICSharpCode.Decompiler kitaplığıyla gerçekleştirilebiliyor. Sanal makine üzerinde çalışan diğer diller için de benzer yöntemler uygulanabilir.

Tüm işlem için ihtiyaç duyulan namespace’ler aşağıdaki gibi:

using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.Metadata;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

Dll’lerin listesinin elimizde olduğunu varsayalım. İlk yapmamız gereken şey dll’i decompile etmek. Bunu aşağıdaki gibi bir kod parçacığı ile gerçekleştirebiliriz:

dll’in decompilation adımı

Bu adımdan sonra code değişkeni içinde dll’e ait C# kodunu bulabilirsiniz. Dll’in içinde projenin dosya yapısına ait bir bilgi olmadığından class/interface/enum vb. her şey tek bir string içine çıkartılacaktır.

Sonraki aşama bu kodun başarılı derlenip derlenmediğini görmek. Bunun için ilk yapmamız gereken elimizdeki kodun syntax bilgilerini çıkarmak:

SyntaxTree ve CompilationUnitSyntax oluşturulması

Kodda özellikle belirtilmiş bir target framework olabilir, fakat biz uygulamamızım 4.8 ile çalıştığını biliyoruz. Bu nedenle kodu bize ait TargetFramework bilgileriyle derlemek için aşağıdaki gibi bu framework tanımlarını eğer varsa kaldırıyoruz.

TargetFramework tanımlarını silme

Ardından decompile ettiğimiz dll’in referans verdiği diğer dll’lerin bir listesini çıkartıyoruz. Buna kodu tekrar derlerken ihtiyacımız olacak:

Dll’in referans listesini çıkartma

Getreferences metodunun içeriği ise şöyle (bkz: stackoverflow):

Artık ilk derleme girişimimizi yapmaya hazırız:

Kodu ilk derleme denemesi

Bu adımda hala eksik referanslar sebebiyle hata almamız mümkün. Bunun sebebi AppDomain’de olduğu varsayılan ve doğrudan referans edilmeyen uygulamaya ait framework dll’leri. Bu sebepten referans bulunamadı hatasıyla (CS0012) karşılaşıldığında bunları da yükleyip tekrar derlemeyi denememiz gerekli:

Dolaylı referansları bulma, ekleme ve tekrar derleme

Bu işlemi CS0012 hatası almayana kadar denedikten sonra elimizde kalan sonuç gerçek derleme hataları olacaktır. Artık derleyici çıktılarını örneğin aşağıdaki gibi bir kod bloğuyla kontrol ederek dönebiliriz:

Yakaladığımız derleme hataları

Bu noktadan sonra yakalanan hataların değerlendirilmesi taşıma otomasyon sistemine kalmış durumda. Bir sonraki yazıda kod ve veri tabanı nesneleri arasındaki uyumsuzlukların taşıma öncesinde tespit edilmesinden bahsedeceğiz.

Referanslar

--

--