เทคนิคการเขียนโปรแกรมมากเกินไปหรือถูกทารุณกรรม [ปิด]


38

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

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


33
ฉันยอมรับว่า IE ใช้วิธีการใช้งานมากเกินกว่าที่ควรจะเป็น แต่เป็นหลักโดยผู้ที่ไม่ใช่โปรแกรมเมอร์ . .
Eric Wilson

7
@FarmBoy - ฉันคิดว่าเขาหมายถึง IE: "Ie" ย่อมาจาก "นั่นคือ" ซึ่งเขียนอย่างเต็มที่ในภาษาละตินคือ 'id est'
กราฟิลส์

แก้ไขได้แล้วตอนนี้ :)
Anto

4
เทคนิคใด ๆ ที่สามารถ (และมักจะถูกทารุณกรรม) ก็จะต้องมีการนำเสนอเป็นกระสุนเงินถัดไปและคุณจะพบว่าคนที่ปฏิบัติต่อทุกปัญหาเป็นเล็บ (เพื่อผสมคำอุปมาอุปมัย)
ChrisF

8
@Rapheal - ฉันล้อเล่นแน่นอน ขอบคุณสำหรับการศึกษา
Eric Wilson

คำตอบ:


73

ความคิดเห็นในรหัส

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

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


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

24
@ Woot4Moo: หากคุณอ่านClean CodeFowler ระบุอย่างชัดเจนว่าเอกสารที่ล้าสมัยนั้นแย่กว่าไม่มีเอกสารประกอบและความคิดเห็นทั้งหมดมีแนวโน้มที่จะกลายเป็นเก่าและโยกย้ายออกไปจากรหัสที่เอกสารนั้นทำ หนังสือเล่มนั้นคือทั้งหมดที่เกี่ยวกับวิธีการเขียนรหัสการจัดทำเอกสารด้วยตนเอง
Scott Whitlock

12
การสอนพวกเขาให้เปลี่ยนความคิดเห็นด้วยรหัสเป็นการเริ่มต้นที่ดี ...
Shog9

15
+1 ฉันได้เห็นสิ่งต่อไปนี้ในรหัสโลกแห่งความจริง: "loopVar ++; // increment loopVar" AAAAAAAAAAAAARRRRRGH!
Bobby Tables

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

57

รูปแบบการออกแบบเดี่ยว

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


ฉันใช้ข้อแก้ตัวที่ได้รับการออกแบบมาไม่ดีสำหรับกรอบทุกวัน codeigniter.com/user_guide/libraries/email.htmlพวกเขาคิด OOP เป็น prefixing $this->ฟังก์ชั่นที่มี PHP เป็นภาษาที่เน่าเสียดังนั้นฉันไม่สามารถคาดหวังได้ว่ากรอบงานจะยอดเยี่ยม
Keyo

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

2
ฉันใช้งานซิงเกิลตันครั้งเดียวในอาชีพการงานของฉัน (ในหลายบริบท) และฉันต้องสำนึกบาปของฉันโดยเขียนใหม่
Spoike

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

2
@ ราฟาเอล: นั่นคือเหตุผลที่ฉันไม่เชื่อว่าการศึกษารูปแบบการออกแบบเป็นสิ่งที่ดี
กำหนดค่า

53

สิ่งที่ชั่วร้ายที่สุดในการปกป้องการเขียนโปรแกรมโง่ วางทุกอย่างในการลองจับและไม่ทำอะไรเลยกับการจับ

        try
        {
            int total = 1;
            int avg = 0;
            var answer = total/avg;
        }
        catch (Exception)
        {

        }

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


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

5
@Steve กรณีที่คุณอธิบายเป็นเงื่อนไขที่หายาก อีกอย่างหนึ่งที่ฉันคิดว่าเป็นรหัสการบันทึก - หากการเข้าสู่ระบบล้มเหลวตัวเองไม่มีประเด็นใดที่พยายามบันทึกข้อยกเว้นหรือขัดขวางแอป
dbkk

1
@dbkk - เห็นด้วยกับเงื่อนไขของขอบและฉันจะเพิ่มว่าเมื่อคุณจำเป็นต้องได้รับการยกเว้น แต่ไม่จำเป็นต้องดำเนินการแก้ไขให้เพิ่มความคิดเห็นใน catch block เพื่ออธิบายว่าเป็นสิ่งสำคัญหากเพียงแค่สงบลง ดูแล มันไม่ค่อยหายากในการทดสอบหน่วยดังนั้นฉันจะทิ้งความคิดเห็นไว้ในกรณีนั้น
Steve314

5
เมื่อเกิดข้อผิดพลาดต่อไป
jk

2
@ jk01 - ข้อผิดพลาดไม่ใช่ข้อผิดพลาด (จำเป็น) เงื่อนไขใด ๆ ที่เป็นข้อผิดพลาดหรือไม่ขึ้นอยู่กับบริบท ตัวอย่างเช่น "ไม่พบไฟล์" ไม่ใช่ข้อผิดพลาดหากคุณไม่ต้องการไฟล์ อาจเป็นเพียงไฟล์การตั้งค่าเพิ่มเติมที่อาจจะมีหรือไม่มีอยู่ก็ได้และคุณสามารถปล่อยให้ค่าเริ่มต้นของคุณอยู่ในตำแหน่งที่กำหนดหากไฟล์ไม่อยู่ที่นั่น (ดังนั้นจึงไม่จำเป็นต้องดำเนินการแก้ไขหลังจากจับ)
Steve314

47

พึ่งพา StackOverflow เพื่อแก้ปัญหาของคุณแทนที่จะหาวิธีที่ยาก

โปรแกรมเมอร์ใหม่ที่ค้นหาความรู้มากมายเกี่ยวกับโพสต์ SO (บ่อยเกินไป) ก่อนที่จะคิดและทดลองใช้

ในวันของฉันเราต้องใช้รหัสจากหนังสือไม่มีอินเทอร์เน็ตไม่มี ตอนนี้ลงจากสนามหญ้าของฉัน


28
ฉันต้องยอมรับว่าฉันสะดุ้งเมื่อได้ยินคำถามบางอย่างเกี่ยวกับ SO เพราะพวกเขาถูกถามหลายครั้งทุกวันและพวกเขาไม่ได้ค้นหาเลย หรือแย่กว่านั้นคือพวกเขาปฏิบัติต่อชุมชนในฐานะบริการเอาท์ซอร์สฟรี
Orbling

2
@dbkk: stackoverflow.com/questions/4665778/… -> ความคิดเห็นแรก "คุณเคยลองไหม"
Matthieu M.

5
ฉันเริ่มเรียนรู้จากหนังสือ แต่เมื่อฉันมีพื้นฐานฉันได้เรียนรู้เกือบทุกอย่างจากการสนทนาในฟอรัมออนไลน์ ไม่ใช่โดยการถาม แต่ส่วนใหญ่ (และตอนแรกเท่านั้น) โดยการอ่าน วิธีนี้สอนภาษาการเขียนโปรแกรมหลายภาษาให้ฉันอย่างลึกซึ้ง (ด้วยซอกและ crannies) และฉันคิดว่ามันไม่ใช่วิธีที่แย่เลย
Konrad Rudolph

1
@ Konrad Rudolph: วิธีการที่ดีและฉลาดอ่านคำถามค้นหาดี การถามนั้นทำได้ดีที่สุดเมื่อผู้ถามมีกรอบที่เข้าใจคำตอบ บ่อยครั้งที่ผู้คนถามคำถามที่พวกเขายังไม่มีความสามารถที่จะเข้าใจ
Orbling

3
ปัญหาคือว่าดังนั้นให้กำลังใจนี้โดยให้ตัวแทนจำนวนมากสำหรับการถาม / ตอบคำถามง่าย ๆ ที่สามารถตอบด้วยการค้นหา google ง่าย ๆ คำถามที่ยากมากที่ผู้คนตอบเพียงเพราะพวกเขาต้องการ
IAdapter

36

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

อีกสิ่งหนึ่งคือ (ใน Perl เช่นกัน) OOP มักจะเขียนสิ่งเดียวกันด้วยวิธีอื่น: result = $object ->function(pars)แทนที่จะเป็นแบบresult = function(object, pars)นี้บางครั้งก็สมเหตุสมผล แต่เมื่อผสมกับการเขียนโปรแกรมตามขั้นตอนก็สามารถทำให้การอ่านรหัสค่อนข้างสับสน และนอกเหนือจากนั้นคุณเพียงแค่แนะนำค่าใช้จ่ายเพิ่มเติมซึ่งไม่ได้ปรับปรุงการออกแบบ มันมาถึงสิ่งที่พูดเกี่ยวกับรูปแบบซิงเกิลเช่นกัน: ควรใช้ แต่ไม่ใช่ทุกอย่าง

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


6
@Craige: ฉันใช้ OOP เอง แต่ในสาขาของฉัน (การคำนวณทางวิทยาศาสตร์) ประสิทธิภาพเป็นเรื่องใหญ่และ OOP มักถูกกระทำที่นั่นเนื่องจากนักเรียนทุกคนได้รับ Java ทุกวันนี้ มันยอดเยี่ยมสำหรับการจัดการกับปัญหาที่ใหญ่กว่าสำหรับการกำหนดแนวคิดและอื่น ๆ แต่ถ้าคุณทำงานกับลำดับดีเอ็นเอเช่นใน BioPerl การใช้วัตถุทุกครั้งและทำงานอย่างต่อเนื่องกับตัวรับและตัวตั้งค่าสามารถเพิ่มเวลาในการคำนวณได้สิบเท่า เมื่อรหัสของคุณทำงานสองสามวันแทนที่จะเป็นสองสามชั่วโมงความแตกต่างนั้นสำคัญจริงๆ
Joris Meys

1
@Craige: วิธีการผูกมัด (เหมือนFoo.DoX().DoY().DoZ()) เป็นสิ่งที่ดี แต่มันไม่ได้เป็นวิธีเดียวที่จะไปเกี่ยวกับบางสิ่งบางอย่าง องค์ประกอบของฟังก์ชั่น (เหมือนdoZ . doY . doX $ fooเป็นทางเลือกที่ถูกต้องสมบูรณ์
อานนท์

1
@Joris: สิ่งที่ฉันสงสัยมาเป็นเวลานาน (ตัวฉันเป็น bioinformatician): ถ้าประสิทธิภาพการทำงานมีความสำคัญมากทำไมใช้ Perl ตั้งแต่แรกแทนที่จะเป็น C ++? หากคุณกังวลเกี่ยวกับการกำจัดปัจจัย 10 จากรันไทม์ (ข้อกังวลที่ถูกต้อง!) การเปลี่ยนเป็น C ++ จะทำให้คุณพึงพอใจทันที แน่นอนภาษาดูด ... แต่แล้ว Perl ก็เช่นกันและมีห้องสมุดชีวสารสนเทศที่ดีสำหรับ C ++
Konrad Rudolph

1
@ Konrad: มันขึ้นอยู่กับ BioPerl มีเนื้อหามากที่สุดสำหรับนักชีวสารสนเทศจากทุกภาษา (ฉันคิดว่า Python กำลังไล่ตามอยู่) นอกจากนี้ยังมีการทำงานจำนวนมากใน Perl และการปรับสคริปต์ง่ายกว่าการเขียนใหม่ทุกอย่างใน C ++ ท้ายที่สุดมันไม่ได้ให้บริการในการเขียนแอปพลิเคชันที่สมบูรณ์เมื่อสคริปต์จะทำ เดาสิว่าทำไม Perl ถึงยังอยู่ใกล้แค่นั้น และอย่างสุจริตฉันไม่รังเกียจฉันชอบภาษา มันยังคงเป็นสิ่งที่ดีที่สุดที่ฉันรู้สำหรับงานสตริงและไฟล์ การคำนวณนั้นทำในภาษาอื่นและเชื่อมโยงกลับมา (ซึ่งค่อนข้างง่าย)
Joris Meys

1
@ Konrad: มันขึ้นอยู่กับว่ามันจะทำอย่างไร มันเป็นไปได้ที่จะทำทั้งหมดใน Perl แต่ Perl สามารถเชื่อมโยงกับเครื่องมืออื่น ๆ ได้อย่างง่ายดายโดยเฉพาะบน Linux ฉันใช้ Perl บ่อยครั้งเป็นสคริปต์ทุบตีขั้นสูงที่มีการจัดการสตริงที่แข็งแกร่งและการสร้างชุดข้อมูลที่ง่ายที่จะถูกทิ้งลงในแอปพลิเคชันอื่น
Joris Meys

27

ต้องใช้เวลาหลายปีใน ASP.NET Webforms ฉันต้องพูดอย่างแจ่มแจ้ง:

Smart UI

ในขณะที่มันเป็นไปได้ทั้งหมดในการสร้างแอปพลิเคชันแบบเลเยอร์ทดสอบได้ในเว็บฟอร์ม Visual Studio ทำให้นักพัฒนาสามารถคลิกเพียงครั้งเดียวในการสร้างวิธีที่จะผูกพันกับแหล่งข้อมูลได้อย่างแน่นหนาด้วยตรรกะแอพพลิเคชั่น

Steve Sanderson อธิบายรูปแบบการต่อต้านนี้ดีกว่าที่ฉันสามารถทำได้ในหนังสือ Pro ASP.NET MVC ของเขา:

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


1
GUI อย่างน้อยต้องมีข้อกำหนดคุณสมบัติบางประการ ฉันไม่คิดว่าโปรแกรมเมอร์ที่เขาอธิบายจะทำได้ดีกว่านี้หากนำเสนอด้วยไฟล์ข้อความเปล่าแทน

4
@ qpr ฉันไม่รู้เกี่ยวกับสิ่งนั้น หากพวกเขามีไฟล์ข้อความเปล่าพวกเขาอาจไม่สามารถทำอะไรได้ (ซึ่งอาจเป็นเพียงโบนัส)
เคนเฮนเดอร์สัน

ข้อดีอย่างหนึ่งของการใช้ WPF คือการนำ MVVM ไปใช้จะทำให้รูปแบบการต่อต้านนี้เป็น smithereens
Robert Rossney

2
พันครั้งนี้ ฉันยังเห็นนักพัฒนา. NET ที่มีประสบการณ์อาศัย "รูปแบบ" นี้เพราะมันง่ายกว่าการทำความเข้าใจหรือใส่ใจเกี่ยวกับการแยกความกังวล แม้ว่าพวกเขาจะไม่ใช้วิซาร์ดการลากและวาง แต่รูปแบบที่พบบ่อยที่สุดในการพัฒนา. NET WebForms ก็คือการทำทุกอย่างในเหตุการณ์ที่ล้าหลังโค้ดและคัดลอก / วางโค้ดตามต้องการ
Wayne Molina

23

ฉันเห็นสิ่งนี้เป็นครั้งคราวและมักเป็นผลมาจากการไม่เข้าใจนิพจน์บูลีน

if (someCondition == true)

16
มันมีข้อดีของการทำให้โค้ดชัดเจนยิ่งขึ้น
Pemdas

7
ฉันคิดว่าดูคำถามนี้อยู่ในลำดับ: programmers.stackexchange.com/questions/12807/ …
gablin

5
ฉันไม่ทำอย่างนั้น แต่จริงจังไปกว่านั้น มีนรกที่แย่กว่านั้นเยอะ :)
MetalMikester

4
หากคุณตั้งชื่อตัวแปรของคุณอย่างถูกต้องตัวอย่างเช่นbools เริ่มต้นด้วยisหรือคุณไม่ต้องการที่จะทำให้รหัสของคุณอย่างชัดเจนมากขึ้นด้วยhas = true
ไม่มีใคร

3
@DisgruntledGoat เพราะไม่ควรใช้งานเลย
Corey

19

การปรับใช้ฟังก์ชันการทำงานหลัก (หรือให้ไว้เป็นอย่างอื่น) อาจเนื่องมาจากความไม่รู้ของการมีอยู่หรือเนื่องจากความจำเป็นในการรับรู้สำหรับการปรับแต่ง


2
การเรียนรู้เป็นข้อยกเว้น เมื่อศึกษาอะไรก็มักจะเป็นประโยชน์ในการ "บูรณาการล้อใหม่"
Maxpm

แน่นอน - ฉันควรระบุว่าเกี่ยวข้องเฉพาะเมื่อสร้างซอฟต์แวร์ที่ใช้งานจริง
l0b0

1
โดยเฉพาะอย่างยิ่งเมื่อใช้สิ่งที่เกี่ยวข้องกับความปลอดภัย ซอฟต์แวร์ความปลอดภัยที่ดีจะป้องกันการโจมตีที่คนส่วนใหญ่ไม่เคยนึกถึง
David Thornley

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

18

มรดก

อย่าบังคับใช้ - เป็นสิ่งที่ไม่สมเหตุสมผล


6
ปัญหาคือว่า "is-a" สังหรณ์ใจปรากฏบ่อยครั้งมากที่จะทำให้รู้สึก (โดยเฉพาะอย่างยิ่งเนื่องจากการดำเนินการทุก / ความสัมพันธ์สัญญาสามารถเรียกขานว่า "is-a") มันต้องมีความเข้าใจที่ดีของ OOP เพื่อให้ทราบว่านี่เป็นความผิดพลาดจริงและการใช้งานการสืบทอดและส่วนต่อประสานนั้นแตกต่างกันอย่างมาก
Konrad Rudolph

@ Konrad - เห็นด้วยอย่างแน่นอน ฉันพยายามกระตุ้นให้ผู้คนเริ่มต้นด้วยการเรียบเรียงย้ายไปยังอินเทอร์เฟซและพิจารณาการสืบทอดล่าสุด (ตามกฎของหัวแม่มือแน่นอน) แต่อาจเป็นเพราะพื้นหลัง VB ของฉันกำลังพูดถึง ... ;-)
Mike Woodhouse

1
นี่เป็นคำถามการออกแบบภาษาเป็นส่วนใหญ่ เหตุผลที่คุณควร "ชอบองค์ประกอบมากกว่าการสืบทอด (การใช้งาน)" ในภาษาเช่น Java หรือ C # เป็นเพราะการสืบทอดการติดตั้งใช้งานในภาษาเหล่านั้น บางคนวิพากษ์วิจารณ์การสร้างซอฟต์แวร์เชิงวัตถุของ Bertrand Meyer สำหรับการรับมรดกมากเกินไป แต่เมื่อคุณดูที่ไอเฟล (ภาษาที่ใช้ในหนังสือเล่มนี้) คุณรู้ว่ามันได้รับการออกแบบมาเพื่อใช้ในการถ่ายทอดทางพันธุกรรม ส่วนประกอบ ในที่กรณีอย่างน้อย
Jörg W Mittag

14

การปรับแต่งซอฟต์แวร์ off-the-shelf

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


นี่ไม่ใช่แนวโน้มที่จะเกิดขึ้นกับแอปพลิเคชันที่กำหนดเองใช่หรือไม่
JeffO

13

ใช้ complier เป็นดีบักเกอร์

ไม่สนใจคำเตือนผู้ใช้หรือปิดอย่างสมบูรณ์

ตัวแปรทั่วโลก


18
เกิดอะไรขึ้นกับ "การใช้คอมไพเลอร์เป็นดีบั๊ก" มีคอมไพเลอร์ที่สามารถชี้ข้อผิดพลาดในรหัสของคุณก่อนที่จะกลายเป็นปัญหาที่รันไทม์เป็นข้อได้เปรียบอย่างมาก
Mason Wheeler

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

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

2
คุณบอกว่าราวกับว่า coder อยู่ในความมืดบอดพยายามทำบางสิ่งบางอย่าง - อะไรก็ตาม - เพื่อให้ได้รหัสเพื่อคอมไพล์ นั่นไม่ใช่วิธีการทำงานของ IME คอมไพเลอร์ให้ข้อความแสดงข้อผิดพลาดที่มีประโยชน์และนำคุณไปยังที่ตั้งของข้อผิดพลาดและโดยปกติแล้วหากบางสิ่งไม่ได้รวบรวมรหัสใหม่ที่คุณเขียนเองดังนั้นคุณจึงมีความคิดที่ดีว่ามีอะไรผิดปกติและวิธีแก้ไขเมื่อชี้ไป ออก. ( แต่ถ้าคุณโยนกำลัง * สุ่ม s รอบ ๆ คุณอาจจะมีการทำงานใน C ++ ที่รวบรวมข้อผิดพลาดจะรู้จักที่จะช่วยเหลืออย่างสูงสุดดังนั้นสิ่งที่ผมพูดอาจใช้ไม่ได้.)
เมสันล้อ

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

11

รูปแบบการออกแบบทั้งหมด

พวกเขาเป็นเหมือนเกลือหรือน้ำตาล บางคนในอาหารของคุณทำให้มันยอดเยี่ยมมากของพวกเขาทำให้อาหารของคุณแย่

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

ตัวอย่างหนึ่งคือ "รูปแบบผู้เข้าชม" ซึ่งเป็นผู้กำกับมากขึ้นสำหรับ "คอลเลกชันตามลำดับ" ฉันต้องทำงานกับโครงสร้างข้อมูลทรีครั้งหนึ่ง เพื่อที่จะ "เยี่ยมชม" แต่ละรายการฉันรหัสวิธีการออกแบบที่ไม่ใช่รูปแบบและเจ้านายเก่ายืนยันที่จะใช้หรือปรับเปลี่ยน "รูปแบบผู้เข้าชม" จากนั้นฉันเรียกดูเน็ตเพื่อความเห็นที่สอง โปรแกรมเมอร์คนอื่น ๆ ก็มีสถานการณ์เดียวกันและเป็นทางออกเดียวกัน และเรียกมันว่า "Tree / Hierarchical Visitor Pattern". เป็นรูปแบบการออกแบบใหม่

ฉันหวังว่ามันจะเพิ่มเป็นรูปแบบใหม่ให้กับหนังสือที่มีอยู่ในหนังสือ "Design Patterns" รุ่นใหม่


3
ฉันไม่เคยใช้รูปแบบการออกแบบถึงแม้ว่าบางครั้งพวกเขาก็ปรากฏตัวเป็นธรรมชาติในรหัสของฉัน
กำหนดค่า

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

2
@configurator เมื่อฉันอ่านเกี่ยวกับรูปแบบการออกแบบ ฉันยังค้นพบว่าฉันและนักพัฒนาซอฟต์แวร์อื่น ๆ ที่ใช้งานบางส่วนของพวกเขาแล้ว ;-)
umlcat

9

ใช้ข้อยกเว้นเป็นการควบคุมการไหล เรียงคล้ายกับคำตอบนี้แต่แตกต่างกัน

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

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


ข้อยกเว้นในการสร้างโค้ดที่ไม่มีประสิทธิภาพขึ้นอยู่กับภาษาของคุณ - การสร้างสแต็กเฟรม ฯลฯ เป็นต้นใน Squeak สแต็กของคุณได้รับการแก้ไขใหม่ทั้งหมดดังนั้นจึงไม่มีความแตกต่างระหว่างการใช้ข้อยกเว้นหรือไม่ (ในคำอื่น ๆ ยกเว้นเป็นส่วนหนึ่งของห้องสมุดไม่ภาษา.) อย่างไรก็ตามมันก็ทำให้เกิดความสับสนกับการทำงานกับการควบคุมการไหลยกเว้นควบคุม: lshift.net/blog/2011/01/04/try-again-with-exceptionsแสดงให้เห็นว่า ข้อยกเว้นการใช้ loop ที่ฉันเพิ่งค้นพบ
Frank Shearar

เกี่ยวกับย่อหน้าสุดท้ายอีกครั้งมันขึ้นอยู่กับภาษาของคุณ ข้อยกเว้น ("เงื่อนไข") ใน Common LISP เป็นส่วนเสริมที่เข้มงวดของแนวคิดส่วนใหญ่ของภาษาที่มีข้อยกเว้น ดูตัวอย่างได้ที่นี่: gigamonkeys.com/book/…เช่นเดียวกับทุกสิ่งคุณสามารถไปไกลได้!
Frank Shearar

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

7

ฉันจะไปด้วยความยืดหยุ่นผ่านการซ่อนข้อมูลมากเกินไป

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

ปัญหาคือเช่นเดียวกับปัญหาการค้นพบที่สมดุลสำหรับทุกบริบทมันต้องอาศัยประสบการณ์


7

เปิดเผยอาร์เรย์ภายใน

    public class Data {
    int[] x;

    public void setArray(int[] x) {

        this.x = x;
    }

    public int[] getArray() {

        return x;
    }
}

ตามhttp://www.oracle.com/technetwork/java/seccodeguide-139067.html

คัดลอกวัตถุที่ไม่แน่นอนก่อนที่จะกลับมาเว้นแต่ว่ามีเจตนาที่จะแบ่งปันรัฐ


6

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

ตัวอย่างเช่นสิ่งนี้นำมาโดยตรงจากเธรด StackOverflow:

// ECMAScript
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
    thing = things[i];
    if(things_by_type[thing.type]) {
        things_by_type[thing.type].push(thing);
    } else {
        things_by_type[thing.type] = [thing];
    }
}

# Ruby
things_by_type = {}
things.each do |thing|
  (things_by_type[thing.type] ||= []) << thing
end

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

// ECMAScript
things.reduce(function (acc, thing) {
    (acc[thing.type] || (acc[thing.type] = [])).push(thing);
    return acc;
}, {});

# Ruby
things.group_by(&:type)

// Scala
things groupBy(_.type)

// C#
from thing in things group thing by thing.Type // or
things.GroupBy(thing => thing.Type);

ไม่มีลูปและไม่มีสถานะที่ไม่แน่นอน ก็โอเคไม่มีลูปอย่างชัดเจนและไม่มีตัวนับลูป

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


ฉันเชื่อว่าในบรรทัดที่สองของ ECMAScript "คงที่" ของคุณควรอ่าน(acc[thing.type] || (acc[thing.type] = []))ตรงข้ามกับ `= [สิ่ง] สิ่งที่, unless you want to add 'ลงในรายการสองครั้ง ... หรือฉันหายไปบางอย่าง?
Austin Hyde

@ Austin Hyde: ถูกต้อง
Jörg W Mittag

1
ตัวอย่าง ecmascript นั้นไม่สามารถเข้าใจได้สำหรับโปรแกรมเมอร์จำนวนมาก มันอาศัยกลวิธีทางวากยสัมพันธ์มากเกินไป การวนซ้ำมีข้อดีของความชัดเจนสำหรับนักพัฒนารุ่นเยาว์
Joeri Sebrechts

6

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


เห็นด้วยในทฤษฎี mocks มีประโยชน์ แต่คุณไม่จำเป็นต้องมี
Wayne Molina

ความไม่ถูกต้องของการเยาะเย้ยขึ้นอยู่กับภาษาที่คุณใช้ ใน C # มันสามารถรุกรานได้มากและเพิ่ม rafts ของอินเตอร์เฟสที่ไม่จำเป็น
Frank Hileman

3

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

และ "เร็ว ๆ นี้" เราจะเรียนรู้ว่าการเก็บจำนวนเต็มในรายการไม่ดีเมื่อเราต้องการเปลี่ยนแปลงเป็น 64 บิตเป็นอย่างไร


2
ฉันคิดว่าส่วนใหญ่ของปัญหา Unicode จะไม่เกิดขึ้นถ้า Borland ได้ประกาศประเภท DataString ที่เป็นพื้นเดียวกันกับ AnsiString แต่โดยเฉพาะสำหรับใช้กับ blobs แล้วทำให้แน่ใจว่าคนรู้เกี่ยวกับมัน
Mason Wheeler

2

คุณสมบัติ. ฉันรู้ว่านี่เป็นการโต้เถียง แต่ฉันรู้สึกว่ามีการใช้คุณสมบัติมากเกินไปใน. net

ความแตกต่างระหว่างสองบรรทัดนี้คืออะไร?

public string Property { get; set; }

public string Field;

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


1
ตกลงกัน; ถ้าคุณรู้ 100% คุณจะไม่ต้องทำอะไรกับการได้รับ / การตั้งค่า "คุณสมบัติ" ดังนั้นจึงไม่มีเหตุผลที่จะมีคุณสมบัติใด ๆ อย่างไรก็ตามหากมีโอกาสคุณจะต้องทำอะไรบางอย่าง (เช่นการบันทึกว่ามีการเปลี่ยนแปลงค่าตัวอย่าง) จากนั้นคุณควรใช้คุณสมบัติ ส่วนตัวผมไม่เห็นความแตกต่างใหญ่พอที่จะไม่ใช้สถานที่ให้บริการในกรณีที่คุณทำจำเป็นต้องปรับเปลี่ยนได้ในภายหลัง (ฉันรู้ว่าฉันรู้YAGNIแต่ฉันรู้สึกเบี่ยงเบนประเด็นไปในกรณีนี้ไม่ได้ค่าใช้จ่ายอะไร)
เวย์น Molina

2
@Wayne: จะเปลี่ยน;ไป{ get { ... } set { ... } }ทำงานมากกว่าการเปลี่ยน{ get; set; }เป็น{ get { ... } set { ... } }อย่างไร
กำหนดค่า

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