È una buona idea progettare un'architettura pensando che le classi dell'interfaccia utente possano essere sostituite da un'interfaccia a riga di comando?


92

Nella pagina 25 di Codice completo, si dice che è una buona idea poter sostituire facilmente le normali classi dell'interfaccia utente con una riga di comando.

Conoscendo i suoi vantaggi per i test, che dire dei problemi che può portare?

Questo lavoro extra ripagherà davvero i progetti Web e mobili? Che dire di piccoli e medi progetti; si applicano le stesse regole? E se rendesse il tuo design più complesso?


2
In Perl, questo è proprio ciò a cui servono strumenti come MooseX :: Getopt e Plack :: Handler :: CLI .
Ether

4
Se prima costruisci il tuo programma con una CLI, l'interfaccia utente può essere sovrapposta a essa, offrendo molta più flessibilità di un'interfaccia utente profondamente incorporata nel programma. Questo è più o meno lo stesso per i servizi web.
zzzzBov,

28
È sempre una parola forte.
Mark Canlas,

8
Si prega di notare la citazione originale, che è: "L'architettura dovrebbe essere modularizzata in modo che una nuova interfaccia utente possa essere sostituita senza influire sulle regole di business e sulle parti di output del programma. Ad esempio, l'architettura dovrebbe rendere abbastanza facile tagliare gruppo di classi di interfaccia interattiva e collegare un gruppo di classi della riga di comando. " Quindi CC non dice che dovresti prepararti a sostituire una GUI con una riga di comando, dice solo che l'architettura dovrebbe adattarsi alla modifica dell'interfaccia utente. La cosa della riga di comando della GUI-> è solo un esempio.
sleske,

2
@Vandell Ho la seconda edizione del codice completo e questo non è menzionato a pagina 25. A quale edizione ti riferisci?
JW01,

Risposte:


43

Essere in grado di riutilizzare la funzionalità sotto diverse interfacce (ad es. GUI vs CLI vs REST) ​​non è sempre necessario ma bello avere e abilitare il riutilizzo fortuito per un sistema, poiché altre persone trovano nuovi modi di interagire con esso.

Ciò presenta alcuni svantaggi che devono essere ponderati:

  1. Richiederà ulteriori livelli di astrazione (a volte anche livelli). Pur avendo questi livelli è una buona pratica ingegneristica, essi hanno un costo aggiuntivo in fase di sviluppo, la comprensione che potrebbe non portare a ridurre gli sforzi in altre aree (ad esempio manutenzione, riutilizzo, test), quindi vale la pena di riflettere un po 'su di esso.
  2. Il flusso ottimale per un mezzo può essere terribile per gli altri. Se la funzionalità è stata progettata per supportare una GUI, potrebbe essere troppo chiacchierona per il Web . Non tutte le funzionalità sono utili su ogni supporto.
  3. C'è una trappola nel tentativo di definire un convertitore generico tra i servizi e l'interfaccia utente, quindi è possibile definire il contratto di servizio e derivare automaticamente (o il più possibile) l'interfaccia utente per tutti i mezzi. Molti progetti hanno sprecato troppi sforzi nel tentativo di creare tali framework e di aggiungere ogni possibile personalizzazione al variare dei requisiti.

Detto questo, nella mia esperienza l'implementazione di tali livelli ha sempre finito per pagare lo sforzo. In un paio di casi sono riuscito a distribuire i sistemi in tempo perché alla fine abbiamo dovuto scambiare i media (ad esempio dall'integrazione dei servizi Web all'interfaccia utente) alcune settimane prima della data di scadenza.


2
Come altri commenti hanno notato, dovrebbe aumentare la coesione del codice e ridurre l'accoppiamento. Entrambi dovrebbero rendere il codice più semplice e più facile da testare. Flow è più un concetto di GUI e di solito non dovrebbe essere presente in altre funzionalità.
BillThor,

Non riesco a credere che questo non sia stato ancora menzionato, ma questa è l'essenza dell'architettura Model-View-Controller. Il punto è poter scambiare visualizzazioni e controller a piacimento, per ridurre l'accoppiamento come dice @BillThor. Questo è il miglior caso d'uso per MVC.
Rudolf Olah,

110

Completamente a parte il test, l'ovvio vantaggio di questo approccio è che renderà il vostro progetto automatizzabili e script . Se sono in grado di inviare comandi da riga di comando a un programma, posso scrivere uno script per eseguire compiti complicati molto più facilmente (e in modo più affidabile!) Di quanto potrei creare una macro per automatizzare la stessa cosa su una GUI.

Il fatto che valga davvero la pena fare, ovviamente, dipende interamente dal fatto che tu abbia o meno molti utenti che vorrebbero automatizzare il tuo programma.


12
Molte applicazioni utilizzano un modello di plug-in per gli script. Di solito viene esposto il modello a oggetti e un linguaggio come python viene utilizzato per scrivere gli script. Non credo che i parametri della riga di comando funzioneranno per un'app non banale.
softveda,

Un altro vantaggio può essere la rilevabilità. La funzione Ctrl-Maiusc-P di Sublime Text ne è un esempio fantastico. Se c'è qualche oscura funzionalità che desidero, piuttosto che dover cercare nei menu, scrivo semplicemente quello che penso che sarebbe chiamato, e posso vedere il comando (e il collegamento) e sono in grado di eseguirlo immediatamente.
Adam Iley,

OpenDJ, un server LDAP open source basato su Java è un ottimo esempio di questo: la riga di comando per ogni modifica effettuata nella GUI è disponibile nella finestra di dialogo di conferma.
Franck,

1
@ Marnixv.R .: i gesti sono semplicemente un modo conveniente per eseguire alcune azioni che potrebbero essere specificate da un comando, ad esempio "Ingrandisci 35.73 N 118.23 O". Un disegno potrebbe essere inserito come comandi, anche se sarebbe scomodo. Penso comunque che ci sia una grande utilità in un'interfaccia opportunamente gestibile da script, e per crearne uno è necessario pochissimo lavoro.
Kevin Cline,

7
+1: Un altro vantaggio chiave è che semplifica la registrazione delle azioni dell'utente, semplificando la riproduzione dei problemi di produzione.
Kevin Cline,

81

Non è un lavoro extra, solo un lavoro diverso . Se lo fai bene, non solo non lo renderà più complesso, lo renderà più semplice perché ti costringerà a disaccoppiare il tuo design. Indipendentemente dal fatto che tu abbia effettivamente implementato l'interfaccia della riga di comando, il tuo progetto sarà migliore per renderlo possibile.


4
-1 per diverse istruzioni completamente errate. Naturalmente lo renderà più complesso. Dopotutto, è un requisito / funzionalità aggiuntivo.
Boris Yankov

@BorisYankov Penso che volesse dire "complicato" anziché "complesso" - suonano simili e si sovrappongono nel significato, quindi sono facili da confondere in occasione
Izkata

43

Un vantaggio chiave che non sembra essere stato menzionato è che essere in grado di fare questo praticamente impone il rigoroso disaccoppiamento dell'interfaccia utente dal codice sottostante. Un vantaggio chiave di ciò è che significa che se è necessario modificare in modo significativo la GUI (ad esempio gli standard iOS in standard OSX o un motore grafico in un altro), è tutto ciò che è necessario modificare, poiché il codice sottostante non dipende da il layout dell'interfaccia utente. Non può essere, perché se lo fosse, gli strumenti da riga di comando non funzionerebbero.

Oltre a questo, essere in grado di automatizzare i test è un vantaggio chiave.


Correggimi se sbaglio, ma passare da una GUI a un'altra richiederebbe comunque un lavoro significativo in termini di convalida del modulo / visualizzazione di messaggi di errore, impostazione dei gestori di eventi, ecc.
Fai clic su Aggiorna

5
Sì, ma tutta quella convalida fa parte di una buona interfaccia utente, che ho detto che è necessario modificare. Il codice back-end che memorizza (ad esempio) lo stato corrente dell'account dell'utente, l'algoritmo per la ricerca di oggetti, le regole specifiche del gioco, ecc. La cosa chiave qui è che se devo passare dall'interfaccia utente basata su mouse / tastiera a interfaccia utente touchscreen per un gioco, dovrei comunque essere in grado di utilizzare lo stesso motore back-end per gestire calcoli di combattimento e punteggio, quindi posso concentrarmi sulla scrittura di nuovi gestori di eventi che utilizzano lo stesso sistema sottostante.
Deworde,

2
non è affatto facile, odio scrivere gestori di eventi e formare un codice di convalida molto più di un codice aziendale. (anche se sono d'accordo con te sul fatto che dovrebbero essere de accoppiati nel modo in cui hai descritto)
Fai clic per votare il

2
@ClickUpvote In una certa misura dipende da come si implementa la GUI. Una GUI davvero sottile che invia messaggi ValueChanged a una classe di supporto e riceve in risposta messaggi ValueValid / ValueInvalid sarà molto più semplice sostituire quella che esegue tutta la convalida negli eventi OnTextboxChanged.
Dan Neely,

@ClickUpvote Sono abbastanza d'accordo, è per questo che voglio essere in grado di concentrarmi su ciò che mi piace incorrotto, o dare a ciò che odio la mia piena attenzione, in modo da poterlo fare al più presto.
Deworde

17

Sì, è quasi sempre una buona idea.

Se segui questo approccio, probabilmente non avrai una logica aziendale o l'accesso ai dati in uno stesso thread della GUI e dietro alcuni gestori della GUI. Solo per questo motivo vale la pena investire.


2
Quale sarebbe il vantaggio di questo, se stai scrivendo ad esempio un editor di testo?
Nikie,

5
@nikie Perché, ad esempio, è possibile sostituire la vista dell'editor di testo WYSIWIG con un front-end basato su testo semplice o basato su markup e purché passasse le stesse informazioni al modello sottostante, l'infrastruttura esistente continuerà a funzionare.
Deworde,

5

Penso che sia una buona idea. Inoltre, essere in grado di scrivere un secondo front-end della riga di comando, dimostra in definitiva che la logica aziendale è totalmente disaccoppiata con qualsiasi particolare architettura del server delle applicazioni.


5

L'unico pericolo che vedo nel fare questo è che per arrivare a una certa parte dell'interfaccia utente, l'utente deve normalmente attraversare altre parti dell'interfaccia utente.

Dove lo sviluppatore può semplicemente eseguire direttamente l'interfaccia utente. Ho visto situazioni in cui uno sviluppatore non poteva riprodurre un problema degli utenti fino a quando non hanno effettivamente utilizzato il prodotto.

Quindi, anche nel creare i test.


3

No. Terribile consiglio.

È un po 'yagni (non ne avrai bisogno).

L'esposizione di un'interfaccia a riga di comando non equivale a strutturare l'app in un modo che supporti il ​​test di unità o sia conforme a qualsiasi parte di SOLID o qualsiasi pratica di programmazione che consiglierei.

Non funziona per nessuna interfaccia utente che non si adatta a un'interfaccia a riga di comando. MS Paint è un'app davvero semplice, ma come, in ogni situazione, vedresti un vantaggio nel poterlo controllare da una riga di comando?

Non ti aiuterebbe a implementare gli script. In realtà ostacolerebbe qualsiasi progresso in quella direzione.

L'unica cosa positiva è che è apparso a pagina 25, quindi almeno ricevi un avvertimento che il resto del libro potrebbe essere, ... puzzolente. L'ho letto molto tempo fa e non mi è piaciuto, quindi sono di parte.


1
Concordato +100000000

4
Scriptable MSPaint sembra davvero utile in realtà.
RoundTower

IMO la migliore risposta. Da quando seguo il mantra "non implementare 'YAGNI", ho molto più tempo a concentrarmi sul lavoro reale e mi rimane ancora abbastanza tempo per sperimentare molto. Cercare di essere intelligente in anticipo mi ha dimostrato che la maggior parte delle volte il cliente desiderava un'estensione diversa da quella precedentemente menzionata, quindi non è stato sprecato tempo in qualcosa di non necessario.
topskip

PSPaint + interfaccia della riga di comando = AutoCAD
Vorac

-1 (se potessi) Nota che non dice "implementare una CLI e una GUI"; dice "provvedere all'implementazione di un'interfaccia utente alternativa, come una CLI".
Mark Hurd,

2

Basandosi su ciò che ha detto Mason Wheeler, essere in grado di interagire con un'applicazione tramite una riga di comando rende molto semplice automatizzare le attività.

Ciò è particolarmente utile nei test.

Per fare un esempio pratico, se voglio eseguire test automatici su un'applicazione, potrei voler installare l'applicazione automaticamente. Per fare ciò, potrei passare i seguenti parametri, "myApplication.exe / silentinstall".

Potrei programmarlo in modo tale che quando specifico questa opzione da riga di comando, un'installazione venga eseguita silenziosamente in background, senza il programma di installazione della GUI. Qualunque input per l'installer (come la directory di installazione) potrebbe forse essere prelevato da un file XML.

Prendi un altro esempio. La GUI di Microsoft Test Manager (fornita con Visual Studio) consente agli utenti di avviare esecuzioni di test dalla sua interfaccia GUI, ma fornisce anche un'interfaccia della riga di comando per fare la stessa cosa (usando una combinazione di opzioni e input della riga di comando). Ciò significa che posso montare uno script PowerShell o DOS per automatizzare l'avvio dei test e quindi creare un'attività pianificata in modo che gli script vengano eseguiti ogni notte, forse.

Alcune applicazioni dispongono di opzioni della riga di comando che specificano l'apertura di un'applicazione con determinate opzioni (ad esempio, potrei usare '/ maximize' per aprire l'applicazione in una finestra ingrandita).

Esistono molti scenari in cui è possibile utilizzare un'interfaccia della riga di comando. Questi sono solo alcuni esempi.


1

Notare di nuovo la frase: "[E '] una buona idea poter sostituire facilmente le normali classi dell'interfaccia utente con una riga di comando". Non significa che devi scrivere una CLI, solo che puoi farlo facilmente.

Quindi, ciò che dice è che la tua UI dovrebbe essere disaccoppiata dal resto del codice.


2
Penso che tu abbia intenzione di fare un commento, giusto?
Julio Rodrigues,

1

Dipende e quando dico che dipende, non si tratta solo di avere un paio di casi limite, ma dipende molto dall'applicazione e dal pubblico di destinazione. Supponendo che stiamo eliminando i giochi dall'equazione, allora c'è ancora una vasta gamma di applicazioni che potresti scrivere dove un comando come è improbabile o non verrà mai implementato. In cima alla mia testa, qualsiasi applicazione destinata a un ambiente mobile (ad es. IOS, Android, ecc.) Probabilmente rientrerà in questa rubrica.

Tenendo presente ciò, nello spazio generale del software, è improbabile che qualsiasi applicazione fortemente dipendente dalla visualizzazione (ad es. PowerPoint, Maya , ecc.) Vedrà mai implementata una sostituzione della riga di comando. In effetti, nel caso di software di grafica come Maya, è discutibile un buon esercizio mentale per determinare come funzionerebbe una versione completa e corretta della riga di comando e potrebbe non essere possibile farlo dal punto di vista dell'utente. Pertanto, è chiaro che ci sono applicazioni definitivamente comuni che possono essere incontrate laddove è improbabile che un comando come un'interfaccia sia mai stato visto, o desiderabile anche se lo scripting dell'applicazione può essere desiderabile.

Successivamente, se osserviamo la forma suggerita dal punto di vista dell'architettura generale del software, posso vedere dove avrebbe senso chiedersi periodicamente "Come posso accedere a questa funzione senza l'interfaccia utente?" In generale, se non c'è modo di farlo e non interagisce direttamente con l'utente (ad es. Input di gesti), è probabile che ci sia una situazione in cui l'architettura complessiva deve essere migliorata. Per consentire una facile verifica, si desidera poter accedere direttamente al comando senza passare attraverso l'interfaccia utente, anche se potrebbero non essere invocati tramite una riga di comando. Ciò significa generalmente che deve essere presente un'API solida e teoricamente un'API valida dovrebbe consentire l'accesso tramite riga di comando o interfaccia utente. Inoltre, a lungo termine,

Alla fine della giornata, penso che ciò che il suggerimento sta cercando di ottenere abbia senso (ad esempio avere una buona API e costruire la tua interfaccia utente da quella), ma la selezione della parola potrebbe essere stata un po 'migliore per ottenere il punto .


1
Non sono in disaccordo in generale, ma uno dei grandi punti di forza di Maya è il fatto che in realtà ha un'API di scripting molto potente (originariamente MELScript, ora Python).
jwd

@jwd - Maya è un esempio che ho scelto perché l'ho usato un paio di anni fa, se ne hai uno migliore nella stessa linea di pensiero fammi sapere. Forse Bryce anche se non lo sa bene?
rjzii,

0

Dipende.

Spesso partizioniamo i nostri programmi come modello / vista / controller o modello / vista / vista / modello. Sembra che il modello dovrebbe consentire l'accesso alla riga di comando, ma non sono sicuro del controller. Naturalmente, la vista è ciò che viene sostituito.

Alcune differenze possono esistere in base alla catena degli strumenti. Code Complete è un libro di Microsoft Press, quindi forse stai usando le tecnologie Microsoft per questa GUI? In tal caso, penso che potrebbe esserci una casella di controllo quando si crea l'app per esporre le interfacce tramite COM o DCOM. Per alcune tecnologie Microsoft, penso che le tabelle delle risorse e il passaggio dei messaggi siano abbastanza intensamente associati a tutto ciò che i Wizards ti aiutano a prototipare rapidamente. Penso che stia migliorando, ma se stai mantenendo MFC o moduli, potrebbe farti un po 'male.

In alcuni casi il tuo programma basato sulla GUI potrebbe essere un wrapper attorno a un'interfaccia di gestione o potrebbe avere una logica così piccola, che non c'è molto da controllare dall'interfaccia della riga di comando. La creazione di un'app console separata potrebbe essere più rapida e consentire comunque di eseguire script, testare o utilizzare ciò che è importante.

Il punto chiave immagino che il suggerimento non sia una regola. Se lo segui, dovresti ottenere test dell'unità e di accettazione più facili o un'interfaccia di riserva per quando tu o un cliente preferisci digitare invece di fare clic. Se si ripaga da solo, fallo. In bocca al lupo.


4
-1: Code Complete è un libro indipendente dalla lingua sulla programmazione artigianale.
Deworde,

1
Non ha mai detto diversamente.
Fai clic su Aggiorna

E la sua domanda era specifica per lo sviluppo dell'interfaccia utente ... Il tuo punto signor deworde?
Ian,

0

Dipende da quanto utile sarebbe il programma da riga di comando. Alcune cose, come tracciare un percorso su una mappa o giocare a un gioco 3D, semplicemente non si prestano a un'interfaccia a riga di comando. Ma altre cose, come gli strumenti di sistema, sono molto migliori dalla riga di comando che da una GUI, per la semplice ragione che possono essere copiate.

Il Dr. Richard Hipp una volta disse che il suo sistema operativo GUI ideale era un desktop vuoto con un'icona per aprire le finestre di comando e un'altra icona per aprire un browser web. Mi sento quasi allo stesso modo. Se fosse utile come programma da riga di comando e non troppo difficile da costruire in quel modo, lo farei. La GUI potrebbe essere un programma completamente separato, magari creato da qualcun altro!


Perché tracciare un percorso su una mappa non si presta all'automazione della CLI? Qualcosa del genere PlotRoute(startPoint, endPoint)è piuttosto semplice.
Mason Wheeler,

@MasonWheeler - Credo che sarebbe più simile aPlotRoute(startPoint, endPoint, chart)
Fabricio Araujo il

0

In questi giorni (almeno per Java) sembra che prima o poi tutti i programmi aggiungano un servizio web (SOAP o Ajax o entrambi) prima o poi. Quindi in generale sì, pensa in questo modo, ma un front-end del servizio web è più probabile di una riga di comando se vuoi una metafora mentale migliore ... e una più probabile.


0

C'è un modo diverso di vedere le cose. Invece di supporre che una riga di comando sia l'unica strada da percorrere, perché non supporre che al suo posto si possa usare il controllo vocale? È quindi richiesto un paradigma completamente diverso.

Prima che Jobs prendesse il controllo di Apple, venivano esplorati meccanismi di controllo vocale molto sofisticati. Apple lo ha schiacciato a favore di cose come Siri.

Sospiro.

Popolare e ovvio non sono sempre "migliori".


Uno dei motivi principali della riga di comando è principalmente quello di poter testare e scriptare la funzionalità del software. Potrebbe essere un po 'imbarazzante (o almeno disco-hoggy) registrare clip audio delle nostre voci solo per testare l'unità del software o eseguire uno script batch.

0

Questa è generalmente una buona idea, sì.

Per metafora, le persone possono pensare a questo come una forma di design RESTful. .... non è, di per sé, in quanto una tipica interfaccia utente (G) potrebbe comportare transazioni multi-fase complesse come la creazione di un account.

Better that one stays away from multi-stage complexity through shopping-cart-like models for transactional setup.

Una volta ho programmato una metafora dell'interfaccia utente drag'n'drop nel browser. Regole di interazione molto complesse sul back-end per rendere la UX naturale. Ho risolto questo problema rendendo il sito un'API e la GUI era un'app completa che generava eventi su azione. Un modulo ha rilevato questi eventi e, in un timer, li ha raggruppati in "chiamate API" (per l'efficienza della rete).

Il risultato è stato un sistema core completamente RESTful. Il secondo risultato fu che avevo un'interfaccia per terze parti, che potevo esporre usando i profili di affiliazione secondo il modello di business.


-1

Un vantaggio è che sarai costretto a pensare al flusso dell'interfaccia utente dal punto di vista dell'utente. (Cosa sto cercando di raggiungere? Quale contesto devo impostare? Dato quel contesto, come posso raggiungere l'obiettivo?)

C'è una grande differenza tra "creare un conto bancario" e "scrivere un documento MS Word". Anche se non si crea una CLI, potrebbe aggiungere valore solo per considerare il "contesto CLI" necessario. Le modelle non vivono solo nel modello a oggetti business!

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.