Gần đây, tôi gặp phải bộ ria mép được cho là mẫu không có logic .
Tuy nhiên, không có lời giải thích tại sao nó được thiết kế theo cách Logic-less. Nói cách khác, ưu điểm của mẫu không logic là gì?
Gần đây, tôi gặp phải bộ ria mép được cho là mẫu không có logic .
Tuy nhiên, không có lời giải thích tại sao nó được thiết kế theo cách Logic-less. Nói cách khác, ưu điểm của mẫu không logic là gì?
Câu trả lời:
Nói cách khác, nó ngăn bạn bắn vào chân mình. Trong những ngày JSP cũ, rất phổ biến khi có các tệp JSP được rắc mã Java, điều này khiến việc tái cấu trúc khó hơn nhiều, vì bạn có mã của mình bị phân tán.
Nếu bạn ngăn chặn logic trong các mẫu theo thiết kế (giống như ria mép), bạn sẽ có nghĩa vụ đặt logic ở nơi khác, vì vậy các mẫu của bạn sẽ không gọn gàng.
Một lợi thế khác là bạn buộc phải suy nghĩ về việc tách biệt các mối quan tâm: bộ điều khiển hoặc mã logic của bạn sẽ phải thực hiện việc xoa bóp dữ liệu trước khi gửi dữ liệu đến giao diện người dùng. Nếu sau đó bạn chuyển mẫu của mình cho một mẫu khác (giả sử bạn bắt đầu sử dụng một công cụ tạo khuôn mẫu khác), quá trình chuyển đổi sẽ dễ dàng vì bạn chỉ phải triển khai chi tiết giao diện người dùng (vì không có logic nào trên mẫu, hãy nhớ).
Tôi có cảm giác rằng tôi gần như đơn độc theo quan điểm của tôi, nhưng tôi chắc chắn ở trong trại đối diện. Tôi không tin rằng sự pha trộn logic nghiệp vụ có thể có trong các mẫu của bạn là đủ lý do để không sử dụng toàn bộ sức mạnh của ngôn ngữ lập trình của bạn.
Đối số thông thường cho các mẫu không logic là nếu bạn có toàn quyền truy cập vào ngôn ngữ lập trình của mình, bạn có thể kết hợp logic mà không có chỗ trong một mẫu. Tôi thấy điều này giống với lý luận rằng bạn nên dùng thìa để cắt thịt vì bạn có thể tự cắt mình nếu bạn dùng dao. Điều này rất đúng, nhưng bạn sẽ có năng suất cao hơn nhiều nếu sử dụng cái sau, mặc dù cẩn thận.
Ví dụ: hãy xem xét đoạn mã mẫu sau sử dụng ria mép :
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Tôi có thể hiểu điều này, nhưng tôi thấy cách sau (sử dụng dấu gạch dưới ) đơn giản và trực tiếp hơn nhiều:
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
Nói như vậy, tôi hiểu rằng các mẫu không logic có những lợi thế (ví dụ: chúng có thể được sử dụng với nhiều ngôn ngữ lập trình mà không cần thay đổi). Tôi nghĩ rằng những lợi thế khác là rất quan trọng. Tôi không nghĩ bản chất ít logic của chúng là một trong số chúng.
name
và items
có thể chứa JavaScript.
Bộ ria mép là logic-ít?
Đây không phải là:
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
Khá giống với cái này?
if x
"foo"
else
"bar"
end
Và điều đó chẳng phải khá giống với (đọc: gần như là một định nghĩa của) logic trình bày sao?
if x > 0 && x < 10
) ... Vì vậy, mặc dù có thể sử dụng Mustache có hoặc không có logic, tùy thuộc vào bạn. Rốt cuộc, nó chỉ là một công cụ.
Mẫu không logic là mẫu chứa các lỗ để bạn lấp đầy chứ không phải cách bạn lấp chúng. Logic được đặt ở nơi khác và được ánh xạ trực tiếp tới mẫu. Sự tách biệt các mối quan tâm này là lý tưởng vì khi đó mẫu có thể dễ dàng được xây dựng với các logic khác nhau, hoặc thậm chí với một ngôn ngữ lập trình khác.
Từ hướng dẫn sử dụng ria mép :
Chúng tôi gọi nó là "logic-less" vì không có câu lệnh if, mệnh đề else hoặc vòng lặp for. Thay vào đó chỉ có các thẻ. Một số thẻ được thay thế bằng một giá trị, một số không có gì và những thẻ khác là một chuỗi giá trị. Tài liệu này giải thích các loại thẻ Mustache khác nhau.
Mặt trái của vấn đề này là trong một nỗ lực tuyệt vọng để giữ logic nghiệp vụ ra khỏi bản trình bày, cuối cùng bạn đã đưa rất nhiều logic trình bày vào mô hình. Một ví dụ phổ biến có thể là bạn muốn đặt các lớp "lẻ" và "chẵn" trên các hàng xen kẽ trong bảng, điều này có thể được thực hiện bằng một toán tử mô-đun đơn giản trong mẫu dạng xem. Nhưng nếu mẫu chế độ xem của bạn không cho phép bạn làm điều đó, thì trong dữ liệu mô hình của bạn, bạn không chỉ phải lưu trữ hàng nào là hàng lẻ hoặc hàng chẵn, mà tùy thuộc vào mức độ giới hạn của công cụ mẫu của bạn, bạn thậm chí có thể phải làm ô nhiễm mô hình của mình với tên của các lớp CSS thực tế. Chế độ xem phải tách biệt với Mô hình, toàn bộ. Nhưng Mô hình cũng nên là Chế độ xem bất khả tri, và đó là điều mà nhiều công cụ tạo mẫu "không logic" này khiến bạn quên. Logic có ở cả hai nơi,thực sự để quyết định chính xác nơi nó đi. Đó là mối quan tâm về bản trình bày, hay mối quan tâm về kinh doanh / dữ liệu? Trong một nỗ lực để có tầm nhìn nguyên sơ 100%, ô nhiễm chỉ đổ bộ vào một nơi khác ít nhìn thấy hơn nhưng cũng không phù hợp.
Ngày càng có nhiều sự dịch chuyển trở lại theo hướng khác, và hy vọng mọi thứ sẽ tập trung ở đâu đó ở khu vực trung bình hợp lý hơn.
Nó làm cho các mẫu của bạn sạch hơn và nó buộc bạn phải giữ logic ở một nơi mà nó có thể được kiểm tra đơn vị đúng cách.
Cuộc trò chuyện này giống như khi các nhà sư thời trung cổ tranh luận về việc có bao nhiêu thiên thần có thể lắp vào cuối một chiếc ghim. Nói cách khác, nó bắt đầu cảm thấy tôn giáo, vô ích và tập trung không chính xác.
Mini-rant xảy ra sau đó (vui lòng bỏ qua):
Nếu bạn không muốn tiếp tục đọc .. Câu trả lời ngắn gọn của tôi cho chủ đề trên là: Tôi không đồng ý với các mẫu không logic. Tôi nghĩ về nó như một hình thức lập trình của chủ nghĩa cực đoan. :-) :-)
Bây giờ lời rant của tôi tiếp tục trong xoay: :-)
Tôi nghĩ rằng khi bạn đưa nhiều ý tưởng đến mức cực đoan, kết quả sẽ trở nên lố bịch. Và đôi khi (tức là chủ đề này), vấn đề là chúng ta đưa ra ý tưởng "sai lầm" đến cùng cực.
Loại bỏ tất cả logic khỏi chế độ xem là "lố bịch" và là ý tưởng sai lầm.
Lùi lại một chút.
Câu hỏi chúng ta cần tự hỏi là tại sao lại loại bỏ logic? Khái niệm, rõ ràng là tách biệt các mối quan tâm . Giữ cho chế độ xem càng tách biệt với logic nghiệp vụ càng tốt. Tại sao làm điều này? Nó cho phép chúng tôi hoán đổi các chế độ xem (cho các nền tảng khác nhau: di động, trình duyệt, máy tính để bàn, v.v.) và nó cho phép chúng tôi dễ dàng hoán đổi luồng điều khiển, trình tự trang, thay đổi xác thực, thay đổi mô hình, truy cập bảo mật, v.v. Ngoài ra, khi logic bị xóa khỏi các chế độ xem (đặc biệt là các chế độ xem web), nó làm cho các chế độ xem dễ đọc hơn và do đó dễ bảo trì hơn. Tôi hiểu điều đó và đồng ý với điều đó.
Tuy nhiên, trọng tâm chính nên được tập trung vào việc tách rời các mối quan tâm. Không phải 100% chế độ xem ít logic. Logic trong các khung nhìn nên liên quan đến cách hiển thị "mô hình". Theo như tôi liên quan, logic trong các quan điểm là hoàn toàn ổn. Bạn có thể có view-logic không phải là business-logic.
Đúng vậy, trước đây khi chúng ta viết các trang JSP, PHP hoặc ASP với rất ít hoặc không có sự tách biệt giữa logic mã và logic xem, việc duy trì các ứng dụng web này là một cơn ác mộng tuyệt đối. Hãy tin tôi Tôi biết, tôi đã tạo ra và sau đó duy trì một số trong số những điều quái dị này. Chính trong giai đoạn bảo trì đó, tôi thực sự hiểu (về mặt nội hàm) lỗi trong cách làm của tôi và các đồng nghiệp. :-) :-)
Vì vậy, quyết định từ trên cao (các chuyên gia trong ngành) đã trở thành, bạn phải cấu trúc các ứng dụng web của mình bằng cách sử dụng thứ gì đó giống như bộ điều khiển chế độ xem trước (được gửi đến người xử lý hoặc hành động [chọn khung làm việc web của bạn]) và chế độ xem của bạn không được chứa mã . Các khung nhìn đã trở thành các mẫu ngu ngốc.
Vì vậy, nhìn chung tôi đồng ý với quan điểm trên, không phải vì các chi tiết cụ thể của các mục của sắc lệnh, mà là động lực đằng sau sắc lệnh - đó là mong muốn tách biệt mối quan tâm giữa quan điểm và logic kinh doanh.
Trong một dự án mà tôi đã tham gia, chúng tôi đã cố gắng tuân theo ý tưởng chế độ xem không logic đến mức cực kỳ lố bịch. Chúng tôi đã có một công cụ mẫu tự phát triển cho phép chúng tôi hiển thị các đối tượng mô hình trong html. Đó là một hệ thống dựa trên mã thông báo đơn giản. Nó thật khủng khiếp vì một lý do rất đơn giản. Đôi khi trong một khung nhìn, chúng tôi phải quyết định xem tôi có nên hiển thị đoạn mã HTML nhỏ này hay không .. Quyết định thường dựa trên một số giá trị trong mô hình. Khi bạn hoàn toàn không có logic trong khung nhìn, làm thế nào để bạn làm điều đó? Vâng, bạn không thể. Tôi đã có một số tranh luận chính với kiến trúc sư của chúng tôi về điều này. Những người sử dụng HTML front-end viết quan điểm của chúng tôi đã hoàn toàn bị cản trở khi họ đối mặt với điều này và rất căng thẳng vì họ không thể đạt được các mục tiêu đơn giản khác của mình. Vì vậy, tôi đã giới thiệu khái niệm về câu lệnh IF đơn giản trong công cụ tạo mẫu của chúng tôi. Tôi không thể mô tả cho bạn sự nhẹ nhõm và bình tĩnh xảy ra sau đó. Vấn đề đã được giải quyết với một khái niệm IF-Statement đơn giản trong các mẫu của chúng tôi! Đột nhiên công cụ tạo khuôn mẫu của chúng tôi trở nên tốt.
Vậy làm thế nào mà chúng ta lại rơi vào tình huống căng thẳng ngớ ngẩn này? Chúng tôi tập trung vào mục tiêu sai. Chúng tôi đã tuân theo quy tắc, bạn không được có bất kỳ logic nào trong quan điểm của mình. Điều đó không đúng. Tôi nghĩ "quy tắc ngón tay cái" nên là, giảm thiểu số lượng logic đó trong quan điểm của bạn. Bởi vì nếu bạn không làm vậy, bạn có thể vô tình cho phép logic nghiệp vụ len lỏi vào chế độ xem - điều này vi phạm sự phân tách các mối quan tâm.
Tôi hiểu rằng khi bạn tuyên bố rằng "Bạn không được có logic trong các khung nhìn", bạn sẽ dễ dàng biết được khi nào bạn là một lập trình viên "giỏi". (Nếu đó là thước đo lòng tốt của bạn). Bây giờ, hãy thử triển khai một ứng dụng web có độ phức tạp thậm chí trung bình với quy tắc trên. Nó không dễ dàng thực hiện.
Đối với tôi, quy tắc logic trong các quan điểm không quá rõ ràng và thành thật mà nói, đó là nơi tôi muốn.
Khi tôi thấy nhiều logic trong các khung nhìn, tôi phát hiện ra mùi mã và cố gắng loại bỏ hầu hết logic khỏi các khung nhìn - tôi cố gắng đảm bảo logic nghiệp vụ tồn tại ở những nơi khác - tôi cố gắng tách các mối quan tâm ra. Nhưng khi tôi bắt đầu trò chuyện với những người nói rằng chúng ta phải loại bỏ tất cả logic khỏi chế độ xem, đối với tôi, đó chỉ là một đống sự cuồng tín như tôi biết bạn có thể rơi vào những tình huống như tôi đã mô tả ở trên.
Tôi đã hoàn thành lời nói của mình. :-)
Chúc mừng,
David
Đối số tốt nhất mà tôi đưa ra cho các mẫu không logic là bạn có thể sử dụng các mẫu giống hệt nhau trên cả máy khách và máy chủ. Tuy nhiên, bạn không thực sự cần vô logic, chỉ cần một cái có "ngôn ngữ" của riêng nó. Tôi đồng ý với những người phàn nàn rằng ria mép đang hạn chế một cách vô nghĩa. Cảm ơn, nhưng tôi là một cậu bé lớn và tôi có thể giữ sạch các mẫu của mình mà không cần sự giúp đỡ của bạn.
Một tùy chọn khác là chỉ cần tìm một cú pháp tạo mẫu sử dụng ngôn ngữ được hỗ trợ trên cả máy khách và máy chủ, cụ thể là javascript trên máy chủ bằng cách sử dụng node.js hoặc bạn có thể sử dụng trình thông dịch js và json thông qua một cái gì đó như therubyracer.
Sau đó, bạn có thể sử dụng một cái gì đó như haml.js, nó rõ ràng hơn nhiều so với bất kỳ ví dụ nào được cung cấp cho đến nay và hoạt động rất tốt.
Trong một câu: Logic-less có nghĩa là bản thân công cụ mẫu ít phức tạp hơn và do đó có dấu chân nhỏ hơn và có ít cách để nó hoạt động không mong muốn.
Mặc dù câu hỏi đã cũ và đã được trả lời, tôi muốn thêm 2 ¢ của mình (nghe có vẻ giống như một lời khen ngợi, nhưng không phải vậy, đó là về những hạn chế và khi chúng trở nên không thể chấp nhận được).
Mục tiêu của mẫu là hiển thị một cái gì đó, không phải để thực hiện logic nghiệp vụ. Bây giờ có một ranh giới mỏng giữa việc không thể làm những gì bạn cần làm trong một mẫu và có "logic kinh doanh" trong chúng. Mặc dù tôi thực sự tích cực đối với Mustache và cố gắng sử dụng nó, nhưng cuối cùng tôi vẫn không thể làm những gì tôi cần trong những trường hợp khá đơn giản.
Việc "xoa bóp" dữ liệu (để sử dụng các từ trong câu trả lời được chấp nhận) có thể trở thành một vấn đề thực sự - ngay cả những đường dẫn đơn giản cũng không được hỗ trợ (điều mà Handlebars.js đề cập). Nếu tôi có dữ liệu chế độ xem và tôi cần phải điều chỉnh mỗi khi tôi muốn hiển thị thứ gì đó vì công cụ mẫu của tôi quá hạn chế, thì điều này cuối cùng không hữu ích. Và nó đánh bại một phần tính độc lập của nền tảng mà ria mép tự nhận; Tôi phải lặp lại logic xoa bóp khắp nơi.
Điều đó nói rằng, sau một số thất vọng và sau khi thử các công cụ mẫu khác, chúng tôi đã kết thúc việc tạo của riêng mình (... nhưng một ... khác ...), sử dụng cú pháp lấy cảm hứng từ các mẫu .NET Razor. Nó được phân tích cú pháp và biên dịch trên máy chủ và tạo ra một hàm JS đơn giản, khép kín (thực sự là mô-đun RequestJS) có thể được gọi để "thực thi" mẫu, kết quả là trả về một chuỗi. Mẫu được đưa ra bởi brad sẽ trông như thế này khi sử dụng công cụ của chúng tôi (cá nhân tôi thấy nó vượt trội hơn nhiều so với cả Mustache và Underscore):
@name:
<ul>
@for (items) {
<li>@.</li>
}
</ul>
Một hạn chế không có logic khác xảy ra với chúng tôi khi gọi thành phần bằng Mustache. Trong khi các phần tử được hỗ trợ bởi Mustache, không có khả năng tùy chỉnh dữ liệu được chuyển vào trước. Vì vậy, thay vì có thể tạo một mẫu mô-đun và sử dụng lại các khối nhỏ, tôi sẽ kết thúc việc tạo các mẫu với mã lặp lại trong chúng.
Chúng tôi đã giải quyết điều đó bằng cách triển khai một ngôn ngữ truy vấn lấy cảm hứng từ XPath, mà chúng tôi gọi là JPath. Về cơ bản, thay vì sử dụng / để truyền đến trẻ em, chúng tôi sử dụng dấu chấm và không chỉ chuỗi, số và các ký tự boolean được hỗ trợ mà còn hỗ trợ các đối tượng và mảng (giống như JSON). Ngôn ngữ này không có tác dụng phụ (điều bắt buộc để tạo khuôn mẫu) nhưng cho phép "xoa bóp" dữ liệu khi cần thiết bằng cách tạo các đối tượng theo nghĩa đen mới.
Giả sử chúng tôi muốn hiển thị một bảng "lưới dữ liệu" với các tiêu đề có thể tùy chỉnh và liên kết đến các hành động trên các hàng và sau đó thêm động các hàng bằng jQuery. Do đó, các hàng cần phải ở một phần nếu tôi không muốn sao chép mã. Và đó là nơi mà rắc rối bắt đầu nếu một số thông tin bổ sung như cột nào sẽ được hiển thị là một phần của mô hình chế độ xem và chỉ giống nhau đối với các hành động đó trên mỗi hàng. Dưới đây là một số mã làm việc thực tế bằng cách sử dụng mẫu và công cụ truy vấn của chúng tôi:
Mẫu bảng:
<table>
<thead>
<tr>
@for (columns) {
<th>@title</th>
}
@if (actions) {
<th>Actions</th>
}
</tr>
</thead>
<tbody>
@for (rows) {
@partial Row({ row: ., actions: $.actions, columns: $.columns })
}
</tbody>
</table>
Mẫu hàng:
<tr id="@(row.id)">
@for (var $col in columns) {
<td>@row.*[name()=$col.property]</td>
}
@if (actions) {
<td>
@for (actions) {
<button class="btn @(id)" value="@(id)">@(name)...</button>
}
</td>
}
</tr>
Lời mời từ mã JS:
var html = table({
columns: [
{ title: "Username", property: "username" },
{ title: "E-Mail", property: "email" }
],
actions: [
{ id: "delete", name: "Delete" }
],
rows: GetAjaxRows()
})
Nó không có bất kỳ logic nghiệp vụ nào trong đó, nhưng nó có thể tái sử dụng và định cấu hình, và nó cũng không có tác dụng phụ.
row
đối tượng, thay vì sử dụng tên tĩnh. Ví dụ: nếu $col.property == 'Something'
thì điều này sẽ mang lại nội dung của row.Something
.
Dưới đây là 3 cách hiển thị danh sách, với số lượng ký tự. Tất cả trừ cái đầu tiên và ngắn nhất đều bằng ngôn ngữ tạo mẫu ít logic ..
CoffeeScript (với Reactive Coffee builder DSL) - 37 ký tự
"#{name}"
ul items.map (i) ->
li i
Knockout - 100 ký tự
<span data-bind="value: name"/>
<ul data-bind="foreach: items">
<li data-bind="value: i"/>
</ul>
Ghi đông / ria mép - 66 ký tự
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Dấu gạch dưới - 87 ký tự
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
Lời hứa của các mẫu không logic là, tôi cho rằng những người có bộ kỹ năng rộng hơn sẽ có thể quản lý các mẫu ít logic hơn mà không cần tự bắn vào chân mình. Tuy nhiên, những gì bạn thấy trong các ví dụ trên là khi bạn thêm ngôn ngữ logic tối giản vào đánh dấu dựa trên chuỗi, kết quả sẽ phức tạp hơn, không phải ít hơn. Ngoài ra, bạn trông giống như bạn đang làm PHP cũ.
Rõ ràng là tôi không phản đối việc giữ "logic nghiệp vụ" (tính toán mở rộng) ra khỏi các khuôn mẫu. Nhưng tôi nghĩ rằng bằng cách cung cấp cho họ một ngôn ngữ giả cho logic hiển thị thay vì ngôn ngữ hạng nhất, cái giá phải trả. Không chỉ nhiều hơn để nhập, mà một số người cần phải đọc nó với sự kết hợp ghê gớm của việc chuyển đổi ngữ cảnh.
Tóm lại, tôi không nhìn thấy logic của các mẫu không logic, vì vậy tôi muốn nói rằng lợi thế của chúng là không đối với tôi, nhưng tôi tôn trọng rằng nhiều người trong cộng đồng nhìn nhận nó theo cách khác :)
Những ưu điểm chính của việc sử dụng các mẫu không logic là:
Tôi đồng ý với Brad: văn underscore
phong dễ hiểu hơn. Nhưng tôi phải thừa nhận rằng đường cú pháp có thể không làm hài lòng tất cả mọi người. Nếu _.each
hơi khó hiểu, bạn có thể sử dụng for
vòng lặp truyền thống .
<% for(var i = 0; i < items.length; i++) { %>
<%= items[i] %>
<% } %>
Sẽ luôn tốt nếu bạn có thể dự phòng cho các cấu trúc tiêu chuẩn như for
hoặc if
. Chỉ sử dụng <% if() %>
hoặc <% for() %>
trong khi Mustache
sử dụng phần nào thuyết tân học cho if-then-else
(và khó hiểu nếu bạn không đọc tài liệu):
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
Công cụ mẫu rất tuyệt khi bạn có thể đạt được các mẫu lồng nhau một cách dễ dàng ( underscore
phong cách):
<script id="items-tmpl" type="text/template">
<ul>
<% for(var i = 0; i < obj.items.length; i++) { %>
<%= innerTmpl(obj.items[i]) %>
<% } %>
</ul>
</script>
<script id="item-tmpl" type="text/template">
<li>
<%= name %>
</li>
</script>
var tmplFn = function(outerTmpl, innerTmpl) {
return function(obj) {
return outerTmpl({obj: obj, innerTmpl: innerTmpl});
};
};
var tmpl = tmplFn($('#items-tmpl').html(), $('#item-tmpl').html());
var context = { items: [{name:'A',{name:'B'}}] };
tmpl(context);
Về cơ bản, bạn chuyển tmpl bên trong của mình như một thuộc tính của ngữ cảnh. Và gọi nó cho phù hợp. Ngọt :)
Nhân tiện, nếu thứ duy nhất bạn quan tâm là công cụ mẫu, hãy sử dụng triển khai mẫu độc lập. Nó chỉ có 900 ký tự khi được thu nhỏ (4 dòng dài):