Javascript modülerliği, sunucu tabanlı MVC ve işletme gerçekliği


32

Bunun çok geniş bir soru olduğunu biliyorum, ancak bu sorunun çeşitli yönleriyle ayrı ayrı çalıştım ve tüm kavramları ve teknolojileri bir araya getirmek için mücadele ediyorum.

Cevapların şu teknolojileri içermesi gerektiğini belirtmek isterim:

  • C #
  • MVC 3 ile Jilet
  • Javascript w / jQuery tarafından

Bunların üstünde ve ötesinde olan herhangi bir şey (örneğin, Backbone.js , Entity Framework , vb.), Soruyu cevaplamaya yardımcı olurlarsa öneri olarak kabul edilir:

Yukarıda sıralanan teknolojileri kullanarak, ölçeklenebilirliği ve zengin, hızlı, temiz bir kullanıcı arayüzü oluşturma yeteneğini korurken kod ve mantığı düzenlemek için en uygun strateji nedir?

İdeal olarak odak, iş / şirket ortamında konuşlandırılan bir çözüme odaklanmalıdır. Bu notta, yukarıdaki teknolojiler listesi değişmeyeceğinden, lütfen "şu anda kullandığınız yyy yerine xxx kullanıyor olmalısınız" ile çözümler sunmayın .

Arka fon

Her gün jQuery ile çalışıyorum, ASP.NET'in MVC'sini benimsedim ve uzun süredir C # ile çalışıyorum. Böylece, bu teknolojiler hakkında orta ila ileri düzeyde bilgi varsayarak çözümler sunabilirsiniz.

Yanıt vermeyi kolaylaştırmak için , soruyu daha küçük bölümler halinde düzenleyeceğim :

1. Proje yapısı

Verilen ASP.NET MVC ile çalışıyorum ( Visual Studio 2010'da ) Bu tür uygulamaların ana düzenini kabul etmesini sağlayan bir dizin yapısı çözümü istiyorum. Brunch gibi bir şey varsayalım, ancak her klasörün ne içereceği ve uygulamanın diğer alanları ile nasıl çalıştığı hakkında biraz daha ayrıntılı.

2. Veri erişimi

API tipi bir yapıyla veri erişimimi olabildiğince modülerleştirmek istiyorum. Sen POCO nesnelerin (sürü varsayabiliriz User, UserGroup, Customer, OrderHeader, OrderDetails, vb) değil, aynı zamanda veri yoğun bir SQL ve dikkatli UI render gerektiren bazı kompleks raporlar olacaktır. EF + LINQ ilki için harika, ikincisi için pek bir şey ifade etmiyor. Aşırı karmaşık veya aşırı basit olmadan her iki senaryoya da uyan bir şey bulamıyorum.

3. Müşteri Tarafındaki Kod Organizasyonu ve Kullanıcı Arabirimi Oluşturma

Çoğu geliştirici ilk önce jQuery'yi seçtiğinde olduğu gibi, gitmesi gereken yerde birlikte kod ezme tuzağına düştüm, ancak çabucak yığıldığını ve çirkin hale geldiğini gördüm. O zamandan beri sıçramalar ve sınırlamalar getirmeme rağmen, kodumu modülerleştirmek ve kodu tekrarlamadan UI'nin çeşitli bölümleriyle çalışmak için hala mücadele ediyorum.

Örnek olarak, yazabileceğim tipik bir kod parçası şöyle görünür, beni rahatsız eden şeyleri yorumladım ( ertelenmiş AJAX çağrılarını kullanmak için değiştiğime ve asıl veri isteklerini DOM manipülasyonundan ayırdığına dikkat edin ):

$('#doSomethingDangerous').click(function () {
    // maybe confirm something first
    if (confirm('Are you sure you want to do this?')) {   

        // show a spinner?  something global would be preferred so I don't have to repeat this on every page 
        $('#loading').show();  

        // maybe the page should notify the user of what's going on in addition to the dialog?
        $('#results').show().html('<h2>Please wait, this may take a while...</h2>');  

        $.ajax({
            url: 'blah/DoDangerousThing',
            success: function (data) {                     
                // The results will be loaded to the DOM obviously, is there a better way to pull this type of specific code out of the data access calls?
                $('#results').empty();
                $('#results').append('<b>' + data.length + '</b> users were affected by this dangerous activity');
                $('#results').append('<ul>');

                // I've recently started to use jQuery templates for this sort of logic, is that the way to go?
                $(data).each(function (i, user) {
                    $('#results').append('<li>' + user.Username + '</li>');
                });                    
                $('#results').append('</ul>');

                // Need to hide the spinner, again would prefer to have this done elsewhere
                $('#loading').hide();
            }
        });
    }
});

Genel Sorular

  • İstemci MVC'sine karşı sunucu MVC? Projem zaten bir sunucu tarafı MVC yapısı, bu yüzden hala Backbone.js'nin sağladığı gibi MVC istemcisine ihtiyaç var mı?
  • Her nesne için Javascript dosyaları oluşturulmalı mı (an gibi OrderHeader.js) ve derleme sırasında küçültülmeli / birleştirilmeli mi? Ya da sadece vb Order.jsiçin bir mantık olan bir OrderHeader, OrderDetails, Reportsmi olmalı ?
  • Karmaşık sorgular nasıl ele alınmalıdır? Şu anda lider teorim /Reports/Orders-By-Date/bu satırlar boyunca ya da bir şey ViewModelve Razor View'a özel bir veri kümesi (veya ) veren özel bir SQL sorgusu kullanıyorum . Peki, sayfalama, sıralama vb. İstemci veya sunucu tarafında yapılması daha mı iyidir? (daha büyük veri kümesini varsayalım - 2 ila 3 saniye SQL sorgusu)
  • Microsoft'un Proje İpekini okudum . Bu gitmek için iyi bir yol mu? Backbone.js veya diğerleriyle karşılaştırır mı?
  • N katmanlı bir mimariye çok alışkınım, bu kavramlar biraz camdan dışarı atıyor mu? MVC, geçmişte ön uç veya üst kademe olan şey içerisinde bir grup mini N-katmanlı bölüme benziyor.

Yine, cevaplarınız ne kadar belirgin olursa, o kadar iyi olacaktır. Pek çok üst düzey dokümantasyon ve örnek okudum , gerçek dünyadaki örneklere dönüştürmeyi daha iyi anlamaya çalışıyorum .


2
Bu soruya çok çaba sarfedersiniz, fakat bu bana bir Stackoverflow sorusu gibi görünmüyor. Belki de programcılar yığın değişimi daha iyi olur.
Sivri

3
Bunun ilginç bir konu olduğu konusunda hemfikir değilim, ancak Stackoverflow'un nesnel sorular hakkında olması gerekiyordu . Bu soruya benzer bir şey temelde “muhtemelen görüş, tartışma, tartışmalar, oy kullanma veya genişletilmiş tartışmalar talep edecek” soruların posteridir.
Sivri

8
Sessizce işlerini elimden alırken, her zaman en büyük skalayı planlayan bir halk kampı var çünkü hiç olmadıkları bir şeyi planlamak için çok uzun zaman aldı.
Jason Sebring,

1
@Pinin ile bunun Programcılar yığına ait olduğuna katılıyorum. Sorunuz çok ilginç ve bunu açıklayacağım çünkü her zaman tavsiye arıyorum. Ancak bu nesnel bir soru değil ve sadece tercihli tartışmalarla sonuçlanıyor. Her zaman olduğu gibi, durumunuz için en iyi olanı yapın ... hiçbirimiz ağ yapınız, müşteri sayılarınız veya trafik istatistikleriniz hakkında hiçbir şey bilmiyoruz, ya da yapım süreci ... bu yüzden soru YOL çok belirsiz ... İpek önlemek. ;)
one.beat.consumer

1
Bu soru “aşırı geniş” ve dolayısıyla “gerçek bir soru” tanımına uymuyor. Bir şey olsa bile, bireysel soru sorulmalıdır bireysel soru olarak bazı hafif arka plan ile (çok fazla ve insanların bayrak olacak o "gerçek bir soru"). Ancak, dikkatli olun, sorduğunuz bireysel soruların bir kısmı muhtemelen kendi başlarına "yapıcı değil" olarak işaretlenecektir, bu yüzden bu soruları nasıl sorduğunuza dikkat ederim.
casperOne

Yanıtlar:


10

TerryR arkadaşım, sen ve ben bir şeyler içmeliyiz. Bazı benzer problemlerimiz var.

1. Proje Yapısı: Eduardo ile bir MVC uygulamasındaki klasör yapısının arzulanan bir şey bıraktığını kabul ediyorum. Standart Kontrol Cihazları, Modelleri ve Görünümleri klasörleriniz var. Ancak, Görüntüler klasörü her Denetleyici için ayrı bir klasöre, ayrıca bir Paylaşılan klasöre bölünür. Ve her Görünüm / DenetleyiciAdı veya Görünüm / Paylaşılan, EditorTemplates ve DisplayTemplates öğelerine ayrılabilir. Ancak, Modeller klasörünüzü nasıl düzenleyeceğinize karar vermenize olanak tanır (alt klasörler veya alt adlar ve ek ad alanı bildirimleri ile yapabilirsiniz).

Tanrı, her bir alan için Denetleyicileri, Modelleri ve Görünümleri klasör yapısını çoğaltan Alanları kullanmanızı yasaklamaktadır.

/Areas
    /Area1Name
        /Controllers
            FirstController.cs
            SecondController.cs
            ThirdController.cs
        /Models
            (can organize all in here or in separate folders / namespaces)
        /Views
            /First
                /DisplayTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                /EditorTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                PartialViewAbc.cshtml <-- to be used by FirstController
            /Second
                PartialViewDef.cshtml <-- to be used by SecondController
            /Third
                PartialViewMno.cshtml <-- to be used by ThirdController
            /Shared
                /DisplayTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                /EditorTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                PartialViewXyz.cshtml <-- to be used anywhere in Area1
            _ViewStart.cshtml <-- area needs its own _ViewStart.cshtml
            Web.config <-- put custom HTML Helper namespaces in here
        Area1NameRegistration.cs <-- define routes for area1 here
    /Area2Name
        /Controllers
        /Models
        /Views
        Area2NameRegistration.cs <-- define routes for area2 here

/Controllers
    AccountController.cs
    HomeController.cs
/Models
/Views
    /Account
        /DisplayTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        /EditorTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        PartialViewGhi.cshtml <-- to be used by AccountController
    /Home
        (same pattern as Account, views & templates are controller-specific)
    /Shared
        /DisplayTemplates 
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        /EditorTemplates
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        _Layout.cshtml <-- master layout page with sections
        Error.cshtml <-- custom page to show if unhandled exception occurs
    _ViewStart.cshtml <-- won't be used automatically in an area
    Web.config <-- put custom HTML Helper namespaces in here

Bunun anlamı, eğer bir WidgetController gibi bir şeyle çalışıyorsanız, ilgili WidgetViewModels, WidgetViews, WidgetEditorTemplates, WidgetDisplayTemplates, vb. Bulmak için diğer klasörlere bakmanız gerekir. bu MVC sözleşmeleri. Aynı klasöre model, kontrolör ve görünüm koymak, ancak farklı ad alanlarıyla, ReSharper kullandığım için bundan kaçınıyorum. Squiggly, sınıfın bulunduğu klasörle eşleşmeyen bir ad alanının altını çizer. Bu R # özelliğini kapatabileceğimi biliyorum, ancak projenin diğer bölümlerinde yardımcı oluyor.

Sınıf dışı dosyalar için, MVC size kutudan İçerik ve Komut Dosyaları verir. Konvansiyonu takip etmek için tüm statik / derlenmemiş dosyalarımızı bu yerlerde tutmaya çalışıyoruz. Temaları kullanan bir js kütüphanesini her eklediğimizde (resimler ve veya css), tema dosyaları / içeriğin altında bir yere gider. Betik için hepsini doğrudan / betiklere koyarız. Başlangıçta bu, JS'nin VS'den intellisense'ini almaktı, ancak şimdi / # komutlarına yerleştirmeden bağımsız olarak JS # Rlis'ten intellisense'i alıyoruz, sanırım bundan sapabilir ve komut dosyalarını daha iyi organize etmek için klasöre bölebiliriz. ReSharper kullanıyor musunuz? Saf altın IMO.

Yeniden yapılandırmaya çok yardımcı olan bir başka altın parçası da T4MVC'dir. Bunu kullanarak, alan adları, denetleyici adları, işlem adları, hatta içerik ve komut dosyalarındaki dosyalar için dize yollarını girmemize gerek yoktur. T4MVC, sizin için tüm sihirli dizeleri güçlü bir şekilde yazıyor. İşte T4MVC kullanıyorsanız, proje yapınızın nasıl bir önemi olmadığını gösteren küçük bir örnek:

// no more magic strings in route definitions
context.MapRoutes(null,
    new[] { string.Empty, "features", "features/{version}" },
    new
    {
        area = MVC.PreviewArea.Name,
        controller = MVC.PreviewArea.Features.Name,
        action = MVC.PreviewArea.Features.ActionNames.ForPreview,
        version = "december-2011-preview-1",
    },
    new { httpMethod = new HttpMethodConstraint("GET") }
);

@* T4MVC renders .min.js script versions when project is targeted for release *@
<link href="@Url.Content(Links.content.Site_css)?r=201112B" rel="stylesheet" />
<script src="@Url.Content(Links.scripts.jquery_1_7_1_js)" type="text/javascript">
</script>

@* render a route URL as if you were calling an action method directly *@
<a href="@Url.Action(MVC.MyAreaName.MyControllerName.MyActionName
    (Model.SomeId))">@Html.DisplayFor(m => m.SomeText)</a>

// call action redirects as if you were executing an action method
return RedirectToAction(MVC.Area.MyController.DoSomething(obj1.Prop, null));

2. Veri erişimi: PetaPoco ile hiç bir tecrübem yok, ancak kontrol etmeye değer olduğuna eminim. Karmaşık raporlarınız için SQL Server Raporlama servislerini düşündünüz mü? Veya farklı bir db ile mi çalışıyorsunuz? Üzgünüm tam olarak ne istediğin konusunda net değilim. EF + LINQ kullanıyoruz, ancak etki alanı sınıflarında nasıl rapor oluşturulacağı konusunda da bazı bilgiler veriyoruz. Bu nedenle, doğrudan denetleyici çağrı havuzuna sahip olmak yerine denetleyici çağrı etki alanı servis çağrısı deposuna sahibiz. Geçici raporlar için, yine mükemmel olmayan SQL Reporting Services'ı kullanıyoruz, ancak kullanıcılarımız Excel'e kolayca veri sağlayabilmek istiyor ve SSRS bu işi kolaylaştırıyor.

3. Müşteri Tarafındaki Kod Organizasyonu ve Kullanıcı Arayüzü Oluşturma: Burası, size yardımcı olabileceğimi düşündüğüm yer. MVC göze batmayan doğrulama ve göze çarpmayan AJAX kitabından bir sayfa alın. Bunu düşün:

<img id="loading_spinner" src="/path/to/img" style="display:none;" />
<h2 id="loading_results" style="display:none;">
    Please wait, this may take a while...
</h2>
<div id="results">
</div>
<input id="doSomethingDangerous" class="u-std-ajax" 
    type="button" value="I'm feeling lucky" 
    data-myapp-confirm="Are you sure you want to do this?"
    data-myapp-show="loading_spinner,loading_results" 
    data-myapp-href="blah/DoDangerousThing" />

Şimdilik ajax başarı fonksiyonunu dikkate almayın (bundan sonra daha fazlası için). Bazı eylemleriniz için tek bir komut dosyası ile kurtulabilirsiniz:

$('.u-std-ajax').click(function () {
    // maybe confirm something first
    var clicked = this;
    var confirmMessage = $(clicked).data('myapp-confirm');
    if (confirmMessage && !confirm(confirmMessage )) { return; } 

    // show a spinner?  something global would be preferred so 
    // I dont have to repeat this on every page 
    // maybe the page should notify the user of what's going on 
    // in addition to the dialog?
    var show = $(clicked).data('myapp-show');
    if (show) {
        var i, showIds = show.split(',');
        for (i = 0; i < showIds.length; i++) {
            $('#' + showIds[i]).show();
        }
    }

    var url = $(clicked).data('myapp-href');
    if (url) {
        $.ajax({
            url: url,
            complete: function () {                     
                // Need to hide the spinner, again would prefer to 
                // have this done elsewhere
                if (show) {
                    for (i = 0; i < showIds.length; i++) {
                        $('#' + showIds[i]).hide();
                    }
                }
            }
        });
    }
});

Yukarıdaki kod, onaylayıcıyı gösterir, döndürücüyü gösterir, bekleme mesajını gösterir ve ajax çağrısı tamamlandıktan sonra döndürücü / bekleme mesajını gizler. Davranışları, mütevazi kütüphaneler gibi data- * niteliklerini kullanarak yapılandırırsınız.

Genel Sorular

- İstemci MVC'sine karşı sunucu MVC? Başarı işlevinde gerçekleştirdiğiniz eylemleri sınırlandırmaya çalışmadım çünkü kontrol cihazınız JSON'a dönüyor gibi görünüyor. Denetleyicileriniz JSON’u iade ediyorsa, KnockoutJS’a bakmak isteyebilirsiniz. Nakavt JS sürüm 2.0 bugün piyasaya sürüldü . JSON'unuza doğrudan bağlanabilir, böylece gözlemlenebilir bir tıklama otomatik olarak javascript şablonlarınıza verileri bağlayabilir. Diğer yandan, ajax eylem yöntemlerinin JSON yerine HTML döndürmesini istemiyorsanız, önceden oluşturulmuş UL'i LI çocuklarıyla birlikte döndürebilirler ve bunu data-myapp-response = komutunu kullanarak bir öğeye ekleyebilirsiniz. "Sonuçlar". Başarı fonksiyonunuz daha sonra şöyle görünür:

success: function(html) {
    var responseId = $(clicked).data('myapp-response');
    if (responseId) {
        $('#' + responseId).empty().html(html);
    }
}

Bunun için en iyi cevabımı özetlemek gerekirse, JSON'u eylem yöntemlerinden döndürmeniz gerekiyorsa, sunucu tarafı Görünümü atlıyorsunuz, yani bu gerçekten sunucu MVC'si değil - sadece MC. PartialViewResult komutunu html ile ajax çağrılarına döndürürseniz, bu sunucu MVC'sidir. Bu nedenle, uygulamanız ajax aramaları için JSON verilerini döndürmek zorundaysa, KnockoutJS benzeri bir istemci MVVM kullanın.

Her iki durumda da, düzeninizi (html etiketlerini) davranışla (eşzamansız veri yükleme) karıştırdığı için gönderdiğiniz JS'yi sevmiyorum. Kısmi html görünümüne sahip sunucu MVC'sini veya saf JSON viewmodel verisine sahip istemci MVVM'yi seçmek sizin için bu sorunu çözecektir, ancak javascript'te DOM / HTML'yi el ile oluşturmak endişelerin ayrılmasını ihlal ediyor.

- Javascript dosyası oluşturma Görünüşe göre minyatür özellikleri .NET 4.5'te geliyor . Göze çarpmayan rotaya giderseniz, tüm JS'nizi 1 kod dosyasına yüklemenizi engelleyen hiçbir şey olmamalıdır. Her varlık türü için farklı JS dosyaları oluşturma konusunda dikkatli olurdum, JS dosya patlamasıyla bitirdiniz. Komut dosyanız bir kez yüklendiğinde, tarayıcının gelecekteki istekler için önbelleğe alması gerektiğini unutmayın.

- Karmaşık sorgular Sayfalandırma, sıralama vb. Gibi özelliklerin karmaşık olduğunu düşünmüyorum. Tercihim, URL'leri ve sunucu tarafı mantığını kullanmak, db sorgularını gerektiği kadar sınırlandırmak. Ancak, Azure'a konuşlandırıldık, bu nedenle sorgu optimizasyonu bizim için önemlidir. Örneğin: /widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}. EF ve LINQ to Entities, sayfalama ve sıralama işlemlerini .Take (), .Skip (), .OrderBy () ve .OrderByDescending () gibi yöntemlerle işleyebilir, böylece db gezisi sırasında ihtiyacınız olanı elde edersiniz. Henüz bir clientlib ihtiyacı bulamadım, bu yüzden dürüstçe onlar hakkında fazla bir şey bilmiyorum. Bu konuda daha fazla tavsiye için diğer cevaplara bakın.

- Proje ipeği Hiç duymadım, kontrol etmek zorunda kalacak. Steve Sanderson, kitapları, BeginCollectionItem HtmlHelper ve blogunun büyük bir hayranıyım. Bu, üretimde KnockoutJS ile hiçbir deneyimim olmadığını söyledi . Öğreticilerine baktım, ancak en azından 2.0 sürümü olana kadar bir şey yapmamaya çalışıyorum. Bahsettiğim gibi, KnockoutJS 2.0 yeni piyasaya sürüldü.

- N-katmanlı Eğer farklı fiziksel makine demek istiyorsan, o zaman hayır, hiçbir şeyin bir pencereden dışarı çıkacağını sanmıyorum. Genellikle 3 katmanlı, 3 makineniz olduğunu gösterir. Dolayısıyla, sunum katmanınız olarak bir kullanıcının makinesinde çalışan şişman bir müşteriniz olabilir. Şişman istemci, bir uygulama sunucusunda çalışan ve XML'i veya ne olursa olsun, yağ istemcisine döndüren bir hizmet katmanına erişebilir. Ve hizmet katmanı verilerini 3. makinedeki bir SQL sunucusundan alabilir.

MVC, 1 katmanlı bir katmandır. Denetleyicileriniz, modelleriniz ve görünümleriniz, fiziksel mimaride 1 katmanlı olan Sunum Katmanınızın bir parçasıdır. MVC, ilave katmanlar görebileceğiniz Model-View-Controller desenini uygular. Ancak, bu 3 yönü katmanlar veya katmanlar olarak düşünmemeye çalışın. Bunların üçünü de Sunum Katmanı Endişeleri olarak düşünmeye çalışın.

Pres / bus / data yorumundan sonra güncelleme

Tamam, yani katmanlı ve katmanı birbirinin yerine kullanıyorsunuz. Genellikle "katman" terimini mantıksal / proje / montaj bölümleri için ve fiziksel ağ ayrımı için kullanılır. Karışıklık için özür dilerim.

MVC kampında, varlık veri modeliniz için MVC'deki "Modelleri" kullanmamanız gerektiğini veya Kontrol Cihazlarınızı iş mantığı için kullanmamanız gerektiğini söyleyen epeyce insan bulacaksınız. İdeal olarak, modelleriniz görünüme özgü ViewModels olmalıdır. Automapper gibi bir şey kullanarak, varlıklarınızı etki alanı modelinizden alır ve DTO'yu ViewModels'e görüntüler, özellikle görünüm tarafından kullanılmak üzere şekillendirilir.

Herhangi bir iş kuralı ayrıca etki alanınızın bir parçası olmalıdır ve bunları MVC sunum katmanında değil, etki alanı katmanınıza uygun olan etki alanı hizmetleri / fabrika modeli / uygun olanını kullanarak uygulayabilirsiniz. Kontrolörler aptal olmalı, model kadar aptal olmasalar ve işletme bilgisi gerektiren her şey için etki alanına sorumluluk vermelidirler. Kontrolörler, HTTP isteklerinin ve yanıtlarının akışını yönetir, ancak gerçek ticari değeri olan herhangi bir şey kontrol cihazının ödeme derecesinin üzerinde olmalıdır.

Böylece, sunum katmanı olarak MVC ile katmanlı bir mimariye sahip olabilirsiniz. Uygulama katmanınızın, hizmet katmanınızın veya etki alanı katmanınızın müşterisidir, nasıl tasarladığınıza bağlı olarak. Ancak sonuçta varlık modeliniz, MVC'deki modeller değil, alanın bir parçası olmalıdır.


Bu cevaba tamamen katılıyorum! Özellikle: • Resharper, bir MVC dehasıdır ... hata kontrolünden IDE navigasyonuna kadar, kullanışlılığı beni uçuruyor! • Sunucu Tarafı MVC hemen her zaman en iyi yaklaşımdır • MVC değil 3 ayrı katman ise, tek Sunum Katmanı - Ben gerçekten bu konuda bu açıdan düşünmemiştim, ama bu kesinlikle doğru.
Scott Rippey

Çok güzel cevap, kesinlikle benim 300 temsilcisi pahasına ne aradığını. Toronto bölgesinde iseniz içecekler üzerimde :)

btw Fiziksel olarak nerede oturduklarına bakılmaksızın N-Kadını her zaman Pres / Bus / Data olarak düşündüm. Bu yüzden MVC'nin bu mimariyi neredeyse kaldırdığını söyledim, çünkü temelde aynı fikirde olduğunu söylediğiniz 3'ü birleştiriyor ama aynı zamanda üzerinde farklı bir bakış açısı sunuyor.

ViewModel'e karşı bakış açısı modeline karşı uyarırdım. Son zamanlarda DTO’dan ViewModel’e bu soyutlamanın yapılmamasını diledim. Bakınız: stackoverflow.com/q/7181980/109456

Genel bir kural olarak, jQuery'yi görmeyi sevmiyorum ve bunun yerine herhangi bir sunucu tarafı geliştiricisinin, işi yapan JQ veya DOM API ile oldukça hızlı bir şekilde anlayabileceği arayüzlü nesneler yazmaktan hoşlanmıyorum. Ayrıca Django'nun URLConfig konseptini çok seviyorum ve sayfalarda uygulama için nesneler oluşturmak için yararlı olduğunu gördüm. MV'nin ne olduğu hakkında hiçbir fikrim yok? kütüphanelerin benim için yapması gerekiyordu. Soruna tam olarak uymuyorlar, IMO ve DOM + etkinlik delegasyonu, belirli bir yapıya aşırı derecede bağlı olmadan sayfaları işlemek için ihtiyacım olan tüm model.
Erik Reppen

6

Tam bir cevap yazmayacağım, ancak bazı ipuçlarını paylaşmak istiyorum.

İpuçlarım:

1. Proje yapısı
Varsayılan MVC yapısının benim için iyi olmadığını buldum. Genel olarak kontrolörde, aynı kuruluşun (ürün, sipariş, müşteri) görüş ve modellerini aynı anda yapıyorum. Bu nedenle, dosyaları aynı klasörde, ancak farklı ad alanlarında bulundurmayı seviyorum.

2. Veri
Linq-to-SQL veya EF ile giderseniz daha sonra pişman olacaksınız.
PetaPoco'yu kullanarak SQL'e eşleme sıkıntısı çekmeden kayıtları alma ve güncelleme işlemlerini çalıştırmamı, işleri yapmak için ve performans kabusları olmadan yeni bir yol öğrenmeme izin veriyor.

PetaPoco özniteliklerine sahip ilk POCO sınıfını oluşturmak için bir kod üretecim var ve ardından bir alan eklendiğinde veya kaldırıldığında sınıfı değiştiriyorum.

PetaPoco dinamik ve standart sınıflarla çalışır, böylece hiçbir ödün vermezsiniz (Massive tüm dinamiktir ve tüm standart sınıfları Dapper)

Ayrıca , varlık için tüm standart birleşimleri içeren yerleşik SqlBuilder'ı kullanarak bir ana SQL oluşturuyorum , ancak NEREDE YOKTUR, bu nedenle bir SQL nesnesini veya bir listeyi almak için aynı SQL'i yeniden kullanıyorum.

3. Jquery Genel bir jQuery çağrısı kullanarak (HTML öğesinin içine bazı verileri doldurma) kullanıcı arayüzünün bazı bölümlerini standartlaştırabilirsiniz.

Örneğin, silmek için bu var.

var deleteLinkObj;
// delete Link
$('.jbtn-borrar').click(function () {
    deleteLinkObj = $(this);  //for future use
    $('#delete-dialog').dialog('open');
    return false; // prevents the default behaviour
});
$('#delete-dialog').dialog({
    autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
    buttons: {
        "Borrar": function () {
            $.post(deleteLinkObj[0].href, function (data) {  //Post to action
                if (data == 'OK') {
                    deleteLinkObj.closest("tr").hide('fast'); //Hide Row
                }
                else {
                    alert(data);
                }
            });
            $(this).dialog("close");
        },
        "Cancelar": function () {
            $(this).dialog("close");
        }
    }
});

Sınıfı jbtn-borrarbir köprüye eklemem gerekiyor ve bir iletişim kutusu gösteriyor, kaydı sil ve gizlemeyi kaldırtr

Ama bunu düşünme. Uygulamanız her görünümde küçük dokunuşlarla parlayacak.

İstemci MVC'ye karşılık sunucu MVC
Sunucusu MVC. İlk görüntülemede kullanabileceğiniz kısmi görünümlerden yararlanın ve aynı görünümü kullanarak Ajax ile bazı parçaları yenileyin. Bu mükemmel makaleye bakın

Karmaşık sorgular nasıl ele alınmalı (buna bir Rapor
demeliyiz) Rapor parametrelerinin özellik olarak (MVC otomatik eşlemesini kullanmak için kullanışlıdır) özelliklere sahip bir sınıf Generateve sorguyu uygulayan ve özel bir sınıfın Listesini dolduracak bir yöntem (eğer ViewModel'e uyan bir sınıfa sahip
değilsiniz ) Bu sınıfı görünüm modeli olarak kullanabilir ve tabloyu oluşturulan listeyle doldurabilirsiniz.

Microsoft'un Projesi Silk
Overarchitected. Ters yönde olabildiğince hızlı koş.


Komik, Proje İpekini okuduğum gibi, bu sürükleyici duyguyu almaya devam ettim ve yerleştiremedim. Overarchitected olabilirdi ...

3

1. Proje yapısı

Çözümümde 2 proje dosyası var

1) Servis / İş katmanı Tüm İş mantığımı ve DB erişim kodumu ve POCO'larımı bu ayrı projeye yerleştiriyorum. ORM olarak bir ORM kullanıyorsanız, Veri Tabanı katmanına gerek yok, DB katmanını zaten soyutlar.

2) UI katmanı tüm Görünümlerimi, Denetleyicileri, Modelleri, Komut Dosyalarımı, CSS'yi içerir

Denetleyicileri, Görünümleri, komut dosyalarını ve CSS'lerin hepsinin benzer bir klasör yapısı kullanmasını sağlamaya çalışıyorum. Ayrıca dosyalarımı URL yolunu mümkün olduğunca eşleştirecek şekilde yapılandırın. Özel yönlendirme yazmak zorunda kalmamak için.

DisplayTemplates, EditorTemplates, Kısmi görünümler ve Paylaşılan klasörü mümkün olduğu kadar kullanın.

Daha sonra tüm Scriptlerimi aynı Alanlar, c # dosyalarımın Kontrolörleri ile eşleşecek şekilde yapılandırdım. Böylece kökte ortak bir jeo dosyasına sahip olacak, sayfa başına bir js dosyasını ve her bir alan için ortak bir jeo dosyasını alacağım.

CSS dosyalarım normalde 2 + n olur (burada n alan sayısıdır) 1. CSS dosyası yalnızca açılış sayfası için yalnızca daha hızlı sayfa yükleme süresiyle yardımcı olmak için CSS'dir (muhtemelen işletme / şirket ortamı için çok önemli değildir) 2. CSS dosyası diğer tüm sayfalar için tüm stilleri içeren bir common.css'dir. Daha sonra her alan için başka bir common.css dosyası, örneğin her yönetici sayfası için CSS'ye sahip bir AdminArea.css dosyası.

2. Veri erişimi

Varlık Çerçevesini kullanırsam, POCOS ile çok iyi çalıştığı için CodeFirst'i kullanırım ve sürdürecek bir modeliniz yoktur. nHabernate çok daha güçlü fakat daha kademeli bir öğrenme eğrisi var. DB sonuçlarının sayfalandırılması için, tüm görüşlerim için kullandığım, yeniden kullanılabilir bir c # sınıfı ve patial manzarasına sahibim.

Karmaşık sorgular ve raporlar üretmek için Saklı yordamları kullanıyorum. LINQ'u yazmak, bakımını yapmak ve daha fazla güç sunmak çok daha kolaydır. SSRS gibi diğer servisler tarafından da kullanılabilirler. Automapper'ı geri döndürdüğüm veri setini aynı POCO entiry framework kullandığı dönüştürebilmek için kullanıyorum.

3. Müşteri Tarafındaki Kod Organizasyonu ve Kullanıcı Arabirimi Oluşturma

Eduardo Molteni cevabı iyi bir örnek kod var. Ek olarak, knockoutj'leri hem iyi şablonlama hem de ciltleme özelliklerinden ötürü kesinlikle kullanmanızı tavsiye ederim. Eğer JSON kullanıyorsanız, AJIX çağrılarınızın tümü için çok kullanıyorum, o zaman UI otomatik haritasının JS nesnelerine sahip olması çok büyük bir zaman tasarrufu sağlıyor.

Genel Sorular

Karmaşık sorgular depolanmış bir proseste yaşamalıdır. (bkz emeraldcode.com yorumu)

Bu MVC'yi kullanarak N katmanlı mimarinizi hala korursunuz.


1

Son zamanlarda, listelediğiniz üç teknolojiyi kullanmayı planlıyorsanız, önce Orchard CMS'yi benimseyerek kabul etmeniz gerektiğine inandım . Bunun merkezi ihtiyacınıza en iyi cevap olduğuna inanıyorum:

Ölçeklenebilirliği ve zengin, hızlı, temiz bir kullanıcı arayüzü oluşturma yeteneğini korurken kod ve mantığı düzenlemek için en uygun strateji nedir?

Ochard senaryosunda, konfigürasyon mekanizmaları yoluyla ele alamayacağınız herhangi bir şey daha sonra ücretsiz çevrimiçi modüller ekleyerek veya kendi modülünüzü yazarak (tabii ki C #, ustura, vb.) Yazabilirsiniz. Kod organizasyonu Orchard'ın gücüdür.

Veri erişimine gelince, bir mikro-ORM'nin en iyi yöntem olduğunu düşünmeye başladığım tam kapsamlı bir ORM için yeterli artı ve eksiler var. Massive veya Dapper'ı deneyin . Her ikisi de Hanselminutes'da yayınlandı . Bunu söyleyerek ikisini özetleyeceğim: SQL'den gelen soyutlamalar bir proje büyüdükçe neredeyse her zaman bozulmaz hale geldi. Sonunda, DB erişimi için en iyi çözüm, SQL (alaycı bit ama gerçek) adı verilen bu soyutlamadır. Mikro-ORM'nin bununla çalışmasına izin verin.

Orchard'ı mikro-ORM'lerle bir araya getirin, çelik gibi tereyağı dilimleyebilirsiniz. Er, hızlı bir şekilde gelişebildiğiniz, ölçekleyebileceğiniz ve kolaylıkla teslim alabilen bir ekip tarafından kolayca yönetilebilen bir koda sahip olduğunuz anlamına gelir.


0

Bu soruyu ne kadar özlediğimden emin değilim ama iki yıl sonra iki kuruş ekleyeceğim.

İstemci MVC'sine karşı sunucu MVC? Projem zaten bir sunucu tarafı MVC yapısı, bu yüzden hala Backbone.js'nin sağladığı gibi MVC istemcisine ihtiyaç var mı?

MVC ve MV? Müşteri tarafına itilmeden önce bile, temel olarak, bir şekilde verinin gerçekten bir şekilde vermesi zor olan ama DIY için gerçekten zor olmayan başka şeylerden ayrılacağına dair söz veren bir pazarlama terimine dönüşmüştür. Hangi yaklaşımı kullanıyor olursanız olun, sunumda veya etkileşim olanaklarını etkileyen HTML’de değişiklikler yapmanın tam ortasında veya tam ortasında, işin verilerle ne yapmasını istediğini çözmenin en berbat yeri.

"Mantığı görüntüle" hakkında özel bir şey yok. Aynı ilke tüm mantık için geçerli olmalıdır. Ve bu, şimdi daha önce yapmayı çok daha anlamlı kılacak hiçbir şey yapmayın. Bazı örgüleriniz bazı verileri geçmeden veya yeni bir işlem başlatmadan önce üst üste geldiğinde, önceki aşamada benzer bir şey yapan sistemdeki herhangi bir şey için çok daha kullanışlı olabilir.

Javascript dosyaları her bir nesne için yaratılmalı mı (OrderHeader.js gibi) ve sonra derlemede küçültülmeli / birleştirilmeli mi? Yoksa OrderHeader, OrderDetails, Reports vb. İçin mantığı olan bir Order.js mi olmalı?

Gerçekten size kalmış ama tek dosyalık, tek sınıf şeyden uzaklaşmaya çalışacağım. Örneğin, soyut dosyayı ve arayüzü ve uygulama dosyalarını vb. Bulmanın neden yararlı olduğunu hiç anlamadım. Daha geniş kapsamlı endişelere göre kategorize edin. ctrl + f biraz uzun sürerse kullanımı zor değildir.

Bununla birlikte, dosyaları web'de daha küçük yapmak için JS'yi asla yeniden birleştirmemelisiniz. Tarayıcılar JS'yi önbelleğe alır, böylece eski JS'yi yeni dosyalara yapıştırarak aynı JavaScript'i yeniden yüklemenizi zorlarsınız. Sayfadaki tüm JS'lere sahip olmamanız gereken tek şey, büyük miktarda JavaScript’i engellemenin, sitenin bir bölümüne çok özel bir örtüşme / gri alanı olmayan çok fazla miktarda ihtiyaç duyulmamasıdır. sayfa.

Ve FFS, bağımlılık yönetimiyle web’de JavaScript ile uğraşmaz. Orta ve düşük karmaşıklıktaki web sitelerinde Require.js, bebek fokları yapmak istememi sağlıyor. Üçüncü taraf kütüphanelerinizi en üste yapıştırın. İkinci bloktaki kurum içi kütüphaneleriniz. Ve sonra uygulama kodunuz (bu, kurum içi kütüphane kodunuz sürece asla onuncu olmamalıdır - yani bu çok kısa bir sürede, çok özlü ve net ve anlaşılması kolay).

Karmaşık sorgular nasıl ele alınmalıdır? Şu an öncü teorim / Reports / Order-By-Date / veya bu satırlar boyunca bir şey ve Razor View'a özel bir veri kümesi (veya ViewModel) sağlayan özel bir SQL sorgusu kullanıyorum. Peki, sayfalama, sıralama vb. İstemci veya sunucu tarafında yapılması daha mı iyidir? (daha büyük veri kümesini varsayalım - 2 - 3 saniye SQL sorgusu) Microsoft'un Proje İpekini okudum. Bu gitmek için iyi bir yol mu? Backbone.js veya diğerleriyle karşılaştırır mı?

Dürüst olmak gerekirse, müşteri için pis kokusu olmayan sizin için daha kolay olanı söyleyebilirim. Web sayfaları modern teknolojide oldukça hızlı yükleniyor. Ajax'ta uygulamak size çok acı veriyorsa, yapma. Sadece en iyi bildiğinizle devam edin, sonra daha sonra hoşunuza gidebilir ve disk belleği için nasıl hoşunuza gittiğini görebilirsiniz. Sıfırdan yeni bir karmaşık uygulama oluşturuyorsanız, gerekli ile başlayın ve daha sonra tekrar vurun.

N katmanlı bir mimariye çok alışkınım, bu kavramlar biraz camdan dışarı atıyor mu? MVC, geçmişte ön uç veya üst kademe olan şey içerisinde bir grup mini N-katmanlı bölüme benziyor.

Bu gerçekten kimsenin hangi MV hakkındaki fantazi fikrine bağlı? olduğunu. IMO, mikro kozmos olayı çok iyi çalışma eğilimindedir. Verileri, iletişimi ve görünümle ilgili öğeleri ayıran bir widget sınıfı dahili olarak harika çalışıyor. Müşteri tarafı ağında, kritik olan IMO, yeniden bir araya getirme işlerini anlamayı ve yeniden kullanmayı ve değiştirmeyi zorlaştıran minik kaygılarla gereksiz yere ayrılmadan endişeleri birbirinden ayırma dengesini korumaktır. Temel "duh" OOP burada harika çalışıyor. Karmaşık süreçler istemiyorsunuz. Açıkça hareket ettirilebilecek ve bir şeyler yapabileceği söylenilen şeyler istiyorsun. İşte o cephede birkaç ipucu:

  • ÖRNEK bu (OOP) arayüzü DOM veya jQuery veya bir tutam vurucu sunucu tarafı devi görmek istemiyorum uygulama kodumda oldukça hızlı bir şekilde çözemedim. Tüm bu kişinin bilmesi gereken, bir div kabına hangi sınıfın tokatlanacağını ve belirli bir sayfada oldukça genel bir kullanıcı arayüzü kümesini etkin hale getirmek için hangi anahtarın çevrileceğini. Bir temanın varyasyonları, belgeye bakmaya başlamadan önce, iyi belgelenmiş / yorumlanmış seçenek nesnelerinden geçirilerek veya CSS'nin en temel temellerinin ötesinde bir şey anlamadan önce hala gerçekleştirilmelidir.

  • Tamam, peki bunu nasıl yapıyorsun? Zaten bir modelimiz var. Buna DOM denir. Ve etkinlik delegasyonumuz var. Eğer fark etmeden ayrımcılığa uğramazsanız olayın köpürmesini engellemiyorsanız (bunu yapmayın - çünkü bu faydalıdır) İsterseniz her birini vücudunuzdan bile alabilirsiniz. Ardından, iletilen olay nesnesinin target özelliğini inceleyin ve kimin "ne olursa olsun" olduğunu belirleyin. Bir HTML belgesini makul bir şekilde yapılandırıyorsanız, temsilci model olarak kullanmamak için hiçbir neden yoktur. Davranış ve içerik yapısı doğal olarak bağlantılıdır. İkisinin birbiriyle çakışan tanımlayıcıları olması sorun değil.

  • Veri Bağlama için Ödeme Yapma Ve "ödeme" derken, elbette "aslında kendi için zor olmayan bazı mucize faydalar elde etmek için her zaman her şeyi yapmanıza ısrar eden kod tabanınıza bir kütüphane tokatlayın." JQ olay sistemi oldukça kolaylaştırır.

Örnek Zaman:

function PoliticianData(){ //a constructor

    var
        that = this, //I hate 'that' but example so convention

        flavorsOfLie = {

            lies: "Oh Prism? Psh... no we're all good. There's a guy keeping an eye on that.",

            damnedLies: "50% of the people chose to not give a damn when asked whether it was better to let the terrorists win or not give a damn."

        }
    ;//end instance vars

    this.updateLies = function( lieType, newData ){
        flavorsOfLie[lieType] = newData;
        $(that).trigger({type:'update', lieType:lieType, newData: newData });
    }

    //so everytime you use the updateLies method, we can have a listener respond
    //and pass the data
}

var filthyLies = new PoliticianData();

$(filthyLies).on('update', function(e){
    stickNewDataInHTMLWithSomeFuncDefinedElsewhere(e.lieType, e.newData);
} );

filthyLies.update('damnedLies','50% of the people said they didn\'t give a damn');
//oh look, WaPo's front page just changed!
  • Web'i Saklamayın Tüm erken deneme girişimlerinde, müşteri tarafında sunucu tarafında ve uygulama geliştiricilerinde bu kritik noktaya dayanan kolaylık sağlama girişimlerinin temel kaynağı. HTTP İstekleri karmaşık değildir ve hiçbir zaman karmaşık değildir. Anlaşmayı kolaylaştırmak için 18! @ # $ İng bir katman kafa karıştırıcı olay-olay-adı-her aşamada bir canavarlık istemiyorlardı. Aynı şekilde, müşteri tarafı hakkında bilecek çok şey var ama üzerine devasa bir modeli tokatlayarak HTML ve DOM'dan gizlenecek hiçbir neden yok. Zaten büyük dev bir model ve çok iyi çalışıyor. Bunu biraz daha yönetilebilir hale getirmek için tek ihtiyacımız olan bazı mantıklı OOP uygulamaları ve bazı JS ve DOM bilgisi.

  • Favor Esneklik

EXTjs <==== esneklik ölçeği ====> jQuery (eklentilerinden herhangi biri gerekmez)

IMO, hızlı bir şekilde DIY yapmanıza izin veren araçlar her zaman daha iyi bir seçimdir. Her şeyi sizin için yapan araçlar, başınızdaki hiç kimsenin özellikle detaylar konusunda seçici olamadığı ve size yardım etmesi gereken şeyin kontrolünü durdurma sakıncası yoksa, doğru seçimdir. Aslında orada tam olarak aynı ekran özelliklerine sahip farklı bir öğe türü gizlice gizlememek için HTML'yi doğrulayan eklentiler gördüm. Niye ya? Sadece teorim var. Sanırım tamamlayıcılar, birisinin eşyalarını amaçlanmayan bir şekilde kullanma fikrinden gerçekten nefret ediyor ve bu her zaman kaçınılmaz olarak birisinin UI'de yapmanı istediği şeydir.

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.