วิธีปฏิบัติที่ดีที่สุดสำหรับการเริ่มต้นสมาชิกคลาสใน php


10

ฉันมีรหัสจำนวนมากเช่นนี้ในตัวสร้างของฉัน: -

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

มันจะดีกว่าที่จะทำเช่นนี้แทนที่จะระบุค่าเริ่มต้นในการกำหนดคุณสมบัติ? คือpublic $property = default_valอะไร บางครั้งมีตรรกะสำหรับค่าเริ่มต้นและค่าเริ่มต้นบางอย่างมาจากคุณสมบัติอื่นซึ่งเป็นสาเหตุที่ฉันทำเช่นนี้ในตัวสร้าง

ฉันควรใช้ตัวตั้งค่าเพื่อแยกตรรกะทั้งหมดสำหรับค่าเริ่มต้นหรือไม่

คำตอบ:


8

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

สิ่งหนึ่งที่ฉันเห็นว่าอาจช่วยตอบคำถามก็คือการผ่าน $ params ซึ่งอาจมีหรือไม่มีสมาชิกแอททริบิว / อาร์เรย์ที่ตั้งค่าไว้

ในช่วงหลายปีที่ผ่านมาฉันได้ข้อสรุปนี้:

หลีกเลี่ยงการผ่านอาร์เรย์

ทำไม? ไม่มีวิธีตั้งค่าหรือกำหนดค่าของ Sentinel สำหรับอาร์กิวเมนต์ที่ส่งเป็นทางเลือก

กล่าวอีกนัยหนึ่งเมื่อคุณใช้รหัสที่คุณระบุคุณไม่สามารถทำสิ่งนี้ได้:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1 และ $ arg2 เป็นอาร์กิวเมนต์ตัวเลือก - หากไม่ผ่านก็มี NULL และ DEFAULT_VAL ตามลำดับ - ไม่จำเป็นต้องตรวจสอบอย่างชัดเจน

บางทีนี่อาจจะเป็นเรื่องที่ไม่มีเหตุผล

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

ถ้าไม่ผ่านตัวแปร "atomic" (สตริง, จำนวนเต็ม, ตัวอักษร) จากนั้นส่งผ่านวัตถุ

มีประโยชน์ด้านประสิทธิภาพที่นี่เนื่องจากการส่งวัตถุทำได้โดยการอ้างอิง (แม้ว่าอาร์เรย์ฉันคิดว่าเหมือนกันภายใน PHP)

ดังนั้นคุณอาจทำสิ่งที่ชอบ:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

อาร์กิวเมนต์วัตถุที่ผ่านไปนั้นจะรับประกันว่าจะมี "คุณสมบัติ 1", "คุณสมบัติ 2" แม้ว่าอาจมีค่าเริ่มต้นเอง

นอกจากนี้ที่นี่คุณสามารถพิมพ์คำใบ้และ IDE ที่ดีจะทำการกรอกรหัสให้ถูกต้องโดยอัตโนมัติ

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

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

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

ตอนนี้นี่ไม่ได้เป็นการบอกว่าคุณไม่ควรทำให้ข้อมูลของคุณสะอาด นั่นเป็นอีกการสนทนาทั้งหมด

หวังว่านี่จะช่วยได้


1
มันเป็นจุดที่ดีและมีประโยชน์มากสำหรับการแจ้งให้ IDE แต่มีคุณสมบัติของวัตถุมากเกินกว่าที่จะส่งผ่านพวกเขาทั้งหมดเป็นพารามิเตอร์ หากคุณมีข้อโต้แย้ง 7 ข้อว่าข้อ 5 ข้อเป็นตัวเลือกคุณจะได้สิ่งที่ต้องการnew object($param1,-some default value so I can specify the next parameter-, $param3);และคุณมีค่าเริ่มต้นของคุณที่กำหนดค่าไว้อย่างหนักในหลาย ๆ ที่
rgvcorley

3

แม้ว่าฉันมักจะหลีกเลี่ยงการส่งผ่านอาร์เรย์ไปยังตัวสร้าง แต่บางครั้งฉันก็จำเป็นต้องประมวลผลค่าอาร์เรย์ขาเข้า (เช่นคลาสที่อ่านค่าจากไฟล์กำหนดค่า)

ในกรณีเช่นนี้ฉันจะใช้ประโยชน์จากฟังก์ชั่นอาร์เรย์ของ PHP เพื่อให้แน่ใจว่าฉันกำลังทำงานกับสิ่งที่ฉันคิดว่าฉันทำงานด้วย:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

ที่ใช้บรรทัดสุดท้ายarray_merge()เขียนทับค่าใด ๆ ในที่มีค่าที่สอดคล้องกันของพวกเขาจาก$defaults $incomingฉันยังใช้array_intersect_key()เพื่อให้แน่ใจว่าอาร์เรย์ผลลัพธ์ไม่มีคีย์พิเศษใด ๆ ที่คลาส / วิธีไม่ทราบวิธีการประมวลผล


สวัสดีพฤติกรรมคืออะไรถ้าค่าเริ่มต้น $ มีอาร์เรย์แทนที่จะเป็นตัวแปรอย่างง่าย
Pol Dellaiera

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