Sự khác biệt giữa API và Ngôn ngữ cụ thể miền nhúng (DSL) là gì?
Có phải chỉ là cú pháp?
Hãy xem xét một API như OpenGL. Nó khác với DSL đồ họa như thế nào?
Nói cách khác, nếu một API đủ phức tạp, nó có thể được coi là một DSL nhúng không?
Sự khác biệt giữa API và Ngôn ngữ cụ thể miền nhúng (DSL) là gì?
Có phải chỉ là cú pháp?
Hãy xem xét một API như OpenGL. Nó khác với DSL đồ họa như thế nào?
Nói cách khác, nếu một API đủ phức tạp, nó có thể được coi là một DSL nhúng không?
Câu trả lời:
Sự khác biệt là khó thực hiện, và phụ thuộc vào ngôn ngữ được sử dụng. Đó cũng là chủ quan.
Trong clojure, bạn có thể xác định các API trông giống như DSL. Ví dụ, nấc cụt cho phép bạn tạo html:
(html [:span {:class "foo"} "bar"])
Điều này có thể được coi là một DSL với một cú pháp lisp. Thực tế html
có thể là một macro mang lại cho nó sức mạnh tương tự như khi bạn đang viết một lib templating html với biểu thức s (xem sxml )
Trong python, API tương tự có thể trông giống như:
html(["span", {"class" : "foo"}, "bar"])
html là một hàm. Đối số của nó sẽ được đánh giá trước, và sau đó lệnh gọi hàm sẽ xảy ra. Thực tế là cú pháp python cụ thể hơn, và ngữ nghĩa của python nghiêm ngặt hơn có nghĩa là biểu thức này khó diễn giải hơn như là một DSL độc lập với ngôn ngữ.
Một biểu diễn ngôn ngữ cổ điển là một cây giống như cấu trúc dữ liệu và một hàm eval được gọi đệ quy trên các nút của nó. Các ngôn ngữ LISP làm cho cấu trúc cây này rất rõ ràng, do đó, bất kỳ lệnh gọi hàm lồng nhau nào không thể phân biệt được với tính năng ngôn ngữ tích hợp. Đó là lý do tại sao cộng đồng LISP nói về DSL cho hầu hết mọi thứ.
Tôi tin rằng lập trình là về việc cung cấp trừu tượng hữu ích. Tôi thấy rằng nhìn vào mọi thứ bạn xây dựng (một lib hoặc thậm chí là UI của ứng dụng của bạn) như các yếu tố ngôn ngữ giúp mọi người giải quyết vấn đề phức tạp là một cách hiệu quả để thiết kế hầu hết mọi thứ. Với viễn cảnh này, tôi khẳng định rằng mọi thư viện đều là DSL, nhưng một số trong số chúng được thiết kế kém :-)
API và DSL là các khái niệm khá khác nhau và chỉ có một số lĩnh vực mà chúng có thể được cho là trùng lặp.
Tất cả DSL là ngôn ngữ máy tính . Chúng có thể được giải thích, biên dịch, đánh dấu, ngôn ngữ truy vấn (ví dụ SQL) hoặc (như JSON hoặc một số cách sử dụng XML) ngôn ngữ có thể được sử dụng trong các thông báo được truyền qua API, nhưng chúng phải là ngôn ngữ . Thuật ngữ mô tả bản chất , không phải mục đích.
API là các giao diện cho phép một thành phần phần mềm được sử dụng bởi các thành phần khác. Thuật ngữ mô tả mục đích , không phải bản chất. Ví dụ, một API có thể là một tập hợp các phương thức đối tượng - đó không phải là DSL. API web có thể sử dụng DSL (hoặc, nếu nó yên tĩnh, bạn có thể lập luận rằng đó là DSL) nhưng ngôn ngữ cụ thể, tên miền được chia sẻ không phải là một phần của định nghĩa. Trình điều khiển phần mềm cho thiết bị có thể được viết bằng C, API được phân phối dưới dạng thư viện được biên dịch, giao thức hoàn toàn nhị phân và bất kỳ ngôn ngữ nào có thể sử dụng thư viện có thể được sử dụng để tạo máy khách. Không có gì trong API đó có thể được gọi là DSL (danh sách các tên tượng trưng cho các hàm API không cắt nó).
Tôi hơi bối rối về lý do tại sao bạn chỉ có thể nhìn thấy sự tương đồng, được đưa ra các định nghĩa.
Nói chung, không. DSL được cố tình làm cho không chung chung nhằm mục đích làm cho một số hoạt động thuận tiện hơn. Những thứ như HTML hoặc Logo ban đầu là các ngôn ngữ dành riêng cho tên miền.
Nói chung, bạn không thể nhúng DSL vào ngôn ngữ khác ngay cả với API mạnh nhất; bất cứ điều gì bạn lập trình chống lại API đó vẫn sẽ trông giống như một loạt các biểu thức trong ngôn ngữ máy chủ và không thuận tiện như sử dụng ngôn ngữ có mục đích đặc biệt.
Các ngoại lệ là các ngôn ngữ cung cấp các cơ hội đặc biệt để sửa lỗi cú pháp thông qua thư viện (quá tải toán tử như C ++, phát minh ra các toán tử mới như Scala hoặc thậm chí đưa ra một cú pháp đọc hoàn toàn khác như Perl với các bộ lọc nguồn). Khi bạn sử dụng ngôn ngữ như vậy và tận dụng tối đa tính linh hoạt mà họ cung cấp, thì kết quả có thể trông giống như một ngôn ngữ mới, có mục đích đặc biệt (nhưng ngữ nghĩa thường sẽ khác biệt với những gì bạn mong đợi nếu ngôn ngữ đó thực sự được phát minh từ mặt đất lên để phục vụ kết thúc của bạn).
Ở đây, từ DslBoundary của Martin Fowler
Từ bài viết, sự hiểu biết của tôi về cơ bản DSL được nhúng và API không quá khác biệt. Nhưng tuy nhiên, có một chút khác biệt ở đây.
Nhưng nếu nói về DSL bên ngoài thì đó sẽ là một câu chuyện khác. DSL bên ngoài giống như một ngôn ngữ lập trình nhỏ nhưng chắc chắn, nó không phải là ngôn ngữ có mục đích chung có nghĩa là nó không thể giải quyết tất cả các vấn đề mà thay vào đó là vấn đề cụ thể.
Tôi nghĩ rằng mọi API là một DSL nhúng nhưng điều ngược lại là không đúng: không phải mọi DSL được nhúng đều là API. Chỉ khi ngôn ngữ được sử dụng làm phương tiện để tích hợp các thành phần, nó mới có thể được gọi là API.
Tại sao API có thể được coi là DSL nhúng? Trước hết, nó tạo thành một ngôn ngữ: nó có các yếu tố nguyên thủy (loại và hoạt động) có thể được kết hợp (bằng phương tiện của ngôn ngữ máy chủ) để tạo thành trừu tượng và giải quyết các vấn đề phức tạp. Ví dụ: API OpenGL có thể được sử dụng để hiển thị cảnh 3D trong thời gian thực. API Bộ sưu tập có thể được sử dụng để tạo các thuật toán hoạt động trên các bộ đối tượng, v.v. Thứ hai, nó rõ ràng là miền cụ thể; ví dụ: miền của Bộ sưu tập API đang xử lý các bộ đối tượng và miền của API OpenGL là kết xuất 3D. Do đó, API là một ngôn ngữ cụ thể của miền.
Nhưng không phải mọi DSL đều là API. Ví dụ, một số DSL không được triển khai bởi một thành phần được chỉ định. Tất cả các hệ thống xác định một số trừu tượng và các trừu tượng liên quan đến một số miền cụ thể có thể được coi là DSL, nhưng điều đó không có nghĩa là việc triển khai các trừu tượng này phải là "có thể hoán đổi", nói cách khác, chúng không phải tạo thành API . Họ có thể, nhưng điều đó không phải lúc nào cũng cần thiết. Tuy nhiên, trong trường hợp khi triển khai được "thành phần hóa" (xin lỗi vì thiếu thuật ngữ tốt hơn), DSL thực sự trở thành một API.