Sobre los frameworks de BDD

BDD como idea original me parece correctísima. No obstante, la mayoría de los frameworks para llevar sus conceptos a cabo en C# me parecen ridículos. Veamos una misma prueba de ejemplo escrita de dos maneras:

Alternativa 1:

[Subject(typeof(Account), "Funds tranfer")]
public class When_transferring_between_two_accounts
{
static Account fromAccount;
static Account toAccount;

Establish context = () =>
{
fromAccount = new Account { Balance = 1m };
toAccount = new Account { Balance = 1m };
};

Because of = () => fromAccount.Transfer(1m, toAccount);

It should_debit_the_from_account_by_the_amount_transferrend = () =>
fromAccount.Balance.ShouldEqual(0m);

It should_credit_the_to_account_by_the_amount_transferrend = () =>
toAccount.Balance.ShouldEqual(2m);
}

Alternativa 2:

[TestFixture]
public class TransferringSpces
{
[Test]
public void It_should_debit_from_source_account_and_credit_to_target_account()
{
var fromAccount = new Account(balance: 1m);
var toAccount = new Account(balance: 1m);

fromAccount.Transfer(1m, toAccount);

Assert.That(toAccount.Balance, Is.EqualTo(2m));
Assert.That(fromAccount.Balance, Is.EqualTo(0m));
}
}

¿Es la primera prueba más clara que la segunda?, ¿Ayudan todos esos delegados (Establish, Because, It) a comunicar mejor el comportamiento del método que hace la transferencia?

NullReferenceException/ArgumentNullException

Leyendo al tío Bob (Robert Martin) en su libro Clean Code, me doy con que en uno de los capítulos sugiere algo verdaderamente elemental: no pasarle null a los métodos!

Bien, está claro que salvo algún que otro caso, los métodos no esperan nulos como valores válidos. Por lo tanto si le pasamos un null seguramente recibiremos un NullReferenceException como respuesta. Mucha gente cree que para defenderse de esto debe validar las entradas más o menos así:

public void SaveCustomer(Customer customer)
{
if (customer == null)
throw new ArgumentNullException("customer");

De esta forma, si ahora le pasamos un nulo como argumento, lo que logramos es recibir un ArgumentNullException en lugar de un NullReferenceException. No parece una verdadera mejora, ¿o sí? Lo cierto es que ambas excepciones, en este caso, nos dicen lo mismo: le pasamos un nulo a un método y no deberíamos y la única manera de lograr que el código funcione correctamente es NO haciéndolo.

Básicamente, si no vamos a pasarle nulos a los métodos las validaciones resultan superfluas y ensucian el código innecesariamente. Solo basta ver lo espantoso que quedan esas dos líneas de ejemplo para comprobarlo, aunque como ya dijimos no se trata de un tema de estética.

Ahora bien, muchos desarrolladores, influenciados seguramente por el Frameworks Design Guidelines, ponen irreflexivamente chequeo de nulos en todos sus métodos, incluso algunos lo hacen hasta en los internos y privados. Eso es un error.

Las Framework Design Guidelines son lineamientos para la creación de APIs y es justamente en ese contexto en donde ArgumentNullException cobra sentido. ArgumentNullException existe con el propósito de “salvar la reputación” del creador de una API. Es para evitar que los clientes (programadores) obtengan un NullReferenceException proveniente de lo profundo de una API de la cual no tienen el código y en su lugar reciban un alerta que les indica que son ellos mismos los culpables de la excepción que obtienen ya que están pasando un valor nulo a un método.

Más allá de que la validación de nulos puede aportarnos una detección algo más cercana del problema, lo cierto es que en el balance resulta a todas luces innecesario usarla en código que solo usaremos nosotros y que está bajo nuestro poder, salvo algunas excepciones específicas como la de crear barreras de contención.