Come posso pianificare il mio software per evitare un eccessivo riscrittura e interdipendenze

StackOverflow https://stackoverflow.com/questions/3472405

  •  28-09-2019
  •  | 
  •  

Domanda

Sto scrivendo un controller motore che ha una coppia di interfacce (pulsanti, Bluetooth, tattili manopole), che è un compito che sta crescendo sempre di essere più grande di quanto ho capito.Ho cercato di andare solo a farlo partendo da un basso livello di moduli (ad es.scrivere il codice per parlare sul bus I2C), poi quelli di cui sopra che (codice per parlare di un particolare dispositivo sul bus I2C...), ma troppo spesso ho a tuffarsi di nuovo giù per il mio basso moduli per gestire le stranezze non ho accogliere.Questo richiede molto tempo o sono veramente hack-ish codice.

Il mio obiettivo è un 8-bit MCU, in modo bottom-up mi sembra in grado di sfruttare l'hardware migliore.Se vado top-down, non ho alcuna struttura di costruire o di test/debug.

Ho provato elaborazione complessiva dei diagrammi e quelli per particolari livelli/driver, ma non so come strutturare il loro modo posso essere molto sistematico su di esso e di evitare di perdere il dispari segnale che deve passare attraverso 2-3 strati.

Credo che questo è il motivo per cui un CS di laurea?Io sono un ingegnere elettrico :P

È stato utile?

Soluzione

Sembra che si è sulla strada giusta. A volte nessuna quantità di pianificazione sta andando per evitare di dover riprogettare o parti refactoring di un sistema in un secondo momento. Provare alcuni dei seguenti suggerimenti:

  • Mantenere il proprio codice in moduli separati da funzioni logiche.
  • Do codice non duplicato, anziché progettare metodi riutilizzabili per la funzionalità condivise.
  • Cercate di evitare la tentazione di aggiungere hack per casi particolari. Alla fine questo diventerà impossibile da mantenere. Invece, regolare e refactoring piccole sezioni più breve tempo possibile. Cercando di fare un grande re-design alla fine sarà più difficile.
  • Non cercare di over-progettare il sistema fin dall'inizio, come si potrebbe semplicemente sprecare il vostro tempo quando si arriva alla realizzazione vera e propria.
  • Mantenere i livelli più bassi il più semplice possibile, poi costruire le capacità più avanzate in alto.
  • Documentare le funzioni e scrivere alcuni test di unità, in particolare dopo l'aggiunta di istruzioni condizionali complesse.
  • Prova a errori di cattura più in alto lo stack possibile. Per esempio facendo convalida dell'input e controllando i valori di ritorno. Questo renderà più facile il debug.

Altri suggerimenti

Quando si lavora in codice a più livelli, è forte la tentazione di tuffarsi in un livello inferiore quando l'API non consente di fare esattamente quello che vuoi che faccia. Ciò è particolarmente difficile quando scrittura livelli mulitple allo stesso tempo.

Ecco alcuni suggerimenti:

  • Trattare tutti gli altri livelli rispetto a quello che si sta lavorando come se essi sono sigillate. Creato da un'altra società, sviluppatore, ecc Resistere alla tentazione di modificare un altro livello per risolvere un problema nel vostro livello corrente.
  • Crea una "tier pari livello" per quello che si sta lavorando. Questo è difficile da descrivere in senso astratto, ma permette di dire la tua livello inferiore è un livello di business, e il livello superiore è un'interfaccia utente, creare un altro strato di interfaccia utente per una diversa applicazione. Ora avendo due consumatori della stessa API punto può dare una mano quello che dovrebbe essere in ogni strato.
  • Prova alternando l'ordine in cui si lavora su livelli. Per esempio, in alcune applicazioni trovo più utile per progettare l'interfaccia utente, poi lavorare il mio fino in fondo per lo strato di business / database per fare quel lavoro UI come progettato. Altre volte, rende più senso stat con il modello di dati e il lavoro fino ad un interfaccia utente. Ma il punto è, si "pensa" di un'API in modo diverso in questi due scenari. E dopo aver guardato codice multi livelli da entrambe le angolazioni aiuta.
  • L'esperienza conta. A volte basta fare l'errore di codice di eccessivamente accoppiato è l'unico modo per imparare veramente per evitarlo. Invece di programmare sulla vostra applicazione essere perfetto, piano su di esso essere imperfetto. Con questo voglio dire prima configurazione di un rapido ciclo di sviluppo / test / refactoring, in modo da poter adattarsi rapidamente a errori che è solito vedere fino a che dopo averli fatti. Questa è anche una zona dove "usa e getta di prototipazione" viene in aiuto. Fare una semplice bozza, imparare da esso, e buttarlo via. La parte buttare via è importante. Anche se la sua incredibile, cominciare a costruire un altro da zero. Potrai inevitabile renderlo migliore (e nel mio expirience, più organizzata) in base a quello che hai imparato dal prototipo.

E 'davvero più una questione di esperienza che il vostro grado. Se si sta ancora imparando cose su come controllare l'hardware, poi, naturalmente, il codice sta per cambiare. Non vorrei agonizzare su questo. Tuttavia, dal momento che ciò che si sta realmente facendo è la prototipazione, si dovrebbe essere pronti per il refactoring del codice, una volta che lo avete a lavorare. Rimuovere licenziamenti, i dati compartimenti stagni e funzionalità, e organizzare le interfacce in modo che abbia senso.

La mia esperienza è che il codice del driver dispositivo ha bisogno di top-down e bottom-up di progettazione / realizzazione, quello che io chiamo outside-in. Sapete ciò che l'utente sta andando a voler fare e si può scrivere queste interfacce, e si sa che cosa il driver di basso livello ha bisogno di fare e si scrive che. Se non soddisfano bene in mezzo, ripensare il layout del modulo.

Per un miglioramento, soggetto il vostro disegno e il codice di rivedere da persone con più esperienza. Lasciare fuori ego di esso e solo ottenere loro assumere il problema. Si potrebbe anche leggere un libro su analisi e progettazione orientata agli oggetti (che ho usato per come i libri di Peter Coad. Non so chi li sta scrivendo ora). Un buon mostrerà esempi di come partizionare un problema in oggetti con ruoli e responsabilità chiare.

L'altra, una volta che hai finito di prototipazione dei driver e sapere come controllare l'hardware, è quello di rendere le disposizioni assicurarsi di aver dettagliate. Niente colpi di scena codice più che scoprire esigenze mentre si sta scrivendo. Si potrebbe anche provare ad imparare UML e creare con gli schemi prima di scrivere codice. Questo non funziona per tutti. Si noti inoltre che non è necessario essere di codifica in un linguaggio che supporti object-oriented costrutti per uso OOD.

Se il problema è come costruire astrazioni appropriate, che sembra essere il caso, penso che la cosa più importante che puoi fare per imparare (oltre a chiedere recensioni Design-code / leggere libri / lettura codice) è pensare duro prima di iniziare la scrittura di codice .

Di solito succede che si avvia con una vaga idea di ciò che si vuole e come dovrebbe essere fatto e poi andare a scrivere il codice. Più tardi si scopre che non hai pensato le cose attraverso e si dispone di diversi buchi che ora, perché avete investito tempo nella scrittura del codice, sono difficili da patch, che porta ad uno spreco di tempo o il codice hacky.

Riflettere su come creare un design che può gestire facilmente le modifiche. Ad esempio, incapsulare i dati che devono viaggiare tra gli strati, quindi se si scopre in seguito vi siete persi un parametro cruciale è possibile aggiungere facilmente alla struttura senza dover modificare il codice in tutto il mondo.

Prova a "eseguire il disegno nella tua testa", più volte, finché non si è reasoanly sicuri di aver considerato i dettagli più importanti e si può dire (questa è la parte più importante, perché ti manca sempre cose o richieste cambierà) che, se vi siete persi qualcosa che si può modificare i moduli con relativa facilità.

UML può aiutare a strutturare il modo di pensare alla progettazione. E 'certamente non è una panacea, ma mostra i diversi criteri da prendere in considerazione quando si crea un disegno di software.

E 'un po' come il classico consiglio insegnante di scacchi: " sedersi sulle mani ": -)

I driver sono suscettibili di un livello di approccio.

Il driver potrebbe avere diverse "classi":

  • Solo ingresso
  • Solo l'uscita
  • sia io che O.

Si dovrebbe avere un'interfaccia standard, ad es.:

GetKnobLevel()
GetNextKeyboardButton

Oppure, un altro approccio è quello di avere qualcosa di simile

syscall(DRIVERNUMBER, command)

mettere i parametri/risultati in specifici registri.

Si tratta di un semplice, utilizzabile approccio.Una più complessa variante potrebbe essere quello di avere circolare code tra hardware comunicando il codice e il software di comunicare il codice, invece di registri.

Qui è il modello mentale che sto utilizzando:

---
Application
---
OS
---
Driver communicators
---
drivers
---
hardware

C'è un ben definito, non-varianza interfaccia tra ogni strato (continuo a immaginare una torta a strati, con una spessa glassa tra livelli...).Il sistema operativo potrebbe non esistere per voi, naturalmente.

Se il tuo MCU supporta il software e gli interrupt hardware come CPU x86, è possibile utilizzare quelli per isolare i driver dal driver comunicatori.

Questo è un po ' un "overengineery" soluzione, ad essere onesti.Ma, in una situazione in cui la complessità è sempre significativa, è più facile avere stretto di ingegneria che hanno sciolto ingegneria.

Se si sta comunicando tra gli strati, è possibile utilizzare una variabile globale per ogni comunicazione di "canale", e accedere in modo disciplinato, utilizzando solo le funzioni per l'accesso.

In genere si vuole fare carta disegni a un certo livello, qualche lavoro di esplorazione e di riprogettazione prima è veramente impostato il codice del tuo progetto.Diagrammi di flusso e diagrammi di transizione lavorare bene qui.

Questo è l'approccio che ho favorito nel mio embedded e dei sistemi di lavoro e funziona bene per me.

Anche questo problema di spazio non è ben esplorato dai computer tradizionali, i programmi di scienze.È molto meno indulgente di Web o sistemi operativi moderni.

A mio parere, gli aspetti più importanti del codice ben architectured sono a basso grado di accoppiamento e la separazione di effetti collaterali da State .

Inoltre - il codice è un mestiere. Non credo che si può fare la soluzione perfetta fin dall'inizio. Siate pronti a modificare il codice come si impara cose nuove. In realtà - Assicurarsi di abbracciare cambiarlo auto come parte del vostro lavoro

.

di non essere troppo loquace, ma una citazione da The Mythical Man-Month viene in mente: "Piano di buttare via uno; si vuole in ogni caso"

Il corollario dei quali è "farlo funzionare. Fare bene. Lo rendono veloce".

Suppongo che questo mi fa un sostenitore di fare qualche disegno up-front, ma non sempre paralizzato da esso. Non deve essere perfetto la prima volta attraverso. Piano di refactoring. Speriamo che si hai scritto le cose in modo tale che un non sei veramente buttando molto codice via, ma riorganizzare le cose in un modo più gradevole.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top