analisi orientata agli oggetti, metodologia mancante

2

Ho studiato i principi del design e dei principi di oop, sento ancora che manchi qualcosa nella maggior parte delle teorie sul design. Forse il fatto è che non esiste una "teoria" come nella progettazione del database.
Lasciatemi spiegare un esempio.

Supponiamo che io voglia modellare diversi modi per produrre il succo d'arancia .

Diciamo che comincio con una classe Oranges , che modella un sacco di arance che saranno di una certa varietà, di una certa maturità, potrebbero essere state froozen ecc., E queste saranno le mie proprietà della classe Arance.

Quindi continuo fornendo a Orange un metodo di compressione.
Questo sembra essere corretto, perché unisce il metodo con i dati a cui si applica, che è la condizione preliminare per ottenere l'incapsulamento e altri principi di oop di valore.

Ma presto viene fuori che non è stata una buona scelta perché non c'è solo un modo per spremere un'arancia. Sarebbe preferibile avere una classe Juicer le cui istanze contengano dettagli del metodo di spremitura: a mano, con uno spremiagrumi elettrico, compresa la polpa, per non parlare della miscelazione di diverse varietà di arance. Dove quest'ultimo apre una nuova gamma di possibilità che non erano disponibili (o non ottenibili con facilità) se ciascuna istanza di Arance sarebbe stata elaborata usando il suo metodo di compressione.

Diciamo che abbiamo eseguito un "refactoring" della nostra architettura di oo e ci spostiamo su un altro esempio simile che ci porterà al punto.
È ormai prassi comune utilizzare un ORM per salvare istanze di classi nel database e recuperarle in seguito. In che cosa è simile all'esempio di classe Arance? Bene, qui ho una classe le cui istanze possono essere persistite in un database, cioè 'consentire un particolare processo'. Ma la classe stessa non contiene la logica per farlo , che in realtà è nelle classi ORM. Quindi sembra che lo stesso processo di "esternalizzazione" dell'esempio di Arance sia avvenuto anche in questo caso.

Ed ecco la domanda

Dato che è desiderabile ridurre al minimo il numero di tentativi-e-refattori, quali sono le domande che un programmatore dovrebbe porre per determinare precocemente se un metodo debba essere esternalizzato ad un'altra classe? Tutti i metodi di una classe sono esternalizzabili o esiste un insieme di metodi principali che sono intrinsecamente della classe stessa e quindi non esternalizzabili?

Idee

Come ho detto all'inizio, non sono completamente all'oscuro, mi sembra più che manchi una teoria "completa".
È facile mettere alcuni esempi:
se ho una classe le cui istanze rappresentano fatture, avrò un metodo 'calculateTotalAmount'. Questo è chiaramente un metodo intrinseco e core di quella classe, in quanto opzionato dai metodi per salvare quella fattura nel database che sarà 'esterna' della classe stessa. Ma questa non è una "risposta finale", ma un punto di partenza che serve a dimostrare che "non tutti i metodi sono uguali", ma i metodi possono essere suddivisi in categorie. Quante (utili) categorie possiamo fare e ci sono metodologie che mettono queste domande?

    
posta AgostinoX 10.08.2013 - 16:23
fonte

6 risposte

2

Given that it is desireable to reduce the number of attempts-and-refactorings to the minimum...

Auspicabile, sì. Praticamente possibile in ogni caso, no: perché non sai ancora tutto sulla soluzione.

Non vedo questo come mancanza di una metodologia formale (avrai gli stessi problemi con un modello relazionale del tuo spremiagrumi quando scoprirai nuovi modi di estrarre il succo), ma come un intrinseco processo di riflessione e evoluzione del design e dell'applicazione .

EDIT: Ho mancato un'asserzione in prima lettura, aggiunta qui per ulteriori illustrazioni (non per martellare te o altro, hai fatto una domanda molto buona, fondamentale, solo cercando di essere esauriente) -

...if i have a class whose instances represent invoices, i will have a method 'calculateTotalAmount'. This is clearly an inthrinsic, core method of that class...

No, non è . Il totale può essere mantenuto in modo incrementale, mentre gli articoli della fattura vengono aggiunti, eliminati o modificati. Oppure 'CalculateTotalAmount' potrebbe essere conveniente se la classe Invoice ha solo pochi oggetti InvoiceLineItem in una raccolta in memoria, ma anche in questo caso il calcolo effettivo può essere ridicolmente complesso, dipendente dal tempo, richiedere un carico di oggetti di supporto ed essere soggetto a più livelli di sconto variabili in base all'acquirente, all'agente di fatturazione, ai codici di elementi pubblicitari, al fornitore di servizi, all'ubicazione, all'ora del giorno e così via (si pensi alla "fattura di richiesta di assicurazione").

I metodi e le proprietà delle classi (e quindi i protocolli dell'applicazione) dipendono da ciò che stai cercando di fare, il che influenza le strutture che saranno più (o meno) convenienti per farlo. E conosci solo tutti di quel dopo aver terminato .

(Il motivo per cui il refactoring è cruciale per la longevità del codice, ma questa è un'altra discussione)

    
risposta data 10.08.2013 - 17:46
fonte
1

Penso che tu stia cercando SOLID . Più precisamente, Principio di responsabilità singola .

Queste non sono metodologie, ma in modo più simile dovresti pensare alla tua soluzione e alle linee guida per convalidare questa soluzione. Alla fine, devi ancora usare la tua esperienza e il buon senso per giudicare il tuo progetto finale.

La ragione per cui la non esistenza di una tale metodologia rigida, che ti consentirebbe di convalidare la tua soluzione, è semplicemente perché lo scopo di tale convalida è enorme. La correttezza della progettazione OO dipende dai requisiti non solo per le classi stesse, ma anche per le classi che dipendono e dipendono da questo progetto. E anche il contesto dell'intera applicazione. Se prendiamo gli esempi Orange e Invoice, potrebbero avere design radicalmente diversi a seconda dell'applicazione, tuttavia potrebbero essere implementazioni "corrette" in tutti questi casi.

    
risposta data 10.08.2013 - 17:55
fonte
1

Presumibilmente c'è un essere umano da qualche parte che voleva che modellassi la produzione di succo d'arancia. Forse invece sei tu e desideri solo modellarlo per il gusto di farlo.

Inizia scrivendo, in inglese (o nella lingua che preferisci) come descriveresti il processo. Tieni traccia dei nomi, dei verbi e di altre parti del discorso.

Potresti ritrovarti con qualcosa del tipo: "Prendo un'arancia dalla ciotola e la faccio rotolare sul tavolo per" ammorbidire "l'interno in modo che possa produrre più succo quando viene tagliato, quindi taglio l'arancia a metà, e usa uno spremiagrumi per spremere il succo in un bicchiere, a volte, se sono pigro, userò lo spremiagrumi meccanico nella mia dispensa, ma di solito fa troppa poltiglia, poi bevo il bicchiere di succo e vado a sedere il divano per un'ora "

Ora hai una descrizione di cosa sta succedendo e di cosa hai bisogno per modellare.

Quindi trovi i nomi e rendi quelle le classi. Trovi i verbi e fai quei metodi. È solo un punto di partenza, ma è importante notare quanto segue:

Il software modella sempre qualcosa, e la cosa reale che stai modellando è ciò che guida il modo in cui progetta le classi e le loro relazioni. E ora la parte più importante: qualcun altro potrebbe descrivere lo stesso processo in modo diverso. L'ordine potrebbe essere diverso, alcune parti potrebbero essere diverse e quindi hanno bisogno di un modello diverso nel software per descrivere cosa sta succedendo. MA NESSUN MODELLO È MEGLIO o PIÙ ACCURATO rispetto ad altri, sono semplicemente modelli diversi.

Alcuni sistemi software potrebbero persino richiedere più di un modello per lo stesso processo, anche. Quindi ricorda, il tuo progetto OOP riguarda l'abbinamento di un modello per uno scopo specifico in un particolare dominio. Il design OOP "corretto" è quello che cattura al meglio il modello nel particolare dominio.

    
risposta data 11.08.2013 - 00:59
fonte
1

Are all the methods of a class externalizable?

Sì, puoi separare completamente tutti i metodi che operano su una classe dalla classe stessa. Dovresti separare completamente tutti i metodi da una classe? Beh, questo dipende da come vuoi organizzare il tuo codice.

is there a set of core methods that are inherently of the class itself and so not externalizable?

Sì, qualsiasi metodo che richiede solo i valori associati a un oggetto. Qualunque altra cosa dovrebbe probabilmente essere esternalizzata e gestita da un'altra classe.

Hai menzionato il database e gli ORM, se volevi includere il metodo per salvare un'arancia nel database all'interno di una classe arancione, ora l'arancione ha bisogno di conoscere il tuo database. Perché il tuo arancio ha bisogno di sapere del tuo database e quali sono i pro e i contro di questa decisione? Bene, il metodo per il salvataggio di un'arancia è vicino ai dati che vengono salvati, a quanto pare. Tuttavia, ora non puoi avere un'arancia senza avere il database.

Per me, quell'ultima riga la porta davvero a casa. Nel mondo reale, le arance non conoscono i database, quindi perché dovrebbero farlo nel tuo codice. In breve, non esiste una taglia adatta a tutte le teorie / schemi, spetta a te come ingegnere vedere come tutti i pezzi si incastrano.

    
risposta data 11.08.2013 - 18:13
fonte
0

What are the questions that a programmer should put in order to determine precociously if a method should be externalized to another class? Are all the methods of a class exernalizable or is there a set of core methods that are inherently of the class itself and so not externalizable?

Come ho imparato a conoscere del design ( "Principi, modelli e pratiche agili in C #" di Robert e Micah Martin), è necessario comprendere appieno il processo reale per creare l'astrazione corretta. E una volta che l'hai fatto, dopo aver basato l'astrazione sulle interfacce, sei ricompensato con un "guadagno di polimorfismo". Avendo questo in mente, vedo una domanda importante è " Questo comportamento è qualcosa che questo elemento fa per sé o è un altro comportamento di un elemento - che sta facendo questo - che produce il risultato? (succo d'arancia, persistenza, qualunque cosa) ".

Inoltre in "Applicare UML e Pattern" di Craig Larman trovi ciò che chiama "GRASP" (Pattern software di assegnazione della responsabilità generale). Ad esempio:

  • Esperto di informazioni Un principio generale di design dell'oggetto e assegnazione della responsabilità? Assegna una responsabilità all'esperto dell'informazione, la classe che ha le informazioni necessarie per soddisfare la responsabilità.
  • Basso accoppiamento Come supportare una dipendenza bassa e un maggiore riutilizzo? Assegnare responsabilità in modo che l'accoppiamento (non necessario) rimanga basso.
  • Alta Di coesione Come mantenere la complessità gestibile? Assegnare responsabilità affinché la coesione rimanga alta.
  • Pure Fabrication Chi è responsabile quando sei disperato e non vuoi violare alta coesione e basso accoppiamento? Assegna un insieme di responsabilità altamente coeso a un "comportamento" artificiale o pratico classe che non rappresenta un concetto di dominio problematico - qualcosa inventato, al fine di supporta alta coesione, basso accoppiamento e riutilizzo.
  • Indirection Come assegnare le responsabilità per evitare l'accoppiamento diretto? Assegnare la responsabilità a un oggetto intermedio per mediare tra altri componenti o servizi, in modo che non siano direttamente accoppiati.

Ho visto che quando riesci a produrre un buon modello hai davvero un gruppo di oggetti coesivi che inviano messaggi l'uno all'altro e tutto procede senza intoppi. D'altra parte tu sai che "qualcosa" è sbagliato perché le interazioni non sono naturali.

    
risposta data 11.08.2013 - 16:56
fonte
0

andando direttamente dal tuo esempio:

"certa maturità" - è una regola del core business che ha il controllo sul comportamento di qualunque cosa sia costruita. ci sono arance acerbe e arance mature.

questo è automatizzato - le arance vengono confrontate con una scala di maturazione. O questo deve essere fatto manualmente da un Orange Juice Manager. in entrambi i casi, da dove provengono i requisiti di implementazione degli oggetti. la prima domanda è: l'Orange Juice Manager controlla anche i Juicing? O l'Orange Juice Manager distribuisce un set "maturo" di Arance a una Orange Juicer Person?

se sì, questo è il primo confine chiaro. il gestore del succo d'arancia approva le arance, determina l'importo da spremere e lo consegna alla persona Orange Juicer. Il Manager non sa come si spremerà il succo o che tipo di dispositivo verrà utilizzato.

Questi sono i dettagli importanti del design. le specifiche delle arance e il modo in cui vengono schiacciati sono dettagli di implementazione e in quanto tali: sono volatili e ci aspettiamo che cambino.

Il gestore del succo d'arancia agisce sugli oggetti, ma approvano sempre arance e ordini. Lo spremiagrumi agirà sempre sugli oggetti - restituisce sempre il succo d'arancia. Questo è un concetto astratto: è stabile e non cambia. COME stringe le arance è un concetto specifico - quindi è instabile, quindi cambierà, quindi è più in basso nella catena di responsabilità di classe.

    
risposta data 11.08.2013 - 23:11
fonte

Leggi altre domande sui tag