İş mantığının görünüme girmemesi mümkün mü?


31

Son 3 yıldır hem kişisel hem de iş yerinde birkaç web uygulaması projesi için geliştirdim ve uygulamanın görünüm katmanında bitmeyen en azından bazı işletme mantıklarının mümkün olup olmadığını anlayamıyorum.

Çoğu durumda, "Eğer kullanıcı x seçeneğini seçtiyse, o zaman uygulama onu bilgi vermesini sağlamalıdır, eğer değilse o zaman bilgi z vermelidir" gibi sorunlar olacaktır. Veya, modele bazı değişiklikler yapması gereken, ancak kullanıcı açıkça talep edene kadar bunları KADAR ETMEYECEK bazı AJAX işlemleri yapın. Bunlar karşılaştığım en basit sorunlardan bazıları ve görünümdeki karmaşık mantıktan kaçınmanın nasıl mümkün olduğunu çözemiyorum.

MVC'yi açıklayan okuduğum kitapların çoğu, genellikle sunucudaki verileri güncelleyen ve bunları görüntüleyen CRUD işlemleri gibi çok önemsiz örnekleri gösterir; ancak CRUD, çoğu zengin uygulama için geçerli değildir.

İş mantığı olmayan bir bakış açısı elde etmek mümkün mü?


2
MVC ve MVVM türevlerine bakınız ( en.wikipedia.org/wiki/Model_View_Presenter ve en.wikipedia.org/wiki/Model_View_ViewModel'e bakınız ), aradığınız şey olabilir.
Doc Brown

ilişkili (muhtemelen bir yinelenen): Kullanıcı arayüzünden sınıfları ayırma
gnat

2
Görünüm, verilerinizin ve mantığınızın dış, görünür tezahürüdür. Görünümün iş mantığını sunmaması mümkün değildir. Yoksa manzaranın içinde herhangi bir kod olmaması gerektiğini mi söylüyorsun? Kesinlikle yalnızca HTML görünümleri oluşturabilirsiniz.
BobDalgleish

Şablon animasyonuna bakabilirsiniz ; Bu muhtemelen tüm mantığı görünüm katmanından ortadan kaldırmayacak olsa da, olayların biraz daha iyi ayrılmasına yol açacak gibi görünüyor.
Paul,

Bence daha iyi bir soru, veriyi modeli kirletecek görünüm verilerinin daha iyi olup olmadığı veya iş mantığı ile ilgili görünüm mantığı içermesi görünümünün daha mı iyi olduğu? Bu daha gerçek dünya senaryosudur. Sorunuz temelde modelin kirlenmesini savunmak, sormak istediğinizi başarmanın tek yolu olacaktı.
Dunk

Yanıtlar:


22

İş mantığı olmayan bir bakış açısı elde etmek mümkün mü?

Buna cevap vermek için aldatıcı bir soru buluyorum. (Düşünce kışkırtıcı bir soru!)

Teorik olarak, evet, iş mantığı olarak tanımladığımız şeye bağlı olarak. Uygulamada, katı ayrılık çok daha zor hale gelir ve hatta istenmeyen bir duruma gelir.

Endişelerin ayrılması, bina yazılımı hakkında düşünmenin harika bir yoludur: size kodu nereye yerleştireceğiniz konusunda fikir verir ve bakıcılara kodu nerede arayacakları hakkında iyi bir fikir verir. İnsanların kaygı duymadan ayrılmadan çalışan bir yazılım geliştirmesinin imkansız olduğunu savunacağım. Buna ihtiyacımız var.

Ancak, her şeyde olduğu gibi takaslar da var. En iyi kavramsal konum, diğer nedenlerden dolayı en iyi konum olmayabilir. Belki de web sunucunuzda çok fazla yük vardır, bu yüzden sunucunuza basmadan önce giriş hatalarını kolayca yakalamak için web sayfalarınıza javascript eklersiniz; şimdi sizce bazı iş mantıkları var.

Görüşün kendisi, iş mantığı olmadan hiçbir değere sahip değildir. Kullanımda ve sergilenmede etkili olmak için, dolaylı veya açık bir şekilde, görünümün arkasında devam eden iş süreçleri hakkında bir bilgisi olacaktır. Bu miktarda bilgiyi sınırlayabiliriz ve onun bir kısmını koruyabiliriz, ancak pratik düşünceler bizi sık sık endişelerin ayrılmasını 'kırmaya' zorlar.


2
The best conceptual location may not be the best location for other reasons: Bravo!!
Magno C

8

Bunu genellikle yaparım: kullanıcı x seçeneğini seçtiyse, görünüm

controller->OptionXChanged()

Ardından kontrolör görünümde y'yi etkinleştirir:

view->SetEnableInfoY(True) // suppose False=SetDisable

Görünüm, hiçbir şeye karar vermeden ne olduğunu kontrol eder.


+1. OP'nin önemsiz sorunları genellikle önemsiz bir uygulamada bu şekilde ele alınacaktır
dev_feed

Bu mantığı kontrol cihazına yerleştirmenin iki sorunu var: 1) ünite testini zorlaştırıyor ve aynı verinin birden fazla görüntüsünü desteklemek mümkün değil.
kevin cline

4

Tarif ettiğiniz örneklerin gerçekten iş mantığı olup olmadığını sorgularım. Tarif ettiğiniz örnekler, sistemde gerçekleştirilebilecek işlemlerdir. Kullanıcıya seçimleri, iş mantığını görünümde yaptığınız görünümü veren şekliyle sunmayı tercih ettiniz.

"Görünüm" görüş noktasından sisteme sadece InfoY veya InfoZ sağlıyor. Kullanıcı arayüzü uygulamanızın bir operatör seçimine dayanan bazı dinamik güncellemeler yapması nedeniyle (örn. InfoY veya InfoZ'i etkinleştirmek) işlevsellik işini mantıklı kılmaz. Gerçekten uygulama mantığını inceliyor. Çok iyi bir şekilde operatöre, InfoH veya InfoZ’ye tüm etkinleştirici şey olmadan girme seçeneği sunmuş olabilirsiniz. Bu bağlamda, yine de iş mantığı düşünür müsünüz? Değilse, aynı durum bilgi alanlarının dinamik olarak etkinleştirilmesi / devre dışı bırakılması için de geçerlidir.

Aynı taahhüt örneği için de geçerli. Bunlar, sistemin düzgün çalışması için gereken 2 ayrı işlemdir. Görünümünüz, istenen işlevi gerçekleştirmek için uygun eylemleri başlatabilmelidir. Sisteminizi nasıl kullanacağınızı bilmek iş mantığının sızdığı anlamına mı geliyor? Birisinin nasıl evet diyebileceğini anlayabiliyorum ama eğer böyle düşünürseniz gerçek şu ki, iş mantığının herhangi bir şeyden ayrılması gibi bir şey yoktur. Anlamlı bir şey elde etmek için sistemin ne yaptığını / birlikte çalıştığını bilmek zorundasınız. Aksi takdirde, akla gelebilecek her MVC uygulamasında çalışan tek bir genel Görünüm ve Denetleyici oluşturmak bir esinti olacaktır. Bildiğimiz bu imkansız.

Sonuç olarak, işletme mantığı tanımınızın diğer tanımlarla aynı olmadığını düşünüyorum.


1

Bu şekilde çalışıyorum (Struts2 + Hibernate):

Struts İşlemlerim, yalnızca web tarayıcısındaki bilgilerin gösterilmesinden sorumludur. Düşünmemek

Kullanıcı -> İşlem -> Servis -> Depo -> Veri Erişimi

Veya:

Görmek İstiyorum -> Nasıl Görülür -> Ne Yapmalı -> Nasıl Gidilir -> Nereden Alınır?

Öyleyse, ilk katmanda (manzara) şöyle bir şey var:

public String execute ()   {
    try {
        CourseService cs = new CourseService();
        Course course = cs.getCourse(idCourse);
    } catch (NotFoundException e) {
        setMessageText("Course not found.");
    } catch (Exception e) {

    }
    return "ok";
}

Gördüğün gibi benim "bakış açım" sanmıyorum. Bir hizmet istiyor (kursları yönetmek için) belirli bir kurs istiyor. Bu hizmet, raporlar, seraches vb. Gibi daha birçok şeyi yapabilir. Sonuçlar her zaman bir liste veya belirli bir nesnedir (örnek gibi). Hizmetler gerçek makinedir, kurallar uygular ve Depoya erişir (verileri yönetmek için).

Dolayısıyla, Servislerimi, Depolarımı ve DAOS'umu farklı kütüphanelere koyarsam, onu metin tabanlı bir programda veya Pencere tabanlı bir masaüstü sisteminde bile hiçbir şeyi değiştirmeden kullanabilirim.

Servis ne yapılacağını bilir, ancak nasıl gösterileceğini bilmez. Görünüm nasıl gösterileceğini bilir, ancak ne yapacağını bilemez. Servis / Havuz ile aynı: Servis veriyi gönderiyor ve talep ediyor, ancak verilerin nerede olduğunu ve nasıl alınacağını bilmiyor. Depo, Hizmetin çalışabileceği nesneleri oluşturmak için ham verileri "oluşturur".

Ancak Havuz veri tabanı hakkında hiçbir şey bilmiyor. Veri tabanı türü (MySQL, PostgreSQL, ...) DAO ile ilgilidir.

Veritabanını değiştirmek istiyorsanız DAO'yu değiştirebilirsiniz ve üst katmanları etkilememelidir. Veri yönetiminizi güncellemek istiyorsanız Depoyu değiştirebilirsiniz, ancak bu DAO ve üst katmanları etkilememelidir. Mantığınızı değiştirmek istiyorsanız, Servisleri değiştirebilirsiniz, ancak bunun üstündeki veya altındaki katmanlarla karışmaması gerekir.

Ve görünümdeki herhangi bir şeyi, hatta teknolojiyi (web, masaüstü, metin) bile değiştirebilirsiniz, ancak bu, aşağıdaki hiçbir şeyle temas halinde olmamalıdır.

İş mantığı Servis. Ancak bununla nasıl etkileşime girileceğini görmektir. Şimdi gösterilecek düğme nedir? Kullanıcı bu bağlantıyı görebilir mi? Sisteminizin konsol tabanlı bir program olduğunu mu düşünüyorsunuz: yanlış kullanıcının #> myprogram -CourseService -option=getCourse -idCourse=234bu komutu yazmak için tuşlara basması için onu seçtiğini veya durdurduğunu inkar etmelisiniz ?

Web tabanlı sistemlerde (Struts + JavaEE) konuşma Ayrı bir GUI denetleyici paketim var. Eylem görünümünde Kaydedilen kullanıcıya veriyorum ve sınıf bana düğmeleri (veya istediğim herhangi bir arayüz elemanını) veriyor.

                <div id="userDetailSubBox">
                    <c:forEach var="actionButton" items="${actionButtons}" varStatus="id">
                        ${actionButton.buttonCode}
                    </c:forEach>
                </div>

Ve

private List<ActionButton> actionButtons;

Bunu hizmetlerden uzak tutmayı unutma. Bu VIEW olayı. Struts Eylemlerinde saklayın. Herhangi bir arayüz etkileşimi, gerçek işletme kodundan tamamen ayrı olmalıdır, bu nedenle sisteminizi taşırsanız, artık ihtiyacınız olmayacak olanı kesmeniz kolaylaşacaktır.


1

Çoğu durumda, "Eğer kullanıcı x seçeneğini seçtiyse, o zaman uygulamanın y için bilgi vermesini sağlamalı, eğer değilse o zaman bilgiyi z sağlamalıdır" gibi sorunlar olacaktır.

Bu model için mantık, görünüm değil. Kullanıcı arabirimini desteklemek için özel olarak oluşturulmuş bir "görünüm modeli" olabilir, ancak yine de model mantığıdır. Kontrol sırası:

  • Denetleyici olayları görüntülemek için bir işleyici ekler
  • Görünüm, model etkinlikleri için bir işleyici ekler
  • Kullanıcı X seçeneğini seçer.
  • Görünüm, "Seçenek X Seçildi" etkinliğini yükseltir
  • Denetleyici olayı alır ve model.selectOptionX () öğesini çağırır.
  • Model, "Model durumu değişti" olayını yükseltir
  • Görünüm, değiştirilen model olayını alır ve görünümü yeni durumuna uygun olacak şekilde günceller: inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed());

UI View Controller Model |.checkbox X checked.> | | | | | .. X selected ...>| | | | |-----> set X ------->| | | | | | |< .............state changed ............| | | | | | |-------------- Get state --------------->| | | | | | |<----------- new state ------------------| | <-- UI updates ------| Bu klasik MVC modelidir. Model mantığını kullanıcı arayüzünden ayrı olarak tamamen test etmek mümkündür. Kontrolör ve görünüm çok ince ve test etmek kolaydır.

=== Dunk'a cevaben ===

UI MVC desen modeli (genellikle) olmayan bir iş nesne modeli. Bu sadece UI durum için bir modeldir. Bir masaüstü uygulamasında, birden fazla işletme modeline referans verebilir. Bir Web 2.0 uygulamasında, UI durumunu tutan ve AJAX aracılığıyla sunucuya iletişim kuran bir Javascript sınıfıdır. UI durum modelinin hands-off birim testlerini yazabilmek çok önemlidir, çünkü çoğu UI böceği bulunur. Görünüm ve denetleyici çok ince konektörler olmalıdır.


1
Sanırım her şey MVC'nin tanımının olduğuna inandığınız şeye bağlı. Bu sürüm kesinlikle MVC'nin çok katı bir yorumuna bağlıdır. Sorun, bu katı yorumlamanın nadiren gerçek hayatta kullanışlı veya sürdürülebilir bir sistem sağlamasıdır. Nedeni, hemen her yeni bir UI öğesi / bir şey yapmanın yolu ile geldiğinde modeli değiştirmek zorunda olmanızdır. Bu durumda model, yalnızca UI ile alakalı işe yaramaz özelliklerle doludur. Bunların, oluşturmaya çalıştığınız uygulama ile ilgisi yoktur, sadece verileri operatöre nasıl sunmak istediğinize bağlıdır. KÖTÜ!
Dunk,

kevin, yorumlarınızı buraya kutuya yazınız, bu yüzden size cevap vermemiz kolaydır. Size katılıyorum. Arayüz (UI) bilgisini herhangi bir yapı olmadan korumak mümkün değildir, ancak “MODEL” terminolojisi kafa karıştırıcı olabilir. @Dunk'un bahsettiği şeyi kolayca yapabilmek için, kullanıcı arayüzünü farklı bir değiştirilebilir pakette yönetmeyi tercih ediyorum. Cevabımı gör.
Magno C

@MagnoC: Dunk'a cevap olarak cevabını düzenledim, çünkü eklenen metnin cevabı geliştirdiğini düşündüm. Sitenin konusu bu: sorular ve cevaplar. Model oldukça genel bir terimdir ve MVC düzeninde "UI durum modeli" anlamına gelir.
kevin cline

0

Bir işletme mantığı daha gibidir If X then return InfoType.Y, daha sonra kullanıcı arayüzü etki alanının döndürdüğü sonuçlara göre alanları görüntüler.

// Controller method pseudocode
option changed routine

    get selected option

    get required info type from domain routine based on selected option

    display fields based on required info type

Kullanıcı Arabirimi bir iş mantığı gerektiriyorsa, seçimi etki alanına devredin. UI basitçe karara bağlanacaktır.


0

Eğer kullanıcı x seçeneğini seçtiyse, uygulama y için bilgi vermesini sağlamalı, eğer değilse z bilgisini vermelidir ".

Koşullu temelde gerekli değerleri içeren girdiler vardır. GUI ortamlarının çoğunda, girdilerin özellikle zamanlamanın nasıl işleneceği konusunda birçok seçenek vardır. Seçilen seçeneğin (bu durumda x) işlenmesi gerekir, bu nedenle kontrol cihazına gönderin. Kullanıcılar giriş alanından çıktığında gönderin. Başka bir nesneye tıklayana ya da kaydet düğmesine basana kadar bekleyin. İş mantığı için önemli değil. Öyle ya da böyle, denetleyici bir karar verecek ve "y gereklidir" görüşünü söylemesi gerekiyor.

Görüşün bunu nasıl yorumladığı veya uyguladığı, iş mantığı açısından gerçekten önemli değil. Zorunlu alan yap. Bir pop-up açın veya bir topu vurun ve kullanıcıya y girmesini veya sadece inatçı olmasını söyleyin ve bunu anlayana kadar zayıf kullanıcının hiçbir şey yapmasına izin vermeyin.

Ve sadece, tüm bunların, denetleyicinin kaydetmeye çalıştığı ve veritabanında gerekli bir alan için bir değer koymadığı ve tamamen bir veritabanı hatasını yanıtladığı için oluştuğunu düşünün. Bakış açısıyla ilgili önemli değil.

Bir giriş için gerekli veya sınırlı bir değer gibi bir şey birçok yerde kullanılabilir. Görünümde "yalnızca" yazarsanız, birçok geliştirici birden fazla kullanıcı arayüzü olduğunda bunu problem olarak görür. Bu nedenle, işletme mantığı çok fazla kullanıcı arayüzü veya bir veritabanı olmadan oluşturulabilir ve test edilebilir. Bir web siteniz bile yok.

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.