Tại sao tôi không nên sử dụng ký hiệu tiếng Hungary Hungary?


122

Tôi biết những gì Hungary đề cập đến - cung cấp thông tin về một biến, tham số hoặc nhập làm tiền tố cho tên của nó. Mọi người dường như đang điên cuồng chống lại nó, mặc dù trong một số trường hợp, nó có vẻ là một ý tưởng tốt. Nếu tôi cảm thấy rằng thông tin hữu ích đang được truyền đi, tại sao tôi không nên đặt nó ngay tại nơi có sẵn?

Xem thêm: Mọi người có sử dụng các quy ước đặt tên Hungary trong thế giới thực không?


Câu trả lời:


174

Hầu hết mọi người sử dụng ký hiệu Hungary một cách sai lầm và đang nhận được kết quả sai.

Đọc bài viết xuất sắc này của Joel Spolsky: Làm cho mã sai nhìn sai .

Nói tóm lại, Ký hiệu Hungary nơi bạn đặt tiền tố tên biến của mình bằng type(chuỗi) (Hệ thống tiếng Hungary) là xấu vì nó vô dụng.

Ký hiệu tiếng Hungary theo ý định của tác giả của nó, nơi bạn đặt tiền tố tên biến với kind(sử dụng ví dụ của Joel: chuỗi an toàn hoặc chuỗi không an toàn), vì vậy được gọi là Ứng dụng Hungary có cách sử dụng và vẫn còn giá trị.


5
Liên kết tốt, một bản tóm tắt tốt về những gì đằng sau liên kết và không có sự cuồng tín. Thông minh.
quét bụi

12
Lưu ý rằng ví dụ Joels là trong VBScript, một ngôn ngữ từ lâu không có các lớp do người dùng định nghĩa. Trong ngôn ngữ OO, bạn chỉ cần tạo kiểu HtmlEncodingString và phương thức Write chỉ chấp nhận điều đó. "Ứng dụng" chỉ có ích trong các ngôn ngữ mà không có loại do người dùng xác định.
JacquesB

4
Microsoft được biết đến với việc lạm dụng ký hiệu Hungary trong quá khứ. Chuẩn bị thông tin loại cho các định danh không chỉ vô ích mà nó thực sự có thể gây hại. Đầu tiên, khả năng đọc là ít trôi chảy. Thứ hai, trong các ngôn ngữ hỗ trợ đa hình hoặc gõ vịt, thông tin sai được thông qua.
wilmustell

9
Tôi vẫn thích sử dụng ký hiệu Hungary nếu tôi đang phát triển C thẳng với một IDE cũ hơn ... theo cách đó tôi biết không có vấn đề về kiểu truyền.
Bíp bíp

3
@Krumia: Điều này thường được ngăn chặn bằng cách đặt tên biến mô tả ở vị trí đầu tiên. Nhưng nếu bạn muốn chắc chắn, sẽ an toàn hơn nhiều khi tạo các loại riêng biệt (ví dụ: cấu trúc) cho độ dài, trọng lượng, v.v. và sử dụng quá tải toán tử để đảm bảo rằng chỉ có thể thực hiện các thao tác hợp lệ.
JacquesB

277

vUsing adjHungary nnotation vmakes nreading ncode adjdiff Khó.


101
Tương tự tốt đẹp, mặc dù hơi không công bằng. So sánh: vUsing adjHungarian nNotation vMakes nRead nCode adjDiff Khó.
Chris Noe

27
Trong câu đó, cả Sử dụng và Đọc đều là gerunds. Nhưng tôi hiểu điểm bạn đang làm ...
tinh tinh

28
@chimp: điều đó làm cho mọi thứ thậm chí rõ ràng hơn. Bây giờ bạn đã tìm thấy một lỗi trong loại bạn sẽ đổi tên tất cả các tài liệu tham khảo hoặc để chúng như chúng là, cung cấp thông tin sai? bạn thua một trong hai cách nhưng tất nhiên, đây là cách áp dụng SAU.
wilmustell

1
@Chris Noe: đối với các kiểu đọc nhất định (phân tích tiền tố và hậu tố với một cái liếc ở giữa), ví dụ của bạn chỉ làm cho mọi thứ tồi tệ hơn. Tôi thấy "vUsing" và nghe thấy "vệt" trong đầu.
Bob Cross

3
@Jon: nếu bạn có một tên biến không hoàn toàn cho đi những gì nó đại diện, thì hoàn toàn có nghĩa là trọng tâm nên đổi tên thành một cái gì đó mô tả hơn (và ký hiệu Hungary không phải là một sự cải tiến, rất, rất trường hợp tốt nhất đó là sửa chữa triệu chứng - không giải quyết được vấn đề).
hlovdal

104

Joel là sai, và đây là lý do tại sao.

Đó là thông tin "ứng dụng" mà anh ấy đang nói đến nên được mã hóa trong hệ thống loại . Bạn không nên phụ thuộc vào việc lật tên biến để đảm bảo bạn không chuyển dữ liệu không an toàn cho các chức năng yêu cầu dữ liệu an toàn. Bạn nên làm cho nó một lỗi loại, do đó không thể làm như vậy. Bất kỳ dữ liệu không an toàn nào cũng phải có một loại được đánh dấu là không an toàn, do đó đơn giản là nó không thể được chuyển đến một chức năng an toàn. Để chuyển đổi từ không an toàn sang an toàn cần phải xử lý với một số loại chức năng khử trùng.

Rất nhiều điều mà Joel nói về "các loại" không phải là các loại; trong thực tế, chúng là các loại.

Tuy nhiên, điều mà hầu hết các ngôn ngữ thiếu là một hệ thống loại đủ biểu cảm để thực thi các loại khác biệt này. Ví dụ: nếu C có một loại "typedef mạnh" (trong đó tên typedef có tất cả các hoạt động của loại cơ sở, nhưng không thể chuyển đổi thành nó) thì rất nhiều vấn đề này sẽ biến mất. Ví dụ: nếu bạn có thể nói, strong typedef std::string unsafe_string;để giới thiệu một loại mới unsafe_stringkhông thể chuyển đổi thành chuỗi std :: (và do đó có thể tham gia giải quyết quá tải, v.v.) thì chúng ta sẽ không cần các tiền tố ngớ ngẩn.

Vì vậy, tuyên bố trung tâm rằng tiếng Hungary dành cho những thứ không phải là loại sai. Nó đang được sử dụng cho thông tin loại. Thông tin loại phong phú hơn thông tin loại C truyền thống, chắc chắn; đó là loại thông tin mã hóa một số loại chi tiết ngữ nghĩa để chỉ ra mục đích của các đối tượng. Nhưng đó vẫn là loại thông tin và giải pháp thích hợp luôn là mã hóa nó vào hệ thống loại. Mã hóa nó vào hệ thống loại là cách tốt nhất để có được xác nhận hợp lệ và thực thi các quy tắc. Tên biến chỉ đơn giản là không cắt mù tạt.

Nói cách khác, mục tiêu không nên là "làm cho mã sai nhìn sai cho nhà phát triển". Nó phải là "làm cho mã sai nhìn vào trình biên dịch ".


30
Mục đích của biến phải được mã hóa trong loại biến, không được để lại một thứ gì đó quá mong manh như một sơ đồ đặt tên rõ ràng.
DrPizza

3
Tôi cũng thích biến nó thành công việc của trình biên dịch / trình thông dịch, nhưng điều đó sẽ phải chịu một chi phí rất lớn cho các ngôn ngữ động (Python, Ruby, PHP hoặc Javascript).
quá nhiều php

22
"Tuy nhiên, điều mà hầu hết các ngôn ngữ thiếu là một hệ thống loại đủ biểu cảm để thực thi các loại khác biệt này" Và vấn đề nằm ở chỗ. AppsHungarian là một phương pháp thực dụng để làm nổi bật các vấn đề khi sử dụng các ngôn ngữ này theo cách rõ ràng để lập trình viên xem mã, thay vì kiểm tra các báo cáo lỗi.
Neil Trorupt

6
@DrPizza: Tôi tin rằng bạn đã bỏ lỡ một trong những điểm rất quan trọng mà Joel đang thực hiện trong khi ủng hộ Ứng dụng Hungary: ký hiệu này chỉ là một sự đánh đổi rất thực dụng . Làm cho trình biên dịch có khả năng nhìn thấy "mã sai" là một mục tiêu tuyệt vời, nhưng nó có luôn xứng đáng với chi phí của nó không?
Yarik

4
@DrPizza: Joel is wrongWhat most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions.Vì vậy, vì hầu hết các ngôn ngữ làm thiếu đủ biểu cảm để thực thi các loại phân biệt, Joel đúng. Đúng?
sampathsris

46

Tôi nghĩ rằng nó ồ ạt làm tăng mã nguồn.

Nó cũng không giúp bạn đạt được nhiều thứ trong một ngôn ngữ được gõ mạnh. Nếu bạn thực hiện bất kỳ hình thức loại nào không phù hợp, trình biên dịch sẽ cho bạn biết về nó.


Ồ 90 rep trong 15 phút. Cuộc gọi tốt
quét bụi

2
Nếu bạn sử dụng nó cho loại, thì có, nó vô dụng. Nó hữu ích để truyền đạt thông tin khác.
Lou Franco

12
@Lou, chính xác - cá nhân, tôi lưu trữ lịch sử sửa đổi trong tên biến của mình: chuỗi FirstName_wasName_wasNameID_wasSweetCupinCakes
Shog9

@nsanders: Hãy thử sử dụng trình biên dịch để kiểm tra xem bạn có sử dụng cùng một đơn vị đo hay không khi cả hai loại biến đều là số nguyên.
Igor Levicki

1
@ Shog9: Tôi nghĩ bạn không hiểu Ký hiệu tiếng Hungary. Đó là thông tin thêm về sFirstName vs unFirstName (an toàn so với không an toàn, không được bảo vệ), theo cách này bạn biết thêm về điều đó. Tuy nhiên, tôi nghĩ rằng trong các ngôn ngữ tĩnh, tốt hơn là nên phân loại Chuỗi để tạo UnsafeString và SafeString và chỉ cho phép SafeString xuất ra. Công ước là ok, nhưng (thường xuyên hơn) thực thi biên dịch là tốt hơn.
kgadek

28

Ký hiệu Hungary chỉ có ý nghĩa trong các ngôn ngữ mà không có loại do người dùng định nghĩa . Trong một ngôn ngữ chức năng hoặc OO hiện đại, bạn sẽ mã hóa thông tin về "loại" giá trị vào kiểu dữ liệu hoặc lớp chứ không phải vào tên biến.

Một số câu trả lời tham khảo bài viết Joels . Tuy nhiên, xin lưu ý rằng ví dụ của anh ta là trong VBScript, không hỗ trợ các lớp do người dùng định nghĩa (ít nhất là trong một thời gian dài). Trong một ngôn ngữ với các loại do người dùng xác định, bạn sẽ giải quyết vấn đề tương tự bằng cách tạo loại HtmlEncodingString và sau đó để phương thức Write chỉ chấp nhận điều đó. Trong một ngôn ngữ được gõ tĩnh, trình biên dịch sẽ bắt gặp bất kỳ lỗi mã hóa nào, trong một kiểu gõ động, bạn sẽ có một ngoại lệ thời gian chạy - nhưng trong mọi trường hợp bạn được bảo vệ chống lại việc viết các chuỗi không được mã hóa. Các ký hiệu Hungary chỉ biến lập trình viên thành một trình kiểm tra loại người, với loại công việc thường được xử lý tốt hơn bởi phần mềm.

Joel phân biệt giữa "hệ thống" và "ứng dụng", trong đó "hệ thống" được mã hóa các loại tích hợp như int, float, v.v. và "ứng dụng" "mã hóa" các loại ", đó là thông tin meta cấp cao hơn về biến làm thay đổi loại máy, Trong ngôn ngữ chức năng hiện đại hoặc OO, bạn có thể tạo các loại do người dùng xác định, do đó không có sự phân biệt giữa loại và "loại" theo nghĩa này - cả hai đều có thể được biểu thị bằng hệ thống loại - và "ứng dụng" Tiếng Anh chỉ là dư thừa như "hệ thống".

Vì vậy, để trả lời câu hỏi của bạn: Các hệ thống chỉ có thể hữu ích trong một ngôn ngữ được gõ không an toàn, yếu, trong đó, ví dụ việc gán giá trị float cho một biến int sẽ làm sập hệ thống. Ký hiệu Hungary được phát minh đặc biệt vào những năm sáu mươi để sử dụng trong BCPL , một ngôn ngữ cấp thấp khá không thực hiện bất kỳ loại kiểm tra nào. Tôi không nghĩ rằng bất kỳ ngôn ngữ nào nói chung sử dụng ngày nay đều có vấn đề này, nhưng ký hiệu vẫn tồn tại như một loại lập trình sùng bái hàng hóa .

Ứng dụng có thể có ý nghĩa nếu bạn đang làm việc với một ngôn ngữ không có các loại do người dùng xác định, như VBScript cũ hoặc các phiên bản đầu tiên của VB. Có lẽ cũng là phiên bản đầu của Perl và PHP. Một lần nữa, sử dụng nó trong một languge hiện đại là sùng bái hàng hóa thuần túy.

Trong bất kỳ ngôn ngữ nào khác, tiếng Anh chỉ là xấu xí, dư thừa và mong manh. Nó lặp lại thông tin đã biết từ hệ thống loại và bạn không nên lặp lại chính mình . Sử dụng tên mô tả cho biến mô tả ý định của trường hợp cụ thể này của loại. Sử dụng hệ thống loại để mã hóa các bất biến và thông tin meta về "các loại" hoặc "các lớp" của các biến - tức là. các loại.

Điểm chung của bài viết Joels - để có mã sai nhìn sai - là một nguyên tắc rất tốt. Tuy nhiên, một sự bảo vệ tốt hơn chống lại các lỗi là - khi có thể - có mã sai được trình biên dịch tự động phát hiện.


Các ngôn ngữ với các loại do người dùng xác định không làm cho việc sử dụng các loại thay vì "các loại" luôn thực tế. Xem xét các tiền tố "c", "d", "ix" từ Joel's Apps Hungary. Bạn có sử dụng các loại số nguyên tùy chỉnh cho những thứ đó, trong mọi ngôn ngữ hiện đại không? Tôi không nghĩ vậy. Bởi vì các ngôn ngữ hiện đại vẫn chưa có các kiểu số nguyên tùy chỉnh dựng sẵn cho các chỉ số, số đếm và sự khác biệt giữa hai số. Miễn là chúng tôi vẫn đang sử dụng vanilla ints, Ứng dụng Hungary sẽ không dư thừa và hữu ích.
Câu hỏi hóc búa Eldritch

27

Tôi luôn sử dụng ký hiệu Hungary cho tất cả các dự án của tôi. Tôi thấy nó thực sự hữu ích khi tôi xử lý hàng trăm tên định danh khác nhau.

Ví dụ, khi tôi gọi một hàm yêu cầu một chuỗi, tôi có thể nhập 's' và nhấn control-space và IDE của tôi sẽ hiển thị cho tôi chính xác các tên biến có tiền tố là 's'.

Một lợi thế khác, khi tôi đặt tiền tố u cho unsign và i cho ints đã ký, tôi thấy ngay nơi tôi đang trộn lẫn đã ký và unsign theo những cách nguy hiểm tiềm tàng.

Tôi không thể nhớ số lần khi trong một cơ sở mã 75000 dòng lớn, các lỗi đã xảy ra (do tôi và những người khác) do đặt tên biến cục bộ giống như biến thành viên hiện có của lớp đó. Kể từ đó, tôi luôn tiền tố thành viên với 'm_'

Đó là một câu hỏi về hương vị và kinh nghiệm. Đừng gõ nó cho đến khi bạn đã thử nó.


1
Mã hóa chữ ký thành tên biến là tuyệt vời khi đoạn mã thực sự xử lý chữ ký. Sử dụng điều đó như một cái cớ để thực thi quy ước cho tất cả các biến chỉ là chủ nghĩa thống trị IMHO.
Plumator

Bạn có một điểm tốt với các biến thành viên, mặc dù. Nhưng trong các ngôn ngữ như Python, nơi bạn buộc phải hội đủ điều kiện cho thành viên với đối tượng tự / đối tượng này thì đó là tranh luận.
Plumator

Đó chỉ là một mẹo để giúp năng suất. Cũng giống như IDE tự động hoàn thành. Không có gì xấu về cơ bản về nó. Tôi tin rằng các lập trình viên có kinh nghiệm phải được phép sử dụng phong cách riêng của họ. Buộc bất cứ ai chọn một phong cách nhất định là xấu. Bây giờ tôi làm việc như một nhà phát triển duy nhất, nhưng tôi sẽ không thực thi một phong cách đối với bất kỳ ai tôi làm việc cùng trừ khi họ thiếu một phong cách nhất quán ở nơi đầu tiên.
rep_movsd

Vì vậy, bạn đang sử dụng quy ước đặt tên để lọc các biến, phải không? Tôi phải đồng ý rằng đó là thông minh . :-) Tuy nhiên, cách tôi kết nối, điểm neo (hoặc tiêu chí lọc, nếu bạn thích) luôn là ngữ nghĩa đối với tôi. Hiếm khi loại (trừ khi nó ngữ nghĩa). Tôi hy vọng rằng ý thức thực hiện. TL; DR: Tôi vẫn gắn bó với việc đặt tên biến theo những gì chúng thể hiện hơn là cách chúng được biểu diễn.
Plumator

1
Tôi đã ủng hộ điều này sau đó kể từ khi tôi ủng hộ tiếng Hungary. Bây giờ tôi rất tiếc, và sẽ không bao giờ quay lại tiền tố một biến nào đó ..
nawfal

22

Bạn đang quên lý do số một để bao gồm thông tin này. Nó không có gì để làm với bạn, lập trình viên. Nó có mọi thứ để làm với người xuống đường 2 hoặc 3 năm sau khi bạn rời công ty, người phải đọc những thứ đó.

Có, một IDE sẽ nhanh chóng xác định các loại cho bạn. Tuy nhiên, khi bạn đang đọc qua một số mã dài 'quy tắc kinh doanh', thật tuyệt khi không phải tạm dừng trên mỗi biến để tìm hiểu loại đó là gì. Khi tôi thấy những thứ như strUserID, intSản phẩm hoặc gui ProducttID, điều đó giúp cho việc 'tăng tốc' dễ dàng hơn nhiều .

Tôi đồng ý rằng MS đã đi quá xa với một số quy ước đặt tên của họ - tôi phân loại rằng trong đống "quá nhiều thứ tốt".

Quy ước đặt tên là những điều tốt, miễn là bạn gắn bó với chúng. Tôi đã trải qua đủ mã cũ khiến tôi liên tục quay lại để xem xét các định nghĩa cho rất nhiều biến có tên tương tự mà tôi đẩy "vỏ lạc đà" (như nó được gọi ở một công việc trước đó). Ngay bây giờ tôi đang làm một công việc có hàng ngàn dòng mã ASP cổ điển hoàn toàn không bị lỗi với VBScript và đó là một cơn ác mộng khi cố gắng tìm ra mọi thứ.


Là một người dùng VIM (không có IDE, không làm nổi bật, không có người dùng hover-Tell-you-what-type), tôi hoàn toàn không hiểu lập luận này. Tôi tự nhiên hiểu rằng một biến được gọi là tên là một chuỗi và một biến được gọi là i hoặc Count là một int. Có ai thực sự cần sName và iCount? Làm thế nào để nó thực sự giúp đỡ? Tôi sẽ tranh luận rằng ví dụ id sản phẩm của bạn là một trường hợp đặc biệt, và có lẽ ở đó nó sẽ ổn. Nhưng ngay cả khi đó, việc thống nhất và đại diện cho ID sản phẩm bằng ints hoặc chuỗi ở mọi nơi sẽ là một giải pháp tốt hơn nhiều, phải không? Toàn bộ việc đặt tên có vẻ như là một cảnh sát.
MrFox

6
Đó là sự nhất quán. Có, "tên" vốn đã bao hàm một chuỗi. Nhưng những gì bạn sẽ đoán "userid" là gì? HƯỚNG DẪN? Chuỗi? Số nguyên? Ngay cả một cái gì đó như "acctno" có thể có giá trị 42 hoặc "23X". Tài liệu đủ thưa thớt trong hầu hết các mã. Tiêu chuẩn này giúp các lập trình viên bảo trì cùng một chút.
David

1
@David Tôi hoàn toàn đồng ý với câu trả lời của bạn - biết trong nháy mắt ý định của biến là lý do tôi thích tiền tố hơn, hơn nữa là trong một ngôn ngữ động như JS.
Daniel Sokolowski

10

Việc xử lý các ký tự khó hiểu ở đầu mỗi tên biến là không cần thiết và cho thấy rằng tên biến tự nó không đủ để mô tả. Hầu hết các ngôn ngữ đều yêu cầu loại biến khi khai báo, vì vậy thông tin đã có sẵn.

Cũng có tình huống, trong khi bảo trì, một loại biến cần phải thay đổi. Ví dụ: nếu một biến được khai báo là "uint_16 u16foo" cần trở thành không dấu 64 bit, một trong hai điều sẽ xảy ra:

  1. Bạn sẽ xem qua và thay đổi từng tên biến (đảm bảo không sử dụng bất kỳ biến nào không liên quan có cùng tên) hoặc
  2. Chỉ cần thay đổi loại và không thay đổi tên, điều này sẽ chỉ gây nhầm lẫn.

9

Joel Spolsky đã viết một bài đăng blog tốt về điều này. http://www.joelonsoftware.com/articles/Wrong.html Về cơ bản, điều này dẫn đến việc không làm cho mã của bạn khó đọc hơn khi một IDE tốt sẽ cho bạn biết muốn nhập biến là nếu bạn không thể nhớ. Ngoài ra, nếu bạn làm cho mã của mình đủ ngăn, bạn không cần phải nhớ biến nào được khai báo là ba trang trở lên.


9

Không có phạm vi quan trọng hơn loại ngày nay, ví dụ

* l for local
* a for argument
* m for member
* g for global
* etc

Với các kỹ thuật hiện đại để tái cấu trúc mã cũ, tìm kiếm và thay thế một ký hiệu vì bạn đã thay đổi loại của nó là tẻ nhạt, trình biên dịch sẽ bắt các thay đổi loại, nhưng thường sẽ không bắt được sử dụng phạm vi, các quy ước đặt tên hợp lý giúp ở đây.


Sau đó, một lần nữa, mã có lẽ không nên phụ thuộc vào phạm vi rất nhiều. :-)
Plumator

8

Không có lý do tại sao bạn không nên sử dụng đúng ký hiệu Hungary. Sự phổ biến của nó là do một cú đánh ngược dài chống lại việc sử dụng sai ký hiệu Hungary, đặc biệt là trong các API của Windows.

Vào thời xa xưa, trước khi mọi thứ giống như IDE tồn tại cho DOS (tỷ lệ là bạn không có đủ bộ nhớ trống để chạy trình biên dịch trong Windows, vì vậy sự phát triển của bạn đã được thực hiện trong DOS), bạn không nhận được sự trợ giúp nào từ di chuột qua một tên biến. (Giả sử bạn có một con chuột.) Bạn đã phải làm gì với các hàm gọi lại sự kiện trong đó mọi thứ được chuyển cho bạn dưới dạng int 16 bit (WORD) hoặc int 32 bit (LONG WORD). Sau đó, bạn phải truyền các tham số đó thành các loại thích hợp cho loại sự kiện đã cho. Trên thực tế, phần lớn API hầu như không có loại.

Kết quả, một API có tên tham số như sau:

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

Lưu ý rằng tên wParam và lParam, mặc dù khá khủng khiếp, nhưng thực sự không tệ hơn việc đặt tên cho chúng là param1 và param2.

Để làm cho vấn đề tồi tệ hơn, Window 3.0 / 3.1 có hai loại con trỏ, gần và xa. Vì vậy, ví dụ, giá trị trả về từ chức năng quản lý bộ nhớ LocalLock là một PVOID, nhưng giá trị trả về từ GlobalLock là LPVOID (với 'L' từ lâu). Ký hiệu khủng khiếp đó sau đó đã được mở rộng để một chuỗi l ong p ointer được tiền tố lp , để phân biệt nó với một chuỗi đơn giản là malloc'd.

Không có gì ngạc nhiên khi có một phản ứng dữ dội chống lại loại điều này.


6

Ký hiệu Hungary có thể hữu ích trong các ngôn ngữ mà không cần kiểm tra kiểu thời gian biên dịch, vì nó sẽ cho phép nhà phát triển nhanh chóng tự nhắc nhở về cách sử dụng biến cụ thể. Nó không làm gì cho hiệu suất hoặc hành vi. Nó được cho là để cải thiện khả năng đọc mã và chủ yếu là một vấn đề về phong cách và mã hóa. Vì lý do này, nó bị chỉ trích bởi nhiều nhà phát triển - không phải ai cũng có hệ thống dây điện giống nhau trong não.

Đối với các ngôn ngữ kiểm tra kiểu thời gian biên dịch, phần lớn là vô dụng - cuộn lên một vài dòng sẽ tiết lộ khai báo và do đó gõ. Nếu bạn biến toàn cục hoặc khối mã của bạn kéo dài nhiều hơn một màn hình, bạn có các vấn đề về thiết kế và tái sử dụng nghiêm trọng. Do đó, một trong những lời chỉ trích là Ký hiệu Hungary cho phép các nhà phát triển có thiết kế xấu và dễ dàng thoát khỏi nó. Đây có lẽ là một trong những lý do cho sự ghét bỏ.

Mặt khác, có thể có trường hợp ngay cả các ngôn ngữ kiểm tra kiểu thời gian biên dịch sẽ được hưởng lợi từ Ký hiệu Hungary - con trỏ trống hoặc TAY trong API win32. Những thứ này làm xáo trộn kiểu dữ liệu thực tế và có thể có một công đức để sử dụng Ký hiệu Hungary ở đó. Tuy nhiên, nếu người ta có thể biết loại dữ liệu tại thời điểm xây dựng, tại sao không sử dụng loại dữ liệu phù hợp.

Nói chung, không có lý do khó để không sử dụng Ký hiệu Hungary. Đó là vấn đề thích, chính sách và phong cách mã hóa.


6

Là một lập trình viên Python, Ký hiệu Hungary sụp đổ khá nhanh. Trong Python, tôi không quan tâm nếu một cái gì đó một chuỗi - Tôi quan tâm nếu nó có thể hoạt động như một chuỗi (tức là nếu nó có một ___str___()phương thức trả về một chuỗi).

Ví dụ: giả sử chúng ta có foo là số nguyên, 12

foo = 12

Ký hiệu Hungary cho chúng ta biết rằng chúng ta nên gọi iFoo hoặc một cái gì đó, để biểu thị nó là một số nguyên, để sau này, chúng ta biết nó là gì. Ngoại trừ trong Python, điều đó không hoạt động, hay đúng hơn, nó không có ý nghĩa. Trong Python, tôi quyết định loại tôi muốn khi tôi sử dụng nó. Tôi có muốn một chuỗi không? tốt nếu tôi làm một cái gì đó như thế này:

print "The current value of foo is %s" % foo

Lưu ý %s- chuỗi. Foo không phải là một chuỗi, nhưng %toán tử sẽ gọi foo.___str___()và sử dụng kết quả (giả sử nó tồn tại). foovẫn là một số nguyên, nhưng chúng ta coi nó như một chuỗi nếu chúng ta muốn một chuỗi. Nếu chúng ta muốn một cái phao, thì chúng ta coi nó như một cái phao. Trong các ngôn ngữ được gõ động như Python, Ký hiệu Hungary là vô nghĩa, bởi vì nó không quan trọng là loại gì cho đến khi bạn sử dụng nó và nếu bạn cần một loại cụ thể, thì hãy đảm bảo chuyển nó sang loại đó (ví dụ float(foo)) khi bạn sử dụng nó.

Lưu ý rằng các ngôn ngữ động như PHP không có lợi ích này - PHP cố gắng thực hiện 'điều đúng đắn' trong nền dựa trên một bộ quy tắc tối nghĩa mà hầu như không ai ghi nhớ, điều này thường dẫn đến những mớ hỗn độn bất ngờ. Trong trường hợp này, một số loại cơ chế đặt tên, như $files_counthoặc $file_name, có thể có ích.

Theo quan điểm của tôi, ký hiệu Hungary giống như con đỉa. Có thể trong quá khứ chúng rất hữu ích, hoặc ít nhất là chúng có vẻ hữu ích, nhưng ngày nay nó chỉ là việc gõ thêm mà không mang lại nhiều lợi ích.


Điều thú vị là ví dụ của bạn với .str () trong Python không phải là kết quả của ngôn ngữ động. Java, chắc chắn không phải là một ngôn ngữ động, cũng làm điều tương tự.
quét bụi

C # cũng làm điều tương tự, mọi lớp trong ngôn ngữ đều thực hiện .ToString()sao cho tất cả có thể được in
Cà phê điện

5

IDE nên truyền đạt thông tin hữu ích đó. Tiếng Hungary có thể đã tạo ra một số loại (không phải là toàn bộ, nhưng một số loại) có ý nghĩa khi IDE kém tiên tiến hơn nhiều.


4
Sau đó, một lần nữa, bạn không nên dựa vào IDE nói với bạn nhiều hơn. Rốt cuộc, mã có thể được xem bên ngoài IDE ...
TraumaPony

5

Ứng dụng tiếng Hungary là tiếng Hy Lạp đối với tôi - một cách tốt

Là một kỹ sư, không phải là lập trình viên, tôi đã ngay lập tức đọc bài viết của Joel về giá trị của Ứng dụng Hungary: "Làm cho mã sai nhìn sai" . Tôi thích Ứng dụng Hungary vì nó bắt chước cách thức kỹ thuật, khoa học và toán học biểu thị các phương trình và công thức sử dụng các ký hiệu phụ và siêu chữ (như chữ cái Hy Lạp, toán tử toán học, v.v.). Lấy một ví dụ cụ thể về Định luật vạn vật hấp dẫn của Newton : đầu tiên là ký hiệu toán học tiêu chuẩn, sau đó là mã giả tiếng Hungary:

Định luật vạn vật hấp dẫn của Trái đất và Sao Hỏa

frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)

Trong ký hiệu toán học, các ký hiệu nổi bật nhất là các ký hiệu đại diện cho loại thông tin được lưu trữ trong biến: lực, khối lượng, vectơ vị trí, v.v ... Các chỉ số đóng vai trò thứ hai để làm rõ: vị trí của cái gì? Đây chính xác là những gì Ứng dụng Hungary đang làm; nó cho bạn biết loại điều được lưu trữ trong biến trước tiên và sau đó đi vào chi tiết cụ thể - về mã gần nhất có thể nhận được ký hiệu toán học.

Việc gõ mạnh rõ ràng có thể giải quyết ví dụ chuỗi an toàn và không an toàn từ bài luận của Joel, nhưng bạn sẽ không xác định các loại riêng biệt cho vectơ vị trí và vận tốc; cả hai đều là mảng kép có kích thước ba và bất cứ điều gì bạn có thể làm với cái này có thể áp dụng cho cái kia. Hơn nữa, nó có ý nghĩa hoàn hảo để nối vị trí và vận tốc (để tạo một vectơ trạng thái) hoặc lấy sản phẩm chấm của chúng, nhưng có lẽ không thêm chúng. Làm thế nào để gõ cho phép hai cái đầu tiên và cấm cái thứ hai, và làm thế nào một hệ thống như vậy sẽ mở rộng cho mọi hoạt động có thể bạn muốn bảo vệ? Trừ khi bạn sẵn sàng mã hóa tất cả toán học và vật lý trong hệ thống đánh máy của bạn.

Trên hết, rất nhiều kỹ thuật được thực hiện bằng các ngôn ngữ cấp cao được đánh máy yếu như Matlab, hoặc các ngôn ngữ cũ như Fortran 77 hoặc Ada.

Vì vậy, nếu bạn có một ngôn ngữ ưa thích và IDE và Ứng dụng Hungary sẽ không giúp bạn quên nó - rất nhiều người rõ ràng có. Nhưng đối với tôi, một điều tồi tệ hơn một lập trình viên mới làm việc trong các ngôn ngữ được gõ yếu hoặc động, tôi có thể viết mã tốt hơn nhanh hơn với Ứng dụng Hungary hơn là không có.


4

Nó cực kỳ dư thừa và vô dụng là hầu hết các IDE hiện đại, nơi chúng làm tốt công việc làm cho loại hình rõ ràng.

Thêm vào đó - với tôi - thật khó chịu khi thấy intI, strUserName, v.v. :)


3
Như TraumaPony đã nói với Paul Batum, không phải ai cũng nhìn thấy mã trong IDE.
Chris Charabaruk

4

Nếu tôi cảm thấy rằng thông tin hữu ích đang được truyền đi, tại sao tôi không nên đặt nó ngay tại nơi có sẵn?

Sau đó, ai quan tâm những gì người khác nghĩ? Nếu bạn thấy nó hữu ích, sau đó sử dụng ký hiệu.


Bởi vì chỉ có một trong số tôi và một người khác có thể duy trì mã của tôi sau này. Vì tất cả những người đó đều ở trong đội (nhưng họ chưa biết điều đó), tôi muốn có một số ý tưởng nếu họ vượt xa tôi.
quét bụi

4

Theo kinh nghiệm của tôi, nó là xấu bởi vì:

1 - sau đó bạn phá vỡ tất cả mã nếu bạn cần thay đổi loại biến (tức là nếu bạn cần mở rộng số nguyên 32 bit thành số nguyên 64 bit);

2 - đây là thông tin vô dụng vì loại này đã có trong khai báo hoặc bạn sử dụng ngôn ngữ động trong đó loại thực tế không nên quá quan trọng ở vị trí đầu tiên.

Ngoài ra, với ngôn ngữ chấp nhận lập trình chung (nghĩa là các hàm trong đó loại của một số biến không được xác định khi bạn viết hàm) hoặc với hệ thống gõ động (nghĩa là khi kiểu này thậm chí không xác định tại thời điểm biên dịch), bạn sẽ đặt tên như thế nào biến? Và hầu hết các ngôn ngữ hiện đại đều hỗ trợ cái này hay cái kia, ngay cả khi ở dạng hạn chế.


4

Trong Joel Spolsky's Making Wrong Code Look Wrong , anh giải thích rằng những gì mọi người nghĩ về Ký hiệu Hungary (mà anh gọi là Hệ thống Hungary) không phải là những gì nó thực sự được dự định (cái mà anh gọi là Ứng dụng Hungary). Cuộn xuống tiêu đề Tôi là Hungary để xem cuộc thảo luận này.

Về cơ bản, Hệ thống Hungary là vô giá trị. Nó chỉ cho bạn biết điều tương tự trình biên dịch và / hoặc IDE của bạn sẽ cho bạn biết.

Ứng dụng Hungary cho bạn biết ý nghĩa của biến đó là gì và thực sự có thể hữu ích.


4

Tôi đã luôn nghĩ rằng một hoặc hai tiền tố ở đúng nơi sẽ không bị tổn thương. Tôi nghĩ rằng nếu tôi có thể truyền đạt một cái gì đó hữu ích, như "Này đây là một giao diện, đừng tin vào hành vi cụ thể" ngay tại đó, như trong IEnumerable, tôi không nên làm điều đó. Nhận xét có thể làm lộn xộn mọi thứ nhiều hơn chỉ là một hoặc hai biểu tượng nhân vật.


1
Tôi không bao giờ có được cái gì đó. Nếu đó là một -able, điều đó có nghĩa là giao diện nào. (Ít nhất là trong java)
tunaranch

4

Đó là một quy ước hữu ích để đặt tên các điều khiển trên một biểu mẫu (btnOK, txtLastName, v.v.), nếu danh sách các điều khiển hiển thị trong danh sách kéo xuống theo thứ tự chữ cái trong IDE của bạn.


4

Tôi có xu hướng sử dụng Notation Hungary với các điều khiển máy chủ ASP.NET chỉ , nếu không tôi thấy nó quá khó để tìm ra những gì kiểm soát được những gì về hình thức.

Lấy đoạn mã này:

<asp:Label ID="lblFirstName" runat="server" Text="First Name" />
<asp:TextBox ID="txtFirstName" runat="server" />
<asp:RequiredFieldValidator ID="rfvFirstName" runat="server" ... />

Nếu ai đó có thể chỉ ra một cách tốt hơn để có bộ tên kiểm soát mà không có tiếng Hungary, tôi sẽ bị cám dỗ chuyển sang nó.


4

Bài viết của Joel rất hay, nhưng dường như bỏ qua một điểm chính:

Hungary làm cho một 'ý tưởng' (loại + tên định danh) cụ thể, hoặc gần như duy nhất, trên cơ sở mã - thậm chí là một cơ sở mã rất lớn.

Đó là rất lớn để bảo trì mã. Điều đó có nghĩa là bạn có thể sử dụng tìm kiếm văn bản một dòng tốt (grep, findstr, 'find trong tất cả các tệp') để tìm MỌI đề cập đến 'ý tưởng' đó.

Tại sao điều đó lại quan trọng khi chúng ta có IDE biết cách đọc mã? Bởi vì họ chưa giỏi lắm. Điều này khó thấy trong một cơ sở mã nhỏ, nhưng rõ ràng trong một cơ sở lớn - khi 'ý tưởng' có thể được đề cập trong các bình luận, tệp XML, tập lệnh Perl và cả ở những nơi ngoài kiểm soát nguồn (tài liệu, wiki, cơ sở dữ liệu lỗi).

Bạn phải cẩn thận một chút ngay cả ở đây - ví dụ: dán mã thông báo trong macro C / C ++ có thể ẩn đề cập đến mã định danh. Những trường hợp như vậy có thể được xử lý bằng cách sử dụng các quy ước mã hóa, và dù sao chúng có xu hướng chỉ ảnh hưởng đến một số ít các định danh trong cơ sở mã.

PS Quan điểm về việc sử dụng hệ thống loại so với Hungary - tốt nhất là sử dụng cả hai. Bạn chỉ cần sai mã để tìm sai nếu trình biên dịch sẽ không bắt được nó cho bạn. Có rất nhiều trường hợp không thể làm cho trình biên dịch bắt được nó. Nhưng nơi nào khả thi - vâng, xin vui lòng làm điều đó thay vào đó!

Tuy nhiên, khi xem xét tính khả thi, hãy xem xét các tác động tiêu cực của việc tách các loại. ví dụ: trong C #, gói 'int' bằng loại không tích hợp có hậu quả rất lớn. Vì vậy, nó có ý nghĩa trong một số tình huống, nhưng không phải trong tất cả chúng.


4

Làm sáng tỏ những lợi ích của ký hiệu Hungary

  • Nó cung cấp một cách để phân biệt các biến.

Nếu loại là tất cả phân biệt giá trị này với giá trị khác, thì nó chỉ có thể được chuyển đổi từ loại này sang loại khác. Nếu bạn có cùng một giá trị đang được chuyển đổi giữa các loại, rất có thể bạn nên thực hiện điều này trong một chức năng dành riêng cho chuyển đổi. (Tôi đã thấy phần còn lại của VB6 sử dụng chuỗi trên tất cả các tham số phương thức của chúng chỉ đơn giản vì chúng không thể tìm ra cách giải tuần tự hóa một đối tượng JSON hoặc hiểu đúng cách khai báo hoặc sử dụng các loại nullable. ) Nếu bạn có hai biến chỉ được phân biệt bởi Tiền tố Hungary, và chúng không phải là một chuyển đổi từ cái này sang cái khác, sau đó bạn cần phải giải thích ý định của bạn với chúng.

  • Nó làm cho mã dễ đọc hơn.

Tôi đã thấy rằng ký hiệu Hungary làm cho mọi người lười biếng với tên biến của họ. Họ có một cái gì đó để phân biệt nó và họ cảm thấy không cần phải xây dựng mục đích của nó. Đây là những gì bạn thường tìm thấy trong mã ký hiệu Hungary so với hiện đại: sQuery so với groupSelectSql ( hoặc thường không có sQuery nào cả vì chúng được cho là đang sử dụng ORM được các nhà phát triển trước đó đưa vào. ), SValue so với formCollectionValue ( hoặc thường không có sValue, bởi vì chúng tình cờ ở trong MVC và nên sử dụng các tính năng ràng buộc mô hình của nó ), sType so với PublishSource, v.v.

Nó không thể đọc được. Tôi thấy nhiều sTemp1, sTemp2 ... sTempN từ bất kỳ VB6 còn lại nào được đưa ra so với mọi người khác cộng lại.

  • Nó ngăn ngừa lỗi.

Điều này sẽ là do số 2, đó là sai.


3

Theo lời của chủ:

http://www.joelonsoftware.com/articles/Wrong.html

Một cách đọc thú vị, như thường lệ.

Chất chiết xuất:

"Ai đó, ở đâu đó, đọc bài viết của Simonyi, ở đó anh ta đã sử dụng từ kiểu Cam, chữ và nghĩ rằng anh ta có nghĩa là kiểu, giống như trong một hệ thống kiểu, giống như kiểu kiểm tra mà trình biên dịch thực hiện. Anh ta đã không giải thích rất cẩn thận. chính xác những gì anh ta muốn nói với loại từ, loại nhưng không giúp được gì. Thiệt hại đã được thực hiện. "

"Nhưng vẫn còn một lượng giá trị to lớn đối với Ứng dụng Hungary, ở chỗ nó tăng khả năng sắp xếp thứ tự trong mã, giúp mã dễ đọc, viết, gỡ lỗi và bảo trì hơn và quan trọng nhất là mã sai khiến mã sai."

Hãy chắc chắn rằng bạn có một chút thời gian trước khi đọc Joel On Software. :)


Không có thời gian bây giờ tôi có Stackoverflow. Tôi nghĩ rằng sự kết hợp đơn thuần của Spolsky với dự án phải được thực hiện. :)
Dustman

3

Nhiều lý do:

  • Bất kỳ IDE hiện đại nào cũng sẽ cung cấp cho bạn loại biến bằng cách di chuột qua biến.
  • Hầu hết các tên loại đều dài (nghĩ rằng httpClientRequestProvider ) được sử dụng hợp lý làm tiền tố.
  • Thông tin loại không mang thông tin đúng , nó chỉ diễn giải khai báo biến, thay vì phác thảo mục đích của biến (nghĩ myInteger so với pageSize ).

2

Tôi không nghĩ mọi người đang chống lại nó. Trong các ngôn ngữ không có kiểu tĩnh, nó khá hữu ích. Tôi chắc chắn thích nó khi nó được sử dụng để cung cấp thông tin chưa có trong loại. Giống như trong C, char * szName nói rằng biến sẽ đề cập đến một chuỗi kết thúc null - điều đó không ẩn trong char * - tất nhiên, một typedef cũng sẽ giúp ích.

Joel đã có một bài viết tuyệt vời về việc sử dụng Lynn để biết liệu một biến có được mã hóa HTML hay không:

http://www.joelonsoftware.com/articles/Wrong.html

Dù sao, tôi có xu hướng không thích tiếng Hungary khi nó được sử dụng để truyền đạt thông tin mà tôi đã biết.


Tôi nghĩ rằng câu đầu tiên có thể tin những câu trả lời trên trang này.
quét bụi

@Dustman Chà, bạn đã biết chuỗi C bị hủy không? Tôi thấy nó hữu ích như thế nào khi chuỗi có thể không nhưng điều đó rất hiếm và vì vậy tôi nghĩ rằng việc sử dụng quy ước nên được giới hạn trong các trường hợp đó.
Plumator

Không phải mọi char * là một chuỗi c kết thúc null. Quan điểm của Hungary là sử dụng nó cho mọi biến số, ngay cả những biến rơi vào trường hợp phổ biến. Cuối cùng, tôi cảm thấy như bạn làm - và do đó tôi không sử dụng nó trong C.
Lou Franco

2

Tất nhiên khi 99% lập trình viên đồng ý về một cái gì đó, có một cái gì đó sai. Lý do họ đồng ý ở đây là vì hầu hết trong số họ chưa bao giờ sử dụng ký hiệu Hungary một cách chính xác.

Đối với một cuộc tranh luận chi tiết, tôi giới thiệu cho bạn một bài viết blog tôi đã thực hiện về chủ đề này.

http://codingthriller.blogspot.com/2007/11/rediscovering-hungarian-notation.html


2

Tôi bắt đầu viết mã khá nhiều về thời gian ký hiệu Hungary được phát minh và lần đầu tiên tôi buộc phải sử dụng nó cho một dự án mà tôi ghét nó.

Sau một thời gian tôi nhận ra rằng khi nó được thực hiện đúng cách nó thực sự có ích và ngày nay tôi yêu nó.

Nhưng giống như tất cả những điều tốt, nó phải được học và hiểu và để làm điều đó đúng cách cần có thời gian.


1

Ký hiệu Hungary đã bị Microsoft lạm dụng, đặc biệt là Microsoft, dẫn đến tiền tố dài hơn tên biến và cho thấy nó khá cứng nhắc, đặc biệt khi bạn thay đổi các loại (lparam / wparam khét tiếng, có loại / kích cỡ khác nhau trong Win16, giống hệt trong Win32 ).

Do đó, cả hai do sự lạm dụng này và việc sử dụng nó bởi M $, nó đã bị coi là vô dụng.

Trong công việc của tôi, chúng tôi viết mã bằng Java, nhưng người sáng lập đến từ thế giới MFC, vì vậy sử dụng kiểu mã tương tự (dấu ngoặc thẳng, tôi thích cái này!, Chữ hoa cho tên phương thức, tôi quen với nó, tiền tố như m_ cho các thành viên lớp (các trường ), s_ cho các thành viên tĩnh, v.v.).

Và họ nói rằng tất cả các biến nên có tiền tố hiển thị loại của nó (ví dụ: BufferedReader được đặt tên là brData). Điều này được coi là một ý tưởng tồi, vì các loại có thể thay đổi nhưng tên không tuân theo hoặc các lập trình viên không nhất quán trong việc sử dụng các tiền tố này (tôi thậm chí còn thấy aBuffer, theProxy, v.v.!).

Cá nhân, tôi đã chọn một vài tiền tố mà tôi thấy hữu ích, quan trọng nhất là các biến boolean tiền tố, vì chúng là những tiền tố duy nhất mà tôi cho phép cú pháp như if (bVar) (không sử dụng autocast của một số giá trị thành đúng hoặc sai). Khi tôi mã hóa bằng C, tôi đã sử dụng tiền tố cho các biến được phân bổ bằng malloc, như một lời nhắc nhở nó sẽ được giải phóng sau. Vân vân.

Vì vậy, về cơ bản, tôi không từ chối toàn bộ ký hiệu này, nhưng lấy những gì có vẻ phù hợp với nhu cầu của tôi.
Và tất nhiên, khi đóng góp cho một số dự án (công việc, nguồn mở), tôi chỉ sử dụng các quy ước tại chỗ!

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.