Kavrama. En iyi uygulamalar


11

Bu konudan sonra başladım

Singleton Kalıbı

Sınıflarımın ne kadar bağlı olduğunu ve gevşek bağlantıyı en iyi nasıl elde edebileceğimi düşündürdü. Unutmayın ki yeni bir programcıyım (ilk işime 4 ay) ve bu gerçekten bunu ilk kez göz önünde bulunduruyorum ve konsepti anlamaya çok hevesliyim.

Peki, ağır bağlantıya karşı gevşek bağlantıyı tam olarak ne oluşturur? Şu anki (ve ilk projemde), GUI bölümünün olayları için nesneler oluşturduğu ve alt aboneleri oluşturduğu ac # winforms projesi üzerinde çalışıyorum, tetiklendiklerinde GUI başka bir nesne oluşturur (bu örnekte bir datagridview (sınıf Ben standart bir datagridview sarar ve ek işlevsellik ekledi yarattık) ve GUI ekler.Bu kötü bir bağlantı veya iyi mi?

Gerçekten kötü alışkanlıklara girmek ve kötü kodlamaya başlamak istemiyorum, bu yüzden cevaplarınızı takdir ediyorum.

Yanıtlar:


11

Kodunuzu gevşek bir şekilde birleştirmek için hatırlamanız gereken birkaç basit şey var:

Bölüm 1:

Teknik olarak "Endişelerin Ayrılması" olarak bilinir. Her sınıfın belirli bir rolü vardır, iş mantığını veya uygulama mantığını idare etmelidir. Her iki sorumluluğu da birleştiren sınıftan uzak durmaya çalışın. yani verileri yöneten (geniş terimli) bir sınıf uygulama mantığı iken, verileri kullanan bir sınıf iş mantığıdır.

Şahsen ben buna (kendi küçük dünyamda) atıfta bulunuyorum create it or use it. Bir sınıf bir nesne yaratmalı veya hiçbir zaman ikisini birden yapmaması gereken bir nesne kullanmalıdır.

Bölüm 2:

Endişe ayrılığı nasıl uygulanır.
Başlangıç ​​noktası olarak iki basit teknik vardır:

Not: Tasarım desenleri mutlak değildir.
Durumlara göre özelleştirilmeleri gerekiyor, ancak tüm uygulamalara benzer bir teması var. Bu yüzden aşağıdaki örneklere bakmayın ve bunu katı bir şekilde izlemem gerektiğini söyleyin; bunlar sadece örnektir (ve bu konuda biraz çelişkilidir).

Bağımlılık Enjeksiyonu :

Burası, sınıfın kullandığı bir nesneye geçtiğiniz yerdir. Bir arabirime dayanarak ilettiğiniz nesne, böylece sınıfınız onunla ne yapacağını bilir, ancak gerçek uygulamayı bilmesine gerek yoktur.

class Tokenizer
{
    public:
        Tokenizer(std::istream& s)
            : stream(s)
        {}
        std::string nextToken() { std::string token; stream >> token;return token;}
    private:
        std::istream& stream;
};

Burada akışı Tokenizer'e enjekte ediyoruz. Belirteç, std :: istream arabirimini uyguladığı sürece akışın ne tür olduğunu bilmez.

Servis Konumlandırıcı Deseni :

Servis bulucu modeli bağımlılık enjeksiyonunda küçük bir değişikliktir. Kullanabileceği bir nesneyi vermek yerine, ona kullanmak istediğiniz nesneyi nasıl bulacağını (oluşturduğunu) bilen bir nesne iletirsiniz.

class Application
{
     public:
         Application(Persister& p)
             : persistor(p)
         {}

         void save()
         {
             std::auto_ptr<SaveDialog> saveDialog = persistor.getSaveDialog();
             saveDialog.DoSaveAction();
         }

         void load()
         {
             std::auto_ptr<LoadDialog> loadDialog = persistor.getLoadDialog();
             loadDialog.DoLoadAction();
         }
    private:
        Persister& persistor;
};

Burada uygulama nesnesine bir persistor nesnesi geçiyoruz. Bir kaydetme / yükleme eylemi gerçekleştirdiğinizde, eylemin nasıl yapılacağını gerçekten bilen bir nesne oluşturmak için persistor kullanılır. Not: Yine direnç bir arayüzdür ve duruma bağlı olarak farklı uygulamalar sağlayabilirsiniz.

Bu, potentiallyher eylem başlattığınızda benzersiz bir nesne gerektiğinde kullanışlıdır .

Şahsen bunun birim testleri yazarken özellikle yararlı olduğunu düşünüyorum.

Desen Notu:

Tasarım modelleri kendi başına büyük bir konudur. Bu, gevşek bağlantıya yardımcı olmak için kullanabileceğiniz özel bir desen listesi değildir; bu sadece ortak bir başlangıç ​​noktasıdır.

Tecrübe ile, zaten bu kalıpları kullandığınızı fark edeceksiniz, sadece onların resmi adlarını kullanmadığınızdır. İsimlerini standart hale getirerek (ve herkesin onları öğrenmesini sağlayarak) fikirleri iletmenin kolay ve hızlı olduğunu görüyoruz.


3
@Darren Young: Kabul ettiğin için teşekkürler. Ama sorunuz sadece üç saat. Bir gün içinde geri gelecekti ve başkalarının daha iyi cevaplar sağlamadığını doğrulayın.
Martin York

Mükemmel yanıt için teşekkürler. Endişe ayrılması konusunda .... Ben onun kullanımı için bazı veri gerektiren sınıfları var ve sonra bu verilerle bir şeyler yapmak. Geçmişte böyle dersler tasarladım. Bu nedenle, verileri alan ve doğru forma adapte eden bir sınıf oluşturmak ve daha sonra verileri gerçekten kullanmak için başka bir sınıf oluşturmak daha iyi olur mu?
Darren Young

@Darren Young: Tüm programlamada olduğu gibi, çizgi gri ve bulanıktır, iyi tanımlanmamıştır. Kodunuzu okumadan kesin bir yanıt vermek zor. Ama konuştuğumda managing the datadeğişkenlere atıfta bulunuyorum (gerçek verilere değil). Bu nedenle, işaretçiler gibi şeylerin sızdırılmaması için yönetilmesi gerekir. Ancak veriler enjekte edilebilir veya verilerin nasıl alınacağı soyutlanabilir (böylece sınıfınız farklı veri alma yöntemleriyle yeniden kullanılabilir). Daha kesin olamadığım için üzgünüm.
Martin York

1
@Darren Young: Cevabında @StuperUser tarafından belirtildiği gibi. Denize gitme (AKA minutae of loose coupling(minutae kelimesini seviyorum)). Programlamanın sırrı, tekniklerin ne zaman kullanılacağını öğrenmektir. Aşırı kullanım bir kod karmaşasına yol açabilir.
Martin York

@ Martin - tavsiye için teşekkürler. Sanırım şu anda mücadele ediyorum ..... Kodumu mimarisi hakkında sürekli endişe ve C # kullandığım belirli bir dil öğrenmeye çalışıyorum. Sanırım deneyim ve bu şeyleri öğrenme arzumla gelecek. Yorumlarınız için teşekkür ederim.
Darren Young

6

ASP.NET geliştiricisiyim, bu yüzden WinForms kuplajı hakkında çok fazla şey bilmiyorum, ancak 3 katmanlı uygulama mimarisi UI, Domain, Data Access Layer (DAL) varsayarak N-Tier web uygulamalarından biraz biliyorum.

Gevşek bağlantı soyutlamalarla ilgilidir.

@MKO'nun bir montajı başka bir montajla değiştirip değiştiremeyeceğinizi belirttiği gibi (örneğin, Domain projenizi kullanan yeni bir UI projesi, bir veritabanı yerine bir elektronik tabloya kaydeden yeni bir DAL), gevşek bağlantı vardır. Etki Alanınız ve DAL'niz zincirin ilerisindeki projelere bağlıysa, bağlantı daha gevşek olabilir.

Gevşek bir şekilde bağlanan bir şeyin bir yönü, bir nesneyi aynı arabirimi uygulayan başka bir nesneyle değiştirip değiştiremeyeceğinizdir. Gerçek nesneye değil, yaptığı şeyin (arayüzünün) soyut açıklamasına bağlıdır .
Gevşek bağlantı, arayüzler ve Bağımlılık Enjektörleri (DI) ve Konversiyon Kontrol (IoC), test edilebilirlik tasarımının izolasyon yönü için faydalıdır.

UI projesindeki bir nesne, Domain projesinde bir Depo nesnesini çağırır. Test edilen kodun kullandığı havuzla aynı arabirimi uygulayan sahte bir nesne
oluşturabilir , ardından testler için özel davranışlar yazabilir ( kaydedilen / silen / alınan / kaydedilen üretim kodunu önlemek için taslaklar ve taslak olarak hareket eden ve takip eden alaylar) Test amacıyla sahte nesnenin durumunun). Aranan tek üretim kodunun artık yalnızca kullanıcı arabirimi nesnenizde olduğu anlamına gelir, testiniz yalnızca bu yönteme aykırı olur ve tüm test hataları bu yöntemin kusurunu yalıtır.

Ayrıca, VS'deki Analiz menüsünde (sahip olduğunuz sürüme bağlı olarak) projeniz için Kod Metriklerini Hesaplamak için araçlar vardır, bunlardan biri Sınıf Bağlantısıdır, bu konuda MSDN belgelerinde daha fazla bilgi olacaktır.

Anlamayın TOO YOK şans şeyler (birden fazla UI ile örneğin etki alanı projesi) yeniden almak için ve ürünün ömrü küçük olduğunu varsa, gerçi gevşek bağlantısının minutae saplanıp, ardından gevşek bağlantı daha az olur (yine de dikkate alınacaktır), ancak yine de kodunuzu inceleyecek olan mimarların / teknoloji liderlerinin sorumluluğu olacaktır.


3

Birleştirme, bir sınıfın diğeriyle ilgili doğrudan bilgi derecesini ifade eder . Bu, kapsülleme ile kapsüllemenin karşılaştırılması anlamına gelmez. Bir sınıfın başka bir sınıfın nitelikleri veya uygulaması hakkındaki bilgisine değil, diğer sınıfın kendisinin bilgisine atıfta bulunur. Bağımlı bir sınıf, gerekli davranışı sağlayan somut bir sınıfa doğrudan bir işaretçi içerdiğinde güçlü bağlanma oluşur. Bağımlılık sınıfında bir değişiklik yapılmasına gerek olmadan bağımlılık değiştirilemez veya "imzası" değiştirilemez. Gevşek bağlantı, bağımlı sınıf yalnızca bir arabirime bir işaretçi içerdiğinde oluşur; bu daha sonra bir veya daha fazla somut sınıf tarafından uygulanabilir.Bağımlı sınıfın bağımlılığı, arabirim tarafından belirtilen bir "sözleşmeye" bağlıdır; sınıfların uygulanması gereken yöntemlerin ve / veya özelliklerin tanımlanmış bir listesi. Arabirimi uygulayan herhangi bir sınıf, bu nedenle sınıfı değiştirmek zorunda kalmadan bağımlı bir sınıfın bağımlılığını tatmin edebilir. Bu yazılım tasarımında genişletilebilirlik sağlar; bağımlı sınıfta değişiklik yapılmasına gerek kalmadan, bazı veya tüm durumlarda geçerli bağımlılığın yerini almak için bir arabirim uygulayan yeni bir sınıf yazılabilir; yeni ve eski sınıflar serbestçe değiştirilebilir. Güçlü bağlantı buna izin vermez. Ref Link.


3

5 SOLID prensibine bir göz atın . SRP'ye bağlı kalarak, ISS ve DIP, DIP açık arayla en güçlü bağlantıdır. Daha önce bahsedilen DI'nin altındaki temel prensiptir .

Ayrıca, GRASP bir göz atmaya değer. Soyut kavramlar (ilk başta uygulamak zor bulacaksınız) ve somut kalıplar (aslında yardımcı olabilir) arasında garip bir karışımdır, ancak güzellik muhtemelen şu anda endişelerinizin en azıdır.

Ve son olarak, IoC'deki bu bölümü yaygın tekniklere giriş noktası olarak oldukça yararlı bulabilirsiniz .

Aslında, yığın akışında bir soru buldum , burada somut bir problem üzerinde SOLID uygulamasını gösterdim. İlginç bir okuma olabilir.


1

Wikipedia'ya göre:

Bilgisayar ve sistem tasarımında gevşek bağlanmış bir sistem, bileşenlerinin her birinin diğer ayrı bileşenlerin tanımları hakkında çok az bilgiye sahip olduğu veya hiç kullanmadığı bir sistemdir.

Sıkı kaplin sorunu, değişiklik yapmayı zorlaştırır. (Birçok yazar bunun öncelikle bakım sırasında sorunlara neden olduğunu öne sürüyor, ancak benim deneyimime göre ilk geliştirme sırasında da alakalı.) Sıkı birleştirilmiş sistemlerde gerçekleşme eğilimi, sistemdeki bir modüldeki değişikliğin ek değişiklikler gerektirmesidir. bağlı olduğu modüllerde. Çoğu zaman, bu diğer modüllerde daha fazla değişiklik gerektirir ve bu böyle devam eder.

Aksine, gevşek bağlı bir sistemde değişiklikler nispeten izole edilir. Bu nedenle daha az maliyetlidirler ve daha güvenli bir şekilde yapılabilirler.

Özel örneğinizde, olay işleme öğeleri GUI ile temel alınan veriler arasında bir miktar ayrım sağlar. Ancak, keşfedebileceğiniz başka ayrılık alanları varmış gibi geliyor. Özel durumunuz hakkında daha fazla ayrıntı olmadan, spesifik olmak zordur. Ancak, birbirinden ayrılan 3 katmanlı bir mimari ile başlayabilirsiniz:

  • Veri depolama ve alma mantığı
  • İş mantığı
  • Kullanıcı arayüzünü çalıştırmak için mantık gerekiyor

Dikkate alınması gereken bir şey, tek bir geliştiriciye sahip küçük, bir kerelik uygulamalar için, her düzeyde gevşek kuplajı uygulamanın faydalarının çabaya değmeyebileceğidir. Öte yandan, birden fazla geliştirici ile daha büyük daha karmaşık uygulamalar bir zorunluluktur. Başlangıçta, mimariye ilişkin koda aşina olmayan soyutlamaları tanıtmak ve geliştiricileri eğitmek için bir maliyet söz konusudur. Bununla birlikte, uzun vadede, gevşek bağlantı maliyetlerin çok üzerinde avantajlar sunmaktadır.

Gevşek bağlı sistemler tasarlamak konusunda ciddiyseniz, SOLID ilkelerini ve tasarım modellerini okuyun.

Bununla birlikte, gerçekleştirilmesi gereken önemli şey bu örüntülerin ve ilkelerin sadece örüntüler ve ilkeler olduğudur. Bunlar değil hükmeder. Bu, pragmatik ve akıllı bir şekilde uygulanması gerektiği anlamına gelir

Kalıplar söz konusu olduğunda, kalıplardan herhangi birinin tek bir "doğru" uygulamasının olmadığını anlamak önemlidir. Kendi uygulamanızı tasarlamak için çerez kesici şablonlar da değildir. Size, iyi bir çözümün hangi şekle sahip olabileceğini söylemek ve tasarım kararlarını diğer geliştiricilerle iletmek için ortak bir dil sunmak için oradalar.

Herşey gönlünce olsun.


1

Bağımlılık enjeksiyonu, strateji modelleri ve olayları kullanın. Genel olarak: tasarım modellerini okuyun, hepsi gevşek birleştirme ve bağımlılıkları azaltma ile ilgilidir. Bağımlılık enjeksiyonu ve strateji kalıpları bazı arayüzler gerektirirken, olayların alacağınız kadar gevşek olduğunu söyleyebilirim.

İyi bir hile, sınıfları farklı kütüphanelere / meclislere yerleştirmek ve mümkün olduğunca az sayıda kütüphaneye bağımlı hale getirmektir;


4
Prezervatif soyut bir BT terimi mi yoksa ben sadece ceza almıyor muyum?
Darren Young

3
Bağımlılık enjeksiyon kabı için başka bir isim.
Mchl

2
Ayrıca virüslerin yayılmasını önlemek için harika bir yoldur. Aynı şeyden mi bahsediyoruz?
sova

1
Ağır bağlantı genellikle arka uçta yapılır
Homde

1
Başlık ayarlamak biçimlendirmeyi kötüye kullanıyor
Homde

0

Alternatif bir görüş sunayım. Ben sadece her sınıf iyi bir API olduğunu düşünüyorum. Yöntemlerin çağrıldığı sıra açıktır. Yaptıkları açık. Yöntem sayısını gereken asgariye indirdiniz. Örneğin,

init, açık, kapat

karşı

setTheFoo, setBar, initX, getConnection, kapat

Birincisi açık ve güzel bir API gibi görünüyor. İkincisi yanlış sırada çağrıldığında hatalara neden olabilir.

Arayanları değiştirmek ve yeniden derlemek zorunda kaldığım için fazla endişelenmiyorum. Bazı yeni ve bazı 15 yaşında kod bir sürü korumak. Değişiklik yaptığımda genellikle derleyici hataları istiyorum. Bazen bu nedenle bir API'yı bilerek bozurum. Bana her arayanın sonuçlarını gözden geçirme şansı veriyor. Bağımlılık enjeksiyon büyük bir hayranı değilim çünkü siyah kutular olmadan kodumu görsel olarak izlemek istiyorum ve derleyici mümkün olduğunca çok hata yakalamak istiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.