Cara mendokumentasikan pengecualian yang dilemparkan di c # /. Net

139

Saat ini saya sedang menulis kerangka kerja kecil yang akan digunakan secara internal oleh pengembang lain dalam perusahaan.

Saya ingin memberikan informasi Intellisense yang baik, tetapi saya tidak yakin bagaimana cara mendokumentasikan pengecualian yang dilemparkan.

Dalam contoh berikut:

public void MyMethod1()
{
    MyMethod2();

    // also may throw InvalidOperationException
}

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException

    // also may throw DivideByZeroException
}

Saya tahu markup untuk mendokumentasikan pengecualian adalah:

/// <exception cref="SomeException">when things go wrong.</exception>

Apa yang saya tidak mengerti adalah bagaimana mendokumentasikan pengecualian yang dilemparkan oleh kode yang dipanggil oleh MyMethod1() ?

  • Haruskah saya mendokumentasikan pengecualian yang diajukan MyMethod2()
  • Haruskah saya mendokumentasikan pengecualian yang diajukan File.Open()?

Apa cara terbaik untuk mendokumentasikan kemungkinan pengecualian?

Arnold Zokas
sumber
4
Saya tahu ini bukan apa yang Anda tanyakan (dan ini adalah pertanyaan yang sangat lama) tetapi Eric Lippert (pengembang utama pada kompiler dan tim desain microsoft C) menulis posting blog tentang 4 jenis pengecualian yang saya pikir setiap pengembang harus berpikir tentang saat menulis pengecualian penanganan kode: blogs.msdn.com/b/ericlippert/archive/2008/09/10/...
javajavajavajavajava
@javajavajavajavajava Terima kasih atas tautannya - pasti layak dibaca.
Arnold Zokas
Saya pikir ini adalah pertanyaan yang valid karena tidak jelas sama sekali bagaimana mendokumentasikan pengecualian dalam C # dan pandangan 50K menunjukkan bahwa itu juga tidak jelas bagi banyak orang. Jawaban terbanyak kedua sangat membantu karena menunjukkan untuk menggunakan xmldocs yang ada untuk mendokumentasikan ini. Voting untuk dibuka kembali. Alasan dekat "berbasis opini" ini membunuh banyak pertanyaan pemrograman yang sebenarnya sangat berguna.
Alexei

Jawaban:

110

Anda harus mendokumentasikan setiap pengecualian yang mungkin dilontarkan oleh kode Anda, termasuk yang ada dalam metode apa pun yang mungkin Anda panggil.

Jika daftar menjadi agak besar, Anda mungkin ingin membuat jenis pengecualian Anda sendiri. Tangkap semua yang mungkin Anda temui dalam metode Anda, bungkus dengan pengecualian Anda, dan buang itu.

Tempat lain yang mungkin ingin Anda lakukan dengan cara ini adalah jika metode Anda ada di depan API Anda. Seperti halnya fasad menyederhanakan banyak antarmuka menjadi satu antarmuka tunggal, API Anda harus menyederhanakan banyak pengecualian menjadi satu pengecualian. Membuat penggunaan kode Anda lebih mudah bagi penelepon.


Untuk menjawab beberapa kekhawatiran Andrew (dari komentar), ada tiga jenis pengecualian: Yang tidak Anda ketahui, yang Anda tahu dan tidak bisa lakukan, dan yang Anda tahu dan bisa Anda lakukan.

Yang Anda tidak tahu tentang Anda ingin melepaskannya. Ini adalah prinsip gagal cepat - lebih baik aplikasi Anda mogok daripada memasuki keadaan di mana Anda mungkin akhirnya merusak data Anda. Kecelakaan akan memberi tahu Anda tentang apa yang terjadi dan mengapa, yang dapat membantu memindahkan pengecualian itu dari daftar "yang tidak Anda ketahui".

Yang Anda ketahui dan tidak bisa lakukan adalah pengecualian seperti OutOfMemoryExceptions. Dalam kasus ekstrem, Anda mungkin ingin menangani pengecualian seperti ini, tetapi kecuali jika Anda memiliki beberapa persyaratan yang cukup luar biasa, Anda memperlakukannya seperti kategori pertama - biarkan mereka pergi. Apakah Anda harus mendokumentasikan pengecualian ini? Anda akan terlihat sangat bodoh mendokumentasikan OOM pada setiap metode yang baru saja menemukan objek.

Yang Anda tahu dan bisa lakukan sesuatu adalah yang harus Anda dokumentasikan dan bungkus.

Anda dapat menemukan beberapa panduan lebih lanjut tentang penanganan pengecualian di sini.


sumber
3
Saya harus mengakui ini kedengarannya tidak praktis. Saya tidak dapat membayangkan berapa banyak pengecualian potensial yang dapat dilemparkan oleh kode apa pun yang saya sebut, plus ada hal-hal seperti OutOfMemoryException yang tidak ingin Anda tangkap dan bungkus.
Andrew Hare
3
Apakah jawaban Anda baik, tetapi sebenarnya dua jawaban yang saling bertentangan. "mendokumentasikan setiap pengecualian yang mungkin dilontarkan oleh kode Anda" dan "Yang Anda ketahui dan dapat Anda lakukan adalah yang harus Anda dokumentasikan".
tymtam
2
@Tymek: Tidak. Babak pertama menjawab pertanyaan "bagaimana saya harus mendokumentasikan pengecualian", bagian kedua menunjukkan jawaban yang jelas jelas untuk "pengecualian apa yang harus saya dokumentasikan." Yang pertama tidak menyiratkan bahwa Anda mendokumentasikan setiap pengecualian yang mungkin pernah terjadi. Beberapa orang terlalu harfiah, yang membutuhkan babak kedua.
5
@Tymek Saya pikir maksud Anda adalah jika Anda dapat melakukan sesuatu tentang hal itu, mengapa tidak melakukan sesuatu tentang hal itu alih-alih memikirkan kembali dan mendokumentasikannya? Mungkin lebih tepat untuk mengatakan "Yang Anda tahu tentang kode klien dapat melakukan sesuatu tentang". Ini menghilangkan kontradiksi, karena ini adalah pengecualian ideal untuk didokumentasikan.
mo.
Adapun pengecualian yang Anda 'lepaskan', Anda selalu dapat menangkapnya pada tingkat yang lebih rendah yang mencatatnya atau sesuatu. Kamu tahu; hanya membuat cara yang ramah pengguna untuk membiarkan program macet.
Nyerguds
96

Anda harus menggunakan dokumentasi xml standar .

/// <exception cref="InvalidOperationException">Why it's thrown.</exception>
/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod1()
{
    MyMethod2();
    // ... other stuff here
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod2()
{
    System.IO.File.Open(somepath...);
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
public void MyMethod3()
{
    try
    {
        MyMethod2();
    }
    catch (DivideByZeroException ex)
    {
        Trace.Warning("We tried to divide by zero, but we can continue.");
    }
}

Nilai dalam melakukannya dengan cara ini adalah Anda memberikan dokumentasi pengecualian yang diketahui yang dapat terjadi. Dokumentasi ini tersedia di intellisense jika Anda menggunakan studio visual dan dapat mengingatkan Anda (atau orang lain) nanti tentang pengecualian yang dapat Anda harapkan.

Anda ingin menentukan jenis pengecualian tertentu, karena Anda mungkin dapat menangani satu jenis pengecualian, sementara jenis lainnya adalah hasil dari masalah serius dan tidak dapat diperbaiki.

menggigil42
sumber
1
Bagaimana itu menambah nilai? Misalnya, semua pengecualian ini adalah turunan dari tipe Pengecualian. Dari pengalaman saya, tidak praktis untuk memikirkan setiap jenis pengecualian lain yang mungkin dilempar dari API lain yang disebut dalam metode Anda. Maksud saya adalah, kita tidak perlu khawatir tentang pengecualian yang dilemparkan dari suatu metode daripada yang membawa informasi Bisnis.
Illuminati
7
@ShiranGinige pengalaman Anda salah.
Grozz
35

Anda dapat membuat proses dokumentasi Anda lebih mudah dengan menggunakan beberapa peralatan tambahan yang hebat. Salah satunya adalah GhostDoc , add-in gratis untuk Visual Studio yang menghasilkan komentar XML-doc. Juga, jika Anda menggunakan ReSharper , lihat Plugin Agent Johnson yang luar biasa untuk ReSharper, yang menambahkan opsi untuk menghasilkan komentar XML untuk pengecualian yang dilemparkan.

Pembaruan: Tampaknya Agen Johnson tidak tersedia untuk R # 8, checkout Luar Biasa untuk ReSharper sebagai alternatif ...

Langkah 1: GhostDoc menghasilkan komentar XML (Ctrl-Shift-D), sementara plugin Agent Johnson untuk ReSharper menyarankan untuk mendokumentasikan pengecualian juga:

Langkah 1

Langkah 2: Gunakan tombol pintas ReSharper (Alt-Enter) untuk menambahkan dokumentasi pengecualian juga:

langkah 2 http://i41.tinypic.com/osdhm

Semoga itu bisa membantu :)

Igal Tabachnik
sumber
Tautan tinypic terputus.
ANeves
11

Dari apa yang saya pahami, niat menggunakan elemen <exception> adalah menggunakannya saat mendekorasi metode, bukan pengecualian:

/// <summary>Does something!</summary>
/// <exception cref="DidNothingException">Thrown if nothing is actually done.</exception>
public void DoSomething()
{
// There be logic here
}

Pengecualian yang dapat dilemparkan dengan metode lain yang disebut harus ditangkap, ditangani, dan didokumentasikan dalam metode tersebut. Pengecualian yang mungkin dilemparkan oleh .NET, atau pengecualian yang secara eksplisit dilemparkan oleh kode Anda sendiri harus didokumentasikan.

Sejauh mendapatkan lebih spesifik dari itu, mungkin Anda bisa menangkap dan melempar pengecualian Anda sendiri?

Daniel Schaffer
sumber
4

Bagian dari kontrak untuk metode Anda harus memastikan bahwa prasyarat tersebut valid, jadi:

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException
}

menjadi

/// <exception cref="FileNotFoundException">Thrown when somepath isn't a real file.</exception>
public void MyMethod2()
{
    FileInfo fi = new FileInfo( somepath );
    if( !fi.Exists )
    {
        throw new FileNotFoundException("somepath doesn't exists")
    }
    // Maybe go on to check you have permissions to read from it.

    System.IO.File.Open(somepath...); // this may still throw FileNotFoundException though
}

Dengan pendekatan ini, lebih mudah untuk mendokumentasikan semua pengecualian yang Anda lemparkan secara eksplisit tanpa harus mendokumentasikan bahwa OutOfMemoryException mungkin ada yang dibuang, dll.

Rowland Shaw
sumber
1
Tidak yakin apa gunanya cek itu jika Anda hanya akan menduplikasi pengecualian bahwa Openpanggilan akan dibuang (belum lagi, seperti yang Anda perhatikan, bahwa ada perlombaan dan cek tidak menjamin keberhasilan Open) .. .
Matt Enright
1
@MattEnright Diberikan, tapi saya membuat ini sedikit dibikin untuk mengilustrasikan poin ...
Rowland Shaw
1

Anda harus mendokumentasikan semua pengecualian yang mungkin dapat dilemparkan dengan metode Anda.

Untuk menyembunyikan detail implementasi, saya akan mencoba menangani beberapa pengecualian dari MyMethod2 sendiri.

Anda dapat mempertimbangkan untuk mengembalikannya, jika Anda tidak dapat menangani atau memecahkan pengecualian. Sebagian besar dikemas / dibungkus dengan pengecualian yang lebih bermakna bagi penelepon.

GvS
sumber
1

Memang, seperti yang sudah dijawab, cara mendokumentasikan pengecualian menggunakan Komentar XML.

Selain plugin, Anda juga dapat menggunakan alat analisis statis yang dapat diintegrasikan dengan TFS untuk memastikan Anda memiliki pengecualian yang didokumentasikan.

Di tautan di bawah ini Anda dapat melihat cara membuat aturan khusus untuk StyleCop untuk memvalidasi pengecualian yang dilemparkan oleh metode Anda yang sedang didokumentasikan.

http://www.josefcobonnin.com/post/2009/01/11/Xml-Documentation-Comments-Exceptions-I.aspx http://www.josefcobonnin.com/post/2009/01/15/Xml-Documentation -Komentar-Pengecualian-II.aspx

Salam.


sumber
0

Dokumentasikan pengecualian yang diharapkan dalam metode Anda, dalam contoh Anda, saya akan memberi tahu pengguna bahwa metode itu dapat membuang file tidak ditemukan pengecualian.

Ingatlah bahwa ini adalah untuk memberi tahu si penelepon tentang apa yang diharapkan sehingga mereka dapat memilih cara menghadapinya.

Damien
sumber