มันหมายถึงอะไรในการฉีดข้อมูล (พฤติกรรมเทียบ) ในตัวสร้างคลาสและทำไมจึงถือว่าการปฏิบัติที่ไม่ดี?


10

ฉันกำลังอ่านหนังสือ "Learning TypeScript" โดย Remo Jansen ในส่วนเดียวผู้เขียนอธิบายถึงวิธีการสร้างกรอบงาน MVC ที่พิสูจน์ง่ายของแนวคิดรวมถึงวิธีการสร้างModelชั้นเรียนและกล่าวว่าต่อไปนี้:

รูปแบบจะต้องมี URL ของบริการบนเว็บที่ใช้ พวกเราจะใช้ตัวตกแต่งคลาสชื่อ ModelSettings เพื่อตั้งค่า URL ของบริการที่จะใช้ เราสามารถฉีด URL บริการผ่านทางคอนสตรัค แต่ก็ถือว่ามีการปฏิบัติที่ไม่ดีที่จะฉีดข้อมูล (เมื่อเทียบกับพฤติกรรม) ผ่านการสร้างคลาส

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

class Person {
  constructor(name) {
    this.name = name;
  }
}

แน่นอนฉันคิดว่าnameเป็นข้อมูลไม่ใช่เป็นพฤติกรรมและรวมอยู่ในระดับสากลในตัวอย่างประเภทนี้เป็นพารามิเตอร์ตัวสร้างและไม่เคยมีการเอ่ยถึงว่านี่เป็นการปฏิบัติที่ไม่ดี ฉันคิดว่าฉันเข้าใจผิดบางอย่างในคำพูดข้างต้นไม่ว่า "data" หรือ "inject" หมายถึงอะไร

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


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

@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
  constructor(metiator : IMediator) {
    super(metiator);
  }
...
}

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

constructor(metiator : IMediator, serviceUrl : string) {...

ผมขอแนะนำให้คุณทำในการค้นหาใน google เกี่ยวกับการฉีดพึ่งพา นี่ไม่ใช่ฟอรัมที่ถูกต้องที่จะถามคำถามนี้ :)
toskv

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

การพึ่งพาการฉีดและการฉีดข้อมูลเป็น 2 สิ่งที่แตกต่างกัน ที่หนึ่งคือหลักการออกแบบในขณะที่ที่สองคือประเภทของการโจมตี หากคุณต้องการคำค้นหาที่ชัดเจนยิ่งขึ้นลอง "inversion of control" มันกว้างขึ้นเล็กน้อย แต่ก็ช่วยให้ได้ภาพที่ชัดเจนขึ้นเช่นกัน
toskv

1
ฉันเชื่อว่าการโจมตี "การฉีดข้อมูล" เป็นสัตว์ที่แตกต่างกันมากซึ่งสิ่งที่ผู้เขียนหนังสืออ้างอิงพูดถึงเมื่อเขาพูดว่า "ฉีดข้อมูล" นั่นเป็นหนึ่งในเหตุผลที่ฉันผิดหวังกับการค้นหาของ Google ในเรื่องนี้ แม้ว่าฉันต้องเข้าใจเช่นหลักการ SOLID ดีกว่าฉันไม่เข้าใจวิธีการให้ "ชื่อ" เป็นพารามิเตอร์ให้กับตัวสร้าง "บุคคล" เป็นเรื่องปกติและตกลง แต่ให้ "serviceUrl" เป็นพารามิเตอร์ให้กับ "แบบจำลอง" ตัวสร้างไม่เหมาะสมหรือแตกต่างจากตัวอย่าง "name" / "Person"

7
ฉันคิดว่า Remo ผิดพลาด พารามิเตอร์คือข้อมูลไม่ว่าเขาจะพูดอะไร ข้อมูลที่ถูกฉีดจะมีชนิดอยู่เสมอ และทุกประเภทในภาษาเชิงวัตถุจะมีลักษณะการทำงานบางอย่าง
Robert Harvey

คำตอบ:


5

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

จากด้านบนของหัวของฉันฉันสามารถนึกถึงสถานการณ์ที่หลากหลายซึ่งการส่งผ่านข้อมูลผ่านตัวสร้างดีบางอย่างที่เป็นกลาง แต่ไม่มีที่ไหนที่ไม่ดี

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

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

แม้ว่าวัตถุที่ไม่แน่นอนเป็นสิ่งที่คุณต้องการการฝึกฝนที่ไม่ดีนี้เป็นอย่างไร:

var blah = new Rectangle(x,y,width,height);

ในความโปรดปรานของ:

var blah = new Rectangle();
blah.X = x;
blah.Y = y;
blah.Width = width;
blah.Height = height;

ผู้เขียนคิดว่าสิ่งแรกคือการปฏิบัติที่ไม่ดีจริง ๆ หรือไม่และฉันควรเลือกตัวเลือก 2 เสมอหรือไม่ ฉันคิดว่ามันเป็นการพูดที่บ้า

ดังนั้นเนื่องจากฉันไม่มีหนังสือและจะไม่อ่านมันต่อไปแม้ว่าฉันจะทำฉันก็จะดูข้อความนั้นและมีข้อความทั่วไปในตอนนี้ด้วยความสงสัยจำนวนมาก


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

0

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

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


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

0

เพียงแค่คาดเดา

ถ้าฉันรู้ว่าพฤติกรรมการฉีดไม่ใช่ข้อมูลฉันจะคิดแทนการทำสิ่งนี้:

(ขออภัยสำหรับตัวอย่างใน pseudocode):

class NoiseMaker{
  String noise;
  NoiseMaker(String noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise)
  }
}

เพื่อทำสิ่งนี้:

interface Noise{
  String getAudibleNoise();
}

class PanicYell implements Noise{
   String getAudibleNoise(){
       return generateRandomYell();
   }
   .....
}



class WhiteNoise implements Noise{
   String getAudibleNoise(){
       return generateNoiseAtAllFrequences();
   }
   .....
}

class NoiseMaker{
  Noise noise;
  NoiseMaker(Noise noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise.getAudibleNoise())
  }
}

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

ฉันคิดว่ามันคือทั้งหมดที่เกี่ยวกับกฎ 'คอมโพสิตสนับสนุนเหนือสืบทอด' ซึ่งเป็นกฎที่ดีฉันต้องพูด

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

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