i работал с небольшой подпрограммой, которая используется для создания подключения к базе данных:
Перед
public DbConnection GetConnection(String connectionName)
{
ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
DbConnection conn = factory.CreateConnection();
conn.ConnectionString = cs.ConnectionString;
conn.Open();
return conn;
}
Затем я начал изучать документацию по платформе .NET, чтобы узнать, что такое поведение документировано, и посмотреть, могу ли я с ними справиться.
Например:
ConfigurationManager.ConnectionStrings...
Документация говорит, что вызов ConnectionStrings вызывает ConfigurationErrorException, если он не смог получить сбор. В этом случае я ничего не могу сделать для обработки этого исключения, поэтому я его отпущу.
Следующая часть - это фактическое индексирование ConnectionStrings, чтобы найти connectionName:
...ConnectionStrings[connectionName];
В этом случае ConnectionStrings documentation говорит, что свойство вернет null, если имя соединения не найдено, я могу проверить это и выбросить исключение, чтобы кто-то высоко сказал, что они дали недопустимое имя соединения:
ConnectionStringSettings cs=
ConfigurationManager.ConnectionStrings[connectionName];
if (cs == null)
throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
Я повторяю одно и то же упражнение:
DbProviderFactory factory =
DbProviderFactories.GetFactory(cs.ProviderName);
В методе GetFactory отсутствует документация о том, что произойдет, если не удалось найти factory для указанного ProviderName
. Он не документировал возврат null
, но я все еще могу защищаться и проверять на null:
DbProviderFactory factory =
DbProviderFactories.GetFactory(cs.ProviderName);
if (factory == null)
throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");
Далее - построение объекта DbConnection:
DbConnection conn = factory.CreateConnection()
Опять документация не говорит, что произойдет, если не сможет создать соединение, но снова я могу проверить нулевой объект возврата
DbConnection conn = factory.CreateConnection()
if (conn == null)
throw new Exception.Create("Connection factory did not return a connection object");
Далее устанавливается свойство объекта Connection:
conn.ConnectionString = cs.ConnectionString;
Документы не говорят, что произойдет, если он не может установить строку подключения. Вызывает ли это исключение? Он игнорирует это? Как и в случае с большинством исключений, если при попытке установить ConnectionString для соединения произошла ошибка, я ничего не могу сделать для ее восстановления. Поэтому я ничего не буду делать.
И, наконец, открытие соединения с базой данных:
conn.Open();
Открытый метод DbConnection является абстрактным, поэтому он зависит от того, какой провайдер спускается с DbConnection, чтобы решить, какие исключения они выбрасывают. Кроме того, в документации по открытым методам Open нет руководства по поводу того, что я могу ожидать, если есть ошибка. Если произошла ошибка подключения, я знаю, что я не могу справиться с этим - я должен позволить этому пузыриться там, где вызывающий может показать некоторый пользовательский интерфейс пользователю, и позволить им попробовать еще раз.
После
public DbConnection GetConnection(String connectionName)
{
//Get the connection string info from web.config
ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
//documented to return null if it couldn't be found
if (cs == null)
throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
//Get the factory for the given provider (e.g. "System.Data.SqlClient")
DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
//Undefined behaviour if GetFactory couldn't find a provider.
//Defensive test for null factory anyway
if (factory == null)
throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");
//Have the factory give us the right connection object
DbConnection conn = factory.CreateConnection();
//Undefined behaviour if CreateConnection failed
//Defensive test for null connection anyway
if (conn == null)
throw new Exception("Could not obtain connection from factory");
//Knowing the connection string, open the connection
conn.ConnectionString = cs.ConnectionString;
conn.Open()
return conn;
}
Резюме
Итак, моя четырехлинейная функция, стала 12 строк и потребовала 5 минут поиска документации. В конце концов я поймал один случай, когда методу разрешено возвращать null. Но на практике все, что я сделал, это преобразование исключения нарушения доступа (если я пытаюсь вызвать методы на нулевой ссылке) в InvalidArgumentException.
Я также поймаю два возможных случая, когда могут быть null объекты возврата; но опять я только торгую одно исключение для другого.
С положительной стороны он обнаружил две проблемы и объяснил, что произошло в сообщении об исключении, а не о плохих вещах, происходящих в будущем (т.е. доллар останавливается здесь)
Но стоит ли это? Это избыток? Это защитное программирование пошло не так?