การมีเพศสัมพันธ์กับสตริง“ คลาย” มากกว่าด้วยวิธีการเรียน?


18

ฉันเริ่มโครงการกลุ่มโรงเรียนใน Java โดยใช้ Swing มันเป็น GUI ที่เรียบง่ายบนแอปเดสก์ท็อปฐานข้อมูล

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

ฉันหวังว่าจะหาเหตุผลว่าทำไมระบบของเขาถึงดีหรือไม่ดี (ฉันถามอาจารย์และเขาบอกว่าฉันจะเห็นทีหลังว่าทำไมมันถึงดีกว่าซึ่งไม่พอใจฉัน)

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

เมื่อมีการทริกเกอร์เหตุการณ์มุมมองหรือรูปแบบจะส่งสตริงไปยังสมาชิกทั้งหมดของผู้ตัดสินใจว่าจะทำอย่างไรกับเหตุการณ์นั้น ตัวอย่างเช่นในหนึ่งในวิธีการฟังการกระทำมุมมอง (ฉันเชื่อว่านี่เป็นเพียงการตั้งค่า bicycleMakeField บนวัตถุที่คงอยู่):

    else if(evt.getSource() == bicycleMakeField)
    {
        myRegistry.updateSubscribers("BicycleMake", bicycleMakeField.getText());
    }

ในที่สุดการโทรนั้นถึงวิธีนี้ในโมเดลรถ:

public void stateChangeRequest(String key, Object value) {

            ... bunch of else ifs ...

    else
    if (key.equals("BicycleMake") == true)
    {
                ... do stuff ...

ศาสตราจารย์กล่าวว่าวิธีการทำสิ่งนี้สามารถขยายได้และบำรุงรักษาได้ดีกว่าการมีมุมมองเพียงเรียกวิธีการบนวัตถุทางตรรกะทางธุรกิจ เขาบอกว่าไม่มีการมีเพศสัมพันธ์ระหว่างมุมมองและแบบจำลองเพราะพวกเขาไม่รู้การมีอยู่ของกันและกัน

ฉันคิดว่านี่เป็นข้อต่อที่แย่กว่าเดิมเพราะมุมมองและโมเดลต้องใช้สายอักขระเดียวกันเพื่อใช้งานได้ หากคุณลบมุมมองหรือโมเดลหรือพิมพ์ข้อความในสตริงคุณจะไม่ได้รับข้อผิดพลาดในการรวบรวม นอกจากนี้ยังทำให้รหัสยาวกว่าที่ฉันคิด

ฉันต้องการปรึกษาเรื่องนี้กับเขา แต่เขาใช้ประสบการณ์ในอุตสาหกรรมของเขาเพื่อโต้แย้งการโต้เถียงใด ๆ ที่ฉันนักเรียนมือใหม่อาจทำ มีประโยชน์กับวิธีการของเขาที่ฉันหายไปบาง


เพื่อชี้แจงฉันต้องการเปรียบเทียบวิธีข้างต้นโดยมีมุมมองที่ชัดเจนควบคู่ไปกับโมเดล ตัวอย่างเช่นคุณสามารถส่งผ่านวัตถุรูปแบบยานพาหนะไปยังมุมมองแล้วเปลี่ยน "ทำ" ของยานพาหนะทำสิ่งนี้:

vehicle.make = bicycleMakeField.getText();

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


ปรับปรุง

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


12
OT ฉันคิดว่าอาจารย์ของคุณควรปรับปรุงตัวเองและไม่ใช้รหัสเก่า ในสถาบันการศึกษาไม่มีเหตุผลที่จะใช้รุ่น JAVA ตั้งแต่ปี 2549 เมื่อปี 2555
Farmor

3
โปรดให้เราโพสต์เมื่อคุณได้รับคำตอบในที่สุด
JeffO

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

1
จริง ฉันไม่ได้เรียกพวกเขาว่าสายเวทย์มนตร์ขณะที่พูดกับเขา แต่คุณพูดถูกไม่มีความจำเป็นที่จะต้องทำให้เสียงแย่ไปกว่านี้
Philip

2
วิธีการที่อาจารย์อธิบาย (การแจ้งผู้ฟังผ่านเหตุการณ์ที่มีชื่อเป็นสตริง) อาจเป็นเรื่องดี ที่จริงแล้ว enums อาจทำให้รู้สึกมากขึ้น แต่นี่ไม่ใช่ปัญหาที่ใหญ่ที่สุด ปัญหาจริงที่ฉันเห็นที่นี่คือวัตถุที่ได้รับการแจ้งเตือนนั้นเป็นรุ่นของตัวเองแล้วคุณต้องทำการจัดส่งด้วยตนเองตามประเภทของเหตุการณ์ ในภาษาที่ฟังก์ชั่นเป็นชั้นหนึ่งคุณจะต้องลงทะเบียนฟังก์ชั่นไม่ใช่วัตถุในเหตุการณ์ ใน Java ฉันคิดว่าควรใช้การห่อวัตถุบางชนิดในฟังก์ชั่นเดียว
Andrea

คำตอบ:


32

วิธีการที่อาจารย์เสนอนั้นอธิบายได้ดีที่สุดเมื่อพิมพ์อย่างเข้มงวดและผิดในเกือบทุกระดับ

การมีเพศสัมพันธ์จะลดลงได้ดีที่สุดโดยการพึ่งพาการผกผันซึ่งทำโดยการส่ง polymorphic แทนที่จะเดินสายหลายกรณี


3
คุณเขียนว่า "เกือบทุกระดับ" แต่คุณยังไม่ได้เขียนสาเหตุที่ไม่เหมาะกับตัวอย่าง (ในความคิดของคุณ) คงจะน่าสนใจที่จะรู้
hakre

1
@hakre: ไม่มีกรณีที่เหมาะสมอย่างน้อยใน Java ฉันบอกว่ามัน "ผิดในเกือบทุกระดับ" เพราะมันดีกว่าการไม่ใช้ทางอ้อมเลยและเพียงแค่โยนรหัสทั้งหมดในที่เดียว อย่างไรก็ตามการใช้สตริงมายากล (ทั่วโลก) ยังคงเป็นพื้นฐานสำหรับการจัดส่งด้วยตนเองเป็นเพียงวิธีที่ซับซ้อนในการใช้วัตถุทั่วโลกในที่สุด
back2dos

ดังนั้นข้อโต้แย้งของคุณคือ: ไม่มีกรณีที่เหมาะสมดังนั้นอันนี้ก็ไม่ได้เป็นอย่างนั้นหรือ มันแทบจะเป็นข้อโต้แย้งและไม่ค่อยมีประโยชน์จริงๆ
hakre

1
@hakre: ข้อโต้แย้งของฉันคือว่าวิธีการนี้ไม่ดีด้วยเหตุผลหลายประการ (ย่อหน้า 1 - มีเหตุผลเพียงพอที่จะหลีกเลี่ยงสิ่งนี้ได้ในคำอธิบายของการพิมพ์อย่างเข้มงวด) และไม่ควรใช้เพราะมีดีกว่า (วรรค 2 )
back2dos

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

19

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

เพื่อให้เป็นธรรมกับอาจารย์เขาพยายามที่จะสร้างใน Java สิ่งที่ดูคล้ายกับอินเตอร์เฟส. NET ที่เรียกว่าINotifyPropertyChangedซึ่งแจ้งผู้สมัครสมาชิกของเหตุการณ์การเปลี่ยนแปลงโดยผ่านสตริงที่ระบุว่าทรัพย์สินใดมีการเปลี่ยนแปลง ใน. NET อย่างน้อยที่สุดอินเทอร์เฟซนี้ใช้เพื่อสื่อสารจากตัวแบบข้อมูลเพื่อดูวัตถุและองค์ประกอบ GUI (การรวม) เป็นหลัก

หากทำถูกต้องการใช้วิธีนี้อาจมีประโยชน์บ้าง:

  1. มุมมองขึ้นอยู่กับรุ่น แต่รุ่นไม่จำเป็นต้องขึ้นอยู่กับมุมมอง นี่คือการผกผันของการควบคุมที่เหมาะสม
  2. คุณมีที่เดียวในรหัสมุมมองของคุณที่จัดการการตอบสนองต่อการเปลี่ยนแปลงการแจ้งเตือนจากโมเดลและมีเพียงที่เดียวที่จะสมัคร / ยกเลิกการสมัครลดความน่าจะเป็นของการรั่วไหลของหน่วยความจำอ้างอิงแบบลอย
  3. การเขียนโค้ดมีค่าใช้จ่ายน้อยลงเมื่อคุณต้องการเพิ่มหรือลบกิจกรรมจากผู้เผยแพร่กิจกรรม ใน. NET มีกลไกการเผยแพร่ / สมัครสมาชิกในตัวที่เรียกว่าeventsแต่ใน Java คุณจะต้องสร้างคลาสหรือวัตถุและเขียนรหัสสมัครสมาชิก / ยกเลิกการสมัครสำหรับแต่ละเหตุการณ์
  4. ความล้มเหลวที่ใหญ่ที่สุดด้วยวิธีนี้คือรหัสการสมัครสมาชิกอาจหลุดจากการซิงค์กับโค้ดการประกาศ อย่างไรก็ตามนี่เป็นประโยชน์ในสภาพแวดล้อมการพัฒนาบางอย่าง หากเหตุการณ์ใหม่ได้รับการพัฒนาในรูปแบบและมุมมองยังไม่ได้อัปเดตเพื่อสมัครสมาชิกมุมมองจะยังคงทำงานได้ ในทำนองเดียวกันหากมีการลบกิจกรรมคุณมีรหัสที่ตายแล้ว แต่ก็ยังสามารถรวบรวมและเรียกใช้
  5. ใน. NET อย่างน้อยที่สุด Reflection จะถูกใช้อย่างมีประสิทธิภาพที่นี่เพื่อเรียกใช้ getters และ setters โดยอัตโนมัติขึ้นอยู่กับสตริงที่ส่งผ่านไปยังผู้สมัครสมาชิก

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


¹ค้นหา Google INotifyPropertyChangedเพื่อค้นหาวิธีที่ผู้คนพยายามหลีกเลี่ยงการใช้เวทมนต์เมื่อใช้งาน


ดูเหมือนว่าคุณจะอธิบายสบู่ที่นี่ : D … (แต่ใช่ฉันเข้าใจคุณแล้ว)
Konrad Rudolph

11

enumpublic static final Stringควรใช้s (หรือs) แทน Magic Strings

อาจารย์ของคุณไม่เข้าใจ OO เช่นมีคลาสยานพาหนะคอนกรีต?
และเพื่อให้ชั้นเรียนนี้เข้าใจการทำจักรยาน?

ยานพาหนะควรเป็นนามธรรมและควรมีซับคลาสคอนกรีตที่เรียกว่าไบค์ ฉันจะเล่นตามกฎของเขาเพื่อให้ได้เกรดที่ดีและลืมคำสอนของเขา


3
นอกจากประเด็นของแบบฝึกหัดนี้คือการปรับปรุงโค้ดโดยใช้หลักการ OO ที่ดีขึ้น ในกรณีนั้นให้ทำการรีแฟคเตอร์ออกไป
joshin4colours

2
@ joshin4colours หาก StackExchange ถูกให้คะแนนคุณจะถูกต้อง แต่เนื่องจากนักเรียนระดับประถมเป็นคนคนเดียวกันที่คิดไอเดียว่าเขาจะให้คะแนนไม่ดีกับพวกเราเพราะเขารู้ว่าการติดตั้งของเขานั้นดีกว่า
Dan Neely

7

ฉันคิดว่าคุณมีจุดที่ดีสายเวทนั้นไม่ดี บางคนในทีมของฉันต้องแก้ปัญหาที่เกิดจากสายเวทเมื่อสองสามสัปดาห์ก่อน (แต่มันเป็นรหัสของตัวเองที่พวกเขาเขียนดังนั้นฉันจึงปิดปาก) และมันเกิดขึ้น ... ในอุตสาหกรรม !!

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

ในบริบทนี้ดูเหมือนว่า Enum อาจดีกว่าสายเวทหรือค่าคงที่สตริงทั่วโลก นอกจากนี้ IDEs มักจะให้การจัดเรียงของการช่วยรหัส (ป้อนข้อมูลอัตโนมัติ, refactor, find-all-References, ฯลฯ ... ) เมื่อคุณใช้สตริงคงที่หรือ Enums IDE จะไม่ให้ความช่วยเหลือมากนักหากคุณใช้สายเวท


ฉันยอมรับว่า enums ดีกว่าตัวอักษรสตริง แต่ถึงอย่างนั้นมันจะดีกว่าหรือที่จะเรียกว่า "stateChangeRequest" ด้วยคีย์ enum หรือเพียงแค่เรียกเมธอดบนโมเดลโดยตรง ทั้งสองวิธีโมเดลและมุมมองจะถูกรวมเข้าด้วยกันในจุดเดียว
Philip

@Philip: ถ้าอย่างนั้นผมคิดว่าจะแยกรูปแบบและมุมมองที่จุดที่คุณอาจจำเป็นต้องเรียงลำดับของตัวควบคุมระดับบางอย่างที่จะทำอย่างนั้น ...
FrustratedWithFormsDesigner

@FrustratedWithFormsDesigner - ใช่ สถาปัตยกรรม MVC เป็นโครงสร้างแยกส่วนมากที่สุด
cdeszaq

ใช่ถ้าเลเยอร์อื่นจะช่วยแยกพวกเขาออกฉันจะไม่เถียงกับมัน แต่เลเยอร์นั้นยังคงสามารถพิมพ์แบบสแตติกและใช้วิธีการจริงแทนที่จะเป็นสตริงหรือข้อความ enum เพื่อเชื่อมต่อพวกเขา
Philip

6

การใช้ 'ประสบการณ์อุตสาหกรรม' เป็นข้อโต้แย้งที่ไม่ดี อาจารย์ของคุณจำเป็นต้องมีข้อโต้แย้งที่ดีกว่า :-)

ดังที่คนอื่น ๆ ได้กล่าวไว้การใช้เวทสตริงนั้นขมวดคิ้วอย่างแน่นอนการใช้ enums นั้นถือว่าปลอดภัยกว่า Enum มีความหมายและขอบเขตไม่สามารถใช้เวทมนตร์ได้ นอกจากนั้นวิธีการที่ศาสตราจารย์ของคุณแยกข้อกังวลออกมานั้นถือเป็นเทคนิคที่เก่ากว่าและเปราะบางกว่าที่ใช้ในปัจจุบัน

ฉันเห็นว่า @backtodos ได้กล่าวถึงเรื่องนี้ในขณะที่ฉันตอบคำถามนี้ดังนั้นฉันจะเพิ่มความคิดเห็นของฉันว่าการใช้Inversion of Control (ซึ่งการพึ่งพาการฉีดเป็นแบบฟอร์ม .. ) ถือเป็นวิธีที่ทันสมัยกว่าในการจัดการกับการแยกประเภทนี้


2
นักวิชาการเห็นด้วยอย่างเต็มที่ควรมีความต้องการสูงกว่าอุตสาหกรรม สถาบันการศึกษา == วิธีทางทฤษฎีที่ดีที่สุด; อุตสาหกรรม == วิธีปฏิบัติที่ดีที่สุด
Farmor

3
น่าเสียดายที่บางคนที่สอนสิ่งนี้ในสถาบันการศึกษาทำเช่นนั้นเพราะพวกเขาไม่สามารถตัดมันในอุตสาหกรรม ในทางบวกผู้เรียนบางคนเก่งและไม่ควรซ่อนตัวอยู่ในสำนักงานของ บริษัท
FrustratedWithFormsDesigner

4

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

กลยุทธ์การลด / ประนีประนอมสำหรับ Java สามารถใช้อินเทอร์เฟซที่พิมพ์ได้ แต่ที่อินเทอร์เฟซที่พิมพ์นั้นอยู่ในแพคเกจแยกต่างหาก ควรประกอบด้วยเพียง Java interfaceและประเภทค่าพื้นฐาน (เช่นการแจกแจงข้อยกเว้น) ควรจะมีไม่มีการใช้งานของอินเตอร์เฟซในแพคเกจที่ จากนั้นทุกคนดำเนินการกับสิ่งนั้นและหากจำเป็นต้องถ่ายทอดข้อความด้วยวิธีที่ซับซ้อนการดำเนินงานโดยเฉพาะของผู้ได้รับมอบหมายจาวาสามารถใช้สายเวทได้ตามความจำเป็น นอกจากนี้ยังทำให้การย้ายรหัสไปยังสภาพแวดล้อมแบบมืออาชีพง่ายขึ้นเช่น JEE หรือ OSGi ง่ายขึ้นและช่วยสิ่งเล็ก ๆ น้อย ๆ เช่นการทดสอบ ...


4

สิ่งที่อาจารย์ของคุณเสนอก็คือการใช้ "สายเวท" ในขณะที่มันมีคลาส "คับคู่" ระหว่างกันช่วยให้การเปลี่ยนแปลงง่ายขึ้นมันเป็นรูปแบบการต่อต้าน; สตริงควรมาก, ไม่ค่อยใช้ในการควบคุมหรือคำสั่งรหัส, และเมื่อมันเกิดขึ้นจริง ๆ , ค่าของสตริงที่คุณใช้ในการควบคุมลอจิกควรจะถูกกำหนดจากส่วนกลางและตลอดเวลา สตริงเฉพาะใด ๆ

เหตุผลง่ายมาก สตริงจะไม่ตรวจสอบคอมไพเลอร์สำหรับไวยากรณ์หรือความสอดคล้องกับค่าอื่น ๆ (ที่ดีที่สุดพวกเขากำลังตรวจสอบสำหรับรูปแบบที่เหมาะสมเกี่ยวกับอักขระหลบหนีและการจัดรูปแบบเฉพาะภาษาอื่น ๆ ภายในสตริง) คุณสามารถใส่อะไรก็ได้ที่คุณต้องการในสตริง ดังนั้นคุณสามารถรวบรวมอัลกอริทึม / โปรแกรมที่ไม่สมบูรณ์เพื่อรวบรวมและจะไม่ทำงานจนกว่าจะมีข้อผิดพลาดเกิดขึ้น พิจารณารหัสต่อไปนี้ (C #):

private Dictionary<string, Func<string>> methods;

private void InitDictionary() //called elsewhere
{
   methods = new Dictionary<string, Func<string>> 
      {{"Method1", ()=>doSomething()},
       {"MEthod2", ()=>doSomethingElse()}} //oops, fat-fingered it
}

public string RunMethod(string methodName)
{
   //very naive, but even a check for the key would generate a runtime error, 
   //not a compile-time one.
   return methods[methodName](); 
}

...

//this is what we thought we entered back in InitDictionary for this method...
var result = RunMethod("Method2"); //error; no such key

... ทั้งหมดของรหัสนี้รวบรวมลองครั้งแรก แต่ข้อผิดพลาดที่เห็นได้ชัดด้วยรูปลักษณ์ที่สอง มีตัวอย่างมากมายของการเขียนโปรแกรมประเภทนี้และพวกเขาทั้งหมดอยู่ภายใต้ข้อผิดพลาดประเภทนี้แม้ว่าคุณจะกำหนดสตริงเป็นค่าคงที่ (เนื่องจากค่าคงที่ใน. NET จะถูกเขียนไปยังรายการของแต่ละไลบรารีที่ใช้ จากนั้นทั้งหมดจะถูกคอมไพล์ใหม่เมื่อค่าที่กำหนดถูกเปลี่ยนเพื่อให้ค่าเปลี่ยน "global") เนื่องจากข้อผิดพลาดไม่ได้รับการรวบรวมในเวลานั้นจะต้องถูกตรวจจับในระหว่างการทดสอบแบบรันไทม์และรับประกันได้ว่าจะมีการครอบคลุมโค้ด 100% ในการทดสอบหน่วยที่มีการออกกำลังกายรหัสที่เพียงพอซึ่งมักจะพบได้ใน ระบบเรียลไทม์


2

ที่จริงแล้วชั้นเรียนเหล่านั้นยังคงอยู่คู่กันอย่างแน่นหนา ยกเว้นตอนนี้พวกเขากำลังเชื่อมโยงอย่างแน่นหนาในลักษณะที่คอมไพเลอร์ไม่สามารถบอกคุณได้เมื่อสิ่งต่าง ๆ พัง!

หากใครบางคนเปลี่ยน "BicycleMake" เป็น "BicyclesMake" ก็ไม่มีใครจะพบว่าสิ่งต่าง ๆ จะพังจนรันไทม์

ข้อผิดพลาดรันไทม์เป็นวิธีที่มีค่าใช้จ่ายในการแก้ไขมากกว่าข้อผิดพลาดในการรวบรวมเวลา - นี่เป็นเพียงความชั่วร้ายทุกชนิด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.