4. Yineleme – Uygulamanın gevşek bir şekilde bağlanmasını sağlama (VB)
Microsoft tarafından
Bu dördüncü yinelemede, Contact Manager uygulamasının bakımını ve değiştirilmesini kolaylaştırmak için çeşitli yazılım tasarım desenlerinden yararlanıyoruz. Örneğin, uygulamamızı Depo desenini ve Bağımlılık Ekleme düzenini kullanacak şekilde yeniden düzenleyeceğiz.
MVC Uygulaması ASP.NET Kişi Yönetimi Oluşturma (VB)
Bu öğretici serisinde, baştan sona bir Kişi Yönetimi uygulamasının tamamını oluşturuyoruz. Contact Manager uygulaması kişi listesi için kişi bilgilerini (adlar, telefon numaraları ve e-posta adresleri) depolamanıza olanak tanır.
Uygulamayı birden çok yineleme üzerinden derleyeceğiz. Her yinelemede uygulamayı aşamalı olarak iyileştiriyoruz. Bu çoklu yineleme yaklaşımının amacı, her değişikliğin nedenini anlamanıza olanak tanımaktır.
Yineleme #1 - Uygulamayı oluşturun. İlk yinelemede, Contact Manager'ı mümkün olan en basit şekilde oluştururuz. Temel veritabanı işlemleri için destek ekliyoruz: Oluşturma, Okuma, Güncelleştirme ve Silme (CRUD).
Yineleme #2 - Uygulamanın güzel görünmesini sağlayın. Bu yinelemede, MVC görünümü ana sayfasını ve basamaklı stil sayfasını varsayılan ASP.NET değiştirerek uygulamanın görünümünü iyileştireceğiz.
3. Yineleme - Form doğrulaması ekleyin. Üçüncü yinelemede temel form doğrulamasını ekleyeceğiz. Gerekli form alanlarını tamamlamadan kişilerin form göndermesini engelleriz. Ayrıca e-posta adreslerini ve telefon numaralarını doğrularız.
Yineleme #4 - Uygulamayı gevşek bir şekilde birleştirin. Bu dördüncü yinelemede, Contact Manager uygulamasının bakımını ve değiştirilmesini kolaylaştırmak için çeşitli yazılım tasarım desenlerinden yararlanıyoruz. Örneğin, uygulamamızı Depo desenini ve Bağımlılık Ekleme düzenini kullanacak şekilde yeniden düzenleyeceğiz.
Yineleme #5 - Birim testleri oluşturun. Beşinci yinelemede, birim testleri ekleyerek uygulamamızın bakımını ve değiştirilmesini kolaylaştırıyoruz. Veri modeli sınıflarımızla dalga geçiyoruz ve denetleyicilerimiz ve doğrulama mantığımız için birim testleri oluşturuyoruz.
Yineleme #6 - Test temelli geliştirmeyi kullanın. Bu altıncı yinelemede, önce birim testleri yazıp birim testlerine kod yazarak uygulamamıza yeni işlevler ekleyeceğiz. Bu yinelemede kişi grupları ekleyeceğiz.
Yineleme #7 - Ajax işlevselliğini ekleyin. Yedinci yinelemede Ajax için destek ekleyerek uygulamamızın yanıt hızını ve performansını iyileştiriyoruz.
Bu Yineleme
Contact Manager uygulamasının bu dördüncü yinelemesinde, uygulamayı daha gevşek bir şekilde birleştiğinden emin olmak için yeniden düzenleyeceğiz. Bir uygulama gevşek bir şekilde bağlandığında, uygulamanın diğer bölümlerinde kodu değiştirmenize gerek kalmadan uygulamanın bir bölümündeki kodu değiştirebilirsiniz. Gevşek bir şekilde bağlanmış uygulamalar, değişmeye daha dayanıklıdır.
Şu anda, Contact Manager uygulaması tarafından kullanılan tüm veri erişimi ve doğrulama mantığı denetleyici sınıflarında yer almaktadır. Bu kötü bir fikir. Uygulamanızın bir bölümünü değiştirmeniz gerektiğinde, hataları uygulamanızın başka bir bölümüne ekleme riskiyle karşılaşırsınız. Örneğin, doğrulama mantığınızı değiştirirseniz veri erişiminize veya denetleyici mantığınıza yeni hatalar ekleme riskiyle karşılaşırsınız.
Not
(SRP), bir sınıfın değiştirmek için hiçbir zaman birden fazla nedeni olmamalıdır. Denetleyici, doğrulama ve veritabanı mantığının karıştırılması, Tek Sorumluluk İlkesi'nin çok büyük bir ihlalidir.
Uygulamanızı değiştirmenizin birkaç nedeni olabilir. Uygulamanıza yeni bir özellik eklemeniz gerekebilir, uygulamanızdaki bir hatayı düzeltmeniz veya uygulamanızın bir özelliğinin uygulanma şeklini değiştirmeniz gerekebilir. Uygulamalar nadiren statiktir. Zamanla büyüme ve sessize alma eğilimindedirler.
Örneğin, veri erişim katmanınızı uygulama şeklinizi değiştirmeye karar ve ettiğinizi düşünün. Contact Manager uygulaması şu anda veritabanına erişmek için Microsoft Entity Framework kullanıyor. Ancak, ADO.NET Data Services veya NHibernate gibi yeni veya alternatif bir veri erişim teknolojisine geçiş yapmaya karar vekleyebilirsiniz. Ancak, veri erişim kodu doğrulama ve denetleyici kodundan yalıtılmadığından, veri erişimiyle doğrudan ilgili olmayan diğer kodları değiştirmeden uygulamanızdaki veri erişim kodunu değiştirmenin hiçbir yolu yoktur.
Öte yandan, bir uygulama gevşek bir şekilde birleştirildiğinde, uygulamanın diğer bölümlerine dokunmadan uygulamanın bir bölümünde değişiklik yapabilirsiniz. Örneğin, doğrulama veya denetleyici mantığınızı değiştirmeden veri erişim teknolojileri arasında geçiş yapabilirsiniz.
Bu yinelemede, Contact Manager uygulamamızı daha gevşek bir şekilde bağlanmış bir uygulamada yeniden düzenlememizi sağlayan çeşitli yazılım tasarım desenlerinden yararlanıyoruz. bitirdiğimizde, Contact Manager daha önce yapmadığı hiçbir şeyi yapmaz. Ancak, gelecekte uygulamayı daha kolay değiştirebileceğiz.
Not
Yeniden düzenleme, bir uygulamayı mevcut işlevleri kaybetmeyecek şekilde yeniden yazma işlemidir.
Depo Yazılım Tasarım Desenini Kullanma
İlk değişikliğimiz, Depo deseni adı verilen bir yazılım tasarım deseninin avantajlarından yararlanmaktır. Veri erişim kodumuzu uygulamamızın geri kalanından yalıtmak için Depo desenini kullanacağız.
Depo düzenini uygulamak için aşağıdaki iki adımı tamamlamamız gerekir:
- Arabirim oluşturma
- Arabirimini uygulayan somut bir sınıf oluşturma
İlk olarak, gerçekleştirmemiz gereken tüm veri erişim yöntemlerini açıklayan bir arabirim oluşturmamız gerekir. IContactManagerRepository arabirimi Listeleme 1'de yer alır. Bu arabirim beş yöntemi açıklar: CreateContact(), DeleteContact(), EditContact(), GetContact ve ListContacts().
Listeleme 1 - Models\IContactManagerRepository.vb
Public Interface IContactManagerRepository
Function CreateContact(ByVal contactToCreate As Contact) As Contact
Sub DeleteContact(ByVal contactToDelete As Contact)
Function EditContact(ByVal contactToUpdate As Contact) As Contact
Function GetContact(ByVal id As Integer) As Contact
Function ListContacts() As IEnumerable(Of Contact)
End Interface
Ardından, IContactManagerRepository arabirimini uygulayan somut bir sınıf oluşturmamız gerekir. Veritabanına erişmek için Microsoft Entity Framework'i kullandığımız için EntityContactManagerRepository adlı yeni bir sınıf oluşturacağız. Bu sınıf Liste 2'de yer alır.
Listeleme 2 - Models\EntityContactManagerRepository.vb
Public Class EntityContactManagerRepository
Implements IContactManagerRepository
Private _entities As New ContactManagerDBEntities()
Public Function GetContact(ByVal id As Integer) As Contact Implements IContactManagerRepository.GetContact
Return (From c In _entities.ContactSet _
Where c.Id = id _
Select c).FirstOrDefault()
End Function
Public Function ListContacts() As IEnumerable(Of Contact) Implements IContactManagerRepository.ListContacts
Return _entities.ContactSet.ToList()
End Function
Public Function CreateContact(ByVal contactToCreate As Contact) As Contact Implements IContactManagerRepository.CreateContact
_entities.AddToContactSet(contactToCreate)
_entities.SaveChanges()
Return contactToCreate
End Function
Public Function EditContact(ByVal contactToEdit As Contact) As Contact Implements IContactManagerRepository.EditContact
Dim originalContact = GetContact(contactToEdit.Id)
_entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit)
_entities.SaveChanges()
Return contactToEdit
End Function
Public Sub DeleteContact(ByVal contactToDelete As Contact) Implements IContactManagerRepository.DeleteContact
Dim originalContact = GetContact(contactToDelete.Id)
_entities.DeleteObject(originalContact)
_entities.SaveChanges()
End Sub
End Class
EntityContactManagerRepository sınıfının IContactManagerRepository arabirimini uyguladığına dikkat edin. sınıfı, bu arabirim tarafından açıklanan yöntemlerin beşini de uygular.
Neden bir arabirimle uğraşmamız gerektiğini merak ediyor olabilirsiniz. Neden hem bir arabirim hem de bunu uygulayan bir sınıf oluşturmamız gerekiyor?
Tek bir istisna dışında, uygulamamızın geri kalanı somut sınıfla değil arabirimle etkileşim kurar. EntityContactManagerRepository sınıfı tarafından kullanıma sunulan yöntemleri çağırmak yerine IContactManagerRepository arabirimi tarafından kullanıma sunulan yöntemleri çağıracağız.
Bu şekilde, uygulamamızın geri kalanını değiştirmeye gerek kalmadan arabirimini yeni bir sınıfla uygulayabiliriz. Örneğin, gelecekteki bir tarihte IContactManagerRepository arabirimini uygulayan bir DataServicesContactManagerRepository sınıfı uygulamak isteyebiliriz. DataServicesContactManagerRepository sınıfı, Microsoft Entity Framework yerine veritabanına erişmek için ADO.NET Veri Hizmetleri'ni kullanabilir.
Uygulama kodumuz beton EntityContactManagerRepository sınıfı yerine IContactManagerRepository arabirimine göre programlanmışsa kodumuzun geri kalanını değiştirmeden somut sınıfları değiştirebiliriz. Örneğin, veri erişimimizi veya doğrulama mantığımızı değiştirmeden EntityContactManagerRepository sınıfından DataServicesContactManagerRepository sınıfına geçebiliriz.
Somut sınıflar yerine arabirimlere (soyutlamalar) karşı programlamak, uygulamamızı değiştirmek için daha dayanıklı hale getirir.
Not
Yeniden Düzenle, Arabirimi Ayıkla menü seçeneğini belirleyerek Visual Studio'da somut bir sınıftan hızla bir arabirim oluşturabilirsiniz. Örneğin, önce EntityContactManagerRepository sınıfını oluşturabilir ve ardından Ayıklama Arabirimi'ni kullanarak IContactManagerRepository arabirimini otomatik olarak oluşturabilirsiniz.
Bağımlılık Ekleme Yazılımı Tasarım Desenini Kullanma
Veri erişim kodumuzu ayrı bir Depo sınıfına geçirdiğimize göre, Contact denetleyicimizi bu sınıfı kullanacak şekilde değiştirmemiz gerekir. Denetleyicimizdeki Depo sınıfını kullanmak için Bağımlılık Ekleme adlı yazılım tasarım deseninin avantajlarından yararlanacağız.
Değiştirilen Kişi denetleyicisi Liste 3'te yer alır.
Liste 3 - Controllers\ContactController.vb
Public Class ContactController
Inherits System.Web.Mvc.Controller
Private _repository As IContactManagerRepository
Sub New()
Me.New(new EntityContactManagerRepository())
End Sub
Sub New(repository As IContactManagerRepository)
_repository = repository
End Sub
Protected Sub ValidateContact(contactToValidate As Contact)
If contactToValidate.FirstName.Trim().Length = 0 Then
ModelState.AddModelError("FirstName", "First name is required.")
End If
If contactToValidate.LastName.Trim().Length = 0 Then
ModelState.AddModelError("LastName", "Last name is required.")
End If
If (contactToValidate.Phone.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.")
End If
If (contactToValidate.Email.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.")
End If
End Sub
Function Index() As ActionResult
Return View(_repository.ListContacts())
End Function
Function Create() As ActionResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
' Validation logic
ValidateContact(contactToCreate)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_repository.CreateContact(contactToCreate)
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
Function Edit(ByVal id As Integer) As ActionResult
Return View(_repository.GetContact(id))
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal contactToEdit As Contact) As ActionResult
' Validation logic
ValidateContact(contactToEdit)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_repository.EditContact(contactToEdit)
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
Function Delete(ByVal id As Integer) As ActionResult
Return View(_repository.GetContact(id))
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Delete(ByVal contactToDelete As Contact) As ActionResult
Try
_repository.DeleteContact(contactToDelete)
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
Liste 3'teki Kişi denetleyicisinin iki oluşturucuya sahip olduğuna dikkat edin. İlk oluşturucu, IContactManagerRepository arabiriminin somut bir örneğini ikinci oluşturucuya geçirir. Contact denetleyici sınıfı Oluşturucu Bağımlılık Ekleme'yi kullanır.
EntityContactManagerRepository sınıfının kullanıldığı tek ve tek yer ilk oluşturucudadır. sınıfının geri kalanı beton EntityContactManagerRepository sınıfı yerine IContactManagerRepository arabirimini kullanır.
Bu, gelecekte IContactManagerRepository sınıfının uygulamalarını değiştirmeyi kolaylaştırır. EntityContactManagerRepository sınıfı yerine DataServicesContactRepository sınıfını kullanmak istiyorsanız ilk oluşturucuyu değiştirmeniz gerekir.
Oluşturucu Bağımlılığı ekleme ayrıca Contact denetleyici sınıfını çok test edilebilir hale getirir. Birim testlerinizde, IContactManagerRepository sınıfının sahte bir uygulamasını geçirerek Contact denetleyicisinin örneğini oluşturabilirsiniz. Bağımlılık Ekleme'nin bu özelliği, Contact Manager uygulaması için birim testleri oluştururken bir sonraki yinelemede bizim için çok önemli olacaktır.
Not
Contact controller sınıfını IContactManagerRepository arabiriminin belirli bir uygulamasından tamamen ayrıştırmak istiyorsanız, StructureMap veya Microsoft Entity Framework (MEF) gibi Bağımlılık Eklemeyi destekleyen bir çerçeveden yararlanabilirsiniz. Bağımlılık Ekleme çerçevesinden yararlanarak kodunuzda somut bir sınıfa başvurmanız gerekmez.
Hizmet Katmanı Oluşturma
Doğrulama mantığımızın, Liste 3'teki değiştirilmiş denetleyici sınıfındaki denetleyici mantığımızla hala karma olduğunu fark etmiş olabilirsiniz. Veri erişim mantığımızı yalıtmanın iyi bir fikir olmasıyla aynı nedenle, doğrulama mantığımızı yalıtmak iyi bir fikirdir.
Bu sorunu çözmek için ayrı bir hizmet katmanı oluşturabiliriz. Hizmet katmanı, denetleyicimiz ve depo sınıflarımız arasına ekleyebileceğimiz ayrı bir katmandır. Hizmet katmanı, tüm doğrulama mantığımız dahil olmak üzere iş mantığımızı içerir.
ContactManagerService, Liste 4'te yer alır. Contact denetleyici sınıfından doğrulama mantığını içerir.
Listeleme 4 - Models\ContactManagerService.vb
Public Class ContactManagerService
Implements IContactManagerService
Private _validationDictionary As IValidationDictionary
Private _repository As IContactManagerRepository
Public Sub New(ByVal validationDictionary As IValidationDictionary)
Me.New(validationDictionary, New EntityContactManagerRepository())
End Sub
Public Sub New(ByVal validationDictionary As IValidationDictionary, ByVal repository As IContactManagerRepository)
_validationDictionary = validationDictionary
_repository = repository
End Sub
Public Function ValidateContact(ByVal contactToValidate As Contact) As Boolean
If contactToValidate.FirstName.Trim().Length = 0 Then
_validationDictionary.AddError("FirstName", "First name is required.")
End If
If contactToValidate.LastName.Trim().Length = 0 Then
_validationDictionary.AddError("LastName", "Last name is required.")
End If
If contactToValidate.Phone.Length > 0 AndAlso (Not Regex.IsMatch(contactToValidate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}")) Then
_validationDictionary.AddError("Phone", "Invalid phone number.")
End If
If contactToValidate.Email.Length > 0 AndAlso (Not Regex.IsMatch(contactToValidate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$")) Then
_validationDictionary.AddError("Email", "Invalid email address.")
End If
Return _validationDictionary.IsValid
End Function
#Region "IContactManagerService Members"
Public Function CreateContact(ByVal contactToCreate As Contact) As Boolean Implements IContactManagerService.CreateContact
' Validation logic
If Not ValidateContact(contactToCreate) Then
Return False
End If
' Database logic
Try
_repository.CreateContact(contactToCreate)
Catch
Return False
End Try
Return True
End Function
Public Function EditContact(ByVal contactToEdit As Contact) As Boolean Implements IContactManagerService.EditContact
' Validation logic
If Not ValidateContact(contactToEdit) Then
Return False
End If
' Database logic
Try
_repository.EditContact(contactToEdit)
Catch
Return False
End Try
Return True
End Function
Public Function DeleteContact(ByVal contactToDelete As Contact) As Boolean Implements IContactManagerService.DeleteContact
Try
_repository.DeleteContact(contactToDelete)
Catch
Return False
End Try
Return True
End Function
Public Function GetContact(ByVal id As Integer) As Contact Implements IContactManagerService.GetContact
Return _repository.GetContact(id)
End Function
Public Function ListContacts() As IEnumerable(Of Contact) Implements IContactManagerService.ListContacts
Return _repository.ListContacts()
End Function
#End Region
End Class
ContactManagerService oluşturucusunun geçerlilik sözlüğü gerektirdiğine dikkat edin. Hizmet katmanı bu ValidationDictionary aracılığıyla denetleyici katmanıyla iletişim kurar. Aşağıdaki bölümde, Dekoratör desenini tartışırken ValidationDictionary'i ayrıntılı olarak ele alıyoruz.
Ayrıca ContactManagerService'in IContactManagerService arabirimini uyguladığına da dikkat edin. Her zaman somut sınıflar yerine arabirimlere karşı programlamaya çalışmanız gerekir. Contact Manager uygulamasındaki diğer sınıflar ContactManagerService sınıfıyla doğrudan etkileşim kurmaz. Bunun yerine, tek bir özel durum dışında, Contact Manager uygulamasının geri kalanı IContactManagerService arabirimine göre programlanır.
IContactManagerService arabirimi Listeleme 5'te yer alır.
Listeleme 5 - Models\IContactManagerService.vb
Public Interface IContactManagerService
Function CreateContact(ByVal contactToCreate As Contact) As Boolean
Function DeleteContact(ByVal contactToDelete As Contact) As Boolean
Function EditContact(ByVal contactToEdit As Contact) As Boolean
Function GetContact(ByVal id As Integer) As Contact
Function ListContacts() As IEnumerable(Of Contact)
End Interface
Değiştirilen Contact controller sınıfı Liste 6'da yer alır. Kişi denetleyicisinin artık ContactManager deposuyla etkileşim kurmadığını göreceksiniz. Bunun yerine, Kişi denetleyicisi ContactManager hizmetiyle etkileşim kurar. Her katman diğer katmanlardan mümkün olduğunca yalıtılır.
Listeleme 6 - Controllers\ContactController.vb
Public Class ContactController
Inherits System.Web.Mvc.Controller
Private _service As IContactManagerService
Sub New()
_service = new ContactManagerService(New ModelStateWrapper(ModelState))
End Sub
Sub New(service As IContactManagerService)
_service = service
End Sub
Function Index() As ActionResult
Return View(_service.ListContacts())
End Function
Function Create() As ActionResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
If _service.CreateContact(contactToCreate) Then
Return RedirectToAction("Index")
End If
Return View()
End Function
Function Edit(ByVal id As Integer) As ActionResult
Return View(_service.GetContact(id))
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal contactToEdit As Contact) As ActionResult
If _service.EditContact(contactToEdit) Then
Return RedirectToAction("Index")
End If
Return View()
End Function
Function Delete(ByVal id As Integer) As ActionResult
Return View(_service.GetContact(id))
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Delete(ByVal contactToDelete As Contact) As ActionResult
If _service.DeleteContact(contactToDelete) Then
return RedirectToAction("Index")
End If
Return View()
End Function
End Class
Uygulamamız artık Tek Sorumluluk İlkesi 'nin (SRP) bir altyapısını çalıştırmaz. Liste 6'daki Kişi denetleyicisi, uygulama yürütme akışını denetleme dışında her sorumluluktan alındı. Tüm doğrulama mantığı Kişi denetleyicisinden kaldırıldı ve hizmet katmanına gönderildi. Tüm veritabanı mantığı depo katmanına gönderildi.
Dekoratör Desenini Kullanma
Hizmet katmanımızı denetleyici katmanımızdan tamamen ayrıştırabilmek istiyoruz. Prensip olarak, MVC uygulamamıza başvuru eklemeye gerek kalmadan hizmet katmanımızı denetleyici katmanımızdan ayrı bir derlemede derleyebilmemiz gerekir.
Ancak hizmet katmanımızın doğrulama hata iletilerini denetleyici katmanına geri geçirebilmesi gerekir. Hizmet katmanının denetleyiciyle hizmet katmanını bağlamadan doğrulama hata iletilerini iletmesini nasıl sağlayabiliriz? Dekoratör deseni adlı bir yazılım tasarım deseninin avantajlarından yararlanabiliriz.
Denetleyici, doğrulama hatalarını göstermek için ModelState adlı bir ModelStateDictionary kullanır. Bu nedenle ModelState'i denetleyici katmanından hizmet katmanına geçirmek isteyebilirsiniz. Ancak hizmet katmanında ModelState kullanmak, hizmet katmanınızı ASP.NET MVC çerçevesinin bir özelliğine bağımlı hale getirir. Bir gün hizmet katmanını ASP.NET MVC uygulaması yerine wpf uygulamasıyla kullanmak isteyebileceğiniz için bu durum kötü olabilir. Bu durumda, ModelStateDictionary sınıfını kullanmak için ASP.NET MVC çerçevesine başvurmak istemezsiniz.
Dekoratör düzeni, arabirim uygulamak için mevcut bir sınıfı yeni bir sınıfa sarmalamanızı sağlar. Contact Manager projemiz, Liste 7'de yer alan ModelStateWrapper sınıfını içerir. ModelStateWrapper sınıfı, Listing 8'de arabirimini uygular.
Listeleme 7 - Models\Validation\ModelStateWrapper.vb
Public Class ModelStateWrapper
Implements IValidationDictionary
Private _modelState As ModelStateDictionary
Public Sub New(ByVal modelState As ModelStateDictionary)
_modelState = modelState
End Sub
Public Sub AddError(ByVal key As String, ByVal errorMessage As String) Implements IValidationDictionary.AddError
_modelState.AddModelError(key, errorMessage)
End Sub
Public ReadOnly Property IsValid() As Boolean Implements IValidationDictionary.IsValid
Get
Return _modelState.IsValid
End Get
End Property
End Class
Listeleme 8 - Models\Validation\IValidationDictionary.vb
Public Interface IValidationDictionary
Sub AddError(ByVal key As String, ByVal errorMessage As String)
ReadOnly Property IsValid() As Boolean
End Interface
Liste 5'e yakından bakarsanız ContactManager hizmet katmanının yalnızca IValidationDictionary arabirimini kullandığını görürsünüz. ContactManager hizmeti ModelStateDictionary sınıfına bağımlı değildir. Contact denetleyici ContactManager hizmetini oluşturduğunda, denetleyici ModelState'ini şöyle sarmalar:
_service = new ContactManagerService(New ModelStateWrapper(ModelState))
Özet
Bu yinelemede, Contact Manager uygulamasına yeni bir işlev eklemedik. Bu yinelemenin amacı, Bakımı ve değiştirilmesini kolaylaştırmak için Contact Manager uygulamasını yeniden düzenlemekti.
İlk olarak, Depo yazılım tasarım desenini uyguladık. Tüm veri erişim kodunu ayrı bir ContactManager deposu sınıfına geçirdik.
Ayrıca doğrulama mantığımızı denetleyici mantığımızdan yalıtdık. Tüm doğrulama kodumuzu içeren ayrı bir hizmet katmanı oluşturduk. Denetleyici katmanı hizmet katmanıyla, hizmet katmanı ise depo katmanıyla etkileşim kurar.
Hizmet katmanını oluşturduğumuzda ModelState'i hizmet katmanımızdan yalıtmak için Dekoratör deseninden yararlandık. Hizmet katmanımızda ModelState yerine IValidationDictionary arabirimine karşı programlandık.
Son olarak, Bağımlılık Ekleme deseni adlı bir yazılım tasarım deseninin avantajından yararlandık. Bu düzen, somut sınıflar yerine arabirimlere (soyutlamalar) karşı programlama yapmamızı sağlar. Bağımlılık Ekleme tasarım desenini uygulamak da kodumuzu daha test edilebilir hale getirir. Sonraki yinelemede projemize birim testleri ekleyeceğiz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin