มันเป็นกลิ่นรหัสหรือไม่ถ้าวัตถุรู้เจ้าของเป็นจำนวนมาก?


9

ในแอปพลิเคชัน Delphi 2007 ของเราเราใช้โครงสร้างต่อไปนี้มากมาย

FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));

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

ตัวอย่าง: เมื่อสร้างรายงานข้อมูลที่ได้จะถูกบีบอัดและจัดเก็บไว้ในเขตข้อมูล Blob ของตารางที่เข้าถึงผ่านดาต้าโมดูลแบบ TdmReportBaseData ในโมดูลที่แยกต่างหากของแอปพลิเคชันของเรามีฟังก์ชั่นเพื่อแสดงข้อมูลจากรายงานในรูปแบบเพจโดยใช้ ReportBuilder รหัสหลักของโมดูลนี้ (TdmRBReport) ใช้คลาส TRBTempdatabase เพื่อแปลงข้อมูล Blob ที่ถูกบีบอัดไปยังตารางต่าง ๆ ที่ใช้งานได้ใน Reportbuilder รันไทม์ Reportdesigner TdmRBReport มีการเข้าถึง TdmReportBaseData สำหรับข้อมูลที่เกี่ยวข้องกับรายงานทุกประเภท (ประเภทของรายงานการตั้งค่ารายงานการคำนวณ ฯลฯ ) TRBTempDatabase ถูกสร้างขึ้นใน TdmRBR พอร์ต แต่ต้องมีการเข้าถึง TdmReportBasedata ดังนั้นตอนนี้จะใช้การก่อสร้างด้านบน:

constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
  inherited Create(aOwner);

  FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }

ความรู้สึกของฉันคือสิ่งนี้หมายความว่า TRBTempDatabase รู้เจ้าของจำนวนมากและฉันสงสัยว่านี่เป็นกลิ่นรหัสหรือรูปแบบต่อต้าน

คุณคิดอย่างไรเกี่ยวกับเรื่องนี้? นี่เป็นกลิ่นรหัสหรือไม่? ถ้าอย่างนั้นเป็นวิธีที่ดีกว่าอะไร


1
ถ้ามันควรจะรู้ว่ามากเกี่ยวกับคลาสอื่นมันจะได้รับการจัดให้มีวิธีที่ง่ายกว่าในการทำมัน
Loren Pechtel

คำตอบ:


13

ดูเหมือนว่ารูปแบบการบริการค้นหาซึ่งเป็นครั้งแรกโดยมาร์ตินฟาวเลอร์ (ซึ่งได้รับการระบุว่าเป็นรูปแบบต่อต้านทั่วไป)

การฉีดขึ้นอยู่กับการก่อสร้างเป็นที่ต้องการมากกว่า Service Locator เพราะมันช่วยให้มองเห็นพารามิเตอร์ที่ต้องการและส่งเสริมการทดสอบหน่วยที่ง่ายขึ้น

ปัญหาของการใช้ Service Locator ไม่ใช่ว่าคุณต้องพึ่งพาการใช้งานตัวระบุตำแหน่งของบริการ (แม้ว่าอาจจะเป็นปัญหาเช่นกัน) แต่มันเป็นรูปแบบการต่อต้านที่แท้จริง มันจะทำให้ผู้ใช้ API ของคุณได้รับประสบการณ์การพัฒนาที่แย่มากและมันจะทำให้ชีวิตของคุณในฐานะนักพัฒนาการบำรุงรักษาแย่ลงเพราะคุณจะต้องใช้พลังสมองจำนวนมากเพื่อเข้าใจความหมายของการเปลี่ยนแปลงทุกอย่างที่คุณทำ

คอมไพเลอร์สามารถให้ทั้งผู้บริโภคและผู้ผลิตได้มากเมื่อใช้ Constructor Injection แต่ไม่มีความช่วยเหลือใดที่มีให้สำหรับ API ที่ใช้บริการ Locator

นอกจากนี้ที่โดดเด่นที่สุดก็ยังทำลายกฎหมายของ Demeter

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

กฎของ Demeter สำหรับฟังก์ชั่นกำหนดให้วิธีการ M ของวัตถุ O อาจเรียกใช้วิธีการของวัตถุประเภทต่อไปนี้เท่านั้น:

  1. โอตัวเอง
  2. พารามิเตอร์ของ M
  3. วัตถุใด ๆ ที่สร้าง / สร้างอินสแตนซ์ภายใน M
  4. วัตถุองค์ประกอบโดยตรงของ O
  5. ตัวแปรโกลบอลซึ่งสามารถเข้าถึงได้โดย O ในขอบเขตของ M

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

วิธีที่ดีกว่า

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

constructor TRBTempDatabase.Create(aOwner: TComponent, ownerClass: IComponent);
begin
  inherited Create(aOwner);

  FdmReportBaseData := TdmRBReport(ownerClass).dmReportBaseData;
end;{- .Create }

3
คำตอบที่ดีและอุปกรณ์ประกอบฉากสำหรับผู้ที่เกิดขึ้นกับการเปรียบเทียบที่ยอดเยี่ยมนี้:As a simple example, when one wants to walk a dog, it would be folly to command the dog's legs to walk directly; instead one commands the dog and lets it take care of its own legs.
แอนดี้ล่า

3

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

ขึ้นอยู่กับความลึกของคลาสที่สองของคุณที่เชื่อมต่อกันมันฟังดูคล้ายกับคำอธิบายของ Fowler เกี่ยวกับ Feature Envy หรือกลิ่นรหัส Intimacy ที่ไม่เหมาะสมจะเห็นได้ชัด

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

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