Hocam anlatımınız çok profesyonelce. Onion mimarisini internette birçok yerde araştırdım ve anlayamamıştım. Sayenizde bu mimariyi hakkında da bilgi sahibi oldum. Teşekkür ederim.
Valla süper anlatımınız var hocam. İş mülakatlarına tekrar ve eksikleri tamamlama amaçlı anlatımlara bakıyordum, sizin kanalınıza denk geldim. Videolarınızdan çıkamıyorum :) Ezbere yapıp, sorulduğunda açıklayamadığım birçok konu sizin videolardan netleşti. Ağzınıza sağlık.
GenericRepository class'ı içerisindeki private dbContext field'ını protected olarak değiştirmeliyiz bence. Çünkü genericRepo'yu base alan productRepo içerisinde belki sadece productRepo'ya özgü func'lar tanımlama ihtiyacımız doğabilir ve dbContext field'ını productRepo içerisinde kullanmamız gerekirse, kullanamayız. Çünkü dbContext genericRepo içerisinde private olarak tanımlı.
Videonuzu izledim, web api katmanina çok fazla iş yüklenmiş görünüyor, verinin gelme işi application katmaninda olmalı ve maplemeler orada yapılmalıdır. Application katmani generic repoyu alıp business uygulayıp veriyi dönmelidir. web api gelen sonucu dis dunyaya direk iletebilir.
Hocam merhaba öncelikle ağzınıza ve emeğinize sağlık çok güzel videolar hazırlıyorsunuz. Benim aklıma takılan bir soru oldu cevaplarsanız çok sevinirim. Application tarafında tanımladığınız genericrepository interfacelerini domain katmanına taşısak bu sayede Application ile Persistence arasındaki depend olayınıda ortadan kaldırmış olmazmıyız. Yani presentation kısmının kullanabileceği interfaceleri yine Application tarafında service interfaceleri olarak tanımlasak ve bunu kullansak olmazmıydı bu konu kafama takılmıştı. Benim sorum sizde belirttiniz referans eklenmesi onların sıkı sıkıya bağlı olduğu anlamına gelmez diye fakat buradaki genericrepositoryler yerine service interfaceleri yani business harici kısmı domaine interface olarak tanımlasak bize ne gibi bir dezavantaj sağlar.
Merhabalar, domain katmanı bize şunu söylüyor. Mesela benim bir domain'im olsun. Diyelim ki rezervasyon sistemi yazıcam ve domain'im rezervasyon olsun. Bu projenin domain katmanında, sadece bu sistemin olmazsa olmazları yer almalı. Mesela Rezervasyon yapılacak kişilerin entity'leri. Rezervasyon modeli vs gibi. Bunun dışında bu katmana başka bir şey girmemeli. Şimdi sizin örneğe bakacak olursak, Repository leri domain katmanına alalım diyorsunuz ama biz bu sistemi repository ler olmadan da yapabiliriz değil mi, başka bir yöntem kullanabiliriz (dbcontext gibi mesela). Bu repository'ler bizim rezervasyon sistemimizin değişmez ve vazgeçilmez parçaları değil. O yüzden Domain katmanında yer almıyor. Neden Application katmanında yer alıyor derseniz de şöyle diyeyim. Biz bir uygulama yazacağız, Domain'i rezervasyon olan. Bir application katmanı yaratarak client'larıma diyorum ki, ben bu domain'i kullanarak Application katmanını geliştiriyorum. Domain ile ilgili işlemleri ben yürüteceğim, size hangi metodlara sahip olacağınızı ben söyleyeceğim, siz beni tanıyacaksınız. Dolayısı ile Application katmanı, bu domain'in interface'i oluyor gibi. Daha sonra bu interface'lerin implemente edilmesi gerekiyor ki bu da infrastructure katmanı oluyor. WebApi katmanı ise bu Application'ı kullanan ve bu datayı son kullanıcıya sunan bir platform. Şimdi bu senaryomuzda domain olmazsa olmaz parçamız ve Application ise interface'imiz demiştik.. Bunun dışındaki tüm parçaları istediğimiz gibi değiştirebiliriz. Mesela infrasturcture katmanını öyle bir kurgularız ki hiç db ye gitmeden tüm datayı istersek bellek üzerinde tutar ve yönetiriz. Bu durumda bile ne domain ne de application katmanında değişiklik yapmamız gerekmez. İstersek WebApi katmanımızı da değiştirip yerine bir Windows App koyarız ve yine başka bir hiç katmanda değişiklik yapmamız gerekmez. İşte Onion Architecture'ın en büyük avantajı da böyle bir durum.
@@TechBuddyTR teşekkür ederim detaylı açıklayıp kafamdaki soru işaretlerini ve yerine oturmayan kısımlara vurgu yaparak beni aydınlattığınız için burada kritik nokta domainin vazgeçilmez şeyler haricinde birşey tutulmaması ve parçaları değiştirmek istediğimizde infrastructure kısmına müdahelemiz yani datayı çekme yöntemlerimizin diğerlerini etkilememesi çok teşekkür ederim tekrardan çok yararlı bilgiler ediniyoruz sayesinizde
İyi günler dilerim . Aslında argümanlarınızı anlayışla karşılamama rağmen Jeffrey Palermo'nun Onion Mimariyi tanıttıgı makalesinde özellikle Repository Interface'lerinin Generic Repository Pattern dogru kurulduğu takdirde (Read ve Write kısımlarının ayrılması) Domain katmanında barındırılmasının ,Unit Test ve Domain'in bu senaryolarda test etmek isteyebileceği yapıların da olmasından dolayı daha sağlıklı olduğu belirtiliyor.Aslında Yazılım fraksiyonları bayagı ayrılmıs durumda ve her iki yonelimden de güzel argümanlar mevcut. Repository Pattern kullanmak istemeyebiliriz deniyor fakat Generic Repository'e anti pattern argümanları sunulmasına rağmen doğru kurulduğunda her türlü teknolojiye esneyebilen faydalı bir yaklaşım geliştirilebilir ve bu durumdan dolayı Domain'de barındırıldığı bir sürü senaryo ile karşılaşabiliyoruz. Aynı zamanda belli gerçek hayat senaryoları da Repository Interface'lerinin Application'da veya Domain'de tutulmasının daha iyi olduğu mimariler yaratabiliyor. Her halükarda bu Interface'ler Domain'de olmayacaksa bile kesinlikle Manager Interface'lerden ayrı tutulması gerektiği kanaatindeyim. Farklı bir katman acılıp Repository Interfaceler orada Manager Interface'ler baska bir katmanda tutulsa Single Responsibility acısından daha iyi olduğunu düşünüyorum. Mesela Domain, Application, RepositoryContracts gibi. Repository iş akışından ziyade artık business'in işinin bitip emrin son tetiklendiği yer olursa daha dağıtık bir sistem olacaktır. Tekrardan emeğinize saglık...
Merhaba , Application kısmında requestparameter dan bahsettiniz. Örnek olarak da paging olayını verdiniz. Paging ile ilgili birçok örnek var ama tam olarak bu şekilde requestparameters tarzında bir örnek pek yok. Bu konuyu da biraz açabilirseniz kullanım açısından bir örnekle çok sevinirim.
Aynı şekilde kullanılmak zorunda değil tabi ki de. Hem RequestParameter hem de Response modellerini özelleştirmek isterseniz, bunları kullanacağımız yer Application tarafı olacaktır diye belirtmek istedim. Bir model içinden almak yerine direk queryString ile de alınabilir elbet. Diğer bir çok örnekte böyle çıkıyordur karşımıza da.
@@TechBuddyTR nette global exception handling ile ilgili birçok makale ve video var aslında ama onion architechture en doğru şekilde nasıl uygulanmalı bununla ilgili de bir video çekebilirseniz çok memnun olurum. Anlatımınız gerçekden çok akıcı ve anlaşılır. Tüm emekleriniz için teşekkürler
The idea of separating the persistence library is that allowing the app might have more than one persistence layer such as Writing to DB, api or local file system. It is obviously not a N tier architecture because in onion architecture the main goal is that seperation of concern so Core (domain, application), infrastructure (held contacting 3th party intergration) and UI (presentation) are our parts in the application. As we think all parts come together and our project appears. Adding references doesn't mean that we have dependency.
I really appreciate your way of explaining things. Thank you. Is it too much to ask if you could do some videos on Unit Testing, specifically testing WEB Api-s? Thank you again good sir!
Thanks for spending time by watching my videos and for your time to comment. Currently I have project that already been started such as EntityFramework and Microservices. After these finished, I want to make a video series about UnitTesting.
Merhaba elinize sağlık videolarınız çok güzel bir sorum olacak CQRS kullanmak yerine infrastructure katmanında Business classları yazılsa mesela ProductBusiness sınıfı ve bu sınıf ProductRepositoryden aldığı domain modelini ProductDto ya map ederek verse ve controllerdada ProductRepository yerine PrpductBusinessi kullansak bu problemi çözmüş olmazmıyız?
Merhabalar çok teşekkür ederim. Bahsettiğiniz senaryoda Dağıtık uygulama geliştirme kurallarına karşı duran 1-2 durum ortaya çıkıyor. 1 repository pattern'i kullanamıyor ve dolayısı ile abstraction dan faydalanamıyor oluyoruz. ikincisi ise Infrastructure katmanını görevi dışında bir iş içi kullanmış oluyoruz. Business kuralları Application'ını ilgilendiren bir durum olduğu için Application tarafında yer almalı. CQRS'in güzel yanı ise, Presentation katmanı ile Application katmanı arasında doğrudan bir bağlantı kurmadan işimizi halledebilmemizi sağlıyor. Bu tarz katmanlarda özellikle Onion Architecture kullanırken, projeler arası bağımlılıklar çok dikkat edilmesi gereken konular. Çünkü ne kadar bağlarsak, projeler üzerinde değişiklik yaptığımızda dikkat edip düzenleme yapmamız gereken o kadar çok yer çıkıyor karşımıza.
Merhaba, bağımlılıklar dıştan içe dedik ama UI'a persistence katmanı bağımlılığı ekledik. Yani yatayda da bağımlılık ekleyebiliyoruz Onion Architecture'da değil mi?
UI katmanı diğer katmanların dışında kalıyor aslında. O yüzden eklemekte bir sorun yok. Ama yataydaki bağımlılıkları da yaratabiliriz, onda da sorun yok :)
Repository'ler Ado veya Dapper gibi teknolojilerle çok iyi olsa da EF kullanırken var olan soyutlamayı tekrar soyutluyormuşuz gibi hissediyorum. Proje doğrudan EF'ye bağımlı olmasın diye yapıldığını biliyorum ama yine de hoşuma gitmiyor. Ayrıca bir tablomda 30 tane kolon olduğunu düşünelim, bana sadece 5 tanesi lazım ise o 5 taneyi almalıyım. Bunun için DTO oluşturabiliriz ama Repository'lerde DTO kullanan hiç görmedim. Select ile veya AutoMapper gibi kütüphaneler üzerinden Repository'lerde DTO kullanmak yanlış bir şey mi?
EF'in zaten bir repository pattern olduğunu ve dolayısı ile tekrar generic bir repository içinde kullanılmaması gerektiğini düşünenler de var. Bahsettiğiniz problem ise repository pattern'de sıklıkla karşılaşılan bir problem. Tüm sütunların gereksiz olarak çekilmesi işlemi ancak AutoMapper'ın bunun için çok güzel bir extension metodu var ProjectTo isminde. Bu şekilde IQuerable sınıfını bir dto olarak geriye dönebiliyoruz. Bunun illa repository içerisinde olmasına gerek de yok, Automapper için bir injection kullanılarak çözüm bulunabilir. Bu sebeple dto kullanmak yanlış değil, hatta daha doğrusu bu bence
domain katmanımızda entity ve domain ile ilgili base modellerimizin tanımlamasını yapıyoruz. Application katmanında ise hem presentation katmanına gerekli Interface'leri tanımlıyoruz hem de business rule larımızı bu katmanda yazıyoruz.
Hocam bu arada chatgpt'ye sordum. Onion mimarisinde Presentation'dan Persistence'a gitmek aykırıdır diyor. Ancak biz neden Persistence'a ServiceRegistration ekleyip, presentation'da AddPersistenceService metodunu ekledik? İlginiz için şimdiden teşekkürler.
Presentation'dan Persistence'e gitmek OA kuralına aykırı değil aslında. Her katman kendi ve altındaki katmanlara ulaşabilirler. Ama şöyle bir şey var burada Presentation ile Persistence arasında bağ kurmamak gerekir çünkü bunlar doğrudan bağ kurmaya gerek olmayan katmanlar. Persistence aslında Application daki interface'leri implemente eden katman. Biz Presentation'dan Application'a gidiyoruz, gerisini o hallediyor şeklinde olmalı. Diğer yandan ise şöyle bir durum var, bizim burada ana uygulamamız WebApi yani Presentation katmanımız, dolayısı ile bu veritabanı bağlantılarının, ayarlarının vs yapılması, bunların bağımlılıklarının sisteme eklenebilmesi için WebApi deki ServiceCollection nesnesine ihtiyacımız var. Persistence katmanındaki DbContext'in falan da sisteme eklenebilmesi için ikisi arasında böyle gevşek bir bağ kurmamız gerekiyordu. Fazlası gereksiz olurdu zaten.
Dbcontexti'in özelliklerini kısıtlayarak bir generic repo oluşturmayı aklım almıyor. Zaten generic bir şeyi generic yapıyoruz. Onun dışında unitofwork oluşturuyoruz onunla da savechangesi methodunu çağırmaktan başka bir şey olmuyor. Biri aydınlatırsa sevinirim
GenericRepository eğer entiryframework önüne konuyorsa genelde bu tek bir amaç için yapılır. Orm tarafını da dinamik olarak değiştirebilmek. Haklısınız EF zaten generic repository patterni ile çalışıyor. Eğer bir gün ef in desteklemediği bir db ile çalışmak isterseniz, veya ef yerine başka bir orm koymak isterseniz generic repository burada işinize yarar. Uof ise transactional işleri biraz daha kontrol altına almak için. Ef kullanmadığınız durumda override edip özelleştirebileceğiniz bir SaveChanges metodu olmayacağı için,uof deki save metodu özelleştirilebilir
@@TechBuddyTR cok tesekkur ederim, cok iyi anladım. Peki son bir soru sorabilir miyim, genis tecrubenize dayanarak. Generic repo direkt enumerable dönmeli diye dusunuyorum cunku bazi db ler iqueryable destegi vermiyor. Fakat cogu kisi iqueryable dönüyor. Dogru olmasi gereken reponun enumarable dönmesi midir?
@@kazimkesler ienumerable mantıklı olur ama zorunlu da değil. Diyelim ki orm olarak dapper kullanıyoruz ve diyelim dapper geriye ienumerable değil de List dönüyor. Biz metoddan geriye yine ienumerable dönüp, bu listi return edebiliriz. Ama eğer bu metodu çağırabin kişi bizim döndüğümüz ienumerable ı alıp tekrar List e dönüştürüyorsa, o zaman direkt list dönmek daha mantıklı olurdu
Cok tesekkur ederim, cok yardimci oldunuz, ayagınıza taş degmesin. Benim kastettigim GenericRepoda şöyle bir method var diyelim IQueryable GetAll(); Bununla sorgu inşasına repo dısinda da devam edilebilir, bu dogru bir yaklasim degil gibi sanki
@@kazimkesler bu özellikle eklenmiş bir metod. Normalde GetAll() metodu tablodaki tüm verileri dönüyor olmalı ama bu da pek mantıklı değil. Bu getall metodunu çağıran taraf servis metodu olmak zorunda değil. Kendi reponuz içerisinden bu metodu kullanarak özel bir metod yazabilirsiniz. UserRepository de GetActiveUsers diye bir metod bu getall u çağırıp sadece aktif olanları filtreleyebilir mesela
Tümü ile ilgili videolar planlamıyorum. Ara ara sohbet toplantılarımızda bahsediyoruz bazılarından. En çok talep gören bir kaç tanesini tek video şeklinde yayınlayabiliriz belki bilemedim :)
Hocam anlatımınız çok profesyonelce. Onion mimarisini internette birçok yerde araştırdım ve anlayamamıştım. Sayenizde bu mimariyi hakkında da bilgi sahibi oldum. Teşekkür ederim.
Mükemmel anlatım, çok iyi açıklıyorsunuz. Emeğinize sağlık hocam.
Teşekkürler. Elinize sağlık hocam.
Teşekkürler, iyi seyirler
Valla süper anlatımınız var hocam. İş mülakatlarına tekrar ve eksikleri tamamlama amaçlı anlatımlara bakıyordum, sizin kanalınıza denk geldim. Videolarınızdan çıkamıyorum :) Ezbere yapıp, sorulduğunda açıklayamadığım birçok konu sizin videolardan netleşti. Ağzınıza sağlık.
GenericRepository class'ı içerisindeki private dbContext field'ını protected olarak değiştirmeliyiz bence. Çünkü genericRepo'yu base alan productRepo içerisinde belki sadece productRepo'ya özgü func'lar tanımlama ihtiyacımız doğabilir ve dbContext field'ını productRepo içerisinde kullanmamız gerekirse, kullanamayız. Çünkü dbContext genericRepo içerisinde private olarak tanımlı.
Ağzınıza sağlık hocam çok güzel anlatmışsınız yeni yeni öğrenmeye başlayan bir kişinin beyni yanıyor 😄
E biraz zamana ihtiyaç var o zaman :)
Cok basarili bir seri, tesekkur ederiz Tech Buddy !
Ben teşekkür ederim. İyi seyirler
Aşırı iyi bir video :)
Elinize sağlık, Teşekkürler.
Aman yarabbi bu nasil bir anlatimdir boyle. Kesfedilmemis bir hazine adeta.
😂😂 teşekkürler
Harikaydı
Teşekkürler hocam
emeğinize sağlık hocam
Teşekkürler :)
Videonuzu izledim, web api katmanina çok fazla iş yüklenmiş görünüyor, verinin gelme işi application katmaninda olmalı ve maplemeler orada yapılmalıdır. Application katmani generic repoyu alıp business uygulayıp veriyi dönmelidir. web api gelen sonucu dis dunyaya direk iletebilir.
Videoyu izlerken kaçırmışsınız sanırım. Söylediğiniz şeyden bahsediyorum. CQRS kullanmaya başlıyoruz ve dolayısı ile Application katmanında tamamlanıyor business kuralları.
çok teşekkürler👍
Çok iyi anlatım
Teşekkürler 😊
Hocam merhaba öncelikle ağzınıza ve emeğinize sağlık çok güzel videolar hazırlıyorsunuz. Benim aklıma takılan bir soru oldu cevaplarsanız çok sevinirim.
Application tarafında tanımladığınız genericrepository interfacelerini domain katmanına taşısak bu sayede Application ile Persistence arasındaki depend olayınıda ortadan kaldırmış olmazmıyız. Yani presentation kısmının kullanabileceği interfaceleri yine Application tarafında service interfaceleri olarak tanımlasak ve bunu kullansak olmazmıydı bu konu kafama takılmıştı. Benim sorum sizde belirttiniz referans eklenmesi onların sıkı sıkıya bağlı olduğu anlamına gelmez diye fakat buradaki genericrepositoryler yerine service interfaceleri yani business harici kısmı domaine interface olarak tanımlasak bize ne gibi bir dezavantaj sağlar.
Merhabalar, domain katmanı bize şunu söylüyor. Mesela benim bir domain'im olsun. Diyelim ki rezervasyon sistemi yazıcam ve domain'im rezervasyon olsun. Bu projenin domain katmanında, sadece bu sistemin olmazsa olmazları yer almalı. Mesela Rezervasyon yapılacak kişilerin entity'leri. Rezervasyon modeli vs gibi. Bunun dışında bu katmana başka bir şey girmemeli.
Şimdi sizin örneğe bakacak olursak, Repository leri domain katmanına alalım diyorsunuz ama biz bu sistemi repository ler olmadan da yapabiliriz değil mi, başka bir yöntem kullanabiliriz (dbcontext gibi mesela). Bu repository'ler bizim rezervasyon sistemimizin değişmez ve vazgeçilmez parçaları değil. O yüzden Domain katmanında yer almıyor.
Neden Application katmanında yer alıyor derseniz de şöyle diyeyim. Biz bir uygulama yazacağız, Domain'i rezervasyon olan. Bir application katmanı yaratarak client'larıma diyorum ki, ben bu domain'i kullanarak Application katmanını geliştiriyorum. Domain ile ilgili işlemleri ben yürüteceğim, size hangi metodlara sahip olacağınızı ben söyleyeceğim, siz beni tanıyacaksınız.
Dolayısı ile Application katmanı, bu domain'in interface'i oluyor gibi. Daha sonra bu interface'lerin implemente edilmesi gerekiyor ki bu da infrastructure katmanı oluyor.
WebApi katmanı ise bu Application'ı kullanan ve bu datayı son kullanıcıya sunan bir platform.
Şimdi bu senaryomuzda domain olmazsa olmaz parçamız ve Application ise interface'imiz demiştik.. Bunun dışındaki tüm parçaları istediğimiz gibi değiştirebiliriz. Mesela infrasturcture katmanını öyle bir kurgularız ki hiç db ye gitmeden tüm datayı istersek bellek üzerinde tutar ve yönetiriz. Bu durumda bile ne domain ne de application katmanında değişiklik yapmamız gerekmez. İstersek WebApi katmanımızı da değiştirip yerine bir Windows App koyarız ve yine başka bir hiç katmanda değişiklik yapmamız gerekmez. İşte Onion Architecture'ın en büyük avantajı da böyle bir durum.
@@TechBuddyTR teşekkür ederim detaylı açıklayıp kafamdaki soru işaretlerini ve yerine oturmayan kısımlara vurgu yaparak beni aydınlattığınız için burada kritik nokta domainin vazgeçilmez şeyler haricinde birşey tutulmaması ve parçaları değiştirmek istediğimizde infrastructure kısmına müdahelemiz yani datayı çekme yöntemlerimizin diğerlerini etkilememesi çok teşekkür ederim tekrardan çok yararlı bilgiler ediniyoruz sayesinizde
İyi günler dilerim . Aslında argümanlarınızı anlayışla karşılamama rağmen Jeffrey Palermo'nun Onion Mimariyi tanıttıgı makalesinde özellikle Repository Interface'lerinin Generic Repository Pattern dogru kurulduğu takdirde (Read ve Write kısımlarının ayrılması) Domain katmanında barındırılmasının ,Unit Test ve Domain'in bu senaryolarda test etmek isteyebileceği yapıların da olmasından dolayı daha sağlıklı olduğu belirtiliyor.Aslında Yazılım fraksiyonları bayagı ayrılmıs durumda ve her iki yonelimden de güzel argümanlar mevcut. Repository Pattern kullanmak istemeyebiliriz deniyor fakat Generic Repository'e anti pattern argümanları sunulmasına rağmen doğru kurulduğunda her türlü teknolojiye esneyebilen faydalı bir yaklaşım geliştirilebilir ve bu durumdan dolayı Domain'de barındırıldığı bir sürü senaryo ile karşılaşabiliyoruz. Aynı zamanda belli gerçek hayat senaryoları da Repository Interface'lerinin Application'da veya Domain'de tutulmasının daha iyi olduğu mimariler yaratabiliyor. Her halükarda bu Interface'ler Domain'de olmayacaksa bile kesinlikle Manager Interface'lerden ayrı tutulması gerektiği kanaatindeyim. Farklı bir katman acılıp Repository Interfaceler orada Manager Interface'ler baska bir katmanda tutulsa Single Responsibility acısından daha iyi olduğunu düşünüyorum. Mesela Domain, Application, RepositoryContracts gibi. Repository iş akışından ziyade artık business'in işinin bitip emrin son tetiklendiği yer olursa daha dağıtık bir sistem olacaktır. Tekrardan emeğinize saglık...
Merhaba , Application kısmında requestparameter dan bahsettiniz. Örnek olarak da paging olayını verdiniz. Paging ile ilgili birçok örnek var ama tam olarak bu şekilde requestparameters tarzında bir örnek pek yok. Bu konuyu da biraz açabilirseniz kullanım açısından bir örnekle çok sevinirim.
Aynı şekilde kullanılmak zorunda değil tabi ki de. Hem RequestParameter hem de Response modellerini özelleştirmek isterseniz, bunları kullanacağımız yer Application tarafı olacaktır diye belirtmek istedim. Bir model içinden almak yerine direk queryString ile de alınabilir elbet. Diğer bir çok örnekte böyle çıkıyordur karşımıza da.
@@TechBuddyTR nette global exception handling ile ilgili birçok makale ve video var aslında ama onion architechture en doğru şekilde nasıl uygulanmalı bununla ilgili de bir video çekebilirseniz çok memnun olurum. Anlatımınız gerçekden çok akıcı ve anlaşılır. Tüm emekleriniz için teşekkürler
Hocam ağzına sağlık
Why did you add persistance library to web project as a reference? This way you got not an onion but a regular N tier arch. No?
The idea of separating the persistence library is that allowing the app might have more than one persistence layer such as Writing to DB, api or local file system. It is obviously not a N tier architecture because in onion architecture the main goal is that seperation of concern so Core (domain, application), infrastructure (held contacting 3th party intergration) and UI (presentation) are our parts in the application. As we think all parts come together and our project appears. Adding references doesn't mean that we have dependency.
I really appreciate your way of explaining things. Thank you.
Is it too much to ask if you could do some videos on Unit Testing, specifically testing WEB Api-s?
Thank you again good sir!
Thanks for spending time by watching my videos and for your time to comment. Currently I have project that already been started such as EntityFramework and Microservices. After these finished, I want to make a video series about UnitTesting.
Teşekkürler
🎉
Teşekkürler.
Merhaba elinize sağlık videolarınız çok güzel bir sorum olacak CQRS kullanmak yerine infrastructure katmanında Business classları yazılsa mesela ProductBusiness sınıfı ve bu sınıf ProductRepositoryden aldığı domain modelini ProductDto ya map ederek verse ve controllerdada ProductRepository yerine PrpductBusinessi kullansak bu problemi çözmüş olmazmıyız?
Merhabalar çok teşekkür ederim. Bahsettiğiniz senaryoda Dağıtık uygulama geliştirme kurallarına karşı duran 1-2 durum ortaya çıkıyor. 1 repository pattern'i kullanamıyor ve dolayısı ile abstraction dan faydalanamıyor oluyoruz. ikincisi ise Infrastructure katmanını görevi dışında bir iş içi kullanmış oluyoruz. Business kuralları Application'ını ilgilendiren bir durum olduğu için Application tarafında yer almalı. CQRS'in güzel yanı ise, Presentation katmanı ile Application katmanı arasında doğrudan bir bağlantı kurmadan işimizi halledebilmemizi sağlıyor. Bu tarz katmanlarda özellikle Onion Architecture kullanırken, projeler arası bağımlılıklar çok dikkat edilmesi gereken konular. Çünkü ne kadar bağlarsak, projeler üzerinde değişiklik yaptığımızda dikkat edip düzenleme yapmamız gereken o kadar çok yer çıkıyor karşımıza.
@@TechBuddyTR Anladım teşekkür ederim martin fowlerin clean architecture adlı kitabınıda aldım. Konuyu pekiştirmek için onada bakacağım.
Merhaba, bağımlılıklar dıştan içe dedik ama UI'a persistence katmanı bağımlılığı ekledik. Yani yatayda da bağımlılık ekleyebiliyoruz Onion Architecture'da değil mi?
UI katmanı diğer katmanların dışında kalıyor aslında. O yüzden eklemekte bir sorun yok. Ama yataydaki bağımlılıkları da yaratabiliriz, onda da sorun yok :)
Repository'ler Ado veya Dapper gibi teknolojilerle çok iyi olsa da EF kullanırken var olan soyutlamayı tekrar soyutluyormuşuz gibi hissediyorum. Proje doğrudan EF'ye bağımlı olmasın diye yapıldığını biliyorum ama yine de hoşuma gitmiyor. Ayrıca bir tablomda 30 tane kolon olduğunu düşünelim, bana sadece 5 tanesi lazım ise o 5 taneyi almalıyım. Bunun için DTO oluşturabiliriz ama Repository'lerde DTO kullanan hiç görmedim. Select ile veya AutoMapper gibi kütüphaneler üzerinden Repository'lerde DTO kullanmak yanlış bir şey mi?
EF'in zaten bir repository pattern olduğunu ve dolayısı ile tekrar generic bir repository içinde kullanılmaması gerektiğini düşünenler de var. Bahsettiğiniz problem ise repository pattern'de sıklıkla karşılaşılan bir problem. Tüm sütunların gereksiz olarak çekilmesi işlemi ancak AutoMapper'ın bunun için çok güzel bir extension metodu var ProjectTo isminde. Bu şekilde IQuerable sınıfını bir dto olarak geriye dönebiliyoruz. Bunun illa repository içerisinde olmasına gerek de yok, Automapper için bir injection kullanılarak çözüm bulunabilir.
Bu sebeple dto kullanmak yanlış değil, hatta daha doğrusu bu bence
eğer ınfrastructure ve persistence katmanından domain'e erişebiliyorsak application katmanının ne anlamı var onu anlayamadım tam olarak
domain katmanımızda entity ve domain ile ilgili base modellerimizin tanımlamasını yapıyoruz. Application katmanında ise hem presentation katmanına gerekli Interface'leri tanımlıyoruz hem de business rule larımızı bu katmanda yazıyoruz.
Hocam bu arada chatgpt'ye sordum. Onion mimarisinde Presentation'dan Persistence'a gitmek aykırıdır diyor. Ancak biz neden Persistence'a ServiceRegistration ekleyip, presentation'da AddPersistenceService metodunu ekledik? İlginiz için şimdiden teşekkürler.
Presentation'dan Persistence'e gitmek OA kuralına aykırı değil aslında. Her katman kendi ve altındaki katmanlara ulaşabilirler. Ama şöyle bir şey var burada Presentation ile Persistence arasında bağ kurmamak gerekir çünkü bunlar doğrudan bağ kurmaya gerek olmayan katmanlar. Persistence aslında Application daki interface'leri implemente eden katman. Biz Presentation'dan Application'a gidiyoruz, gerisini o hallediyor şeklinde olmalı. Diğer yandan ise şöyle bir durum var, bizim burada ana uygulamamız WebApi yani Presentation katmanımız, dolayısı ile bu veritabanı bağlantılarının, ayarlarının vs yapılması, bunların bağımlılıklarının sisteme eklenebilmesi için WebApi deki ServiceCollection nesnesine ihtiyacımız var. Persistence katmanındaki DbContext'in falan da sisteme eklenebilmesi için ikisi arasında böyle gevşek bir bağ kurmamız gerekiyordu. Fazlası gereksiz olurdu zaten.
Dbcontexti'in özelliklerini kısıtlayarak bir generic repo oluşturmayı aklım almıyor. Zaten generic bir şeyi generic yapıyoruz. Onun dışında unitofwork oluşturuyoruz onunla da savechangesi methodunu çağırmaktan başka bir şey olmuyor. Biri aydınlatırsa sevinirim
GenericRepository eğer entiryframework önüne konuyorsa genelde bu tek bir amaç için yapılır. Orm tarafını da dinamik olarak değiştirebilmek. Haklısınız EF zaten generic repository patterni ile çalışıyor. Eğer bir gün ef in desteklemediği bir db ile çalışmak isterseniz, veya ef yerine başka bir orm koymak isterseniz generic repository burada işinize yarar.
Uof ise transactional işleri biraz daha kontrol altına almak için. Ef kullanmadığınız durumda override edip özelleştirebileceğiniz bir SaveChanges metodu olmayacağı için,uof deki save metodu özelleştirilebilir
@@TechBuddyTR cok tesekkur ederim, cok iyi anladım. Peki son bir soru sorabilir miyim, genis tecrubenize dayanarak. Generic repo direkt enumerable dönmeli diye dusunuyorum cunku bazi db ler iqueryable destegi vermiyor. Fakat cogu kisi iqueryable dönüyor. Dogru olmasi gereken reponun enumarable dönmesi midir?
@@kazimkesler ienumerable mantıklı olur ama zorunlu da değil. Diyelim ki orm olarak dapper kullanıyoruz ve diyelim dapper geriye ienumerable değil de List dönüyor. Biz metoddan geriye yine ienumerable dönüp, bu listi return edebiliriz. Ama eğer bu metodu çağırabin kişi bizim döndüğümüz ienumerable ı alıp tekrar List e dönüştürüyorsa, o zaman direkt list dönmek daha mantıklı olurdu
Cok tesekkur ederim, cok yardimci oldunuz, ayagınıza taş degmesin. Benim kastettigim
GenericRepoda şöyle bir method var diyelim
IQueryable GetAll();
Bununla sorgu inşasına repo dısinda da devam edilebilir, bu dogru bir yaklasim degil gibi sanki
@@kazimkesler bu özellikle eklenmiş bir metod. Normalde GetAll() metodu tablodaki tüm verileri dönüyor olmalı ama bu da pek mantıklı değil. Bu getall metodunu çağıran taraf servis metodu olmak zorunda değil. Kendi reponuz içerisinden bu metodu kullanarak özel bir metod yazabilirsiniz. UserRepository de GetActiveUsers diye bir metod bu getall u çağırıp sadece aktif olanları filtreleyebilir mesela
Hocam Merhaba,
Tasarım Kalıpları hakkında detaylı bir videonuz olucak mı?
Tümü ile ilgili videolar planlamıyorum. Ara ara sohbet toplantılarımızda bahsediyoruz bazılarından. En çok talep gören bir kaç tanesini tek video şeklinde yayınlayabiliriz belki bilemedim :)
@@TechBuddyTR Teşekkürler bekliyoruz hocam
Teşekkürler, elinize sağlık.