การเขียนโค้ดที่มีประสิทธิภาพเทียบกับการใช้งานเกินกำลัง


33

พวกคุณรู้ได้อย่างไรว่าคุณกำลังเขียนโค้ดที่แข็งแกร่งที่สุดเท่าที่จะเป็นไปได้

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


2
เขียนโค้ดใน Agda2
SK-logic

ตัวอย่างที่เป็นรูปธรรมจะช่วยชี้ประเด็นของคุณอย่างมาก :)
João Portela

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

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

1
นี่คือบทความที่พูดถึงเกี่ยวกับเรื่องนี้: code-tag.com/2017/04/02/…
San

คำตอบ:


39

พวกคุณรู้ได้อย่างไรว่าคุณกำลังเขียนโค้ดที่แข็งแกร่งที่สุดเท่าที่จะเป็นไปได้

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

ฉันทำตามหลักการต่าง ๆ : อันดับแรกและสำคัญที่สุดYAGNI (ยัง) และKISSดังนั้นฉันจึงไม่เขียนโค้ดที่ไม่จำเป็น ที่มีประสิทธิภาพยังช่วยป้องกันไม่ให้ overengineering ฉัน refactor แอปพลิเคชันเมื่อต้องการส่วนขยาย เครื่องมือการเปลี่ยนโฉมใหม่ช่วยให้คุณสามารถสร้างส่วนต่อประสานและแลกเปลี่ยนการใช้งานได้ง่ายในภายหลังเมื่อคุณต้องการ

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

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

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

ความเรียบง่ายนั้นแข็งแกร่งความซับซ้อนนั้นเปราะบาง

ความซับซ้อนฆ่า


2
เพราะมันไม่มีคลาสโรงงานและนามธรรมมากมาย มันเป็นสิ่งที่ผิดธรรมดา แต่บางคนก็ชอบสิ่งนั้น ไม่รู้ว่าทำไม
Coder

5
นี่คือสปาร์ตา!!!
Tom Squires

4
คนที่ไม่ได้ทำสิ่งนี้มายี่สิบปีก็ไม่ได้รับความซับซ้อนที่สามารถฆ่าคุณได้ พวกเขาคิดว่าพวกเขาฉลาด พวกเขาไม่ฉลาดไม่ฉลาด ความซับซ้อนนั้นกำลังจะฆ่าคุณตาย
PeterAllenWebb

1
ความทนทานไม่ได้เกี่ยวกับการพิสูจน์ในอนาคต - มันเกี่ยวกับการทำงานอย่างต่อเนื่องกับอินพุตที่ไม่ถูกต้องหรือสภาพแวดล้อมที่เครียด - รหัสสมบูรณ์ p464
DJClayworth

5
หากผู้ถามใช้ 'แข็งแกร่ง' ในแง่ที่แตกต่างจากที่ฉันเข้าใจคุณกำลังตอบคำถามอื่น เขาไม่ได้ถามว่า "ฉันควรรหัสเพื่ออนุญาตสำหรับข้อกำหนดในอนาคต" เขากำลังถามว่า ไม่มีของ YAGNI, KISS และ SOLID ที่เกี่ยวข้อง คุณต้องการอนุญาตให้ผู้ใช้หลายล้านคนพยายามเข้าสู่ระบบพร้อมกันหรือไม่? จะเกิดอะไรขึ้นถ้าชื่อล็อกอินเริ่มต้นด้วยแบ็กสแลช YAGNI ไม่ตอบคำถามเหล่านี้
DJClayworth

8

ฉันพยายามรักษาสมดุลโดยมุ่งเน้นที่

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

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


ตัวอย่างจะดีที่นี่จัดการเส้นทางการดำเนินการที่เป็นไปได้ทั้งหมดในกรณีการใช้งานที่มีอยู่
CodeYogi

5

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

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


4

1) รับข้อกำหนด

2) เขียนรหัสขั้นต่ำเพื่อตอบสนองความต้องการ หากสิ่งที่คลุมเครือให้คาดเดาการศึกษา ถ้ามันเป็นซุปเปอร์คลุมเครือกลับไป 1

3) ส่งไปทดสอบ

4) หากผู้ทดสอบพูดว่าดีให้จัดทำเอกสารอนุมัติ หากสิ่งที่ปิดไปกลับไปที่ 1

มุ่งเน้นไปที่การทดสอบที่ผ่านไม่คาดการณ์การทดสอบ หากคุณไม่มีผู้ทดสอบ ... รับผู้ทดสอบ! พวกเขามีความสำคัญไม่เพียง แต่เพื่อตรวจสอบความถูกต้องของรหัส แต่ยังรวมถึงกระบวนการพัฒนา


1
+1 สำหรับการมุ่งเน้นที่การทดสอบที่ผ่านการคาดคะเนการทดสอบอย่างไรก็ตามนักพัฒนาหลายคนอย่างผมคาดว่าจะทำทั้งสองอย่างอย่างไรก็ตามในการขาดนักวิเคราะห์ธุรกิจที่แข็งแกร่ง
maple_shaft

@maple_shaft - จริงมาก ประเด็นก็คือปัญหาเหล่านี้เกิดขึ้นเพราะความไร้ความสามารถของคนอื่น การย้ำกับงานของคนอื่นคือเส้นทางที่เหนื่อยหน่าย หาก บริษัท ของฉันเป็นใบ้พอที่จะให้ฉันทำบัญชีลูกหนี้สำหรับเดือนฉันจะไม่ผิดหวังมากเกินไปในตัวเองถ้ามันไม่ดี การกำหนดความต้องการมักจะหมายถึงการอธิบายสิ่งที่คุณทำทุกวันเพื่อให้เป็นไปโดยอัตโนมัติ หากไม่มีพนักงานคนใดที่สามารถทำสิ่งนั้นได้ดี ... บริษัท อาจประสบปัญหา
Morgan Herlocker

3

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

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

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

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

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


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

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

การทดสอบของคุณจะต้องกำหนดความสามารถของโปรแกรมและความแข็งแกร่งของมัน - เพิ่มการทดสอบจนกว่าคุณจะพอใจกับอัตราความสำเร็จและอินพุต การปรับปรุงการขยายและการเสริมสร้างตามต้องการ


2

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


2

ความทนทาน: ระดับที่ระบบยังคงทำงานต่อเมื่อมีอินพุตไม่ถูกต้องหรือสภาวะแวดล้อมที่ตึงเครียด (รหัสสมบูรณ์ 2, p464)

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

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

ดังนั้นจึงเป็นการดีกว่าที่จะทำผิดด้านการตรวจสอบข้อผิดพลาดที่ผิดปกติ แต่มีความสมดุล บางสิ่งที่ควรพิจารณาในสมดุลนี้:

  • ข้อผิดพลาดนี้อาจเกิดขึ้นบ่อยแค่ไหน?
  • ค่าใช้จ่ายของการมีข้อผิดพลาดนี้เกิดขึ้นคืออะไร?
  • นี่สำหรับใช้ภายในหรือภายนอก?

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

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

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