Hầu hết (tất cả?) Các khung mà bạn đang xem xét giải quyết các vấn đề tương tự, nhưng chúng thực hiện theo các cách hơi khác nhau với các mục tiêu hơi khác nhau.
Tôi nghĩ thật công bằng khi nói rằng tất cả các dự án này sẽ giải quyết các vấn đề trong các danh mục này:
- Cung cấp bộ mặc định hợp lý
- Giảm mã soạn sẵn
- Cung cấp cấu trúc ứng dụng trên đỉnh các khối xây dựng BackboneJS
- Trích xuất các mẫu mà tác giả sử dụng trong ứng dụng của họ
Marionette, mà tôi đã xây dựng từ tháng 12 năm 2011, cũng có một vài mục tiêu và lý tưởng rất khác biệt:
- Kiến trúc ứng dụng tổng hợp
- Ảnh hưởng mẫu tin nhắn doanh nghiệp
- Tùy chọn mô đun hóa
- Sử dụng tăng dần (không yêu cầu tất cả hoặc không có gì)
- Không khóa máy chủ
- Giúp dễ dàng thay đổi các giá trị mặc định đó
- Mã dưới dạng cấu hình / trên cấu hình
Tôi không nói rằng không có khuôn khổ nào khác có cùng mục tiêu này. Nhưng tôi nghĩ sự độc đáo của Marionette đến từ sự kết hợp của những mục tiêu này.
Kiến trúc ứng dụng tổng hợp
Tôi đã dành hơn 5 năm làm việc trong các hệ thống phần mềm phân tán, máy khách dày sử dụng WinForms và C #. Tôi đã xây dựng các ứng dụng cho máy tính để bàn, máy tính xách tay (máy khách thông minh), thiết bị di động và ứng dụng web, tất cả đều chia sẻ một bộ chức năng cốt lõi và làm việc với cùng một máy chủ back-end nhiều lần. Trong thời gian này, tôi đã học được giá trị của mô đun hóa và rất nhanh chóng chuyển xuống một con đường thiết kế ứng dụng tổng hợp.
Ý tưởng cơ bản là "tổng hợp" trải nghiệm thời gian chạy của ứng dụng của bạn và xử lý nhiều phần nhỏ hơn, riêng lẻ mà không nhất thiết phải biết về nhau. Họ tự đăng ký với hệ thống ứng dụng tổng hợp và sau đó họ liên lạc qua nhiều phương tiện khác nhau của tin nhắn và cuộc gọi.
Tôi đã viết một chút về điều này trên blog của mình, giới thiệu Marionette như một kiến trúc ứng dụng tổng hợp cho Backbone:
Hàng đợi / Mẫu tin nhắn
Cùng một quy mô lớn, các hệ thống phân tán cũng tận dụng hàng đợi tin nhắn, mẫu tích hợp doanh nghiệp (mẫu tin nhắn) và xe buýt dịch vụ để xử lý tin nhắn. Điều này, hơn bất cứ điều gì khác, có ảnh hưởng to lớn đến cách tiếp cận phát triển phần mềm tách rời của tôi. Tôi bắt đầu thấy các ứng dụng WinForms trong bộ nhớ đơn xử lý theo quan điểm này, và chẳng mấy chốc, phía máy chủ và sự phát triển ứng dụng web của tôi đã bị ảnh hưởng từ việc này.
Điều này đã trực tiếp dịch chính nó vào cách tôi nhìn vào thiết kế ứng dụng Backbone. Tôi cung cấp một trình tổng hợp sự kiện trong Marionette, cho cả đối tượng Ứng dụng cấp cao và cho từng mô-đun mà bạn tạo trong ứng dụng.
Tôi nghĩ về các tin nhắn mà tôi có thể gửi giữa các mô-đun của mình: tin nhắn lệnh, tin nhắn sự kiện và hơn thế nữa. Tôi cũng nghĩ về giao tiếp phía máy chủ là các tin nhắn có cùng các mẫu này. Một số mô hình đã tìm đến Marionette, nhưng một số chưa có.
Mô đun hóa
Việc mô đun hóa mã là rất quan trọng. Tạo các gói nhỏ, được đóng gói tốt, có trọng tâm riêng biệt với các điểm vào và thoát được xác định rõ là điều bắt buộc đối với bất kỳ hệ thống nào có kích thước và độ phức tạp đáng kể.
Marionette cung cấp mô đun hóa trực tiếp thông qua các module
định nghĩa của nó . Nhưng tôi cũng nhận ra rằng một số người thích RequireJS và muốn sử dụng nó. Vì vậy, tôi cung cấp cả bản dựng tiêu chuẩn và bản dựng tương thích RequireJS.
MyApp = new Backbone.Marionette.Application();
MyApp.module("MyModule", function(MyModule, MyApp, Backbone, Marionette, $, _){
// your module code goes here
});
(Chưa có bài đăng blog nào cho việc này)
Sử dụng tăng dần
Đây là một trong những triết lý cốt lõi mà tôi áp dụng cho mọi phần của Marionette mà tôi có thể: không yêu cầu "tất cả hoặc không có gì" đối với việc sử dụng Marionette.
Xương sống tự nó có một cách tiếp cận rất gia tăng và mô đun với tất cả các đối tượng khối xây dựng của nó. Bạn có thể tự do lựa chọn những gì bạn muốn sử dụng, khi nào. Tôi tin tưởng mạnh mẽ vào nguyên tắc này và cố gắng đảm bảo Marionette hoạt động theo cách tương tự.
Cuối cùng, phần lớn các tác phẩm mà tôi đã xây dựng cho Marionette được chế tạo để đứng một mình, để làm việc với các phần cốt lõi của Xương sống và để làm việc với nhau thậm chí còn tốt hơn.
Ví dụ: gần như mọi ứng dụng Xương sống cần hiển thị động chế độ xem Đường trục ở một vị trí cụ thể trên màn hình. Các ứng dụng cũng cần xử lý việc đóng các chế độ xem cũ và dọn dẹp bộ nhớ khi một vị trí mới được đưa vào. Đây là nơi Marionette Region
đến chơi. Một vùng xử lý mã soạn sẵn của chế độ xem, gọi kết xuất trên đó và đưa kết quả vào DOM cho bạn. Sau đó sẽ đóng chế độ xem đó và dọn sạch nó cho bạn, miễn là chế độ xem của bạn có phương thức "đóng" trên đó.
MyApp.addRegions({
someRegion: "#some-div"
});
MyApp.someRegion.show(new MyView());
Nhưng bạn không bắt buộc phải sử dụng quan điểm của Marionette để sử dụng một khu vực. Yêu cầu duy nhất là bạn đang mở rộng từ Backbone.View tại một số điểm trong chuỗi nguyên mẫu của đối tượng. Nếu bạn chọn cung cấp một close
phương thức, một onShow
phương pháp hoặc các phương thức khác, Vùng của Marionette sẽ gọi nó cho bạn vào đúng thời điểm.
Không khóa máy chủ
Tôi xây dựng các ứng dụng Backbone / Marionette trên một loạt các công nghệ máy chủ:
- ASP.NET MVC
- Viên ngọc trên tay vịn
- Ruby / Sinatra
- NodeJS / ExpressJS
- PHP / Slim
- Java
- Erlang
- ... và hơn thế nữa
JavaScript là JavaScript, khi nói đến việc chạy trong trình duyệt. JavaScript phía máy chủ cũng tuyệt vời, nhưng nó không ảnh hưởng hay ảnh hưởng đến cách tôi viết JavaScript dựa trên trình duyệt của mình.
Do tính đa dạng trong các dự án mà tôi xây dựng và các công nghệ phụ trợ mà khách hàng của tôi sử dụng, tôi không thể và sẽ không khóa Marionette vào một ngăn xếp công nghệ phía máy chủ vì bất kỳ lý do gì. Tôi sẽ không cung cấp một dự án nồi hơi. Tôi sẽ không cung cấp đá quý ruby hoặc gói npm. Tôi muốn mọi người hiểu rằng Marionette không yêu cầu máy chủ phụ trợ cụ thể. Đó là JavaScript dựa trên trình duyệt và back-end không thành vấn đề.
Tất nhiên, tôi hoàn toàn hỗ trợ người khác cung cấp các gói cho ngôn ngữ và khung của họ. Tôi liệt kê các gói đó trong Wiki và hy vọng mọi người tiếp tục xây dựng nhiều gói hơn khi họ thấy cần. Nhưng đó là hỗ trợ cộng đồng, không phải hỗ trợ trực tiếp từ Marionette.
Dễ dàng thay đổi mặc định
Trong nỗ lực của tôi để giảm mã soạn sẵn và cung cấp các giá trị mặc định hợp lý (đó là ý tưởng mà tôi đã trực tiếp "mượn" từ Trình quản lý Bố cục của Tim Branyen), tôi nhận thấy sự cần thiết cho các nhà phát triển khác sử dụng các triển khai hơi khác so với tôi.
Tôi cung cấp kết xuất dựa trên các <script>
thẻ nội tuyến cho các mẫu, sử dụng khuôn mẫu Underscore.js theo mặc định. Nhưng bạn có thể thay thế điều này bằng cách thay đổi Renderer
và / hoặc TempalteCache
các đối tượng trong Marionette. Hai đối tượng này cung cấp cốt lõi của khả năng kết xuất và có các trang wiki chỉ ra cách thay đổi điều này cho các công cụ tạo khuôn mẫu cụ thể và các cách tải mẫu khác nhau.
Với v0.9 của Marionette, nó thậm chí còn dễ dàng hơn. Ví dụ: nếu bạn muốn thay thế việc sử dụng các khối tập lệnh mẫu nội tuyến bằng các mẫu được biên dịch sẵn, bạn chỉ phải thay thế một phương thức trên Trình kết xuất:
Backbone.Marionette.Renderer.render = function(template, data){
return template(data);
};
và bây giờ toàn bộ ứng dụng sẽ sử dụng các mẫu được biên dịch sẵn mà bạn đính kèm vào template
thuộc tính của khung nhìn .
Tôi thậm chí còn cung cấp một tiện ích bổ sung Marionette.Async với v0.9 cho phép bạn hỗ trợ các chế độ xem hiển thị không đồng bộ. Tôi liên tục cố gắng để làm cho nó dễ dàng nhất có thể để thay thế các hành vi mặc định trong Marionette.
Mã dưới dạng cấu hình
Tôi là một fan hâm mộ của "quy ước về cấu hình" trong các bối cảnh nhất định. Đó là một cách mạnh mẽ để hoàn thành công việc và Marionette cung cấp một chút về điều này - mặc dù không quá nhiều, trung thực. Nhiều khung công tác khác - đặc biệt là LayoutManager - cung cấp nhiều quy ước hơn về cấu hình so với Marionette.
Điều này được thực hiện với mục đích và ý định.
Tôi đã xây dựng đủ các plugin, khung, tiện ích và ứng dụng JavaScript để biết được nỗi đau của việc cố gắng làm cho các quy ước hoạt động một cách có ý nghĩa và nhanh chóng. Nó có thể được thực hiện với tốc độ, nhưng thường với chi phí có thể thay đổi nó.
Cuối cùng, tôi sử dụng cách tiếp cận "mã như cấu hình" cho Marionette. Tôi không cung cấp nhiều API "cấu hình" trong đó bạn có thể cung cấp một đối tượng bằng chữ với các giá trị tĩnh thay đổi một loạt các hành vi. Thay vào đó, tôi ghi lại các phương thức mà mỗi đối tượng có - cả thông qua mã nguồn được chú thích và thông qua tài liệu API thực tế - với mục đích cho bạn biết cách thay đổi Marionette để hoạt động theo cách bạn muốn.
Bằng cách cung cấp API rõ ràng và rõ ràng cho các đối tượng Marionette, tôi tạo ra một tình huống thay thế hành vi của một đối tượng cụ thể hoặc Marionette nói chung là tương đối đơn giản và rất linh hoạt. Tôi hy sinh các lệnh gọi API cấu hình "đơn giản" để linh hoạt cung cấp mã của riêng bạn để khiến mọi thứ hoạt động theo cách bạn muốn.
Bạn sẽ không tìm thấy API "cấu hình" hoặc "tùy chọn" trong Marionette. Nhưng bạn sẽ tìm thấy một số lượng lớn các phương thức mà mỗi phương thức phục vụ một mục đích rất cụ thể, với chữ ký rõ ràng, giúp dễ dàng thay đổi cách thức hoạt động của Marionette.