The assertion is an old paradigm that has been around since before the advent of object-oriented languages. An assertion is a statement that asserts that some condition is true, and causes an execution failure if the condition is not respected. It’s that simple. Failure can be translated into an exception, a runtime error, or even a runtime failure resulting in unstoppable application termination. Traditionally, assertions are not compiled into production code. Instead, it’s being used as debug/test time safeguards. In such cases, the goal is to detect erroneous behaviour or non-compliant use of methods during application validation, and then remove such internal checks in order to reduce the drag on application performance and avoid any unsavoury failures in production use of the application. One common place in which assertions are used is in unit test frameworks. All the unit testing frameworks provide a way of validating for the expected condition or result following a test. Once again, these are rarely moved into production, and the assertions are written outside the production code. Note that the intent of the test and the assertion differ somewhat, but the mechanics of the assertion are the same. Times have changed, but popular views of assertions remain somewhat antiquated. Even though we like to think of assertions as debug and test-time checks, the reality is that the assertion-model is alive and well in the core runtimes and classes of the Java and .NET platforms. Take a look at the API documentation for any of the system classes. Most methods will throw an exception if one of the arguments passed to them is null or invalid in some way. Usually such exceptions identify which argument is at fault. This can save a lot of time troubleshooting—you don’t need to look inside a method to find where the problem is, it fails early instead of fails eventually. Implementing such preventive APIs is pretty straightforward, starting each method with a block of argument validation. Typically these are written as a series of “if/throw” statements. These can take up a lot of vertical and horizontal space in the code that often obscure their intent. This brings us back to the conciseness of the assertion. Rather than writing a verbose validation block or handling basic assertion failures, I prefer to write assertion-style helpers that throw standard exceptions on failure. Thus, this allows this:

public void SomeVerboseOperation(string sin, PostalAddress address)  {      if (address == null)          throw new ArgumentNullException("address");      if (string.IsNullOrEmpty(sin))          throw new ArgumentNullException("sin");      // do stuff  }

To become this:

public void SomeOperation(string sin, PostalAddress address)  {      Validate.ArgumentIsNotNull(address, "address");      Validate.ArgumentIsNotEmpty(sin, "sin");      // do stuff  }

I expect this to throw an argument null exception that points to the argument named “postalCode”. Fairly self-explanatory. Other possible forms that work well include “IsNotEmpty” for strings and “IsPositive” for integers. Other possibilities include regular expression checks and many more. I can’t take the credit for this approach. I borrowed it from the DDD sample application that Eric Evans published some years back. As an aside, I would point out that some languages support notions of method pre-conditions, effectively providing a formal mechanism for building this concept into the program. Some tools exist to inject this kind of behavior into C# and Java, but I find that these take away from the clarity of the code. Does anybody have any other tricks to clean up argument validation checks?

gabriel bélanger

Billet précédent

Validating XML content when testing

Billet suivant

Notre équipe en Suisse s'agrandit