ฉันควรตรวจสอบว่ามีบางสิ่งบางอย่างใน db และล้มเหลวอย่างรวดเร็วหรือรอข้อยกเว้น db


32

มีสองคลาส:

public class Parent 
{
    public int Id { get; set; }
    public int ChildId { get; set; }
}

public class Child { ... }

เมื่อกำหนดChildIdให้Parentฉันควรตรวจสอบก่อนว่ามันมีอยู่ในฐานข้อมูลหรือรอให้ฐานข้อมูลเกิดข้อยกเว้นหรือไม่

ตัวอย่างเช่น (ใช้ Entity Framework Core):

หมายเหตุการตรวจสอบประเภทนี้มีอยู่ทั่วอินเทอร์เน็ตแม้ในเอกสารอย่างเป็นทางการของ Microsoft: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using- mvc / handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application # modified-the-department-controllerแต่มีการจัดการข้อยกเว้นเพิ่มเติมสำหรับSaveChanges

นอกจากนี้โปรดทราบว่าจุดประสงค์หลักของการตรวจสอบนี้คือการส่งคืนข้อความที่เป็นมิตรและสถานะ HTTP ที่เป็นที่รู้จักแก่ผู้ใช้ API และไม่ละเว้นข้อยกเว้นฐานข้อมูลอย่างสมบูรณ์ และยกเว้นสถานที่เดียวที่จะถูกโยนอยู่ภายในSaveChangesหรือSaveChangesAsyncโทร ... ดังนั้นจะไม่มีข้อยกเว้นใด ๆ เมื่อคุณโทรหรือFindAsync Anyดังนั้นหากเด็กมีอยู่ แต่ถูกลบไปก่อนSaveChangesAsyncข้อยกเว้นจะเกิดขึ้นพร้อมกัน

ฉันทำสิ่งนี้เนื่องจากข้อเท็จจริงที่ว่าการforeign key violationจัดรูปแบบข้อยกเว้นจะยากกว่ามากในการแสดง "เด็กที่มี id {parent.ChildId} ไม่พบ"

public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
    // is this code redundant?
   // NOTE: its probably better to use Any isntead of FindAsync because FindAsync selects *, and Any selects 1
    var child = await _db.Children.FindAsync(parent.ChildId);
    if (child == null)
       return NotFound($"Child with id {parent.ChildId} could not be found.");

    _db.Parents.Add(parent);    
    await _db.SaveChangesAsync();        

    return parent;
}

เมื่อเทียบกับ:

public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
    _db.Parents.Add(parent);
    await _db.SaveChangesAsync();  // handle exception somewhere globally when child with the specified id doesn't exist...  

    return parent;
}

ตัวอย่างที่สองใน Postgres จะแสดง23503 foreign_key_violationข้อผิดพลาด: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html

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

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

ที่เกี่ยวข้อง:

https://stackoverflow.com/questions/6171588/preventing-race-condition-of-if-exists-update-else-insert-in-entity-framework

https://stackoverflow.com/questions/4189954/implementing-if-not-exists-insert-using-entity-framework-without-race-conditions

https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries


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

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

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

1
@ Konrad มีข้อยกเว้นอะไรเกี่ยวกับมันบ้าง? หยุดคิดถึงสภาพการแข่งขันเป็นสิ่งที่อยู่ในรหัสของคุณ: มันเป็นสมบัติของจักรวาล สิ่งใดก็ตามที่สัมผัสกับทรัพยากรที่ไม่ได้ควบคุมอย่างสมบูรณ์ (เช่นการเข้าถึงหน่วยความจำโดยตรง, หน่วยความจำที่แชร์, ฐานข้อมูล, REST API, ระบบไฟล์, ฯลฯ ) มากกว่าหนึ่งครั้งและคาดว่าจะไม่มีการเปลี่ยนแปลงใด ๆ Heck เราจัดการกับเรื่องนี้ใน C ซึ่งไม่ได้มีข้อยกเว้น อย่าเพิ่งแยกสาขากับสถานะของทรัพยากรที่คุณไม่ได้ควบคุมถ้าสาขาอย่างน้อยหนึ่งสาขายุ่งกับสถานะของทรัพยากรนั้น
Jared Smith

1
@DanielPryden ในคำถามของฉันฉันไม่ได้บอกว่าฉันไม่ต้องการจัดการข้อยกเว้นฐานข้อมูล (ฉันรู้ว่าข้อยกเว้นนั้นหลีกเลี่ยงไม่ได้) ผมคิดว่าหลาย ๆ คนเข้าใจผิดผมอยากที่จะมีข้อผิดพลาดที่เป็นมิตรสำหรับ Web API ของฉัน (สำหรับผู้ใช้ในการอ่าน) Child with id {parent.ChildId} could not be found.เช่น และการจัดรูปแบบ "การละเมิดคีย์ต่างประเทศ" ฉันคิดว่าแย่ลงในกรณีนี้
Konrad

คำตอบ:


3

ค่อนข้างคำถามสับสน แต่ใช่คุณควรตรวจสอบก่อนและไม่เพียงจัดการข้อยกเว้นฐานข้อมูล

ในตัวอย่างของคุณคุณอยู่ที่ชั้นข้อมูลโดยใช้ EF โดยตรงบนฐานข้อมูลเพื่อเรียกใช้ SQL รหัสของคุณเทียบเท่ากับการทำงาน

select * from children where id = x
//if no results, perform logic
insert into parents (blah)

ทางเลือกที่คุณแนะนำคือ:

insert into parents (blah)
//if exception, perform logic

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

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

using (var transaction = new TransactionScope())
{
    var child = await _db.Children.FindAsync(parent.ChildId);
    if (child == null) 
    {
       return NotFound($"Child with id {parent.ChildId} could not be found.");
    }

    _db.Parents.Add(parent);    
    await _db.SaveChangesAsync();        
    transaction.Complete();

    return parent;
}

สิ่งสำคัญคือการถามตัวเอง:

"คุณคาดหวังว่าสถานการณ์นี้จะเกิดขึ้นหรือไม่"

ถ้าไม่เช่นนั้นให้แน่ใจว่าแทรกออกไปและโยนข้อยกเว้น แต่เพียงจัดการข้อยกเว้นเช่นข้อผิดพลาดอื่น ๆ ที่อาจเกิดขึ้น

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

แก้ไข - มีข้อโต้แย้งมากมายเกี่ยวกับเรื่องนี้ ก่อนที่คุณจะลงคะแนนให้พิจารณา:

A. จะเกิดอะไรขึ้นถ้ามีข้อ จำกัด FK สองข้อ คุณจะสนับสนุนการแยกวิเคราะห์ข้อความแสดงข้อผิดพลาดเพื่อหาว่าวัตถุใดหายไปหรือไม่

B. หากคุณพลาดจะมีคำสั่ง SQL เพียงคำสั่งเดียวเท่านั้น มันเป็นเพียงความนิยมที่ต้องเสียค่าใช้จ่ายเพิ่มเติมของการค้นหาครั้งที่สอง

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


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
maple_shaft

1
นี่เป็นความผิดทั้งหมดและทำให้เข้าใจผิด! มันเป็นคำตอบเช่นนี้ที่สร้างมืออาชีพที่ไม่ดีที่ฉันต้องต่อสู้ SELECT ไม่ล็อคตารางดังนั้นระหว่าง SELECT และ INSERT, UPDATE หรือ DELTE เรคคอร์ดอาจเปลี่ยนแปลงได้ ดังนั้นจึงเป็นซอฟต์แวร์หมัดที่ไม่ดียอมและอุบัติเหตุที่เกิดขึ้นในการผลิต
Daniel Lobo

1
@DanielLobo transactioncope แก้ไขนั่น
Ewan

1
ทดสอบถ้าคุณไม่เชื่อฉัน
Ewan

1
@yusha ฉันมีรหัสที่นี่
Ewan

111

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


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

6
@ Konrad ตำแหน่งของฉันคือตัวเลือกที่ถูกต้องเป็นค่าเริ่มต้นคือหนึ่งแบบสอบถามที่จะล้มเหลวในตัวเองและเป็นวิธีการสอบถามล่วงหน้าแยกต่างหากที่มีภาระการพิสูจน์เพื่อพิสูจน์ตัวเอง สำหรับ "กลายเป็นปัญหา": คุณกำลัง ใช้การทำธุรกรรมหรืออื่น ๆ เพื่อให้แน่ใจว่าคุณปลอดภัยจากข้อผิดพลาด ToCToUใช่ไหม? ไม่ชัดเจนสำหรับฉันจากโค้ดที่โพสต์ว่าคุณเป็น แต่ถ้าคุณไม่ใช่มันก็กลายเป็นปัญหาในแบบที่ระเบิดติ๊กกลายเป็นปัญหานานก่อนที่มันจะระเบิดจริง
mtraceur

4
@Konrad EF Core จะไม่ใส่ทั้งเช็คและการแทรกลงในธุรกรรมโดยปริยายคุณจะต้องขออย่างชัดเจน หากไม่มีธุรกรรมการตรวจสอบก่อนนั้นไม่มีจุดหมายเนื่องจากสถานะฐานข้อมูลสามารถเปลี่ยนแปลงระหว่างการตรวจสอบและการแทรกได้ แม้จะมีธุรกรรมคุณอาจไม่สามารถป้องกันฐานข้อมูลจากการเปลี่ยนแปลงได้ เราพบปัญหาเมื่อไม่กี่ปีที่ผ่านมาโดยใช้ EF กับ Oracle ที่แม้ว่าฐานข้อมูลรองรับ แต่ Entity ไม่ได้เรียกการล็อกเร็กคอร์ดการอ่านภายในธุรกรรมและมีการแทรกเฉพาะที่ถือเป็นธุรกรรม
Mr.Mindor

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

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

38

ฉันคิดว่าสิ่งที่คุณเรียกว่า "ล้มเหลวอย่างรวดเร็ว" และสิ่งที่ฉันเรียกมันไม่เหมือนกัน

บอกฐานข้อมูลเพื่อทำการเปลี่ยนแปลงและจัดการกับความล้มเหลวนั่นก็คือรวดเร็ว วิธีการของคุณซับซ้อนช้าและไม่น่าเชื่อถือเป็นพิเศษ

เทคนิคของคุณนั้นไม่ได้ล้มเหลวอย่างรวดเร็วมันคือ“ การ preflighting” บางครั้งมีเหตุผลที่ดี แต่ไม่ใช่เมื่อคุณใช้ฐานข้อมูล


1
มีหลายกรณีที่คุณต้องการคิวรีที่ 2 เมื่อคลาสหนึ่งขึ้นอยู่กับคลาสอื่นดังนั้นคุณไม่มีตัวเลือกในกรณีเช่นนั้น
Konrad

4
แต่ไม่ใช่ที่นี่ และการสืบค้นฐานข้อมูลนั้นค่อนข้างฉลาดดังนั้นโดยทั่วไปฉันสงสัยว่า "ไม่มีตัวเลือก"
gnasher729

1
ฉันคิดว่ามันขึ้นอยู่กับแอพพลิเคชั่นด้วยถ้าคุณสร้างมันขึ้นมาสำหรับผู้ใช้เพียงไม่กี่คนมันก็ไม่ควรสร้างความแตกต่างและรหัสก็อ่านได้มากขึ้นด้วย 2 ข้อความค้นหา
Konrad

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

15

สิ่งนี้เริ่มต้นเป็นความคิดเห็น แต่ขยายใหญ่เกินไป

ไม่ตามคำตอบอื่น ๆ ที่ระบุไว้ไม่ควรใช้รูปแบบนี้ *

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

คุณต้องการการจัดการข้อผิดพลาดอยู่ดี

ในความคิดเห็นที่คุณถามว่าคุณต้องการข้อมูลจากหลายแหล่ง
ยังคงไม่.

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

คุณยังต้องการการจัดการข้อผิดพลาดอยู่ดี

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

คุณอาจยังต้องการฐานข้อมูลอื่นที่เกี่ยวข้องกับการจัดการข้อผิดพลาดอยู่ดี การจัดการข้อผิดพลาดนี้อาจเป็นชิ้นเล็ก ๆ

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

คุณยังต้องการการจัดการข้อผิดพลาดอยู่ดี

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

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

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


2

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

ฉันอยากแนะนำให้คุณ:

ก) แสดงข้อความข้อผิดพลาดทั่วไปที่เหมือนกันสำหรับผู้ใช้ทุกข้อผิดพลาดที่เกิดขึ้น

b) บันทึกข้อยกเว้นที่เกิดขึ้นจริงเฉพาะที่นักพัฒนาเท่านั้นที่สามารถเข้าถึง (ถ้าบนเซิร์ฟเวอร์) หรือที่อื่นที่สามารถส่งถึงคุณโดยเครื่องมือรายงานข้อผิดพลาด (หากลูกค้าปรับใช้)

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


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


2
"แสดงข้อความข้อผิดพลาดทั่วไปแบบเดียวกันสำหรับผู้ใช้ทุกข้อผิดพลาดที่เกิดขึ้น" นั่นเป็นเหตุผลหลักที่การจัดรูปแบบข้อยกเว้นสำหรับผู้ใช้ปลายทางดูเหมือนจะเป็นเรื่องที่น่ากลัวมาก ..
Konrad

1
ในระบบฐานข้อมูลที่สมเหตุสมผลใด ๆ คุณควรจะสามารถค้นหาสาเหตุโดยทางโปรแกรมได้ ไม่จำเป็นต้องแยกวิเคราะห์ข้อความแสดงข้อยกเว้น และโดยทั่วไปแล้ว: ใครบอกว่าข้อความแสดงข้อผิดพลาดจะต้องแสดงต่อผู้ใช้เลย คุณสามารถแทรกครั้งแรกและลองใหม่ในลูปจนกว่าคุณจะประสบความสำเร็จ (หรือมากถึงขีด จำกัด ของการลองใหม่หรือเวลา) และในความเป็นจริง backoff-and-retry เป็นสิ่งที่คุณต้องการนำไปใช้ในที่สุด
Daniel Pryden
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.