delega la logica del programma agli oggetti di livello inferiore

0

Sto scrivendo una libreria per l'uso nel calcolo scientifico e ho avuto un po 'di imbarazzo. I tipi al lavoro qui sono una classe M che consiste in circa data e un riferimento a una classe contenitore C . Ci sono molte diverse implementazioni di C e ho dedicato molto lavoro per assicurarmi che gli oggetti M potessero usare C oggetti senza conoscere la loro rappresentazione interna.

Un giorno il codice potrebbe essere utilizzato per l'elaborazione scientifica ad alte prestazioni, quindi la velocità è davvero una preoccupazione. Se M dovesse interrompere l'incapsulamento degli oggetti C , il codice potrebbe essere eseguito più velocemente. Ho provato questo e infatti potrei ottenere un 50% di accelerazione. Ma ciò implicherebbe un sacco di codice ripetuto e violazione del principio di open-closed.

In alternativa, posso prendere il comportamento che M deve eseguire e delegarlo a C . Per impostazione predefinita, C utilizzerà lo stesso algoritmo di implementazione-agnostico che avevo in precedenza, ma la logica si è appena spostata in centro verso una nuova classe. Il vantaggio di questo approccio è che, se CO è un'implementazione di C che può fare sostanzialmente meglio dell'implementazione predefinita, può sovrascrivere quel metodo con la sua versione.

Al momento, esiste solo un metodo che M dovrà delegare a C . Posso immaginare al massimo 2 altri comportamenti che dovranno essere trattati in questo modo. Potrebbe esserci un po 'di codice ripetuto, ma potrebbe essere gestito anche con un generatore di codice.

È un approccio comune? Se sì, come si chiama? Se no, è perché è una pessima idea per qualche motivo che non ho notato? Non è proprio il modello strategico; la maggior parte degli oggetti container non si preoccupa nemmeno di implementare la propria strategia, usano l'impostazione predefinita.

    
posta korrok 14.06.2014 - 03:07
fonte

1 risposta

1

A meno che tu non abbia architettura multilivello e queste classi ricadano in diversi livelli, un modo per pensarci è in termini di responsabilità (dato che gli aspetti OO del tuo programma non mi sono chiari dalla domanda), piuttosto che se una classe è "inferiore" o "superiore". Preferisci idealmente che ogni classe abbia esattamente una sola responsabilità (che è il principio di responsabilità singola ) indipendentemente dal fatto che esponga un metodo o molti. Nella mia esperienza, ciò è molto importante per ottenere un design open-closed, perché la responsabilità che delegate a una classe è ben contenuta all'interno della classe. Man mano che estendi la tua applicazione, avrai nuove classi con nuove responsabilità o estendere le classi esistenti se la funzionalità che stai aggiungendo rientrerà nelle responsabilità delle classi esistenti.

In base alla tua descrizione, se il metodo è in M o in C, puoi consentire alla classe derivata di sovrascrivere il metodo e migliorare le prestazioni. E una classe derivata di M su una piattaforma particolare può anche essere una con il codice che è mirato verso quella piattaforma invece della piattaforma generica in modo che migliori le prestazioni.

Tuttavia, quando si pensa all'implementazione generica e alle ottimizzazioni specifiche della piattaforma, è necessario considerare se averli in una singola classe aggiungerà più di una singola responsabilità in un unico posto. (E se questo problema non è limitato a una singola classe, potrebbe essere necessario considerarlo a un livello superiore, ad esempio vedi Separazione delle preoccupazioni principio ).

Un secondo problema che appare in questo esempio potrebbe essere se M e C (se dovessero essere due classi separate a causa di responsabilità diverse) è se devono essere accoppiati (cioè M ha bisogno di istanziare o usare direttamente C o viceversa). In molti casi questo può essere lasciato al chiamante in modo tale che il chiamante possa istanziare C o un'implementazione di C, e quindi passarlo a M. In tal caso, M funziona solo contro C (o un'interfaccia da cui deriva C ) e man mano che aggiungi ulteriori implementazioni di C, il codice chiamante sceglie quello corretto e poi passa a M.

Ove possibile, guardo anche ad altri esempi che potrebbero essere già stati implementati o che conosco da progetti precedenti o che sono disponibili pubblicamente, ad es. in .NET Framework Class Library (non deve necessariamente essere nella lingua che si sta utilizzando). FCL ha quindi una classe SymmetricAlgorithm che viene derivato per ogni implementazione di un algoritmo crittografico simmetrico (come AES), ma se è necessario utilizzare una password per la crittografia, è necessario utilizzare un DeriveBytes classe (che ha le proprie derivazioni) per calcolare prima una chiave e un vettore di inizializzazione, che sono i input per SymmetricAlgorithm. È questa separazione che consente di indirizzare vari tipi di algoritmi di derivazione chiave verso qualsiasi tipo di algoritmo simmetrico.

    
risposta data 14.06.2014 - 22:21
fonte

Leggi altre domande sui tag