คุณส่งวัตถุหรือตัวแปรสมาชิกไปยังฟังก์ชั่นหรือไม่?


31

ซึ่งเป็นวิธีปฏิบัติที่ยอมรับกันโดยทั่วไประหว่างสองกรณีนี้:

function insertIntoDatabase(Account account, Otherthing thing) {
    database.insertMethod(account.getId(), thing.getId(), thing.getSomeValue());
}

หรือ

function insertIntoDatabase(long accountId, long thingId, double someValue) {
    database.insertMethod(accountId, thingId, someValue);
}

กล่าวอีกนัยหนึ่งโดยทั่วไปแล้วการส่งวัตถุทั้งหมดไปรอบ ๆ


5
มันทั้งหมดจะขึ้นอยู่กับสิ่งที่ฟังก์ชั่นสำหรับและวิธีการที่เกี่ยวข้อง (หรือไม่เกี่ยวข้อง) กับวัตถุที่มีปัญหา
MetaFight

นั่นคือปัญหา. ฉันไม่สามารถบอกได้ว่าฉันจะใช้อันใดอันหนึ่ง ฉันรู้สึกเหมือนฉันสามารถเปลี่ยนรหัสเพื่อรองรับวิธีการทั้งสองได้เสมอ
AJJ

1
ในข้อตกลง API (และไม่ได้ดูการใช้งานเลย) อดีตเป็นนามธรรมและมุ่งเน้นโดเมน (ซึ่งเป็นสิ่งที่ดี) ในขณะที่หลังไม่ได้ (ซึ่งไม่ดี)
Erik Eidt

1
วิธีแรกจะเป็น OO 3 ชั้นมากกว่า แต่ควรมีมากยิ่งขึ้นโดยการกำจัดคำฐานข้อมูลออกจากวิธีการ ควรเป็น "Store" หรือ "Persist" และทำบัญชีหรือสิ่งต่าง ๆ (ไม่ใช่ทั้งคู่) ในฐานะที่เป็นไคลเอนต์ของเลเยอร์นี้คุณไม่ควรระวังสื่อจัดเก็บข้อมูล เมื่อรับบัญชีคุณจะต้องผ่าน ID หรือการรวมกันของค่าคุณสมบัติ (ไม่ใช่ค่าฟิลด์) เพื่อระบุวัตถุที่ต้องการ หรือ / และฝังวิธีการแจงนับที่ส่งผ่านบัญชีทั้งหมด
Martin Maat

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

คำตอบ:


24

ไม่ดีกว่าอย่างอื่น มันเป็นการเรียกการตัดสินที่คุณต้องทำเป็นกรณีไป

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

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

function addWidgetButtonClicked(clickEvent) {
    // get form data
    // get user's account
    insertIntoDatabase(account, data);
}
function insertIntoDatabase(Account account, Otherthing data) {
    // open database connection
    // check data doesn't already exist
    database.insertMethod(account.getId(), data.getId(), data.getSomeValue());
}

VS

function addWidgetButtonClicked(clickEvent) {
    // get form data
    // get user's account
    insertIntoDatabase(account.getId(), data.getId(), data.getSomeValue());
}
function insertIntoDatabase(long accountId, long dataId, double someValue) {
    // open database connection
    // check data doesn't already exist
    database.insertMethod(accountId, dataId, someValue);
}

ในเวอร์ชันแรกรหัส UI นั้นจะส่งผ่านdataวัตถุอย่างสุ่มและขึ้นอยู่กับรหัสฐานข้อมูลเพื่อแยกเขตข้อมูลที่มีประโยชน์ออกมา ในเวอร์ชันที่สองรหัส UI จะแยกdataวัตถุออกเป็นฟิลด์ที่มีประโยชน์และรหัสฐานข้อมูลจะรับพวกเขาโดยตรงโดยไม่ทราบว่ามาจากไหน ความหมายหลักคือถ้าโครงสร้างของdataวัตถุมีการเปลี่ยนแปลงในบางวิธีรุ่นแรกจะต้องเปลี่ยนรหัสฐานข้อมูลเท่านั้นในขณะที่รุ่นที่สองจะต้องเปลี่ยนรหัส UIเท่านั้น ข้อใดที่สองเหล่านั้นถูกต้องขึ้นอยู่กับชนิดของข้อมูลที่dataมีในวัตถุ แต่โดยทั่วไปจะชัดเจนมาก ตัวอย่างเช่นถ้าdataเป็นสตริงที่ผู้ใช้ระบุเช่น "20/05/1999" ซึ่งควรเป็นรหัส UI เพื่อแปลงให้เป็นDateประเภทที่เหมาะสมก่อนส่งต่อ


8

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

วัตถุนั้นไม่เปลี่ยนรูปหรือไม่? ฟังก์ชั่น 'บริสุทธิ์' หรือไม่?

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

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

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

มีวิธีการขัดแย้งกันอยู่กี่ข้อ?

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

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

วัตถุที่ส่งผ่านนั้นเป็นของ "เลเยอร์" ภายในแอปพลิเคชันของคุณหรือไม่ (ตัวอย่างเช่น ViewModel หรือเอนทิตี ORM)

คิดเกี่ยวกับการแยกความกังวล (SoC) บางครั้งถามตัวเองว่าวัตถุ "เป็น" ของเลเยอร์หรือโมดูลเดียวกันซึ่งมีวิธีการของคุณอยู่หรือไม่ (เช่นไลบรารี wrapper API ที่รีดด้วยมือหรือ Core Business Layer Layer ของคุณเป็นต้น) สามารถแจ้งได้ว่าควรส่งวัตถุนั้นจริงหรือไม่ วิธี.

SoC เป็นรากฐานที่ดีสำหรับการเขียนโค้ดแบบแยกส่วนที่สะอาด ตัวอย่างเช่นวัตถุเอนทิตี ORM (การจับคู่ระหว่างรหัสของคุณกับสคีมาฐานข้อมูลของคุณ) ไม่ควรมีการนำมาใช้ในเลเยอร์ธุรกิจของคุณหรือแย่กว่านั้นในการนำเสนอ / UI เลเยอร์ของคุณ

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

ฟังก์ชันมีขนาดใหญ่เกินไปและ / หรือซับซ้อนเกินไปหรือไม่

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

ฟังก์ชันควรเป็นวัตถุคำสั่ง / แบบสอบถามหรือไม่

ในบางกรณีความสัมพันธ์ระหว่างข้อมูลและฟังก์ชั่นอาจจะปิด; ในกรณีดังกล่าวให้พิจารณาว่าCommand ObjectหรือQuery Objectนั้นเหมาะสมหรือไม่

การเพิ่มพารามิเตอร์วัตถุในวิธีการบังคับคลาสที่มีเพื่อนำมาใช้ใหม่ขึ้นอยู่กับการพึ่งพา?

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

คุณต้องการส่งผ่านวัตถุที่สมบูรณ์จริง ๆ หรือคุณต้องการเพียงส่วนเล็ก ๆ ของอินเทอร์เฟซของวัตถุนั้นหรือไม่

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


5

ดังนั้นเมื่อคุณสร้างฟังก์ชั่นคุณจะประกาศสัญญาโดยใช้รหัสที่เรียกมัน ฟังก์ชั่นนี้ใช้ข้อมูลนี้และเปลี่ยนเป็นสิ่งอื่น (อาจมีผลข้างเคียง)

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

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


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

3

มันขึ้นอยู่กับ.

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

void invite(String emailAddressString) {
  invite(EmailAddress.parse(emailAddressString));
}
void invite(EmailAddress emailAddress) {
  ...
}
void invite(User user) {
  invite(user.getEmailAddress());
}

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

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


0

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

insertIntoDatabase(new Account(id) , new Otherthing(id, "Value"));

เป็นการโทรที่อ่านได้ง่ายกว่า

insertIntoDatabase(myAccount.getId(), myOtherthing.getId(), myOtherthing.getValue() );

ไม่สามารถตกลงที่นั่น ทั้งสองไม่ได้มีความหมายเหมือนกัน การสร้างวัตถุ 2 อินสแตนซ์ใหม่เพื่อส่งต่อไปยังเมธอดนั้นไม่ดี ฉันจะใช้ insertIntoDatabase (myAccount, myOtherthing) แทนตัวเลือกใดตัวเลือกหนึ่งของคุณ
jwenting

0

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

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

ครั้งเดียวที่คุณควรเขียนวิธีการยอมรับฟิลด์บนวัตถุคือเมื่อเขียนวิธีการดึงข้อมูลวัตถุ:

public User getUser(String primaryKey) {
  return ...;
}

ณ จุดที่ทำการโทรนั้นรหัสการโทรยังไม่มีการอ้างอิงไปยังวัตถุเนื่องจากจุดที่เรียกวิธีนั้นคือการรับวัตถุ


1
"จะเกิดอะไรขึ้นหากคุณเปลี่ยนฟิลด์ในOtherthing" (1) นั่นจะเป็นการละเมิดหลักการเปิด / ปิด (2) แม้ว่าคุณจะผ่านในวัตถุทั้งรหัสภายในนั้นเข้าถึงสมาชิกของวัตถุว่า (และถ้ามันไม่ได้ผ่านวัตถุในทำไม?) ยังคงทำลาย ...
เดวิดอาร์โน

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

0

จากมุมมองของการบำรุงรักษาอาร์กิวเมนต์ควรแยกออกจากกันอย่างชัดเจนโดยเฉพาะอย่างยิ่งในระดับคอมไพเลอร์

// this has exactly one way to call it
insertIntoDatabase(Account ..., Otherthing ...)

// the parameter order can be confused in practice
insertIntoDatabase(long ..., long ...)

การออกแบบครั้งแรกนำไปสู่การตรวจหาข้อบกพร่องในระยะแรก การออกแบบที่สองสามารถนำไปสู่ปัญหา runtime ละเอียดที่ไม่แสดงในการทดสอบ ดังนั้นการออกแบบครั้งแรกจะเป็นที่ต้องการ


0

ในสองวิธีนี้การตั้งค่าของฉันเป็นวิธีแรก:

function insertIntoDatabase(Account account, Otherthing thing) { database.insertMethod(account.getId(), thing.getId(), thing.getSomeValue()); }

เหตุผลที่การเปลี่ยนแปลงที่ทำกับวัตถุใด ๆ ก็ตามบนท้องถนนตราบใดที่การเปลี่ยนแปลงยังคงรักษาตัวรับสัญญาณเหล่านั้นไว้ดังนั้นการเปลี่ยนแปลงนั้นจะโปร่งใสนอกวัตถุแล้วคุณจะมีรหัสน้อยกว่าในการเปลี่ยนแปลงและทดสอบและมีโอกาสน้อยกว่า

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

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

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

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

ฉันเดาว่ามี "ฐานข้อมูล" วัตถุที่สามอยู่แล้วและฉันโน้มตัวไปสู่การวางฟังก์ชันนี้ลงในวัตถุนั้นและจากนั้นจะกลายเป็นงานวัตถุที่จะสามารถจัดการบัญชีและ OtherThing แปลงแล้วยังยืนยันผลลัพธ์ .

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

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

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

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


0

ทั้งสองวิธีมีข้อดีและข้อเสียของตัวเอง สิ่งที่ดีกว่าในสถานการณ์นั้นขึ้นอยู่กับกรณีใช้งานในมือ


Pro หลาย params, การอ้างอิง Con Object:

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

การอ้างอิงวัตถุมืออาชีพ:

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

ดังนั้นสิ่งที่จะต้องใช้และเมื่อขึ้นอยู่กับการใช้งานเป็นจำนวนมาก

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

0

ในอีกด้านหนึ่งคุณมีบัญชีและวัตถุอื่น ๆ ในอีกด้านหนึ่งคุณมีความสามารถในการแทรกค่าลงในฐานข้อมูลกำหนดรหัสของบัญชีและรหัสของสิ่งอื่น ๆ นั่นคือสองสิ่งที่ได้รับ

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

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

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

ใน C ++ คุณสามารถมีวิธีรับสองรหัสบวกค่าและวิธีแบบอินไลน์รับบัญชีและสิ่งอื่น ๆ ดังนั้นคุณจึงมีทั้งสองวิธีโดยไม่มีค่าใช้จ่ายเป็นศูนย์

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