Modularitas Javascript, MVC berbasis server & realitas bisnis

32

Saya mengerti ini adalah pertanyaan yang sangat luas, tetapi saya telah bekerja dengan berbagai aspek masalah ini secara individual dan saya berjuang untuk menyatukan semua konsep dan teknologi.

Saya ingin menentukan bahwa jawaban harus mencakup teknologi ini:

  • C #
  • MVC 3 w / Pisau Cukur
  • Javascript dengan jQuery

Apa pun di atas dan di luar itu (seperti Backbone.js , Entity Framework , dll) dipersilakan sebagai saran jika mereka membantu menjawab pertanyaan yaitu:

Dengan menggunakan teknologi yang tercantum di atas, apa strategi optimal untuk mengatur kode dan logika sambil mempertahankan skalabilitas dan kemampuan untuk membuat UI yang kaya, cepat, bersih?

Idealnya fokus harus diberikan pada solusi yang digunakan dalam lingkungan bisnis / perusahaan. Pada catatan itu, daftar teknologi di atas tidak akan diubah jadi tolong jangan menawarkan solusi dengan "Anda harus menggunakan xxx bukannya yyy yang Anda gunakan sekarang".

Latar Belakang

Saya bekerja dengan jQuery setiap hari, telah mengadopsi ASP.NET's MVC dan telah bekerja dengan C # untuk waktu yang lama. Jadi, Anda bisa menghadirkan solusi dengan asumsi pengetahuan menengah ke atas dari teknologi tersebut.

Saya akan mengatur pertanyaan menjadi beberapa bagian yang lebih kecil agar lebih mudah untuk merespons:

1. Struktur proyek

Mengingat saya bekerja dengan ASP.NET MVC (dalam Visual Studio 2010 ) saya ingin solusi struktur direktori yang menawarkan beberapa penerimaan tata letak utama jenis aplikasi ini. Sesuatu seperti Brunch, saya kira, tetapi dengan sedikit lebih detail tentang apa yang masing-masing folder akan berisi dan bagaimana cara kerjanya dengan area lain dari aplikasi.

2. Akses data

Saya ingin memodulasi akses data saya sebanyak yang saya bisa, dengan struktur tipe API. Anda dapat mengasumsikan banyak POCO benda ( User, UserGroup, Customer, OrderHeader, OrderDetails, dll), tetapi juga akan ada beberapa laporan yang kompleks yang memerlukan data SQL intensif dan hati-hati UI rendering. EF + LINQ fantastis untuk yang pertama tetapi tidak begitu banyak untuk yang terakhir. Saya tidak dapat menemukan sesuatu yang cocok dengan kedua skenario tanpa terlalu rumit atau terlalu sederhana.

3. Organisasi Kode Sisi Klien dan Rendering UI

Seperti kebanyakan pengembang yang pertama kali mengambil jQuery, saya jatuh ke dalam perangkap menumbuk kode bersama ke mana pun ia perlu pergi, tetapi dengan cepat menemukannya menumpuk dan berubah jelek. Meskipun saya telah datang lompatan sejak itu, saya masih berjuang dengan memodulasi kode saya dan bekerja dengan berbagai bagian dari UI tanpa kode berulang.

Sebagai contoh, sepotong kode khas yang mungkin saya tulis akan terlihat seperti ini, saya telah mengomentari hal-hal yang mengganggu saya ( perhatikan bahwa saya sejak itu berubah menjadi menggunakan panggilan AJAX yang ditangguhkan dan memisahkan permintaan data aktual dari manipulasi DOM ):

$('#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();
            }
        });
    }
});

Pertanyaan Umum

  • Klien MVC vs server MVC? Proyek saya sudah merupakan struktur MVC sisi server, jadi apakah masih ada kebutuhan untuk MVC klien seperti yang disediakan Backbone.js?
  • Haruskah file Javascript dibuat untuk setiap objek (seperti a OrderHeader.js) dan kemudian diperkecil / digabungkan selama pembuatan? Atau haruskah ada Order.jsyang memiliki logika untuk OrderHeader, OrderDetails, Reportsdll?
  • Bagaimana seharusnya pertanyaan kompleks ditangani? Saat ini teori utama saya adalah /Reports/Orders-By-Date/sesuatu atau sesuatu di sepanjang baris tersebut dan saya menggunakan query SQL khusus yang membuat dataset kustom (atau ViewModel) ke Tampilan Razor. Tapi bagaimana dengan paging, sortir, dll? Apakah ini lebih baik dilakukan sisi klien atau server? (asumsikan dataset lebih besar - 2 hingga 3 detik query SQL)
  • Saya sudah membaca Microsoft Project Silk . Apakah ini cara yang baik untuk pergi? Bagaimana cara membandingkannya dengan Backbone.js atau orang lain?
  • Saya sangat terbiasa dengan arsitektur bertingkat N, apakah konsep-konsep ini agak membuang itu ke luar jendela? Sepertinya MVC adalah seperti sekelompok bagian mini N-tier dalam apa yang akan menjadi front-end atau tier teratas di masa lalu.

Sekali lagi semakin spesifik jawaban Anda, semakin baik jawabannya. Saya telah membaca banyak dokumentasi dan contoh tingkat tinggi , saya mencoba untuk lebih memahami menerjemahkannya menjadi contoh dunia nyata .

Terry
sumber
2
Anda berupaya keras untuk menjawab pertanyaan ini, tetapi sepertinya itu bukan pertanyaan Stackoverflow bagi saya. Mungkin programer stackexchange akan lebih cocok.
Runcing
3
Saya tidak setuju bahwa ini adalah topik yang menarik, tetapi Stackoverflow seharusnya tentang pertanyaan obyektif . Sesuatu seperti pertanyaan ini pada dasarnya adalah poster anak untuk pertanyaan yang akan "kemungkinan mengumpulkan opini, debat, argumen, polling, atau diskusi panjang."
Runcing
8
Ada sekelompok orang yang merencanakan untuk skala terbesar sepanjang waktu sementara saya diam-diam mengambil bisnis mereka karena mereka terlalu lama merencanakan sesuatu yang tidak pernah terjadi.
Jason Sebring
1
Saya setuju dengan @Pointy bahwa ini termasuk dalam tumpukan Programmer. Pertanyaan Anda sangat menarik, dan saya akan mengikutinya karena saya selalu mencari saran. Tetapi ini bukan pertanyaan obyektif, dan hanya akan berakhir dalam perdebatan preferensial. Seperti biasa, lakukan yang terbaik untuk situasi Anda ... tidak ada di antara kami yang tahu apa pun tentang struktur jaringan Anda, jumlah klien atau statistik lalu lintas, atau proses pembangunan ... jadi pertanyaannya WAY terlalu kabur ... yang saya tahu adalah hindari Silk. ;)
one.beat.consumer
1
Pertanyaan ini sangat cocok dengan definisi "terlalu luas" dan karenanya "bukan pertanyaan nyata". Jika ada, pertanyaan individu harus diajukan sebagai pertanyaan individual dengan sedikit latar belakang (terlalu banyak dan orang akan menyebutnya "bukan pertanyaan nyata"). Namun, berhati-hatilah, sejumlah pertanyaan individual yang Anda ajukan mungkin akan ditandai sebagai "tidak konstruktif" sendiri, jadi saya akan berhati-hati tentang cara Anda mengajukan pertanyaan itu.
casperOne

Jawaban:

10

TerryR teman saya, Anda dan saya harus minum. Kami memiliki beberapa masalah serupa.

1. Struktur Proyek: Saya setuju dengan Eduardo bahwa struktur folder dalam aplikasi MVC meninggalkan sesuatu yang diinginkan. Anda memiliki folder Pengontrol, Model, dan Tampilan standar Anda. Tetapi kemudian folder Views dipecah menjadi folder yang berbeda untuk masing-masing Pengendali, ditambah folder Bersama. Dan setiap Views / ControllerName atau Views / Shared dapat dipecah menjadi EditorTemplates dan DisplayTemplates. Tapi itu memungkinkan Anda memutuskan bagaimana mengatur folder Model Anda (Anda dapat melakukannya dengan atau tanpa subfolder & deklarasi namespace tambahan).

Tuhan melarang Anda menggunakan Area, yang menduplikasi struktur folder Controller, Model, dan Views untuk masing-masing area.

/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

Ini berarti jika Anda bekerja dengan sesuatu seperti WidgetController, Anda harus mencari di folder lain untuk menemukan WidgetViewModels, WidgetViews, WidgetEditorTemplates terkait, WidgetDisplayTemplates terkait, dll. Seperti rumitnya, saya tetap menggunakannya dan jangan menyimpang dari konvensi MVC ini. Sejauh meletakkan model, pengontrol, dan tampilan di folder yang sama tetapi dengan ruang nama yang berbeda, saya menghindari ini karena saya menggunakan ReSharper. Ini akan secara singkat menggarisbawahi namespace yang tidak cocok dengan folder di mana kelas berada. Saya tahu saya bisa mematikan fitur R # ini, tetapi membantu di bagian lain dari proyek.

Untuk file non-kelas, MVC memberi Anda Konten dan Skrip di luar kotak. Kami mencoba menyimpan semua file statis / tidak dikompilasi di tempat-tempat ini, sekali lagi, untuk mengikuti konvensi. Setiap kali kami menggabungkan perpustakaan js yang menggunakan tema (gambar dan atau css), file tema semua pergi ke suatu tempat di bawah / konten. Untuk skrip, kami langsung memasukkan semuanya ke / skrip. Awalnya ini adalah untuk mendapatkan JS intellisense dari VS, tetapi sekarang kita mendapatkan JS intellisense dari R # terlepas dari penempatan di / skrip, saya kira kita bisa menyimpang dari itu dan membagi skrip dengan folder untuk mengatur lebih baik. Apakah Anda menggunakan ReSharper? Itu adalah IMO emas murni.

Sepotong emas kecil lain yang banyak membantu dalam refactoring adalah T4MVC. Dengan menggunakan ini, kita tidak perlu mengetikkan jalur string untuk nama area, nama controller, nama tindakan, bahkan file dalam konten & skrip. T4MVC sangat mengetik semua string ajaib untuk Anda. Berikut adalah contoh kecil tentang bagaimana struktur proyek Anda tidak terlalu penting jika Anda menggunakan T4MVC:

// 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. Akses data: Saya tidak punya pengalaman dengan PetaPoco, tapi saya yakin ini layak untuk dicoba. Untuk laporan kompleks Anda, sudahkah Anda mempertimbangkan layanan Pelaporan SQL Server? Atau, apakah Anda menjalankan db yang berbeda? Maaf saya tidak jelas apa yang sebenarnya Anda minta. Kami menggunakan EF + LINQ, tetapi kami juga menaruh pengetahuan tertentu tentang cara membuat laporan di kelas domain. Dengan demikian, kami memiliki repositori panggilan layanan panggilan pengontrol, alih-alih memiliki repositori panggilan pengontrol secara langsung. Untuk laporan ad-hoc kami menggunakan Layanan Pelaporan SQL, yang sekali lagi tidak sempurna, tetapi pengguna kami ingin dapat membawa data ke Excel dengan mudah, dan SSR membuatnya mudah bagi kami.

3. Organisasi Kode Side-Klien dan Rendering UI: Di sinilah saya pikir saya dapat menawarkan bantuan. Ambil satu halaman dari buku MVC validasi yang tidak mencolok dan AJAX yang tidak mencolok. Pertimbangkan ini:

<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" />

Abaikan fungsi sukses ajax untuk saat ini (lebih lanjut tentang ini nanti). Anda dapat lolos dengan satu skrip untuk beberapa tindakan Anda:

$('.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();
                    }
                }
            }
        });
    }
});

Kode di atas akan menangani konfirmasi, menampilkan pemintal, menampilkan pesan tunggu, dan menyembunyikan pesan pemintal / tunggu setelah panggilan ajax selesai. Anda mengonfigurasi perilaku menggunakan atribut data- *, seperti pustaka yang tidak mengganggu.

Pertanyaan Umum

- Klien MVC vs server MVC? Saya tidak mencoba untuk menjelaskan tindakan yang Anda ambil dalam fungsi sukses karena sepertinya controller Anda mengembalikan JSON. Jika pengendali Anda mengembalikan JSON, Anda mungkin ingin melihat KnockoutJS. Knockout JS versi 2.0 dirilis hari ini . Itu dapat menyambungkan langsung ke JSON Anda, sehingga klik yang dapat diamati dapat secara otomatis mengikat data ke templat javascript Anda. Di sisi lain jika Anda tidak keberatan memiliki metode aksi ajax Anda mengembalikan HTML alih-alih JSON, mereka dapat mengembalikan UL yang sudah dibangun dengan anak-anak LI-nya, dan Anda dapat menambahkannya ke elemen dengan menggunakan data-myapp-response = "hasil". Fungsi kesuksesan Anda kemudian akan terlihat seperti ini:

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

Untuk meringkas jawaban terbaik saya untuk ini, jika Anda harus mengembalikan JSON dari metode tindakan Anda, Anda melewatkan Tampilan sisi server, jadi ini sebenarnya bukan server MVC - ini hanya MC. Jika Anda mengembalikan PartialViewResult dengan html ke panggilan ajax, ini adalah server MVC. Jadi, jika aplikasi Anda harus mengembalikan data JSON untuk panggilan ajax, gunakan MVVM klien seperti KnockoutJS.

Either way, saya tidak suka JS yang Anda posting karena mencampur tata letak Anda (tag html) dengan perilaku (memuat data asinkron). Memilih server MVC dengan tampilan html parsial atau klien MVVM dengan data model tampilan JSON murni akan menyelesaikan masalah ini untuk Anda, tetapi membuat DOM / HTML secara manual dalam javascript melanggar pemisahan kekhawatiran.

- Pembuatan file Javascript Tampaknya fitur minifikasi datang dalam .NET 4.5 . Jika Anda memilih rute yang tidak mencolok, seharusnya tidak ada yang menghentikan Anda dari memuat semua JS Anda dalam 1 file skrip. Saya akan berhati-hati tentang membuat file JS yang berbeda untuk setiap jenis entitas, Anda akan berakhir dengan ledakan file JS. Ingat, setelah file skrip Anda dimuat, browser harus menyimpannya untuk permintaan di masa mendatang.

- Pertanyaan kompleks Saya tidak menganggap memiliki fitur seperti pagination, sorting, dll, sebagai yang kompleks. Preferensi saya adalah untuk menangani ini dengan URL dan logika sisi server, untuk membuat permintaan db sebatas yang diperlukan. Namun kami dikerahkan ke Azure, jadi optimisasi kueri penting bagi kami. Sebagai contoh: /widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}. EF dan LINQ ke Entitas dapat menangani pagination dan pengurutan dengan metode seperti. Take (), .Skip (), .OrderBy (), dan .OrderByDescending (), sehingga Anda mendapatkan apa yang Anda butuhkan selama perjalanan db. Saya belum menemukan kebutuhan untuk clientlib, jadi saya jujur ​​tidak tahu banyak tentang mereka. Lihat jawaban lain untuk saran lebih lanjut tentang itu.

- Proyek sutera Belum pernah mendengar yang satu ini, harus memeriksanya. Saya penggemar berat Steve Sanderson, buku-bukunya, BeginCollectionItem HtmlHelper-nya, dan blog-nya. Yang mengatakan, saya tidak punya pengalaman dengan KnockoutJS dalam produksi . Saya telah memeriksa tutorialnya, tetapi saya mencoba untuk tidak melakukan sesuatu sampai setidaknya versi 2.0. Seperti yang saya sebutkan, KnockoutJS 2.0 baru saja dirilis.

- N-tier Jika menurut Anda maksud mesin fisik yang berbeda, maka tidak, saya tidak berpikir ada yang keluar dari jendela. Umumnya 3-tier berarti Anda memiliki 3 mesin. Jadi, Anda mungkin memiliki klien gemuk sebagai tingkat presentasi Anda, yang berjalan pada mesin pengguna. Klien gemuk mungkin mengakses tingkat layanan, yang berjalan di server aplikasi dan mengembalikan XML atau apa pun ke klien gemuk. Dan tingkat layanan mungkin mendapatkan datanya dari server SQL pada mesin ke-3.

MVC adalah satu lapisan, pada 1 tingkat. Kontroler, model, dan tampilan Anda adalah bagian dari Lapisan Presentasi Anda, yang merupakan 1 tingkat dalam arsitektur fisik. MVC mengimplementasikan pola Model-View-Controller, di mana Anda mungkin melihat lapisan tambahan. Namun, cobalah untuk tidak menganggap 3 aspek ini sebagai tingkatan atau lapisan. Cobalah untuk memikirkan ketiganya sebagai Presentation Layer Concerns.

Perbarui setelah komentar pres / bus / data

Oke, jadi Anda menggunakan tier dan layer secara bergantian. Saya biasanya menggunakan istilah "layer" untuk divisi logical / project / assembly, dan tier untuk pemisahan jaringan fisik. Maaf bila membingungkan.

Anda akan menemukan beberapa orang di kamp MVC yang mengatakan Anda tidak boleh menggunakan "Model" di MVC untuk model data entitas Anda, Anda juga tidak boleh menggunakan Pengontrol Anda untuk logika bisnis. Idealnya model Anda harus ViewModels khusus tampilan. Menggunakan sesuatu seperti Automapper, Anda mengambil entitas Anda dari model domain Anda dan mengubahnya menjadi ViewModels, diukir secara khusus untuk digunakan oleh tampilan.

Setiap aturan bisnis juga harus menjadi bagian dari domain Anda, dan Anda dapat menerapkannya menggunakan layanan domain / pola pabrik / apa pun yang sesuai di lapisan domain Anda, bukan di lapisan presentasi MVC. Pengontrol harus bodoh, meskipun tidak sebodoh model, dan harus memberikan tanggung jawab kepada domain untuk apa pun yang membutuhkan pengetahuan bisnis. Pengontrol mengelola aliran permintaan dan respons HTTP, tetapi apa pun dengan nilai bisnis nyata harus di atas nilai gaji pengontrol.

Jadi, Anda masih dapat memiliki arsitektur berlapis, dengan MVC sebagai lapisan presentasi. Ini adalah klien dari lapisan aplikasi Anda, lapisan layanan, atau lapisan domain, tergantung pada bagaimana Anda mendesainnya. Tetapi pada akhirnya model entitas Anda harus menjadi bagian dari domain, bukan model dalam MVC.

danludwig
sumber
Saya sangat setuju dengan jawaban ini! Terutama: • Resharper adalah seorang jenius MVC ... mulai dari pengecekan error hingga navigasi IDE, kegunaannya membuat saya terkejut! • Server-Side MVC hampir selalu merupakan pendekatan terbaik • MVC bukan 3 tingkatan terpisah, ini adalah Lapisan Presentasi tunggal - Saya tidak pernah benar-benar memikirkannya dengan cara ini, tetapi itu benar-benar benar.
Scott Rippey
Jawaban yang sangat bagus, pasti apa yang saya cari dengan biaya 300 rep saya. Minuman ada pada saya jika Anda berada di area Toronto :)
tapi saya selalu menganggap N-tier sebagai Pres / Bus / Data di mana pun mereka duduk. Itu sebabnya saya katakan MVC hampir menghilangkan arsitektur itu karena pada dasarnya menggabungkan 3, apa yang Anda katakan agak setuju dengan itu tetapi juga memberikan perspektif yang berbeda di atasnya.
Saya akan memperingatkan terhadap pendekatan ViewModel, model per tampilan,. Saya baru-baru ini mengalami situasi di mana saya berharap nanti bahwa saya tidak memiliki abstraksi ini dari DTO ke ViewModel. Lihat: stackoverflow.com/q/7181980/109456
Sebagai aturan umum, saya tidak suka melihat jQuery dan sebagai gantinya menulis objek dengan antarmuka yang bisa dipahami oleh server-side dev mana pun dengan cukup cepat dengan JQ atau DOM API yang melakukan bisnis di dalamnya. Saya juga sangat suka konsep URLConfig Django dan merasa terbantu untuk mengatur objek untuk implementasi pada halaman. Saya tidak tahu apa MVnya? perpustakaan seharusnya melakukannya untuk saya. Mereka tidak cocok untuk masalah ini, IMO dan delegasi acara DOM + adalah semua model yang saya butuhkan untuk menangani halaman tanpa terlalu terikat pada struktur tertentu.
Erik Reppen
6

Saya tidak akan menulis jawaban lengkap, tetapi ingin berbagi beberapa tips.

Kiat saya:

1. Struktur proyek
Saya menemukan bahwa struktur MVC default tidak baik untuk saya. Saya biasanya bekerja di controller, pandangan dan model entitas yang sama (pikirkan produk, pesanan, pelanggan) pada saat yang sama. Jadi, saya suka memiliki file dalam folder yang sama, tetapi dengan ruang nama yang berbeda.

2. Data
Jika Anda menggunakan Linq-to-SQL atau EF, Anda akan menyesal kemudian.
Saya menggunakan PetaPoco yang memungkinkan saya menjalankan pengambilan SQL dan memperbarui catatan tanpa rasa sakit pemetaan, tetapi tanpa belajar cara baru untuk melakukan sesuatu dan tanpa mimpi buruk kinerja.

Saya memiliki pembuat kode untuk membuat kelas POCO awal dengan atribut PetaPoco, dan kemudian mengubah kelas ketika beberapa bidang ditambahkan atau dihapus.

PetaPoco bekerja dengan kelas dinamis dan standar, sehingga Anda tidak memiliki kompromi (Massive semuanya dinamis dan Dapper semua kelas standar)

Saya juga menghasilkan master SQL, menggunakan built in SqlBuilder, yang berisi semua gabungan standar untuk entitas, tetapi tidak di WHERE, jadi saya menggunakan SQL yang sama untuk mengambil satu entitas atau daftar.

3. Jquery Anda dapat standarisasi beberapa bagian UI menggunakan panggilan jQuery umum (isian beberapa data di dalam elemen HTML).

Sebagai contoh, saya punya ini untuk dihapus.

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");
        }
    }
});

Saya hanya perlu menambahkan kelas jbtn-borrarke hyperlink, dan itu menunjukkan dialog, menghapus catatan dan menyembunyikantr

Tapi jangan terlalu dipikirkan. Aplikasi Anda akan bersinar dengan sentuhan kecil di setiap tampilan.

Klien MVC vs. server MVC
Server MVC. Manfaatkan tampilan parsial yang dapat Anda gunakan dalam rendering awal dan segarkan beberapa bagian dengan Ajax menggunakan tampilan yang sama. Lihat artikel yang luar biasa ini

Bagaimana seharusnya kueri kompleks ditangani (sebut saja Laporan)
Saya menggunakan kelas yang memiliki parameter Laporan sebagai properti (berguna untuk menggunakan automatisasi MVC) dan Generatemetode yang mengeksekusi kueri dan mengisi Daftar kelas khusus (jika Anda tidak dapat memiliki kelas yang sesuai dengan ViewModel)
Anda dapat menggunakan kelas ini sebagai model tampilan dan mengisi tabel dengan daftar yang dihasilkan.

Project Silk
Overarchitected dari Microsoft . Berlari secepat mungkin ke arah yang berlawanan.

Eduardo Molteni
sumber
Lucu, ketika saya membaca Project Silk, saya terus-menerus merasakan perasaan mengomel ini dan saya tidak bisa menempatkannya. Overarchitected mungkin saja ...
3

1. Struktur proyek

Saya memiliki 2 file proyek dalam solusi saya

1) Lapisan Layanan / Bisnis Saya menempatkan semua logika Bisnis dan kode akses DB serta POCO saya ke dalam proyek terpisah ini. Tidak perlu untuk lapisan Akses Data jika Anda menggunakan ORM karena ORM sudah mengabstraksi lapisan DB.

2) Lapisan UI berisi semua Tampilan, Pengontrol, Model, Skrip, CSS saya

Saya mencoba membuat pengontrol, Tampilan, skrip dan CSS saya semua menggunakan struktur folder yang sama. Juga susun file saya agar sesuai dengan jalur URL sebanyak mungkin. Untuk menghindari harus menulis perutean kustom.

Gunakan DisplayTemplates, EditorTemplates, Tampilan parsial dan folder Shared sebanyak mungkin.

Saya kemudian menyusun semua Skrip saya untuk mencocokkan Area yang sama, Pengontrol file c # saya. Jadi saya akan memiliki file common.js di root, file js per halaman dan file common.js untuk setiap area.

File CSS Saya biasanya memiliki 2 + n (di mana n adalah jumlah area) File CSS pertama adalah CSS hanya untuk halaman arahan hanya untuk membantu dengan waktu buka halaman yang lebih cepat (mungkin tidak begitu penting untuk lingkungan bisnis / perusahaan) file CSS ke-2 adalah common.css yang memiliki semua gaya untuk semua halaman lainnya. Kemudian file common.css lain untuk setiap area misalnya file AdminArea.css yang memiliki CSS untuk setiap halaman admin.

2. Akses data

Jika saya menggunakan Entity Framework, saya menggunakan CodeFirst karena berfungsi sangat baik dengan POCOS dan Anda tidak memiliki model untuk dipelihara. n Hibernate jauh lebih kuat tetapi memiliki kurva pembelajaran steper. Untuk Paging hasil DB saya memiliki util menggunakan kelas # c dan tampilan sabar saya gunakan untuk semua pandangan saya.

Untuk pertanyaan kompleks dan menghasilkan laporan, saya menggunakan prosedur tersimpan. Mereka jauh lebih mudah untuk menulis dan memelihara dan menawarkan lebih banyak kekuatan LINQ. Mereka juga dapat digunakan kembali oleh layanan lain seperti SSRS. Saya menggunakan automapper untuk mengonversi dataset yang dikembalikan ke kembali ke penggunaan kerangka kerja POCO yang sama secara keseluruhan.

3. Organisasi Kode Sisi Klien dan Rendering UI

Eduardo Molteni memiliki kode contoh yang bagus. Selain itu saya pasti akan merekomendasikan menggunakan knockouts karena memiliki templating dan binding yang baik. Jika Anda menggunakan JSON untuk semua panggilan AJAX Anda yang saya gunakan banyak maka memiliki peta otomatis UI ke objek JS adalah penghemat waktu yang sangat besar.

Pertanyaan Umum

Kueri kompleks harus hidup dalam proc yang disimpan. (lihat komentar emeraldcode.com)

Anda masih menyimpan arsitektur bertingkat N Anda menggunakan MVC ini.

Daveo
sumber
1

Baru-baru ini saya tergerak untuk percaya bahwa, jika Anda berencana menggunakan tiga teknologi yang Anda daftarkan, Anda harus mulai dengan mengasumsikan adopsi CMS Orchard . Saya percaya ini adalah jawaban tunggal terbaik untuk kebutuhan utama Anda:

Apa strategi optimal untuk mengatur kode dan logika sambil mempertahankan skalabilitas dan kemampuan untuk membuat UI yang kaya, cepat, bersih?

Dalam skenario Ochard, apa pun yang tidak dapat Anda atasi melalui mekanisme konfigurasinya, Anda kemudian akan menangani baik melalui penambahan modul online gratis, atau menulis modul Anda sendiri (yang tentu saja adalah C #, silet, dan sebagainya). Organisasi kode adalah kekuatan Orchard.

Adapun akses data, ada cukup pro dan kontra untuk ORM bor penuh yang saya juga datang untuk berpikir bahwa mikro-ORM adalah yang terbaik. Coba Massive atau Dapper . Keduanya ditampilkan di Hanselminutes . Saya akan meringkas keduanya dengan mengatakan ini: abstraksi dari SQL hampir selalu rusak sebagai proyek berskala. Pada akhirnya, solusi terbaik untuk akses DB adalah abstraksi ini yang disebut SQL (sedikit sarkasme, tetapi benar). Biarkan mikro-ORM bekerja dengan itu, dan Anda mendapatkan emas.

Masukkan Orchard bersama dengan mikro-ORM, dan Anda bisa mengiris baja seperti mentega. Eh, artinya Anda dapat mengembangkan dengan cepat, skala, dan memiliki kode yang mudah dikelola oleh tim yang menerima hand-off.

Brent Arias
sumber
0

Tidak yakin bagaimana saya melewatkan pertanyaan ini, tetapi saya akan menambahkan dua sen saya dua tahun kemudian.

Klien MVC vs server MVC? Proyek saya sudah merupakan struktur MVC sisi server, jadi apakah masih ada kebutuhan untuk MVC klien seperti yang disediakan Backbone.js?

MVC dan MV? bahkan sebelum didorong ke sisi klien, pada dasarnya telah berkembang menjadi istilah pemasaran yang benar-benar hanya menjanjikan bahwa entah bagaimana data akan dipisahkan dari hal-hal lain yang pada umumnya merupakan ide bagus tetapi tidak terlalu sulit untuk DIY. Apa pun pendekatan yang Anda ambil, tepat sebelum atau tepat di tengah-tengah melakukan perubahan pada HTML yang memengaruhi kemungkinan presentasi atau interaksi adalah tempat yang paling mengerikan untuk memilah apa yang bisnis ingin Anda lakukan dengan data.

Tidak ada yang istimewa tentang "view logic". Prinsip yang sama harus berlaku untuk semua logika. Dan itu, jangan lakukan apa pun sekarang yang akan lebih masuk akal untuk dilakukan sebelum sekarang. Ketika semua bebek Anda berada dalam barisan sebelum Anda melewatkan beberapa data atau memulai proses baru, fase sebelumnya kemungkinan akan jauh lebih dapat digunakan kembali untuk hal lain dalam sistem melakukan sesuatu yang serupa.

Haruskah file Javascript dibuat untuk setiap objek (seperti OrderHeader.js) dan kemudian diperkecil / digabungkan selama proses pembangunan? Atau haruskah hanya ada Order.js yang memiliki logika untuk OrderHeader, OrderDetails, Laporan dll?

Ini benar-benar terserah pada Anda, tetapi saya akan mencoba untuk menjauh dari satu file, satu hal kelas. Saya tidak pernah mengerti mengapa itu membantu misalnya harus menemukan file abstrak dan antarmuka, dan file yang mengimplementasikan, dll ... Kategorikan pada masalah yang lebih luas. ctrl + f tidak terlalu sulit digunakan jika terlalu lama.

Yang mengatakan, Anda tidak boleh menggabungkan kembali JS untuk membuat file lebih kecil di web. Browser cache JS sehingga Anda hanya memaksa memuat ulang JavaScript yang sama dengan menempelkan JS lama di file baru. Kecuali jumlah JavaScript yang mengejutkan, satu-satunya waktu Anda tidak harus memiliki semua JS pada halaman adalah ketika jumlah yang sangat besar itu sangat spesifik untuk satu bagian situs tanpa tumpang tindih / wilayah abu-abu tidak akan pernah diperlukan pada suatu pemberian halaman.

Dan FFS tidak repot dengan manajemen ketergantungan dengan JavaScript di web. Require.js pada situs web dengan kompleksitas sedang hingga rendah membuat saya ingin mengencangkan segel bayi. Tempel pustaka pihak ketiga Anda di blok teratas. Pustaka in-house Anda di blok kedua. Dan kemudian kode implementasi Anda (yang tidak boleh sepersepuluh selama kode perpustakaan di rumah Anda - yaitu sangat ringkas dan jelas dan mudah dimengerti) di bock ketiga.

Bagaimana seharusnya pertanyaan kompleks ditangani? Saat ini teori utama saya adalah / Laporan / Pesanan-Menurut-Tanggal / atau sesuatu di sepanjang baris tersebut dan saya menggunakan kueri SQL khusus yang membuat dataset kustom (atau ViewModel) ke Tampilan Razor. Tapi bagaimana dengan paging, sortir, dll? Apakah ini lebih baik dilakukan sisi klien atau server? (asumsikan dataset lebih besar - 2 hingga 3 detik query SQL) Saya sudah membaca Microsoft Project Silk. Apakah ini cara yang baik untuk pergi? Bagaimana cara membandingkannya dengan Backbone.js atau orang lain?

Jujur, saya akan mengatakan apa pun yang lebih mudah bagi Anda yang tidak bau bagi pelanggan. Halaman web memuat sangat cepat pada teknologi modern. Jika menerapkan di Ajax sangat menyusahkan Anda, jangan. Hanya pergi dengan apa yang Anda tahu terbaik dan kemudian Anda bisa mendapatkan mewah nanti dan lihat bagaimana Anda suka paging. Jika Anda membuat aplikasi kompleks baru dari awal, mulailah dengan esensial dan tekan rapi nanti.

Saya sangat terbiasa dengan arsitektur bertingkat N, apakah konsep-konsep ini agak membuang itu ke luar jendela? Sepertinya MVC adalah seperti sekelompok bagian mini N-tier dalam apa yang akan menjadi front-end atau tier teratas di masa lalu.

Itu benar-benar tergantung pada ide fantasi siapa pun tentang MV apa? aku s. IMO, hal mikrokosmos cenderung bekerja dengan sangat baik. Kelas widget yang memisahkan data, komunikasi, dan hal-hal terkait tampilan secara internal berfungsi dengan baik. Di web sisi klien, hal yang paling penting, IMO, adalah menjaga keseimbangan menjaga keprihatinan tetap terpisah tanpa perlu memecah-mecah menjadi keprihatinan kecil yang pemasangannya membuatnya sulit untuk memahami dan menggunakan kembali dan memodifikasi berbagai hal. Basic "duh" OOP bekerja dengan sangat baik di sini. Anda tidak ingin proses yang rumit. Anda ingin hal-hal yang jelas disebutkan yang dapat digerakkan dan disuruh melakukan hal-hal. Berikut beberapa tips di bagian depan itu:

  • KISS bahwa (OOP) antarmuka saya tidak ingin melihat DOM atau jQuery atau apa pun dev sisi server memukul-mencubit tidak bisa mengetahui dengan cepat dalam kode implementasi saya. Yang harus diketahui oleh orang itu adalah kelas apa yang akan ditampar pada wadah div dan saklar apa untuk membalik untuk membuat set UI yang cukup umum aktif pada halaman tertentu. Variasi pada tema masih harus diselesaikan dengan mengirimkan objek opsi yang terdokumentasi dengan baik / berkomentar sebelum mereka harus mulai melihat dokumen. Dapatkan <anything> atau mengerti apa pun di luar dasar-dasar paling sederhana dari CSS.

  • Oke jadi bagaimana Anda melakukannya? Kita sudah punya model. Ini disebut DOM. Dan kami memiliki delegasi acara. Jika Anda tidak membabi buta mematikan acara (jangan lakukan itu - itu ada di sana karena itu berguna) Anda dapat mengambil setiap bahkan dari tubuh jika Anda mau. Kemudian periksa properti target objek acara yang dilewati dan tentukan siapa yang hanya 'apa pun.' Jika Anda menyusun dokumen HTML dengan bijaksana, tidak ada alasan untuk tidak menggunakannya sebagai model pendelegasian. Perilaku dan struktur konten terhubung secara alami. Tidak apa-apa bagi keduanya untuk memiliki pengidentifikasi yang tumpang tindih.

  • Jangan Membayar Untuk Mengikat Data Dan dengan "membayar" tentu saja saya maksudkan "menampar perpustakaan ke basis kode Anda yang bersikeras Anda melakukan hal-hal yang benar-benar setiap saat untuk mendapatkan beberapa manfaat ajaib yang sebenarnya tidak sulit untuk DIY." Sistem acara JQ membuatnya sangat mudah.

Contoh waktu:

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!
  • Jangan Sembunyikan Web Sumber utama pengisap dalam semua upaya awal untuk membuat sisi klien mudah untuk sisi server dan pengembang aplikasi bergantung pada titik kritis ini. Permintaan HTTP tidak dan tidak pernah rumit. Mereka tidak memerlukan 18! @ # $ Ing layer membingungkan-nama-acara-di-setiap-tahap monstrositas untuk membuatnya lebih mudah untuk dipahami. Demikian juga, ada banyak yang perlu diketahui tentang sisi klien tetapi tidak ada alasan untuk bersembunyi dari HTML dan DOM yang berinteraksi dengannya dengan menampar model raksasa besar di atasnya. Itu sudah merupakan model raksasa besar dan ini bekerja dengan sangat baik. Yang kita butuhkan untuk membuatnya sedikit lebih mudah dikelola adalah beberapa praktik OOP yang masuk akal dan beberapa pengetahuan JS dan DOM.

  • Mendukung Fleksibilitas

EXTjs <==== skala fleksibilitas ====> jQuery (tidak harus plug-in apa pun)

IMO, alat yang membuat Anda DIY cepat selalu merupakan pilihan yang lebih baik. Alat-alat yang melakukan semuanya untuk Anda hanyalah pilihan yang tepat ketika tidak ada orang di luar kepala Anda yang pilih-pilih dalam hal detail dan Anda tidak keberatan menyerahkan kontrol pada hal yang seharusnya membantu Anda. Saya sebenarnya telah melihat plug-in yang memvalidasi HTML untuk memastikan Anda tidak menyelinap jenis elemen yang berbeda dengan semua sifat tampilan yang persis sama di sana. Mengapa? Saya hanya punya teori. Saya pikir itu bermuara pada orang yang benar-benar membenci ide seseorang menggunakan barang-barang mereka dengan cara yang tidak dimaksudkan dan itu selalu pasti apa yang seseorang ingin Anda lakukan di UI.

Erik Reppen
sumber