Magento 2 - แนวปฏิบัติที่ดีในการใช้ / หลีกเลี่ยง Magic getters?


21

Magic getters on Varien_Object(M1) และDataObject(M2) เป็นเรื่องธรรมดา แต่ด้วย Magento 2 มันรู้สึกผิดที่จะใช้มัน

ดี:

  • ง่ายต่อการอ่าน / เขียน

ไม่ดี

คำถาม

ด้วย Magento 2 เรามีสองวิธีใหม่:

  • getDataByKey($key)
  • getDataByPath($path)

มีเหตุผลที่ดีที่จะยังคงใช้getData($key)หรือผู้ได้รับเวทมนตร์?


แก้ไข:

@Vinai ขอบคุณ ฉันไม่ได้พูดถึง@methodวิธีการเพราะวิธีการของฉันแตกต่างกันมาก

มันช่วย IDE เท่านั้น แต่ไม่มีผลกระทบต่อสิ่งอื่น

มีการรวม PR หลาย ๆ อันที่เป็น "การปรับให้เหมาะสมที่สุดของไมโคร" อย่างที่ต้องการ(int)แทนintval()หรือรับขนาดของอาเรย์ภายนอกลูป (แม้กระทั่งสำหรับอาเรย์ขนาดเล็ก)

ในทางกลับกันมี

  1. ผู้ได้รับเวทมนตร์ที่มี "ค่าใช้จ่าย" ตามที่ Marius อธิบายไว้ ....

    strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
  2. getData($key) mehtods ต้องตรวจสอบเพิ่มเติมอีก 2-3 รายการ ...

    • if ('' === $key) {
    • if (strpos($key, '/')) {
    • if ($index !== null) {

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

$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');

ใช้ที่ 3 กับ/** @var some $value */ดูดีที่สุดสำหรับฉัน (?)


1
คุณสามารถเพิ่มวิธีการใน class doc bloc เพื่อให้เครื่องมือวิเคราะห์รหัสจะไม่บ่นเกี่ยวกับวิธีการที่ไม่มีอยู่ นอกจากนี้ฉันคิดว่าการใช้ตัวเลขในคีย์เป็นวิธีปฏิบัติที่ไม่ดีดังนั้นจึงไม่ควรแสดงเป็น "ไม่ดี" ที่นี่ imo
Lily Bergonzat

คำตอบ:


20

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

getData*วิธีการทั้งหมดที่มีข้อเสียที่ว่าพวกเขาจะต้องมีคำอธิบายประกอบสำหรับประเภทการอนุมานในการทำงาน
โดยปกติแล้วจะมี/* @var string $foo */คำอธิบายประกอบอยู่ด้านบนการgetData*โทร
นี่เป็นกลิ่นเหม็นเล็กน้อยเนื่องจากควรประกาศประเภทของข้อมูลในคลาสที่มีข้อมูลไม่ใช่คลาสที่เรียกgetData*ใช้
สาเหตุที่เป็นเช่นนั้นหากข้อมูลมีการเปลี่ยนแปลงชั้นเรียนมีแนวโน้มที่จะได้รับการอัพเดทมากที่สุดไม่ใช่getData*ไซต์โทรทั้งหมด
นั่นคือเหตุผลที่ฉันคิดว่าวิธีการจริงช่วยเพิ่มความสามารถในการบำรุงรักษาเทียบกับการใช้getData*accessors

ดังนั้นฉันคิดว่ามันจะทำให้การแลกเปลี่ยนระหว่างการบำรุงรักษาและการใช้งานเร็วขึ้น (โค้ดน้อยกว่าในการเขียน)

โชคดีที่ทุกวันนี้ IDEs นั้นเก่งในการสร้างการติดตั้ง getter และ setter ให้กับเราดังนั้นการโต้แย้งนั้นก็ไม่ได้นำมาใช้อีกต่อไป

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

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

ข้อดี

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

จุดด้อย

  • มันง่ายสำหรับสิ่งที่ผิดพลาด
    • คำอธิบายประกอบเป็นความคิดเห็นพวกมันล้าสมัยง่ายเมื่อโค้ดวิวัฒนาการ แต่คำอธิบายประกอบไม่ได้รับการอัพเดต วิธีการจริงนั้นแข็งแกร่งกว่า
    • เป็นไปได้ที่จะเพิ่มคำอธิบายประกอบหลายรายการที่มีลายเซ็นประเภทที่แตกต่างกันโดยไม่มีข้อผิดพลาดล่าม - พฤติกรรมการวิเคราะห์รหัสแบบคงที่นั้นไม่ได้กำหนดไว้และอาจนำไปสู่ข้อบกพร่องที่ละเอียดอ่อน
    • หากทั้ง@methodคำอธิบายประกอบและวิธีจริงที่มีชื่อเดียวกันมีอยู่ลายเซ็นประเภทคำอธิบายประกอบจะแทนที่วิธีจริงระหว่างการวิเคราะห์รหัสคงที่ซึ่งเป็นสิ่งที่ตรงกันข้ามกับสิ่งที่ล่าม PHP ทำ สิ่งนี้สามารถนำไปสู่ข้อบกพร่องที่ละเอียดอ่อนได้อีกครั้ง

ด้วยเหตุผลข้างต้นฉันเองไม่ได้ใช้@methodบันทึกย่อหากฉันสามารถหลีกเลี่ยงได้
สำหรับโค้ดที่ตั้งใจจะใช้งานได้นานฉันใช้เมธอด getter และ setter จริง การบำรุงรักษาที่เพิ่มขึ้นนั้นคุ้มค่ากับความพยายามในการกระตุ้น IDE เพื่อสร้างมันขึ้นมา

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


สรุปที่ดี ขอบคุณ Vinai คำตอบนั้นมากกว่าที่ฉันถามจริง
sv3n

1

getData*วิธีการทั้งหมดที่มีข้อเสียที่ว่าพวกเขาจะต้องมีคำอธิบายประกอบสำหรับประเภทการอนุมานในการทำงาน

โดยปกติแล้วจะมี/*@var string $foo */คำอธิบายประกอบอยู่ด้านบนการgetData*โทร นี่เป็นกลิ่นเหม็นเล็กน้อยเนื่องจากควรประกาศประเภทของข้อมูลในคลาสที่มีข้อมูลไม่ใช่คลาสที่เรียกใช้ getData *

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

ใช่มันมีกลิ่น แต่สามารถ (และควร?) หลีกเลี่ยง ฉันคิดว่านี่เป็นรหัสทั่วไปมากและมักจะแนะนำ:

/** @var Foo $product */
$product = $model->getProduct()
if ($product->getId()) {
    $product->doSomething();
}

ปัญหาคือคุณเพียงแค่เดาว่าค่าส่งคืนเป็นชนิดที่FooมีgetId()เมโทดcallable

เพื่อการบำรุงรักษาทำไมไม่คิดประเภทตัวแปรและเพิ่ม InvalidArgumentException ?

$product = $model->getProduct()
if ($product instanceof Foo && $product->getId()) {
    $product->doSomething();
}

นี้แก้ analyzation รหัสคงที่ในกรณีที่มีผลตอบแทนที่แตกต่างกันประเภทที่ชอบ$model->getProduct() - Foo|falseในกรณีแรกก็จะบ่นเกี่ยวกับการเรียกบนที่เป็นไปได้doSomething()false

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