เหตุใดผู้คนจึงต่อต้านแท็ก #region ในวิธีการอย่างมาก


27

ฉันได้ยินมามากมายเกี่ยวกับการทำให้วิธีการสั้นและฉันได้ยินโปรแกรมเมอร์จำนวนมากพูดว่าการใช้ #region tags ในวิธีนั้นเป็นสัญญาณที่แน่ใจว่ามันยาวเกินไปและควรได้รับการแบ่งเป็นหลาย ๆ วิธี อย่างไรก็ตามสำหรับฉันแล้วดูเหมือนว่ามีหลายกรณีที่การแยกรหัสด้วยแท็ก #region ภายในเมธอดนั้นเป็นวิธีที่เหนือกว่าในการรีแฟคเตอร์เป็นหลายวิธี

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

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

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

คิด?


4
ฉันกำลังทำงานกับชั้นเรียนที่ค่อนข้างใหญ่ มันเป็นไปตามหลักการความรับผิดชอบเดียว; การทำงานทุกอย่างในชั้นเรียนเป็นสิ่งจำเป็น มันมีวิธีส่วนตัวมากมายซึ่งส่วนใหญ่เกิดจากการปรับโครงสร้างใหม่ ฉันใช้ #region เพื่อแบ่งวิธีการเหล่านี้ออกเป็นหมวดหมู่การทำงานซึ่งได้ผลดีมากสำหรับเรา มีคลาสอื่น ๆ อีกมากมายในโครงการนี้ที่ไม่ต้องการการรักษาเช่นนี้ เครื่องมือที่เหมาะสมสำหรับงานที่เหมาะสมฉันพูด
Robert Harvey

4
@RobertHarvey การใช้พวกมันในคลาสนั้นแตกต่างจากการใช้มันในเมธอด
CaffGeek

18
@Chad: อาไม่ได้สังเกตว่า ใช้พวกเขาในวิธีการที่ดูเหมือนจะสุดขีด หากวิธีการนั้นใช้เวลานานจนต้องมี #regions ฉันจะทำการปรับโครงสร้างให้เป็นวิธีแยกต่างหาก
Robert Harvey

8
ไม่ใช่คำตอบจริงๆ แต่ไม่เพียง แต่ฉันเกลียด#regionแท็กทั้งหมดฉันปิดการพับโค้ดใน Visual Studio ทั้งหมด ฉันไม่ชอบรหัสที่พยายามซ่อนจากฉัน
Daniel Pryden

2
"นอกจากนี้ในแต่ละขั้นตอนเหล่านี้มีความเกี่ยวข้องกับการคำนวณสำหรับวิธีการนี้เท่านั้นดังนั้นการแตกออกเป็นวิธีการใหม่ทำให้เราไม่ต้องใช้รหัสซ้ำ" OTOH ฉันพบว่าถ้าฉันแบ่งฟังก์ชั่นออกเป็น 3 ฉันมักจะพบในภายหลังว่าแต่ละส่วน <i> นั้นมีประโยชน์ </i> ในภายหลังเช่น หากข้อมูลอินพุทบางส่วนเปลี่ยนแปลงเพียงเฟสเดียวคุณสามารถทดสอบแยกได้เป็นต้น
Jack V.

คำตอบ:


65

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

อาร์กิวเมนต์ "ฉันต้องการสิ่งนี้เฉพาะที่นี่" นั้นแย่การวางอย่างสุภาพ เทคนิคที่คุณอธิบายมักจะถูกเรียกว่าเทคนิคหัวข้อและมักขมวดคิ้ว

  1. คุณไม่สามารถทดสอบภูมิภาคได้ แต่คุณสามารถทดสอบวิธีการแยกได้
  2. ภูมิภาคคือความคิดเห็นไม่ใช่องค์ประกอบของวากยสัมพันธ์ ในกรณีที่เลวร้ายที่สุดการซ้อนกันของภูมิภาคและบล็อกของคุณขัดแย้งกัน คุณควรพยายามแสดงความหมายของโครงสร้างของคุณด้วยองค์ประกอบทางไวยากรณ์ของภาษาที่คุณใช้
  3. หลังจากปรับโครงสร้างเป็นเมธอดแล้วไม่มีใครต้องการการพับเพื่ออ่านข้อความอีกต่อไป อาจมีการดูซอร์สโค้ดในเครื่องมือใด ๆ ที่ไม่มีการพับเช่นเทอร์มินัลไคลเอ็นต์อีเมลมุมมองเว็บสำหรับ VCS หรือ diff-viewer ของคุณ
  4. หลังจากเปลี่ยนไปใช้วิธีการใหม่อย่างน้อยวิธีการที่ได้นั้นก็ดีพอ ๆ กับภูมิภาคและมันง่ายกว่าที่จะเคลื่อนย้ายชิ้นส่วนแต่ละชิ้นไปรอบ ๆ
  5. หลักการความรับผิดชอบเดี่ยวชี้ให้เห็นว่าหน่วยงานใดควรมีหนึ่งงานและหนึ่งงานเท่านั้น งานของวิธีการ "หลัก" คือการเขียนวิธีการ "ผู้ช่วย" เพื่อให้ได้ผลลัพธ์ที่ต้องการ วิธีการ "ผู้ช่วย" แก้ปัญหาแยกง่าย ๆ ในการแยก คลาสที่มีเมธอดทั้งหมดเหล่านี้ควรทำตามภารกิจเดียวเท่านั้นและมีเมธอดที่เกี่ยวข้องกับงานนั้นเท่านั้น ดังนั้นวิธีการช่วยเหลืออย่างใดอย่างหนึ่งเป็นของเข้าไปในขอบเขตของคลาสหรือรหัสไม่ควรจะเป็นในชั้นเรียนในสถานที่แรก แต่อย่างน้อยในวิธีการที่ทั่วโลกบางส่วนหรือดีกว่ายังควรได้รับการฉีด

ที่เกี่ยวข้องเพิ่มเติม: ความคิดของ Jeff Atwoods เกี่ยวกับการพับโค้ด


9
1. โปรแกรมเมอร์ส่วนใหญ่ไม่ได้ทดสอบวิธีการส่วนตัวทั้งหมด 2. ชื่อวิธีการไม่สามารถถ่ายทอดทุกสิ่งที่ต้องรู้เกี่ยวกับวิธีการนั้น ข้อยกเว้นอะไรที่อาจถูกโยนทิ้ง การป้อนข้อมูลที่ถูกต้องเป็นโมฆะหรือไม่ บางครั้งมันก็โอเคที่จะใช้โครงสร้างที่ไม่เกี่ยวกับวากยสัมพันธ์เพื่อทำให้โค้ดของคุณเข้าใจได้ง่ายขึ้น ในหลายภาษาไฟล์เป็นตัวอย่างขององค์ประกอบที่ไม่เกี่ยวกับวากยสัมพันธ์ซึ่งเป็นที่ยอมรับกันอย่างกว้างขวางว่าเป็นวิธีการจัดระเบียบรหัส 3. การดำน้ำในการทำงานภายในของวิธีการพยายามอย่างดีที่สุดใน IDE ด้วยเหตุผลหลายประการ สถานการณ์ที่ภูมิภาคอาจกัดคุณใน VCS หรือโปรแกรมรับส่งเมลหายาก
jjoelson

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

7
@jjoelson: 1. แล้วอะไรนะ? 2. จุดที่แน่นอนของฉัน: มันก็โอเคที่จะใช้โครงสร้างที่ไม่ใช่วากยสัมพันธ์หาก (และถ้าเพียง) ไวยากรณ์เพียงอย่างเดียวไม่เพียงพอ 3. "หายาก" - ฉันคิดว่าคุณมีตัวเลขที่จะแสดงให้เห็นว่า ฉันสามารถบอกคุณได้ว่าเครื่องมือ diff (หรือตำหนิหรืออะไรก็ตาม) ที่มาพร้อมกับ TortoiseSVN ไม่มีการพับ 4. มันเกี่ยวข้องกับจุดที่ฉันทำอย่างไร 5. นั่นคือเหตุผลที่ภาษาสมัยใหม่ส่วนใหญ่มีเนมสเปซแบบซ้อนได้ คุณกำลังหันไปใช้งานศิลปะ ASCII แทนที่จะใช้ชุดจานสีกว้าง ๆ ขององค์ประกอบภาษาที่มีอยู่เพื่อจัดโครงสร้างโค้ดของคุณ
back2dos

4
@jjoelson: 1. นั่นคือความคิดเห็นของคุณและอยู่นอกขอบเขตของคำถามนี้ 2. โดยส่วนขยายของฟังก์ชั่นที่ซ้อนกันของอาร์กิวเมนต์ของฉันดีกว่าภูมิภาคใช่ 3. เพราะบางครั้งฉันต้องเรียกดูการแก้ไขจำนวนมากเพื่อติดตามปัญหา ไม่ว่าจะด้วยวิธีใดซอร์สโค้ดเขียนขึ้นสำหรับมนุษย์ไม่ใช่ IDE 4. หนึ่งข้อโต้แย้งไม่เกี่ยวข้องกับประเด็นของฉันประการที่สองนั่นเป็นเพียงความคิดเห็นของคุณอีกครั้งประการที่สามมันไม่ได้อยู่ในขอบเขตของคำถามนี้ 5. C # มีวิธีการอื่นในการสร้างโค้ดนอกเหนือจากฟังก์ชั่นการซ้อน คุณควรใช้สิ่งเหล่านั้นหรือภาษาที่อนุญาตให้ใช้ฟังก์ชันซ้อนกันได้
back2dos

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

15

ไม่ใช่ภูมิภาคในวิธีการที่เป็นปัญหา แต่ในกรณีที่มีความต้องการ (หรือแม้แต่การใช้งาน) เพื่อวางภูมิภาคในวิธีการ

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

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

ไม่นั่นไม่ดีพอ แยกออกเป็นภูมิภาคทั้งหมดที่คุณต้องการ แต่ฉันยังคงส่ายหัวแค่คิดเกี่ยวกับมัน

หากคุณแบ่งเป็นวิธีการที่คุณได้รับประโยชน์มากมาย:

  • ความเข้าใจที่ชัดเจนยิ่งขึ้นเกี่ยวกับสิ่งที่เกิดขึ้นแม้ว่าจะผ่านชื่อของวิธีการ และคุณมีความผิดที่วิธีการที่ไม่สามารถได้รับการบันทึกอย่างเต็มที่ - เพิ่มบล็อกเอกสาร (ตี///) และป้อนคำอธิบายพารามิเตอร์ชนิดกลับและยังexception, example, remarksโหนดในรายละเอียดสถานการณ์เหล่านั้น นั่นคือสิ่งที่จะไปนั่นคือสิ่งที่มันมีไว้สำหรับ!
  • ไม่มีผลข้างเคียงหรือปัญหาการกำหนดขอบเขต คุณอาจบอกว่าคุณประกาศตัวแปรทั้งหมดของคุณในขอบเขตย่อยด้วย{}แต่ฉันต้องตรวจสอบทุกวิธีเพื่อให้แน่ใจว่าคุณไม่ได้ 'โกง'? นี่dodgyObjectฉันใช้ที่นี่เพียงเพราะใช้ในภูมิภาคนี้หรือมาจากที่อื่นใช่หรือไม่ ถ้าฉันอยู่ในวิธีการของตัวเองฉันจะสามารถเห็นได้อย่างง่ายดายว่ามันถูกส่งผ่านมาให้ฉันหรือไม่ว่าฉันจะสร้างมันเอง (หรือมากกว่าคุณสร้างมันขึ้นมา)
  • บันทึกเหตุการณ์ของฉันบอกฉันว่ามีข้อผิดพลาดเกิดขึ้นในระบบใช่ฉันอาจสามารถค้นหารหัสที่ละเมิดด้วยหมายเลขบรรทัดได้ แต่การรู้ชื่อเมธอด (โดยเฉพาะอย่างยิ่งถ้าฉันตั้งชื่อถูกต้อง) ทำให้ฉันมีข้อบ่งชี้ เกิดอะไรขึ้นและเกิดข้อผิดพลาดอะไรขึ้น "โอ้TurnThingsUpsideDownวิธีการล้มเหลว - มันอาจจะล้มเหลวในขณะที่เปลี่ยนสิ่งเลวร้าย" ดีกว่า "โอ้DoEverythingวิธีการล้มเหลว - อาจเป็น 50 สิ่งที่แตกต่างกันและฉันจะต้องขุดหาเวลาหนึ่งชั่วโมงเพื่อหามัน" .

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

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


การแยกวิเคราะห์ข้อคิดเห็น XML ของ Visual Studio พร้อมด้วยแท็ก #region อยู่ภายใต้หมวดหมู่ของคุณลักษณะของ Visual Studio ประเด็นทั้งหมดของฉันคือการไม่พึ่งพาคุณลักษณะเหล่านี้หากทุกคนในโครงการของคุณใช้ Visual Studio สำหรับผลข้างเคียงและปัญหาการกำหนดขอบเขตคุณยังสามารถไขสิ่งต่าง ๆ กับเขตข้อมูลส่วนกลาง ไม่ว่าในกรณีใดคุณต้องพึ่งพาโปรแกรมเมอร์ไม่ให้ทำสิ่งที่โง่เขลาด้วยผลข้างเคียง
jjoelson

5
@jjoelson คุณยังสามารถอ่านความคิดเห็น XML โดยไม่มี visual studio แต่แท็กภูมิภาคแทบไร้ประโยชน์อย่างสมบูรณ์นอก VS ส่วนขยายแบบลอจิคัลของอาร์กิวเมนต์ของคุณเป็นวิธีการยักษ์ที่เรียกใช้แอปพลิเคชันทั้งหมดของคุณไม่เป็นไรตราบใดที่คุณแยกมันออกเป็นภูมิภาค!
Kirk Broadhurst

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

@OliverS, Kirk เป็นคนหนึ่งที่เลี้ยงดูรัฐที่ใช้ร่วมกันว่าเป็นปัญหากับแผนงานในภูมิภาคของฉัน โดยพื้นฐานแล้วฉันกำลังพูดในสิ่งที่คุณกำลังพูดอยู่: ความจริงที่ว่าผู้เขียนโปรแกรมสามารถดูหมิ่นสถานะโดยการแชร์ตัวแปรมากเกินไประหว่างภูมิภาคไม่ใช่ข้อกล่าวหาของทั้งโครงการ t คำฟ้องของรูปแบบหลายวิธี
jjoelson

7

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

"แต่ชั้นเรียนของฉันจะมีวิธีการสาธารณะเพียงวิธีเดียวเท่านั้น!"

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

ชั้นเรียนของคุณสามารถโทรหาทั้งสามวิธีในทางกลับกันและส่งคืนผลลัพธ์ สิ่งหนึ่ง.

เป็นโบนัสตอนนี้วิธีการของคุณสามารถทดสอบได้เพราะไม่ใช่วิธีส่วนตัวอีกต่อไป

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

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

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

แก้ไข :

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

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

หากคุณกังวลเกี่ยวกับคนที่เห็นโครงสร้างของวิธีการ (และคุณปฏิเสธที่จะปรับโครงสร้างใหม่) ให้เพิ่มความคิดเห็นแบนเนอร์เช่นนี้:

//
// ---------- COMPUTE SOMETHING OR OTHER ----------
//

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


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

1
@jjoelson มันยากไหมที่จะสร้างคลาสใหม่? มันคืออะไรหนึ่งบรรทัดวงเล็บเปิดหนึ่งอันและวงเล็บปิดหนึ่งอัน โอ้และคุณต้องกดctrl+n
Kirk Broadhurst

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

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

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

4

ฉันคิดว่าตัวอย่างที่คุณให้ในการโต้แย้งของคุณนั้นน้อยกว่า YAGNI (คุณไม่ต้องการมัน) และอีกมากมายเกี่ยวกับการเขียนรหัสคุณภาพที่เหมาะสมซึ่งรักษาได้ง่าย

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

ประการที่สองถ้าฉันเขียนวิธี A, B และ C ที่ใช้ภายในวิธี D เท่านั้นฉันสามารถทดสอบหน่วย AB และ C ได้อย่างอิสระโดยไม่ขึ้นกับ D ทำให้การทดสอบหน่วยที่แข็งแกร่งมากขึ้นในทั้ง 4 วิธี


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

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

2
โปรแกรมเมอร์ส่วนใหญ่ที่ฉันไม่เห็นด้วยกับแนวคิดของการทดสอบหน่วยทุกวิธีส่วนตัว มันไม่คุ้มค่ากับเวลาที่ต้องใช้ในการติดตั้งและบำรุงรักษาการทดสอบกับวิธีการส่วนตัวทั้งหมด
jjoelson

3

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

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


1
ctrl-f10- วิ่งไปที่เคอร์เซอร์
Steven Jeuris

2

กฎส่วนบุคคลของฉันคือถ้าวิธีหนึ่งยาวกว่าหนึ่งหน้าจอให้พูด 40 บรรทัดมันยาวเกินไป ถ้าคลาสยาวเกิน 500 บรรทัดมันใหญ่เกินไป ฉันทำผิดกฎเหล่านี้บางครั้งบางครั้งถึงหลายตัว แต่โดยทั่วไปฉันรู้สึกเสียใจภายในปี

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

การทำลายฟังก์ชันที่มีความยาวตามข้อกำหนดนี้มีประโยชน์อย่างน้อยสองประการ:

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

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

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

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


2

ที่นี่เราจะไปอีกครั้ง ... มีหัวข้ออื่น ๆ อีกมากมายที่นี่สำหรับโปรแกรมเมอร์ซึ่งสิ้นสุดในการสนทนาเดียวกัน

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

อย่างไรก็ตาม ...

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

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


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

1

แม้ว่าฉันจะยอมรับว่าโดยปกติจะเป็นการดีกว่าที่จะ refactor code มากกว่าที่จะใช้#regionแต่ก็ไม่สามารถทำได้

เพื่อสนับสนุนคำแถลงนั้นขอยกตัวอย่าง

class Foo : IComparable
{
  private String name;
  private int foo;
  private Bar bar;

  public int CompareTo(Foo other)
  {
#region Ascending on name
     if (this.name < other.name) return -1;
     if (this.name > other.name) return 1;
#endregion
#region Usual order on bar
     int compBar = bar.compareTo(other.bar);
     if (compBar != 0) return compBar;
#endregion
#region Descending on foo
     if (this.foo > other.foo) return -1;
     if (this.foo < other.foo) return 1;
#endregion
     return 0; // equal
  }

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

อย่างไรก็ตามข้อยกเว้นเหล่านั้นหายาก มักจะเป็นไปได้ที่จะ refactor เหมือนคำตอบอื่น ๆ ที่พูด


0

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

  • ชื่อและคำสั่งของภูมิภาคทำให้การจัดลำดับและการจัดระเบียบของรหัสชัดเจนยิ่งขึ้นซึ่งใช้รูปแบบเฉพาะซึ่งสามารถเป็นแหล่งของความขัดแย้งและการแยกส่วน
  • แนวคิดส่วนใหญ่ไม่พอดีกับภูมิภาคจำนวนเล็กน้อยอย่างหมดจด โดยปกติแล้วคุณจะเริ่มต้นกับภูมิภาคโดยการเข้าถึงการปรับเปลี่ยนสาธารณะ , ส่วนตัวแล้วบางทีตามประเภทของสมาชิก (อดีตวิธีการคุณสมบัติฟิลด์.) แต่แล้วสิ่งที่เกี่ยวกับการก่อสร้างที่ขยายตัวปรับแต่งเหล่าพันธุ์คงที่ของสิ่งเหล่านี้สมาชิกในการป้องกันสมาชิกภายในการป้องกันภายใน สมาชิกสมาชิกอินเทอร์เฟซโดยนัยเหตุการณ์และอื่น ๆ ในท้ายที่สุดคุณจะมีคลาสที่ออกแบบมาอย่างดีที่สุดซึ่งคุณมีวิธีการเดียวในแต่ละภูมิภาคเนื่องจากการจัดหมวดหมู่แบบละเอียด
  • หากคุณสามารถเก็บรักษาสิ่งที่เป็นประโยชน์และจัดกลุ่มได้เฉพาะในภูมิภาคที่มีกลุ่มพูดสามหรือสี่ประเภทนั่นอาจใช้งานได้ แต่สิ่งที่เพิ่มมูลค่าจริง ๆ หากคุณออกแบบคลาสให้ดีคุณไม่จำเป็นต้องกรองหน้ารหัส
  • ดังที่ได้กล่าวไว้แล้วข้างต้นภูมิภาคสามารถซ่อนรหัสที่น่าเกลียดซึ่งอาจทำให้เกิดปัญหาน้อยกว่าที่เป็นอยู่ การรักษาอาการปวดตาอาจช่วยในการแก้ไข
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.