Very frequently I encounter the similar architectural problem. How often should one check for validity of entered arguments? Let's check the following example (don't care about the code correctness or compileability):
public void DoSth()
{
context.DbPerform((SQLiteConnection connection) =>
{
// *** 1 ***
if (connection == null)
throw new ArgumentNullException("connection");
if (!connection.IsOpen)
connection.Open();
try
{
Data.Insert(data, connection);
}
finally
{
connection.Close();
}
});
}
// ----
public static void Insert(Data data, SQLiteConnection connection)
{
// *** 2 ***
if (data == null)
throw new ArgumentNullException("data");
if (connection == null)
throw new ArgumentNullException("connection");
if (!connection.IsOpen)
connection.Open();
try
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = SQL.InsertData;
FillParameters(data, connection, cmd);
cmd.ExecuteNonQuery();
}
}
finally
{
connection.Close();
}
}
// ----
public static void FillParameters(Data data,
SQLiteConnection connection,
SQLiteCommand cmd)
{
// *** 3 ***
if (connection == null)
throw new ArgumentNullException("connection");
// And so on, you get the idea
}
In the previous snippet, the connection has been checked for being null or closed for three times. This seems like a little bit of overkill for me - sometimes 50% of the method's body are the security checks. I don't feel like that much security checks are necessary, but on the other hand always someone else could have used these methods and I cannot be sure if he passed valid parameters.
So my questions are:
class C
{
private Obj obj;
public C (Obj newObj)
{
if (newObj == null)
throw new ArgumentNullException("newObj");
obj = newObj;
}
public void DoSth()
{
// Should I check, whether obj is not null?
}
}
Regarding the first example, the checks in Insert()
are a good idea because Insert()
is public
. It could be called from another context where no checks were done.
In general, always validate at a public interface point. This helps in making your code loosely-coupled and reusable.
And every layer (tier, method) has its own requirements. So validate what you need to do a certain task at the beginning of that task.
I agree with Henk. Moreover try to consider the Code Contracts extension for Visual Studio which provide a way to specify preconditions, postconditions, and object invariants in your code: http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970 . It enforces a very consistent way to secure your code and the tool "Pex" can be used to auto-generate tests based on the contracts.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.