วิธีการหลีกเลี่ยงวิธีการกาวยักษ์?


21

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

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

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

ฉันจะหลีกเลี่ยงวิธีการดังกล่าวได้อย่างไร นี่เป็นอาการของข้อมูลที่พันกันหรือภาพสะท้อนบางอย่างที่ฉันทำผิดหรือเปล่า?


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

1
พวกเรายังพูดถึงวัตถุที่นี่หรือเพียงแค่ funcs ทั่วสถานที่?
Erik Reppen

3
ฉันไม่คิดว่านี่เป็นคำถามที่ซ้ำกันฉันกำลังพูดมากกว่าปกติเล็กน้อย (และในระดับที่ใหญ่กว่าฟังก์ชั่นเดียว)
cmhobbs

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

2
วิธีการในโลกที่ซ้ำกันได้อย่างไร
MattDavey

คำตอบ:


12

ฉันจะให้ประสบการณ์การ Refactoring LedgerSMB แก่คุณ เราตัดสินใจที่จะทำสิ่งต่าง ๆ ในช่วงต้นและยังคงทำสิ่งที่คุณอธิบาย แต่ยังไม่มีวิธีการกาวจำนวนมาก (เรามีวิธีการติดกาวไม่กี่วิธีต่อไปนี้

ชีวิตกับรหัสสองฐาน

LedgerSMB รอดชีวิตมาได้กับสองรหัสฐานเป็นเวลาประมาณ 5 ปีและจะมีอีกหลายก่อนที่จะกำจัด codebase เก่า codebase เก่าเป็นหนังสยองขวัญที่แท้จริงที่เห็น การออกแบบ db ที่ไม่ถูกต้อง Perl สร้างเหมือนIS->some_func(\%$some_object);พร้อมกับรหัสซึ่งแสดงให้เห็นว่าทำไมบางครั้งใช้สปาเก็ตตี้อุปมา codebase ใหม่หลีกเลี่ยงสิ่งนี้โดยการย้ายเคียวรี db ไปยังโพรซีเดอร์ที่เก็บไว้มีเฟรมเวิร์กที่สะอาดกว่าสำหรับการจัดการคำร้องขอและอื่น ๆ อีกมากมาย

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

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

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

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

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


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

1
"เส้นทางการดำเนินการที่คดเคี้ยวระหว่างโมดูลและด้านหลังและระหว่างภาษาโดยไม่มีการสัมผัสหรือเหตุผล" - นี่ทำให้ฉันนึกถึงวิธีปฏิบัติ OO ที่ทันสมัยบางอย่างเช่นกัน
user253751

8

มันเสียงเหมือนสิ่งที่คุณทำจะนำมาเป็นระเบียบอีนุงตุงนังของprecedural codebase และสร้างที่น่ารักแบบแยกส่วนprecedural codebase

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

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


6

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


2
คุณไม่ได้รับต้นไม้กาวหรือ?
ปีเตอร์บี

3
@PieterB อาจจะเป็น แต่มันง่ายกว่าที่จะแยกการพึ่งพาที่แตกต่างกันเมื่อคุณมีงานที่แตกต่างกันในวิธีการที่แตกต่างกัน คุณสามารถทำอีกครั้งผ่าน refactoring หลังจากแยกวิธีการใหม่
Paling

1

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

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


0

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

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

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