MVC (Model, Görünüm, Kontrolör), bir uygulamada bakımı kolaylaştırmak için kod düzenlemek için kullanılan bir kalıptır.
Bir stüdyoda kamerasıyla bir fotoğrafçı düşünün. Bir müşteri ondan bir kutunun fotoğrafını çekmesini ister.
MVC olmayan mimariler birbirine sıkı sıkıya entegre olma eğilimindedir. Kutu, denetleyici ve kamera aynı nesneden biriyse, yeni bir görünüm elde etmek istediğimizde hem kutuyu hem de kamerayı söküp yeniden inşa etmemiz gerekirdi . Ayrıca, fotoğraf çekmek her zaman bir selfie çekmeye çalışmak gibi olurdu - ve bu her zaman çok kolay değil.
bwaha yazdı:
Yazar, MVC tasarımının bir örneği olarak wxPython'daki mvctree.py dosyasına atıfta bulunur. Ancak hala çok yeşil olduğumdan, bu özel örneği çok karmaşık buluyorum ve yazarın önerdiği ayrımları anlamıyorum.
MVC, endişelerin ayrılması ile ilgilidir.
Modelin program verilerini yönetmekten sorumludur (hem özel hem de müşteri verileri). Görünüm / Kontrolör, dış dünyaya programın müşteri verileriyle etkileşimde bulunmak için araçlar sağlamaktan sorumludur.
Model, programın diğer bölümlerinin onunla etkileşime girmesini sağlamak için bir iç arayüz (API) sağlar. Görünüm / Denetleyici, programın dışındaki her şeyle iletişim kurmasını sağlamak için harici bir arabirim (GUI / CLI / web formu / üst düzey IPC / vb.) Sağlar.
Modelin program verilerinin bütünlüğünü korumaktan sorumludur, çünkü eğer bu bozulursa herkes için oyun biter. Görünüm / Denetleyici, kullanıcı arabiriminin bütünlüğünün korunmasından, tüm metin görünümlerinin güncel değerler gösterdiğinden, geçerli odak için geçerli olmayan menü öğelerinin devre dışı bırakıldığından vb. Sorumludur.
Model Görünüm / Denetleyici kodu içermiyor; GUI widget sınıfı yok, iletişim kutuları düzenlemek veya kullanıcı girişi almak için kod yok. Görünüm / Kontrolör Model kodu içermiyor; URL'lerin doğrulanması veya SQL sorgularının gerçekleştirilmesi için kod yoktur ve orijinal durumların hiçbiri yoktur: widget'lar tarafından tutulan veriler yalnızca görüntüleme amaçlıdır ve yalnızca Modelde depolanan gerçek verilerin bir yansımasıdır.
Şimdi, işte gerçek bir MVC tasarımının testi: programın bir Görüntü / Denetleyici takılı olmasa bile özünde tamamen işlevsel olması gerekir. Tamam, dış dünya onunla bu şekilde etkileşime girmekte zorlanacak, ancak uygun Model API gelişmelerini bildiği sürece, program verileri normal şekilde tutacak ve değiştirecektir.
Bu neden mümkün? Basit cevap, Model ve Görünüm / Denetleyici katmanları arasındaki düşük bağlantı sayesinde hepsi bu. Ancak, bu tam hikaye değil. Ne bütün MVC deseni anahtarıdır olan yönü TÜM talimatları akış: O bağlantı gider hangi gelen Görünüm / Kontrolör için Modeli. Model ASLA Görünüm / Denetleyiciye ne yapacağını söylemez.
Neden? Çünkü MVC’de, Görünüm / Denetleyici Model hakkında biraz bilgi sahibi olurken (özellikle Model API’sı), ancak Model Görünüm / Denetleyici ile ilgili herhangi bir şey bilmesine izin verilmez.
Neden? Çünkü MVC endişelerin net bir şekilde ayrılmasıyla ilgilidir.
Neden? Programın karmaşıklığının kontrolden çıkmaması ve sizi, geliştiricinin altından gömülmesini önlemeye yardımcı olmak için. Program büyüdükçe, programdaki bileşen sayısı da artar. Ve bu bileşenler arasında daha fazla bağlantı var, geliştiricilerin ayrı ayrı bileşenleri korumasını / genişletmesini / değiştirmesini, hatta tüm sistemin nasıl çalıştığını takip etmesini zorlaştırıyor. Kendinize şunu sorun: programın yapısının bir şemasına bakarken, bir ağaç mı yoksa bir kedinin beşiği mi görmek istersiniz? MVC paterni, dairesel bağlantıları devre dışı bırakarak ikincisini önler: B, A'ya bağlanabilir, ancak A, B'ye bağlanamaz. Bu durumda, A, Model'dir ve B, Görüntü / Denetleyici'dir.
BTW, keskinseniz, daha önce açıklanan 'tek yönlü' kısıtlamada bir sorun olduğunu fark edeceksiniz: Model, Model bile izin verilmediğinde Model'in kullanıcı verilerindeki değişikliklerin Görünümü / Denetleyicisini nasıl bilgilendirebilir? View / Controller'ın mesaj göndermeye aldırış etmediğini biliyor musun? Ancak endişelenmeyin: Bunun bir çözümü var ve ilk başta biraz dolambaçlı görünse de oldukça temiz. Birazdan buna geri döneceğiz.
Daha sonra, pratik olarak, bir View / Controller nesnesi, Model'in API'sı aracılığıyla, 1. Model'e bir şeyler yapmasını söyler (komutları yürütür) ve 2. Model'e bir şeyler vermesini söyler (veri döndürür). Görünüm / Denetleyici katmanı, talimatları Model katmanına
iter ve bilgileri Model katmanından çeker .
İlk MyCoolListControl örneğinizin yanlış gittiği yer burasıdır, çünkü o sınıfın API'si bu bilginin
içine itilmesini gerektirir , bu nedenle katmanlar arasında iki yönlü bir bağlantı kurmaya, MVC kurallarını ihlal etmeye ve sizi doğrudan geri almaya başlıyorsunuz Kedinin beşiği mimarisi [muhtemelen] ilk etapta kaçınmaya çalışıyordu.
Bunun yerine, MyCoolListControl sınıfı, ihtiyaç duyduğu zaman aşağıdaki katmandan ihtiyaç duyduğu verileri çekerek akışa devam etmelidir. Bir liste gereci söz konusu olduğunda, bu genellikle kaç değer olduğunu sormak ve daha sonra sırayla bu maddeleri sormak anlamına gelir, çünkü bu, onu yapmanın en basit ve en gevşek yoluyla ilgilidir ve bu nedenle de kuplajı minimumda tutar. Ve eğer widget bu kullanıcıya kullanıcıya güzel bir alfabetik sıraya göre dizmek isterse, o zaman bu perogatif; ve elbette ki sorumluluğu.
Şimdi, daha önce de bahsettiğim gibi son bir bilmece: UI ekranını Modelin durumu ile MVC tabanlı bir sistemde nasıl senkronize ediyorsun?
İşte problem: birçok View nesnesi durumludur, örneğin bir onay kutusu işaretlenebilir veya işaretlenmemiş olabilir, bir metin alanı düzenlenebilir bir metin içerebilir. Bununla birlikte, MVC tüm kullanıcı verilerinin Model katmanında saklanmasını zorunlu kılar, bu nedenle görüntüleme amacıyla diğer katmanlar tarafından tutulan herhangi bir verinin (onay kutusunun durumu, metin alanının geçerli metni) bu nedenle bu birincil Model verilerinin bir kopyası olması gerekir. Ancak Modelin durumu değişirse, Görünüm'ün bu durumun kopyası artık doğru olmayacak ve yenilenmesi gerekecektir.
Ama nasıl? MVC deseni, Modelin bu bilgilerin yeni bir kopyasını Görünüm katmanına sokmasını önler. Heck, Modelin Durumun değiştiğini söylemek için bir Mesaj göndermesine bile izin vermiyor.
Neredeyse. Tamam, Model katmanının doğrudan diğer katmanlarla konuşmasına izin verilmez, çünkü bunu yapmak için bu katmanlarla ilgili bir şeyler bilmesi gerekir ve MVC kuralları bunu önler. Bununla birlikte, bir ağaç ormana düşerse ve kimse duymayacaksa, ses çıkarır mı?
Yanıt, gördüğünüz gibi, Model katmanına kimseye ilan edemeyeceği bir yer sağlayarak, özellikle ilginç bir şey yaptığını bildiren bir bildirim sistemi kurmaktır. Diğer katmanlar daha sonra, gerçekten ilgilendikleri duyuruları dinlemek için bu bildirim sistemiyle dinleyicileri gönderebilir. Model katmanı kimin dinlediği hakkında bir şey bilmek zorunda değildir (veya birileri dinliyor olsa bile!); sadece bir duyuru yayınlar ve sonra unutur. Ve eğer biri bu duyuruyu duyarsa ve daha sonra bir şeyler yapmak istiyorsa - Modelden bazı yeni veriler istemesini isteyin, böylece ekran görüntüsünü güncelleyebilir - o zaman harika. Model sadece API tanımının bir parçası olarak hangi bildirimleri gönderdiğini listeler; ve bu bilgiyle başkasının yaptığı şey onlara bağlıdır.
MVC korunur ve herkes mutludur. Uygulama çerçeveniz yerleşik bir bildirim sistemi sağlayabilir ya da yoksa kendiniz yazabilirsiniz ('gözlemci modeline bakın).
...
Neyse, yardımcı olur umarım. MVC'nin arkasındaki motivasyonları anladıktan sonra, işlerin neden yapıldığı gibi yapılmasının sebepleri, ilk bakışta bile gerekenden daha karmaşık göründüğünde bile, anlamlı olmaya başlar.
Alkış,
vardır