Ne zaman bir geliştirici "bunu yapmanın anlamı nedir?" Bu amaçla size birkaç örnek göstereyim.
Tüm örnekler bu basit veri modeline dayanacaktır:
Bir Person
işletmenin beş mülkü vardır:Id, FirstName, LastName, Age, CityId
Ve uygulamanın bu verileri çeşitli şekillerde (raporlar, formlar, pop-up'lar, ...) kullandığını varsayabilirsiniz.
Tüm uygulama zaten var. Bahsettiğim her şey mevcut kod tabanında bir değişiklik. Bunu hatırlamak önemlidir.
Örnek 1 - Temel veri yapısını değiştirme - DTO olmadan
Gereksinimler değişti. Kişinin yaşının, hükümet veri tabanından dinamik olarak alınması gerekir (diyelim ki ad ve soyadlarına göre).
Age
Değeri artık yerel olarak depolamanız gerekmediğinden , Person
varlıktan kaldırılması gerekir . Burada varlığın veritabanı verilerini temsil ettiğini ve daha fazlası olmadığını anlamak önemlidir . Veritabanında değilse, varlıkta değildir.
Yaşı hükümetin web hizmetinden aldığınızda, bu farklı bir nesnede (veya int) depolanır.
Ancak ön ucunuz hala bir yaş gösteriyor. Tüm görünümler, Person.Age
artık mevcut olmayan mülkü kullanacak şekilde ayarlandı . Bir sorun kendiliğinden ortaya çıkar: Bir kişiye ilişkin tüm görünümlerin Age
düzeltilmesi gerekir .
Örnek 2 - Temel veri yapısını değiştirme - DTO ile
Eski sistemde, orada da PersonDTO
aynı beş özelliklere sahip varlık: Id, FirstName, LastName, Age, CityId
. A alındıktan sonra Person
, hizmet katmanı a PersonDTO
öğesine dönüştürür ve sonra döndürür.
Ama şimdi, gereksinimler değişti. Kişinin yaşının, hükümet veri tabanından dinamik olarak alınması gerekir (diyelim ki ad ve soyadlarına göre).
Age
Değeri artık yerel olarak depolamanız gerekmediğinden , Person
varlıktan kaldırılması gerekir . Burada varlığın veritabanı verilerini temsil ettiğini ve daha fazlası olmadığını anlamak önemlidir . Veritabanında değilse, varlıkta değildir.
Eğer bir aracı var Ancak, PersonDTO
bu bu sınıf olduğunu görmek önemlidir tutmakAge
özelliği. Hizmet katmanı getirilecek Person
, a dönüştürülecek PersonDTO
, daha sonra kişinin yaşını hükümetin web hizmetinden alacak, bu değeri depolayacak PersonDTO.Age
ve o nesneyi iletecektir.
Burada önemli olan, servis katmanını kullanan herkesin eski ve yeni sistem arasında bir fark görmemesidir . Buna ön ucunuz da dahildir. Eski sistemde tam bir PersonDTO
nesne aldı . Ve yeni sistemde hala tam bir PersonDTO
nesne alıyor. Görünümlerin güncellenmesi gerekmez .
Endişelerin cümle ayrılmasını kullandığımızda kastettiğimiz budur : İki farklı endişe vardır (verileri veritabanında depolamak, verileri ön uca sunmak) ve her biri farklı bir veri türüne ihtiyaç duyarlar. Bu iki veri türü şu anda aynı verileri içeriyor olsa bile, bu gelecekte değişebilir.
Verilen örnekte, Age
iki veri türü arasında bir fark vardır: Person
(veritabanı varlığı) bir Age
, ancak PersonDTO
(ön uç veri türü) buna ihtiyaç duymaz.
Endişeleri (= ayrı veri türleri oluşturmak) başından ayırarak, kod tabanı veri modelinde yapılan değişikliklere çok daha dayanıklıdır.
Veritabanına yeni bir sütun eklendiğinde, bir DTO nesnesine sahip olmanın, özelliği hem varlık hem de DTO'ya ekleyerek çift çalışma yapmanız gerektiği anlamına gelebilir. Bu teknik olarak doğrudur. Bir yerine iki sınıfı korumak için biraz fazla çaba gerektirir.
Ancak, gerekli çabayı karşılaştırmanız gerekir. Bir veya daha fazla yeni sütun eklendiğinde, birkaç özelliğin kopyalanması / yapıştırılması bu kadar uzun sürmez. Veri modeli yapısal olarak değiştiğinde, muhtemelen sadece çalışma zamanında (ve derleme zamanında değil) hatalara neden olacak şekilde ön ucu değiştirmek zorunda kaldığında, daha fazla çaba harcar ve geliştiricilerin hata aramalarını gerektirir.
Size daha fazla örnek verebilirim, ancak prensip her zaman aynı olacaktır.
Özetlemek
- Ayrı sorumlulukların (endişelerin) birbirinden ayrı çalışması gerekir. Veri sınıfları gibi kaynakları paylaşmamalıdır (ör.
Person
)
- Bir varlığın ve DTO'nun aynı özelliklere sahip olması, onları aynı varlıkla birleştirmeniz gerektiği anlamına gelmez. Köşeleri kesmeyin.
- Daha açık bir örnek olarak, veritabanımızın ülkeleri, şarkıları ve insanları içerdiğini varsayalım. Tüm bu varlıkların bir
Name
. Ancak hepsinin bir Name
mülkü olması, onları ortak bir EntityWithName
temel sınıftan miras almamız gerektiği anlamına gelmez . Farklı Name
özelliklerin anlamlı bir ilişkisi yoktur.
- Özelliklerden biri değiştiğinde (örneğin, bir şarkının
Name
adı değiştirilirse Title
veya bir kişi a FirstName
ve alırsa LastName
), ilk etapta bile ihtiyaç duymadığınız mirasın geri alınması için daha fazla çaba harcamak zorunda kalacaksınız .
- Her ne kadar açık olmasa da, bir varlığınız olduğunda DTO'ya ihtiyacınız olmadığı iddiası aynıdır. Şu an bakıyorsunuz , ancak gelecekteki değişikliklere hazırlıklı değilsiniz. EĞER varlık ve DTO tam olarak aynıdır ve EĞER veri modeline herhangi bir değişiklik olmayacak garanti edemez; DTO'yu atlayabileceğiniz konusunda haklısınız. Ama mesele şu ki, veri modelinin asla değişmeyeceğini asla garanti edemezsiniz.
- İyi uygulama her zaman derhal ödeme yapmaz. Eski bir uygulamayı yeniden ziyaret etmeniz gerektiğinde gelecekte ödemeye başlayabilir.
- Mevcut kod tabanlarının ana katili, kod kalitesinin düşmesine izin vermek ve sürdürülemez olan spagetti kodunun gereksiz bir karmaşasına dönüşene kadar kod tabanının korunmasını sürekli olarak zorlaştırıyor.
- Endişelerin en baştan ayrılmasını sağlamak gibi iyi uygulama, kod tabanının mümkün olduğu kadar uzun süre korunabilmesi için kaygan kötü bakım eğiminden kaçınmayı amaçlamaktadır.
Endişeleri birbirinden ayırmak için genel bir kural olarak, bunu şu şekilde düşünün:
Her endişenin (kullanıcı arayüzü, veritabanı, mantık) farklı bir konumdaki farklı bir kişi tarafından ele alındığını varsayalım. Yalnızca e-posta ile iletişim kurabilirler.
İyi ayrılmış bir kod tabanında, belirli bir endişede yapılacak bir değişikliğin yalnızca bir kişi tarafından ele alınması gerekir:
- Kullanıcı arayüzünün değiştirilmesi yalnızca UI geliştiricisini içerir.
- Veri depolama yönteminin değiştirilmesi yalnızca veritabanı dev.
- İş mantığının değiştirilmesi yalnızca iş geliştiriciyi içerir.
Bu geliştiricilerin tümü aynı Person
kuruluşu kullanıyorsa ve kuruluşta küçük bir değişiklik yapılmışsa, herkesin sürece dahil olması gerekir.
Ancak, her katman için ayrı veri sınıfları kullanarak, bu sorun yaygın değildir:
- Veritabanı geliştiricisi geçerli bir
PersonDTO
nesneyi döndürebildiği sürece , işletme ve kullanıcı arabirimi, verilerin saklanma / alınma şeklini değiştirmesini umursamaz.
- İşletme geliştiricisi verileri veritabanında sakladığı ve gerekli verileri ön uca sağladığı sürece, veritabanı ve UI geliştiricileri, iş kurallarını yeniden düzenlemeye karar verip vermeyeceğini umursamıyorlar.
- Kullanıcı arayüzü `PersonViewModel etrafında tasarlanabildiği sürece, kullanıcı arayüzü kullanıcı arayüzü istedikleri gibi oluşturabilir. Veritabanı ve iş geliştiricileri nasıl yapıldığını umursamıyor, çünkü onları etkilemiyor.
Buradaki anahtar ifade, onları etkilememesi nedeniyle . Endişelerin iyi bir şekilde ayrıştırılması, diğer tarafları etkilemeyi (ve dolayısıyla dahil etmek zorunda kalmayı) en aza indirmeyi amaçlamaktadır.
Tabii ki, bazı büyük değişiklikler birden fazla kişiyi dahil etmekten kaçınamaz, örneğin veritabanına tamamen yeni bir varlık eklendiğinde. Ancak bir uygulamanın ömrü boyunca yapmanız gereken küçük değişikliklerin miktarını hafife almayın. Büyük değişiklikler sayısal bir azınlıktır.
What's the benefit of these conversions?
Kalıcılık veri modelinin tüketicilere sunulan veri modelinden (temsil) ayrıştırılması. Ayrışmanın faydaları SE'de geniş çapta tartışılmıştır. Bununla birlikte, DTO'ların altındaki amaç, istemcilerin sunucuya çağrı kaydetmesi için gerekli görülen bilgiler kadar tek bir yanıtta toplanmasıdır. İletişim istemci-sunucusunu daha pürüzsüz yapan nedir.