martedì 5 luglio 2011

Pratico PHP Refactoring: Rimuovi assegnazioni ai parametri

di Giorgio Sironi

Lo scenario di oggi segue dal precedente articolo : si sta riutilizzando la variabile parametro assegnando ad esso un nuovo valore. Questa volta ci concentriamo sul caso dei parametri, e non alla generica violenza contro le variabili locali.

Il refactoring è basata sull'introduzione di nuove variabili temporanee per evitare l'assegnazione di parametri formali : l'assegnazione è fatta solo da PHP durante la chiamata al metodo.

In realtà, è una specie di variabile temporanea spalato, mentre il sovraccarico variabile è un parametro del metodo. Per inciso, il caso che abbiamo visto a Spalato variabile temporanea è anche un esempio di questo odore: non solo è stato riassegnato il parametro, ma è stato riassegnato più volte .

Perché dovrei preoccuparmi?

Come nota Fowler nel Refactoring libro, la riassegnazione è la modifica ci preoccupiamo di evitare, mentre sei libero di modificare lo stato dell'oggetto passato come vi piace (ci sono modelli come visitatore che si basano su parametri di output).

La prima ragione per evitare di incarichi ai parametri è debole oggi, in PHP: il parametro possono essere passati per riferimento e il parametro originale attuale (quello passato dall'esterno) potrebbe subire un effetto collaterale. Ma se un parametro viene passato per riferimento, un effetto collaterale è necessario per farlo funzionare. Comunque, non ho visto un parametro passato per riferimento in PHP funzioni a livello utente in 5 anni, gli unici sono i funzione sort () e le sue variazioni, e preg_match ().

La seconda ragione , più appropriato, è che più compiti creare confusione su quello che contiene il parametro, il docblock dice una sola verità, mentre il valore del parametro cambia nel tempo.

Proprio come oggetti immutabili semplificare il quadro mentre sono passati in giro, i parametri immutabili consentono di fare ipotesi più rispetto allo stato dei parametri: si può intervenire su ogni riga del metodo in località, sapendo che il parametro contiene ancora il valore originale.

Alcuni linguaggi, come Java, anche fornire una definitiva parola chiave per le variabili immutabili e parametri da utilizzare per la dichiarazione (in questo caso nella firma del metodo). Per entrambi Java e PHP, riassegnazioni impedendo potrebbe facilmente essere il default, in quanto questo refactoring è davvero targeting una regola fondamentale.

Passi

Le operazioni di refactoring sono simili a quelli di Spalato variabile temporanea.

  1. Creare una variabile temporanea dopo la riga dove la riassegnazione è.
  2. Assegnare il valore anche per la nuova variabile.
  3. Sostituire tutti i riferimenti dal parametro con la nuova variabile locale.
  4. Eseguire i test e verificare nulla è rotto.
  5. Eliminare l'assegnazione vecchio . Si può anche scoprire che è possibile semplificare parte del codice facendo riferimento al parametro originale di nuovo.

Esempio

Il codice esempio mostra un calcolo distanza tra due meridiani (all'equatore, ovviamente). Ancora una volta in questa serie, è un algoritmo sufficientemente complesso per guadagnare un refactoring, ma semplice da entrare in un unico post.

Si noti che il codice è solo sufficiente a far passare questa prova: si avrà esito negativo con valori negativi o con i meridiani prova capovolto. Ma refactoring può essere praticato anche tra la scrittura un test e l'altro.

La situazione iniziale è priva di variabili locali, e un parametro arbitrario viene riassegnato per ogni calcolo.

01.
02.class RemoveAssignmentsToParametersTest estende PHPUnit_Framework_TestCase
03.{
04.pubblici funzione testCalculatesDistanceBetweenMeridiansOnTheEasternEmisphere ()
05.{
06.$ mondo = nuovo Mondiale ();
. 07$ distanza = $ mondo -> getDistanceBetweenMeridians (15, 80);
08.$ this -> assertEquals (7223, $ distanza );
09.}
10.}
11.
12.classe mondiale
13.{
14./ **
15.* Questi docblock sarà superata dopo aver letto una sola riga nel metodo.
16.int * @ param $ firstMeridian da -180 a 180
17.int * @ param $ secondMeridian da -180 a 180
18.* Ho scritto questo, ma in una settimana ho difficilmente seguire la logica interna.
19.* Mentre nel caso di separazione temporanea variabile $ data è stata ancora una DateTime
20.oggetto *, ecco il significato di $ secondMeridian diventa completamente diverso.
21.* /
22.pubblici funzione getDistanceBetweenMeridians ( $ firstMeridian , $ secondMeridian)
23.{
24.$ secondMeridian -= $ firstMeridian ;
. 25$ secondMeridian *= 60;
. 26$ secondMeridian *= 1,852;
27.restituire l' ( $ secondMeridian );
28.}
29.}

Dopo l'introduzione, possiamo dare un senso a questo codice e consentire l'algoritmo di evolvere. Il prossimo test sarà probabilmente solo modificare il calcolo della distanza $, mentre $ secondMeridian ovunque reso difficile capire dove intervenire.

01.
02.
03.classe mondiale
04.{
05./ **
06.* I nomi delle variabili locali servire come documentazione ora.
07.int * @ param $ firstMeridian da -180 a 180
08.int * @ param $ secondMeridian da -180 a 180
09.* /
10.pubblici funzione getDistanceBetweenMeridians ( $ firstMeridian , $ secondMeridian)
11.{
12.degreesOfDifference $ = $ secondMeridian - $ firstMeridian ;
13.nauticalMiles $ = $ degreesOfDifference * 60;
14.$ distanza = $ nauticalMiles * 1,852;
15.restituire l' ( $ distanza );
16.}

Nessun commento:

Posta un commento