Sto lavorando a un progetto che genera brochure tecniche in batch. L'API di terze parti in uso prevede POCO con nomi di proprietà corrispondenti ai nomi dei campi utilizzati in ciascuno dei modelli di brochure. Il compito che sto cercando di dare consigli è con l'origine dati che verrà utilizzata per popolare questi POCO. I dati si basano su calcoli a cascata rispetto a un modello di dominio. Inizialmente avevo intrattenuto l'idea che il dominio si potesse auto-calcolare, ma ci sono così tanti calcoli necessari che mi è sembrato ovvio che questo doveva essere sottratto.
Ho creato un codice ipotetico che imita da vicino il modello di progettazione in questione, e sono aperto a qualsiasi suggerimento o riaffermazione sul fatto che mi stia avvicinando correttamente a questo.
Le mie preoccupazioni principali:
-
Il costruttore per la classe "AirplaneResultsContext", che si inietta a classi di calcolo che sono anche proprietà esposte pubblicamente. Questo crea percorsi ricorsivi?
-
La possibile occorrenza di riferimenti circolari con chiamate di calcolo a cascata a varie proprietà / metodi in varie altre classi. Si noti che sto riutilizzando la maggior parte della logica di calcolo (come richiesto), ma posso proporre la necessità che venga refactored, se necessario.
Ho notato che ho usato la parola "Intricato", che di solito è un avvertimento rivelatore per il codice che deve essere estratto, ma sto facendo fatica a vedere come posso renderlo migliore.
L'entità che viene calcolata rispetto a . Immaginalo come una radice aggregata per un modello di dominio più grande.
class Airplane : Entity<int>
{
public double WingLength { get; set; }
public double FuselageCircumference { get; set; }
public double FuselageLength { get; set; }
public double SeatWidth { get; set; }
public double SeatDepth { get; set; }
public double SeatHeight { get; set; }
public double IsleWidth { get; set; }
public double LegRoomArea { get; set; }
}
Il contesto di calcolo . L'intento è che questo oggetto venga passato come parte di un processo batch: una fabbrica astratta che consuma un'interfaccia rappresentata da questa classe di contesto e genera gli oggetti POCO. Nota che ho omesso anche le interfacce e le classi astratte che sarebbero state utilizzate per diverse strategie di calcolo per brevità.
class AirplaneResultsContext
{
public AirplaneResultsContext(Airplane airplane)
{
Airplane = airplane;
Fuselage = new FuselageCalculator(this);
Seating = new SeatingCalculator(this);
}
public Airplane Airplane { get; private set; }
public FuselageCalculator Fuselage { get; private set; }
public SeatingCalculator Seating { get; private set; }
public double ComputeWidth()
{
return Airplane.WingLength*2 + Fuselage.ComputeDiameter();
}
}
Calcolatrici . Nel mio progetto non ipotetico, questi metodi sono privati / protetti, memorizzati nella prima chiamata e riletti da proprietà di sola lettura, ma volevo solo mostrare una rappresentazione di base di alcune delle complessità di calcolo.
class SeatingCalculator
{
private readonly AirplaneResultsContext _context;
public SeatingCalculator(AirplaneResultsContext context)
{
_context = context;
}
public int ComputeNumberOfSeats()
{
double isleArea = _context.Airplane.IsleWidth* _context.Airplane.FuselageLength;
double availableArea = (_context.Fuselage.ComputeDiameter()*_context.ComputeWidth()) - isleArea;
double seatArea = _context.Airplane.SeatDepth * _context.Airplane.SeatWidth + _context.Airplane.LegRoomArea;
return (int) Math.Floor(availableArea/seatArea);
}
}
class FuselageCalculator
{
private readonly AirplaneResultsContext _context;
public FuselageCalculator(AirplaneResultsContext context)
{
_context = context;
}
public double ComputeDiameter()
{
return Math.PI / _context.Airplane.FuselageCircumference;
}
}