Ho lavorato nel settore dei dispositivi embedded più di 5 anni come ingegnere software. La maggior parte delle volte i nostri produttori di hardware forniscono un kit di sviluppo software per le loro schede di riferimento. Sono principalmente dispositivi embedded Linux.
Il problema è che la maggior parte delle volte troviamo che le interfacce di gestione (Web UI, CLI, SNMP ...) sono strettamente accoppiate con il database che memorizza la configurazione persistente del dispositivo e anche le interfacce eseguono ognuna nella propria operazioni per applicare la nuova impostazione al sistema. Ad esempio, quando l'utente aggiorna lo stato del firewall tramite l'interfaccia utente Web, il server Web esegue automaticamente le chiamate alla funzione C system () utilizzando le regole di iptables come argomento. Ci rende molto improduttivi perché:
- Non possiamo riutilizzare componenti coesivi in nuovi prodotti. Le specifiche per i nuovi prodotti stanno diventando sempre più esigenti e il sistema embedded è costoso da sviluppare.
- Le interfacce di gestione non sono coerenti e il codice viene ripetuto tra di loro.
- Poiché il codice è strettamente accoppiato e l'astrazione non è buona, lo stesso vale per le attività. È difficile parallelizzare le attività se lo sviluppatore di una nuova funzionalità dovrebbe conoscere il server Web o il responsabile del server Web dovrebbe conoscere i dettagli di un'implementazione della funzionalità.
- Non possiamo testare i componenti ma l'intero sistema.
A volte le interfacce di gestione chiamano API del database per memorizzare nuove impostazioni e dopo di ciò chiamano la stessa funzione che legge le nuove impostazioni di funzionalità dal database e applica le nuove impostazioni nel sistema. Penso che non sia ancora una buona soluzione, ma mi piacerebbe sentire opinioni su questo design.
Ora stiamo cercando di rompere il software in componenti responsabili che possiamo riutilizzare in nuovi prodotti. Ad esempio vorremmo utilizzare gli attuali servizi di dispositivi incorporati nei nuovi prodotti e vorremmo anche avere interfacce utente che possiamo facilmente adattare per una nuova specifica.
Come ingegnere del software sono consapevole delle conseguenze di una cattiva astrazione, di una bassa coesione e di un cattivo incapsulamento nella progettazione del software, ma non ho una buona conoscenza dei modelli di progettazione. Questo è il nostro piano:
- Creato un set di funzioni C per i servizi del dispositivo che possono essere richiamati dalle interfacce utente, esponendo un'interfaccia che nasconde tutti i possibili dettagli di implementazione dall'utilizzo del servizio. Ci saranno funzioni per cambiare l'orario del sistema, per gestire i GPIO, per cambiare lo stato del firewall ...
- Queste API dei servizi si prenderanno cura della persistenza dei suoi dati utilizzando l'API del livello di persistenza.
- Le interfacce utente recuperano e impostano nuove impostazioni utilizzando questo set di funzioni dei servizi API.
- Ogni API di un servizio esporrà una funzione x_initialize () in modo tale che quando il sistema avvia una applicazione manager di avvio può chiamare questa funzione per ciascun servizio. Queste funzioni recuperano le impostazioni per il servizio dal database e le applicano al sistema chiamando le altre funzioni della propria API di servizio.
Non mi piace molto il punto 4 sopra perché somiglia molto alla situazione che abbiamo ora dove le interfacce utente memorizzano nuove impostazioni nel database e chiamano una grande funzione nessuno sa cosa funzioni questa funzione finché non viene vista la i dettagli di implementazione (e l'aspetto dei dettagli di implementazione di una funzione sono per me un cattivo sintomo).
Sto cercando informazioni sui modelli di progettazione per riutilizzare e separare le preoccupazioni come livello persistente, interfaccia utente e logica degli oggetti di business o di dominio (non sono molto sicuro di utilizzare concetti validi come oggetti di dominio). Vorrei una spiegazione con esempi concreti che potrei capire meglio.