Skip to content
Perspectivas e Iteraciones Entendiendo la IA: técnico, cotidiano y reflexiones.
← atrás

Codificando la Salsa Secreta

15 de septiembre de 2019 • 6 min de lectura

Codificando la Salsa Secreta

Cada aplicación tiene su salsa secreta, su razón de existir. Codificar la salsa secreta es fundamental para escribir aplicaciones mantenibles y exitosas.

Espera. ¿Qué es codificar? Paciencia mi amigo, llegaremos ahí.

Primero hagamos una hipótesis:

Acabas de ser promovido a Ingeniero de Software Principal (¡Felicitaciones!). La primera tarea de tu CEO es crear un nuevo producto para la empresa. Es una aplicación de contabilidad desde cero. Los ejecutivos sienten que tener una solución de contabilidad personalizada les dará una ventaja sobre la competencia.

Han pasado algunos meses, la mayoría de las preocupaciones transversales están desarrolladas (¡bien por ti!). El equipo ahora se enfoca en la bondad deliciosa de la aplicación: el dominio del negocio (la salsa secreta). Aquí es donde comienza la codificación de la salsa secreta.

Codificar, es poner estructura alrededor de un concepto esencial en el dominio del negocio.

En contabilidad, la relación precio (P) ganancia (E) (Relación P/E) es una medida de las ganancias de una empresa. Una relación P/E alta sugiere un alto crecimiento de ganancias en el futuro. La relación P/E se calcula tomando el valor de mercado por acción (precio de la acción) dividido por las ganancias por acción (ganancia – dividendos / # de acciones en circulación).

Una implementación simple, y yo diría, ingenua:

public class Metric
{
    public string Name { get; set; }
    public decimal Value {get; set}
    public int Order {get; set;}
}
public class AccountingSummary
{
    public Metric[] GetMetrics(decimal price, decimal earnings)
    {
        var priceEarningsRatio = price/earnings;
        
        var priceEarningsRatioMetric = new Metric 
        {
            Name = "P/E Ratio",
            Value = priceEarningsRatio,
            Order = 0
        }
        return new [] {priceEarningsRatioMetric};
    }
}

Si esto solo se usa en un lugar, está bien. ¿Qué pasa si usas la relación P/E en otras áreas?

Como aquí en PriceEarnings.cs

var priceEarningsRatio = price/earnings;

Y aquí en AccountSummary.cs

var priceEarningsRatio = price/earnings;

Y aquí en StockSummary.cs

var priceEarningsRatio = price/earnings;

La Relación P/E es fundamental para esta aplicación, pero cómo está implementada, codificada en varios lugares, hace que la importancia de la Relación P/E se pierda en un mar de código. Es solo otro árbol en el bosque.

También te abres al riesgo de cambiar la relación en un lugar pero no en el otro. Esto puede afectar los cálculos posteriores. Este tipo de errores son notoriamente difíciles de encontrar.

A menudo los testers asumirán que si funciona en un área, es correcto en todas las áreas. ¿Por qué no usaría la aplicación el mismo código para generar la Relación P/E para toda la aplicación? ¿No es este el punto de la Programación Orientada a Objetos?

Puedo imaginar un error como este llegando a producción y no siendo descubierto hasta una visita de tu ejecutivo que exige saber por qué los cálculos de la Relación P/E de la SEC son diferentes de lo que la empresa presentó. Ese no es un buen lugar para estar.

Revisemos nuestra implementación de la relación P/E y veamos cómo podemos mejorar nuestro primer intento.

En los sistemas de contabilidad las fórmulas son algo importante, pongamos estructura alrededor de las fórmulas agregando una interfaz:

public interface IFormula
{
    decimal Calculate<T>(T model);
}

Cada fórmula ahora se implementa con esta interfaz dándonos consistencia y predictibilidad.

Aquí está nuestra Relación P/E mejorada después de implementar nuestra interfaz:

Hemos agregado un PriceEarningsModel para pasar los datos necesarios a nuestro método Calculate.

public class PriceEarningsModel
{
    public decimal Price {get; set;}
    public decimal Earnings {get; set;}
}

Usando nuestro PriceEarningsModel, hemos creado una implementación de la interfaz IFormula para la Relación P/E.

public class PriceEarningsRatioFormula : IFormula
{
    public decimal Calculate<PriceEarningsModel>(PriceEarningsModel model)
    {
        return model.Price / model.Earnings;
    }
}

Ahora hemos codificado la Relación P/E. Es un concepto de primera clase en nuestra aplicación. Podemos usarlo en cualquier lugar. Es testeable, y un cambio impacta toda la aplicación.

Como recordatorio, aquí está la implementación con la que comenzamos:

public class Metric
{
    public string Name { get; set; }
    public decimal Value {get; set}
    public int Order {get; set;}
}
public class AccountingSummary
{
    public Metric[] GetMetrics(decimal price, decimal earnings)
    {
        var priceEarningsRatio = price/earnings;
        
        var priceEarningsRatioMetric = new Metric 
        {
            Name = "P/E Ratio",
            Value = priceEarningsRatio,
            Order = 0
        }
        return new [] {priceEarningsRatioMetric};
    }
}

Es simple y hace el trabajo. El problema es que la Relación P/E, que es un concepto central en nuestra aplicación de contabilidad, no se destaca. Los ingenieros no familiarizados con la aplicación o el dominio del negocio no entenderán su importancia.

Nuestra implementación mejorada usa nuestra nueva clase de Relación P/E. Inyectamos la clase PriceEarningsRatioFormula en nuestra clase AccountSummary.

Reemplazamos nuestra Relación P/E codificada con nuestra nueva clase PriceEarningsRatioFormula.

public class AccountingSummary
{
    private PriceEarningsRatioFormula _peRatio;
    
    public AccountingSummary(PriceEarningsRatioFormula peRatio)
    {
        _peRatio = peRatio;
    }
    
    public Metric[] GetMetrics(decimal price, decimal earnings)
    {
        var priceEarningsRatio = _peRatio.Calculate(new PriceEarningsModel 
        { 
            Price = price, 
            Earnings = earnings
        });
        
        var priceEarningsRatioMetric = new Metric 
        {
            Name = "P/E Ratio",
            Value = priceEarningsRatio,
            Order = 0
        }
        return new [] {priceEarningsRatioMetric};
    }
}

Uno podría argumentar que hay un poco más de trabajo con la PriceEarningsRationFormula sobre la implementación anterior y estaría de acuerdo. Hay un poco más de ceremonia pero los beneficios valen la pena el pequeño aumento en código y ceremonia.

Primero, ganamos la capacidad de cambiar la relación P/E para toda la aplicación. También tenemos una sola implementación para depurar si surgen defectos.

Por último, hemos codificado el concepto de la PriceEarningsRatioFormula en la aplicación. Cuando un nuevo ingeniero se una al equipo, sabrá que las fórmulas son esenciales para la aplicación y el dominio del negocio.

Hay otros métodos de codificar (encapsular) el dominio, como microservicios y ensamblados. Cada enfoque tiene sus pros y contras, tú y tu equipo tendrán que decidir qué es mejor para su aplicación.

Proteger conceptos clave del dominio en clases e interfaces crea componentes reutilizables y límites conceptuales. Haciendo que una aplicación sea más fácil de razonar, reduciendo defectos y bajando las barreras para incorporar nuevos ingenieros.

↑ Volver arriba

Autor: Chuck Conway se especializa en ingeniería de software e IA Generativa. Conéctate con él en redes sociales: X (@chuckconway) o visítalo en YouTube.