ฉันได้ยินเสียงพูดว่าการตรวจสอบค่า Null ที่คืนกลับมาจากวิธีการคือการออกแบบที่ไม่ดี ฉันต้องการฟังเหตุผลบางอย่างสำหรับเรื่องนี้
pseudocode:
variable x = object.method()
if (x is null) do something
ฉันได้ยินเสียงพูดว่าการตรวจสอบค่า Null ที่คืนกลับมาจากวิธีการคือการออกแบบที่ไม่ดี ฉันต้องการฟังเหตุผลบางอย่างสำหรับเรื่องนี้
pseudocode:
variable x = object.method()
if (x is null) do something
คำตอบ:
เหตุผลเบื้องหลังการไม่ส่งคืนค่า Null คือคุณไม่จำเป็นต้องตรวจสอบและด้วยเหตุนี้รหัสของคุณจึงไม่จำเป็นต้องทำตามเส้นทางที่ต่างออกไปตามค่าที่ส่งคืน คุณอาจต้องการตรวจสอบNull Object Patternซึ่งให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งนี้
ตัวอย่างเช่นถ้าฉันต้องกำหนดวิธีการใน Java ที่ส่งคืนคอลเลกชันฉันมักจะต้องการคืนคอลเลกชันที่ว่างเปล่า (เช่นCollections.emptyList()
) แทนที่จะเป็นโมฆะเพราะมันหมายความว่ารหัสลูกค้าของฉันสะอาด เช่น
Collection<? extends Item> c = getItems(); // Will never return null.
for (Item item : c) { // Will not enter the loop if c is empty.
// Process item.
}
... ซึ่งสะอาดกว่า:
Collection<? extends Item> c = getItems(); // Could potentially return null.
// Two possible code paths now so harder to test.
if (c != null) {
for (Item item : c) {
// Process item.
}
}
null
"คอนเทนเนอร์" ซึ่งมีศูนย์หรือหนึ่งพอยน์เตอร์ไปยังวัตถุ (แน่นอนว่ามันเป็นแบบอย่างที่ชัดเจนของ Haskell Maybe
ในกรณีเหล่านั้นและเป็นสิ่งที่ดีกว่าสำหรับการทำเช่นนั้น)
นี่คือเหตุผล
ในClean Code ของ Robert Martinเขาเขียนว่าการคืนค่า Null เป็นการออกแบบที่ไม่ดีเมื่อคุณกลับมาพูดแทนอาเรย์ที่ว่างเปล่า เนื่องจากผลลัพธ์ที่คาดไว้เป็นอาร์เรย์ทำไมไม่ มันจะช่วยให้คุณสามารถวนซ้ำผลโดยไม่มีเงื่อนไขพิเศษใด ๆ ถ้าเป็นจำนวนเต็มอาจเป็น 0 พอหากเป็นแฮแฮเปล่าเปล่า เป็นต้น
หลักฐานคือการไม่บังคับให้มีการเรียกรหัสเพื่อจัดการกับปัญหาในทันที รหัสการโทรอาจไม่ต้องการเกี่ยวข้องกับตัวเอง นั่นเป็นเหตุผลว่าทำไมในหลาย ๆ กรณีข้อยกเว้นดีกว่าไม่มี
ใช้กลับคืนเป็นโมฆะ:
การใช้ไม่ถูกต้อง: พยายามแทนที่หรือซ่อนสถานการณ์พิเศษเช่น:
ในกรณีเหล่านั้นการโยนข้อยกเว้นมีความเพียงพอมากกว่าเนื่องจาก:
อย่างไรก็ตามไม่ควรใช้ข้อยกเว้นเพื่อจัดการกับเงื่อนไขการทำงานของโปรแกรมเช่น:
boolean login(String,String)
ดูเหมือนดีและเป็นเช่นนั้นAuthenticationContext createAuthContext(String,String) throws AuthenticationException
ใช่การคืนค่า NULL นั้นเป็นการออกแบบที่แย่มากในโลกแห่งวัตถุ สรุปการใช้งาน NULL นำไปสู่:
ตรวจสอบการโพสต์บล็อกนี้สำหรับคำอธิบายรายละเอียด: http://www.yegor256.com/2014/05/13/why-null-is-bad.html เพิ่มเติมในหนังสือของฉันวัตถุสุดหรูมาตรา 4.1
bool TryGetBlah(out blah)
หรือหรือFirstOrNull()
MatchOrFallback(T fallbackValue)
isEmpty()
) และเฉพาะในกรณีที่มันเป็นจริงแล้วเรียกวิธีการ ผู้คนโต้แย้งกับคนที่ 2 ว่ามันแย่กว่าประสิทธิภาพ - แต่อย่างที่ Unix Philosophy บอกว่า "ให้คุณค่ากับเวลาของมนุษย์ในช่วงเวลาของเครื่องจักร" (เช่นประสิทธิภาพที่ช้ากว่าเล็กน้อยทำให้เสียเวลาน้อยกว่านักพัฒนาที่ดีบั๊ก
ใครบอกว่านี่คือการออกแบบที่ไม่ดี?
การตรวจสอบ nulls เป็นวิธีปฏิบัติทั่วไปที่ได้รับการสนับสนุนไม่เช่นนั้นคุณจะเสี่ยงต่อ NullReferenceExceptions ทุกที่ มันจะดีกว่าที่จะจัดการกับข้อผิดพลาดอย่างสง่างามกว่าการโยนข้อยกเว้นเมื่อคุณไม่ต้องการ
จากสิ่งที่คุณพูดจนถึงตอนนี้ฉันคิดว่ามีข้อมูลไม่เพียงพอ
การคืนค่า null จากเมธอด CreateWidget () นั้นไม่ดี
กลับมาเป็นโมฆะจากวิธี FindFooInBar ()
Create...
ผลตอบแทนอินสแตนซ์ใหม่หรือพ่น ; Get...
ผลตอบแทนที่เป็นตัวอย่างที่มีอยู่คาดว่าจะได้หรือพ่น ; GetOrCreate...
ส่งคืนอินสแตนซ์ที่มีอยู่หรืออินสแตนซ์ใหม่หากไม่มีอยู่จริงหรือส่งออกไป Find...
ผลตอบแทนที่เป็นตัวอย่างที่มีอยู่ถ้ามันมีอยู่แล้วหรือ null
สำหรับข้อความค้นหาการรวบรวม - Get...
ส่งคืนคอลเล็กชันเสมอซึ่งจะว่างถ้าไม่พบรายการที่ตรงกัน
นักประดิษฐ์กล่าวว่าเป็นความผิดพลาดพันล้านดอลลาร์!
ขึ้นอยู่กับภาษาที่คุณใช้ หากคุณอยู่ในภาษาอย่าง C # ซึ่งเป็นวิธีที่บ่งบอกถึงการขาดค่าคือการคืนค่า null การคืนค่า null นั้นเป็นการออกแบบที่ดีถ้าคุณไม่มีค่า อีกทางเลือกหนึ่งในภาษาเช่น Haskell ซึ่งใช้บางทีอาจเป็น monad สำหรับกรณีนี้การส่งคืน null จะเป็นการออกแบบที่ไม่ดี (ถ้าเป็นไปได้)
null
ภาษาเช่น C # และ Java มักจะโหลดมากเกินไปและให้ความหมายบางอย่างในโดเมน หากคุณค้นหาnull
คำหลักในข้อกำหนดภาษามันก็หมายถึง "ตัวชี้ที่ไม่ถูกต้อง" น่าจะหมายความว่าไม่มีอะไรในโดเมนที่มีปัญหา
null
หรือ "ไม่เริ่มต้น"null
หากคุณอ่านคำตอบทั้งหมดคำตอบของคำถามนี้จะชัดเจนขึ้นอยู่กับประเภทของวิธีการ
ประการแรกเมื่อมีสิ่งผิดปกติเกิดขึ้น (IOproblem ฯลฯ ) ข้อยกเว้นเชิงตรรกะจะถูกโยน เมื่อบางสิ่งบางอย่างที่พิเศษอาจเป็นสิ่งที่แตกต่างสำหรับหัวข้อ ...
เมื่อใดก็ตามที่วิธีการที่คาดว่าจะไม่มีผลลัพธ์มีสองหมวดหมู่:
จนกว่าเราจะมีวิธีอย่างเป็นทางการในการแสดงว่าฟังก์ชั่นสามารถหรือไม่สามารถคืนค่าว่างเปล่าได้ฉันพยายามใช้หลักการตั้งชื่อเพื่อแสดงว่า
เช่นเดียวกับที่คุณมีการประชุมTry Something ()สำหรับวิธีการที่คาดว่าจะล้มเหลวฉันมักจะตั้งชื่อวิธีของฉันSafe Something ()เมื่อวิธีส่งคืนผลลัพธ์ที่เป็นกลางแทนที่จะเป็นโมฆะ
ฉันยังไม่ตกลงกับชื่ออย่างเต็มที่ แต่ก็ไม่สามารถคิดอะไรดีขึ้นได้ ดังนั้นตอนนี้ฉันก็วิ่งไปด้วย
ฉันมีการประชุมในพื้นที่นี้ที่ให้บริการฉันดี
สำหรับการค้นหารายการเดียว:
Create...
ส่งคืนอินสแตนซ์ใหม่หรือส่งGet...
ส่งคืนอินสแตนซ์ที่มีอยู่ที่คาดไว้หรือส่งกลับGetOrCreate...
ส่งคืนอินสแตนซ์ที่มีอยู่หรืออินสแตนซ์ใหม่หากไม่มีอยู่หรือส่งFind...
ส่งคืนอินสแตนซ์ที่มีอยู่หากมีอยู่หรือnull
สำหรับข้อความค้นหาคอลเลกชัน:
Get...
ส่งคืนคอลเล็กชันเสมอซึ่งจะว่างถ้าไม่พบรายการ [1] ที่ตรงกัน[1] ให้เกณฑ์บางอย่างชัดเจนหรือโดยนัยกำหนดในชื่อฟังก์ชั่นหรือเป็นพารามิเตอร์
Get
เมื่อฉันคาดหวังว่ามันจะอยู่ที่นั่นเพื่อที่ว่าถ้ามันไม่ได้อยู่ที่นั่นแล้วมันเป็นข้อผิดพลาดและฉันโยน - ฉันไม่จำเป็นต้องตรวจสอบค่าตอบแทน ฉันใช้Find
ถ้าฉันไม่รู้ว่ามันอยู่ที่นั่นจริงหรือเปล่า - ฉันต้องตรวจสอบค่าส่งคืน
ข้อยกเว้นสำหรับข้อยกเว้น al สถานการณ์
หากฟังก์ชันของคุณมีวัตถุประสงค์เพื่อค้นหาแอตทริบิวต์ที่เกี่ยวข้องกับวัตถุที่กำหนดและวัตถุนั้นไม่มีแอตทริบิวต์ดังกล่าวอาจเป็นการเหมาะสมที่จะส่งคืน null หากวัตถุนั้นไม่มีอยู่การโยนข้อยกเว้นอาจเหมาะสมกว่า ถ้าฟังก์ชั่นนั้นมีความหมายที่จะส่งคืนรายการของคุณสมบัติและไม่มีใครที่จะกลับมาการส่งคืนรายการเปล่านั้นสมเหตุสมผล - คุณจะคืนค่าแอตทริบิวต์ที่เป็นศูนย์ทั้งหมด
ไม่เป็นไรที่จะคืนค่าว่างถ้าการทำเช่นนั้นมีความหมายในทางใดทางหนึ่ง:
public String getEmployeeName(int id){ ..}
ในกรณีเช่นนี้การส่งคืนค่าว่างหากรหัสไม่ตรงกับเอนทิตีที่มีอยู่เนื่องจากคุณสามารถแยกแยะกรณีที่ไม่พบการจับคู่จากข้อผิดพลาดที่ถูกกฎหมาย
ผู้คนอาจคิดว่านี่เป็นสิ่งที่ไม่ดีเพราะสามารถถูกทารุณกรรมเป็นค่าตอบแทน "พิเศษ" ที่บ่งบอกถึงเงื่อนไขข้อผิดพลาดซึ่งไม่ดีนักเช่นการส่งคืนรหัสข้อผิดพลาดจากฟังก์ชัน แต่สับสนเพราะผู้ใช้ต้องตรวจสอบการส่งคืน ว่างเปล่าแทนที่จะจับข้อยกเว้นที่เหมาะสมเช่น
public Integer getId(...){
try{ ... ; return id; }
catch(Exception e){ return null;}
}
ไม่จำเป็นต้องเป็นการออกแบบที่ไม่ดี - เช่นเดียวกับการตัดสินใจในการออกแบบจำนวนมาก
หากผลลัพธ์ของเมธอดเป็นสิ่งที่ไม่น่าจะมีผลดีในการใช้งานปกติการคืนค่าว่างจะไม่เป็นผล:
object x = GetObjectFromCache(); // return null if it's not in the cache
หากควรจะมีผลลัพธ์ที่ไม่เป็นโมฆะจริง ๆ ก็อาจจะดีกว่าที่จะโยนข้อยกเว้น:
try {
Controller c = GetController(); // the controller object is central to
// the application. If we don't get one,
// we're fubar
// it's likely that it's OK to not have the try/catch since you won't
// be able to really handle the problem here
}
catch /* ... */ {
}
Optional<>
สำหรับบางสถานการณ์คุณต้องการที่จะสังเกตเห็นความล้มเหลวทันทีที่มันเกิดขึ้น
การตรวจสอบ NULL และไม่ยืนยัน (สำหรับข้อผิดพลาดของโปรแกรมเมอร์) หรือการโยน (สำหรับข้อผิดพลาดของผู้ใช้หรือผู้โทร) ในกรณีความล้มเหลวอาจหมายความว่าการล่มภายหลังนั้นยากที่จะติดตามเพราะกรณีแปลกเดิมไม่พบ
ยิ่งกว่านั้นการละเลยข้อผิดพลาดอาจนำไปสู่การหาประโยชน์ด้านความปลอดภัย บางทีความว่างเปล่าอาจมาจากความจริงที่ว่าบัฟเฟอร์ถูกเขียนทับหรือคล้ายกัน ตอนนี้คุณไม่ได้หยุดทำงานซึ่งหมายความว่าผู้ใช้มีโอกาสที่จะรันในโค้ดของคุณ
ทางเลือกใดที่คุณเห็นว่าส่งคืนค่าว่าง
ฉันเห็นสองกรณี:
ในกรณีนี้เราสามารถ: คืนค่าว่างเปล่าหรือโยนข้อยกเว้น (ทำเครื่องหมาย) (หรืออาจจะสร้างไอเท็มและส่งคืน)
ในกรณีนี้เราสามารถคืนค่า Null คืนค่าว่างหรือส่งข้อยกเว้น
ฉันเชื่อว่าผลตอบแทนที่เป็นโมฆะอาจน้อยกว่าทางเลือกเนื่องจากลูกค้าต้องการให้จำการตรวจสอบค่า Null, โปรแกรมเมอร์ลืมรหัสและ
x = find();
x.getField(); // bang null pointer exception
ใน Java การโยนข้อยกเว้นที่ตรวจสอบแล้ว RecordNotFoundException อนุญาตให้คอมไพเลอร์เตือนลูกค้าให้จัดการกรณีและปัญหา
ฉันพบว่าการค้นหาที่ส่งคืนรายการว่างสามารถทำได้ค่อนข้างสะดวก - เพียงเติมการแสดงผลด้วยเนื้อหาทั้งหมดของรายการโอ้มันว่างเปล่ารหัส "ใช้งานได้"
บางครั้งการส่งคืนค่า NULL เป็นสิ่งที่ถูกต้อง แต่โดยเฉพาะเมื่อคุณจัดการกับลำดับที่แตกต่างกัน (อาร์เรย์, รายการ, สตริง, สิ่งที่มีคุณ) น่าจะดีกว่าที่จะส่งคืนลำดับความยาวเป็นศูนย์ นำไปสู่รหัสที่สั้นลงและเข้าใจได้มากขึ้นในขณะที่ไม่เขียนส่วนของตัวดำเนินการ API มากขึ้น
ทำให้พวกเขาเรียกวิธีอื่นหลังจากข้อเท็จจริงที่จะคิดออกว่าสายก่อนหน้านี้เป็นโมฆะ ;-) เฮ้มันก็ดีพอสำหรับ JDBC
แนวคิดพื้นฐานที่อยู่เบื้องหลังเธรดนี้คือการตั้งโปรแกรมป้องกัน นั่นคือรหัสต่อสิ่งที่ไม่คาดคิด มีอาร์เรย์ของคำตอบต่าง ๆ :
Adamskiแนะนำให้ดูที่รูปแบบวัตถุ Null โดยการตอบนั้นถูกโหวตให้กับคำแนะนำนั้น
Michael Valentyยังแนะนำการตั้งชื่อเพื่อบอกผู้พัฒนาถึงสิ่งที่คาดหวัง ZeroConceptแนะนำให้ใช้ Exception อย่างถูกต้องหากเป็นเหตุผลของ NULL และคนอื่น ๆ.
หากเราทำให้ "กฎ" ที่เราต้องการทำโปรแกรมป้องกันอยู่เสมอเราจะเห็นว่าคำแนะนำเหล่านี้ถูกต้อง
แต่เรามีสถานการณ์การพัฒนา 2 สถานการณ์
คลาส "ผู้สร้าง" โดยนักพัฒนา: ผู้แต่ง
คลาส "ถูกใช้" โดยผู้พัฒนารายอื่น (อาจ): ผู้พัฒนา
ไม่ว่าคลาสจะคืนค่า NULL สำหรับเมธอดที่มีค่าส่งคืนหรือไม่ก็ตามผู้พัฒนาจะต้องทดสอบว่าวัตถุนั้นถูกต้องหรือไม่
หากผู้พัฒนาไม่สามารถทำเช่นนี้แสดงว่าคลาส / วิธีการนั้นไม่ได้กำหนดไว้ นั่นคือถ้า "การเรียกเมธอด" เพื่อให้วัตถุไม่ได้ทำในสิ่งที่ "โฆษณา" (เช่น getEmployee) จะทำให้สัญญาเสียหาย
ในฐานะผู้เขียนชั้นเรียนฉันมักจะต้องการความใจดีและการป้องกัน (และกำหนดขึ้น) ตลอดเวลาเมื่อสร้างวิธีการ
ดังนั้นเมื่อใดก็ตามที่ NULL หรือ NULL OBJECT (เช่นถ้า (พนักงานเป็น NullEmployee.ISVALID)) จำเป็นต้องได้รับการตรวจสอบและอาจต้องเกิดขึ้นกับกลุ่มของพนักงานดังนั้นวิธีการ null จึงเป็นวิธีที่ดีกว่า
แต่ฉันก็ชอบคำแนะนำของMichael Valenty ในการตั้งชื่อวิธีที่ต้องส่งคืน null เช่น getEmployeeOrNull
ผู้เขียนที่ส่งข้อยกเว้นคือลบตัวเลือกสำหรับผู้พัฒนาเพื่อทดสอบความถูกต้องของวัตถุซึ่งไม่ดีมากในการรวบรวมวัตถุและบังคับให้ผู้พัฒนาเข้าสู่การจัดการข้อยกเว้นเมื่อแยกรหัสการบริโภคของตน
ในฐานะนักพัฒนาที่ใช้คลาสฉันหวังว่าผู้เขียนจะให้ความสามารถในการหลีกเลี่ยงหรือตั้งโปรแกรมสำหรับสถานการณ์ว่างที่อาจเกิดขึ้นกับคลาส / วิธีการของพวกเขา
ดังนั้นในฐานะนักพัฒนาฉันจะตั้งโปรแกรมป้องกัน NULL จากวิธีการ หากผู้เขียนได้ให้สัญญาที่ส่งกลับวัตถุเสมอ (วัตถุ NULL ทำเสมอ) และวัตถุนั้นมีวิธีการ / คุณสมบัติที่ใช้ในการทดสอบความถูกต้องของวัตถุดังนั้นฉันจะใช้วิธี / คุณสมบัติเพื่อดำเนินการใช้วัตถุต่อไป มิฉะนั้นวัตถุนั้นไม่ถูกต้องและฉันไม่สามารถใช้ได้
บรรทัดล่างคือว่าผู้เขียนของคลาส / วิธีการต้องมีกลไกที่นักพัฒนาสามารถใช้ในการเขียนโปรแกรมการป้องกันของพวกเขา นั่นคือความตั้งใจที่ชัดเจนของวิธีการ
นักพัฒนาควรใช้การเขียนโปรแกรมป้องกันเพื่อทดสอบความถูกต้องของวัตถุที่ส่งคืนจากคลาส / วิธีอื่น
ความนับถือ
GregJF
ตัวเลือกอื่น ๆ สำหรับสิ่งนี้คือ: คืนค่าบางอย่างที่บ่งชี้ความสำเร็จหรือไม่ (หรือประเภทของข้อผิดพลาด) แต่ถ้าคุณเพียงแค่ต้องการค่าบูลีนที่จะบ่งชี้ความสำเร็จ / ล้มเหลวกลับมาเป็นโมฆะสำหรับความล้มเหลว ให้ถูกต้องน้อยลงจากนั้นส่งคืนจริง / เท็จและรับวัตถุผ่านพารามิเตอร์
วิธีอื่น ๆ ที่จะใช้ข้อยกเว้นเพื่อบ่งบอกถึงความล้มเหลว แต่ที่นี่ - มีอีกหลายเสียงที่บอกว่านี่เป็นแนวทางปฏิบัติที่ไม่ดี (การใช้ข้อยกเว้นอาจสะดวกและมีข้อเสียมากมาย)
ดังนั้นฉันเองไม่เห็นสิ่งใดที่ไม่ดีในการคืนค่า null เป็นตัวบ่งชี้ว่ามีบางอย่างผิดปกติและตรวจสอบในภายหลัง (เพื่อทราบว่าคุณประสบความสำเร็จจริงหรือไม่) นอกจากนี้สุ่มสี่สุ่มห้าคิดว่าวิธีการของคุณจะไม่ส่งกลับค่า NULL แล้วฐานรหัสของคุณบนมันอาจนำไปสู่อื่น ๆ บางครั้งยากที่จะหาข้อผิดพลาด (แม้ว่าในกรณีส่วนใหญ่มันก็จะผิดพลาดระบบของคุณ :) ตามที่คุณอ้างอิง 0x00000000 ไม่ช้าก็เร็ว)
ฟังก์ชั่นโมฆะที่ไม่ได้ตั้งใจสามารถเกิดขึ้นได้ในระหว่างการพัฒนาโปรแกรมที่มีความซับซ้อนและเช่นเดียวกับโค้ดที่ตายแล้วเหตุการณ์เช่นนี้บ่งชี้ข้อบกพร่องร้ายแรงในโครงสร้างของโปรแกรม
ฟังก์ชั่นโมฆะหรือวิธีการที่มักจะใช้เป็นพฤติกรรมเริ่มต้นของฟังก์ชั่น revectorable หรือวิธีการแทนที่ในกรอบวัตถุ
แน่นอนว่าขึ้นอยู่กับจุดประสงค์ของวิธีการ ... บางครั้งทางเลือกที่ดีกว่าคือการยกเว้น ทุกอย่างขึ้นอยู่กับกรณี
หากรหัสเป็นสิ่งที่ชอบ:
command = get_something_to_do()
if command: # if not Null
command.execute()
หากคุณมีวัตถุจำลองที่มีวิธีการ execute () ไม่ทำอะไรเลยและคุณคืนค่านั้นแทน Null ในกรณีที่เหมาะสมคุณไม่ต้องตรวจสอบกรณี Null และสามารถทำได้เพียง:
get_something_to_do().execute()
ดังนั้นที่นี่ปัญหาไม่ได้อยู่ระหว่างการตรวจสอบค่า NULL เทียบกับข้อยกเว้น แต่แทนที่จะเป็นระหว่างผู้โทรต้องจัดการกับกรณีที่ไม่พิเศษต่างกัน (ไม่ว่าในทางใด) หรือไม่
สำหรับกรณีการใช้งานของฉันฉันจำเป็นต้องส่งคืนแผนที่จากเมธอดจากนั้นมองหาคีย์เฉพาะ แต่ถ้าฉันคืนค่าแผนที่ที่ว่างเปล่ามันจะนำไปสู่ NullPointerException และจากนั้นจะไม่แตกต่างจาก null ที่ส่งคืนแทนที่จะเป็นแผนที่ที่ว่างเปล่า แต่จาก Java8 เป็นต้นไปเราสามารถใช้ตัวเลือก ข้างต้นคือเหตุผลที่แนะนำแนวคิดเพิ่มเติม
G'day,
การส่งคืนค่า NULL เมื่อคุณไม่สามารถสร้างออบเจ็กต์ใหม่เป็นแบบฝึกหัดมาตรฐานสำหรับ API จำนวนมาก
ทำไมนรกมันออกแบบไม่ดีฉันไม่มีความคิด
แก้ไข:สิ่งนี้เป็นจริงของภาษาที่คุณไม่มีข้อยกเว้นเช่น C ซึ่งเป็นแบบแผนมาหลายปี
HTH
'Avahappy,