MVC'de bir denetleyici sınıfında özel, eylemsiz, işlevlere sahip olmak iyi bir uygulama olarak kabul edilir mi?


10

Bazen denetleyici sınıfındaki eylem işlevleri, Modelden Görünüme veri akışını basitçe kontrol etmek için birçok kod satırı ile çok büyük ve kötü olabilir. Bir noktada bu devasa işlevler, iyi kodun temel ilkelerini tamamen kaybeder, yani sadece bir şey yapmak, küçük, okunabilir ve yönetilebilir olmak vb.

Bu devasa eylem işlevlerini denetleyici sınıfındaki daha küçük özel işlevlere bölmek iyi bir uygulama olarak mı kabul edilir veya bu tür bir optimizasyon ihtiyacı, bunları modele eklememiz gerektiğini mi gösterir?

Eylemde göreceli olmaları için denetleyicide daha küçük işlevlerin özel olması için oy kullanardım, ancak model çok büyük ve hantal olabiliyorken denetleyicinin tercihen basit olması gerektiği yönündeki argümanları duydum; ve hangisinin en çok tercih edilen yöntem olacağını merak ediyordum.

Yanıtlar:


16

En iyi benzetme olmayabilir, ancak denetleyiciyi bir örümceğin ağı hakkında düşündüğünüz şekilde düşünün. Tek işi, örümceğin (alttaki katmanlar) sindirmesi için sinekleri (istekleri) yakalamaktır. Ağ, daha küçük veya daha büyük sinekleri (modeller) yakalayabilir ve tutabilir. Bir örümceğin web rolü, bu amaçla kullanılabilmesine rağmen, avı sindirmek değildir. Ağ ne kadar ince ve temiz olursa, örümceğin geçimini kolaylaştırır.

MVC uygulamanıza biraz aynı mantığı uygulayabilirsiniz. Açıkladığınız büyük ve kötü işlevler modelin büyük olasılıkla davranışıdır ve modele ait olmalıdır (modelin yalnızca görünümde görüntülenen nesne olmadığını unutmayın). Eğer modelin davranışı değişirse, onu kontrol eden kontrolör değil, değiştirilmesi gereken modeldir.

Ayrıca, bunları denetleyicide özel yöntemler olarak tutmak yalnızca onu dağıtır ve bakımını zorlaştırır. Aynı zamanda kötü bir alışkanlık için de yol açar, çünkü kalkınmaya katılan diğer insanlar da projede daha önce yapıldığını gördükleri için aynı şeyi yapmaya cazip gelecektir.


Yaratıcı benzetme için +1. :) İlginç bir noktaya değindin. Özellikle kötü alışkanlıkların oluşması üzerine. Teşekkür ederim.
David 'kel zencefil'

8

Verebileceğim en iyi cevap, Robert Martin'in "Temiz Kod" adlı konuyla ilgilenen herkese tavsiye ettiğim büyük kitaptan alıntı yapmaktır:

Fonksiyonların ilk kuralı küçük olmalarıdır. İkinci kural, bundan daha küçük olmalarıdır.

Daha iyi söyleyemem. Aynı kitaptan bir başka büyük alıntı daha geçerlidir:

Fonksiyonlar bir şey yapmalıdır. İyi yapmalılar. Sadece yapmalılar.

Kodunuzu daha fazla işleve böldüğünüzde, bu işlevlere kodunuzun okunabilirliğini büyük ölçüde artırabilecek anlamlı adlar vermek zorunda kalırsınız. Söylemeye gerek yok, sınıf dışında kullanılması amaçlanmayan tüm işlevler özel olmalıdır, böylece kodunuzu kalıtım yoluyla kolayca yeniden kullanabilirsiniz.

Denetleyicinizin artık çok fazla işlevi varsa, muhtemelen çok fazla iş yaptığının bir işaretidir. Sonra birkaç bağımsız parçaya bölebilir veya diğer cevaplarda belirtildiği gibi bazı fonksiyonları modellere taşıyabilirsiniz. Ayrıca, Görünümlerin bazı mantıklara sahip olmasına izin verilen klasik olmayan MVC lezzetini takip ederseniz, bazı işlevlerinizi uygun olduğunda buraya koyabilirsiniz.


1
İş mantığını görünümlere yerleştirmenin "klasik olmayan MVC" olduğunu düşünmüyorum, sadece "kötü MVC". Açıkçası, görünümlerde temel kontrol yapılarına ihtiyacınız vardır, ancak bunlar etki alanı / iş endişeleriyle değil kullanıcı / kullanıcı arayüzü endişeleriyle uyumlu olmalıdır. Bir görünümdeki gerçek bir işlev oldukça korkunç.
Aaronaught

1
@Aaronaught "Bazı mantık" ile muğlak davrandım, aklımda olan şey, örneğin olayları ve işlevleri görmeniz için koyduğunuz Backbone.js kütüphanesi. Klasik MVC'de bu kontrolörün görevidir. Bununla birlikte, kullanıcı arayüzünüz her değiştiğinde hem Görünümü hem de Denetleyiciyi ayarlamanız gerekeceğinden bu pratik olmayabilir. Kullanıcı arabirimi işleyici işlevlerinizi Görünüm'e koyarak, yalnızca Görünümü ayarlamanız gerekir. Bu sadece öznel görüşüm - bir şey mi kaçırıyorum?
Dmitri Zaitsev

1
İstemci tarafında bir şey iletilmesi, mantıksal olarak görünümün bir parçası olduğu anlamına gelmez. Görüşlerdeki veri bağları, elbette, ancak Backbone'un kendisi bir MV * çerçevesi (MVC türü, MVP türü, tam olarak değil) ve istemci tarafı komut dosyalarınız buna göre düzenlenmelidir; Aksi halde, sadece hack ediyorsunuz.
Aaronaught

0

MVC'de denetleyicimin mümkün olduğunca "ince" olmasını ve modellerimin mümkün olduğunca aptal olmasını sağlamaya çalışıyorum.

İhtiyaç duyulan mantık ve yardımcı fonksiyonları ayrı ayrı yardımcı sınıflara konur. Testimi de çok daha kolay hale getiriyor (test ediyorsun .. doğru ??: D) Denetleyicileri test etmek çok zordur, test etmek için bir kontrolör örneği oluşturmaya çalıştığınızda HTTP Bağlamı ve sahte hakkında düşünmeniz gerekir. http bu ve bu ve bu bir acı, ama bilerek bir acı. Bir denetleyicinin HTTP ve web'e çok yakından bağlı olması nedeniyle tüm bunlara ihtiyacınız var. Web uygulamanızın giriş noktasıdır.

Mantık ve yardımcı işlevlerin web ile ilgisi yoktur. Tamamen çevre agnostik (ya da olmalı). Bu tek başına size aynı yere ait olmadıklarını söylemelidir. Ayrıca, tüm uygulama mantığınızı web'e veya belirli bir web uygulamasına bu kadar yakın bağlarsanız, onu asla yanınıza alamazsınız.

Biz MVC sitemizi tüm veritabanı varlıkları (mvc modellerimiz, gerçek db varlıkları değil), depolarımız, yardımcı sınıflarımız ve ayrı ayrı dll'lerdeki mantığımızla geliştirdik. Sadece her bir web sitemiz vardı, ama yine de böyle yaptık.

Birkaç ay önce, birkaç saçak sistemimizle ilgili birkaç masaüstü uygulaması oluşturmamız istendi. Test edilen kodlarımızın tümü tekrar kullanılabileceğinden bu kolayca yapılabilir. Kodumuzu web projemize soksaydık ya da kontrolörlerimize koyarsak, bunu asla yapamazdık.


2
MVC'deki model aptal olması gerekmeyen tek katman . Eğer akıllılar modelde değilse ve kontrolörde değilse, o zaman ... nerede görünüyorlar? Denetleyicilerin test edilmesi de zor olmamalıdır; birim testi kolaylaştırmak için DI ve sahte / alay kullanma kabiliyeti MVC'nin diğer çerçevelere göre çekilmelerinden biridir. Denetleyici testlerimin çoğu 5 satırın altında.
Aaronaught

mantık ile bir model nüfuz yerine, mantık ile bir "yardımcı" sınıfı kullanırsınız. bir modelin içine ne tür bir mantık koyardınız? kendini nasıl yükleyeceğini ve kendini nasıl koruyacağını biliyor mu? Sahte / stubbing'in kolay olduğunu kabul ediyorum, ancak denetleyicilerinizi şişirmeye başlamak için bir bahane değil.
spaceman

Bu cevabın iyi olduğunu hissediyorum ama yanlış ifade edilmiş ya da belki de farklı terminoloji.
Simon Whitehead

3
"Yardımcı" sınıflar mimari bir unsur değildir. Emin, daha sonra bu yardımcıları eksikliği hangi değilseniz Onlar M, V ya da C ya parçasısın uyumu . "Yardımcı" kelimesi de tam olarak "handle", "do", "perform" ve dehşet verici Manager ile sıralanır .
Aaronaught

@SimonWhitehead: Çoğu cevap iyi geliyor, ancak çoğu doğru değil. Bu ne yazık ki ya "Model" in anlamını yanlış anlamayı teşvik etmek ya da kritik iş mantığını bunun dışına koymayı tavsiye etmektir. Ben bir milyon "yardımcıları" ile MVC siteleri korumak için şüpheli zevk aldım - korkunç.
Aaronaught

-2

Dmitri Zaitsev ve spaceman büyük cevaplar yanında ben de PHP için de geçerli olup olmadığını bilmiyorum: Otomatik test olanakları olmaması nedeniyle özel yöntemlerden kaçınmaya çalışmalısınız.

Evet, özel yöntemleri test etmek için metaprogramlama veya bağımlılık enjeksiyonu kullanabilirsiniz, ancak kodunuzun okunabilirliği üzerinde büyük bir etkisi olduğundan bunu yapmamalısınız.

KISS prensibini daima hatırlayın: Basit, aptalca tutun.


5
Bu, özel yöntemlerden kaçınmak için iyi bir neden değildir ve aynı zamanda MVC mimarisi ile ilgisi yoktur. Özel yöntemleri test etmeye çalışmazsınız , bunlar genel yöntemlerle ilgili testlerle kapsanmalıdır . Bunları kapsayamazsanız, bu sınıfınızın çok karmaşık ve yeniden düzenlenmesi gerektiğini gösterir; Bu, özel yöntemlere sahip olmamanız gerektiği anlamına gelmez veya (içtenlikle bu gerçekten kastettiğiniz şey olmadığını umarız) bunun yerine kamuya açık olması gerektiği anlamına gelmez.
Aaronaught
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.