Có phải ký hiệu tiếng Anh là một cách giải quyết cho các ngôn ngữ với kiểu gõ tĩnh không đủ biểu cảm? [đóng cửa]


28

Trong bài viết của Eric Lippert Có gì với ký hiệu Hungary? , ông nói rằng mục đích của Ký hiệu Hungary (loại tốt) là để

mở rộng khái niệm "loại" để bao gồm thông tin ngữ nghĩa bên cạnh thông tin đại diện lưu trữ.

Một ví dụ đơn giản sẽ là tiền tố của một biến đại diện cho tọa độ X với "x" và một biến đại diện cho tọa độ Y với "y", bất kể các biến đó là số nguyên hay dấu phẩy hay bất cứ điều gì, khi bạn vô tình viết xFoo + yBar, mã rõ ràng trông sai.

Nhưng tôi cũng đã đọc về hệ thống loại của Haskell và dường như trong Haskell, người ta có thể thực hiện điều tương tự (nghĩa là "mở rộng khái niệm loại để bao gồm thông tin ngữ nghĩa") bằng cách sử dụng các loại thực tế mà trình biên dịch sẽ kiểm tra cho bạn. Vì vậy, trong ví dụ trên, xFoo + yBartrong Haskell thực sự sẽ không biên dịch được nếu bạn thiết kế chương trình của mình một cách chính xác, vì chúng sẽ được khai báo là các loại không tương thích. Nói cách khác, có vẻ như hệ thống loại của Haskell hỗ trợ hiệu quả việc kiểm tra thời gian biên dịch tương đương với Ký hiệu Hungary

Vì vậy, ký hiệu Hungary chỉ là một hỗ trợ ban nhạc cho các ngôn ngữ lập trình mà hệ thống loại không thể mã hóa thông tin ngữ nghĩa? Hay ký hiệu Hungary cung cấp một cái gì đó vượt ra ngoài những gì một hệ thống loại tĩnh như Haskell có thể cung cấp?

(Tất nhiên, tôi đang sử dụng Haskell làm ví dụ. Tôi chắc chắn có những ngôn ngữ khác có hệ thống loại biểu cảm tương tự (giàu? Mạnh?), Mặc dù tôi không bắt gặp bất kỳ ngôn ngữ nào.)


Để rõ ràng, tôi không nói về việc chú thích tên biến với kiểu dữ liệu , mà là thông tin về ý nghĩa của biến trong ngữ cảnh của chương trình. Ví dụ: một biến có thể là một số nguyên hoặc float hoặc double hoặc long hoặc bất cứ điều gì, nhưng có thể ý nghĩa của biến đó là tọa độ x tương đối được đo bằng inch. Đây là loại thông tin tôi đang nói về mã hóa thông qua Ký hiệu Hungary (và thông qua các loại Haskell).


Pascal - mặc dù nếu bạn thử và thêm loại XCood và YCoord mà bạn đã xác định trong Pascal, bạn sẽ nhận được cảnh báo trình biên dịch IIRC
maptle

1
blog.moertel.com/articles/2006/10/18/ Từ là một bài viết về cách làm một cái gì đó rất giống với "ứng dụng" trong hệ thống loại trong Haskell.
Logan Capaldo

1
F # cũng có tính năng phong cách này.
Rangoric

Đó là một liên kết bài viết thực sự hay (moertel.com one) hiển thị chính xác loại điều tôi đang nghĩ đến: sử dụng hệ thống loại để biến các lỗ hổng bảo mật nội suy chuỗi và như vậy thành các lỗi thời gian biên dịch. Cảm ơn các liên kết.
Ryan C. Thompson

Tôi nghĩ rằng rất nhiều OO đã bắt kịp ký hiệu Hungary về ngữ nghĩa, bởi vì hôm nay bạn có thể sẽ viết: Foo.Pocation.X + Bar.Pocation.Y.
Pieter B

Câu trả lời:


27

Tôi sẽ nói có".

Như bạn nói, mục đích của Ký hiệu Hungary là mã hóa thông tin theo tên không thể được mã hóa theo loại. Tuy nhiên, về cơ bản có hai trường hợp:

  1. Thông tin đó rất quan trọng.
  2. Thông tin đó không quan trọng.

Trước tiên, hãy bắt đầu với trường hợp 2: nếu thông tin đó không quan trọng, thì Ký hiệu Hungary chỉ đơn giản là tiếng ồn không cần thiết.

Trường hợp thú vị hơn là số 1, nhưng tôi sẽ lập luận rằng nếu thông tin là quan trọng, thì nó cần được kiểm tra, tức là nó phải là một phần của loại chứ không phải tên .

Điều này đưa chúng ta trở lại với trích dẫn của Eric Lippert:

mở rộng khái niệm "loại" để bao gồm thông tin ngữ nghĩa bên cạnh thông tin đại diện lưu trữ.

Trên thực tế, đó không phải là "mở rộng khái niệm về loại", đó khái niệm về loại! Các toàn bộ mục đích của các loại (như một công cụ thiết kế) là để mã hóa thông tin ngữ nghĩa! Đại diện lưu trữ là một chi tiết triển khai thường không thuộc loại nào cả . (Và cụ thể trong ngôn ngữ OO không thể thuộc loại, vì tính độc lập đại diện là một trong những điều kiện tiên quyết chính cho OO.)


C, trong đó ký hiệu Hungary được AFAIK sử dụng nhiều nhất, mặc dù không phải là ngôn ngữ OO.
Péter Török

4
@ PéterTörök: OO là một mẫu thiết kế, không phải là tính năng của ngôn ngữ, mặc dù các ngôn ngữ hiện đại được thiết kế để làm cho nó dễ dàng trong khi C thì không.
Jan Hudec

3
@ PéterTörök: Tôi đã viết khá nhiều mã hướng đối tượng ở đồng bằng C. Tôi biết tôi đang nói về cái gì.
Jan Hudec

1
Mặc dù có thể đúng là thông tin quan trọng nên được nhúng trong một loại biến thay vì tên của nó, có nhiều điều quan trọng cần nói, nhưng hệ thống loại nào không thể diễn đạt. Ví dụ, nếu S1là tài liệu tham khảo duy nhất ở bất kỳ nơi nào trong vũ trụ char[], người nắm giữ có thể và sẽ thay đổi nó bất cứ khi nào muốn, nhưng không bao giờ được đưa ra mã bên ngoài và S2là một tham chiếu đến char[]không ai có thể thay đổi, nhưng có thể được chia sẻ với các đối tượng hứa sẽ không thay đổi nó, nên S1S2được coi là về mặt ngữ nghĩa như là "cùng một thứ"?
supercat

1
@supercat - Bạn đang mô tả các loại duy nhất.
Jack

9

Toàn bộ mục đích của các loại (như một công cụ thiết kế) là để mã hóa thông tin ngữ nghĩa!

Tôi thích câu trả lời này và muốn theo dõi câu trả lời này ...

Tôi không biết gì về Haskell, nhưng bạn có thể thực hiện một cái gì đó giống như ví dụ về xFoo + yBarbất kỳ ngôn ngữ nào hỗ trợ một số dạng an toàn kiểu như C, C ++ hoặc Java. Trong C ++, bạn có thể định nghĩa các lớp XDir và YDir với các toán tử '+' bị quá tải chỉ lấy các đối tượng thuộc loại riêng của chúng. Trong C hoặc Java, bạn sẽ cần thực hiện phép cộng của mình bằng cách sử dụng hàm / phương thức add () thay vì toán tử '+'.

Tôi luôn thấy Ký hiệu Hungary được sử dụng cho thông tin loại, không phải ngữ nghĩa (ngoại trừ trong trường hợp ngữ nghĩa có thể được biểu thị theo loại). Một cách thuận tiện để ghi nhớ loại biến trở lại trong những ngày trước khi các biên tập viên lập trình "thông minh" hiển thị loại cho bạn theo cách này hay cách khác trong trình chỉnh sửa.


Định hướng đối tượng là không cần thiết và không đủ cho một ngôn ngữ để cho phép các loại xFoo + yBardo người dùng xác định, cũng như khía cạnh OO của C ++ cần thiết để ví dụ đó hoạt động.
Luc Danton

Bạn nói đúng, không phải OO, đó là loại an toàn. Tôi chỉnh sửa câu trả lời của tôi.
BHS

Hừm. Đó là một điểm tốt mà bạn có thể tạo ra xFoo + yBarmột lỗi biên dịch (hoặc ít nhất là lỗi thời gian chạy) bằng bất kỳ ngôn ngữ nào. Tuy nhiên, toán học với các lớp XDir và YDir trong, giả sử, Java hoặc C ++ sẽ chậm hơn toán học với số nguyên? Tôi hiểu rằng trong Haskell, các loại được kiểm tra tại thời gian biên dịch, và sau đó trong thời gian chạy, nó sẽ chỉ là toán học thô mà không kiểm tra kiểu, và do đó không chậm hơn so với việc thêm các số thông thường.
Ryan C. Thompson

Trong C ++, việc kiểm tra kiểu cũng sẽ được thực hiện vào thời gian biên dịch và việc chuyển đổi và như vậy sẽ được tối ưu hóa trong hầu hết các trường hợp. Java cũng không làm điều đó, bởi vì nó không cho phép quá tải toán tử và như vậy - vì vậy, bạn không thể coi một XCoordinateint thông thường, chẳng hạn.
cHao

5

Tôi nhận ra rằng cụm từ "Ký hiệu Hungary" có nghĩa khác với bản gốc , nhưng tôi sẽ trả lời "không" cho câu hỏi. Đặt tên biến với kiểu ngữ nghĩa hoặc kiểu tính toán không thực hiện tương tự như kiểu gõ SML hoặc Haskell. Nó thậm chí không phải là một chiếc băng đô. Lấy C làm ví dụ, bạn có thể đặt tên cho biến gpszTitle, nhưng biến đó có thể không có phạm vi toàn cầu, thậm chí nó có thể không tạo thành một điểm cho chuỗi kết thúc null.

Tôi nghĩ rằng các ký hiệu Hungary hiện đại hơn thậm chí còn có sự phân kỳ lớn hơn từ hệ thống khấu trừ loại mạnh, bởi vì chúng trộn thông tin "ngữ nghĩa" (như "g" cho toàn cầu hoặc "f" cho cờ) với loại tính toán (con trỏ "p", " i "số nguyên, v.v.) Điều đó chỉ kết thúc như một mớ hỗn độn trong đó các tên biến chỉ giống với kiểu tính toán mơ hồ của chúng (thay đổi theo thời gian) và tất cả trông giống nhau đến mức bạn không thể sử dụng" kết hợp tiếp theo " tìm một biến trong một chức năng cụ thể - tất cả đều giống nhau.


4

Ký hiệu Hungary được phát minh cho BCPL, một ngôn ngữ hoàn toàn không có loại. Hay đúng hơn, nó có chính xác một loại dữ liệu, từ. Một từ có thể là một con trỏ hoặc nó có thể là một ký tự hoặc boolean hoặc một số nguyên đơn giản tùy thuộc vào cách bạn sử dụng nó. Rõ ràng điều này làm cho nó rất dễ mắc phải những sai lầm khủng khiếp như hội thảo một nhân vật. Vì vậy, ký hiệu Hungary đã được phát minh để lập trình viên ít nhất có thể thực hiện kiểm tra loại thủ công bằng cách xem mã.

C, hậu duệ của BCPL, có các loại khác nhau cho số nguyên, con trỏ, ký tự, v.v ... Điều này làm cho ký hiệu tiếng Hungary cơ bản trở nên thừa thãi ở một mức độ nào đó (bạn không cần phải mã hóa tên biến nếu là int hoặc con trỏ), nhưng ngữ nghĩa vượt quá mức này vẫn không thể được thể hiện dưới dạng các loại. Điều này dẫn đến sự khác biệt giữa những gì được gọi là "Hệ thống" và "Ứng dụng" tiếng Hungary. Bạn không cần phải biểu thị rằng một biến là một int, nhưng bạn có thể sử dụng các ký tự mã để cho biết liệu int là tọa độ x hay y hay chỉ mục.

Các ngôn ngữ hiện đại hơn cho phép định nghĩa các loại tùy chỉnh, có nghĩa là bạn có thể mã hóa các ràng buộc ngữ nghĩa trong các loại, thay vào đó là các tên biến. Ví dụ, một ngôn ngữ OO điển hình sẽ có các loại cụ thể cho các cặp tọa độ và khu vực, vì vậy bạn tránh thêm tọa độ x vào tọa độ y.

Ví dụ, trong bài viết nổi tiếng của Joels ca ngợi Ứng dụng Hungary, ông sử dụng ví dụ về tiền tố uscho chuỗi không an toàn và scho chuỗi an toàn (được mã hóa html), để ngăn chặn việc tiêm HTML. Nhà phát triển có thể ngăn ngừa các lỗi tiêm HTML bằng cách đơn giản kiểm tra cẩn thận mã và đảm bảo rằng các tiền tố biến đổi khớp với nhau. Ví dụ của anh ấy là trong VBScript, một ngôn ngữ đã lỗi thời ban đầu không cho phép các lớp tùy chỉnh. Trong một ngôn ngữ hiện đại, vấn đề có thể được khắc phục bằng một loại tùy chỉnh và thực sự đây là những gì Asp.net làm với HtmlStringlớp. Bằng cách này, trình biên dịch sẽ tự động tìm ra lỗi, an toàn hơn nhiều khi dựa vào nhãn cầu của con người. Vì vậy, rõ ràng một ngôn ngữ với các loại tùy chỉnh sẽ loại bỏ nhu cầu về "Ứng dụng Hungary" trong trường hợp này.


2

Có, mặc dù nhiều ngôn ngữ có hệ thống loại đủ mạnh vẫn có vấn đề - tính rõ ràng của các loại mới dựa trên / tương tự như các loại hiện có.

tức là trong nhiều languga nơi chúng ta có thể sử dụng hệ thống loại nhiều hơn chúng ta không sử dụng vì chi phí tạo ra một loại mới về cơ bản giống như một loại hiện có ngoài tên và một vài hàm chuyển đổi là quá lớn.

Về cơ bản chúng ta cần một số loại typedefs được gõ mạnh để tiêu diệt triệt để ký hiệu tiếng Đức trong các ngôn ngữ này (U # kiểu UoM cũng có thể làm điều đó)


2

Hãy nhớ rằng, đã có lúc các IDE không có gợi ý bật lên cho bạn biết loại biến của chúng là gì. Đã có lúc IDE không hiểu mã họ đang chỉnh sửa nên bạn không thể chuyển từ sử dụng sang khai báo một cách dễ dàng. Cũng có một thời gian, khi bạn không thể cấu trúc lại một tên biến mà không tự mình đi qua toàn bộ cơ sở mã, thực hiện thay đổi bằng tay và hy vọng bạn không bỏ lỡ một tên nào. Bạn không thể sử dụng tìm kiếm & thay thế bởi vì tìm kiếm Khách hàng cũng giúp bạn có được Tên khách hàng ...

Quay trở lại những ngày đen tối đó, thật hữu ích khi biết loại biến nào được sử dụng. Nếu được bảo trì đúng cách (LỚN nếu vì thiếu công cụ tái cấu trúc) ký hiệu Hungary đã cho bạn điều đó.

Chi phí những ngày này của những cái tên khủng khiếp mà nó tạo ra là quá cao nhưng đó là một điều tương đối gần đây. Rất nhiều mã vẫn tồn tại trước các phát triển IDE mà tôi đã mô tả.


1
Nếu tôi không nhầm, đây là một câu trả lời khác giải quyết một loại ký hiệu Hungary khác với loại mà OP đang hỏi.
MatrixFrog

2
Câu trả lời này mô tả những gì được gọi là "Hệ thống Hungary", trong đó tiền tố biểu thị "loại" cấp độ ngôn ngữ. Câu hỏi hỏi về "Ứng dụng Hungary", trong đó từ "loại" không bị hiểu nhầm và có nghĩa là loại ngữ nghĩa . Các hệ thống Hungary gần như bị lên án phổ biến trong những ngày này (và đúng như vậy; đó là một sự khốn của mục đích thực sự của tiếng Hungary). Ứng dụng Hungary, tuy nhiên, có thể là một điều tốt.
cHao

Các trình soạn thảo có khả năng tìm kiếm sCustomer mà không cần chọn sCustomerName (vi và emacs là 2 ví dụ) đã tồn tại từ những năm 70.
Larry Coleman

@Larry, có thể, nhưng bạn không thể khiến chúng chạy trên các hệ thống mà tôi đã lập trình trong thập niên 80
hủy bỏ

@cHAo, Không, không - Quan điểm của tôi là cố gắng giải thích lý do tại sao mọi người thường đưa thông tin bổ sung vào tên biến. Tôi tránh né đề cập đến bất kỳ phiên bản ký hiệu Hungary nào. Có thể ví dụ tôi đã đưa ra trong phần "tại sao tìm kiếm & thay thế không hoạt động trên mã nguồn" trông giống như "Hệ thống Hungary" nhưng nó không có nghĩa. Tôi đã xóa "s" hàng đầu để tránh nhầm lẫn.
đánh dấu

0

Chính xác!

Bên ngoài các ngôn ngữ hoàn toàn chưa được chỉnh sửa như Trình biên dịch, ký hiệu Hungary là không cần thiết và gây phiền nhiễu. Chắc chắn là như vậy khi bạn xem xét rằng hầu hết các IDE kiểm tra loại an toàn như bạn, er, gõ.

Thêm "i" "d" và "?" các tiền tố chỉ làm cho mã ít đọc hơn và có thể thực sự gây hiểu lầm - vì khi một "người chăn bò" thay đổi loại iaSumsItems từ Integer thành Long nhưng không bận tâm đến việc tái cấu trúc tên trường.


9
Phản hồi của bạn cho thấy rằng bạn không hiểu sự khác biệt giữa tiếng Hungary "Ứng dụng" thông minh ban đầu và sự khốn nạn ngu ngốc gọi là "Hệ thống" tiếng Hungary. Đọc joelonsoftware.com/articles/Wrong.html
Ryan Culpepper
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.