Qual è un semplice processo per progettare un sistema OOP prima di codificarlo?


10

Ogni volta che mi veniva richiesto di costruire un progetto, riuscivo sempre a costruirlo, non prima di escogitare un piano o un progetto, ma dopo aver scritto una classe che era necessaria, completando l'intero progetto, costruendo dal basso verso l'alto. Ora so che questo non è il modo corretto di creare software, ma non è facile per me avvolgere la testa in quello che viene chiamato Analisi e progettazione orientate agli oggetti. Riesco più facilmente a comprendere la progettazione procedurale top-down, poiché consiste semplicemente nel suddividere le attività in sotto-attività, cose che hanno la loro controparte nel codice, funzioni. Ma l'analisi e la progettazione orientate agli oggetti non riesco a capire facilmente, perché non capisco come si possa sapere quali classi avranno bisogno e come interagiranno, a meno che non sappiano come le codificheranno.

Per una volta introduciamo il concetto di classi e oggetti nel processo di progettazione, non possiamo più progettare dall'alto verso il basso, perché non stiamo più suddividendo i nostri problemi in quelle cose che possono essere implementate come procedure. Invece, secondo quanto ho letto sull'argomento, dobbiamo determinare quali classi sono necessarie e creare vari artefatti in Unified Modeling Language, che possiamo quindi utilizzare quando implementiamo il software. Ma questo tipo di processo di progettazione non capisco. Perché come si può sapere di quali classi avranno bisogno e come interagiranno, a meno che non abbiano già concepito l'intero sistema?

Questo è quindi il mio problema. Non capisco come progettare un sistema orientato agli oggetti, anche se capisco i concetti di programmazione orientata agli oggetti e posso usare questi concetti in qualsiasi linguaggio di programmazione orientata agli oggetti che conosco. Pertanto ho bisogno di qualcuno che mi spieghi quale semplice processo posso usare per progettare sistemi orientati agli oggetti in un modo che abbia senso per me.


8
"Ora so che questo non è il modo corretto di creare software" - chi te lo ha detto? Sembra in qualche modo cadere nella trappola popolare di credere che "progettare è qualcosa che fai prima di scrivere codice, magari disegnando fantastici diagrammi UML". Per curarti da questo malinteso, ti consiglio di iniziare con "Code as Design" di Jack Reeves.
Doc Brown,


@DocBrown. Non pensi che il design durante la programmazione sia ciò che rende il nostro lavoro così artigianale? Non riesco a immaginare che altre macchine funzionino allo stesso modo. Immagina un architetto che riempie mattoni e malta e progetta l'edificio / ponte lungo la strada.
Laiv,

5
@Laiv: la "codifica" fa parte di ciò che in altre discipline ingegneristiche è chiamato design. Nella costruzione di case, il passaggio dalla progettazione al prodotto finale viene effettuato utilizzando mattoni e malta da pilling. Nella programmazione, questo passaggio viene eseguito dal compilatore durante la traduzione del progetto (= programma) nel prodotto finale (= binario eseguibile). E questa non è una nuova saggezza. I saggi di Reeves hanno 25 anni.
Doc Brown,

@DocBrown, lo sviluppatore. * Non è più curato? Il pulsante Iscriviti è rotto, ad esempio.
radarbob,

Risposte:


20

Lo stile OOAD dall'alto verso il basso non garantisce che il codice che scrivi sia orientato agli oggetti. Ho visto montagne di codice prodotto rigorosamente OOAD che lo dimostra. Se OO ti confonde, non cercare aiuto qui. Non lo troverai. OO NON richiede di progettare dall'alto verso il basso.

Se immergerti in una classe è come ti piace programmare, così sia. Lascia che ti dica un suggerimento. Procrastinare.

È incredibile quanto sia facile progettare le classi scrivendo il codice che le utilizza anche quando non esistono ancora. Dimentica la procedura. Dimentica la struttura. Basta procurarsi un buon livello coerente di astrazione e attenersi ad esso. Non lasciarti tentare e mescola dettagli extra in esso. Tutto ciò che ti porta fuori dall'astrazione attuale può essere fatto con un metodo che potrebbe essere su qualche altro oggetto che in qualche modo sa tutto ciò che deve sapere. Non costruire nulla a cui puoi semplicemente chiedere di essere consegnato a te.

Impara a scrivere così e scoprirai che stai facendo OO senza nemmeno provarci molto. Questo ti costringe a guardare i tuoi oggetti dal punto di vista di come vengono utilizzati (la loro interfaccia) e quali oggetti conoscono quali altri oggetti. Indovina quali sono i due punti principali di un diagramma UML?

Se riesci a entrare in quel modo di pensare, ciò che resta è l'architettura. Lo stiamo ancora capendo. Da MVC all'architettura pulita alla progettazione guidata dal dominio. Studiali e gioca. Usa ciò che funziona. Se trovi qualcosa di affidabile al 100%, torna indietro e fammi sapere. Lo sto facendo da decenni e sto ancora cercando.


2
O ti ritrovi a non fare OO e tuttavia tutto "in qualche modo" funziona bene comunque ...
Derek Elkins lasciò SE il

2
"È incredibile quanto sia facile progettare le classi scrivendo il codice che le utilizza anche quando non esistono ancora" - Io chiamo questo design top-down, ma sembra che mi sbagli. Cos'è il design top-down e come si chiama così? Sta programmando su un'interfaccia?
Piovezan,

Non è semplicemente dall'alto verso il basso. Devi anche essere disposto a non costruire cose che puoi chiedere semplicemente accettando i parametri.
candied_orange

@Piovezan puoi farlo anche quando l'interfaccia non esiste ancora. Ignora il compilatore per un po '. Più tardi, lo farai esistere.
candied_orange,

@CandiedOrange "Devi anche essere disposto a non costruire cose che puoi semplicemente chiedere accettando i parametri." - Non sono sicuro di aver capito, potresti per favore chiarire / fornire un breve esempio (o contro-esempio per quella materia)?
Piovezan,

4

Sostieni di essere in grado di utilizzare tecniche orientate agli oggetti nel tuo codice, quindi dal momento che sai come progettare già un sistema orientato agli oggetti , credo che il tuo problema sia più una questione di quando , non se puoi o meno. Ti senti a tuo agio con il design orientato agli oggetti in modo iterativo a breve termine, anziché in un modo di pianificazione a lungo termine.

Quando si sviluppa per la prima volta un progetto, può essere molto difficile pianificare e progettare, in quel momento si favorisce lo sviluppo agile rispetto allo sviluppo a cascata , poiché l'ampia portata di un piano a cascata spesso non cattura tutte le complessità di un progetto software.

Affermate che lo sviluppo al volo senza un "piano iniziale" è:

"... non è il modo corretto di creare software ..."

Se il tuo problema è che il tuo piano iniziale non è abbastanza dettagliato, prenditi un po 'più di tempo per spiegare i tuoi primi pensieri. Qual è la prima parte del programma che prevedi di scrivere? Di cosa avrà bisogno ? Forse non pensare nemmeno a quali oggetti cominciare, invece pensa a quali caratteristiche e piani da lì.

Se il tuo problema è che non sei sicuro delle tue capacità di documentare / progettare / UML , fai pratica documentando un progetto esistente.

Personalmente consiglierei di non preoccuparti che i tuoi progetti siano perfettamente orientati agli oggetti, la maggior parte dei sistemi non sono orientati al 100% agli oggetti. L'obiettivo è quello di creare una migliore comprensione e visualizzazione del sistema, non un'astrazione perfetta. L'orientamento agli oggetti non è il proiettile d'argento, è solo un altro strumento sulla cintura.


Volevo anche menzionarlo, anche se un po 'fuori tema per la risposta ... I tuoi piani non devono essere molto grandi! A volte un piano è solo una questione di "Voglio eseguirlo e fa qualcosa". È abbastanza buono, se è davvero tutto ciò che farà.
Erdrik Ironrose,

2

OOAD è un'utopia. Con ciò non intendo che sia l'approccio migliore, intendo dire che non è mai veramente realizzabile secondo la mia modesta opinione. Nella mia esperienza, qualcosa cambia sempre, che si tratti di requisiti o specifiche, o anche di un conflitto di dipendenza che ti costringe a sostituire completamente una dipendenza. Che sia perché ho imparato in questo modo o perché è ciò che viene più naturalmente per me, le mie idee per il design arrivano più prontamente mentre scrivo codice. Se sto per scrivere un codice e non ho una chiara idea di come strutturerò il codice, farò in modo di dedicare tempo alla comprensione del problema prima, anche se il più delle volte vedo necessità per una lezione e ce la farò.

Il mio consiglio è che la cosa migliore che puoi fare per te stesso è usare il codice usando le facciate , fornendo una semplice interfaccia per input e output, e spero che input e output non cambino spesso. Anche se lo fanno, sappi che non è un problema di progettazione tanto quanto è un problema di specifiche (modifica in necessità / operazione / funzionalità). Ciò renderà il tuo programma un po 'resistente ai problemi che risuonano all'interno del tuo programma verso coloro che chiamano il tuo programma o sezione di codice e viceversa.

Per quanto riguarda la progettazione di un sistema orientato agli oggetti, si dovrebbe dire qualcosa per cercare di rendere tutto orientato agli oggetti quando non dovrebbe essere. Questo è un errore comune tra i linguaggi di programmazione OOP come C # e Java è quello di provare a trattare tutto come un oggetto, il che spesso porta alla creazione di una singola istanza di una classe per eseguire quelli che altrimenti sarebbero metodi statici che non cambiano stato. Detto questo, ovviamente dovresti usare la progettazione OOP ove applicabile, anche se non ti sembra di sbagliare quando è più naturale scrivere un metodo statico. Non è sempre l'istinto sbagliato.

Dovresti considerare l'uso di una classe quando rispondi sì a una delle seguenti domande:

  • Ho un gruppo di informazioni relative allo stesso concetto (ovvero nome, cognome, indirizzo)?
  • Devo eseguire un'operazione che richiede diverse informazioni (ad es. calculatePrice(basePrice, quantity, tax))?
  • Ho un altro se con blocchi di codice di grandi dimensioni eseguono operazioni leggermente diverse con le stesse informazioni o simili (cioè if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Ho una classe esistente che esegue più di un'attività specifica e sta diventando un po 'troppo grande?

Dopo un po ', diventerà una seconda natura creare classi. Non aver paura di usarli se il tuo codice rientra in uno dei casi sopra. Spero che aiuti!


2

Penso che i punti sollevati da Doc Brown nei commenti meritino molta più visibilità di un commento poiché ha assolutamente ragione:

" Ora so che questo non è il modo corretto di creare software " - chi te lo ha detto? Sembra in qualche modo cadere nella trappola popolare di credere che "progettare è qualcosa che fai prima di scrivere codice, magari disegnando fantastici diagrammi UML". Per curarti da questo malinteso, ti consiglio di iniziare con "Code as Design" di Jack Reeves. - Doc Brown, 21 giugno alle 5:27

@Laiv: la "codifica" fa parte di ciò che in altre discipline ingegneristiche è chiamato design. Nella costruzione di case, il passaggio dalla progettazione al prodotto finale viene effettuato utilizzando mattoni e malta da pilling. Nella programmazione, questo passaggio viene eseguito dal compilatore durante la traduzione del progetto (= programma) nel prodotto finale (= binario eseguibile). E questa non è una nuova saggezza. I saggi di Reeves hanno 25 anni. - Doc Brown, 21 giugno alle 6:39

Questo stesso sentimento è anche riecheggiato in altri luoghi. Considera i discorsi di "Real Software Engineering" di Glenn Vanderburg e, in parte, i suoi discorsi di "Craft, Engineering, and the Essence of Programming" e "Craft and Software Engineering". Considera anche le pagine / discussioni WhatIsSoftwareDesign e TheSourceCodeIsTheDesign sul wiki C2.

Il concetto del codice come design non è specifico per nessun paradigma. Può essere applicato allo stesso modo a oggetti, funzionali, procedurali, logici o qualsiasi altra cosa. L'idea alla base è la stessa: il design è il codice sorgente stesso. L'atto di costruzione è il processo mediante il quale il codice sorgente (il progetto) viene trasformato in un oggetto utilizzabile da un interprete o un compilatore.

In un sistema complesso, è probabile che ci sia un certo livello di progettazione architettonica di livello superiore: identificare sottosistemi, componenti, moduli, servizi e allocare i requisiti prima di iniziare a scrivere codice. È possibile utilizzare UML come modo per creare, documentare e aiutare nelle discussioni su questo progetto architettonico. Considera l'idea delle modalità UML di cui Martin Fowler discute , in particolare UML come schizzo e UML come note . Considera anche alcune idee della modellazione agile: modelli di architettura iniziale , modelli di iterazione e modelli appena sufficienti .

Tutto ciò significa che il modo giusto di creare software non è quello di dare corpo all'intero progetto. È passare il tempo sufficiente per comprendere i requisiti più critici (al momento attuale), identificare le dipendenze tecniche e gli scambi tra i requisiti e quindi trarre vantaggio dal fatto che il software è morbido. Riconosci anche che il costo di prendere il tuo design e produrre qualcosa è incredibilmente basso (specialmente se paragonato a prendere un design e produrre qualcosa in molte altre discipline ingegneristiche). Quindi ripeti le tue attività di progettazione (codifica) e approfitta di quanto sia facile ed economico costruire o modificare progressivamente ciò che hai fatto.


1

OOAD riguarda l'identificazione di entità e la modellazione di oggetti o concetti di vita reale in un certo grado di astrazione. Lo percepirai come più semplice se invece di scrivere classi in un primo momento scrivi interfacce, dal momento che non devi ancora implementarle, ma il codice viene compilato.

OOAD non esclude la possibilità di pensare nel sistema come grandi moduli. Puoi ancora farlo. Ogni modulo esiste per soddisfare una serie di storie utente (casi d'uso). Tali storie utente hanno bisogno di classi che collaborano per soddisfarle.

Una differenza fondamentale tra approcci procedurali e OO è che il pensiero procedurale di solito mappa i requisiti per gli schermi, mentre OOD ha la tendenza a pensare a ciò che accade sotto il cofano lasciando che il front-end sia realizzato da un'altra persona o in modo non OO.

C'è una tecnica nella programmazione estrema chiamata CRC Cards . CRC sta per "collaboratori di classe-responsabilità".

Fondamentalmente identifichi le classi evidenti e assegni una carta a ciascuna. Supponiamo che la classe Invoiceabbia una sua carta.

Per ogni classe di titolari di carte scrivi quali sarebbero le responsabilità di quella classe, ad esempio "calcola un totale complessivo" .

Inoltre, per ogni classe di titolari di carte, scrivi ciò che le altre classi devono richiedere qualcosa per soddisfare le proprie responsabilità. Qui puoi scoprire le Invoiceesigenze della collaborazione InvoiceDetailo persino scoprire che una tale classe è necessaria in primo luogo.

Potresti scoprire che alcune responsabilità a cui pensavi appartenessero Invoce, appartengono davvero a uno dei suoi collaboratori.

Dopo l'esercizio, ogni carta diventa una classe, ogni responsabilità diventa un metodo e ogni relazione di collaborazione può diventare una composizione, un'agregazione o una semplice chiamata.

Tale esercizio può (e dovrebbe) essere fatto in un gruppo, in cui anche gli uomini d'affari partecipano.

Puoi saperne di più su questa tecnica in questi link:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Esempi di schede CRC:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


0

La sfida principale per noi, come comunità di professionisti del software; più specificamente i professionisti del design orientati agli oggetti, è quello di materializzare tutti i nostri problemi / compiti in una parte di programmazione. Che si tratti di compiti - rappresentati come funzioni o che siano attori dei compiti - rappresentati come interfacce / classi [guidando verso OOAD]. Man mano che evolviamo le nostre abitudini di progettazione del software, acquisendo continuamente conoscenza di varie metodologie / strutture. Il nostro punto di vista diventa sempre più raffinato per separare chiaramente gli oggetti e quale oggetto svolgerebbe quale funzione.

Per quanto riguarda la suddivisione dei problemi in sotto-problemi con la presenza di oggetti intorno, puoi ancora farlo convenientemente, poiché TU hai il controllo totale di tutti gli oggetti che vuoi essere presenti. Hai anche la comodità di impartire natura e scopo ai tuoi oggetti e alle tue interfacce. Tutto quello che devi fare è visualizzare la dichiarazione del problema e pensare a quale scopo / funzionalità può essere impartito su quale oggetto.

Proverò a spiegare ulteriormente con l'aiuto di un esempio della gamma di automobili e metterò in evidenza due modi diversi di visualizzare lo stesso modello di oggetti.

Prendi un esempio del costruttore di automobili che si estende a varie categorie di automobili: veicoli commerciali, automobili di consumo (berline, berlina, station wagon) ecc.

Affinché il produttore abbia chiaramente una separazione per categoria e scopo, ci sono diversi modi con cui possono creare classi.

Produttore del veicolo OOAD

  1. Basato sulla categoria (settore di mercato) del veicolo: veicolo pesante, veicolo di consumo [berlina, berlina, station wagon ecc.]

  2. In base alla capacità del motore e al modo di guida: 800-1500 CC,> 1500 CC ecc.

Seguendo il modo migliore in cui il produttore può impartire individualmente funzioni agli oggetti appartenenti a ciascuna di queste classificazioni, possono scegliere un appropriato design dell'oggetto sottostante e costruirvi sopra un modello.


Inizi bene, ma l'ultimo bit sembra l'errore di OOD nel classificare le cose piuttosto che nel raggruppare comportamenti simili.
Pete Kirkham,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.