Là mã nguồn tạo ra một mô hình chống?


118

Nếu một cái gì đó có thể được tạo ra, thì thứ đó là dữ liệu, không phải mã.

Cho rằng, toàn bộ ý tưởng về việc tạo mã nguồn này có phải là một sự hiểu lầm không? Đó là, nếu có một trình tạo mã cho một cái gì đó, vậy thì tại sao không biến cái đó thành một hàm thích hợp có thể nhận các tham số cần thiết và thực hiện đúng hành động mà mã "sẽ tạo" sẽ làm?

Nếu nó đang được thực hiện vì lý do hiệu suất, thì điều đó nghe có vẻ như là một thiếu sót của trình biên dịch.

Nếu nó được thực hiện để kết nối hai ngôn ngữ, thì điều đó nghe có vẻ như thiếu thư viện giao diện.

Am i thiếu cái gì ở đây?

Tôi biết rằng mã là dữ liệu là tốt. Điều tôi không hiểu là tại sao lại tạo mã nguồn ? Tại sao không làm cho nó thành một chức năng có thể chấp nhận các tham số và hành động trên chúng?


11
Một thuật ngữ liên quan đến việc tạo mã là siêu lập trình
Vô dụngCat

4
en.wikipedia.org/wiki/Code_as_data , Lisp, FP, kịch bản, lập trình meta, Von Neumann / sửa đổi kiến trúc Harvard vv Nó được bao phủ nauseam quảng cáo . tl; dr phân biệt "mã nguồn" so với "mã đầu ra", "mã" so với "dữ liệu", vv có nghĩa là để đơn giản hóa mọi thứ. Họ không bao giờ nên giáo điều .
vaxquis

9
@Utku, những lý do tốt hơn để tạo mã thường liên quan đến việc muốn cung cấp một mô tả cấp cao hơn ngôn ngữ hiện tại của bạn có thể diễn đạt . Cho dù trình biên dịch có thể hoặc không thể tạo mã hiệu quả không thực sự có liên quan đến nó. Hãy xem xét các trình tạo trình phân tích cú pháp - một trình phân tích cú pháp được tạo bởi flexhoặc một trình phân tích cú pháp được tạo bởi bisongần như chắc chắn sẽ dễ đoán hơn, chính xác hơn và thường được thực thi nhanh hơn so với các chữ viết tay tương đương bằng C; và được xây dựng từ mã ít hơn rất nhiều (do đó cũng ít phải làm việc hơn để duy trì).
Charles Duffy

1
Có thể bạn đến từ một ngôn ngữ không có nhiều yếu tố chức năng, nhưng trong nhiều ngôn ngữ, chức năng là hạng nhất - bạn có thể chuyển chúng đi, vì vậy trong các loại ngôn ngữ đó là dữ liệu và bạn có thể coi nó như thế.
Restioson

1
@Restioson trong một mã ngôn ngữ chức năng không phải là dữ liệu. Các hàm hạng nhất có nghĩa chính xác là: Hàm là dữ liệu. Và không nhất thiết là dữ liệu đặc biệt tốt: bạn không nhất thiết phải biến đổi chúng chỉ một chút (như biến đổi tất cả các bổ sung trong các hàm thành phép trừ, giả sử). Mã là dữ liệu trong các ngôn ngữ Homoiconic. (hầu hết các ngôn ngữ đồng âm đều có chức năng hạng nhất. Nhưng điều ngược lại là không đúng.).
Lyndon White

Câu trả lời:


150

Là mã nguồn tạo ra một mô hình chống?

Về mặt kỹ thuật, nếu chúng ta tạo mã, nó không phải là nguồn ngay cả khi đó là văn bản mà con người có thể đọc được. Mã nguồn là mã gốc, được tạo ra bởi một con người hoặc trí thông minh thực sự khác, không được dịch một cách máy móc và không thể tái tạo ngay lập tức từ nguồn (thật) (trực tiếp hoặc gián tiếp).

Nếu một cái gì đó có thể được tạo ra, hơn thứ đó là dữ liệu, không phải mã.

Tôi sẽ nói mọi thứ đều dữ liệu . Ngay cả mã nguồn. Đặc biệt là mã nguồn! Mã nguồn chỉ là dữ liệu trong một ngôn ngữ được thiết kế để hoàn thành các nhiệm vụ lập trình. Dữ liệu này sẽ được dịch, giải thích, biên dịch, tạo khi cần thiết thành các dạng khác - của dữ liệu - một số trong đó có thể được thực thi.

Bộ xử lý thực hiện các hướng dẫn ra khỏi bộ nhớ. Bộ nhớ tương tự được sử dụng cho dữ liệu. Trước khi bộ xử lý thực thi các lệnh, chương trình được tải vào bộ nhớ dưới dạng dữ liệu .

Vì vậy, tất cả mọi thứ là dữ liệu , thậm chí mã .

Cho rằng [mã được tạo là dữ liệu], không phải toàn bộ ý tưởng tạo mã này là sự hiểu lầm sao?

Hoàn toàn ổn khi có nhiều bước biên dịch, một trong số đó có thể là tạo mã trung gian dưới dạng văn bản.

Đó là, nếu có một trình tạo mã cho một cái gì đó, vậy thì tại sao không biến cái đó thành một hàm thích hợp có thể nhận các tham số cần thiết và thực hiện đúng hành động mà mã "sẽ tạo" sẽ làm?

Đó là một cách, nhưng có những cách khác.


Đầu ra của việc tạo mã là văn bản, là thứ được thiết kế để con người sử dụng.

Không phải tất cả các hình thức văn bản được dành cho tiêu dùng của con người. Cụ thể, mã được tạo (dưới dạng văn bản) thường dành cho tiêu dùng trình biên dịch chứ không phải tiêu dùng của con người.


Mã nguồn được coi là bản gốc: bản gốc - những gì chúng tôi chỉnh sửa & phát triển; những gì chúng tôi lưu trữ bằng cách sử dụng kiểm soát mã nguồn. Mã được tạo, ngay cả khi văn bản có thể đọc được của con người, thường được tạo lại từ mã nguồn ban đầu . Mã được tạo, nói chung, không phải chịu sự kiểm soát nguồn vì nó được tạo lại trong quá trình xây dựng.


1
Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
maple_shaft

65

Lý luận thực tiễn

OK, tôi biết rằng mã là dữ liệu là tốt. Điều tôi không hiểu là tại sao lại tạo mã nguồn?

Từ chỉnh sửa này, tôi giả sử bạn đang hỏi ở mức độ khá thực tế, không phải là Khoa học Máy tính lý thuyết.

Lý do cổ điển để tạo mã nguồn bằng các ngôn ngữ tĩnh như Java là các ngôn ngữ như thế đơn giản là không thực sự đi kèm với các công cụ ngôn ngữ dễ sử dụng để làm các công cụ rất năng động. Ví dụ, trở lại thời kỳ hình thành của Java, đơn giản là không thể dễ dàng tạo một lớp có tên động (khớp tên bảng từ DB) và các phương thức động (khớp các thuộc tính từ bảng đó) với các kiểu dữ liệu động (khớp các loại thuộc tính đã nói). Đặc biệt là vì Java đặt toàn bộ tầm quan trọng, nay, đảm bảo, về khả năng bắt lỗi kiểu trong thời gian biên dịch.

Vì vậy, trong một cài đặt như vậy, một lập trình viên chỉ có thể tạo mã Java và viết rất nhiều dòng mã theo cách thủ công. Thông thường, lập trình viên sẽ thấy rằng bất cứ khi nào một bảng thay đổi, anh ta phải quay lại và thay đổi mã cho phù hợp; và nếu anh ta quên điều đó, những điều tồi tệ sẽ xảy ra. Do đó, lập trình viên sẽ đi đến điểm mà anh ta viết một số công cụ làm việc đó cho anh ta. Và do đó, con đường bắt đầu tạo mã thông minh hơn bao giờ hết.

(Vâng, bạn có thể tạo mã byte một cách nhanh chóng, nhưng lập trình một thứ như vậy trong Java sẽ không phải là thứ mà một lập trình viên ngẫu nhiên sẽ làm chỉ bằng cách viết một vài dòng mã miền.)

So sánh điều này với các ngôn ngữ rất năng động, ví dụ như Ruby, mà tôi sẽ xem xét phản đề đối với Java ở hầu hết các khía cạnh (lưu ý rằng tôi đang nói điều này mà không đánh giá một trong hai cách tiếp cận; chúng đơn giản là khác nhau). Ở đây, 100% bình thường và tiêu chuẩn để tự động tạo các lớp, phương thức, v.v. trong thời gian chạy, và quan trọng nhất, lập trình viên có thể thực hiện nó ngay trong mã, mà không cần đi đến mức "meta". Vâng, những thứ như Ruby on Rails đi kèm với việc tạo mã, nhưng chúng tôi thấy trong công việc của mình, về cơ bản chúng tôi sử dụng nó như một loại "chế độ hướng dẫn" nâng cao cho các lập trình viên mới, nhưng sau một thời gian, nó trở nên thừa thãi (vì có quá ít mã để viết trong hệ sinh thái đó rằng khi bạn biết bạn đang làm gì, viết nó bằng tay sẽ nhanh hơn việc dọn sạch mã được tạo).

Đây chỉ là hai ví dụ thực tế từ "thế giới thực". Sau đó, bạn có các ngôn ngữ như LISP trong đó mã dữ liệu, theo nghĩa đen. Mặt khác, trong các ngôn ngữ được biên dịch (không có công cụ thời gian chạy như Java hoặc Ruby), có (hoặc, tôi không theo kịp các tính năng C ++ hiện đại ...) đơn giản là không có khái niệm xác định tên lớp hoặc phương thức khi chạy, Vì vậy, việc tạo mã quá trình xây dựng là công cụ được lựa chọn cho hầu hết mọi thứ (các ví dụ cụ thể khác về C / C ++ sẽ là những thứ như flex, yacc, v.v.).


1
Tôi nghĩ rằng điều này là tốt hơn so với các câu trả lời được bình chọn nhiều hơn. Cụ thể, ví dụ được đề cập với Java và lập trình cơ sở dữ liệu thực hiện công việc tốt hơn nhiều trong việc giải quyết lý do tại sao việc tạo mã được sử dụng và là một công cụ hợp lệ.
Panzercrisis

Ngày nay, Java có thể tạo các bảng động từ DB không? Hay chỉ bằng cách sử dụng ORM?
Noumenon

"(Hoặc là, tôi đã không theo kịp các tính năng C ++ hiện đại ...)" chắc chắn điều này đã có thể có trong C ++ trong hơn hai thập kỷ nhờ các con trỏ chức năng? Tôi đã không kiểm tra nó nhưng tôi chắc chắn có thể phân bổ một mảng char, điền mã máy và sau đó chuyển một con trỏ đến phần tử đầu tiên thành một con trỏ hàm và sau đó chạy nó? (Giả sử nền tảng đích không có một số biện pháp bảo mật để ngăn bạn làm điều đó, điều đó có thể làm tốt.)
Pharap

1
"phân bổ một mảng char, điền nó với mã máy và sau đó chuyển một con trỏ tới phần tử đầu tiên thành một con trỏ hàm và sau đó chạy nó?" Ngoài hành vi không được xác định, C ++ tương đương với "tạo mã byte khi đang di chuyển". Nó thuộc cùng loại "không được các lập trình viên bình thường" xem xét
Caleth

1
@Pharap, "chắc chắn điều này đã có thể có trong C ++ trong hơn hai thập kỷ" ... Tôi đã phải cười thầm một chút; đó là khoảng 2 thập kỷ kể từ lần cuối tôi mã hóa C ++. :) Nhưng dù sao thì câu nói của tôi về C ++ đã được hình thành rất tệ. Tôi đã thay đổi nó một chút, bây giờ nó phải rõ ràng hơn những gì tôi muốn nói.
AnoE

44

Tại sao tạo mã?

Bởi vì lập trình với thẻ đục lỗ (hoặc mã alt trong notepad ) là một nỗi đau.

Nếu nó đang được thực hiện vì lý do hiệu suất, thì điều đó nghe có vẻ như là một thiếu sót của trình biên dịch.

Thật. Tôi không quan tâm đến hiệu suất trừ khi tôi bị ép buộc.

Nếu nó được thực hiện để kết nối hai ngôn ngữ, thì điều đó nghe có vẻ như thiếu thư viện giao diện.

Hmm, không biết bạn đang nói về cái gì

Trông giống như thế này: Mã nguồn được tạo và giữ lại luôn luôn và mãi mãi là một nỗi đau ở mông. Nó tồn tại chỉ vì một lý do. Ai đó muốn làm việc bằng một ngôn ngữ trong khi người khác khăng khăng làm việc bằng ngôn ngữ khác và không ai có thể bận tâm tìm ra cách tương tác giữa họ để một trong số họ tìm ra cách biến ngôn ngữ yêu thích của họ thành ngôn ngữ bị áp đặt để họ có thể làm gì họ muốn.

Điều đó là tốt cho đến khi tôi phải duy trì nó. Tại điểm mà tất cả các bạn có thể đi chết.

Có phải là một mô hình chống? Thở dài, không. Nhiều ngôn ngữ thậm chí sẽ không tồn tại nếu chúng ta không muốn nói lời tạm biệt với những thiếu sót của các ngôn ngữ trước đó và tạo mã của các ngôn ngữ cũ là có bao nhiêu ngôn ngữ mới bắt đầu.

Đó là một cơ sở mã còn lại trong một nửa chắp vá quái vật Frankenstein đã chuyển đổi mà tôi không thể chịu được. Mã được tạo là mã không thể chạm tới. Tôi ghét nhìn vào mã không thể chạm tới. Tuy nhiên, mọi người tiếp tục kiểm tra nó. TẠI SAO? Bạn cũng có thể được kiểm tra trong thực thi.

Giờ tôi đang ca ngợi. Quan điểm của tôi là tất cả chúng ta "tạo mã". Đó là khi bạn coi mã được tạo như mã nguồn khiến bạn phát điên. Chỉ cần làm cho nó trông giống như mã nguồn không làm cho nó mã nguồn.


41
Nếu bạn tạo nó, nó không phải là mã NGUỒN. Đó là mã trung gian. Tôi sẽ khóc bây giờ.
candied_orange

65
ARG !!! Nó không quan trọng nó trông như thế nào !!! Văn bản, nhị phân, DNA, nếu không phải là NGUỒN thì đó không phải là thứ bạn nên chạm vào khi thực hiện thay đổi. Không có ai kinh doanh nếu quá trình biên dịch của tôi có 42 ngôn ngữ trung gian mà nó đi qua. Ngừng chạm vào chúng. Dừng kiểm tra chúng trong. Thực hiện các thay đổi của bạn tại nguồn.
candied_orange

24
XML là văn bản và rõ ràng nó không có nghĩa là tiêu dùng của con người. :-)
Nick Keighley

38
@utku: "Nếu một thứ gì đó không có nghĩa là bị con người tiêu thụ, thì nó không nên là văn bản": Tôi hoàn toàn không đồng ý. Một số ví dụ ngược lại trên đầu tôi: giao thức HTTP, mã hóa MIME, tệp PEM - khá nhiều thứ sử dụng Base64 ở bất cứ đâu. Có rất nhiều lý do để mã hóa dữ liệu thành luồng an toàn 7 bit ngay cả khi không có con người nào nhìn thấy nó. Chưa kể không gian lớn hơn rất nhiều những điều mà bình thường một con người không bao giờ nên tương tác với, nhưng mà họ có thể muốn thỉnh thoảng: file log, /etc/file trên Unix, vv
Daniel Pryden

12
Tôi không nghĩ "lập trình với thẻ đục lỗ" có nghĩa là những gì bạn nghĩ nó có nghĩa. Tôi đã ở đó, tôi đã làm điều đó, và vâng, đó một nỗi đau; nhưng nó không có kết nối với "mã được tạo." Một tập hợp các thẻ đục lỗ chỉ là một loại tệp khác - như một tệp trên đĩa, hoặc một tệp trên băng hoặc một tệp trên thẻ SD. Trước đây, chúng tôi sẽ ghi dữ liệu vào các cỗ bài và đọc dữ liệu từ chúng. Vì vậy, nếu lý do chúng tôi tạo mã là vì lập trình bằng thẻ đục lỗ là một nỗi đau, thì điều đó ngụ ý rằng lập trình với bất kỳ loại lưu trữ dữ liệu nào là một nỗi đau.
Solomon chậm

41

tại sao tạo mã nguồn

Trường hợp sử dụng thường xuyên nhất cho các trình tạo mã mà tôi phải làm việc trong sự nghiệp của mình là các trình tạo

  • lấy một số mô tả meta mức cao cho một số loại mô hình dữ liệu hoặc lược đồ cơ sở dữ liệu làm đầu vào (có thể là một lược đồ quan hệ hoặc một loại lược đồ XML)

  • và sản xuất mã CRUD của nồi hơi cho các lớp truy cập dữ liệu làm đầu ra và có thể bổ sung những thứ như SQL hoặc tài liệu tương ứng.

Lợi ích ở đây là từ một dòng của một đặc tả đầu vào ngắn, bạn nhận được 5 đến 10 dòng mã gỡ lỗi, an toàn loại, không có lỗi (giả sử đầu ra của trình tạo mã là trưởng thành) mà bạn phải thực hiện và duy trì bằng tay. Bạn có thể tưởng tượng điều này làm giảm bao nhiêu nỗ lực bảo trì và phát triển.

Hãy để tôi cũng trả lời câu hỏi ban đầu của bạn

Là mã nguồn tạo ra một mô hình chống

Không, không phải tạo mã nguồn mỗi se, nhưng thực sự có một số cạm bẫy. Như đã nêu trong Lập trình viên thực dụng , người ta nên tránh sử dụng trình tạo mã khi nó tạo mã khó hiểu . Mặt khác, các nỗ lực gia tăng để sử dụng hoặc gỡ lỗi mã này có thể dễ dàng vượt xa nỗ lực được lưu bằng cách không viết mã theo cách thủ công.

Tôi cũng muốn nói thêm rằng, nhiều khi nên tách các phần mã được tạo ra khỏi mã được viết thủ công theo cách vật lý theo cách tạo lại không ghi đè lên bất kỳ thay đổi thủ công nào. Tuy nhiên, tôi cũng đã xử lý tình huống hơn một lần khi nhiệm vụ di chuyển một số mã được viết bằng ngôn ngữ cũ X sang ngôn ngữ Y hiện đại hơn, với ý định bảo trì sau đó bằng ngôn ngữ Y. Đây là cách sử dụng hợp lệ trường hợp để tạo mã một lần.


Tôi đồng ý với câu trả lời này. Sử dụng một cái gì đó như Torque cho java, tôi có thể tạo các tệp nguồn java tự động, với các trường khớp với cơ sở dữ liệu sql. Điều này làm cho hoạt động crud dễ dàng hơn nhiều. Lợi ích chính là an toàn kiểu, bao gồm chỉ có thể tham chiếu các trường tồn tại trong cơ sở dữ liệu (Cảm ơn bạn tự động hoàn thành).
MTilsted

Có, đối với các ngôn ngữ được nhập tĩnh, đây là phần quan trọng: bạn có thể đảm bảo mã viết tay của mình thực sự phù hợp với ngôn ngữ được tạo.
Paŭlo Ebermann

"Di chuyển một số mã được viết bằng ngôn ngữ cũ" - ngay cả khi đó, việc tạo mã một lần có thể là một nỗi đau lớn. Ví dụ: sau một số thay đổi thủ công, bạn phát hiện ra lỗi trong trình tạo và cần làm lại việc tạo sau khi sửa. May mắn thay, git hoặc như nhau thường có thể làm giảm đau.
maaartinus

13

Tại sao tạo mã nguồn?

Tôi đã gặp hai trường hợp sử dụng cho mã được tạo (tại thời điểm xây dựng và chưa bao giờ đăng ký):

  1. Tự động tạo mã soạn sẵn, chẳng hạn như getters / setters, toString, bằng và hashCode từ một ngôn ngữ được xây dựng để chỉ định những thứ đó (ví dụ: dự án lombok cho Java)
  2. Tự động tạo các lớp loại DTO từ một số đặc tả giao diện (REST, SOAP, bất cứ thứ gì) để sau đó được sử dụng trong mã chính. Điều này tương tự như vấn đề cầu nối ngôn ngữ của bạn, nhưng cuối cùng lại sạch sẽ và đơn giản hơn, với cách xử lý kiểu tốt hơn so với cố gắng thực hiện điều tương tự mà không tạo các lớp.

15
Mã lặp đi lặp lại cao trong các ngôn ngữ không diễn đạt. Chẳng hạn, tôi đã phải viết mã mà thiết yếu đã làm điều tương tự trên nhiều cấu trúc dữ liệu tương tự nhưng không giống nhau. Nó có thể đã được thực hiện với một cái gì đó giống như một mẫu C ++ (không phải đó là việc tạo mã?). Nhưng tôi đã sử dụng C. Tạo mã đã giúp tôi viết rất nhiều mã gần giống nhau.
Nick Keighley

1
@NickKeighley Có lẽ chuỗi công cụ của bạn không cho phép bạn sử dụng ngôn ngữ khác phù hợp hơn?
Wilson

7
Bạn thường không được chọn và chọn ngôn ngữ thực hiện. Dự án là ở C, đó không phải là một lựa chọn.
Nick Keighley

1
@Wilson các ngôn ngữ biểu cảm hơn thường sử dụng việc tạo mã (ví dụ: macro lisp, ruby ​​trên đường ray), chúng chỉ không yêu cầu được lưu dưới dạng văn bản trong khi đó.
Pete Kirkham

4
Vâng, tạo mã về cơ bản là lập trình meta. Các ngôn ngữ như Ruby cho phép bạn tự lập trình meta bằng ngôn ngữ, nhưng C không vì thế mà bạn phải sử dụng tạo mã thay thế.
Sean Burton

13

Sussmann đã có nhiều điều thú vị để nói về những điều như vậy trong "Cấu trúc và giải thích các chương trình máy tính" cổ điển của mình, chủ yếu là về tính đối ngẫu của dữ liệu mã.

Đối với tôi, việc sử dụng chính của việc tạo mã adhoc là sử dụng một trình biên dịch có sẵn để chuyển đổi một số ngôn ngữ cụ thể của miền thành một thứ mà tôi có thể liên kết vào các chương trình của mình. Hãy nghĩ về BNF, nghĩ về ASN1 (Thật ra, đừng, nó thật xấu xí), hãy nghĩ về bảng tính từ điển dữ liệu.

Các ngôn ngữ cụ thể của miền tầm thường có thể là một trình tiết kiệm thời gian khổng lồ và xuất ra thứ gì đó có thể được biên dịch bằng các công cụ ngôn ngữ tiêu chuẩn là cách để tạo ra những thứ như vậy, mà bạn muốn chỉnh sửa, một trình phân tích cú pháp không tầm thường trong bất kỳ ngôn ngữ bản địa nào bạn đang sử dụng viết, hoặc BNF cho một tự động tạo ra?

Bằng cách xuất văn bản sau đó được đưa đến một số trình biên dịch hệ thống, tôi có được tất cả các tối ưu hóa trình biên dịch và cấu hình cụ thể của hệ thống mà không phải suy nghĩ về nó.

Tôi đang sử dụng hiệu quả ngôn ngữ nhập trình biên dịch như một đại diện trung gian khác, vấn đề là gì? Các tệp văn bản vốn không phải là mã nguồn, chúng có thể là IR cho trình biên dịch và nếu chúng tình cờ trông giống như C hoặc C ++ hoặc Java hoặc bất cứ điều gì, ai quan tâm?

Bây giờ nếu bạn cảm thấy khó khăn, bạn có thể chỉnh sửa OUTPUT của trình phân tích cú pháp ngôn ngữ đồ chơi, điều này rõ ràng sẽ gây thất vọng vào lần tới khi ai đó chỉnh sửa các tệp ngôn ngữ đầu vào và xây dựng lại, câu trả lời là không cam kết IR được tạo tự động cho repo, hãy để nó được tạo bởi chuỗi công cụ của bạn (Và tránh việc có những người như vậy trong nhóm nhà phát triển của bạn, họ thường hạnh phúc hơn khi làm công việc tiếp thị).

Đây không phải là một sự thất bại về tính biểu cảm trong các ngôn ngữ của chúng tôi, vì một biểu hiện của thực tế là đôi khi bạn có thể lấy (hoặc xoa bóp) các phần của đặc tả thành một hình thức có thể được tự động chuyển đổi thành mã và thường sẽ ít bị lãng quên hơn lỗi và dễ dàng hơn để duy trì. Nếu tôi có thể cung cấp cho các nhân viên kiểm tra và cấu hình của mình một bảng tính, họ có thể điều chỉnh và một công cụ mà sau đó họ chạy dữ liệu đó và tạo ra một tệp hex hoàn chỉnh cho flash trên ECU của tôi thì đó là một cách tiết kiệm thời gian rất lớn khi có ai đó dịch thủ công thiết lập mới nhất thành một tập hợp các hằng số trong ngôn ngữ trong ngày (Hoàn thành với lỗi chính tả).

Điều tương tự với các mô hình xây dựng trong Simulink và sau đó tạo C bằng RTW sau đó biên dịch để nhắm mục tiêu với bất kỳ công cụ nào có ý nghĩa, C trung gian là không thể đọc được, vậy thì sao? Các công cụ Matlab RTW cấp cao chỉ cần biết một tập hợp con của C và trình biên dịch C sẽ chăm sóc các chi tiết nền tảng. Lần duy nhất con người phải mò mẫm thông qua C được tạo là khi các tập lệnh RTW có lỗi và loại điều đó dễ dàng hơn nhiều để gỡ lỗi với IR có thể đọc được trên con người sau đó chỉ bằng một cây phân tích nhị phân.

Tất nhiên bạn có thể viết những thứ như vậy để xuất mã byte hoặc thậm chí mã thực thi, nhưng tại sao bạn lại làm vậy? Chúng tôi có các công cụ để chuyển đổi IR thành những thứ đó.


Điều này là tốt, nhưng tôi nói thêm rằng có một sự đánh đổi khi xác định sử dụng IR nào: sử dụng C làm IR làm cho một số thứ dễ dàng hơn và những thứ khác khó hơn, khi so sánh với ngôn ngữ lắp ráp x86. Sự lựa chọn thậm chí còn có ý nghĩa hơn khi lựa chọn giữa, giả sử, mã ngôn ngữ Java và mã byte Java, vì có nhiều hoạt động khác chỉ tồn tại trong một hoặc ngôn ngữ khác.
Daniel Pryden

2
Nhưng ngôn ngữ lắp ráp X86 tạo ra một IR kém khi nhắm mục tiêu lõi ARM hoặc PPC! Tất cả mọi thứ là một sự đánh đổi trong kỹ thuật, đó là lý do tại sao họ gọi nó là Kỹ thuật. Mọi người sẽ hy vọng rằng các khả năng của mã byte Java là sự thay thế nghiêm ngặt các khả năng của ngôn ngữ Java và điều này nói chung là đúng khi bạn đến gần hơn với kim loại bất kể chuỗi công cụ và nơi bạn tiêm IR.
Dan Mills

Ồ, tôi hoàn toàn đồng ý: nhận xét của tôi là phản hồi cho câu hỏi cuối cùng của bạn về lý do tại sao bạn từng xuất mã byte hoặc một số thứ cấp thấp hơn - đôi khi bạn cần cấp thấp hơn. (Cụ thể trong Java, có rất nhiều điều hữu ích bạn có thể làm với mã byte mà bạn không thể làm bằng chính ngôn ngữ Java.)
Daniel Pryden

2
Tôi không đồng ý, nhưng có một chi phí khi sử dụng IR gần kim loại hơn, không chỉ ở tính tổng quát giảm, mà trên thực tế là bạn thường phải chịu trách nhiệm cho việc tối ưu hóa mức độ thực sự khó chịu. Thực tế là ngày nay chúng ta nghĩ về việc tối ưu hóa sự lựa chọn thuật toán thay vì triển khai là một sự phản ánh về việc trình biên dịch đã đi được bao xa, đôi khi bạn phải thực sự gần với kim loại trong những điều này, nhưng hãy suy nghĩ kỹ trước khi vứt bỏ trình biên dịch khả năng tối ưu hóa bằng cách sử dụng IR quá thấp.
Dan Mills

1
"Họ thường hạnh phúc hơn khi làm công việc tiếp thị" Catty, nhưng hài hước.
dmckee

13

Câu trả lời thực dụng: việc tạo mã có cần thiết và hữu ích không? Liệu nó có cung cấp thứ gì đó thực sự rất hữu ích và cần thiết cho cơ sở mã độc quyền hay dường như nó chỉ tạo ra một cách làm việc khác theo cách đóng góp nhiều chi phí trí tuệ hơn cho kết quả tối ưu?

OK, tôi biết rằng mã là dữ liệu là tốt. Điều tôi không hiểu là tại sao lại tạo mã? Tại sao không làm cho nó thành một chức năng có thể chấp nhận các tham số và hành động trên chúng?

Nếu bạn phải hỏi câu hỏi này và không có câu trả lời rõ ràng, thì có lẽ việc tạo mã là thừa và chỉ đóng góp chủ nghĩa kỳ lạ và rất nhiều chi phí trí tuệ cho cơ sở mã của bạn.

Trong khi đó, nếu bạn lấy thứ gì đó như OpenShadingL Language: https://github.com/imageworks/OpenShadingL Language

... Sau đó, những câu hỏi như vậy không cần phải được nêu ra vì chúng được trả lời ngay lập tức bởi kết quả ấn tượng.

OSL sử dụng khung trình biên dịch LLVM để dịch các mạng shader thành mã máy một cách nhanh chóng (chỉ trong thời gian hoặc "JIT") và trong quá trình này tối ưu hóa rất nhiều các shader và mạng với kiến ​​thức đầy đủ về các tham số shader và các giá trị thời gian chạy khác không thể đã được biết đến khi các shader được biên dịch từ mã nguồn. Kết quả là, chúng ta đang thấy các mạng che bóng OSL của chúng ta thực thi nhanh hơn 25% so với các trình tạo bóng tương đương được làm thủ công trong C! (Đó là cách các shader cũ của chúng tôi hoạt động trong trình kết xuất của chúng tôi.)

Trong trường hợp như vậy, bạn không cần phải đặt câu hỏi về sự tồn tại của trình tạo mã. Nếu bạn làm việc trong loại tên miền VFX này, thì phản hồi ngay lập tức của bạn thường là nhiều hơn về các dòng, "im lặng và lấy tiền của tôi!" hoặc, "wow, chúng ta cũng cần phải làm một cái gì đó như thế này."


dịch các mạng shader thành mã máy . Điều này nghe giống như một trình biên dịch chứ không phải là một trình tạo mã, phải không?
Utku

2
Về cơ bản, nó cần một mạng nút mà người dùng kết nối và tạo mã trung gian được biên dịch JIT bởi LLVM. Sự khác biệt giữa trình biên dịch và trình tạo mã là loại mờ. Bạn có nghĩ nhiều hơn về các dòng tính năng tạo mã trong các ngôn ngữ như các mẫu trong C ++ hoặc bộ tiền xử lý C không?

Tôi đã nghĩ về bất kỳ trình tạo nào sẽ xuất mã nguồn.
Utku

Tôi thấy, nơi đầu ra vẫn là cho tiêu dùng của con người tôi giả sử. OpenSL cũng tạo mã nguồn trung gian nhưng mã cấp thấp gần với lắp ráp để tiêu thụ LLVM. Nó thường không phải là mã có nghĩa là được duy trì (thay vào đó các lập trình viên duy trì các nút được sử dụng để tạo mã). Hầu hết thời gian tôi nghĩ rằng các loại trình tạo mã này có khả năng bị lạm dụng nhiều hơn là đủ hữu ích để chứng minh giá trị của chúng, đặc biệt nếu bạn phải liên tục tạo lại mã như một phần của quá trình xây dựng. Đôi khi, họ vẫn có một địa điểm chính hãng để giải quyết những thiếu sót ...

... của (các) ngôn ngữ khả dụng khi được sử dụng cho một tên miền cụ thể. QT có một trong những thứ gây tranh cãi với trình biên dịch đối tượng meta (MOC). MOC làm giảm bản tóm tắt mà bạn thường cần cung cấp các thuộc tính và phản xạ cũng như các tín hiệu và vị trí, v.v. trong C ++, nhưng không đến mức như vậy để chứng minh rõ ràng sự tồn tại của nó. Tôi thường nghĩ rằng QT có thể tốt hơn nếu không có gánh nặng rườm rà trong quá trình tạo mã của MOC.

8

Không, tạo mã trung gian không phải là mẫu chống. Câu trả lời cho phần khác của câu hỏi của bạn, "Tại sao lại làm như vậy?", Là một câu hỏi rất rộng (và riêng biệt), mặc dù tôi sẽ đưa ra một số lý do.

Phân nhánh lịch sử không bao giờ có mã trung gian có thể đọc được của con người

Hãy lấy C và C ++ làm ví dụ vì chúng là một trong những ngôn ngữ nổi tiếng nhất.

Bạn nên lưu ý rằng quá trình logic biên dịch đầu ra mã C không phải là mã máy mà là mã lắp ráp có thể đọc được của con người. Tương tự, các trình biên dịch C ++ cũ được sử dụng để biên dịch vật lý mã C ++ thành mã C. Trong chuỗi sự kiện đó, bạn có thể biên dịch từ mã 1 có thể đọc được của con người sang mã 2 có thể đọc được của con người sang mã 3 có thể đọc được của con người thành mã máy. "Tại sao?" Tại sao không?

Nếu mã trung gian, có thể đọc được của con người không bao giờ được tạo, chúng ta thậm chí có thể không C hoặc C ++. Đó chắc chắn là một khả năng; mọi người đi theo con đường ít kháng cự nhất với mục tiêu của họ và nếu một số ngôn ngữ khác đạt được hơi nước trước tiên vì sự trì trệ phát triển của C, C có thể đã chết trong khi nó vẫn còn trẻ. Tất nhiên, bạn có thể tranh luận "Nhưng sau đó có lẽ chúng ta sẽ sử dụng một số ngôn ngữ khác, và có lẽ nó sẽ tốt hơn." Có lẽ, hoặc có thể nó sẽ tồi tệ hơn. Hoặc có lẽ tất cả chúng ta vẫn sẽ được viết trong hội đồng.

Tại sao sử dụng mã trung gian có thể đọc được của con người?

  1. Đôi khi mã trung gian được mong muốn để bạn có thể sửa đổi nó trước bước tiếp theo trong quá trình xây dựng. Tôi sẽ thừa nhận điểm này là yếu nhất.
  2. Đôi khi, đó là vì công việc ban đầu không được thực hiện bằng bất kỳ ngôn ngữ nào có thể đọc được bằng con người mà thay vào đó là một công cụ mô hình hóa GUI.
  3. Đôi khi bạn cần phải làm một cái gì đó rất lặp đi lặp lại và ngôn ngữ không nên phục vụ cho những gì bạn đang làm bởi vì đó là một điều thích hợp hoặc một điều phức tạp đến nỗi nó không có kinh doanh làm tăng sự phức tạp hoặc ngữ pháp của ngôn ngữ lập trình chỉ để phù hợp bạn.
  4. Đôi khi bạn cần phải làm một cái gì đó rất lặp đi lặp lại, và không có cách nào có thể để có được những gì bạn muốn vào ngôn ngữ một cách chung chung; hoặc nó không thể được đại diện bởi hoặc xung đột với ngữ pháp của ngôn ngữ.
  5. Một trong những mục tiêu của máy tính là giảm nỗ lực của con người và đôi khi mã không thể được chạm lại (khả năng bảo trì thấp) có thể được viết mã meta để tạo mã dài hơn của bạn trong một phần mười thời gian; nếu tôi có thể làm điều đó trong 1 ngày thay vì 2 tuần và nó không có khả năng được duy trì bao giờ hết, sau đó tôi tốt hơn tạo ra nó - và trên cơ hội ra rằng một người nào đó 5 năm từ nay là khó chịu vì họ thực sự làm cần phải duy trì nó, sau đó họ có thể dành 2 tuần để viết nó đầy đủ nếu họ muốn, hoặc bị làm phiền bởi 1 tuần duy trì mã khó xử (nhưng chúng tôi vẫn còn 1 tuần nữa vào thời điểm đó), và đó là nếu việc bảo trì đó cần phải được thực hiện .
  6. Tôi chắc chắn có nhiều lý do tôi đang xem xét.

Thí dụ

Tôi đã làm việc trên các dự án trước khi mã cần được tạo dựa trên dữ liệu hoặc thông tin trong một số tài liệu khác. Ví dụ, một dự án có tất cả các thông điệp mạng và dữ liệu không đổi được xác định trong bảng tính và một công cụ sẽ đi qua bảng tính và tạo ra rất nhiều mã C ++ và Java cho phép chúng tôi làm việc với các thông báo đó.

Tôi không nói rằng đó là cách tốt nhất để thiết lập dự án đó (tôi không phải là một phần của công ty khởi nghiệp), nhưng đó là những gì chúng tôi có, và đó là hàng trăm (thậm chí hàng ngàn, không chắc chắn) về cấu trúc và vật thể và hằng số điều đó đã được tạo ra; tại thời điểm đó có lẽ đã quá muộn để cố gắng làm lại nó trong một cái gì đó như Rhapsody. Nhưng ngay cả khi nó được làm lại trong một cái gì đó như Rhapsody, thì chúng ta vẫn có mã được tạo từ Rhapsody .

Ngoài ra, có tất cả dữ liệu trong bảng tính theo một cách tốt: nó cho phép chúng tôi trình bày dữ liệu theo những cách mà chúng tôi không thể có nếu tất cả chỉ nằm trong các tệp mã nguồn.

Ví dụ 2

Khi tôi thực hiện một số công việc trong quá trình xây dựng trình biên dịch, tôi đã sử dụng công cụ Antlr để thực hiện phân tích và phân tích cú pháp. Tôi đã chỉ định một ngữ pháp ngôn ngữ, sau đó tôi đã sử dụng công cụ này để tạo ra một tấn mã trong C ++ hoặc Java, sau đó tôi đã sử dụng mã được tạo cùng với mã của riêng tôi và đưa nó vào bản dựng.

Làm thế nào khác nên được thực hiện? Có lẽ bạn có thể nghĩ ra một cách khác; có lẽ có những cách khác Nhưng đối với công việc đó, các cách khác sẽ không tốt hơn mã lex / parse được tạo mà tôi có.


Ive đã sử dụng mã trung gian như một loại định dạng tệp và theo dõi gỡ lỗi khi hai hệ thống không tương thích nhưng có một loại api ổn định nào đó, bằng ngôn ngữ kịch bản rất bí truyền. Không có nghĩa là được đọc bằng tay nhưng có thể giống như cách xml có thể. Nhưng điều này là phổ biến hơn bạn nghĩ sau khi tất cả các trang web hoạt động theo cách này, như ai đó đã chỉ ra.
joojaa

7

Những gì bạn đang thiếu là tái sử dụng .

Chúng tôi có một công cụ tuyệt vời để biến văn bản mã nguồn thành nhị phân, được gọi là trình biên dịch. Đầu vào của nó được xác định rõ (thường là!), Và nó đã trải qua rất nhiều công việc để tinh chỉnh cách thức tối ưu hóa. Nếu bạn thực sự muốn sử dụng trình biên dịch để thực hiện một số thao tác, bạn muốn sử dụng trình biên dịch hiện có và không viết trình biên dịch của riêng bạn.

Rất nhiều người phát minh ra các ngôn ngữ lập trình mới và viết các trình biên dịch của riêng họ. Khá nhiều không có ngoại lệ, tất cả chúng đều làm điều này vì họ được hưởng các thách thức, không phải vì họ cần những tính năng mà ngôn ngữ cung cấp. Mọi thứ họ làm đều có thể được thực hiện bằng ngôn ngữ khác; họ chỉ đơn giản là tạo ra một ngôn ngữ mới vì họ thích những tính năng đó. Những gì sẽ không có được chúng mặc dù là một trình biên dịch tối ưu, nhanh, hiệu quả, tối ưu hóa. Chắc chắn, sẽ mang lại cho họ thứ gì đó có thể biến văn bản thành nhị phân, chắc chắn, nhưng nó sẽ không tốt như tất cả các trình biên dịch hiện có .

Văn bản không chỉ là thứ mà con người đọc và viết. Máy tính là hoàn hảo ở nhà với văn bản quá. Trong các định dạng thực tế như XML (và các định dạng liên quan khác) thành công chúng sử dụng văn bản thuần túy. Các định dạng tệp nhị phân thường tối nghĩa và tài liệu kém, và người đọc không thể dễ dàng tìm ra cách chúng hoạt động. XML tương đối tự viết tài liệu, giúp mọi người dễ dàng viết mã sử dụng các tệp có định dạng XML. Và tất cả các ngôn ngữ lập trình được thiết lập để đọc và ghi tệp văn bản.

Vì vậy, giả sử bạn muốn thêm một số cơ sở mới để làm cho cuộc sống của bạn dễ dàng hơn. Có lẽ đó là một công cụ bố trí GUI. Có lẽ đó là giao diện tín hiệu và khe cắm mà Qt cung cấp. Có lẽ đó là cách mà Code Composer Studio cho phép bạn định cấu hình thiết bị bạn đang làm việc và kéo các thư viện phù hợp vào bản dựng. Có lẽ nó đang lấy một từ điển dữ liệu và các typedefs tự động tạo và các định nghĩa biến toàn cục (vâng, đây vẫn là một thứ rất nhiều trong phần mềm nhúng). Dù đó là gì, cách hiệu quả nhất để tận dụng trình biên dịch hiện tại của bạn là tạo ra một công cụ sẽ đưa cấu hình của bạn vào bất cứ thứ gì và nó tự động tạo mã theo ngôn ngữ bạn chọn.

Thật dễ dàng để phát triển và dễ kiểm tra, bởi vì bạn biết những gì đang diễn ra và bạn có thể đọc mã nguồn mà nó phát ra. Bạn không cần phải mất nhiều năm để xây dựng trình biên dịch cho đối thủ GCC. Bạn không cần phải học một ngôn ngữ hoàn toàn mới hoặc yêu cầu người khác phải học. Tất cả những gì bạn cần làm là tự động hóa một khu vực nhỏ này và mọi thứ khác vẫn giữ nguyên. Công việc hoàn thành.


Tuy nhiên, lợi thế của tính dựa trên văn bản của XML là nếu cần thiết , nó có thể được đọc và viết bởi con người (họ thường không bận tâm một khi nó hoạt động, nhưng chắc chắn là trong quá trình phát triển). Về mặt hiệu suất và hiệu quả không gian, các định dạng nhị phân thường tốt hơn nhiều (điều này thường không quan trọng, bởi vì nút cổ chai nằm ở một nơi khác).
leftaroundabout

@leftaroundabout Nếu bạn cần hiệu suất và hiệu quả không gian, chắc chắn. Lý do nhiều ứng dụng đã chuyển sang các định dạng dựa trên XML ngày nay là hiệu suất và hiệu quả không gian không phải là tiêu chí hàng đầu mà chúng từng có và lịch sử đã cho thấy các định dạng tệp nhị phân kém được duy trì như thế nào. (Tài liệu MS Word cũ cho một ví dụ cổ điển!) Điểm vẫn còn - văn bản chỉ phù hợp với máy tính để đọc như con người.
Graham

Chắc chắn, một định dạng nhị phân được thiết kế tồi có thể thực sự hoạt động kém hơn so với suy nghĩ đúng đắn thông qua định dạng văn bản và thậm chí một định dạng nhị phân đàng hoàng thường không gọn hơn nhiều so với XML được đóng gói với một số thuật toán nén đa mục đích. IMO tốt nhất của cả hai thế giới là sử dụng một đặc tả có thể đọc được của con người thông qua các kiểu dữ liệu đại số và tự động tạo ra một biểu diễn nhị phân hiệu quả từ AST của các loại này. Xem ví dụ thư viện phẳng .
rẽ trái

7

Một chút câu trả lời thực tế hơn, tập trung vào lý do tại sao và không phải là mã nguồn và không phải là gì. Lưu ý rằng việc tạo mã nguồn là một phần của quá trình xây dựng trong tất cả các trường hợp này - vì vậy các tệp được tạo không nên tìm đường vào kiểm soát nguồn.

Tương tác / đơn giản

Lấy Bộ đệm Giao thức của Google, một ví dụ điển hình: bạn viết một mô tả giao thức cấp cao duy nhất có thể được sử dụng để tạo triển khai bằng nhiều ngôn ngữ - thường các phần khác nhau của hệ thống được viết bằng các ngôn ngữ khác nhau.

Lý do thực hiện / kỹ thuật

Lấy TypeScript - trình duyệt không thể diễn giải nó để quá trình xây dựng sử dụng bộ chuyển mã (trình dịch mã sang mã) để tạo JavaScript. Trong thực tế, nhiều ngôn ngữ được biên dịch mới hoặc bí truyền bắt đầu bằng việc dịch mã sang C trước khi chúng có được một trình biên dịch thích hợp.

Dễ sử dụng

Đối với các dự án nhúng (nghĩ rằng IoT) được viết bằng C và chỉ sử dụng một nhị phân duy nhất (RTOS hoặc không có HĐH), việc tạo ra một mảng C với dữ liệu sẽ được biên dịch như thể mã nguồn thông thường, trái ngược với việc liên kết chúng trực tiếp với nhau làm tài nguyên.

Biên tập

Mở rộng trên protobuf: tạo mã cho phép các đối tượng được tạo thành các lớp hạng nhất trong bất kỳ ngôn ngữ nào. Trong ngôn ngữ được biên dịch, một trình phân tích cú pháp chung sẽ nhất thiết phải trả về cấu trúc khóa-giá trị - có nghĩa là bạn cần nhiều mã soạn sẵn, bạn bỏ lỡ một số kiểm tra thời gian biên dịch (đặc biệt là các khóa và loại giá trị), có hiệu năng kém hơn và không hoàn thành mã. Hãy tưởng tượng tất cả những người void*trong C hoặc rất lớn std::varianttrong C ++ (nếu bạn có C ++ 17), một số ngôn ngữ có thể không có tính năng nào như vậy cả.


Vì lý do đầu tiên, tôi nghĩ rằng ý tưởng của OP sẽ có một triển khai chung trong từng ngôn ngữ (lấy mô tả bộ đệm giao thức và sau đó phân tích / sử dụng định dạng trực tuyến). Tại sao điều này sẽ tồi tệ hơn việc tạo mã?
Paŭlo Ebermann

@ PaŭloEbermann ngoài các đối số độ hoàn hảo thông thường như một cách giải thích chung chung sẽ khiến không thể sử dụng các mớ hỗn độn đó như các đối tượng hạng nhất trong các ngôn ngữ được biên dịch (và có thể diễn giải) - trong C ++, ví dụ như một trình thông dịch sẽ trả về cấu trúc khóa-giá trị . Tất nhiên sau đó bạn có thể đưa kv đó vào các lớp của mình nhưng nó có thể biến thành rất nhiều mã soạn sẵn. Và cũng có mã hoàn thành quá. Và biên dịch kiểm tra thời gian - trình biên dịch của bạn sẽ không kiểm tra nếu chữ của bạn không có lỗi chính tả.
Jan Dorniak

Tôi đồng ý ... bạn có thể thêm điều này vào câu trả lời không?
Paŭlo Ebermann

@ PaŭloEbermann đã hoàn thành
Jan Dorniak

6

Là mã nguồn tạo ra một mô hình chống?

Đó là một cách giải quyết cho một ngôn ngữ lập trình biểu cảm không đủ. Không cần tạo mã bằng ngôn ngữ có chứa lập trình meta tích hợp đầy đủ.


3
Đó cũng là một cách giải quyết cho việc phải viết một trình biên dịch mã đối tượng đầy đủ, xuống bản địa để có ngôn ngữ biểu cảm hơn. Tạo C, hãy để trình biên dịch có trình tối ưu hóa tốt chăm sóc phần còn lại.
Blrfl

Không phải lúc nào. Đôi khi bạn có một hoặc nhiều cơ sở dữ liệu chứa một số định nghĩa cho các tín hiệu ví dụ trên xe buýt. Sau đó, bạn muốn kéo thông tin này lại với nhau, có thể thực hiện một số kiểm tra tính nhất quán và sau đó viết mã có giao diện giữa các tín hiệu đến từ bus và các biến bạn muốn có trong mã của mình. Nếu bạn có thể chỉ cho tôi một ngôn ngữ có lập trình meta giúp dễ dàng sử dụng một số trang khách được cung cấp Excel, cơ sở dữ liệu và các nguồn dữ liệu khác và tạo mã tôi cần, với một số kiểm tra cần thiết về tính hợp lệ và nhất quán của dữ liệu, thì bằng cách tất cả các phương tiện cho tôi thấy.
CodeMonkey

@CodeMonkey: một cái gì đó giống như triển khai ActiveRecord của Ruby on Rails xuất hiện trong tâm trí. Không cần phải sao chép lược đồ bảng cơ sở dữ liệu trong mã. Chỉ cần ánh xạ một lớp vào một bảng và viết logic nghiệp vụ bằng cách sử dụng các tên cột làm thuộc tính. Tôi không thể tưởng tượng bất kỳ loại mẫu nào có thể được tạo bởi một trình tạo mã cũng không thể được quản lý bởi lập trình meta của Ruby. Các mẫu C ++ cũng cực kỳ mạnh mẽ, mặc dù hơi phức tạp. Macro Lisp là một hệ thống lập trình meta ngôn ngữ mạnh mẽ khác.
kevin cline

@kevincline điều tôi muốn nói là mã dựa trên một số dữ liệu từ cơ sở dữ liệu (có thể được xây dựng từ nó), nhưng không phải là cơ sở dữ liệu. Tức là tôi có thông tin về những tín hiệu tôi nhận được trong Bảng Excel A. Tôi có Cơ sở dữ liệu B với thông tin về các tín hiệu này, v.v ... Bây giờ tôi muốn có một lớp truy cập các tín hiệu này. Không có kết nối với cơ sở dữ liệu hoặc bảng Excel trên máy chạy mã. Sử dụng C ++ Templating thực sự phức tạp để tạo mã này vào thời gian biên dịch, thay vì một trình tạo mã đơn giản. Tôi sẽ chọn codegen.
CodeMonkey

6

Tạo mã nguồn không phải lúc nào cũng là một mô hình chống. Ví dụ, tôi hiện đang viết một khung mà theo đặc tả cụ thể sẽ tạo mã bằng hai ngôn ngữ khác nhau (Javascript và Java). Khung công tác sử dụng Javascript được tạo để ghi lại các hành động của trình duyệt của người dùng và sử dụng mã Java trong Selenium để thực sự thực hiện hành động khi khung ở chế độ phát lại. Nếu tôi không sử dụng tạo mã, tôi sẽ phải đảm bảo thủ công rằng cả hai luôn đồng bộ, điều này rất cồng kềnh và cũng là một sự trùng lặp logic theo một cách nào đó.

Tuy nhiên, nếu người ta đang sử dụng việc tạo mã nguồn để thay thế các tính năng như generic, thì đó là chống mẫu.


Tất nhiên, bạn có thể viết mã của mình một lần trong ECMAScript và chạy nó trong Nashorn hoặc Rhino trên JVM. Hoặc, bạn có thể viết JVM bằng ECMAScript (hoặc thử biên dịch Avian sang WebAssugging bằng Emscripten) và chạy mã Java của bạn trong trình duyệt. Tôi không nói đó là những ý tưởng tuyệt vời (tốt, chúng có thể là những ý tưởng tồi tệ :-D), nhưng ít nhất chúng có thể nếu không khả thi.
Jörg W Mittag

Về lý thuyết, điều đó là có thể, nhưng nó không phải là một giải pháp chung. Điều gì xảy ra nếu tôi không thể chạy một trong các ngôn ngữ bên trong ngôn ngữ khác? Ví dụ, điều bổ sung: Tôi vừa tạo một mô hình Netlogo đơn giản bằng cách sử dụng mã và có một tài liệu tương tác của hệ thống, luôn đồng bộ với máy ghi và trình phát lại. Và nói chung, việc tạo một yêu cầu và sau đó tạo mã giữ cho mọi thứ chạy đồng bộ với nhau về mặt ngữ nghĩa.
Hristo Vrigazov

6

Am i thiếu cái gì ở đây?

Có lẽ một ví dụ tốt trong đó mã trung gian hóa ra là lý do thành công? Tôi có thể cung cấp cho bạn HTML.

Tôi tin rằng điều quan trọng đối với HTML là đơn giản và tĩnh - nó giúp dễ dàng tạo trình duyệt, nó cho phép khởi động trình duyệt di động sớm, v.v. . Nó chỉ ra rằng người dùng thực sự đang bị đe dọa bởi các applet Java và truy cập các trang web như vậy cũng an toàn như thử các vết nứt trò chơi được tải xuống qua DC ++. Mặt khác, HTML đơn giản là vô hại, đủ để cho phép chúng tôi kiểm tra bất kỳ trang web nào có niềm tin hợp lý về bảo mật thiết bị của chúng tôi.

Tuy nhiên, HTML sẽ không ở đâu gần nơi hiện tại nếu nó không phải là máy tính được tạo. Câu trả lời của tôi thậm chí sẽ không hiển thị trên trang này cho đến khi ai đó tự viết lại nó từ cơ sở dữ liệu thành tệp HTML. May mắn thay, bạn có thể tạo HTML có thể sử dụng được trong hầu hết mọi ngôn ngữ lập trình :)

Đó là, nếu có một trình tạo mã cho một cái gì đó, vậy thì tại sao không biến cái đó thành một hàm thích hợp có thể nhận các tham số cần thiết và thực hiện đúng hành động mà mã "sẽ tạo" sẽ làm?

Bạn có thể tưởng tượng cách tốt hơn để hiển thị câu hỏi và tất cả các câu trả lời và nhận xét cho người dùng hơn bằng cách sử dụng HTML làm mã giữa được tạo không?


Vâng, tôi có thể tưởng tượng một cách tốt hơn. HTML là một di sản của một quyết định của Tim Berners-Lee để cho phép tạo nhanh trình duyệt web chỉ có văn bản. Điều đó hoàn toàn tốt vào thời điểm đó, nhưng chúng tôi sẽ không làm điều tương tự với lợi ích của nhận thức muộn màng. CSS đã làm cho tất cả các loại phần tử trình bày khác nhau (DIV, SPAN, TABLE, UL, v.v.) không cần thiết.
kevin cline

@kevincline Tôi không nói rằng HTML như vậy là không có lỗi, tôi đã chỉ ra rằng việc giới thiệu ngôn ngữ đánh dấu (có thể được tạo bởi một chương trình) đã hoạt động rất tốt trong trường hợp này.
Džuris

Vì vậy, HTML + CSS tốt hơn là chỉ HTML. Tôi thậm chí đã viết tài liệu nội bộ cho một số dự án tôi đã làm việc trực tiếp trong HTML + CSS + MathJax. Nhưng hầu hết các trang web tôi truy cập dường như đã được tạo bởi các trình tạo mã.
David K

3

Tại sao tạo mã nguồn?

Bởi vì nó nhanh hơn và dễ dàng hơn (và ít bị lỗi hơn) so với việc viết mã thủ công, đặc biệt là cho các tác vụ lặp đi lặp lại, tẻ nhạt. Bạn cũng có thể sử dụng công cụ cấp cao để xác minh và xác thực thiết kế của mình trước khi viết một dòng mã.

Các trường hợp sử dụng phổ biến:

  • Các công cụ mô hình hóa như Rose hoặc Visual Paradigm;
  • Cao er ngôn ngữ cấp như SQL nhúng hoặc một ngôn ngữ định nghĩa giao diện mà phải được xử lý trước vào một cái gì đó compilable;
  • Máy phát điện và trình phân tích cú pháp như flex / bison;

Đối với "tại sao không chỉ biến nó thành một hàm và truyền tham số trực tiếp cho nó", lưu ý rằng không có cái nào ở trên là môi trường thực thi trong chính chúng. Không có cách nào để liên kết mã của bạn với họ.


2

Đôi khi, ngôn ngữ lập trình của bạn không có các phương tiện bạn muốn, khiến cho việc viết các hàm hoặc macro để thực hiện những gì bạn muốn là không thể. Hoặc có thể bạn có thể làm những gì bạn muốn, nhưng mã để viết nó sẽ xấu. Một tập lệnh Python đơn giản (hoặc tương tự) sau đó có thể tạo mã được yêu cầu như một phần của quy trình xây dựng của bạn, sau đó bạn #includevào tệp nguồn thực tế.

Làm thế nào để tôi biết điều này? Bởi vì đó là giải pháp tôi đã đạt được nhiều lần khi làm việc với nhiều hệ thống khác nhau, gần đây nhất là SourcePawn. Một tập lệnh Python đơn giản phân tích một dòng mã nguồn đơn giản và tạo ra hai hoặc ba dòng mã được tạo tốt hơn nhiều so với việc tạo thủ công mã được tạo, khi bạn kết thúc với hai chục dòng như vậy (tạo tất cả các cvars của tôi).

Mã nguồn trình diễn / ví dụ có sẵn nếu mọi người muốn nó.


1

Hình thức văn bản là cần thiết để tiêu thụ dễ dàng bởi con người. Máy tính cũng xử lý mã ở dạng văn bản khá dễ dàng. Do đó, mã được tạo nên được tạo ở dạng dễ tạo nhất và dễ sử dụng nhất bởi máy tính và đó là văn bản rất thường đọc được.

Và khi bạn tạo mã, chính quá trình tạo mã thường cần được gỡ lỗi - bởi con người. Nó rất, rất hữu ích nếu mã được tạo ra có thể đọc được để con người có thể phát hiện các vấn đề trong quá trình tạo mã. Ai đó phải viết mã để tạo mã, sau khi tất cả. Nó không xảy ra ngoài không khí mỏng.


1

Tạo mã, chỉ một lần

Không phải tất cả việc tạo mã nguồn là một trường hợp tạo ra một số mã, và sau đó không bao giờ chạm vào nó; sau đó tạo lại nó từ nguồn ban đầu khi cần cập nhật.

Đôi khi bạn tạo mã chỉ một lần, sau đó loại bỏ nguồn ban đầu và tiến về phía trước để duy trì nguồn mới.

Điều này đôi khi xảy ra khi chuyển mã từ ngôn ngữ này sang ngôn ngữ khác. Đặc biệt, nếu người ta không muốn chuyển sang các thay đổi mới trong bản gốc (ví dụ: mã ngôn ngữ cũ sẽ không được duy trì hoặc nó thực sự hoàn chỉnh (ví dụ trong trường hợp một số chức năng toán học)).

Một trường hợp phổ biến là viết một trình tạo mã để làm điều này, thực tế chỉ có thể dịch đúng 90% mã. và sau đó 10% cuối cùng cần phải được cố định bằng tay. Đó là nhanh hơn rất nhiều so với dịch 100% bằng tay.

Các trình tạo mã như vậy thường rất khác với loại trình tạo mã mà các trình dịch ngôn ngữ đầy đủ (như Cython hoặc f2c) tạo ra. Vì mục tiêu là để duy trì mã một lần. Họ thường được làm 1 tắt, để làm chính xác những gì họ phải làm. Theo nhiều cách, đây là phiên bản cấp tiếp theo của việc sử dụng regex / find-thay thế cho mã cổng. "Công cụ hỗ trợ chuyển" bạn có thể nói.

Tạo mã, chỉ một lần, từ ví dụ: một trang web cạo.

Liên quan chặt chẽ là nếu bạn tạo mã từ một số nguồn bạn không muốn truy cập lại. Ví dụ: Nếu các hành động cần thiết để tạo mã không thể lặp lại hoặc nhất quán hoặc thực hiện chúng là tốn kém. Tôi đang làm việc trên một cặp dự án ngay bây giờ: DataDeps.jlDataDepsGenerators.jl .

DataDeps.jl giúp người dùng tải xuống dữ liệu (như bộ dữ liệu ML tiêu chuẩn). Để làm điều này, nó cần những gì chúng ta gọi là RegistrationBlock. Đó là một số mã chỉ định một số siêu dữ liệu, như nơi tải xuống các tệp từ và tổng kiểm tra, và một thông báo giải thích cho người dùng bất kỳ điều khoản / mã hóa / trạng thái cấp phép nào trên dữ liệu.

Viết những khối đó có thể gây phiền nhiễu. Và thông tin đó thường có sẵn trong (có cấu trúc hoặc không có cấu trúc) từ các trang web nơi dữ liệu được lưu trữ. Vì vậy, DataDepsGenerators.jl, sử dụng một trình quét web để tạo RegistrationBlockCode, cho một số trang web lưu trữ nhiều dữ liệu.

Nó có thể không tạo ra chúng một cách chính xác. Vì vậy, nhà phát triển sử dụng mã được tạo có thể và nên kiểm tra và sửa nó. Điều lạ lùng là họ muốn đảm bảo rằng nó đã không bỏ sót thông tin cấp phép chẳng hạn.

Điều quan trọng, người dùng / nhà phát triển làm việc với DataDeps.jl không cần phải cài đặt hoặc sử dụng trình duyệt web để sử dụng mã RegistrationBlock đã được tạo. (Và không cần phải tải xuống và cài đặt một trình quét web giúp tiết kiệm một chút thời gian. Đặc biệt đối với các lần chạy CI)

Tạo mã nguồn một lần không phải là một antipotype. và nó thường không thể được thay thế bằng siêu lập trình.


"báo cáo" là một từ tiếng Anh có nghĩa là một từ khác ngoài "cổng một lần nữa". Hãy thử "re-port" để làm cho câu đó rõ ràng hơn. (Nhận xét vì quá nhỏ cho một chỉnh sửa được đề xuất.)
Peter Cordes

Bắt tốt @PeterCordes Tôi đã chia sẻ lại.
Lyndon White

Nhanh hơn nhưng có khả năng nhiều duy trì ít hơn, tùy thuộc vào cách khủng khiếp mã được tạo như. Fortran to C là một thứ trở lại trong ngày (trình biên dịch C có sẵn rộng rãi hơn, vì vậy mọi người sẽ sử dụng f2c+ cc), nhưng mã kết quả không thực sự là điểm khởi đầu tốt cho phiên bản C của chương trình, AFAIK.
Peter Cordes

1
Có khả năng, có khả năng không. Không phải lỗi trong khái niệm về trình tạo mã mà một số trình tạo mã tạo ra mã không thể bảo trì. Đặc biệt, một công cụ thủ công, không cần phải nắm bắt mọi trường hợp thường có thể tạo ra mã hoàn toàn đẹp. Ví dụ, nếu 90% mã chỉ là danh sách các hằng số mảng thì việc tạo các hàm xây dựng mảng đó như là một lần tắt có thể được thực hiện rất độc đáo và nỗ lực thấp. (Mặt khác, đầu ra mã C của Cython không thể được duy trì bởi con người. Bởi vì nó không có ý định. Giống như bạn nói f2clại trong ngày)
Lyndon White

1
Bảng lớn chỉ là đối số đơn giản nhất giảm. Tương tự có thể nói để chuyển đổi for-loop hoặc điều kiện. Quả thực sedđi một chặng đường dài, nhưng đôi khi người ta cần một chút sức mạnh biểu cảm. Dòng giữa logic chương trình và dữ liệu thường là một thứ tốt. Đôi khi sự phân biệt không hữu ích. JSON là (/ was) chỉ là mã xây dựng đối tượng javascript. Trong ví dụ của tôi, tôi cũng đang tạo mã xây dựng đối tượng (có phải là dữ liệu không? Có lẽ (có thể không vì đôi khi nó có chức năng gọi). Nó có được coi là mã tốt hơn không?)
Lyndon White

1

Tạo mã "nguồn" là một dấu hiệu cho thấy sự thiếu sót của ngôn ngữ được tạo ra. Là sử dụng các công cụ để khắc phục điều này một mô hình chống? Hoàn toàn không - hãy để tôi giải thích.

Thông thường việc tạo mã được sử dụng vì tồn tại một định nghĩa cấp cao hơn có thể mô tả mã kết quả ít dài hơn nhiều so với ngôn ngữ cấp thấp hơn. Vì vậy, việc tạo mã tạo điều kiện cho hiệu quả và sự căng thẳng.

Khi tôi viết c ++, tôi làm như vậy vì nó cho phép tôi viết mã hiệu quả hơn so với sử dụng trình biên dịch mã hoặc mã máy. Mã máy được tạo bởi trình biên dịch. Ban đầu, c ++ chỉ đơn giản là một bộ tiền xử lý tạo mã C. Ngôn ngữ mục đích chung là tuyệt vời để tạo ra hành vi mục đích chung.

Theo cách tương tự, bằng cách sử dụng DSL (ngôn ngữ cụ thể của miền), có thể viết ngắn gọn, nhưng có lẽ mã bị giới hạn trong một tác vụ cụ thể. Điều này sẽ làm cho nó ít phức tạp hơn để tạo ra hành vi chính xác của mã. Hãy nhớ rằng mã có nghĩa là và kết thúc . Những gì một nhà phát triển đang tìm kiếm là một cách hiệu quả để tạo ra hành vi.

Lý tưởng nhất là trình tạo có thể tạo mã nhanh từ đầu vào đơn giản hơn để thao tác và hiểu. Nếu điều này được thực hiện không sử dụng một trình tạo là một mô hình chống . Kiểu chống này thường xuất phát từ khái niệm rằng mã "thuần" là "sạch" hơn, giống như cách một người thợ gỗ hoặc nghệ nhân khác có thể nhìn vào việc sử dụng các công cụ điện hoặc sử dụng CNC để "tạo ra" phôi (nghĩ là vàng búa ).

Mặt khác, nếu nguồn mã được tạo ra khó duy trì hoặc tạo mã không đủ hiệu quả, người dùng sẽ rơi vào bẫy sử dụng các công cụ sai (đôi khi vì cùng một cây búa vàng ).


0

Tạo mã nguồn hoàn toàn có nghĩa là mã được tạo là dữ liệu. Nhưng đó là dữ liệu hạng nhất, dữ liệu mà phần còn lại của chương trình có thể thao tác.

Hai loại dữ liệu phổ biến nhất mà tôi biết được tích hợp vào mã nguồn là thông tin đồ họa về các cửa sổ (số lượng và vị trí của các điều khiển khác nhau) và ORM. Trong cả hai trường hợp, việc tích hợp thông qua việc tạo mã giúp cho việc thao tác dữ liệu dễ dàng hơn, vì bạn không phải trải qua các bước "đặc biệt" để sử dụng chúng.

Khi làm việc với máy Mac gốc (1984), các định nghĩa hộp thoại và cửa sổ đã được tạo bằng trình chỉnh sửa resouce giữ dữ liệu ở định dạng nhị phân. Sử dụng các tài nguyên này trong ứng dụng của bạn khó hơn so với "định dạng nhị phân" là Pascal.

Vì vậy, không, việc tạo mã nguồn không phải là một mô hình chống, nó cho phép làm cho phần dữ liệu của ứng dụng, giúp sử dụng dễ dàng hơn.


0

Tạo mã là một mô hình chống khi chi phí cao hơn nó hoàn thành. Tình huống này xảy ra khi thế hệ diễn ra từ A đến B trong đó A gần giống ngôn ngữ với B, nhưng với một số phần mở rộng nhỏ có thể được thực hiện chỉ bằng cách mã hóa trong A với ít nỗ lực hơn tất cả các công cụ tùy chỉnh và xây dựng dàn dựng cho A đến B .

Việc đánh đổi là nghiêm cấm hơn đối với việc tạo mã bằng các ngôn ngữ không có các cơ sở lập trình meta (macro cấu trúc) vì các phức tạp và không phù hợp để đạt được siêu lập trình thông qua việc xử lý văn bản bên ngoài.

Việc đánh đổi kém cũng có thể liên quan đến số lượng sử dụng. Ngôn ngữ A có thể khác biệt đáng kể so với B, nhưng toàn bộ dự án với trình tạo mã tùy chỉnh của nó chỉ sử dụng A ở một hoặc hai vị trí nhỏ, do đó tổng số lượng phức tạp (các bit nhỏ của A, cộng với trình tạo mã A -> B, cộng với dàn dựng xung quanh) vượt quá mức độ phức tạp của một giải pháp vừa được thực hiện trong B.

Về cơ bản, nếu chúng ta cam kết tạo mã, có lẽ chúng ta nên "đi lớn hoặc về nhà": làm cho nó có ngữ nghĩa quan trọng và sử dụng nó nhiều, hoặc không làm phiền.


Tại sao bạn lại xóa đoạn "Khi Bjarne Stroustrup lần đầu tiên triển khai C ++ ..."? Tôi nghĩ nó thật thú vị.
Utku

@Utku Các câu trả lời khác bao gồm điều này từ quan điểm biên dịch toàn bộ ngôn ngữ tinh vi, trong đó phần còn lại của một dự án hoàn toàn được viết. Tôi không nghĩ nó đại diện cho phần lớn những gì được gọi là "tạo mã".
Kaz

0

Tôi đã không thấy điều này được nêu rõ ràng (tôi đã thấy nó được chạm vào bởi một hoặc hai câu trả lời, nhưng nó dường như không rõ ràng)

Tạo mã (như bạn đã nói, như thể đó là dữ liệu) không phải là vấn đề - đó là cách để sử dụng lại trình biên dịch cho mục đích phụ.

Chỉnh sửa mã được tạo là một trong những kiểu chống khủng khiếp, xấu xa, khủng khiếp nhất mà bạn từng gặp. Đừng làm điều này.

Tốt nhất, chỉnh sửa mã được tạo sẽ kéo một loạt mã kém vào dự án của bạn (bộ mã ENTIRE bây giờ thực sự là MÃ NGUỒN - không còn dữ liệu nữa). Tệ nhất là mã được kéo vào chương trình của bạn rất dư thừa, rác được đặt tên kém mà gần như không thể nhận ra.

Tôi cho rằng một danh mục thứ ba là mã bạn sử dụng một lần (trình tạo gui?) Sau đó chỉnh sửa để giúp bạn bắt đầu / tìm hiểu. Đây chỉ là một chút - có thể là một cách tốt để bắt đầu nhưng trình tạo GUI của bạn sẽ được nhắm mục tiêu sử dụng mã "Có thể tạo" sẽ không phải là một khởi đầu tuyệt vời cho bạn với tư cách là một lập trình viên - Ngoài ra, bạn có thể là muốn sử dụng lại nó cho GUI thứ hai, nghĩa là kéo mã SOURCE dư thừa vào hệ thống của bạn.

Nếu công cụ của bạn đủ thông minh để không cho phép bất kỳ chỉnh sửa nào của mã được tạo, hãy thực hiện nó. Nếu không, tôi sẽ gọi nó là một trong những kiểu chống tệ hại nhất ngoài kia.


0

Mã và dữ liệu cả hai là: Thông tin.

Dữ liệu là thông tin chính xác ở dạng bạn cần (và giá trị). Mã cũng là thông tin, nhưng ở dạng gián tiếp hoặc trung gian. Về bản chất, mã cũng là một dạng dữ liệu.

Cụ thể hơn, mã là thông tin cho các máy để giảm tải cho con người tự xử lý thông tin.

Giảm tải cho con người từ xử lý thông tin là động lực quan trọng nhất. Các bước trung gian được chấp nhận miễn là chúng làm cho cuộc sống dễ dàng. Đó là lý do tại sao các công cụ ánh xạ thông tin trung gian tồn tại. Giống như trình tạo mã, trình biên dịch, bộ chuyển đổi, v.v.

Tại sao tạo mã nguồn? Tại sao không làm cho nó thành một chức năng có thể chấp nhận các tham số và hành động trên chúng?

Giả sử ai đó cung cấp cho bạn một chức năng ánh xạ như vậy, việc triển khai của bạn không rõ ràng đối với bạn. Miễn là chức năng hoạt động như đã hứa, bạn có quan tâm nếu bên trong nó tạo mã nguồn hay không?


0

Nếu một cái gì đó có thể được tạo ra, thì thứ đó là dữ liệu, không phải mã.

Khi bạn quy định sau đó về mã đó là dữ liệu, mệnh đề của bạn giảm xuống thành "Nếu một cái gì đó có thể được tạo ra, thì thứ đó không phải là mã." Sau đó, bạn có thể nói rằng mã lắp ráp được tạo bởi trình biên dịch C không phải là mã? Điều gì xảy ra nếu nó trùng khớp chính xác với mã lắp ráp mà tôi viết bằng tay? Bạn được chào đón đến đó nếu bạn muốn, nhưng tôi sẽ không đến với bạn.

Thay vào đó, hãy bắt đầu với một định nghĩa về "mã". Không cần quá kỹ thuật, một định nghĩa khá hay cho mục đích của cuộc thảo luận này sẽ là "hướng dẫn hành động bằng máy để thực hiện tính toán."

Cho rằng, toàn bộ ý tưởng về việc tạo mã nguồn này có phải là một sự hiểu lầm không?

Vâng, đề xuất bắt đầu của bạn là mã không thể được tạo ra, nhưng tôi từ chối đề xuất đó. Nếu bạn chấp nhận định nghĩa của tôi về "mã" thì sẽ không có vấn đề khái niệm nào với việc tạo mã nói chung.

Đó là, nếu có một trình tạo mã cho một cái gì đó, vậy thì tại sao không biến cái đó thành một hàm thích hợp có thể nhận các tham số cần thiết và thực hiện đúng hành động mà mã "sẽ tạo" sẽ làm?

Đó là một câu hỏi hoàn toàn khác, về lý do sử dụng việc tạo mã, hơn là về bản chất của nó. Bạn đang đề xuất phương án thay vì viết hoặc sử dụng trình tạo mã, người ta viết một hàm tính kết quả trực tiếp. Nhưng trong ngôn ngữ nào? Đã qua rồi cái thời mà bất cứ ai viết trực tiếp bằng mã máy và nếu bạn viết mã bằng bất kỳ ngôn ngữ nào khác thì bạn phụ thuộc vào trình tạo mã dưới dạng trình biên dịch và / hoặc trình biên dịch để tạo chương trình thực sự chạy.

Tại sao, sau đó, bạn thích viết bằng Java hoặc C hoặc Lisp hay bất cứ điều gì? Ngay cả lắp ráp? Tôi khẳng định rằng ít nhất một phần vì các ngôn ngữ đó cung cấp sự trừu tượng cho dữ liệu và thao tác giúp dễ dàng thể hiện các chi tiết của tính toán mà bạn muốn thực hiện.

Điều tương tự cũng đúng với hầu hết các trình tạo mã cấp cao hơn. Các trường hợp nguyên mẫu có thể là máy quét và trình phân tích cú pháp như lexyacc. Có, bạn có thể viết một trình quét và trình phân tích cú pháp trực tiếp bằng C hoặc bằng một số ngôn ngữ lập trình khác mà bạn chọn (ngay cả mã máy thô), và đôi khi một trình duyệt. Nhưng đối với một vấn đề phức tạp đáng kể, sử dụng ngôn ngữ có mục đích đặc biệt ở cấp độ cao hơn như lex's hoặc yacc để làm cho mã viết tay dễ viết, đọc và bảo trì hơn. Thường nhỏ hơn nhiều, quá.

Bạn cũng nên xem xét chính xác ý của bạn về "trình tạo mã". Tôi sẽ coi tiền xử lý C và khởi tạo các mẫu C ++ là các bài tập trong việc tạo mã; Bạn có phản đối những điều này? Nếu không, thì tôi nghĩ bạn sẽ cần phải thực hiện một số môn thể dục tinh thần để hợp lý hóa việc chấp nhận những thứ đó nhưng từ chối các hương vị khác của việc tạo mã.

Nếu nó đang được thực hiện vì lý do hiệu suất, thì điều đó nghe có vẻ như là một thiếu sót của trình biên dịch.

Tại sao? Về cơ bản, bạn đang đặt ra rằng một chương trình phổ quát mà người dùng cung cấp dữ liệu, một số được phân loại là "hướng dẫn" và một số khác là "đầu vào" và tiến hành tính toán và phát ra nhiều dữ liệu mà chúng ta gọi là "đầu ra". (Từ một quan điểm nhất định, người ta có thể gọi một chương trình phổ quát như vậy là "hệ điều hành".) Nhưng tại sao bạn cho rằng một trình biên dịch nên có hiệu quả trong việc tối ưu hóa một chương trình đa năng như vậy vì nó tối ưu hóa một chương trình chuyên dụng hơn chương trình? Hai chương trình có đặc điểm khác nhau và khả năng khác nhau.

Nếu nó được thực hiện để kết nối hai ngôn ngữ, thì điều đó nghe có vẻ như thiếu thư viện giao diện.

Bạn nói rằng như thể có một thư viện giao diện phổ quát đến một mức độ nào đó nhất thiết phải là một điều tốt. Có lẽ nó sẽ như vậy, nhưng trong nhiều trường hợp, một thư viện như vậy sẽ rất lớn, khó viết và bảo trì, và thậm chí có thể chậm. Và nếu một con thú như vậy trong thực tế không tồn tại để phục vụ vấn đề cụ thể trong tay, thì bạn là ai để khẳng định rằng chúng được tạo ra, khi một phương pháp tạo mã có thể giải quyết vấn đề nhanh chóng và dễ dàng hơn nhiều?

Am i thiếu cái gì ở đây?

Một số điều, tôi nghĩ.

Tôi biết rằng mã là dữ liệu là tốt. Điều tôi không hiểu là tại sao lại tạo mã nguồn? Tại sao không làm cho nó thành một chức năng có thể chấp nhận các tham số và hành động trên chúng?

Trình tạo mã biến đổi mã được viết bằng một ngôn ngữ thành mã bằng ngôn ngữ khác, thường là cấp thấp hơn. Sau đó, bạn đang hỏi tại sao mọi người muốn viết chương trình bằng nhiều ngôn ngữ và đặc biệt là tại sao họ có thể muốn kết hợp các ngôn ngữ ở các cấp độ chủ quan khác nhau.

Nhưng tôi đã chạm vào đó rồi. Người ta chọn một ngôn ngữ cho một nhiệm vụ cụ thể một phần dựa trên sự rõ ràng và tính biểu cảm của nó cho nhiệm vụ đó. Inasmuch vì mã nhỏ hơn có trung bình ít lỗi hơn và dễ bảo trì hơn, cũng có sự thiên vị đối với các ngôn ngữ cấp cao hơn, ít nhất là cho công việc quy mô lớn. Nhưng một chương trình phức tạp bao gồm nhiều nhiệm vụ và thường một số trong số chúng có thể được giải quyết hiệu quả hơn bằng một ngôn ngữ, trong khi những chương trình khác được giải quyết chính xác hơn hoặc chính xác hơn bằng ngôn ngữ khác. Sử dụng công cụ phù hợp cho công việc đôi khi có nghĩa là sử dụng việc tạo mã.


0

Trả lời câu hỏi trong bối cảnh bình luận của bạn:

Nhiệm vụ của người biên dịch là lấy một mã được viết ở dạng có thể đọc được và chuyển đổi nó thành dạng có thể đọc được bằng máy. Do đó, nếu trình biên dịch không thể tạo mã hiệu quả, thì trình biên dịch không hoạt động đúng. Là sai đó?

Một trình biên dịch sẽ không bao giờ được tối ưu hóa cho nhiệm vụ của bạn. Lý do rất đơn giản: nó được tối ưu hóa để thực hiện nhiều nhiệm vụ. Đây là một công cụ có mục đích chung được nhiều người sử dụng cho nhiều nhiệm vụ khác nhau. Khi bạn biết nhiệm vụ của mình là gì, bạn có thể tiếp cận mã theo cách dành riêng cho tên miền, tạo ra sự đánh đổi mà trình biên dịch không thể thực hiện được.

Ví dụ, tôi đã làm việc trên phần mềm nơi một nhà phân tích có thể cần phải viết một số mã. Họ có thể viết thuật toán của họ bằng C ++ và thêm vào tất cả các kiểm tra giới hạn và các thủ thuật ghi nhớ mà họ phụ thuộc, nhưng điều đó đòi hỏi phải biết nhiều về hoạt động bên trong của mã. Họ thà viết một cái gì đó đơn giản và để tôi ném một thuật toán vào nó để tạo mã C ++ cuối cùng. Sau đó, tôi có thể thực hiện các thủ thuật kỳ lạ để tối đa hóa hiệu suất như phân tích tĩnh mà tôi sẽ không bao giờ mong đợi các nhà phân tích của mình chịu đựng. Tạo mã cho phép họ viết theo cách cụ thể theo miền cho phép họ đưa sản phẩm ra khỏi cửa dễ dàng hơn bất kỳ công cụ mục đích chung nào có thể.

Tôi cũng đã làm điều ngược lại chính xác. Tôi có một công việc khác mà tôi đã thực hiện với nhiệm vụ "không tạo mã". Chúng tôi vẫn muốn làm cho cuộc sống trở nên dễ dàng với những người sử dụng phần mềm, vì vậy chúng tôi đã sử dụng số lượng lớn siêu dữ liệu mẫu để làm cho trình biên dịch tạo mã nhanh chóng. Vì vậy, tôi chỉ cần ngôn ngữ C ++ có mục đích chung để thực hiện công việc của mình.

Tuy nhiên, có một nhược điểm. Đó là rất khó để đảm bảo rằng các lỗi là có thể đọc được. Nếu bạn đã từng sử dụng mã siêu lập trình mẫu trước đây, bạn sẽ biết rằng một lỗi vô tội duy nhất có thể tạo ra một lỗi lấy 100 dòng tên lớp không thể hiểu và các đối số mẫu để hiểu những gì đã sai. Hiệu ứng này rõ rệt đến mức quy trình gỡ lỗi được đề xuất cho các lỗi cú pháp là "Cuộn qua nhật ký lỗi cho đến khi bạn thấy lần đầu tiên một trong các tệp của mình có lỗi. Đi đến dòng đó và chỉ nheo mắt cho đến khi bạn nhận ra mình là gì đã làm sai. "

Nếu chúng ta sử dụng việc tạo mã, chúng ta có thể có khả năng xử lý lỗi mạnh hơn nhiều, với các lỗi có thể đọc được của con người. C'est la vie.


0

Có một vài cách khác nhau để sử dụng tạo mã. Họ có thể được chia thành ba nhóm chính:

  • Tạo mã bằng ngôn ngữ khác làm đầu ra từ một bước trong quy trình biên dịch. Đối với trình biên dịch điển hình, đây sẽ là ngôn ngữ cấp thấp hơn, nhưng nó có thể là ngôn ngữ cấp cao khác như trong trường hợp ngôn ngữ biên dịch thành JavaScript.
  • Tạo hoặc chuyển đổi mã trong ngôn ngữ mã nguồn là một bước trong quy trình biên dịch. Đây là những gì macro làm.
  • Tạo mã với một công cụ tách biệt với quy trình biên dịch thông thường. Đầu ra từ đây là mã sống như các tệp cùng với mã nguồn thông thường và được biên dịch cùng với nó. Ví dụ, các lớp thực thể cho ORM có thể được tạo tự động từ lược đồ cơ sở dữ liệu hoặc các đối tượng truyền dữ liệu và giao diện dịch vụ có thể được tạo từ một đặc tả giao diện như tệp WSDL cho SOAP.

Tôi đoán bạn đang nói về loại mã được tạo thứ ba, vì đây là hình thức gây tranh cãi nhất. Trong hai biểu mẫu đầu tiên, mã được tạo là một bước trung gian được phân tách rất rõ ràng với mã nguồn. Nhưng ở dạng thứ ba, không có sự phân tách chính thức giữa mã nguồn và mã được tạo, ngoại trừ mã được tạo có thể có một nhận xét có nội dung "không chỉnh sửa mã này". Nó vẫn mở ra nguy cơ các nhà phát triển chỉnh sửa mã được tạo sẽ rất xấu. Từ quan điểm của trình biên dịch, mã được tạo là mã nguồn.

Tuy nhiên, các dạng mã được tạo như vậy có thể thực sự hữu ích trong một ngôn ngữ được nhập tĩnh. Ví dụ, khi tích hợp với các thực thể ORM, thực sự hữu ích khi có các hàm bao được gõ mạnh cho các bảng cơ sở dữ liệu. Chắc chắn bạn có thể xử lý tích hợp một cách linh hoạt trong thời gian chạy, nhưng bạn sẽ mất loại an toàn và hỗ trợ công cụ (hoàn thành mã). Một lợi ích chính của ngôn ngữ kiểu tĩnh là sự hỗ trợ của hệ thống loại tại kiểu viết thay vì chỉ trong thời gian chạy. (Ngược lại, kiểu tạo mã này không phổ biến lắm trong các ngôn ngữ được gõ động, vì trong ngôn ngữ như vậy, nó không mang lại lợi ích gì so với chuyển đổi thời gian chạy.)

Đó là, nếu có một trình tạo mã cho một cái gì đó, vậy thì tại sao không biến cái đó thành một hàm thích hợp có thể nhận các tham số cần thiết và thực hiện đúng hành động mà mã "sẽ tạo" sẽ làm?

Bởi vì an toàn kiểu và hoàn thành mã là các tính năng bạn muốn tại thời gian biên dịch (và trong khi viết mã trong IDE), nhưng các hàm thông thường chỉ được thực thi khi chạy.

Mặc dù có thể có một nền tảng trung gian: F # hỗ trợ khái niệm các nhà cung cấp loại về cơ bản là các giao diện được gõ mạnh được tạo theo chương trình tại thời điểm biên dịch. Khái niệm này có thể có thể thay thế nhiều cách sử dụng tạo mã và cung cấp một mối quan tâm rõ ràng hơn.


0

Các bộ hướng dẫn bộ xử lý là bắt buộc về cơ bản , nhưng ngôn ngữ lập trình có thể là khai báo . Chạy một chương trình được viết bằng ngôn ngữ khai báo chắc chắn đòi hỏi một số loại tạo mã. Như đã đề cập trong câu trả lời này và các câu hỏi khác, một lý do chính để tạo mã nguồn bằng ngôn ngữ có thể đọc được của con người là để tận dụng các tối ưu hóa tinh vi được thực hiện bởi các trình biên dịch.


-3

Nếu một cái gì đó có thể được tạo ra, thì thứ đó là dữ liệu, không phải mã.

Bạn đã nhận nó sai cách vòng. Nó nên đọc

Nếu một cái gì đó có thể được đưa vào một trình tạo để có thể hiểu được , thì thứ đó là mã chứ không phải dữ liệu.

Đây là định dạng nguồn cho giai đoạn biên dịch đó và định dạng chìm vẫn là mã.


1
Định nghĩa sai về mã nguồn . Mã nguồn chủ yếu dành cho con người làm việc với nó (và thực tế đó chỉ xác định nó, xem thêm phần mềm miễn phí của FSF là gì). Mã trình biên dịch được tạo ra gcc -fverbose-asm -O -Skhông phải là mã nguồn (và không chỉ hoặc chủ yếu là dữ liệu), ngay cả khi đó là một dạng văn bản luôn được cung cấp cho GNU asvà đôi khi được đọc bởi con người.
Basile Starynkevitch

Ngoài ra, nhiều ngôn ngữ triển khai biên dịch thành mã C , nhưng mã C được tạo ra đó không phải là mã nguồn chính hãng (ví dụ: con người không thể làm việc dễ dàng).
Basile Starynkevitch

Cuối cùng, phần cứng của bạn (ví dụ chip AMD hoặc Intel hoặc bo mạch chủ máy tính của bạn) đang diễn giải mã máy (rõ ràng không phải là mã nguồn). BTW IBM1620 có mã máy bàn phím (BCD), nhưng thực tế đó không biến nó thành "mã nguồn". Tất cả các mã không phải là nguồn.
Basile Starynkevitch

@BasileStarynkevitch Ah, bạn đã đưa tôi đến đó. Tôi không nên cố gắng nén câu nói dí dỏm của mình quá nhiều, hoặc chúng thay đổi ý nghĩa của chúng. Đúng, mã nguồn phải là mã gốc nhất được đưa vào giai đoạn biên dịch đầu tiên.
Bergi

Không có mã nguồn là mã cho con người. Thật khó khăn và chủ quan khi định nghĩa như âm nhạc (so với âm thanh). Đây không phải là vấn đề cố gắng tìm phần mềm tiêu thụ nó.
Basile Starynkevitch
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.