Я не вірю, що локальний улов - це анти-шаблон, адже якщо я правильно пам’ятаю, він фактично застосовується на Java!
Що для мене ключове при реалізації помилок - це загальна стратегія. Можливо, вам потрібен фільтр, який фіксує всі винятки на кордоні служби, ви можете вручну їх перехопити - обидва є нормальними, доки існує загальна стратегія, яка буде входити у стандарти кодування ваших команд.
Особисто мені подобається вловлювати помилки всередині функції, коли я можу зробити одне з наступного:
- Додайте контекстну інформацію (наприклад, про стан об'єктів або що відбувається)
- Керуйте винятком безпечно (наприклад, метод TryX)
- Ваша система перетинає межу обслуговування та переходить у зовнішню бібліотеку чи API
- Ви хочете зловити та повторно скинути виняток іншого типу (можливо, з оригіналом як внутрішнім винятком)
- Виняток було закинуто як частина фонового функціонування низького значення
Якщо це не один із цих випадків, я не додаю локальний спробу / улов. Якщо це так, залежно від сценарію, я можу обробляти виняток (наприклад, метод TryX, який повертає помилку) або повторно скинути, тому виняток буде оброблятися глобальною стратегією.
Наприклад:
public bool TryConnectToDatabase()
{
try
{
this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
return true;
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
return false;
}
}
Або приклад переосмислення:
public IDbConnection ConnectToDatabase()
{
try
{
// connect to the database and return the connection, will throw if the connection cannot be made
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
throw;
}
}
Тоді ви виявляєте помилку у верхній частині стеку та представляєте приємне користувачеві повідомлення.
Незалежно від того, який підхід ви застосуєте, завжди варто створити одиничні тести для цього сценарію, щоб ви могли переконатися, що функціональність не зміниться і не порушить потоки проекту на більш пізній термін.
Ви не згадали, на якій мові працюєте, але як розробник .NET і бачили це занадто багато разів, щоб не згадувати про це.
НЕ ПИШИ:
catch(Exception ex)
{
throw ex;
}
Використання:
catch(Exception ex)
{
throw;
}
Перший скидає стежку стека і робить ваш ловець верхнього рівня абсолютно марним!
TLDR
Ловля локально не є антидією, вона часто може бути частиною дизайну і може допомогти додати додатковий контекст до помилки.