SlideShare a Scribd company logo
1 of 18
.Net ve İstisnalar
Barış ENGİN
baris@basarsoft.com.tr
Temel
Temelde «İstisnalar» ikiye ayrılır.
• Senkron İstisnalar
• .Net Framework’ün verdiği istisnalar: InvalidArgumentException,
ArgumentIsNullException, FormatException… etc.
• Kendi uygulamanızı verdiği istisnalar: Exception sınıfından üretilmiş size ait istisnalar
• Asenkron İstisnalar: Genellikle asenkron istisnalar kendi içinde ikiye ayrılır.
• Sistem tarafından verilen ve hiçbir zaman yakalanmaması gereken hatalar:
MemoryOutOfException, StackoverflowException…
• Altyapı tarafından asenkron olarak fırlatılan hatalar. (Genellikle üçüncü parti uygulamalar
ve/veya native kütüphaneler tarafından)
İstisnalarıYakalamak
Kural #1: Senkron istisnalarıYAKALAYABİLİRSİNİZ(*), asenkron hataları
YAKALAMAMALISINIZ(**).
(*) Size kalmış.Yakalamamanız uygulamanızı sonlanmasına sebep olabilir. Bu
durumda yakalamak isteyebilirsiniz. Ancak bir web servis gibi bir ortamda iseniz
yaptığınız hatalar karşı tarafa aktarılacak, kullanıcı bir sorun olduğunu içeriği ile
anlayacak ve uygulamanız sonlanmayacaktır. Çünkü yakalanmayan her bir istisna
kendi çalıştığıThread’i sonlandırmaya çalışacaktır. Eğer bu MainThread ise
uygulamanız sonlanır.
(**) Genellikle asenkron hataları yakaladığınız zaman yapabileceğiniz bir şey yoktur.
Bu da bizi ileride anlatacağımız ikinci kurala getiriyor.
«İstisna» KavramınınVarolma Sebebi
İstisnalar, uygulama içinde tahmin edilemeyen/beklenmeyen durumları kod
geliştiriciye/kullanıcıya haber veren yapılardır. Sebebini anlamak daha iyi kod
geliştirmenize yardımcı olur.
Günümüz bilgisayarlarında istisnalar donanımsal olarak desteklenir. Onları
kullanmanın size avantajı olacağı gibi yanlış bir yaklaşımla sisteminizi olabildiğince
yavaşlatırlar.
«İstisna» ‘ların oluşmasındaki en büyük motivasyon «Call Stack» içerisinde oluşan bir
hatanın en tepede çağırılan method tarafından yakalanabilmesini sağlamak ve ek
bilgileri edinebilmektir.
Call Stack
• Uygulamanız herhangi bir seviyede hata verebilir. İstisna’ları size sağladığı
en tepeden bu hataları yakalayabilme şansıdır. Aşağıdaki örnekte
GetEntityInfo() metodu içinde oluşacak bir hata kendisini çağıran bütün
metotlar tarafından yakalanabilir.
• Hangi seviyede yakalayacağınız size kalmış.
• Burada sizin üzerinize düşen mimarinizi buna uygun kurmaktır.
• Nasıl?
İstisnalara Karşı Zeka
Önceki slide içerisinde istisnaların kendisini çağıran bütün metotlar tarafından
yakalanabileceğini gördük. İstisnayı hangi seviyede yakalamak istediğiniz,
olayı hangi seviyede çözeceğinizi belirleyecektir.
Ancak bazı durumlar bu kadar derin düşünmeyi ve olayları karışık hale
getirmeyi gerektirmez.
İstisnalara Karşı Zeka
Yukarıdaki örnekte açıkça gözüküyor ki bir zaten kapalı olan bir bağlantıyı tekrar
kapatmamak istisnai durumları önlüyor. Ayrıca gereksiz kod yazılmasının önüne
geçiyor. Peki ya böyle bir durumdan haberdar değilsek? Kapalı olan bir bağlantıyı
tekrar kapatmak hata verebilir veya vermeyebilir. Bu tamamen kullandığınız sınıfların
davranışına bağlı. Eğer kullandığınız sınıflar ile ilgili yeterli bilginiz yoksa nasıl olacak?
(Genelde %99 böyledir, çünkü kodlarına sahip olmuyoruz veya yardım dokümanlarını
okumuyoruz.)
if (conn.State != ConnectionState.Closed)
{
conn.Close();
}
İstisnalarıYakalamak 2
Kural #2:Yönetemeyeceğiniz hiçbir istisnayıYAKALAMAYIN.
İstisnalara Karşı Zeka
Yukarıdakilere benzer kod örnekleri yapabileceğiniz en büyük hatalardan biridir. Yukarıdaki örnekte hiçbir zaman bir hata
olduğunu bilemeyeceksiniz. Çağırılan metodun işin ne kadarını yaptığı veya hangi seviyede hata verdiğini bilemediğiniz gibi,
uygulamanız unstable konuma da geçmiş olabilir. Diğer metotların da artık sağlıklı sonuç döndürdüğünden emin olamazsınız.
Bir hata olduğunu öğrendiğinizde her şey çok geç olabilir. Bütün bir veritabanını veya bir sistemi bozmuş olabilirsiniz. Veya
hiçbir çözüm üretemeyeceğiniz OutOfMemoryException gibi bir hatayı da yakalamış olabilirsiniz.
Public void Method1()
{
try
{
doSomething();
}
catch
{ }
}
İstisnalara Karşı Zeka
Test aşaması uygulamanın en önemli aşamasıdır.
Eğer kullandığınız kütüphane ile ilgili bilgiye sahipseniz soldaki yaklaşımı uygulayabilirsiniz.
Eğer bilginiz yok ise, sağdaki yaklaşımı uygulayın.
Test aşamasında uygulama hata verecektir. Hatayı inceleyip, gerekli kod düzeltmelerini yapın.
Ancak hiçbir zaman bütün hataları yakalama yoluna gitmeyin. Her bir istisna sınıfı için ayrı kod
yazdın.
Günümüz dokümanları içinde metotların vereceği hataların listesi de bulunuyor.
if (conn.State != ConnectionState.Closed)
{
conn.Close();
}
conn.Close();
İstisnalara Karşı Şablonlar (Patterns)
Önceki örneklerden de gördüğünüz gibi her şeyin çözümü istisnaları kullanmak
değil. .Net bize bazı konularda basit çözümler de getiriyor.TryXXX şablonları
.Net 3.5 ile geldi.
Tam olarak bir sınıf şablonu olmasa da istisnaların devreye girmeden durumları
yönetebilmemiz için iyi bir çözümdür.
int k;
string t = GetValue();
if (!int.TryParse(t, out k))
{
// handle the situation
}
int k;
string t = GetValue();
try
{
k = int.Parse(t);
}
catch(FormatException)
{
// Handle situation
}
İstisnalar ve Kullanımı
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
p = 0;
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = GetX();
int y = GetY();
return x * y;
}
static void Main(string[] args)
{
int value = Calculate();
Console.WriteLine(value);
}
}
Soldaki uygulamaGetX() ve GetY()
metotları içinde DivideByZeroException
verme eğilimindedir.
Bu kod bloğu üzerinde nasıl hata yönetimi
yapabiliriz?
Bu sorunun cevabı sorunu hangi seviyede
çözmek istediğimize göre değişir. İşte
birkaç örnek:
İstisnalar ve Kullanımı
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
p = 0;
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = GetX();
int y = GetY();
return x * y;
}
static void Main(string[] args)
{
int value = 0;
try
{
value = Calculate();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return;
}
Console.WriteLine(value);
}
En basit yaklaşım Main() metodu içine bir
try-catch yazmak mı ????
Önceki ekranlarda anlatıldığı üzere bu bize
sadece uygulamamızın herhangi bir hata
yüzünden durmamasını sağlar. Bize hatanın
ne olduğunu söylemez. Sadece hangi
seviyede ne olduğunu anlatır.
Bu sorunu çözebilecek tek kişi uygulamayı
yazan kişidir. Çözebilmesinin tek yolu da
aynı parametreler ile uygulamayı tekrar
çalıştırabilmesinden geçer.
İstisnalar ve Kullanımı
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
p = 0;
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = 0;
int y = 0;
try
{
x = GetX();
y = GetY();
}
catch(DivideByZeroException exception)
{
Console.WriteLine("GetX() veya GetY() içinde sıfıra bölme hatası");
return 0;
}
return x * y;
}
static void Main(string[] args)
{
int value = Calculate();
Console.WriteLine(value);
}
}
Bir seviye daha detaya girelim.
Main() metodu Calculate() metodunu çağırıyor.
Calculate() metodu ise GetX() ve GetY() metodlarını
çağırıyor.
Calculate() içerisine hata kontrolü koysak ne olur?
Bu kod yönetilebilir hatalara iyi bir örnek olabilir. Eğer
sıfıra bölme hatası alınıyorsa kullanıcıya bunu uyaran
bir hata mesajı ve geri dönüş değeri SIFIR verilir.
Elbette Main() bloğu içinde de buna uygun kod
yazılması gerekir.
Eğer Calculate() metodunun geri dönüş değeri SIFIR ise
bir hata var. Ama çağıran kişi bu hatanın ne olduğunu
programatik olarak bilmiyor. Sadece bir hata olduğunu
ve gerekli detayın ekrana yazıldığını biliyor.
Sadece Calculate() metodunun bulunduğu bir
kütüphane yazıyorsanız iyi bir yaklaşım olabilir.Ancak
gene de başarılı ve yeterli değil. (Örnek: Windows API)
İstisnalar ve Kullanımı
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
p = 0;
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
if (p == 0) throw new InvalidOperationException("GetGlobalParameter() metodu
SIFIR değer döndürdü. Olası sebebi metodun içinde hatalı işlem yapılmış olması");
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
if (p == 0) throw new InvalidOperationException("GetGlobalParameter() metodu
SIFIR değer döndürdü. Olası sebebi metodun içinde hatalı işlem yapılmış olması");
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = GetX();
int y = GetY();
return x * y;
}
static void Main(string[] args)
{
int value = Calculate();
Console.WriteLine(value);
}
Aynı şekilde GetX() ve GetY() içerisine de hata
kontrolü konulabilir. Ancak buradaki yaklaşım
çok başarılı olmayacaktır. Çünkü hataya sebep
olan veri GetGlobalParameter() adlı metottan
geliyor.
Eğer olması gereken, GetGlobalParameter()
metodunun hiçbir zaman SIFIR döndürmemesi
ise, bu yönetmememiz gereken hatalara iyi bir
örnek olabilir. GetGlobalParameter() metodu
başkasına ait bir kütüphane içinde veya
kullanıcının ekrandan giriş yaptığı değerlerden
üretiliyorsa olası hatalara karşı kod yazmamız
gerekir.
Biraz daha iyileştirelim.
İstisnalar ve Kullanımı
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
throw new InvalidOperationException("GetGlobalParameter()
metodu SIFIR değer üretti. Kullanıcı hatası veya dış parametrelerden kaynaklı
olabilir.");
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = GetX();
int y = GetY();
return x * y;
}
static void Main(string[] args)
{
int value = Calculate();
Console.WriteLine(value);
}
}
Görüldüğü gibi en alt seviyeden en üst
seviyeye kadar farklı yaklaşımlar uyguladık.
Şu anda verilen hata doğru yerde, en az kod
yazarak en çok bilgiyi veriyor. Ancak .Net
Framework’üne ait bir hata tipi
kullanıyoruz.
İstisnalar ve Kullanımı
public class GlobalParameterException : Exception
{
public GlobalParameterException(string message)
: base(message)
{
}
}
class Program
{
static int GetGlobalParameter()
{
// Do some random calculation
Random r = new Random();
int p = r.Next(-10, 10);
// Do dome random calculation
if (p < 0)
{
throw new GlobalParameterException("GetGlobalParameter() metodu SIFIR değer üretti.
Kullanıcı hatası veya dış parametrelerden kaynaklı olabilir.");
}
else
{
p = p + 10;
}
return p;
}
static int GetX()
{
int p = GetGlobalParameter();
int X = 100 / p;
return X;
}
static int GetY()
{
int p = GetGlobalParameter();
int Y = 100 / p;
return Y;
}
static int Calculate()
{
int x = GetX();
int y = GetY();
return x * y;
}
static void Main(string[] args)
{
int value = 0;
try
{
value = Calculate();
}
catch (GlobalParameterException exception)
{
Console.WriteLine("Global parametrenin hesaplanması ile ilgili birhata alındı. Detay:");
Console.WriteLine(exception.Message);
return;
}
Console.WriteLine(value);
}
}
Artık kendimize ait bir hata tipimiz var.
Başka bir kullanıcı hem hata tipini
anlayabilir hem de gereken açıklamayı
alabilir. Artık try-catch içerisinde ayırım da
yapılabilir. Ayrıca sınıf içerisine ek kod
yazarak daha çok bilgi toplayabilirsiniz.
Sınıf metotlarını yani işi yapmak için
çağırılacak metotları yazarken (bu örnekte
Main() haricindekilerden bahsediyoruz)
kodu bir başkasının kullanacağı şekilde
yazmalısınız. Sadece siz kullanacak olsanız
bile bu sınıfınızın daha sağlam olmasına
yardımcı olur.
Enterprise Design
• Eğer çok büyük bir proje geliştiriyorsanız
mimarinin içerisinde istisnaların yönetimi
ayrı bir iş kalemi olacaktır.
• İstisna yönetimi projenin her aşamasında
kullanılacağı için dikey olarak
konumlandırılır.
• Yakalanan hataların kullanıcıya
gösterilmesi, log tutulması, acil
durumların email veya SMS ile haber
verilmesi gibi işlerin tamamı bu katmanda
yapılır ve ayrı bir kütüphane olarak
düşünebilirsiniz.

More Related Content

Similar to Net ve i̇stisnalar

Similar to Net ve i̇stisnalar (13)

Recep rapor 3 sunu
Recep rapor 3 sunuRecep rapor 3 sunu
Recep rapor 3 sunu
 
Delphi xe5
Delphi xe5Delphi xe5
Delphi xe5
 
Delphi xe5
Delphi xe5Delphi xe5
Delphi xe5
 
Extjs 4 education
Extjs 4 educationExtjs 4 education
Extjs 4 education
 
Sayisal yontemler 2 (1), nümerik analiz
Sayisal yontemler 2 (1), nümerik analizSayisal yontemler 2 (1), nümerik analiz
Sayisal yontemler 2 (1), nümerik analiz
 
Junit
JunitJunit
Junit
 
İleri Seviye Programlama 2
İleri Seviye Programlama 2İleri Seviye Programlama 2
İleri Seviye Programlama 2
 
3 d studio_max_part1
3 d studio_max_part13 d studio_max_part1
3 d studio_max_part1
 
3 d studio_max_el kitabı --- 3DVFX--3D Studio Max Eğitim
3 d studio_max_el kitabı   ---   3DVFX--3D Studio Max Eğitim3 d studio_max_el kitabı   ---   3DVFX--3D Studio Max Eğitim
3 d studio_max_el kitabı --- 3DVFX--3D Studio Max Eğitim
 
5. kurucu, yok edici ve kopyalama fonksiyonları
5. kurucu, yok edici ve kopyalama fonksiyonları5. kurucu, yok edici ve kopyalama fonksiyonları
5. kurucu, yok edici ve kopyalama fonksiyonları
 
C programlama
C programlamaC programlama
C programlama
 
Anet SureLog SIEM IntelligentResponse
Anet SureLog SIEM IntelligentResponse Anet SureLog SIEM IntelligentResponse
Anet SureLog SIEM IntelligentResponse
 
Recep proje 5
Recep proje 5Recep proje 5
Recep proje 5
 

Net ve i̇stisnalar

  • 1. .Net ve İstisnalar Barış ENGİN baris@basarsoft.com.tr
  • 2. Temel Temelde «İstisnalar» ikiye ayrılır. • Senkron İstisnalar • .Net Framework’ün verdiği istisnalar: InvalidArgumentException, ArgumentIsNullException, FormatException… etc. • Kendi uygulamanızı verdiği istisnalar: Exception sınıfından üretilmiş size ait istisnalar • Asenkron İstisnalar: Genellikle asenkron istisnalar kendi içinde ikiye ayrılır. • Sistem tarafından verilen ve hiçbir zaman yakalanmaması gereken hatalar: MemoryOutOfException, StackoverflowException… • Altyapı tarafından asenkron olarak fırlatılan hatalar. (Genellikle üçüncü parti uygulamalar ve/veya native kütüphaneler tarafından)
  • 3. İstisnalarıYakalamak Kural #1: Senkron istisnalarıYAKALAYABİLİRSİNİZ(*), asenkron hataları YAKALAMAMALISINIZ(**). (*) Size kalmış.Yakalamamanız uygulamanızı sonlanmasına sebep olabilir. Bu durumda yakalamak isteyebilirsiniz. Ancak bir web servis gibi bir ortamda iseniz yaptığınız hatalar karşı tarafa aktarılacak, kullanıcı bir sorun olduğunu içeriği ile anlayacak ve uygulamanız sonlanmayacaktır. Çünkü yakalanmayan her bir istisna kendi çalıştığıThread’i sonlandırmaya çalışacaktır. Eğer bu MainThread ise uygulamanız sonlanır. (**) Genellikle asenkron hataları yakaladığınız zaman yapabileceğiniz bir şey yoktur. Bu da bizi ileride anlatacağımız ikinci kurala getiriyor.
  • 4. «İstisna» KavramınınVarolma Sebebi İstisnalar, uygulama içinde tahmin edilemeyen/beklenmeyen durumları kod geliştiriciye/kullanıcıya haber veren yapılardır. Sebebini anlamak daha iyi kod geliştirmenize yardımcı olur. Günümüz bilgisayarlarında istisnalar donanımsal olarak desteklenir. Onları kullanmanın size avantajı olacağı gibi yanlış bir yaklaşımla sisteminizi olabildiğince yavaşlatırlar. «İstisna» ‘ların oluşmasındaki en büyük motivasyon «Call Stack» içerisinde oluşan bir hatanın en tepede çağırılan method tarafından yakalanabilmesini sağlamak ve ek bilgileri edinebilmektir.
  • 5. Call Stack • Uygulamanız herhangi bir seviyede hata verebilir. İstisna’ları size sağladığı en tepeden bu hataları yakalayabilme şansıdır. Aşağıdaki örnekte GetEntityInfo() metodu içinde oluşacak bir hata kendisini çağıran bütün metotlar tarafından yakalanabilir. • Hangi seviyede yakalayacağınız size kalmış. • Burada sizin üzerinize düşen mimarinizi buna uygun kurmaktır. • Nasıl?
  • 6. İstisnalara Karşı Zeka Önceki slide içerisinde istisnaların kendisini çağıran bütün metotlar tarafından yakalanabileceğini gördük. İstisnayı hangi seviyede yakalamak istediğiniz, olayı hangi seviyede çözeceğinizi belirleyecektir. Ancak bazı durumlar bu kadar derin düşünmeyi ve olayları karışık hale getirmeyi gerektirmez.
  • 7. İstisnalara Karşı Zeka Yukarıdaki örnekte açıkça gözüküyor ki bir zaten kapalı olan bir bağlantıyı tekrar kapatmamak istisnai durumları önlüyor. Ayrıca gereksiz kod yazılmasının önüne geçiyor. Peki ya böyle bir durumdan haberdar değilsek? Kapalı olan bir bağlantıyı tekrar kapatmak hata verebilir veya vermeyebilir. Bu tamamen kullandığınız sınıfların davranışına bağlı. Eğer kullandığınız sınıflar ile ilgili yeterli bilginiz yoksa nasıl olacak? (Genelde %99 böyledir, çünkü kodlarına sahip olmuyoruz veya yardım dokümanlarını okumuyoruz.) if (conn.State != ConnectionState.Closed) { conn.Close(); }
  • 9. İstisnalara Karşı Zeka Yukarıdakilere benzer kod örnekleri yapabileceğiniz en büyük hatalardan biridir. Yukarıdaki örnekte hiçbir zaman bir hata olduğunu bilemeyeceksiniz. Çağırılan metodun işin ne kadarını yaptığı veya hangi seviyede hata verdiğini bilemediğiniz gibi, uygulamanız unstable konuma da geçmiş olabilir. Diğer metotların da artık sağlıklı sonuç döndürdüğünden emin olamazsınız. Bir hata olduğunu öğrendiğinizde her şey çok geç olabilir. Bütün bir veritabanını veya bir sistemi bozmuş olabilirsiniz. Veya hiçbir çözüm üretemeyeceğiniz OutOfMemoryException gibi bir hatayı da yakalamış olabilirsiniz. Public void Method1() { try { doSomething(); } catch { } }
  • 10. İstisnalara Karşı Zeka Test aşaması uygulamanın en önemli aşamasıdır. Eğer kullandığınız kütüphane ile ilgili bilgiye sahipseniz soldaki yaklaşımı uygulayabilirsiniz. Eğer bilginiz yok ise, sağdaki yaklaşımı uygulayın. Test aşamasında uygulama hata verecektir. Hatayı inceleyip, gerekli kod düzeltmelerini yapın. Ancak hiçbir zaman bütün hataları yakalama yoluna gitmeyin. Her bir istisna sınıfı için ayrı kod yazdın. Günümüz dokümanları içinde metotların vereceği hataların listesi de bulunuyor. if (conn.State != ConnectionState.Closed) { conn.Close(); } conn.Close();
  • 11. İstisnalara Karşı Şablonlar (Patterns) Önceki örneklerden de gördüğünüz gibi her şeyin çözümü istisnaları kullanmak değil. .Net bize bazı konularda basit çözümler de getiriyor.TryXXX şablonları .Net 3.5 ile geldi. Tam olarak bir sınıf şablonu olmasa da istisnaların devreye girmeden durumları yönetebilmemiz için iyi bir çözümdür. int k; string t = GetValue(); if (!int.TryParse(t, out k)) { // handle the situation } int k; string t = GetValue(); try { k = int.Parse(t); } catch(FormatException) { // Handle situation }
  • 12. İstisnalar ve Kullanımı class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { p = 0; } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); int Y = 100 / p; return Y; } static int Calculate() { int x = GetX(); int y = GetY(); return x * y; } static void Main(string[] args) { int value = Calculate(); Console.WriteLine(value); } } Soldaki uygulamaGetX() ve GetY() metotları içinde DivideByZeroException verme eğilimindedir. Bu kod bloğu üzerinde nasıl hata yönetimi yapabiliriz? Bu sorunun cevabı sorunu hangi seviyede çözmek istediğimize göre değişir. İşte birkaç örnek:
  • 13. İstisnalar ve Kullanımı class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { p = 0; } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); int Y = 100 / p; return Y; } static int Calculate() { int x = GetX(); int y = GetY(); return x * y; } static void Main(string[] args) { int value = 0; try { value = Calculate(); } catch (Exception exception) { Console.WriteLine(exception.Message); return; } Console.WriteLine(value); } En basit yaklaşım Main() metodu içine bir try-catch yazmak mı ???? Önceki ekranlarda anlatıldığı üzere bu bize sadece uygulamamızın herhangi bir hata yüzünden durmamasını sağlar. Bize hatanın ne olduğunu söylemez. Sadece hangi seviyede ne olduğunu anlatır. Bu sorunu çözebilecek tek kişi uygulamayı yazan kişidir. Çözebilmesinin tek yolu da aynı parametreler ile uygulamayı tekrar çalıştırabilmesinden geçer.
  • 14. İstisnalar ve Kullanımı class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { p = 0; } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); int Y = 100 / p; return Y; } static int Calculate() { int x = 0; int y = 0; try { x = GetX(); y = GetY(); } catch(DivideByZeroException exception) { Console.WriteLine("GetX() veya GetY() içinde sıfıra bölme hatası"); return 0; } return x * y; } static void Main(string[] args) { int value = Calculate(); Console.WriteLine(value); } } Bir seviye daha detaya girelim. Main() metodu Calculate() metodunu çağırıyor. Calculate() metodu ise GetX() ve GetY() metodlarını çağırıyor. Calculate() içerisine hata kontrolü koysak ne olur? Bu kod yönetilebilir hatalara iyi bir örnek olabilir. Eğer sıfıra bölme hatası alınıyorsa kullanıcıya bunu uyaran bir hata mesajı ve geri dönüş değeri SIFIR verilir. Elbette Main() bloğu içinde de buna uygun kod yazılması gerekir. Eğer Calculate() metodunun geri dönüş değeri SIFIR ise bir hata var. Ama çağıran kişi bu hatanın ne olduğunu programatik olarak bilmiyor. Sadece bir hata olduğunu ve gerekli detayın ekrana yazıldığını biliyor. Sadece Calculate() metodunun bulunduğu bir kütüphane yazıyorsanız iyi bir yaklaşım olabilir.Ancak gene de başarılı ve yeterli değil. (Örnek: Windows API)
  • 15. İstisnalar ve Kullanımı class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { p = 0; } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); if (p == 0) throw new InvalidOperationException("GetGlobalParameter() metodu SIFIR değer döndürdü. Olası sebebi metodun içinde hatalı işlem yapılmış olması"); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); if (p == 0) throw new InvalidOperationException("GetGlobalParameter() metodu SIFIR değer döndürdü. Olası sebebi metodun içinde hatalı işlem yapılmış olması"); int Y = 100 / p; return Y; } static int Calculate() { int x = GetX(); int y = GetY(); return x * y; } static void Main(string[] args) { int value = Calculate(); Console.WriteLine(value); } Aynı şekilde GetX() ve GetY() içerisine de hata kontrolü konulabilir. Ancak buradaki yaklaşım çok başarılı olmayacaktır. Çünkü hataya sebep olan veri GetGlobalParameter() adlı metottan geliyor. Eğer olması gereken, GetGlobalParameter() metodunun hiçbir zaman SIFIR döndürmemesi ise, bu yönetmememiz gereken hatalara iyi bir örnek olabilir. GetGlobalParameter() metodu başkasına ait bir kütüphane içinde veya kullanıcının ekrandan giriş yaptığı değerlerden üretiliyorsa olası hatalara karşı kod yazmamız gerekir. Biraz daha iyileştirelim.
  • 16. İstisnalar ve Kullanımı class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { throw new InvalidOperationException("GetGlobalParameter() metodu SIFIR değer üretti. Kullanıcı hatası veya dış parametrelerden kaynaklı olabilir."); } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); int Y = 100 / p; return Y; } static int Calculate() { int x = GetX(); int y = GetY(); return x * y; } static void Main(string[] args) { int value = Calculate(); Console.WriteLine(value); } } Görüldüğü gibi en alt seviyeden en üst seviyeye kadar farklı yaklaşımlar uyguladık. Şu anda verilen hata doğru yerde, en az kod yazarak en çok bilgiyi veriyor. Ancak .Net Framework’üne ait bir hata tipi kullanıyoruz.
  • 17. İstisnalar ve Kullanımı public class GlobalParameterException : Exception { public GlobalParameterException(string message) : base(message) { } } class Program { static int GetGlobalParameter() { // Do some random calculation Random r = new Random(); int p = r.Next(-10, 10); // Do dome random calculation if (p < 0) { throw new GlobalParameterException("GetGlobalParameter() metodu SIFIR değer üretti. Kullanıcı hatası veya dış parametrelerden kaynaklı olabilir."); } else { p = p + 10; } return p; } static int GetX() { int p = GetGlobalParameter(); int X = 100 / p; return X; } static int GetY() { int p = GetGlobalParameter(); int Y = 100 / p; return Y; } static int Calculate() { int x = GetX(); int y = GetY(); return x * y; } static void Main(string[] args) { int value = 0; try { value = Calculate(); } catch (GlobalParameterException exception) { Console.WriteLine("Global parametrenin hesaplanması ile ilgili birhata alındı. Detay:"); Console.WriteLine(exception.Message); return; } Console.WriteLine(value); } } Artık kendimize ait bir hata tipimiz var. Başka bir kullanıcı hem hata tipini anlayabilir hem de gereken açıklamayı alabilir. Artık try-catch içerisinde ayırım da yapılabilir. Ayrıca sınıf içerisine ek kod yazarak daha çok bilgi toplayabilirsiniz. Sınıf metotlarını yani işi yapmak için çağırılacak metotları yazarken (bu örnekte Main() haricindekilerden bahsediyoruz) kodu bir başkasının kullanacağı şekilde yazmalısınız. Sadece siz kullanacak olsanız bile bu sınıfınızın daha sağlam olmasına yardımcı olur.
  • 18. Enterprise Design • Eğer çok büyük bir proje geliştiriyorsanız mimarinin içerisinde istisnaların yönetimi ayrı bir iş kalemi olacaktır. • İstisna yönetimi projenin her aşamasında kullanılacağı için dikey olarak konumlandırılır. • Yakalanan hataların kullanıcıya gösterilmesi, log tutulması, acil durumların email veya SMS ile haber verilmesi gibi işlerin tamamı bu katmanda yapılır ve ayrı bir kütüphane olarak düşünebilirsiniz.