İki yılı aşkın süredir şirketimizin gündeminde olan Sonar Cube kod analis uygulaması vasıtasıyla projelerimizi kod analizine tabii tutup, kod kalitemizi yükseltmeye ve yüksek tutmaya çalışıyoruz. Bu kapsamda ekiplerimizde bazı bulgu çözümleri noktasında sorular ve destek talepleri gelebiliyor. Bir yazı dizisi ile bu destek talebi gelen bulgular ya da Sonar Cube kod analiz kuralları hakkında bir yazı dizisi yapmaya karar verdim.
Classes with "IDisposable" members should implement "IDisposable"
Bu yazımda ele alacağımız Sonar Cube kritik hata bulgusu : Classes with "IDisposable" members should implement "IDisposable"
Bu analiz kuralı kritik bulgu seviyesinde ve gayet önemli bir noktaya parmak basıyor. Uygulamamız içersinde kullandığımız kaynakları bırakmamamız durumunda sunucularımızda meydana gelebilecek performans sorunları ve sistem kaynaklarının kötüye kullanımına sebep olacak durumların önüne geçmeye çalışıyor.
Sonar bulgu açıklamasında örneğinin iletildiği gibi, projemizdeki bir sınıf eğer dispose edilmesi gereken bir kaynağı sınıfın bir üyesi olarak kullanıyor ise sınıfın IDisposible arayüzünü uygulayıp bu kaynağı Dispose metodunda elden çıkarması gerekir. Ya da bu kaynak sınıfın bir üyesi olarak değil de gerekli olan metod içerisinde yaratılıp using bloku içerisinde kullanılabilir.
Bu çözüm uygulanınca yeni bir sonar code smell’i yaratıyor olabiliriz : "IDisposable" should be implemented correctly
Bu code smell’i çözmek için de eğer sınıfımız başka sınıfları türetmiyor ise sınıfı mühürlemek yani sealed hale getirmek, aksi halde de aşağıdaki gibi geliştirme yapmak sorunu çözecektir. Yani bu yazımda biri kritik bulgu, biri de code smell olan iki ayrı kod analiz bulgusuna uygulanacak çözümü inceliyor olacağız.
Örnek Çözüm 1
public class ResourceHolder : IDisposable
{
private FileStream fs;
public void OpenResource(string path)
{
this.fs = new FileStream(path, FileMode.Open);
}
public void CloseResource()
{
this.fs.Close();
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
this.fs.Dispose();
}
}
Örnek Çözüm 2
public sealed class ResourceHolder : IDisposable
{
private FileStream fs;
public void OpenResource(string path)
{
this.fs = new FileStream(path, FileMode.Open);
}
public void CloseResource()
{
this.fs.Close();
}
public void Dispose()
{
this.fs.Dispose();
}
}
Örnek Çözüm 3
public class ResourceHolder
{
public void OpenResource(string path)
{
using (FileStream fs = new FileStream(path, FileMode.Open))
{
// burada fs'i kullanalım
}
}
}
Sonuç
IDisposible arayüzü ve doğru kullanımı ile alakalı iki farklı sonar kod analis kuralını incelemiş ve üç farklı çözüm önerisi getirdik. Bu yazımın devamında benzer Sonar Cube Kod Analiz kurallarına değiniyor olacağız. Eğer siz de belli bir kural hakkında detay ve çözüm önerileri istiyorsanız bana ulaşıp haber vermeniz yeterli, kodu inceleyip beraber bir yazı ele alabiliriz.