Costruire calcoli di logica aziendale che richiedono dati da oggetti padre

4

Ho un oggetto che ha bisogno di valori da un oggetto grandparent per eseguire un calcolo. Qual è il modo migliore per gestirlo?

Devo creare una classe di calcolo separata per ottenere i dati, eseguire il calcolo e restituire un valore? O un campo "genitore", quindi posso attraversare il backup dell'oggetto per ottenere i dati? O un servizio che questo oggetto può chiamare per ottenere i dati dal nonno?

Ecco un esempio semplificato.

class GrandParent{
    daysPerYear:360
    account: new Account()
}

class Account{
    percentageRate: 5,
    numberOfMonths: 12,
    paidBy = new PaidByItem()
}

class PaidByItem{
    feeAmount: 100
    totalAmount (){
        // Calculation
    }
}

Per calcolare questo totalAmount ho bisogno di dati da Account e Grandparent ; il calcolo è totalAmount = feeAmount * numberOfMonths / daysPerYear; .

    
posta Aaron Fischer 27.08.2016 - 18:51
fonte

2 risposte

3

Come strategia di base, eviterei quasi sempre di archiviare lo stesso pezzo di informazione in due diversi posti / classi di un modello di dati, che conduce troppo facilmente a codice non gestibile. Se inizi ad avere attributi come numberOfMonths in due classi (come è stato suggerito in un'altra risposta), possono deviare gli uni dagli altri, potresti dover scrivere codice per impedirlo, devi preoccuparti di quale sia la versione "principale" di quell'attributo potrebbe dover duplicare la documentazione e così via.

Una soluzione che hai suggerito era "Un campo genitore in modo che possiamo attraversare il backup dell'oggetto per ottenere i dati" . Va bene quando nel tuo dominio aziendale ogni oggetto PaidByItem è correlato in qualche modo a un Xyz e a un Aaa oggetto. Quindi ha senso esprimere quella relazione anche nel codice con un riferimento:

public class PaidByItem {
    int feeAmount = 100;
    Xyz xyz; // lets assume this is Java or C#, so a reference, no copy!
    AAA aaa;

    // ...

    public double totalAmount (){
        return  feeAmount * xyz.numberOfMonths / aaa.daysPerYear;
    }
}

I nomi non sensoriali come Xyz o Aaa , tuttavia, non ci dicono molto sul vero dominio. Ci possono essere molti motivi per cui non vuoi introdurre una dipendenza da Xyz o Aaa in PaidByItem . Ad esempio, potrebbero portare a una dipendenza ciclica da evitare, oppure questo tipo di relazioni / riferimenti semplicemente non ha alcun senso dal punto di vista del dominio. In questi casi, spesso è preferibile utilizzare l'altro suggerimento "Una classe di calcolo separata per ottenere i dati, eseguire il calcolo e restituire un valore ". In alternativa, puoi cambiare il design in

    public double totalAmount (int numberOfMonths, int daysPerYear){
        return  feeAmount * numberOfMonths / daysPerYear;
    }

che significa che il chiamante di questo metodo ha la responsabilità di assicurarsi che le funzioni totalAmount vengano chiamate con i parametri corretti dagli oggetti giusti. L'ultima opzione ha più senso quando non è richiesto che quei parametri come numberOfMonths provengano da uno specifico oggetto di riferimento.

TLDR: evita l'archiviazione ridondante, scegli la soluzione che rappresenta il tuo dominio aziendale in modo più appropriato.

    
risposta data 27.08.2016 - 22:02
fonte
1

Non so quale lingua stai usando, quindi scriverò in pseudocodice.

Ci sono molti modi per ottenere quello che vuoi. Alcune soluzioni richiedono oggetti contenuti per conoscere i contenitori. Alcuni no. Le soluzioni che richiedono che gli oggetti contenuti siano a conoscenza dei loro contenitori sono più complesse quindi andrò con una soluzione che non ha bisogno di oggetti contenuti per avere accesso allo stato dei loro contenitori.

Credo che una catena di costruttori potrebbe essere una soluzione.

public class GrandParent {
    int daysPerYear = 360;
    Account someObject = new Account(daysPerYear);

}
public class Account {

    int percentageRate = 5;
    int numberOfMonths = 12;
    int daysPerYear;
    PaidByItem paidBy;

    public Account(int daysPerYear) {
        this.daysPerYear=daysPerYear;
        paidBy = new PaidByItem(numberOfMonths,daysPerYear);
    }   
}
public class PaidByItem {
    int feeAmount = 100;
    int daysPerYear;
    int numberOfMonths;

    public PaidByItem(int numberOfMonths, int daysPerYear) {
        this.numberOfMonths = numberOfMonths;
        this.daysPerYear=daysPerYear;
        System.out.println(this.totalAmount());
    }

    public double totalAmount (){
        return  feeAmount * numberOfMonths / daysPerYear;
    }
}
public class Test {
    public static void main(String args[]){
        GrandParent a = new GrandParent();
    }
}

Nota: la tua formula non tiene conto del tasso percentuale quindi immagino sia sbagliato, e non mi piace l'approccio al design originale ma, immagino, come i nomi GrandParent, Account sono fittizi e io in realtà non lo sono capire le ragioni per farlo in quel modo, tradotto come hai fatto tu.

Nel codice di test come figlio mentre installi GrandParent , il risultato viene stampato.

    
risposta data 27.08.2016 - 19:52
fonte

Leggi altre domande sui tag