Skip to content

Commit bbb3969

Browse files
committed
Added Chapter03 samples
1 parent 3d5e8b3 commit bbb3969

File tree

7 files changed

+350
-10
lines changed

7 files changed

+350
-10
lines changed

Azon.WeatherLib/Reporter.cs

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class Reporter
1212
// private City[] cities = new City[10];
1313
// İçerisinde City türünden elemanlar barındıracak bir List koleksiyonu.
1414
private List<City> cityList = [];
15+
1516
public void AddCity(City city)
1617
{
1718
cityList.Add(city);
@@ -29,6 +30,15 @@ public List<City> GetCityList()
2930
}
3031
public Temperature GetTemperature(string cityName)
3132
{
33+
/*
34+
Yeni eklenmeiş ama henüz içeriği yazılmamış metotlar söz konusu olduğunda,
35+
diğer programcıların veya object user'ların bu durumdan haberdar olması adına da
36+
NotImplementeException kullanılabilir.
37+
38+
throw ile çalışma zamanına (runtime) bir Exception nesnesi fırlatılabilir.
39+
new ile başlayan kısım Exception nesne örneğidir.
40+
Bu exception nesneleri bir try...catch mekanizması ile yakalanarak kontrol altına alınabilir.
41+
*/
3242
throw new NotImplementedException();
3343
}
3444

Chapter02/Program.cs

+23-7
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,30 @@ Temperature veri yapısı Azon.WeatherLib kütüphanesi içinde yer almaktadır.
1212
Temperature sınıfı object instance formasyonunda kullanılır. Yani önce new ile bir örnek oluşturulur.
1313
Sonra bu örneğin erişilebilir olan üyeleri(metotlar gibi) kullanılır.
1414
*/
15-
var currentWeatherValue = new Temperature(21, TemperatureType.Celcius);
16-
Console.WriteLine(currentWeatherValue);
17-
currentWeatherValue.ConvertToFahrenheit();
18-
Console.WriteLine(currentWeatherValue);
15+
//var currentWeatherValue = new Temperature(21, TemperatureType.Celcius);
16+
//Console.WriteLine(currentWeatherValue);
17+
//currentWeatherValue.ConvertToFahrenheit();
18+
//Console.WriteLine(currentWeatherValue);
1919

20-
Terminal.SplashScreen("Super Mario");
21-
Terminal.ShowMenu();
22-
Terminal.GetUserInput();
20+
//Terminal.SplashScreen("Super Mario");
21+
//Terminal.ShowMenu();
22+
//Terminal.GetUserInput();
23+
24+
var reporter = new Reporter();
25+
var ankara = new City("Ankara", new Temperature(14, TemperatureType.Celcius));
26+
reporter.AddCity(ankara);
27+
var tokyo = new City("Tokyo", new Temperature(24, TemperatureType.Celcius));
28+
reporter.AddCity(tokyo);
29+
reporter.AddCity(new City("İstanbul", new Temperature(16, TemperatureType.Celcius)));
30+
31+
var cities = reporter.GetCityList();
32+
foreach (var city in cities)
33+
{
34+
Console.WriteLine($"City: {city}");
35+
}
36+
37+
var ankaraTemprature = reporter.GetTemperature("ankara");
38+
Console.WriteLine("{0}", ankaraTemprature);
2339
}
2440
}
2541
}

Chapter03/Chapter03.csproj

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
</Project>

Chapter03/GameWorld.cs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace Chapter03
2+
{
3+
/*
4+
GameObject sınıfımız oyun sahasındaki nesnelerimizin ortak özellik ve fonksiyonlarını sağlayan bir
5+
base tür olarak düşünebiliriz.
6+
7+
Plane ve Player sınıfları GameObject tipinden türemişlerdir ve bu nedenle X,Y özelliklerine ve Draw metoduna sahiptirler.
8+
Ama aynı zamanda Plane nesnesinin ve Player nesnesinin kendisine has özellik ve metotları vardır.
9+
10+
C#, sınıflar üzerinden çok kalıtımı(multi-inheritance) desteklemez ancak bu Interface kullanımları ile mümkün olabilir.
11+
*/
12+
public class GameObject
13+
{
14+
public int X { get; set; }
15+
public int Y { get; set; }
16+
/*
17+
Draw metodu virtual tanımlanmıştır, varsayılan(default) bir davranışı vardır
18+
ama isterseniz türeyen sınıfta bu davranışı değiştirebilirsiniz(override)
19+
*/
20+
public virtual void Draw()
21+
{
22+
Console.WriteLine("Nesne çizdirme operasyonu yapılıyor");
23+
}
24+
}
25+
public class Plane : GameObject
26+
{
27+
public int Alttitude { get; set; }
28+
public double Health { get; set; }
29+
public void Fire()
30+
{
31+
Console.WriteLine("Uçak ateş ediyor");
32+
}
33+
/*
34+
Plane nesnesi için GameObject'te tanımlı Draw metodu ezilmiş ve işleyişi değiştirilmiştir.
35+
*/
36+
public override void Draw()
37+
{
38+
Console.WriteLine("Uçak çiziliyor");
39+
}
40+
}
41+
public class Player : GameObject
42+
{
43+
public string Name { get; set; }
44+
public double Power { get; set; }
45+
public void SayGreetings()
46+
{
47+
Console.WriteLine("Oyuncu sizi selamlıyor");
48+
}
49+
public void Jump()
50+
{
51+
Console.WriteLine("Oyuncu zıplıyor");
52+
}
53+
}
54+
}

Chapter03/HttpManager.cs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace Chapter03
2+
{
3+
/*
4+
HttpManager sınıfının görevi belli url'ler için çeşitli işlemleri gerçekleştirmek olsun.
5+
Örneğin bir web servisine veri göndermek ve cevap almak gibi(Send)
6+
Basit olması açısından sadece string türle çalıştık.
7+
*/
8+
public class HttpManager
9+
{
10+
public string Send(string url, string data)
11+
{
12+
Console.WriteLine($"{url} adresine mesaj gönderilecek");
13+
14+
// Url bilgisi boş veya null ise ya da https:// ile başlamıyorsa ortama exception fırlat
15+
if (string.IsNullOrEmpty(url) || !url.StartsWith("https://"))
16+
{
17+
throw new InvalidUrlException(url);
18+
}
19+
return "Http OK(200)";
20+
}
21+
}
22+
23+
/*
24+
InvalidUrlException sınıfının bir Exception olarak throw edilebilmesi için
25+
Exception sınıfından türemesi(inherit) yeterlidir. Bu sayede Exception sınıfındaki bazı ortak
26+
özellik ve metotlara da sahip olur. Yani kendi exception nesnelerimiz için sahip olmaları gereken
27+
üyeleri tekrardan yazmak zorunda kalmayız. Bunları base type karşılar.
28+
*/
29+
public class InvalidUrlException
30+
: Exception
31+
{
32+
/*
33+
base keyword, bir üst sınıfı işaret eder.
34+
Şu anki senaryoda base ile Exception sınıfı ifade edilir.
35+
constructor' da yaptığımız kullanıma göre base türün yani Exception sınıfının constructor metodu
36+
çağırılır.
37+
*/
38+
public InvalidUrlException(string url)
39+
: base($"{url} bilgisi geçersiz.")
40+
{
41+
}
42+
}
43+
}

Chapter03/Program.cs

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
using System.Data;
2+
3+
namespace Chapter03
4+
{
5+
/*
6+
Kalıtım konusuna geçmeden önce bununu .Net içerisinde uygulandığı Exception sistemini ele alıyoruz.
7+
8+
Exception'lar çalışma zamanında ortaya çıkan hata nesneleridir. Herhangibi sebeple ortama fırlatılabilirler (throw)
9+
Exception'lar çalışma zamanı tarafından kontrol altına alınabilirler. Bunun için try...catch...finally blokları kullanılır.
10+
11+
Kalıtım ile olan ilişkisi:
12+
Tüm istisna türleri Exception süper sınıfından türer(devralınır) Buna göre kendi istisna sınıflarımızı da yazabiliriz.
13+
14+
try..catch blokları olası çalışma zamanı istisnalarını kontrol altına almak için ideal yapılardır ama bu bütün işleyişi
15+
try blokları ile yönetmek anlamına gelmemelidir zira bu mekanizmanın bir çalışma zamanı maliyeti var.
16+
17+
Bütün Exception türleri Exception kelimesi ile biter(Bu bir isimlendirme standartı)
18+
19+
*/
20+
internal class Program
21+
{
22+
static void Main(string[] args)
23+
{
24+
// try bloğunda olabilecek hatalar(exception) catch bloklarınca yakalanabilir ve program akışı kontrollü bir hale getirilebilir
25+
try
26+
{
27+
// double result = Div(10, 0); // Eğer DivideByZeroException hatası kontrol altına alınmazsa burada program crash olur.
28+
// Eğer bir exception oluşursa, try bloğu içerisinde geri kalan kod satırları işletilmez, doğrudan catch bloğuna gidilir
29+
30+
// FileNotFoundException oluşur. Çünkü sistem böyle bir dosyamız yok
31+
// Built-in gelen metotlarda ne tür exception'lar fırlatılabileceğine bir bakmakta yarar var.
32+
// var f = File.OpenRead("C:\\unknown_file.data"); // Sistemden bir dosya okumak üzere açılmak istenir
33+
34+
// throw new ArgumentException("Argüman hatası");
35+
36+
//var silo = new HttpManager();
37+
//var result = silo.Send("http://movies.api/action/12", "");
38+
//Console.WriteLine(result);
39+
40+
/*
41+
Plane is a GameObject.
42+
43+
vecihi değişkeni üzerinden GameObject'teki X,Y özelliklerine erişebilir
44+
Draw metodunu çağırabiliriz ve ayrıca kendi metotlarını da kullanabiliriz.
45+
*/
46+
Plane vecihi = new Plane { X = 10, Y = 20 };
47+
vecihi.Draw(); //base class metodu
48+
vecihi.Fire(); // kendi metodu
49+
50+
Player mario = new Player { X = 11, Y = 12 };
51+
mario.Draw(); // base class metodu
52+
mario.Jump(); //Kendi metodu
53+
54+
GameObject go1 = vecihi; // Bu atama mümkündür çünkü vecihi bir Plane nesnesidir ve Plane nesnesi de bir GameObject' tir.
55+
/*
56+
Plane nesnesinde, GameObject'ten devralınan Draw metodu ezildiği için(override),
57+
go1 değişkeni(GameObject) üstünden yapılan Draw çağrısı, alt sınıfın ezilmiş olan Draw metodunu işletilir.
58+
Yani GameObject, Plane nesnesi gibi davranış sergiler ve bunun adı da Çok Biçimliliktir(Polymorphism)
59+
60+
Ancak tam aksine go2 yine GameObject'ten türeyen Player nesnesi olarak taşınsada Draw operasyonu Player nesnesinde yeniden
61+
yazılmadığından, go2 tam anlamıyla Player gibi davranış sergilemez.
62+
63+
Bir nesnenin çok biçimli olması neden önemli olabilir?
64+
*/
65+
go1.Draw();
66+
GameObject go2 = mario; // Doğal olarak bu da mümkündür.
67+
go2.Draw();
68+
69+
}
70+
catch (DivideByZeroException ex) // Sıfıra bölme hatası oluşursa bu blok çalışacak
71+
{
72+
Console.WriteLine(ex.Message);
73+
}
74+
catch (FileNotFoundException ex)
75+
{
76+
Console.WriteLine(ex.Message);
77+
}
78+
catch (InvalidUrlException ex)
79+
{
80+
Console.WriteLine(ex.Message);
81+
}
82+
catch (Exception ex) // try bloğunda ele alınmamış bir Exception söz konusu ise bu blok çalıştırılır
83+
{
84+
// Exception, diğer tüm Exception nesnelerini çevreler
85+
Console.WriteLine(ex.Message);
86+
}
87+
finally
88+
{
89+
/*
90+
Genellikle kaynakların(resource) geri iadesi(database bağlantısı açılmış olabilir, ağ bağlantıları vardır,
91+
bellekten toplanması gereken nesneler olabilir) gibi durumlarda kullanışlıdır
92+
93+
ya da programın bir önceki state'e döndürülmesi için de ele alınır.
94+
*/
95+
Console.WriteLine("try bloğundaki kod parçasında hata olsa olmasa da çalışır");
96+
}
97+
Console.WriteLine("Program sonu");
98+
}
99+
100+
/*
101+
Bir sonraki derste tekrar ele alalım.
102+
*/
103+
static void DrawLevel(string level,List<GameObject> gameObjects)
104+
{
105+
foreach (var go in gameObjects)
106+
{
107+
go.Draw();
108+
}
109+
}
110+
111+
/*
112+
Soru: Div fonksiyonundaki olası sıfıra bölme hatası Exception mekanizmasına bırakılmadan giderilebilir mi?
113+
114+
*/
115+
//static int Div(int x, int y)
116+
//{
117+
// return x / y; // Muhtemele DivideByZeroException
118+
//}
119+
120+
/*
121+
Aşağıdaki metotda çok bariz olarak bilinen sıfıra bölme hatası daha kontrollü bir şekilde ele alınmış
122+
ve Exception kullanımından kaçınılmıştır.
123+
124+
! Mümkün mertebe Exception kullanımından kaçınmak lazım. Yani bir kontrolü Exception
125+
*/
126+
static Response Div(int x, int y)
127+
{
128+
if (y == 0)
129+
{
130+
return new Response
131+
{
132+
Value = 0,
133+
IsSuccess = false,
134+
ErrorMessage = "Sıfıra bölme hatası"
135+
};
136+
}
137+
return new Response
138+
{
139+
Value = x / y,
140+
IsSuccess = true,
141+
ErrorMessage = string.Empty
142+
};
143+
}
144+
static Response GetAccountInfo(int accountNumber)
145+
{
146+
return new Response
147+
{
148+
Value = new Account(),
149+
IsSuccess = true,
150+
ErrorMessage = string.Empty
151+
};
152+
}
153+
154+
/*
155+
SaveInvoice fonksiyonu bir business domain metodu olabilir. Örneğin finansal işlemlerin yapıldığı ya da bir muhasebe paketinin parçası olabilir.
156+
Fatura kaydetme adımının içerisinde oluşabilecek birçok sorun vardır.
157+
Faturalanacak tutar geçersiz olabilir, müşteri numarası hatalı olabilir, müşterinin limiti geçersiz olabilir vb
158+
Bu gibi iş kuralları söz konusu olduğunda geriye sadece işlemin başarılı olup olmadığına dair true veya false döndürmek yerine,
159+
nesne kullanıcısının (object user) durumla ilişkili detay bilgi almasını sağlayacak(işlem sonucu ile ilgili asıl dönecek veriyi de içerecek şekilde)
160+
bir dönüş türü kullanmak daha mantıklıdır.
161+
Response sınıfının buradaki geliştirilme sebebi de budur.
162+
*/
163+
static Response SaveInvoice(double amount, int customerId)
164+
{
165+
// Aşağıdaki durumlar business case'ler.
166+
// customerId geçersizse false dön
167+
// amount geçersizse false dön
168+
// amount, müşterinin limiti dışında ise false dön
169+
170+
return new Response
171+
{
172+
IsSuccess = false,
173+
Value = amount,
174+
ErrorMessage = "Müşteri limiti yetersiz olduğu için işlem yapılamıyor"
175+
};
176+
}
177+
}
178+
}
179+
/*
180+
Response gibi bir sınıfa neden ihtiyacımız olsun?
181+
182+
Araştırma konusu olarak Response ve Output pattern'ler incelenebilir.
183+
*/
184+
class Response
185+
{
186+
/*
187+
Bütün nesneler bir şekilde Object sınıfından türediğinden, Value özelliğine herhangibir nesne atanabilir.
188+
Div metodundaki int sonucu veya GetAccountInfo'daki Account nesnesi vb...
189+
Ancak bu tehlikelidir(Neden?) Çünkü bu, Value özelliğine alakalı olmayan nesneleri de verebileceğimiz anlamına gelir.
190+
Yani Account döndürmesi gerektiği yerde float dönebilir...
191+
192+
Value özelliğinin daha kısıtlı bir kümede değer döndürmesini sağlamak istersek generic mimariden ve generic contstraint'lerden yararlanabiliriz.
193+
Generic konusunu sonraki derste işleyeceğiz.
194+
*/
195+
public object Value { get; set; }
196+
public bool IsSuccess { get; set; }
197+
public string ErrorMessage { get; set; }
198+
}
199+
class Account // Sembolik bir sınıf olarak tasarlandı
200+
{
201+
}

0 commit comments

Comments
 (0)