มันเป็นวิธีการเขียนโปรแกรมที่ไม่ดีในการสร้างบางสิ่งบางอย่างในการรับถ้ามันไม่ได้อยู่?


18

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

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

สิ่งที่ฉันสงสัยว่าอยู่ในห้องสมุดนี้ถ้าฉันจะสร้างบัญชีgetAccount(accountName)ที่จะได้รับบัญชีหากมีอยู่แล้วและถ้ามันไม่สร้างและส่งคืนข้อมูลนั่นเป็นสิ่งที่ไม่ดีหรือไม่? ฉันควรปล่อยให้ลูกค้าจัดการกับข้อยกเว้นหรือเพียงแค่ตั้งชื่อบางอย่างเช่น getOrCreateAccount? มันสำคัญไหม

มันเป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ที่จะสร้างบางอย่างในการทำงาน


9
อย่างน้อยที่สุดฉันจะตั้งชื่อgetOrCreateAccountหรือคล้ายกัน
Telastyn

4
ดูเหมือนว่าถูกต้องในบริบทของการเริ่มต้นขี้เกียจ อย่างไรก็ตามขึ้นอยู่กับว่าคุณต้องการใช้รูปแบบนั้นในไลบรารีของคุณหรือไม่
Chris C

1
ผมชอบคำกริยาเช่นacquire acquireAccountมันไม่มีความหมายที่มีอยู่ในโปรโตคอลหลัก ๆ ที่ฉันได้พบและมันมีความจำเป็นที่จะต้องเหมาะสมกับมัน "ทำทุกสิ่งที่คุณต้องทำเพื่อให้ได้มาหนึ่งสิ่งนี้สำหรับฉันขอสร้างปลอมปลอมขโมยฉันไม่สนใจแค่เอามาให้ฉันหรือพยายามตาย"
Dan Ross

2
"ลูกค้ามักจะต้องการสร้างบัญชี" ซึ่งดูเหมือนจะผิดปกติอย่างมาก หากฉันไม่สามารถรับบัญชีได้เนื่องจากผู้ใช้พิมพ์ชื่อผู้ใช้ผิดฉันไม่ต้องการสร้างบัญชีด้วยชื่อพิมพ์ผิด
gnasher729

ตามข้อมูลจำเพาะของ javabean oracle.com/technetwork/articles/javaee/spec-136004.html ใช้ getSomething()สำหรับผู้ได้รับและsetSomething()สำหรับผู้ตั้งค่า Imo อะไรที่ทำอะไรบางอย่างทางปัญญาอื่น ๆ ต้องเรียกว่าอย่างอื่นเช่นfetchSomething, obtainSomething, computeSomethingหรือdoSomethingElseอื่น ๆ
ccpizza

คำตอบ:


31

ใช่มันเป็นเรื่องสำคัญ ในความคิดของฉันมันเป็นวิธีปฏิบัติที่ไม่ดีในการสร้างบางสิ่งบางอย่างในขั้นตอนที่ไม่ได้จัดทำเป็นเอกสารว่ามีพลังในการสร้าง ทั้งชื่อขั้นตอนgetOrCreate...หรือมีแยกcreate...ขั้นตอนแล้วถ้าคุณจริงๆต้องการมีgetOrCreate...ที่ความพยายามครั้งแรกget...และหากที่ล้มเหลวโทรแล้วโทรออกcreate...get...

ผู้ใช้ไลบรารีอาจไม่คาดหวังว่าget...กระบวนการจะสร้างหากการดำเนินการ get ล้มเหลว หากพวกเขาพบว่าการทดสอบเรียกร้องให้get...สร้างข้อมูลทั้งหมดจำนวนมหาศาลพวกเขาอาจจะประหลาดใจ และพวกเขาทำความสะอาดได้อย่างไร ถ้าพวกเขาเขียนโค้ดที่คิดว่าพวกเขาจะได้รับข้อผิดพลาดหากget...ล้มเหลวและพวกเขาต้องการจัดการในแบบของพวกเขา ?


ขอบคุณการสร้างคืนค่า ID ที่ได้รับก็เช่นกันดังนั้นฉันไม่จำเป็นต้องทำget... create... get...สองอันแรก ฉันจะพูดคุยกับลูกค้าเกี่ยวกับว่าพวกเขาจะต้องมีความสามารถในการโทรgetโดยไม่ต้องการที่จะสร้าง
ไมค์

6
@ ไมค์: ฉันยังคงคิดว่ามันควรจะcreateอยู่ในชื่อเพียงเพื่อให้ชัดเจน 100% เกี่ยวกับสิ่งที่เกิดขึ้น
FrustratedWithFormsDesigner

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

1
นี่มันช้าไปแล้ว แต่getOrCreateมีความสำคัญกว่าในเว็บเฟรมเวิร์กยอดนิยม: docs.djangoproject.com/en/1.10/ref/models/querysets/…
tex

18

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


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

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

สำหรับบันทึกมันเป็นห้องสมุดภายในทั้งหมดและฉันมีความสามารถที่จะบอกทีมว่าใช้มันได้ผลอย่างไร
Mike

1
@ jmort253: บริการเป็นโมฆะหากไม่มีผลข้างเคียงที่ลูกค้าเห็น เซิร์ฟเวอร์สามารถทำได้ตามที่ต้องการ
วินไคลน์

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

10

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


+1 โดยทั่วไปแล้วGetOrCreateมันเป็นความหมายที่ผิดแต่การได้รับวัตถุซึ่งอาจ "เชิงตรรกะ" มีอยู่ไม่ว่ามันจะมีอยู่จริงหรือไม่ก็ตาม ตัวอย่างเช่นไอเท็มที่ผันแปรได้ของรายการที่ไม่แน่นอนอาจไม่มีการจัดเก็บข้อมูลใด ๆ สำหรับองค์ประกอบ 1,841,533 แต่ยังคงอนุญาตให้องค์ประกอบนั้น "ดึง" โดยการสร้างวัตถุใหม่จัดเก็บและส่งคืนการอ้างอิง
supercat

4

มันสมเหตุสมผลที่สุดในการสร้าง 3 วิธี:

getAccount -> ซึ่งเพิ่งได้รับบัญชี

createAccount -> สร้างบัญชี

getAccountAndCreateIfNeeded -> เลือกการตั้งชื่อของคุณเอง)

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

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

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


นอกจากนี้จากรหัสสะอาด: "หากวิธีการของคุณไม่สามารถทำสิ่งที่ชื่อของมันหมายถึงแล้วโยนข้อยกเว้น" ฉันมีบล็อกลอง / จับภายใน 'GetOrCreateIfneeded' ที่ส่ง GET ที่ล้มเหลวแล้วมี 'createAccount' ในการโยนสำหรับประเภทการยกเว้นใด ๆ ที่กลับมาสำหรับการรับที่ล้มเหลว
เกรแฮม

ฉันอาจแนะนำวิธีที่สี่: getAccountIfExistsซึ่งอาจได้รับบัญชีหรือระบุว่าไม่มีอยู่หากไม่ได้สร้างบัญชีใหม่ getAccountวิธีตัวเองควรส่อว่าบัญชีที่มีอยู่และโยนยกเว้นหากไม่ได้
supercat

2

มันขึ้นอยู่กับสถานการณ์

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

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

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

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