การมีตัวแปรอินสแตนซ์มากเกินไปนำไปสู่การทำซ้ำรหัสได้อย่างไร


19

ตามRefactoring เพื่อรูปแบบ :

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

การมีตัวแปรอินสแตนซ์มากเกินไปนำไปสู่การทำซ้ำรหัสได้อย่างไร


2
เพียงแค่ใส่: ตัวแปรบูลเช่นสร้างสภาพพื้นที่ภายในของn 2^nบ่อยครั้งกว่าที่วัตถุของคุณจะไม่ได้มีสถานะที่สังเกตได้มากมายแต่เนื่องจากคุณยัดเยียดสถานะทั้งหมดนั้นให้กลายเป็นวัตถุชิ้นเดียวภายในคุณยังต้องจัดการกับสิ่งเหล่านั้นทั้งหมด
biziclop

คำตอบ:


23

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

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

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


11

ตัวแปรอินสแตนซ์มากเกินไปหมายถึงสถานะมากเกินไป สถานะมากเกินไปนำไปสู่การทำซ้ำรหัสที่แตกต่างกันเพียงเล็กน้อยสำหรับแต่ละรัฐ

นี่เป็นคลาสคอนกรีตคลาสสิกเดียวที่ทำหลายสิ่งมากเกินไปที่ควรเป็นคลาสย่อยหรือเรียงความ

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

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


7

ข้อความที่คุณอ้างถึงมีไว้เพื่อให้เห็นในบริบทที่เฉพาะเจาะจง

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

http://c2.com/cgi/wiki?CodeSmell

คุณจะพบว่า "ตัวแปรอินสแตนซ์มากเกินไป" นั้นดีพอที่จะได้กลิ่นโค้ดเหมือนกับ "ตัวแปรอินสแตนซ์น้อยเกินไป"

แต่มีปัญหากับตัวแปรอินสแตนซ์ไม่ว่าจะน้อยเกินไปหรือมากเกินไป:

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

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

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

  4. ท้ายสุด แต่ไม่ท้ายสุด: หากตัวแปรอินสแตนซ์จำนวนมากของคลาสมี setter และทะลุแต่ละตัวมันก็อาจบ่งบอกว่าคลาสอื่นไม่ใช้คลาสที่ถูกต้อง มีการพูดคุยเกี่ยวกับ " ทำไมผู้ที่ได้รับและผู้ตั้งตนจึงชั่วร้าย " แนวคิดในระยะสั้นคือถ้าคลาสRectangleมีบางคลาสgetX()และมีอีกสิบคลาสที่ใช้rectangle.getX()คุณจะเขียนโค้ดที่ไม่ทนทานต่อ "เอฟเฟกต์คลื่น" (ระยะไกลคือการเปลี่ยนรหัสที่มีอิทธิพลต่อโค้ดอื่น) ถามว่าเกิดอะไรขึ้นถ้าคุณเปลี่ยนประเภทจากintเป็นdouble? จากการสนทนานี้ผู้คนจำนวนมากrectangle.getX()ควรโทรไปหากันrectanlge.calculateThisThingForMe(). ดังนั้นทางอ้อมรหัสที่ซ้ำกันสามารถเกิดขึ้นได้จากตัวแปรอินสแตนซ์จำนวนมากเนื่องจากคลาสที่อยู่รอบ ๆ ใช้ getters และ setters จำนวนมากที่ทำสิ่งที่คล้ายกันมากเช่นสิ่งที่ถูกคัดลอกซึ่งควรย้ายในชั้นเรียนได้ดีกว่า

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


คำพูด R-to-P กว้างเกินไปซึ่งเป็นสาเหตุที่ฉันชอบคำตอบนี้ การรับของฉันคือ: หากเราเปิดเผยคุณสมบัติเพียงพอที่ลูกค้าสามารถทำได้และจะรับสิ่งเหล่านั้นและเขียนเวอร์ชันการทำงานที่กำหนดของตัวเอง - # 4 ด้านบน ปัญหาสามารถไปได้ลึกเท่ากับองค์ประกอบของวัตถุ - ดู # 2: ฉันเห็นสิ่งนี้บ่อยเกินไปในรหัสของเรา (a) "ทำไมพวกเขาไม่ใช้คลาส <whhat> (เพื่อยืนยันสถานะที่ไม่มีการจัดระเบียบนี้)" หรือ (b) "ทำไมพวกเขาไม่สร้างชั้นเรียนใหม่ฉันไม่สามารถติดตามได้ทั้งหมด" และแน่นอนว่าเรามีหลายคลาสที่ทำซ้ำภายในฟังก์ชั่นสำหรับการขาดคลาสที่เชื่อมโยงกัน
Radarbob

6

ใส่เพียง: การแยกความกังวลที่ไม่ดีภายในรหัสนำไปสู่รหัสที่ไม่ใช่แบบแยกส่วนนำไปสู่การใช้ซ้ำที่ไม่ดี

หากคุณไม่เคยลองใช้ฟังก์ชั่นซ้ำ ๆ คุณจะไม่ได้รับรหัสซ้ำและตัวแปรอินสแตนซ์จำนวนมากจะไม่มีปัญหา

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

ดังนั้นในขณะที่ตัวแปรอินสแตนซ์หลายตัวไม่ได้เป็นต้นเหตุของปัญหามันเป็น "กลิ่น" ที่รุนแรงซึ่งเป็นปัญหา

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

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