Refactorizare spaghete

Buna.

Am o functie de aproximativ 2500 linii de cod care as vrea sa o refactorizez. Din pacate, functia asta e destul de importanta, din cauza ca ea genereaza head-ul (si o parte din body) a mai multor site-uri, deci importanta pastrarii includerilor fisierelor in aceeasi ordine, e vitala.

Ce tehnici imi recomandati astfel incat sa lucrez cat mai sigur, ca sa nu stric site-uri intregi?

Multumesc.

Wow. 2500 linii.

Cred ca cel mai important e sa asiguri pastrarea functionalitatii.

Astfel, as recomanda inceperea scrierii de teste care verifica functionalitatea curenta pe mai multe cazuri. Poti lua site cu site si scrie cate un test pentru fiecare. “Pentru parametri de intrare X, Y, Z iese W” (inteleg ca se face output la HTML). Desi pare un consum mare de timp, avantajul este ca, orice linie de cod vei schimba, poti rula din nou toate testele si te asiguri ca trec. Adica pastrezi exact functionalitatea de acuma. Verificarea aceasta in mod automat prin rularea de teste te va feri de multe, deci e smart sa investesti in a le scrie. Poti incerca Behat, e usor de facut setup.

Apoi, avand asigurate verificarile, ai putea sa spargi functionalitati independente in alte functii (sau metode ale unor clase pe care le creezi) si pe care le poti testa separat daca vrei sa mergi pe varianta TDD. Toata jmecheria este sa refactorizezi putin cate putin din aceasta functie mamut. Uite cum prezinta nenea Martin Fowler refactoring workflows. Daca iti place, poti citi mai multe lucruri scrise de el pe aceasta tema.

4 Likes

Inteleg. Multumesc mult!

Crezi ca ar fi bine sa folosesc PHPUnit sau Codeception?

Sincer sa fiu, nu am facut testing pana acuma. Pentru cazul asta, cred ca ar fi potrivit ca sa incep. De asta, nu stiu exact ce s-ar potrivi mai bine, si cu ce sa incep.

Îți recomand să faci un hash la output înainte de refactor și să compari cu hash-ul de după refactor.

Astfel poți fi sigur că nu strici nimic.

3 Likes

Hash-ul e bun doar de verificare, dar daca scrie exact ce ar trebui sa fie la output vede si unde sunt erorile, uneori poate sa fie si un spatiu, iar cu hash-ul nu prea te prinzi.

1 Like

Am mai vazut tehnica asta cu hash, si mi se pare destul de potrivita pentru cazul asta. Cel putin acopera destul de mult.

Corect, doar că refactor înseamnă refacerea codului fără a altera rezultatul. Nu?

Exact. Asta si vreau.

1 Like

Hai sa ne gandim putin si la limita de timp: in cate zile vrei sa termini acest refactor?

Cred ca poti folosi direct PHPUnit si pentru testarea functionala, eu asa am facut prima mea testare mai acoperitoare, si inca e in productie acel codebase. Cred ca daca citesti cu mare atentie manualul PHPUnit o sa vezi Pe sitepoint este un tutorial cum se face pt subcazul Symfony2 ca sa vezi cum arata level 2.

Practic tu trebuie sa scrii un test f asemanator cu cel de mai jos. Am denumit monolith() functia ta si am presupus ca are 3 parametri. Am folosit trickul cu dataProvider pentru a simplifica lucrurile.

class Monolith_Test extends PHPUnit_Framework_TestCase {
    /**
     * @dataProvider currentSitesProvider
     */
    public function testMonolith($param1, $param2, $param3, $expected) {
        $computed = monolith($param1, $param2, $param3);

        $this->assertEquals($expected, $computed, sprintf('Err... am obtinut %s in loc de %s', $computed, $expected));
    }

    public function currentSitesProvider() {
        return array(
            array('param 1 pt site 1', 'param 2 pt site 1', 'param 3 pt site 1', 'big HTML for site 1'),
            // daca $param2 este null pt site 2, atunci apelul va arata asa:
            array('param 1 pt site 2', null, 'param 3 pt site 2', 'big HTML for site 2')
        );
    }
}

Eu recomand totusi separarea totala: PHPUnit separat, BDD separat. De aceea parca ti-as sugera sa nu te arunci direct in codeception.

2 Likes

Inca nu mi-am pus un target, ca sa stiu in cate zile as vrea sa termin. Momentan adun informatii, ca sa stiu cu ce am de-a face.

In principiu am inteles explicatia ta, si o sa folosesc PHPUnit.

Multumesc mult :smile:

Poor bastard… :frowning:

2 Likes

Cum de nimeni nu a mentionat singura cea mai importanta carte despre legacy code? Working Effectively with Legacy Code

Povesteam cu Michael Feathers la o conferinta recent, si l-am intrebat cum de ajunge el la asa de multe conferinte, ca peste tot el este prezent. Raspunsul lui era simplu. In afara de el nimeni nu a scris o carte intr-adevar practica pentru refactorizare de code legacy, iar cod legacy este si va fi mereu.

5 Likes

Că tot ai adus vorba de cărți: Modernizing Legacy Applications mi se pare o carte mai light despre modalități de refactor, dar care vine cu informații utile și concrete pentru PHP.

1 Like

Multumesc, Patkos.

Cu siguranta ma voi uita peste ea si o voi analiza, pentru ca am incredere ca ai dreptate.

M-au ajutat mult si tutorialele tale de pe Tuts+, asa ca iti multumesc si pentru acelea :smile:

1 Like

Imi place ca e light si sunt sigur ca merita citita, mai ales pentru proiectul la care lucrez acuma. Pare sa fie exact ce imi trebuie :smile:

Multumesc!