Refactoring vs tests

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Topicstarter
Al geruime tijd houden wij de TDD methode aan. Omdat alle code intensief wordt getest zouden developers minder bang zijn om veranderingen in code aan te brengen. Echter loop ik nu tegen een ander probleem aan. Sommige developers durven nu minder snelaanpassingen in code te maken. Niet omdat ze bang zijn dat de code niet meer werkt, maar omdat zij dan vaak tientallen tests moeten aanpassen.

Ik verminder liever niet het aantal tests, aangezien deze tests erg belangrijk zijn bij de kwaliteits controle. Echter wil ik ook niet dat programmeurs terughoudend worden met refactoringen. De tweestrijd tussen wel of niet een refactoring doorvoeren heb ik de afgelopen maanden steeds vaker gezien en ik vrees een beetje voor de toekomst.

Hoe gaan andere architects/development managers hiermee om?

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Arzie
  • Registratie: Juni 1999
  • Laatst online: 19-09 12:37
Impliceert dit probleem niet dat de tests eigenlijk niet goed zijn? Zolang je de public methods van een class niet wijzigt bij je refactoring en alleen de interne werking overhoop gooit zou de test moeten blijven werken.

Als de aanroepen van de public methods gerefactord worden zouden de tests automatisch gewijzigd moeten worden door je IDE.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Arzie schreef op donderdag 18 juni 2009 @ 18:44:
Impliceert dit probleem niet dat de tests eigenlijk niet goed zijn? Zolang je de public methods van een class niet wijzigt bij je refactoring en alleen de interne werking overhoop gooit zou de test moeten blijven werken.
Mja ... Niet noodzakelijk. Een refactoring kan er in bepaalde gevallen toch ook tot leiden dat je public interface veranderd. (Al denk ik dat de meeste refactorings idd wel interne wijzingen zullen zijn).
Als de aanroepen van de public methods gerefactord worden zouden de tests automatisch gewijzigd moeten worden door je IDE.
Als je public interface op een simpele manier wijzigt natuurlijk .... Als de hele interface drastisch wijzigt, dan niet ...

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

whoami schreef op donderdag 18 juni 2009 @ 18:55:
[...]
Als je public interface op een simpele manier wijzigt natuurlijk .... Als de hele interface drastisch wijzigt, dan niet ...
Mwah, met moderne IDE's kun je tegenwoordig (eventueel in meerdere stappen) je interface flink omgooien, zonder bang te zijn voor omvallende code.

Zolang alle aanroepende code van jouw interfaces natuurlijk maar in je project zit. Na je eerste release wordt het mogelijk moeilijker, aangezien je dan aan backwards compatibility moet gaan denken.

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

Verwijderd

Niemand_Anders schreef op donderdag 18 juni 2009 @ 14:56:
Hoe gaan andere architects/development managers hiermee om?
Geen ervaring vanuit dat oogpunt, maar puur gebaseerd op eigen ervaring is mijn mening als volgt. Bij TDD maak je eerst een (falende) test van een geïsoleerde eenheid (unit) code waarin je bedenkt hoe je functionaliteit wilt gebruiken. Dit ga je vervolgens quick 'n dirty uitwerken zodat de test slaagt. Tot slot wordt de code netjes gemaakt en wordt er gezorgd dat de test blijft slagen.

Nu is je probleem dat bij refactoriteraties zoveel breaking changes ontstaan dat je tests niet meer werken. Met bovenstaande in het achterhoofd, betekent dat dus dat je bepaalde functionaliteit op een andere manier wilt aanroepen dan je eerst wilde.

Mijn mening is dus dat het logisch is dat je je testen moet aanpassen, als later blijkt dat je functionaliteit anders wilt benaderen. Hoe te voorkomen? Beter nadenken over hoe je functionaliteit wilt benaderen, zodat je je test beter doordacht is en daardoor je functionaliteit ook.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Volgens de definitie van refactoren verandert het externe gedrag niet. ;) Als je veel breekt ben je eerder aan het herstructureren, en dan is het logisch dat je je testset opnieuw mag bepalen, namelijk het externe gedrag dat je voor ogen hebt.

{signature}


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Topicstarter
Arzie schreef op donderdag 18 juni 2009 @ 18:44:
Impliceert dit probleem niet dat de tests eigenlijk niet goed zijn? Zolang je de public methods van een class niet wijzigt bij je refactoring en alleen de interne werking overhoop gooit zou de test moeten blijven werken.

Als de aanroepen van de public methods gerefactord worden zouden de tests automatisch gewijzigd moeten worden door je IDE.
Bij TDD is het erg belangrijk dat je EERST de test schrijft en dan de code. Bij een refactoring dient je dus eerst de test aan te passen (de break) en daarna pas de implementatie (de fix). De IDE mag de API wijzigingen dus niet automatisch doorvoeren in de tests. Om te voorkomen dat VS of ReSharper de tests automatisch wijzigen zitten deze ook in een aparte solution.

De 3 regels van TDD:
1. You are not allowed to write any production code unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.


Deze regels gelden natuurlijk ook bij een refactoring. Maar aan de reacties te begrijpen houden jullie deze 3 regels dus niet aan bij een refactoring?

@voutloos: Herstructureren heb ik voor het gemak onder het kopje refactoring gegooit.

Het probleem is namelijk dat de gehele (financiele) wereld is gek geworden en dat idioten (politici) proberen de gekken weer in het gareel te krijgen. Dit zorgt al maanden voor wijzigende wetgeving en dus dat wij de producten moeten updaten. Om in de toekomst minder snel wijzigingen te hoeven maken als er wetgeving ergens wijzigt zijn wij dus een aantal optimalisaties aan het doorvoeren. Daarbij is ook gebleken dat door deze optimalisatie een aantal bestaande functionaliteiten kunnen worden samengevoegd middels een refactoring. Het grootste deel wijzigt alleen onder de motorkap, maar aan enkele public API changes ontkomen wij niet.

Wat betreft backwards comptabiliteit: Die is bij ons nooit gegarandeerd (alleen bij minor releases), wel doen wij altijd een poging om de bestaande api zoveel mogelijk te behouden bij een major release. Daarnaast updaten banken echt niet naar een volgende versie zonder hun eigen tests te doorlopen. Die test geeft aan dat versie x van hun systeem correct werkt met onze productversie y. Daarnaast documenten wij alle wijzigingen (ook de interne) uitvoerig zodat de ICT afdeling van een bank weet waarop zij speciaal moeten letten. Niet zozeer de API, maar de correcte werking is heilig. Ter indicatie neemt en gemiddelde acceptatie test van een bank zo'n 14 dagen in beslag. Een programmeur die een uurtje bezig is om een paar wijzigingen door te voeren valt dan in het niet.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

@TS

Gebruiken jullie trouwens veel mocking? Mocking is leuk maar ik zie het regelmatig te veel gebruikt worden waarbij de testcode niets anders is dan een herhaling van de code. En dat is echt enorm breekbaar. Ik ben zelf deels afgestapt van unit testen en doe voornamelijk nog aan mini integratie tests. Geeft veel meer zekerheid (vooral bij complexe software).

Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Topicstarter
Nee, wij maken vrijwel niet gebruik van mocking. Wel hebben wij van een aantal interface implementaties een dummy implementatie (alle code is op basis van interface segregation). Ook wij hebben mini integratie testen, naast regression, automatische acceptatie testen. Maar juist door al die testen merk ik dus dat men minder snel de code optimaliseerd.

Van alle issues zie bij ons zijn aangemeld is nog geen 5% code gerelateerd. Het is namelijk altijd de complexiteit van de context waarin het probleem ontstaat. Laat ik als voorbeeld de leeftijd gebruiken. Stel dat in een land wettelijk is vastgelegd dat een krediet aanvragen tussen de 18 en 60 jaar oud moet zijn. De policy van een (internationale) bank kan echter zijn dat zij al leningen verstrekken vanaf 16 jaar. In dat geval moet de software gewoon 18 jaar aanhouden, maar als de bank de minimum leeftijd op 21 jaar zet, moet wel eerst de waarde van de bank worden overgenomen. Maar elke limiet kent vaak ook weer uitzonderingen. In de VS is de minimum leeftijd op 18 jaar gezet, maar als 2 volwassenen financieel garant willen staan, mag het krediet al vanaf 16 jaar worden afgesloten.. Onze software kent meer dan 2000 van deze software limieten en de meeste issues ontstaat juist bij dit soort configuraties.

En configuratie is heel erg lastig te testen. Vooral omdat deze momenteel vrijwel continue wijzigt.

Per 1 juli gaat er internationaal gezien weer een hoop wijzigen en ben ik men van alles en nog wat bezig en vlieg ik momenteel door half Europa. Mijn reacties zullen dus wat onregelmatiger zijn dan normaal.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Macros
  • Registratie: Februari 2000
  • Laatst online: 15-05 16:29

Macros

I'm watching...

Dit is volgens mij juist ideaal om te vatten in een rule based systeem. Daarbij kan je alle regeltjes in zo'n rule engine proppen en die engine bepaalt dat wat wel en niet mag gebaseerd op alle regeltjes. Maar ja, nu zit je al hier aan vast ;)

"Beauty is the ultimate defence against complexity." David Gelernter


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Niemand_Anders schreef op vrijdag 19 juni 2009 @ 15:15:
[...]
Bij TDD is het erg belangrijk dat je EERST de test schrijft en dan de code.
Maar dan toch wel nadat je hebt nagedacht, hoop ik?
Bij een refactoring dient je dus eerst de test aan te passen (de break) en daarna pas de implementatie (de fix). De IDE mag de API wijzigingen dus niet automatisch doorvoeren in de tests. Om te voorkomen dat VS of ReSharper de tests automatisch wijzigen zitten deze ook in een aparte solution.

De 3 regels van TDD:
1. You are not allowed to write any production code unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
Mja, wie zegt dit? Het manifesto?

De regels die je noemt werken alleen wanneer de tests 100% van de mogelijke situaties dekken (dat is wat anders dan 100% code coverage). Dat is nooit het geval en om het te bereiken moet je veelal een onmogelijke hoeveelheid tests maken. Dit houdt dus in dat je tests vervallen tot integration tests of tests die niet alle mogelijke situaties testen. In dat licht is het dan ook niet onlogisch te concluderen dat pure TDD gewoon niet werkt en je niet uit moet gaan van code maar van wat de code feitelijk representeert.

BDD komt dan veel dichter bij wat je feitelijk aan het doen bent. Bij BDD benoem je veel meer wat de code feitelijk moet doen, en de tests representeren dat dan ook. Als je vanuit dat perspectief te werk gaat is het wijzigen van de code ook logischer: je moet eerst de behavior wijzigen, daaruit volgt een of meerdere gewijzigde tests en daaruit volgt wellicht een of meerdere wijzigingen op de code. TDD is dan dus niet handig, want het dwingt je om meteen met je handen in de tests te gaan zitten poeren maar de vraag waarom test A moet worden aangepast maar niet test B is onbeantwoordbaar.
Deze regels gelden natuurlijk ook bij een refactoring. Maar aan de reacties te begrijpen houden jullie deze 3 regels dus niet aan bij een refactoring?
Als je eerst nadenkt over wat voor functionaliteit je feitelijk wilt representeren in code, en dan de projectie maakt naar code, zul je zien dat code nooit de bron is van wat je moet opleveren maar altijd een representatie van die bron. Het gefocus op code is debet aan veel problemen, waaronder ook jouw initiele vraag valt.
@voutloos: Herstructureren heb ik voor het gemak onder het kopje refactoring gegooit.

Het probleem is namelijk dat de gehele (financiele) wereld is gek geworden en dat idioten (politici) proberen de gekken weer in het gareel te krijgen. Dit zorgt al maanden voor wijzigende wetgeving en dus dat wij de producten moeten updaten. Om in de toekomst minder snel wijzigingen te hoeven maken als er wetgeving ergens wijzigt zijn wij dus een aantal optimalisaties aan het doorvoeren. Daarbij is ook gebleken dat door deze optimalisatie een aantal bestaande functionaliteiten kunnen worden samengevoegd middels een refactoring. Het grootste deel wijzigt alleen onder de motorkap, maar aan enkele public API changes ontkomen wij niet.
Oorzaak (wetswijziging) -> wijziging in functionaliteit van applicatie -> projectie naar code -> wijzigingen maken in code -> klaar.

Niet beginnen met wijzigingen maken in code, want dat is wat we vroeger noemden 'ad hoc prutsen'.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1