2011-10-14 24 views
5

Xin chào các bạn: Tôi đã băn khoăn không biết ai là một ví dụ cụ thể về DSL trong Clojure, thay thế cho khả năng trừu tượng và dễ đọc của một chương trình OO tốt (viết bằng Java).DSL trong Clojure thay thế giải pháp phần mềm hướng đối tượng?

Tôi đã cố gắng để có một mô hình dữ liệu OO (đó là "đậu" dựa, với phương pháp rất trừu tượng mà ẩn cơ bản triển khai) vào một moeity clojure ...

Tôi biết rằng "macro" và Tuy nhiên, "hàm bậc cao hơn" tồn tại, tôi chưa bao giờ thấy chúng được áp dụng cho một tập dữ liệu thế giới thực dễ hiểu (ví dụ như hệ thống đăng ký khóa học, hoặc đại lý ô tô, hoặc hệ thống thanh toán, hoặc thứ gì đó , nhớ lại các ví dụ "JPetStore" khét tiếng mà Hibernate và Ibatis đã phổ biến trong thập kỷ qua).

Anyways ... câu hỏi cơ bản của tôi là:

Do bất kỳ mẫu miền cụ tồn tại cho việc học tập như thế nào để mô hình hóa các hệ thống thế giới thực trong Clojure với các giao thức và chức năng bậc cao?

Trả lời

1

Tôi không biết nếu đây là những gì bạn đang tìm kiếm nhưng tôi đã đọc một cuốn sách về Clojure (Lập trình Clojure; Pragmatic lập trình viên) trong đó có một ví dụ về một chút DSL tốt đẹp. Bạn có thể tìm mã số tại https://github.com/stuarthalloway/lancet. Về cơ bản lancet là một cái gì đó giống như làm cho hoặc kiến ​​ nhưng được triển khai dưới dạng Clojure-DSL.

+0

... lancet là một DSL, nhưng nó không thực sự là một "thế giới thực" vấn đề trong đó hầu hết các lập trình viên chưa bao giờ cố gắng để viết một hệ thống như vậy: Kiểm tra tốt ol 'google: ứng dụng jpetstore .... – jayunit100

1

OOP là tốt trong các sence chúng tôi đang thực sự sử dụng để nó và nó ánh xạ đến các khái niệm trong thế giới thực.

Bạn có thể xem làm thế nào để xây dựng một hệ thống OOP với bản đồ và phương pháp đa (một cái gì đó tương tự để thừa kế nguyên chủng trong JS) trong Joy của clojure, chương 9.

Mở cuốn sách lisp từ Paul Graham cho thấy làm thế nào để tạo ra một hệ thống đối tượng trong lisp. Nên dễ dàng thích nghi nó với clojure.

Cuốn sách này cũng giải thích chương trình "dưới lên" rộng rãi, đó là xây dựng các viên gạch nhỏ cơ bản và soạn chúng để xây dựng các cấu trúc mức cao hơn.

Ngoài ra nếu bạn thấy khái niệm chính trong nhiều ứng dụng (như cửa hàng vật nuôi java) là thủ tục/fonctionnal và không sử dụng các đối tượng khái niệm như tổng quát hoặc đóng gói rộng rãi.

Đậu không có hành vi. Dữ liệu không có đóng gói có getters/setter cho phép truy cập công khai vào chúng. Đối với những gì nó cung cấp cho bạn, bạn có thể sử dụng một cấu trúc C (trong ngôn ngữ đánh máy) hoặc một bản đồ bằng ngôn ngữ động như clojure.

Dịch vụ hoạt động trên chúng về cơ bản hoạt động. Chúng không có trạng thái và lấy dữ liệu từ các tham số (bean) hoặc cơ sở dữ liệu. Nếu bạn thực sự cần inteface, bạn có các giao thức trong clojure.

Điều đó không phức tạp.

Tên đậu của bạn như thế nào trong JAVA ... Nhưng thực hiện chúng vào bản đồ clojure hoặc như một hồ sơ

Tên dịch vụ của bạn và thực hiện chúng như các chức năng.

Cần nhà máy? Các hàm đó có chức năng cấu hình và trả về.

Cần tiêm phụ thuộc? Vâng, bạn có thể sử dụng các tham số chức năng.

3

Không có mẫu đặc biệt cho DSL - bạn chỉ mất công cụ có sẵn trong ngôn ngữ và cố gắng làm cho nó như thuận tiện và gần gũi với lĩnh vực càng tốt. Lisp chỉ cung cấp cho bạn nhiều công cụ hơn các ngôn ngữ khác.

Ví dụ cụ thể về giao diện DSL đẹp tại ClojureQL. Ban đầu, SQL được tạo thành DSL cho cơ sở dữ liệu quan hệ. Và nó rất thuận tiện để làm việc từ bàn điều khiển ... nhưng không phải từ ngôn ngữ lập trình như Java hay Clojure. Java đi kèm với các khuôn khổ ORM lớn như Hibernate, và Clojure cung cấp DSL đơn giản đó là thuận tiện như SQL gốc, nhưng hoạt động hoàn toàn như một phần của ngôn ngữ:

(select (table :users) (where (= :id 5))) 

điều thường gặp trong Lisp DSL đang sử dụng cấu trúc như defsomething. Ví dụ, trong một cuốn sách (xin lỗi, tôi không nhớ tên của nó) có một ví dụ về khớp mẫu trong văn bản. Tác giả tạo mô-đun với một số đối sánh như ? cho một từ, + cho một hoặc nhiều từ, * cho 0 hoặc nhiều từ hơn, v.v. Vì mục đích này, anh ta tạo macro defmatcher để thực hiện cú pháp và thêm trình xử lý cho cú pháp này vào sổ đăng ký trung tâm. Đây chỉ là trừu tượng - thay vì một số hoạt động lặp đi lặp lại, ông giới thiệu đơn macro nói với những gì ông thực sự muốn làm - xác định matcher. Ngoài ra ví dụ này sử dụng cả hai - macro và các hàm bậc cao.

Vì vậy, một lần nữa, không có gì đặc biệt trong các DSL dựa trên Lisp - bạn chỉ cần mô tả khu vực miền bằng các công cụ bạn có bằng ngôn ngữ của mình, có thể là Java, Clojure hay bất kỳ thứ gì khác. Chỉ cần làm quen với các cơ sở ngôn ngữ và bạn sẽ thấy nó trông như thế nào.

UPD. Một số "thực tế" ví dụ nơi DSL Lisp-based được thuận tiện hơn, chẳng hạn, OOP:

miền: xe dillership

(defcar my-cool-car :wheels 4, :doors 2, :color red) ;; in Java you need Factory 
(def car1 (make-car my-cool-car))     ;; and lots of methods to 
                ;; add features to cars and 
                ;; cars to factory 

miền: hệ thống thanh toán

(transaction    ;; in Java you cannot create wrapping constructs 
    (withdraw account1 100) ;; so you have to use inheritance, annotations, etc. 
    (put account2 100))  ;; which is much more code 

miền: một số dịch vụ web xử lý các yêu cầu của một số loại

(defhandler :show-all (fn [params] ...))  ;; adds defined function to the 
(defhandler :find-best (fn [params] ...)) ;; map of :message-type -> function 
... 
(defn handle [message] 
    (let [msg-type (:type message), msg-params (:params message)] 
    (if (contains? *handlers* msg-type) 
     ((*handlers* msg-type) msg-params) 
     (throw (Exception. (concat "No handler for type" (:type message))))))) 

Không có điều đặc biệt về những ví dụ này - bạn có thể thực hiện tất cả chúng bằng Java hoặc bất kỳ ngôn ngữ nào khác. Mặc dù, những thứ như từ khóa (ví dụ 1), các hàm bậc cao hơn (ví dụ thứ 2), các macro (tất cả 3 ví dụ) làm cho bạn mã súc tích và mô tả hơn.

Các vấn đề liên quan