2014-10-01 2 views
-1

Предположим, я хочу создать библиотеку DLL, которая обеспечит общие службы файловой системы простым в использовании способом. Затем эту библиотеку можно использовать в сторонних приложениях .NET. Допустим, эта библиотека предоставляет только этот интерфейс для общественности:.Как сделать правильную обработку исключений при разработке библиотеки на C#?

public interface IFileSystemService 
{ 
    void CreateDirectory(string path); 
    void DeleteDirectory(string path); 
    bool DirectoryExists(string path); 
    IEnumerable<string> EnumerateDirectories(string path); 
    void DeleteFile(string path); 
    bool FileExists(string path); 
    void CopyFile(string sourcePath, string destinationPath, bool overwriteExisting); 
    // ... and other methods 
} 

Что бы наилучшая практика для обработки исключений, когда речь идет о реализации этого интерфейса с помощью стандартных .NET классов из System.IO пространств имен (например, FileInfo, DirectoryInfo, Directory, File и т.д ...)? Как я могу сделать эту библиотеку надежной и простой в использовании клиентским кодом? Как это сделать, чтобы клиентский код для обработки ошибок был чистым и не слишком сложным?

+0

https://github.com/aspnet/FileSystem – SLaks

+0

Что такое четкая и не сложная обработка ошибок? – Reniuz

+0

@reniuz: Я ожидал, что комментарий ... Не уверен, действительно, и я не могу дать точное определение и надеюсь, что в сообществе есть определенный консенсус. Например. для меня одна вещь будет писать клиентский код с небольшим количеством блоков try/catch ... возможно, попробуйте блокировать не более одного или двух блоков catch ... Слишком много try/catchs загромождают код. Например. когда я делаю CopyFile() Я бы хотел, чтобы в InnerException, возможно, был только один тип исключений с более подробной информацией. Не уверен, что это правильный подход, но для меня это значит для меня в настоящее время. – matori82

ответ

2

Лучшая практика - это то, что можно восстановить из исключения, но если вы ничего не можете сделать, пусть это распространение распространяется на вызывающего и позволяет им справляться с ним.

Как сделать библиотеку прочной и простой в использовании, документируйте столько, сколько возможно, для вашей библиотеки. Вы можете использовать XML-документ Doc, чтобы включить то, что исключения вышвырнут прямо в метаданных для DLL

(комментарии, сделанные из Directory.CreateDirectory(string))

public interface IFileSystemService 
{ 

    /// <summary> 
    /// Creates all directories and subdirectories as specified by <paramref name="path"/>. /// 
    /// </summary> 
    /// 
    /// <returns> 
    /// A <see cref="T:System.IO.DirectoryInfo"/> as specified by <paramref name="path"/>. /// 
    /// </returns> 
    /// <param name="path">The directory path to create.</param> 
    /// <exception cref="T:System.IO.IOException">The directory specified by <paramref name="path"/> is read-only.</exception> 
    /// <exception cref="T:System.UnauthorizedAccessException">The caller does not have the required permission.</exception> 
    /// <exception cref="T:System.ArgumentException"><paramref name="path"/> is a zero-length string, contains only white space, or contains one or more invalid characters as defined by <see cref="F:System.IO.Path.InvalidPathChars"/>. 
    /// 
    /// -or- 
    /// <paramref name="path"/> is prefixed with, or contains only a colon character (:).</exception> 
    ///<exception cref="T:System.ArgumentNullException"><paramref name="path"/> is null.</exception> 
    ///<exception cref="T:System.IO.PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.</exception> 
    ///<exception cref="T:System.IO.DirectoryNotFoundException">The specified path is invalid (for example, it is on an unmapped drive).</exception> 
    ///<exception cref="T:System.NotSupportedException"><paramref name="path"/> contains a colon character (:) that is not part of a drive label ("C:\").</exception> 
    void CreateDirectory(string path); 

    //Do similar comments for the rest. 
    void DeleteDirectory(string path); 
    bool DirectoryExists(string path); 
    IEnumerable<string> EnumerateDirectories(string path); 
    void DeleteFile(string path); 
    bool FileExists(string path); 
    void CopyFile(string sourcePath, string destinationPath, bool overwriteExisting); 
    // ... and other methods 
} 
1

Что бы наилучшей практики для обработки исключительных ситуаций, когда это приходит к реализации этого интерфейса, используя стандартные классы .NET из пространств имен System.IO (например, FileInfo, DirectoryInfo, Directory, File и т. д.)?

Лучше всего, насколько я обеспокоен тем, чтобы позволить исключения бурлит. Как разработчик «рамки», вы не можете знать, каково будет намерение - обработка исключений для пользователя вашего API. И поскольку вы не знаете намерений этого пользователя, предпочтительно, чтобы исключение было выбрано.

  1. Позволяя исключение кипящего, вы позволяете получить полную трассировку стеки, где исключение на самом деле произошло
  2. Вы также позволяете обрабатывать исключения один хочет, чтобы поймать на основе одного контекста

, основанные на Eric Lippert «s блоге, Vexing Exceptions который я не могу больше не найти, я помню, как он говорил, что лучше, чтобы увидеть код, как:

if (condition) throw new Exception("message"); 

чем видеть:

try { something(); } 
catch (Exception ex) { throw new Exception(); } 

Поскольку трассировки стека должны быть сброшены каждый раз, когда исключение вызвано повторно. Или же вы можете:

try { something(); } 
catch (Exception ex) { 
    handleTheExceptionInternallyForYourPurpose(); 
    throw ex; // simply let the exception flow go its way to the top, to the caller. 
} 

Плюс все зависит от ваших ожиданий в отношении поведения. Предположим, вы не хотите разрешать нулевые значения как параметр path, тогда вам может потребоваться сбросить ArgumentNullException, когда это так.

public void CreateDirectory(string path) { 
    if (path == null) throw new ArgumentNullException("path"); 
    if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); 

    // create your directory here based on the path provided... 
} 

Как я могу сделать эту библиотеку надежным и простым для использования клиентского кода?

Моя ставка заключается в том, что вы не можете программировать для других программистов. У вас может быть лучшая библиотека в мире, с меньшим опытом или без уважения. SRP может закончиться грязным кодом. Каждому программисту принадлежит ряд руководящих принципов и соблюдение лучших практик и принципов. К сожалению, эти принципы редко соблюдаются, по крайней мере, в моем уголке мира. Что бы вы ни делали, почти всегда будет лучший способ делать вещи в зависимости от вашего контекста.

Как я могу сделать это так, чтобы клиент код для обработки ошибок является чистым и не слишком сложным?

комплекс материал всегда будет сложным для кода, так что нет никакого способа, чтобы избежать. Придерживаясь принципов SOLID и применяя лучшие практики завтрашнего дня, у вас будет простая и понятная библиотека.

XML Comments также являются хорошим способом пойти, когда дело доходит до библиотек, так что IntelliSense может отображать его при наборе текста.

Смежные вопросы