martedì 30 settembre 2014

Any Way the Wind Blows

Con il tasso di turnover per gli sviluppatori di applicazioni di punta di Ventozoom, qualche parte del sistema deve essere maledetto. Dopo che Robert è entrato nel team, e vedere come il suo predecessore gestito dizionari, lui può capire.

Di Mark Bowytz2014/09/29

Poiché atterraggio a Ventozoom sei mesi indietro, Robert ha lavorato su una singola applicazione - un'applicazione NET piuttosto complesso, con una base di codice criptico da abbinare. Dice di essere responsabile di diversi separazioni dei dipendenti, è il tipo di applicazione che ha iniziato la vita come una soluzione mod-sporco e veloce innocente per un piccolo gruppo di clienti che, con l'aiuto di un team di aggressivi ragazzi di vendita, rapidamente cresciuti.

E con il numero di clienti, così è cresciuto richieste di nuove funzionalità.

Aggiungere alla miscela risultante dei requisiti mutevoli e funzionalità di scorrimento, i soliti ingredienti di cui avete bisogno per trasformare un problema in una davvero grande casino strisciato via: mancanza di manodopera, la mancanza di competenza nel manodopera disponibile e, ultimo ma non meno importante, la mancanza di tempo. In altre parole, nel corso dei primi anni il prodotto è stato sviluppato da solo una manciata di persone fuori dalle loro rispettive profondità tecnici, con troppo lavoro da fare e non abbastanza tempo per farlo, o abbastanza sonno per quella materia.

Ma l'applicazione rende i mucchi aziendali di soldi, quindi va bene ... giusto?

Urrà per codici hash!
Mentre confronto di base all'attuazione hashing e uguaglianza nella classe Object non consente contenitori come il NET HashSet <> per lavorare con qualsiasi tipo senza alcuna preparazione particolare per la classe di valore, è anche la fonte di una miriade di (a volte sottili) bug del software: Se GetHashCode viene ignorato, una coerente attuazione di Equals solito deve anche essere fornita (e viceversa), e se l'uguaglianza dipende lo stato dell'oggetto (che è, il più delle volte), l'oggetto deve essere immutabile (perché il codice hash deve essere).

Naturalmente, non ogni programmatore conosce le sottigliezze dei gemelli speciali GetHashCode e Equals. E perché dovrebbero? Uno non deve gravare il proprio sé con tutta questa complessità per godersi semplicemente il fatto che qualsiasi tipo può essere messo all'interno di un HashSet, o utilizzato come tipo di chiave in un dizionario - per quella materia - proprio come il predecessore di Robert a quanto pare ha fatto.

Pubblicità

Quando il refactoring del codice vecchio (o, piuttosto, delicatamente lobotomizing con una motosega virtuale), ha trovato questo:

Dictionary <Dictionary <string, string>, Dictionary <string, stringa >> projectAttributes = new Dictionary <Dictionary <string, string>, Dictionary <string, string >> ();
...
Dictionary <string, string> newAttributes = ProjectUpdate.GetMappingAttributes (projectObject);
Dictionary <string, string> savedAttributes = ProjectUpdate.SaveMappingAttributes (projectObject);
projectAttributes.Add (newAttributes, savedAttributes);
...
ritorno projectAttributes;
Robert era incuriosito. A Dictionary (la versione NET di un array associativo) di dizionario per vocabolario? O forse ... un dizionario Meta . Aveva, naturalmente, già visto un po 'di codice "interessanti" nel corso della sua carriera, ma questo era nuovo e lui non riusciva a capire quale sia lo scopo di tale costrutto potrebbe essere. Cioè, fino a quando Robert ha trovato il luogo in cui è stato utilizzato.

! Coppie chiave-valore FTW
è scoperto, il predecessore di Robert stavano cercando un tipo di dati tupla, e nel buon ol 'giorni della Microsoft.NET Framework 3.5, non c'era nessuno - almeno non built-in. Così, naturalmente, la possibilità di fare le proprie cose, tuttavia, che possa essere, era spalancata:

Dictionary <Dictionary <string, string>, Dictionary <string, string >> projectAttributes =
  Arguments.Attributes come Dictionary <Dictionary <string, string>, Dictionary <string, string >>;
...
foreach (KeyValuePair <Dictionary <string, string>, Dictionary <string, string >>
  projAttributes in projectAttributes)
{
  newProjAttributes = projAttributes.Key come Dictionary <string, string>;
  savedProjAttributes = projAttributes.Value come Dictionary <string, string>;
}
Robert pensò la logica attraverso per un minuto - che cosa è un 2-tuple diverso da una coppia chiave-valore? E che cosa è un array associativo diverso da una lista di coppie chiave-valore? E che cosa è un singolo valore diverso da una lista con una sola voce? (E che cosa è un ciclo foreach oltre che una voce diversa da chiamare prima?)

Guardando la cosa da questo punto di vista, quasi diventa la cosa più naturale di utilizzare un dizionario con precisione una voce come una 2-tuple. Quasi.

Ancora una volta, tutta questa gioia è possibile solo perché ogni tipo NET implementa GetHashCode. A volte, Robert ancora si chiede se i creatori del NET Framework veramente pensato a quello che le cose che avrebbero aiutato a scatenare sul mondo del codice sorgente.

Nessun commento:

Posta un commento