La rilevabilità per gli sviluppatori è un problema quando si utilizzano i principi SOLID?


10

Faccio app line of business in cui tutti gli altri sviluppatori sono abituati a fare app CRUD di base o sono focalizzati esclusivamente sulla creazione di interfacce graziose / funzionali e sto ottenendo molto.

"Con il modo in cui usiamo per farlo, il Dipendente avrebbe tutte le cose che potresti fare con un dipendente." Ed era vero. Quella "Classe" aveva migliaia di righe di codice e tutto ciò che si poteva fare con un dipendente era lì. O, peggio ancora, c'era una tabella di dati sui dipendenti e ogni sviluppatore ha capito come fare ciò che voleva fare nel gestore dell'evento.

Tutte le cose cattive di quell'approccio erano vere ma almeno lo sviluppatore che utilizza il dipendente potrebbe, senza andare ad altri documenti, capire come iscrivere il dipendente in un piano sanitario, dare un aumento di stipendio, licenziare, assumere, trasferire ecc. Lo stesso vale per Manager e tutte le altre idee principali. Oppure, se utilizzavano il dipendente con altre tabelle di dati necessarie, potevano semplicemente fare ciò che volevano.

Sì, c'era molto codice duplicato. Sì, era un codice molto fragile. Sì, test è stato molto più difficile del necessario. Sì, cambiare funzionalità è stata la paura di indurre e Copy Paste è stato naturale grazie all'approccio.

Ma potevano almeno scoprire cosa era disponibile creando una classe o potevano fare quello che dovevano fare senza dover capire la differenza tra interfacce, classi astratte, classi concrete ecc. E non dovevano cercare altro i metodi restituiti da intellisense o conoscere le tabelle in cui risiedevano i dati.

Ho cercato su Google / abbuffato e persino yahoo! D ma non ho trovato alcun riconoscimento di questo problema.

Quindi forse non c'è un problema e mi sto perdendo qualcosa. Ho distrutto il mio cervello cercando di trovare una soluzione in cui gli sviluppatori che non funzionano con il comportamento / il progetto reale possono facilmente scoprire come fare qualcosa senza dover fare riferimento a documenti esterni o scansionare i nomi delle classi nei vari componenti / progetti per trovare quello che sembra funzionare.

L'unica cosa che sono stato in grado di inventare è avere queste, per mancanza di un nome migliore, "Table of Content Class" che non fa altro che restituire le classi effettive (e in realtà la maggior parte di loro sono interfacce ma non lo fanno conoscere la differenza o anche la cura) che altri sviluppatori possono utilizzare per eseguire le attività effettive desiderate. Finiscono ancora con classi davvero grandi ma non c'è quasi nessun comportamento in esse.

Esiste un modo migliore che non richiede una conoscenza intima del livello intermedio in cui avviene l'implementazione effettiva di SOLID?

Fondamentalmente quello che sto chiedendo c'è un modo per consentire agli sviluppatori di tipo CRUD di continuare a essere sviluppatori CRUD in un sistema molto complesso


8
Forse i tuoi sviluppatori non dipendono interamente da IntelliSense (o equivalente) per la rilevabilità. Nomina bene le cose. Documenta bene le cose. Questo è un problema di comunicazione, non un problema tecnico.
Rein Henrichs,

Hmmm. Tipo. Più ci penso e più credo che ci sia un'opportunità commerciale in agguato.
ElGringoGrande,

2
@ReinHenrichs: se lo sviluppatore deve leggere la documentazione, ci vorrà del tempo e la produttività ne risentirà. Quindi è importante che scoprano rapidamente ciò di cui hanno bisogno per un determinato compito. Non deve fare affidamento su intellisense, ma è meglio che sia facile. Renderlo facile è certamente un problema tecnico.
Jan Hudec,

@JanHudec: No, non è un problema tecnico ma organizzativo nell'usare convenzioni adeguate per denominazione, layout e spazi bianchi. Senza le convenzioni di denominazione, non sapresti cosa cercare. Senza una denominazione coerente, non si troverebbe tutto e / o sarebbe molto più difficile rintracciare tutto. Senza un layout coerente e l'uso di spazi bianchi (specialmente nelle dichiarazioni di tipo) non troverai la metà delle istanze di cui hai bisogno. Sì, una regex migliore potrebbe aiutare, ma non voglio imparare regex solo per scoprire dove viene usata una classe.
Marjan Venema,

@JanHudec Non è un "se" ma un "quando". Gli sviluppatori dovranno leggere la documentazione. Se vuoi che "scoprano rapidamente ciò di cui hanno bisogno per un determinato compito", la soluzione migliore è concentrarti sull'efficacia della documentazione. Non cercare di risolvere un problema di persone (come la comunicazione) con una soluzione tecnica. Si. Fa. Non. Lavoro.
Rein Henrichs,

Risposte:


4

Sembra che quello che hai descritto (ad esempio la classe Employee con TUTTO il codice possibile che potresti fare con un dipendente) sia un modello estremamente comune che ho visto personalmente parecchio. Parte di quel codice che ho scritto da solo prima di conoscerlo meglio.

Ciò che inizia come una classe che dovrebbe rappresentare una singola entità con un insieme gestibile di metodi, si trasforma in qualcosa che è un incubo da mantenere perché ogni funzionalità e ogni versione continuano ad aggiungere sempre di più alla stessa classe. Questo va contro i principi SOLIDI che dicono che dovresti scrivere una classe una volta e resistere alla tentazione di modificarla ancora e ancora.

Qualche tempo fa (prima di scoprire modelli di design o SOLID come promossi da altri), ho deciso per il mio prossimo progetto di capovolgere un po 'le cose. Stavo lavorando su un server che fungeva da interfaccia tra due piattaforme molto grandi. Inizialmente, era richiesta solo la sincronizzazione della configurazione, ma potevo vedere che questo sarebbe stato un posto logico per molte altre funzionalità.

Quindi, invece di scrivere una classe che esponeva metodi, ho scritto classi che rappresentavano metodi (si è rivelato essere il modello "Command" di GoF). Invece di fare il lavoro per il cliente, tutte le mie principali classi di applicazione sono diventate titolari di stato persistenti e sono diventate molto più brevi. Ogni volta che dovevo aggiungere un nuovo metodo di interfaccia al servizio stesso, creavo semplicemente una nuova classe con il metodo Execute () che avviava tutto. Se più comandi avevano qualcosa in comune, derivavano dalla classe base comune. Alla fine la cosa aveva oltre 70 diverse classi di comando e l'intero progetto era ancora molto gestibile ed era in realtà un piacere su cui lavorare.

La tua "classe TOC" non è troppo lontana da quello che ho fatto. Avevo una fabbrica astratta (GoF) che era responsabile dell'istanza dei comandi. All'interno della classe factory, ho nascosto la maggior parte dei dettagli dietro la classe base e le macro in stile ATL, quindi quando un programmatore ha dovuto aggiungere o cercare una richiesta, sono entrati lì e tutto ciò che hanno visto è stato:

BEGIN_COMMAND_MAP()
    COMMAND_ENTRY( CChangeDeviceState )
    COMMAND_ENTRY( CSetConfiguration )
    ....
END_COMMAND_MAP()

In alternativa (o in aggiunta a), potresti mettere tutte le tue effettive classi di comandi in uno spazio dei nomi separato, quindi quando le persone scrivono codice e devono eseguire qualcosa, digitano semplicemente il nome dello spazio dei nomi e Intellisense elenca tutti i comandi che hai definito. Quindi ogni comando include tutti i metodi get / set che determinano esattamente quali parametri di input e output.

Puoi anche esplorare l'uso del modello Facade (GoF). Invece di esporre oltre 1000 classi ai tuoi ingegneri CRUD. Nascondili tutti dietro una singola classe che espone solo ciò che è necessario. Continuerei a pensare che ogni "azione" sia la sua classe, ma la tua classe Facade può avere dei metodi per creare un'istanza di ciascuna delle tue azioni e, di nuovo, con Intellisense vedrebbero immediatamente ciò che è disponibile. Oppure facciate avere metodi effettivi, ma internamente rendili istanti comandi, mettili in coda e attendi risposte. Quindi tornare come se fosse stata effettuata una normale chiamata di metodo.

(*) Non volevo entrare in troppi dettagli, ma in realtà avevo un insieme di classi "Command" e "CommandHandler". Ciò separava la responsabilità di gestire / accodare / serializzare i parametri in / out dalle classi che in realtà "gestivano" quei comandi.


Sì. Oggi ho capito che quello che abbiamo finito è un modello di facciata mal implementato. Non credo che ci sia altro da fare oltre a rompere la grande facciata in quelle più piccole. Mi piace la tua idea di incorporare alcune classi di comando dietro le quinte.
ElGringoGrande,

0

Può essere un problema Soprattutto se si nominano le cose male. Ma ci sono una serie di soluzioni senza ricorrere a classi complesse. Diamine, una classe con troppi metodi può essere ugualmente difficile da navigare con Intellisense.

Prova a usare gli spazi dei nomi (C #) o i pacchetti (Java) o qualsiasi concetto simile abbia il tuo linguaggio (li chiamerò tutti spazi dei nomi), per semplificare il problema.

Inizia con il nome della tua azienda. Ciò limita Intellisense ai soli spazi dei nomi scritti da voi stessi. Quindi, se hai più applicazioni, usa la seconda parte dello spazio dei nomi per dividerle. Includi uno spazio dei nomi Core, per cose che esistono tra le applicazioni. Quindi suddividere le cose in tipi di funzionalità. E così via.

Se lo fai bene, finirai con oggetti molto rilevabili.

Per fare un esempio, se desidero la convalida dell'utente, digito "MyCo". e mi dà un elenco di spazi dei nomi delle applicazioni. So che il database degli utenti è utilizzato in tutte le nostre app, quindi digito "Core". quindi ottengo un elenco di tipi di funzionalità. Uno di questi è "Convalida", quindi sembra una scelta ovvia. E lì, all'interno della convalida, c'è "UserValidator" con tutte le sue funzionalità.

In effetti, per cose che uso molto, ricorderò rapidamente i nomi o almeno le convenzioni. Poiché apporto molte modifiche alle regole di convalida, saprò che tutte le mie classi di convalida sono chiamate FooValidator, dove Foo è il nome della tabella. Quindi in realtà non dovrò attraversare gli spazi dei nomi. Digiterò UserValidator e lascerò che l'IDE faccia il resto del lavoro.

Ma per cose che non ricordo, è ancora abbastanza facile trovarle. E quando lo faccio, posso rimuovere il prefisso dello spazio dei nomi.


In parte, è una cattiva denominazione da parte mia. I nomi non sono orribili ma spesso penso a un mese migliore dopo il fatto. Ma anche con buoni nomi se hai migliaia di classi i nomi non sono sempre facilmente individuabili. Sto cercando di superare questo. Ho solo pensato che potrebbe esserci un modo noto.
ElGringoGrande,

0

Dato che li definisci sostanzialmente sviluppatori "CRUD", supponiamo che tu non pensi che siano molto bravi. Non sappiamo se questo significa che anche loro non capiscono il tuo dominio aziendale. Se comprendono il dominio, le classi dovrebbero avere un senso per loro. Sapendo che sono state create diverse classi, dovrebbero prima dare un'occhiata, chiedere in secondo luogo, considerare la costruzione da zero come terza opzione.

Per quanto riguarda il saper sapere come usare / riutilizzare automaticamente una classe semplicemente osservandola, non dovrebbe essere previsto per la prima volta. Dovrai documentare e possibilmente fornire ulteriori spiegazioni attraverso la formazione o eventualmente durante la revisione del codice.

Molti progetti API e open source forniscono documentazione, esempi di codice e altre spiegazioni. Potrebbe non essere necessario che il tuo sia facile da usare, ma non c'è modo di aggirarlo. Insegna loro bene.


No. CRUD non significa che non vadano bene. Sono sviluppatori che hanno sempre avuto a che fare con applicazioni di dati di base. CRUD = crea, leggi, aggiorna ed elimina. Non riesco a vedere come ciò li rende cattivi programmatori.
ElGringoGrande,

Nel gergo inglese britannico, "crud" == "merda".
Michael Shaw,
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.