recentemente mi è stato affidato il compito di implementare un modo per aggiungere il supporto per il controllo delle versioni delle specifiche dei pacchetti hardware in una delle nostre librerie. Prima un po 'di informazioni sul progetto.
Abbiamo una libreria hardware che ha classi per ciascuno dei vari comandi che supportiamo l'invio al nostro hardware. Questi moduli hardware sono essenzialmente solo luci con pochi pulsanti e un display a 2 o 4 cifre. I pacchetti seguono generalmente il formato {SOH}AADD{ETX}
, dove AA è il nostro codice di azione sentinella e DD è l'ID dispositivo. Queste specifiche del pacchetto sono diverse da un comando al successivo, ovviamente, e le diverse versioni del firmware supportano diverse specifiche. Ad esempio, nella versione 1 un codice azione di 14 potrebbe avere una specifica di {SOH}AADDTEXT{ETX}
che sarebbe AA = 14 letterale, DD = ID dispositivo, TEXT = testo letterale da visualizzare sul dispositivo. Quindi usciamo con una revisione aggiungendo un byte esteso alla fine del pacchetto come questo {SOH}AADDTEXTE{ETX}
. Supponiamo che il campo TESTO sia a larghezza fissa per questo esempio. Ora abbiamo aggiunto un nuovo campo all'estremità che potrebbe essere usato per specificare il colore o la velocità del flash del testo / dei pulsanti. Attualmente questa libreria java supporta solo una versione dei comandi, l'ultima.
Nella nostra libreria hardware avremmo una classe per questo comando, diciamo un DisplayTextArgs.java. Quella classe avrebbe i campi per l'ID del dispositivo, il testo e il byte esteso. La classe command esporrà un metodo che genera la stringa ( "{SOH}AADDTEXTE{ETX}"
) usando il valore della classe. In pratica creeremo la classe Args come necessario, popoliamo i campi, chiamiamo il metodo per ottenere la nostra stringa di pacchetti, quindi li spediamo attraverso il CAN.
Alcune delle altre specifiche dei nostri comandi possono variare per lo stesso comando, sulla stessa versione, a seconda di alcuni stati di runtime. Ad esempio, un altro comando per la versione 1 potrebbe essere {SOH}AA{ETX}
, in cui questo codice di azione cancella tutti i moduli dietro uno specifico dispositivo di controllo del loro testo. Potremmo sovraccaricare questo pacchetto per avere campi opzione con più significati come {SOH}AAOC{ETX}
dove OC è testo letterale, che dice al controller di cancellare solo il testo su un tipo specifico di modulo, e di lasciare gli altri da soli, o la specifica potrebbe anche avere un formato di opzione di {SOH}AADD{ETX}
per cancellare il testo da un dispositivo specifico. Attualmente, nel metodo che genera la stringa del pacchetto, valuteremmo i campi della classe args per determinare quale specifica useremo durante la formattazione del pacchetto. Per questo esempio, sarebbe sulla falsariga di:
if m_DeviceID != null then use {SOH}AADD{ETX}
else if m_ClearOCs == true then use {SOH}AAOC{EXT}
else use {SOH}AA{ETX}
Avevo preso in considerazione l'utilizzo di XML o un database per memorizzare stringhe di formato String.format, che erano collegate ai numeri di versione del firmware in alcune tabelle. Li caricheremo all'avvio e passeremo il numero di versione del firmware dei firmware attualmente in uso (posso interrogare i dispositivi per la loro versione del firmware, ma la versione non è inclusa in tutti i pacchetti come parte della specifica). Questo si rompe abbastanza rapidamente a causa della natura dinamica di come selezioniamo quale versione del comando usare.
Ho quindi considerato l'utilizzo di un motore di regole per creare possibilmente espressioni che potevano essere interpretate a runtume, per valutare lo stato della classe args e da quello selezionare la stringa di formato appropriata da utilizzare, ma il mio breve sguardo ai motori di regole per java spaventato me via con la sua complessità. Mentre sembra che potrebbe essere una soluzione praticabile, sembra eccessivamente complessa.
Quindi è per questo che sono qui. Non direi che il design è la mia abilità più strong, e sto avendo problemi a trovare il modo migliore per affrontare questo problema. Probabilmente non sarei in grado di cambiare radicalmente le lezioni di args, ma se il trade off fosse abbastanza buono, potrei essere in grado di convincere il mio capo che il cambiamento è appropriato.
Quello che vorrei dalla community è un feedback su alcune best practice / metodologie di progettazione / API o altre risorse che potrei usare per realizzare:
Logica per determinare quale gruppo di comandi utilizzare per una determinata versione del firmware
Di questi comandi, quale versione di ciascun comando usare (in base allo stato delle classi args)
Mantenere la logica delle regole disaccoppiata dall'applicazione in modo da evitare la necessità di rilasci per ogni versione del firmware
Essere abbastanza semplice, quindi non ho bisogno di settimane di studio e di prove ed errori per attuare in modo efficace.