เมื่อคลาสพยายามทำมากเกินไปมันมักจะแสดงตัวแปรอินสแตนซ์มากเกินไป เมื่อคลาสมีตัวแปรอินสแตนซ์มากเกินไปรหัสที่ซ้ำกันจะไม่สามารถล้าหลังได้
การมีตัวแปรอินสแตนซ์มากเกินไปนำไปสู่การทำซ้ำรหัสได้อย่างไร
เมื่อคลาสพยายามทำมากเกินไปมันมักจะแสดงตัวแปรอินสแตนซ์มากเกินไป เมื่อคลาสมีตัวแปรอินสแตนซ์มากเกินไปรหัสที่ซ้ำกันจะไม่สามารถล้าหลังได้
การมีตัวแปรอินสแตนซ์มากเกินไปนำไปสู่การทำซ้ำรหัสได้อย่างไร
คำตอบ:
การมีตัวแปรอินสแตนซ์มากเกินไปไม่เกี่ยวข้องโดยตรงกับรหัสที่ซ้ำกันหรือในทางกลับกัน คำแถลงนี้ในเรื่องทั่วไปเป็นเท็จ เราสามารถโยนคลาสที่แยกกันสองคลาสโดยไม่มีโค้ดที่ซ้ำกันเป็นคลาสเดียว - ที่สร้างคลาสใหม่ที่มีความรับผิดชอบไม่แยกและตัวแปรอินสแตนซ์มากเกินไป แต่ก็ยังไม่มีโค้ดที่ซ้ำกัน
แต่เมื่อคุณพบชั้นเรียนที่มีความรับผิดชอบมากเกินไปในรหัสมรดกโลกแห่งความเป็นจริงโอกาสสูงที่โปรแกรมเมอร์ที่เขียนมันไม่สนใจรหัสที่สะอาดหรือหลักการที่เป็นของแข็ง (อย่างน้อยไม่ใช่ตอนที่เขาเขียนรหัสนั้น) ไม่น่าเป็นไปได้ที่คุณจะพบกับรหัสอื่น ๆ เช่นรหัสซ้ำกันในนั้น
ตัวอย่างเช่นรูปแบบการต่อต้าน "คัดลอกวางใช้ใหม่" มักจะถูกนำไปใช้โดยการคัดลอกวิธีเก่าและทำการแก้ไขเล็กน้อยโดยไม่ต้องปรับโครงสร้างใหม่อย่างเหมาะสม บางครั้งเพื่อให้งานนี้เราต้องทำซ้ำตัวแปรสมาชิกและปรับเปลี่ยนตัวแปรเล็กน้อยเช่นกัน สิ่งนี้อาจส่งผลให้คลาสมีตัวแปรอินสแตนซ์มากเกินไป (แม่นยำยิ่งขึ้น: ตัวแปรอินสแตนซ์ที่มีลักษณะคล้ายกันมากเกินไป) ในสถานการณ์เช่นนี้ตัวแปรอินสแตนซ์ที่คล้ายกันอาจเป็นตัวบ่งชี้สำหรับรหัสซ้ำที่อื่นในชั้นเรียน อย่างไรก็ตามอย่างที่คุณสังเกตนี่เป็นตัวอย่างที่ประดิษฐ์ขึ้นมาและฉันจะไม่สรุปกฎทั่วไปจากมัน
ตัวแปรอินสแตนซ์มากเกินไปหมายถึงสถานะมากเกินไป สถานะมากเกินไปนำไปสู่การทำซ้ำรหัสที่แตกต่างกันเพียงเล็กน้อยสำหรับแต่ละรัฐ
นี่เป็นคลาสคอนกรีตคลาสสิกเดียวที่ทำหลายสิ่งมากเกินไปที่ควรเป็นคลาสย่อยหรือเรียงความ
ค้นหาคลาสไม่กี่คลาสที่มีตัวแปรอินสแตนซ์มากเกินไปคุณจะเห็นว่ามันรักษาสถานะที่มากเกินไปและมีเส้นทางโค้ดที่ซ้ำกันจำนวนมากซึ่งมีความเชี่ยวชาญเพียงเล็กน้อยสำหรับแต่ละกรณี นี่คือหนึ่งในแหล่งที่ใหญ่side effects
ที่สุดเช่นกัน
มีอย่างน้อยหนึ่งข้อยกเว้นสำหรับสิ่งนี้ที่ไม่ได้อยู่ในหมวดหมู่นี้และเป็นวิธีที่ง่ายในการแก้ไขสิ่งนี้ Immutable
วัตถุไม่มีปัญหานี้เนื่องจากเป็นสถานะที่แน่นอนไม่มีโอกาสใด ๆ สำหรับการจัดการสถานะที่ซับซ้อนหรือผลข้างเคียง
ข้อความที่คุณอ้างถึงมีไว้เพื่อให้เห็นในบริบทที่เฉพาะเจาะจง
จากประสบการณ์ของฉันฉันไม่สามารถยืนยันได้ว่า "ตัวแปรอินสแตนซ์จำนวนมากโดยทั่วไประบุรหัสซ้ำ" นอกจากนี้โปรดทราบว่านี่เป็นของ "รหัสกลิ่น" และมีการกล่าวหาว่ามีกลิ่นที่ขัดแย้ง ดูที่นี่:
http://c2.com/cgi/wiki?CodeSmell
คุณจะพบว่า "ตัวแปรอินสแตนซ์มากเกินไป" นั้นดีพอที่จะได้กลิ่นโค้ดเหมือนกับ "ตัวแปรอินสแตนซ์น้อยเกินไป"
แต่มีปัญหากับตัวแปรอินสแตนซ์ไม่ว่าจะน้อยเกินไปหรือมากเกินไป:
ตัวแปรอินสแตนซ์ทุกตัวอาจหมายถึงสถานะบางอย่างของวัตถุ Stati ต้องการการดูแลอย่างระมัดระวังเสมอ คุณต้องให้แน่ใจว่าคุณได้ครอบคลุมการรวมกันของ stati ที่เป็นไปได้ทั้งหมดเพื่อหลีกเลี่ยงพฤติกรรมที่ไม่คาดคิด คุณต้องชัดเจนอยู่เสมอ: วัตถุของฉันมีสถานะใดในตอนนี้ จากมุมนี้ตัวแปรอินสแตนซ์จำนวนมากอาจบ่งบอกว่าคลาสนั้นไม่มีความเคลื่อนไหว นอกจากนี้ยังอาจบ่งบอกว่าชั้นเรียนมีงานมากเกินไปเนื่องจากต้องการสถิติมาก
ตัวแปรอินสแตนซ์ทุกตัวต้องการให้คุณคอยควบคุมวิธีการใดที่จะเปลี่ยนแปลงตัวแปรในแบบที่เป็นอยู่ ดังนั้นทันใดนั้นคุณก็ไม่รู้จักพ่อครัวที่ทำอาหารอีกต่อไป หนึ่งในนั้นที่ตั้งโปรแกรมอย่างเหนื่อยล้าในช่วงดึกจะทำให้ซุปของคุณเสีย อีกครั้ง: ตัวแปรดังกล่าวมากเกินไปจะนำไปสู่การรหัสยากที่จะเจาะ
อีกด้านหนึ่ง: ตัวแปรอินสแตนซ์น้อยเกินไปอาจทำให้วิธีการมากมายต้องจัดการกับข้อมูลด้วยการทำงานมากเกินไปและมีพารามิเตอร์มากเกินไป คุณรู้สึกเช่นนี้หากคุณให้วิธีการหลายอย่างในพารามิเตอร์ที่เท่าเทียมกันและวิธีการทั้งหมดจะทำสิ่งที่คล้ายกันมากกับพารามิเตอร์นี้ ในสถานการณ์เช่นนั้นรหัสของคุณจะเริ่มขยายตัว คุณจะสิ้นสุดการเลื่อนหน้าจอหลายหน้าจอขึ้น ๆ ลง ๆ เพื่อรวมสิ่งต่าง ๆ เข้าด้วยกัน การรีแฟคเตอร์อาจช่วยได้: แนะนำตัวแปรอินสแตนซ์หนึ่งตัวและทางเข้าหนึ่งทางที่ชัดเจน จากนั้นปลดปล่อยวิธีการทั้งหมดให้เป็นอิสระ
ท้ายสุด แต่ไม่ท้ายสุด: หากตัวแปรอินสแตนซ์จำนวนมากของคลาสมี setter และทะลุแต่ละตัวมันก็อาจบ่งบอกว่าคลาสอื่นไม่ใช้คลาสที่ถูกต้อง มีการพูดคุยเกี่ยวกับ " ทำไมผู้ที่ได้รับและผู้ตั้งตนจึงชั่วร้าย " แนวคิดในระยะสั้นคือถ้าคลาสRectangle
มีบางคลาสgetX()
และมีอีกสิบคลาสที่ใช้rectangle.getX()
คุณจะเขียนโค้ดที่ไม่ทนทานต่อ "เอฟเฟกต์คลื่น" (ระยะไกลคือการเปลี่ยนรหัสที่มีอิทธิพลต่อโค้ดอื่น) ถามว่าเกิดอะไรขึ้นถ้าคุณเปลี่ยนประเภทจากint
เป็นdouble
? จากการสนทนานี้ผู้คนจำนวนมากrectangle.getX()
ควรโทรไปหากันrectanlge.calculateThisThingForMe()
. ดังนั้นทางอ้อมรหัสที่ซ้ำกันสามารถเกิดขึ้นได้จากตัวแปรอินสแตนซ์จำนวนมากเนื่องจากคลาสที่อยู่รอบ ๆ ใช้ getters และ setters จำนวนมากที่ทำสิ่งที่คล้ายกันมากเช่นสิ่งที่ถูกคัดลอกซึ่งควรย้ายในชั้นเรียนได้ดีกว่า
ตัวแปรอินสแตนซ์จำนวนมากหรือไม่กี่ตัวยังคงเป็นการแลกเปลี่ยนอย่างถาวรโดยเปลี่ยนแปลงทั้งสองวิธีในขณะที่ซอฟต์แวร์กำลังเติบโต
ใส่เพียง: การแยกความกังวลที่ไม่ดีภายในรหัสนำไปสู่รหัสที่ไม่ใช่แบบแยกส่วนนำไปสู่การใช้ซ้ำที่ไม่ดี
หากคุณไม่เคยลองใช้ฟังก์ชั่นซ้ำ ๆ คุณจะไม่ได้รับรหัสซ้ำและตัวแปรอินสแตนซ์จำนวนมากจะไม่มีปัญหา
หากคุณพยายามที่จะทำซ้ำฟังก์ชั่นแล้วรหัสเสาหินซึ่งไม่ได้เป็นแบบแยกส่วนไม่สามารถนำมาใช้ซ้ำได้ มันทำมากเกินไปและทำได้ในสิ่งที่ทำ ในการทำสิ่งที่คล้ายกัน แต่ไม่เหมือนกันมันง่ายกว่าที่จะตัดและวางแทนที่จะทำลายรหัสเสาหิน โปรแกรมเมอร์ประสบการณ์รู้ว่ารหัสที่ซ้ำกันนั้นเป็นเส้นทางสู่นรก
ดังนั้นในขณะที่ตัวแปรอินสแตนซ์หลายตัวไม่ได้เป็นต้นเหตุของปัญหามันเป็น "กลิ่น" ที่รุนแรงซึ่งเป็นปัญหา
ภาษา "ไม่สามารถอยู่ได้ไกลนัก" นั้นอ่อนแอกว่าการพูดว่า "ต้องทำตามอย่างแน่นอน" ดังนั้นผู้เขียนไม่ได้อ้างว่ามันจะต้องเกิดขึ้น แต่ในที่สุดจะเกิดขึ้น; หากคุณต้องการใช้ฟังก์ชันการทำงานซ้ำ แต่ไม่สามารถทำได้เนื่องจากรหัสไม่ได้เป็นแบบแยกส่วน
n
2^n
บ่อยครั้งกว่าที่วัตถุของคุณจะไม่ได้มีสถานะที่สังเกตได้มากมายแต่เนื่องจากคุณยัดเยียดสถานะทั้งหมดนั้นให้กลายเป็นวัตถุชิ้นเดียวภายในคุณยังต้องจัดการกับสิ่งเหล่านั้นทั้งหมด