29 Aralık 2022 Perşembe

Init-Only, Get-Only, ve Readonly

 C# da field ve propertylerde unchancing state bildirmenin 3 farklı yolu vardır. Yani nesne create edildikten sonra artık property değerleri değiştirilemez.

Read Only Keyword
readonly keywordu değeri ya declare edildiği yerde yada constructer içerinde verilir ve bu değer bir daha değiştirilemez. 

Yukarıdaki örneği incelersek eğer, readonly olan sayac ve myList ve readonly olmayan myList2 isminde 3 adet declaremiz var. Bunlardan read only olan sayac ve myListin değeri declare edildiği yerde yada constructer içerisnde verilir ve bir daha değiştirilemez. Fakat myList2 readonly tanımlanmadığı için chance metodu içersinde bu myList2 referansına heapden başka bir yer tahsisi oluşturulabildi. Fakat sayac ve myList artık değiştirilemez. Sayacın değeri 8, myListin referensıda artık sabittir. Artık hiç bir yerde myList = new List<string>();  yapamayız. Burası çok önemli. Fakat readonly demek bu listeye yeni elemanlar eklenemez demek değildir. readonly olarak tanımlanmış bir listeye myList.Add("yeni eleman") şeklinde ekleme yapılabilir. Yada remove işlemi yapılabilir.

Get-only Auto-Properties
Bu yapı readonly yapısının benzeridir. Yukarıdaki sayac fieldının değeri sadece constructer üzerinden yapılması ve bir daha değiştirilememesi istenirse aşağıdaki gibi yapabiliriz.





Init Only Setters


Pet myPet = new Pet("Cairn Terrier", 2016, "Jester");
Yukarıdaki gibi bir kod yazdığımızda her yeni eklenen property için constructer daha da büyüyecek bunun yerine aşağıdaki şekilde yazabiliriz.




Yukarıdaki gibi nesne initial edildikten sonra Breed, BirthYear ve Name değerleri değiştirilemez.

İnit-Only çok sayıda parametreyi constructera geçmeye bir alternatif sunarlar, bu da sınıflarınızı basitleştirebilir ve yaratımlarını daha okunaklı hale getirebilir.


SONUÇ
Bir nesne oluşturulduktan sonra bir değerin değişmeyeceğini garanti etmek istiyorsanız, readonly, a get-only auto property, yada  init-only setter  kullanabiliri, Peki hangisi doğru? 

1- Bir değeri depolamak istiyorsam ancak bunu bir property olarak göstermem gerekmiyorsa, readonly  bir field kullanırım.

2- Bir sınıf için az sayıda required attributes varsa ve bu listenin büyümesini beklemiyorsam, get only auto-propertyi kullanırım.

3- Çok sayıda property varsa ve zaman içinde büyümeye devam edecekse init-only kullanırım




23 Aralık 2022 Cuma

Exception

 Exception hangding de yapılan hatalar

1: Exceptionu Yakalamamak( Not Catching Exceptions

Yapılan ilk büyük hata kod içerisindeki Exceptionları yakalamamaktır.
Geliştiriciden kaynaklı pek çok exception olsa da (NullReferenceException, IndexOutOfRangeException, ArgumentException, InvalidOperationException, vb.), hiçbir geliştiricinin oluşmasını engelleyemeyeceği exceptionlar da vardır.

Örneğin, dosyalarla çalışırken gerekli dosya mevcut olmayabilir, kullanıcının dosyayı açma izni olmayabilir, dosya bozuk veya kilitli olabilir veya sabit sürücüde disk alanı bitebilir. Tüm bu sorunlar, developerların oluşmasını engellemesi pek de mümkün olmayan exceptionlara örnektir.

  • Connecting to external APIs
  • Connecting to database
  • Executing SQL statements
  • Working with operating system
  • Requesting resources over the internet 
  • Working with hardware devices such as cameras or microphones
Tüm bu senaryolar, Yazılımcının meydana gelebilecek belirli bir özel durum için bir catch yan tümcesi ekleyerek hesaba katması gereken şeylerdir.


Yukarıdaki gibi yazmak yerine;



Bu şekilde kodunuz yalnızca beklenen senaryolar için doğru şekilde çalışmakla kalmaz, aynı zamanda sorunları incelikle kurtarabilir ve son kullanıcıya iletebilir.

2:Exception Fırlatmamak( Not Throwing Exceptions )
Exceptionları yakalamamak(catch etmemek) kırılgan bir uygulamaya yol açabilirken, Exceptionları fırlatmamak(throw)  da bir hata akışına yol açabilir.

Kodunuzun güvenilir bir şekilde iyi bir sonuç elde edemediği bir senaryo ile karşılaşırsanız, bir exception oluşturmak, daha sonra kodunuzun kararlarının sonuçları arasında gezinmek yerine bu kötü senaryoyu hemen keşfetmenize yardımcı olabilir.

3: Catch Exception and Throwing Exception
Genel bir Exception yakalamak yada geriye Genel bir throw exception göndermek doğru değildir.


Yukarıdaki kod , sorunları erken tespit eder ve bu sorunları bir Exceptionda ortaya çıkarır. Bu iyi bir şeydir.

Fakat  bu kod, ArgumentOutOfRangeException veya InvalidOperationException gibi belirli bir exception oluşturmaz. Bunun yerine, bu kod, Exception sınıfının bir örneğini fırlatır.

Genel bir exception fırlatmak yerine, yukarıdaki kodun bir catch bloğu tarafından özel olarak yakalanıp işlenebilecek daha spesifik bir exception atmış olması gerekirdi.


 4: Incorrectly Rethrowing Exceptions

İşte bu kod doğru gibi görünüyor. Ancak, yukarıdaki throw ex sözdizimi kötü bir uygulamadır. Yukarıdaki hatanın bu metodu çağıran yer tarafından yakalanmasını sağlamaktan başka bir şey yapmıyor.

Bununla birlikte, bu kod, exceptionun nerede meydana geldiğine ilişkin olarak önceden sahip olduğumuz herhangi bir önceki bağlamı da kaldırır. Exceptionun call stacki, exceptionun orijinal olarak meydana geldiği yerde değil, catch bloğunun içinde başlayacaktır.

yukarıdaki yapı güncellenirse;

Exceptionun call stackini  değiştirmeden yukarı doğru yayılmasına sağlamış oluyoruz. Böylece  Exceptionu handle eden kod için exceptionun tüm ayrıntılarını korumuş olacağız.

5: Catching Exceptions in the Wrong Place
Exceptionları  yakalamak için temel kurallarımdan biri, exceptionları yalnızca onlardan doğru bir şekilde kurtarabileceğiniz yerlerde yakalamaktır.

Exception oluşturabileceğini bildiğimiz bir kod satırında try/catch yazma mecburiyetimiz yoktur.

Bunun yerine, içinde bulunduğunuz metodu call eden kodun, istisnai durumlara tepki vermek için daha iyi donanımlıysa try/catch bloğunu oraya koyabiliriz.

6: Using Exceptions for Flow Control
- Exception, gerçekten sıra dışı olan ve yalnızca nadir durumlarda ortaya çıkabilen, program yürütmenin normal bir parçası olmayan bir şeydir.
- Sonuç olarak özetlenen şey şudur: İstisnalar gerçekten istisnai olmalıdır.

İstisnaların kullanımına iyi örnekler:
  • A class requires a parameter that has a valid value and was given an invalid one
  • The system needs to talk to the database, but the database appears to be offline
  • The file the user is trying to load is not in the correct format

7: Not Using Custom Exceptions
Dotnet, aşağıdakiler de dahil olmak üzere çeşitli durumlarda kullanıma uygun çok çeşitli istisna türleri sunar:
  • ArgumentException
  • InvalidOperationException
  • FormatException
Ancak, bir istisna atmanız gereken ve built-in exceptionların hiçbirinin mantıklı olmadığı bazı yerler vardır.

Bu durumlarda, özel istisnanızı temsil eden yeni bir sınıf oluşturmak ve Exception sınıfından  miras almak mantıklı olabilir.

8: Not Providing Enough Exception Details
Çoğu durumda bir istisna atmak yeterli değildir. İstisnalar yakalandığında onlara tepki verebilmemiz gerekir.

İstisnalara tepki vermek genellikle şunları gerektirir:
  • İstisnanın nerede meydana geldiğini bilmek (the stack trace)
  • İstisnanın tam type ını bilmek (the GetType method helps with this)
  • İstisna için yararlı bir mesaja sahip olmak
  • Meydana gelen istisnaya özel ek ayrıntılara sahip olmak
Aşağıdaki kod, bir istisna oluştururken yeterli bilgi sağlamamanın bir örneğidir:



Bu kod, amountun pozitif olmadığı, ancak onu yakalayan herhangi bir kodun son kullanıcıya bilgi görüntülemek veya hata loguna uygun bir mesaj kaydetmek için ilgili ayrıntılara sahip olmadığı durumları başarıyla ele alır.

Daha iyi bir uygulama şöyle olacaktır:


Bu durumda, geçersiz parametrenin adını, o parametrenin değerini ve faydalı bir hata mesajı sağlıyoruz.


REFERENCE

21 Aralık 2022 Çarşamba

AsSplitQuery

Student ve Course sınıfları arasında one - to - many ilişki olduğunu düşünelim.

Split Query Kullanmazsak;
yukarıdaki sorgu için veritabanına  Course ve Student sınıflarının joinlemiş halde tek bir sorgusu gidecektir.




result olarakda;

Burada join kullanıldıgı zaman kartezyen çarpım oluşur ve geriye joinlemiş bir result döner. Bu join maliyetinden kurtulmak için AsSplitQuery kullanılabilir.


Split Qery Kullanırsak

Yukarıdaki gibi kullanırsak EF Core 2 adet query oluşturcak.
İlk query sadece Course ile ilgili dataları çekecek
ikinci query ise sadece Student ile ilgili dataları çekecek.





Gördüğümüz gibi, SpliQuery ile Course"Name" yalnızca bir kez döndürüldü. Bu, daha fazla sütun ve daha fazla ilişki içeren daha complex sorgularımız olsa bile, verilerin tekrarlanmayacağını ve bunun da çok daha performanslı bir sorgu ile sonuçlanacağı anlamına gelir.


Query olarak Split Query Ekleme




Global olarak Split Query Ekleme

REFERENCE

19 Aralık 2022 Pazartesi

CAP Teoremi

CAP teoremi, dağıtık bir sistemin en çok istenen üç özellikten sadece ikisini sağlayabileceğini söyler. Bu özellikler Tutarlılık (Consistency), Erişilebilirlik (Availability) ve Bölünme Toleransı (Partition Tolerance)‘dır. Bu özelliklerden sadece ikisinin üst düzeyde sağlanabileceğini bilmek, bize ihtiyaçlarımıza uygun dağıtık sistemi seçmekte yardımcı olacaktır.





Consistency (Tutarlılık) :Bütün istemcilerin bağlandıkları düğümden bağımsız olarak aynı anda aynı verileri göreceği anlamına gelir. Bunun gerçekleşmesi için, bir düğüme her veri yazılışında, yazma 'başarılı' olarak kabul edilmeden önce verilerin sistemdeki diğer bütün düğümlere anında iletilmesi ya da eşlenmesi gerekir.
Sisteme iletilen herhangi bir okuma isteği her koşulda ilgili kayıt için yapılmış olan son güncel değeri getirebiliyor olmalıdır.Eğer getirilemiyorsa hata verilmeli ve asla güncelliğinden şüphe edilen veriler talep eden taraflarla paylaşılmamalıdır.

Availability (Kullanılabilirlik):Tüm serverlar tüm requestlere doğru ya da hatalı sonuç dönebiliyor mu? Eğer dönebiliyorsa available diyebiliriz. Burada hatalı sonuç dönmekten kasıt aslında tutarlı yani güncel olmayan bir sonuç dönmektir. Yani serverlarınız ya günceldir (consistent)  doğru sonuç döner ya da güncel değildir ve güncel olmayan sonuç döner. İki durumda da server avaliable’dır diyebiliriz.

Partition Tolerance (Hata Toleransı) : 
Burada partition ile kastedilen aslında network bölünmesidir. Yani sisteminizin parçalarının farklı networklerde bulunma durumudur.
Partition Tolerance ise nodelar arasında yaşanabilecek herhangi bir iletişim sorunu durumunda sistemin hayatına devam edebilmesidir.
Bir node başka nodelarla iletişim sorunu yaşarken, bir istemci tarafından direkt olarak erişilebilir durumda olabilir. Bu da ilgili node üzerinde yapılabilecek olan herhangi bir işlemden diğer nodeların haberdar olamaması ya da haberdar etmenin zorunlu olduğu koşullarda ise erişilebilir olamaması anlamına gelir.

(CA) İse Neden (P) olamıyor
Sunucularınızın arasındaki ağ bağlantısı gitmiş. Siz gittiniz birinci sunucuya yazdınız, yukarıdaki resimde görüldüğü gibi diğer sunuculara verinin güncel halini gönderemedi. 2nci, 3ncü sunucuya veriyi sorduğunuzda verinin olmadığını veya 1nci sunucu ile aynı olamadığını göreceksiniz. Yani sistem CA olduğu zaman P(Partition Tolerance) olamıyor. 
Veriniz parçalanmaya toleranslı değil.Verinin doğruluğunun kesin olmasını istediğimiz Müşteri işlemleri, finansal işlemler vb. bu çok önemlidir. İlişkisel veritabanları ve transactional işlemler buna uygun veriler tutar.

(AP) İse Neden (C) olamıyor
2 sunucunuz(server) olduğunu düşünelim X değeri 2 sunucuda da bulunuyor. Sunucular arası ağınız çöktü. Sunuculardan birinde X değerini güncellediniz. Sorguladığınızda iki sunucu ayrı değer vereceği için bu durumda C(Consistent) olamıyor. Bir sunucu X değeri için 5 , bir diğeri 4 değerini dönebilir.
Sosyal medyadan twitter veya facebook akan verilerde bunlar kullanılabilir. Like sayısını düşünün o anda her kişinin doğru şekilde görmesi/görmemesi önemli değildir. Burada bu veriler parçalanarak tutulabilir. NoSQL veritabanlarından Cassandra, Dynamo gibi sistemler buna uygundur. Eventual Consistency yöntemi ile arkaplanda Node’lardaki veriler eşleştirilir. Bu eşleştirmeden önce yapılan sorgularda veri değerlerinde tutarsızlıklar olabilir.

(CP) İse Neden (A) olamıyor
Eğer amacınız hem tutarlılık, hemde verinin parçalara bölünerek kaydedilebilmesi ise. 3 sunucu arasında bağlantı koptuğu andan itibaren A(Availibility) yazma özelliğiniz ortadan kalkacaktır. Eğer ki yazarsanız tutarlılığı bozarsınız. Bu yüzden sadece okuma yapabilirsiniz bu durumda.
MongoDB veritabanı gibi sistemler CP uygundur. Default’ta strongly consistent’ dır.

Sisteminizde nodelar arasında eğer bir iletişim sorunu yaşanıyorsa aşağıdaki şu iki duruma karar vermeniz gerekiyor.Mevcut operasyonu iptal et, sistemin tutarlılığını sağlamış ol ancak erişilebilir olmaktan vazgeç.

1 - Mevcut operasyonu iptal et, sistemin tutarlılığını sağlamış ol ancak erişilebilir olmaktan vazgeç.
2 - Mevcut operasyonu ve sistemdeki tüm nodeların o anda aynı veriye sahip olamayacağını kabul et ve yüksek erişilebilirlik sağlamaya çalış.

15 Aralık 2022 Perşembe

Message Queue vs Message Broker

Microservis Mimarisi, farklı taskları yerine getiren çok sayıda küçük uygulamadan oluşan bir sisteme sahip olmaktır. Bu farklı uygulamalar bir biriyle nasıl iletişime geçecekler ?

Message Queue

Queue, FIFO yapısıyla çalışan bir yapıdır. 
Elimizde bir pipe(boru) olduğunu düşünelim. İki kişi karşılıklı olarak bu boruyu tutuyor olsun. Bu borunun bir ucundan message gönderiyoruz ve bu mesaj borunun diğer ucundan çıkıyor. Queue bu şekilde First In First Out olarak çalışır.

Messageler iletmek istediğimiz bilgi parçalarıdır. Queuedaki bilgiler doğru servis tarafından consume edilene kadar saklanırlar. Message Queue farklı servisler arasında asenkron iletişim yapabilmeyi sağlarlar.  Bilgi gönderilirken producer kesintisiz olarak çalışmaya devam edebilir ve consumer kendi istediği hızda bu queudaki bilgeleri tüketebilir.


Message Broker

Farklı uygulamalar arasında kararlı(stable) ve güvenilir(reliable) iletişim kurmasını sağlayan bir yazılım aracıdır. İletişim kurmak isteyen uygulamalar farklı dillerde ve farklı teknolojileri kullanıyor olabilirler. Bunlar arasındaki mesaj protokolunu ve iletişimi sağlamak message brokerın işidir.

Bunlara ek olarak Mesage Brokerlar Bilgileri depolar(store), yönlendirir(route) ve istenen hedefe iletirler(delivery). Publisher, bu mesajların consumerlarının kim olduğunu, kaç tane olduğunu ve bu consumerların o anda aktif olup olmadığını bilmeden mesaj gönderebilirler.

Point-to-point messaging, message queueları consumer ve publisher arasında one - to - one olacak şekilde kullanılır. Mesajın bir kez gönderileceğini ve bir kez gönderilip tüketileceğini garanti etmek istediğimizde kullanırız. Finansal işlemlerle çalışırken tercih edilebilir. Order,Payment vs.

The publish-subscribe messaging, producer mesajı bir topice gönderir ve bu topice abone olan tüm consumerlar bu mesajı alabilir. one to many.


Message queue vs message broker

Bir message queue, kuyruk veri yapısını kullanarak mesajlar göndererek, alarak ve depolayarak uygulamalar arasındaki iletişimi kolaylaştırır. Data transfer  için message queueları kullansak da onlar taşıdıkları bilgileri okuyamazlar.

Bir messge broker, basitçe message queueların kullanımını genişleten bir mekanizmadır. Mesaj kuyruklarından farklı olarak, mesaj brokerlar bunlar aracılığıyla taşınan bilgilerin içeriğini okuyabilir. Ayrıca, mesaj brokerlar her türlü kaynaktan gelen bilgileri işleyebilir. Örneğin, File veya HTTP requestten okunan bilgiler.

Basitçe söylemek gerekirse, message queue, üretilen veriyi tüketilinceye kadar saklayan bir yapıdır ve mesaj broker, mesaj kuyruklarını yöneten bir yazılım bileşenidir.

Bir mikro hizmet mimarisinde, her bir mikro servis diğerlerinden farklı işlevler sunar. Ancak, diğer servislerle iletişim halinde olmadan bu işlevleri gerçekleştiremezler. Message Queuelar, uygulamaların kuyruğa bilgi göndermesi için bir yol sağlar. Message Brokerlar, bilgiyi göndericiden alır, gerekirse farklı mesajlaşma protokolleri arasında çevirir ve mesajı doğru alıcıya iletir.







Exchangeler brokerların giriş noktaları, message queularda brokerların çıkış noktası olarak düşünebiliriz. Publisher mesajı excahngelere gönderir, exchange de mesajları belirlenen kurallara göre gerekli kuyruklara iletir. Consumerlarda mesaja kuyrukları ile iletişim halindedir.

RabbitMQ bu topolojiye çok benzer bir yapı ile çalışmaktadır. Herbir tüketicinin kendine ait kuyruğu vardır. Exchange üzerine gönderilen mesajların birer örnekleri bu kuyruklarda saklanmaktadır. Bir başka tüketici başkasına ait olan kuyruk üzerinden mesaj okumaz. Tüketici mesajı işledikten sonra bu mesajın bir işlevi kalmaz. Bu sebeple tüketicinin işlemi bittikten sonra kuyruktaki mesaj yok edilir.

Kafka ise yukarıdaki topolojiyi biraz daha farklı bir yapı ile sunmaktadır. Mesajlar ayrı kuyruklarda değildir. Buna karşın tüketiciler mesaj kuyrukları üzerinde kaldıkları yerleri kendi işaretleyicileriyle belirlerler. Tüketici bir mesajı işledikten sonra işaretçisini ilerletir. Başka bir tüketici de bu mesajı işleyebileceği için mesajlar kuyruklardan silinmez. İşaretçiler aracılığı ile birden fazla kuyruk varmış gibi bir davranış sergilenir.

14 Aralık 2022 Çarşamba

Yield Keyword

 


Bir class'ın foreach iterasyonuna sahip olabilmesi için IEnumerable interfacesini implement etmesi gerekmektedir. Bunun yerine yield keywordu kullanılabilir.



13 Aralık 2022 Salı

Repositoryde Return Type Ne Olmalıdır : IQueryable, IEnumerable or IReadOnlyList?




IEnumerable ve IQueryable  çoğu geliştirici tarafından kullanımı karıştırılmakta ve ne zaman nerede kullanılacağı bilinmemektedir.  Kod yazım tipleri birbirine çok benzerdir. Fakat kullanım yerleri işlevselliklerine göre değişir. Yanlış kullanımlar sistem performansını oldukça kötü etkiler.

Repository kullanarak Get ile bir Domain Object Collectionu (GetUsers, GetProduct) geriye dönmek istediğimizde bir kaç dönüş türü arasında seçim yapabiliriz.

  • IQueryable<T>
  • IEnumerable<T>
  • IReadOnlyList<T>
Yukarıdaki return typelerden herhangi birini seçmemiz uygulamamızın performansını, tasarımını ve sürdürülebilirliğini etkileyebilir. Bu nedenle bilinçli bir seçim  yaparak projemizin Access Layerını oluşturmalıyız.

Yukarıdaki bir User sınıfımız ve AppDBContext isminde bir contextimiz olduğunu düşünelim.

IQueryable<T> Return Type

IQueryable<T> interfacesi, C# expressionlarını direkt olarak veritabanı tarafında execute edilebilecek T-SQL sorgularına dönüştürmemize olanak tanır. 
Fakat burada yazılan sorgunun sonuna ToList() demedikçe databaseye sorgu atılmayacaktır.



Yukarıda GetUsers() metodunun resultı bizim için hazır bir T-SQL sorgudur. Henüz databaseden kayıt çekilmemiştir.



Önemli Detaylar
  • Veritabanı sorgusu, yalnızca sonuç gerçekten istendiğinde execute edildi.(GetUsers() ta değil, yalnızca ToList() yöntemi çağrılırken).
  • Where ifadeleri ekleyerek sorgu hazırlanmaya devam ediyoruz. Hala veritabanından kayıt çekmedik
  • ToList() metodunu ekleyerek artık filtrelerle( where vs.)  hazırladığımız sorguyu veritabanına gönderiyoruz.
Yukarıdaki şekilde bir tane Repository içerisine  GetUsers() metodu yazılır ve bu repositoryi kullanan  her yerden GetUserrs() metodunu çağırıp where koşulu eklenerek istenen sorgular dinamik bir şekilde hazırlanabilir. Fakat bu kullanımında dez avantajları vardır.

1- Dublicate Domain Rules

Örneğin Aktif kullanıcı listesi diye bir Domain kuralımız olduğunu ve kuralın bir çok servis tarafından kullanıldığını düşünelim. Tüm servislerin içerisinde aşağıdaki gibi kullanılsın.


Daha sonra aktif userın domain kuralın değiştiğini ve son bir yıldan önce kaydedilmiş kişilerin aktif user olduğu kuralı eklediğimizi düşünelin. Yukarıdaki kodun geçtiği her yere gidip güncelleme yapmamız aşağıdaki şekilde güncelleme yapmamız gerekecektir.


Bu nedenle, codebase bakımı daha zor hale gelir çünkü birkaç yerin güncellenmesi gerekir ve bir şeyler kolayca gözden kaçabilir.


IEnumerable<T> Return Type

IEnumrable<T> yapılan sorgularda filtreler(where vs.) T-SQL sorgusuna çevrilmez. İlk olarak DB den bütün kayıtlar çekilir ve belleğe kaydedilir. Daha sonra bu belleğe alınmış kayıtlar üzerinde filtreler yani where koşulları  uygulanır. 



fark 1


İlk bakışta aynı duran yukarıdaki 2 kod satırı aynı zamanda aynı sonucu dönüyorlar fakat arka planda çalışma prensipleri farklı. Şöyle ki, IQueryable olan 1.satır direkt olarak sunucuda çalışacağı için belirtilen tablodan ilk 10 değeri atlayıp ikinci 10 satırı çeker. IEnumerable ise tüm satırları çeker ve hepsini bellekte tutar daha sonra ilk 10 kaydı atlayıp ikinci 10 kaydı gösterir. Aslında IEnumerable'da tüm tabloyu tutuyor ve hala diğer değerlerle ilgili işlem yapılabilir.

fark 2


Burada kodu derlemek istediğimizde her hangi bir hata ile karşılaşmayız, fakat run time'de kod hata fırlatır. Bunun sebebi T-SQL içinde Convert.ToInt32() metodunun olmayışıdır. Çünkü IQueryable sorguyu sunucuda derler demiştik. Bunun aşağıdaki şekilde çalıştırdığımızda her hangi bir hata ile karşılaşmayacağız.

 
IEnumerable, IQueryable tersine sorguyu sunucuda çalıştırmaz. Önce tüm verileri belleğe alır demiştik, daha sonra alınan verilere filtreleme işlemi yapıyoruz. Doğal olarak artık Convert.ToInt32() ile her hangi bir problem yaşamıyoruz.

IEnumerable Linq => Object işlemlerinde daha yararlı iken IQueryable Linq => Sql işlemlerinde daha kullanışlıdır.

İkisi de "Deferred Execution" destekler. Türkçesi ertelenmiş çalışmadır. Şöyle ki Linq sorguları hemen çalışmaz. Belirli bir komuta kadar bekler. Bunu tetikleyenlerden bir tanesi de ToList() metodudur. Sorgu düzenlenir, fakat çalıştırılmaz ta ki ToList() metodu çağrılır ve veri tabanına istek yapılıp veri getirilir.

IReadOnlyList<T> Return Type


IReadOnlyList, C# programlama dilinde bir interface'tir. IReadOnlyList, bir liste gibi düzenlenmiş verileri depolayan ve bu verilere sadece okuma işlemleri yapmaya izin veren bir yapıdır. IReadOnlyList, bir dizinin içeriğini değiştirmek için kullanılamaz ancak verileri okumak ve kullanmak için kullanılabilir. Bu interface, hem performans hem de güvenlik açısından avantajlıdır ve C# programlama dilinde sıklıkla kullanılır.


Add,Remove vs işlemleri IReadOnlyList üzerinde yapılamaz.


Reference 

9 Aralık 2022 Cuma

MVC Architecture Pattern

Problem
- 1970'li yıllarda GUI ve Desktop uygulamaları popülerdi ve 2 ana sorumlulukları vardı.
- Screen layout  ve Logic
- Bu yüzden View ve Logic  bir birine sıkı bir şekilde bağlıydı. View veya Logicde birşeyler yaptığımızda her ikisini de kontrol etmemiz gerekiyordu ve paralel olarak geliştirme yapılamıyordu.

-View ve Logic bir birine sıkı bir şekilde bağlı ve bizim bunları ayırmamız gerekiyor. Bu ayrımada Separated Presentation denilir. Separed Presentationun amacı Domain Objeleri ile ekranda gördüğümüz GUI objeleri arasında net bir ayrım yapmaktır.

-Presentatiın kısmı View ve Contollerdan oluşur. Logic yada Domain element denilen kısımda Model olarak adlandırılır.


MVC

- Bir uygulamayı bir biriyle bağlantılı üç parçaya bölen bir arayüz tasarım desenidir. Katmanlı mimari değildir.
- Bir kullanıcıya bir form içerisinde data göstermek yada kullanıcıdan bir form vasıtasıyla data kabul etme işlerini birbirinden ayırmak için kullanılır.
- MVC tasarım deseni kodun yeniden kullanılmasına ve paralel olarak geliştirme yapabilmek için bu ana bileşenleri ayırır.

Model
Model, MVC’de projenin iş mantığının (business logic) oluşturulduğu bölümdür. İş mantığıyla beraber doğrulama (validation) ve veri erişim (data access) işlemleri de bu bölümde gerçekleştirilmektedir.
- Model, View ve Controller hakkında hiç bir bilgiye sahip değildir.

View
- Kullanıcıların uygulama ile etkileşimde bulanabileceği yer burasıdır.
- View, MVC’de projenin arayüzlerinin oluşturulduğu bölümdür. Bu bölümde projenin kullanıcılara sunulacak olan HTML dosyaları yer almaktadır
View’ın bir görevi de, kullanıcılardan alınan istekleri controller’a iletmektir.
MVC'nin bazı varyasyonlarında View, Model ile doğrudan etkileşime girmez.
- Ancak başlangıçta MVC, View bölümünü güncellemek için Modeldeki tüm değişiklikleri bilmek için Observer Patterni kullanır.

Controller
Bu bölümde View ile Model arasındaki bağlantı kurulur. Kullanıcılardan gelen istekler (request) Controller’larda değerlendirilir, isteğin detayına göre hangi işlemlerin yapılacağı ve kullanıcıya hangi View’ın döneceği (response) belirtilir.

MVC Çalışma Prensibi

Bir MVC projesinde kullanıcı, tarayıcı üzerinden (View) sayfaya istek yaptığında bu istek Controller’a iletilir. Controller isteği gerçekleştirmek üzere model ve bağlantılı bileşenleri ile gerekli sınıf ve metotları çağırır. Elde ettiği sonuçları View’e göndererek sayfanın görüntülenmesini sağlar.

5 Aralık 2022 Pazartesi

Middleware ve Pipeline



ASP .NET Pipeline , ASP .NET'in bir web applicationına veya web servisine  yapılan requestlerin handle edildiği süreçtir.
  • Bir user, Web browser aracılığıyla bir web application yada web servise request gönderir.
  • Request, ASP .NET uygulamasını barındıran(hosting eden) web sunucusu tarafından alınır.
  • Web sunucu, Requesti ASP .NET runtime iletir. ASP.NET'e gelen requestler Thread Pooldaki Threadler tarafından ele alınır.Thread poolda yaklaşık 5000 adet thread bulunmaktır.Eğer bu threadlerin hepsi dolarsa web sunucusunun Queuesuna alınır. Eğer burasıda dolarsa uygulama 503 : Server To Busy Hatası verir . Bunu önlemek için web servisimizi asenkron olarak kodlamaya özen göstermeliyiz.
  • ASP .NET Runtime , Requesti işler ve requesti ve kullanıcıya geri gönderilecek response hakkındaki bilgileri içeren bir HTTP Context oluşturur.
  • Request , ASP .NET pipelinedaki bir dizi adımdan veya "aşamalardan" geçirilir.

Middleware, Web te bir request’in response’a dönüşene kadar arada geçen süreci handle etmemizi sağlayan yapıdır diyebiliriz.Yani request ile response arasına müdahale etmemizi sağlayan ara katman görevi görür.

Her middleware, pipeline üzerinde kendisinden sonra gelen componeti çalıştırmak veya short-circuiting  ile direk response cevabı vermek ile görevlidir


Uygulama içerisinde tanımlı olan middleware'ler register edilme sırasıyla birlikte yukarıdaki resimde olduğu gibi birbirlerini call ederek pipeline'ı tamamlarlar. 



 

 




ASP.NET Core Derinlemesine Dependency Injection

 Dependency Injection, Bir sınıfın bağımlı olduğu sınıfların, bu sınıf içine dışarıdan enjekte edilme işlemidir. Temel amaç somut sınıflara olan bağımlılığı ortadan kaldırmak ve test edilebilirliği kolaylaştırmaktır.



Bir servis DataServiceye bağımlıysa direkt olarak DataServicenin kendisine bağımlıdır. Bunun gibi servisleri test etmek zor olabilir . Bunun yerine servisimiz IDataServiceye bağlıysa sadece inteface tarafından sağlanan contractlar önemsenir. Hangi uygulamanın implemente edildiğinin bir önemi kalmaz. Servisin davranışını test etmek için IDataServicenin Mockunu kullanabiliriz.

Service Lifetime 

Singleton, Yalnızca tek bir instancenin oluşturulacağı anlamına gelir. Bu instance, kendisine ihtiyaç duyan tüm componenentler tarafından ortak kullanılır.  Böylece hep aynı nesne kullanılmış olur.

Scoped, Uygulamaya yapılan her request için bir intance oluşturulur. Ve bu request için response dönene kadar hep aynı instance kullanılır. Request sonlanana kadar ihtiyaç duyulan  her constructer içerisine aynı nesne injecte edilir.

Transient, Her zaman yeni bir instance oluşturulur. Bir request boyunca her constructerda yeni bir instance oluştururlur.

Not: Bir Component Lifetime süresi kendinden kısa olan bir componente bağımlı olamaz. Örneğin singleton A servisinin construterında scoped bir B servisine bağımlı olamaz.


Implementation factories



DataService nesnesini, IOtherService componentini kullanarak oluşturmak istesek yukarıdaki gibi yapabiliriz.

GetRequiredService<T> yerine GetService<T> de  kullanabiliriz. İkisi arasındaki fark GetRequirdeService de eğer nesne bulunamazsa geriye null döner. fakat GetService bulamazsa geriye InvalidOperationException  exception fırlatır.


Decorator Pattern Configuration





Yukarıdaki UML'e baktığımızda decorator kalıbı kullanılmıştır. IDataService interfacesi DataService sınıfı tarafından implemente edilmiştir. DataService sınıfına run-time da yeni bir özellik eklemek istediğimizde decorator tasarım kalıbını kullanabiliriz. Bu yeni özelliği IDataServiceyi implemente eden CacheDataService sınıfı içerisinde yapacağız. 






Yada aşağıdaki gibi Scrutor kullanarak yapabiliriz.
Package Managert consoldan   NuGet\Install-Package Scrutor  indirilir.




Generic Yapıları Register Etme