สัญกรณ์ฮังการีเป็นวิธีแก้ปัญหาสำหรับภาษาที่มีการพิมพ์คงที่ไม่เพียงพอที่แสดงออก? [ปิด]


28

ในบทความของ Eric Lippert เกิดอะไรขึ้นกับสัญลักษณ์ของฮังการี? เขากล่าวว่าจุดประสงค์ของสัญกรณ์ฮังการี (ประเภทที่ดี) คือการ

ขยายแนวคิดของ "ประเภท" เพื่อรวมข้อมูลเชิงความหมายนอกเหนือจากข้อมูลการเป็นตัวแทนจัดเก็บข้อมูล

ตัวอย่างง่ายๆจะนำหน้าตัวแปรที่แสดงถึงพิกัด X ด้วย "x" และตัวแปรที่แทนพิกัด Y ด้วย "y" โดยไม่คำนึงว่าตัวแปรเหล่านั้นเป็นจำนวนเต็มหรือลอยหรืออะไรก็ตามดังนั้นเมื่อคุณเขียนโดยไม่ตั้งใจxFoo + yBarรหัสดูผิดอย่างชัดเจน

แต่ฉันได้อ่านเกี่ยวกับระบบประเภทของ Haskell ด้วยและดูเหมือนว่าใน Haskell เราสามารถทำสิ่งเดียวกันให้สำเร็จได้ (เช่น "ขยายแนวคิดประเภทที่จะครอบคลุมข้อมูลความหมาย") โดยใช้ประเภทจริงที่คอมไพเลอร์จะตรวจสอบคุณ ดังนั้นในตัวอย่างข้างต้นxFoo + yBarใน Haskell จะล้มเหลวในการรวบรวมถ้าคุณออกแบบโปรแกรมของคุณอย่างถูกต้องเนื่องจากมันถูกประกาศว่าเป็นชนิดที่เข้ากันไม่ได้ ดูเหมือนว่าระบบประเภทของ Haskell สนับสนุนการตรวจสอบเวลาแบบคอมไพล์ได้อย่างมีประสิทธิภาพเทียบเท่ากับสัญลักษณ์ของฮังการี

ดังนั้น Hungarian Notation เป็นเพียงตัวช่วยแบนด์สำหรับภาษาโปรแกรมที่ระบบประเภทไม่สามารถเข้ารหัสข้อมูลความหมายได้หรือไม่? สัญกรณ์ฮังการีหรือเสนอบางสิ่งบางอย่างนอกเหนือจากสิ่งที่ระบบชนิดคงที่เช่น Haskell สามารถนำเสนอ?

(แน่นอนฉันกำลังใช้ Haskell เป็นตัวอย่างฉันแน่ใจว่ามีภาษาอื่นที่มีระบบการพิมพ์ที่มีความหมายคล้ายกัน (rich? strong?) แม้ว่าฉันจะไม่ได้เจอก็ตาม)


เพื่อความชัดเจนฉันไม่ได้พูดถึงคำอธิบายประกอบชื่อตัวแปรด้วยชนิดข้อมูลแต่มีข้อมูลเกี่ยวกับความหมายของตัวแปรในบริบทของโปรแกรม ตัวอย่างเช่นตัวแปรอาจเป็นจำนวนเต็มหรือลอยหรือสองหรือยาวหรืออะไรก็ตาม แต่บางทีความหมายของตัวแปรคือมันเป็นพิกัด x ที่สัมพันธ์กันวัดเป็นนิ้ว นี่คือข้อมูลประเภทหนึ่งที่ฉันกำลังพูดถึงเกี่ยวกับการเข้ารหัสผ่านรูปแบบฮังการี (และผ่านประเภท Haskell)


Pascal - แม้ว่าคุณจะลองและเพิ่มประเภท XCood และ YCoord ที่คุณกำหนดใน Pascal คุณจะได้รับคำเตือนคอมไพเลอร์ IIRC
mcottle

1
blog.moertel.com/articles/2006/10/18/…เป็นบทความเกี่ยวกับการทำสิ่งที่คล้ายกับ "apps Hungarian" ในระบบพิมพ์ใน Haskell
Logan Capaldo

1
F # มีคุณสมบัติสไตล์นี้ด้วย
Rangoric

นั่นคือลิงค์บทความที่ดีจริงๆ (moertel.com หนึ่งรายการ) แสดงประเภทของสิ่งที่ฉันกำลังคิดอย่างแน่นอน: การใช้ระบบประเภทเพื่อเปลี่ยนช่องโหว่ความปลอดภัยของการแก้ไขสตริงและการแก้ไขข้อผิดพลาดในการรวบรวมเวลา ขอบคุณสำหรับลิงค์
Ryan C. Thompson

ฉันคิดว่าเป็นจำนวนมาก OO จมอยู่กับสัญกรณ์ฮังการีสำหรับความหมายเพราะวันนี้คุณอาจจะเขียน: Foo.Position.X + Bar.Position.Y
ปีเตอร์ B

คำตอบ:


27

ฉันจะพูดว่า "ใช่"

อย่างที่คุณพูดวัตถุประสงค์ของสัญกรณ์ฮังการีคือการเข้ารหัสข้อมูลในชื่อที่ไม่สามารถเข้ารหัสในประเภท อย่างไรก็ตามโดยทั่วไปมีสองกรณี:

  1. ข้อมูลนั้นมีความสำคัญ
  2. ข้อมูลนั้นไม่สำคัญ

เริ่มจากกรณีที่ 2 ก่อน: ถ้าข้อมูลนั้นไม่สำคัญสัญญาณฮังการีจะเป็นแค่เสียงฟุ่มเฟือย

กรณีที่น่าสนใจมากขึ้นคือหมายเลข 1 แต่ฉันจะโต้แย้งว่าหากข้อมูลมีความสำคัญควรตรวจสอบเช่นควรเป็นส่วนหนึ่งของประเภทไม่ใช่ชื่อชื่อ

ซึ่งนำเรากลับไปที่คำพูดของ Eric Lippert:

ขยายแนวคิดของ "ประเภท" เพื่อรวมข้อมูลเชิงความหมายนอกเหนือจากข้อมูลการเป็นตัวแทนจัดเก็บข้อมูล

ที่จริงแล้วนั่นไม่ใช่ "การขยายแนวคิดประเภท" นั่นคือแนวคิดประเภท! วัตถุประสงค์ทั้งประเภท (เป็นเครื่องมือในการออกแบบ) คือการเข้ารหัสข้อมูลความหมาย! การเป็นตัวแทนในการจัดเก็บข้อมูลเป็นรายละเอียดการนำไปใช้งานซึ่งโดยปกติไม่ได้อยู่ในประเภทใดๆ เลย (และโดยเฉพาะในภาษา OO ไม่สามารถอยู่ในประเภทได้เนื่องจากความเป็นอิสระในการเป็นตัวแทนเป็นหนึ่งในข้อกำหนดเบื้องต้นที่สำคัญสำหรับ OO)


C ที่สัญกรณ์ฮังการีใช้ AFAIK เป็นส่วนใหญ่ไม่ใช่ภาษา OO
PéterTörök

4
@ PéterTörök: OO เป็นรูปแบบการออกแบบไม่ใช่คุณสมบัติของภาษา แต่ภาษาที่ทันสมัยได้รับการออกแบบมาเพื่อให้ง่ายในขณะที่ C ไม่ใช่
Jan Hudec

3
@ PéterTörök: ฉันเขียนโค้ดเชิงวัตถุค่อนข้างมากในแบบธรรมดา C. ฉันรู้ว่าฉันกำลังพูดถึงอะไร
Jan Hudec

1
ในขณะที่มันอาจเป็นความจริงที่ข้อมูลสำคัญควรฝังตัวอยู่ในประเภทของตัวแปรมากกว่าชื่อของมันมีหลายสิ่งที่สำคัญที่ควรจะพูด แต่ระบบประเภทที่ไม่สามารถแสดง ตัวอย่างเช่นหากS1มีการอ้างอิงเพียงอย่างเดียวที่ใดก็ได้ในเอกภพถึงผู้char[]มีเจ้าของสามารถและจะเปลี่ยนแปลงได้ทุกเมื่อที่ต้องการ แต่จะต้องไม่เปิดเผยรหัสภายนอกและS2เป็นการอ้างอิงถึงสิ่งchar[]ที่ไม่มีใครควรเปลี่ยนแปลง แต่อาจถูกแชร์ กับวัตถุที่สัญญาว่าจะไม่เปลี่ยนแปลงควรS1และควรS2ได้รับการยกย่องความหมายเหมือน "สิ่ง" ชนิดเดียวกันหรือไม่?
supercat

1
@supercat - คุณกำลังอธิบายประเภทที่ไม่ซ้ำ
แจ็ค

9

วัตถุประสงค์ทั้งหมดของประเภท (เป็นเครื่องมือออกแบบ) คือการเข้ารหัสข้อมูลความหมาย!

ฉันชอบคำตอบนี้และต้องการติดตามคำตอบนี้ ...

ฉันไม่รู้อะไรเกี่ยวกับ Haskell แต่คุณสามารถทำสิ่งที่เป็นตัวอย่างให้สำเร็จได้ xFoo + yBarภาษาที่รองรับรูปแบบความปลอดภัยบางประเภทเช่น C, C ++ หรือ Java ใน C ++ คุณสามารถกำหนดคลาส XDir และ YDir ด้วยตัวดำเนินการ '+' ที่โอเวอร์โหลดที่ใช้อ็อบเจกต์ประเภทของตนเองเท่านั้น ใน C หรือ Java คุณจะต้องทำการเพิ่มของคุณโดยใช้ฟังก์ชั่น add () / วิธีแทนการใช้ '+'

ฉันเคยเห็นสัญกรณ์ฮังการีที่ใช้สำหรับข้อมูลประเภทไม่ใช่ความหมาย (ยกเว้นตราบเท่าที่ความหมายอาจถูกแทนด้วยประเภท) วิธีที่สะดวกในการจำประเภทของตัวแปรย้อนหลังไปในวันก่อนบรรณาธิการ "การเขียนโปรแกรมอัจฉริยะ" ที่แสดงประเภทของคุณในทิศทางเดียวหรืออย่างอื่นในตัวแก้ไข


การเป็น object-oriented นั้นไม่จำเป็นหรือไม่เพียงพอสำหรับภาษาที่จะอนุญาตให้xFoo + yBarใช้กับชนิดที่ผู้ใช้กำหนดเองและไม่เป็นลักษณะ OO ของ C ++ ที่จำเป็นสำหรับตัวอย่างในการทำงาน
Luc Danton

คุณพูดถูกมันไม่ใช่ความปลอดภัยของ OO ฉันแก้ไขคำตอบของฉัน
BHS

อืมมม เป็นจุดที่ดีที่คุณสามารถxFoo + yBarคอมไพล์ข้อผิดพลาด (หรืออย่างน้อยก็ข้อผิดพลาดรันไทม์) ในภาษาใด ๆ อย่างไรก็ตามในวิชาคณิตศาสตร์ที่มีคลาส XDir และ YDir จะพูดว่า Java หรือ C ++ ช้ากว่าคณิตศาสตร์ที่มีตัวเลขดิบหรือไม่ ความเข้าใจของฉันคือใน Haskell ประเภทจะถูกตรวจสอบ ณ เวลาที่คอมไพล์แล้วที่รันไทม์มันก็แค่คณิตศาสตร์ดิบที่ไม่มีการตรวจสอบประเภทและดังนั้นจึงไม่ช้ากว่าการเพิ่มตัวเลขปกติ
Ryan C. Thompson

ใน C ++ การตรวจสอบชนิดจะกระทำในเวลารวบรวมเช่นกันและการแปลงและสิ่งนั้นจะได้รับการปรับให้เหมาะสมในกรณีส่วนใหญ่ Java ไม่ทำเช่นนั้นเพราะมันไม่อนุญาตให้ผู้ปฏิบัติงานทำการโหลดมากเกินไปและดังนั้นคุณจึงไม่สามารถใช้งานXCoordinateเป็น int ปกติได้
cHao

5

ฉันรู้ว่าวลี "สัญกรณ์ฮังการี" ได้มาหมายถึงสิ่งที่แตกต่างจากต้นฉบับแต่ฉันจะตอบว่า "ไม่" สำหรับคำถาม ตัวแปรการตั้งชื่อด้วย semantic หรือประเภทการคำนวณไม่ได้ทำสิ่งเดียวกันกับการพิมพ์สไตล์ SML หรือ Haskell มันไม่ได้เป็น bandaid การใช้ C เป็นตัวอย่างคุณสามารถตั้งชื่อตัวแปร gpszTitle แต่ตัวแปรนั้นอาจไม่มีขอบเขตทั่วโลก แต่อาจไม่ได้เป็นจุดสิ้นสุดของสตริงที่สิ้นสุดด้วยค่า null

ฉันคิดว่าสัญกรณ์ฮังการีที่ทันสมัยกว่ามีความแตกต่างที่ยิ่งใหญ่กว่าจากระบบการหักประเภทที่แข็งแกร่งเพราะพวกเขาผสมผสานข้อมูล "ความหมาย" (เช่น "g" สำหรับทั่วโลกหรือ "f" สำหรับธง) กับประเภทการคำนวณ ("p" ฉัน "จำนวนเต็ม ฯลฯ ฯลฯ ) ที่เพิ่งจบลงเป็นระเบียบที่ไม่บริสุทธิ์ที่ชื่อตัวแปรมีความคล้ายคลึงกับประเภทการคำนวณของพวกเขาคลุมเครือ (ซึ่งเปลี่ยนแปลงตลอดเวลา) และดูเหมือนว่าคุณไม่สามารถใช้" คู่ต่อไป "เพื่อ ค้นหาตัวแปรในฟังก์ชั่นเฉพาะ - พวกมันเหมือนกันหมด


4

สัญกรณ์ฮังการีถูกคิดค้นสำหรับ BCPL ซึ่งเป็นภาษาที่ไม่มีประเภทเลย หรือว่ามันมีประเภทข้อมูลหนึ่งคำ คำอาจเป็นตัวชี้หรืออาจเป็นอักขระหรือบูลีนหรือตัวเลขจำนวนเต็มธรรมดาขึ้นอยู่กับวิธีที่คุณใช้ เห็นได้ชัดว่าสิ่งนี้ทำให้ง่ายในการทำผิดพลาดที่น่ากลัวเช่นการอ้างอิงตัวละคร ดังนั้นจึงมีการคิดค้นสัญกรณ์ฮังการีเพื่อให้โปรแกรมเมอร์อย่างน้อยสามารถทำการตรวจสอบประเภทด้วยตนเองโดยดูที่รหัส

C, ผู้สืบทอดของ BCPL, มีประเภทที่แตกต่างกันสำหรับจำนวนเต็ม, พอยน์เตอร์, ตัวอักษร ฯลฯ ทำให้สัญกรณ์ฮังการีพื้นฐานฟุ่มเฟือยในระดับหนึ่ง (คุณไม่จำเป็นต้องเข้ารหัสในชื่อตัวแปรถ้ามันเป็น int หรือตัวชี้) แต่ความหมายที่เกินระดับนี้ยังคงไม่สามารถแสดงเป็นประเภทได้ สิ่งนี้นำไปสู่ความแตกต่างระหว่างสิ่งที่เรียกว่า "ระบบ" และ "แอป" ฮังการี คุณไม่จำเป็นต้องแสดงว่าตัวแปรนั้นเป็น int แต่คุณสามารถใช้รหัสตัวอักษรเพื่อระบุว่า int นั้นเป็นพิกัด x หรือ y หรือดัชนีหรือไม่

ภาษาที่ทันสมัยกว่านี้อนุญาตนิยามของประเภทที่กำหนดเองซึ่งหมายความว่าคุณสามารถเข้ารหัสข้อ จำกัด ทางความหมายในประเภทต่างๆได้แทนที่จะเป็นชื่อตัวแปร ตัวอย่างเช่นภาษา OO ทั่วไปจะมีประเภทเฉพาะสำหรับคู่พิกัดและพื้นที่ดังนั้นคุณจึงหลีกเลี่ยงการเพิ่มพิกัด x ลงในพิกัด y

ตัวอย่างเช่นในบทความ Joels ที่โด่งดังยกย่อง Apps Hungarian เขาใช้ตัวอย่างคำนำหน้าusสำหรับสตริงที่ไม่ปลอดภัยและsสำหรับสตริงที่ปลอดภัย (เข้ารหัส HTML) เพื่อป้องกันการฉีด HTML นักพัฒนาสามารถป้องกันข้อผิดพลาดในการฉีด HTML โดยเพียงแค่ตรวจสอบรหัสและรับรองว่าคำนำหน้าตัวแปรตรงกัน ตัวอย่างของเขาคือ VBScript ซึ่งเป็นภาษาที่ล้าสมัยในตอนนี้ซึ่งไม่อนุญาตให้มีคลาสแบบกำหนดเองในขั้นต้น ในภาษาสมัยใหม่ปัญหาสามารถแก้ไขได้ด้วยประเภทที่กำหนดเองและนี่คือสิ่งที่ Asp.net ทำกับHtmlStringชั้นเรียน วิธีนี้คอมไพเลอร์จะค้นหาข้อผิดพลาดโดยอัตโนมัติซึ่งมีความปลอดภัยมากกว่าที่ต้องใช้การมองดวงตาของมนุษย์ ชัดเจนว่าภาษาที่มีประเภทกำหนดเองไม่จำเป็นต้อง "แอพฮังการี" ในกรณีนี้


2

ใช่แม้ว่าหลายภาษาที่มีระบบพิมพ์ที่แข็งแกร่งเพียงพอ แต่ก็ยังมีปัญหา - การแสดงออกของชนิดใหม่ที่มีพื้นฐานมาจาก / คล้ายกับประเภทที่มีอยู่

เช่นใน langugaes จำนวนมากที่เราสามารถใช้ระบบประเภทได้มากกว่าเราไม่ได้เพราะค่าใช้จ่ายในการสร้างรูปแบบใหม่ที่เป็นแบบเดียวกับประเภทที่มีอยู่นอกเหนือจากชื่อและฟังก์ชั่นการแปลงสองอันนั้นยอดเยี่ยมเกินไป

โดยพื้นฐานแล้วเราต้องการประเภทของคำศัพท์ที่พิมพ์อย่างมากเพื่อฆ่าสัญกรณ์ฮังการีอย่างละเอียดในภาษาเหล่านี้ (U # สไตล์ UoM สามารถทำได้เช่นกัน)


2

โปรดจำไว้ว่ามีบางครั้งที่ IDEs ไม่ได้มีคำแนะนำป๊อปอัปแจ้งให้คุณทราบว่าพวกเขาเป็นตัวแปรชนิดใด มีบางครั้งที่ IDEs ไม่เข้าใจรหัสที่พวกเขาแก้ไขดังนั้นคุณจึงไม่สามารถข้ามจากการใช้งานไปยังการประกาศได้อย่างง่ายดาย นอกจากนี้ยังมีเวลาเมื่อคุณไม่สามารถสร้างชื่อตัวแปรอีกครั้งโดยไม่ต้องผ่านฐานข้อมูลทั้งหมดด้วยตนเองทำการเปลี่ยนแปลงด้วยมือและหวังว่าคุณจะไม่พลาด คุณไม่สามารถใช้การค้นหาและแทนที่เนื่องจากการค้นหาลูกค้ายังทำให้คุณได้รับ CustomerName ...

ย้อนกลับไปในวันที่มืดมนมันเป็นประโยชน์ที่จะรู้ว่าตัวแปรชนิดไหนที่มันถูกใช้ หากได้รับการดูแลอย่างถูกต้อง (ยิ่งใหญ่หากขาดเครื่องมือการปรับโครงสร้างใหม่) สัญกรณ์ฮังการีให้คุณทราบ

ค่าใช้จ่ายในวันนี้ของชื่อที่น่ากลัวที่มันผลิตสูงเกินไป แต่นั่นเป็นสิ่งที่ค่อนข้างใหม่ มีโค้ดจำนวนมากที่ยังคงมีอยู่ซึ่งมีมาก่อนการพัฒนา IDE ที่ฉันได้อธิบายไว้


1
ถ้าฉันไม่เข้าใจผิดนี่เป็นคำตอบอีกข้อหนึ่งที่พูดถึงรูปแบบของฮังการีในรูปแบบอื่นที่แตกต่างจากที่ OP ใช้ถาม
MatrixFrog

2
คำตอบนี้อธิบายสิ่งที่เรียกว่า "Systems Hungarian" ซึ่งคำนำหน้าหมายถึง "ประเภท" ระดับภาษา คำถามถามเกี่ยวกับ "แอพฮังการี" ซึ่งคำว่า "ประเภท" ไม่ได้เข้าใจผิดและหมายถึงประเภทความหมาย ระบบของฮังการีถูกประณามอย่างแพร่หลายเกือบทุกวันนี้ (และถูกต้องเช่นกันมันเป็นการลบล้างความมุ่งหมายที่แท้จริงของเอกสารของฮังการี) แอพ Hungarian อาจเป็นสิ่งที่ดี
cHao

บรรณาธิการมีความสามารถในการค้นหา sCustomer โดยไม่มีการเก็บค่า sCustomerName (vi และ emacs เป็น 2 ตัวอย่าง) มีอยู่ตั้งแต่ 70
Larry Coleman

@ Larry บางที แต่คุณไม่สามารถให้พวกเขาทำงานบนระบบที่ฉันเขียนโปรแกรมใน '80s
mcottle

@cHAo ไม่ไม่ - จุดของฉันพยายามอธิบายว่าทำไมผู้คนใส่ข้อมูลพิเศษลงในชื่อตัวแปรโดยทั่วไป ฉันหลีกเลี่ยงการกล่าวถึงสัญกรณ์ฮังการีทุกรุ่นอย่างรอบคอบ บางทีตัวอย่างที่ฉันให้ไว้ในส่วน "ทำไมการค้นหาและแทนที่ไม่ทำงานบนซอร์สโค้ด" ดูเหมือนคุณชอบ "Systems Hungarian" แต่ไม่ได้มีความหมาย ฉันได้ลบผู้นำ "s" เพื่อหลีกเลี่ยงความสับสน
mcottle

0

แก้ไข!

นอกเหนือจากภาษาที่ไม่ได้พิมพ์อย่างสมบูรณ์เช่น Assembler สัญลักษณ์ของฮังการีนั้นไม่จำเป็นและน่ารำคาญ เพิ่มทวีคูณดังนั้นเมื่อคุณพิจารณาว่า IDEs ส่วนใหญ่ตรวจสอบความปลอดภัยของประเภทในขณะที่คุณเอ้อพิมพ์

"i" "d" และ "พิเศษ" พิเศษ ส่วนนำหน้าทำให้โค้ดอ่านน้อยลงและอาจทำให้เข้าใจผิดอย่างแท้จริง - เมื่อ "cow-orker" เปลี่ยนประเภทของ iaSumsItems จากจำนวนเต็มเป็นยาว แต่ไม่ต้องเปลี่ยนชื่อฟิลด์ใหม่


9
คำตอบของคุณแสดงให้เห็นว่าคุณไม่เข้าใจความแตกต่างระหว่างต้นฉบับ "แอป" ที่ชาญฉลาดของฮังการีและการวางคำใบ้โง่ที่เรียกว่า "ระบบ" อ่านjoelonsoftware.com/articles/Wrong.html
Ryan Culpepper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.