Föreläsning 23. Tobias Wrigstad. Refaktorering

Relevanta dokument
Föreläsning 22. Tobias Wrigstad. Under huven på JVM. Bytekod. JIT. Reflection. Profiling.

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Configuration testing Why? Vad det är tänkt att koden ska göra. Performance testing Kommentarer Skriva om koden som kommentar

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Classes och Interfaces, Objects och References, Initialization

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Tentamen Programmering fortsättningskurs DIT950

Labb 1: Vad, hur, och varför?

Lösningar för tenta 2 DAT043,

Mjukvarudesign. Designprocessen. Teknisk design. Konceptuell design

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Ett problem. Kontrollstrukturer och arrayer. Arrayer. Lösningen. Arrayer och hakparanteser. Exempel int[] results; results = new int[10]; // 0..

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

F5 Enkel Design, Refaktorisering

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

Objektorienterad programmering E. Telefonboken, än en gång. Gränssnitt. Telefonboken med gränssnitt specificerat, del 1.

Principles of subclasses. Objekt-orienterad programmering och design Alex Gerdes, 2018

Föreläsning 2. Täcker material från lektion 1, 2, 3 och 4:

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 2

Överlagring, static, testning, formella metoder och undantag! Förelasning 13!! TDA540 Objektorienterad Programmering!

TDDC30. Kursledning Kursledare: Jonas Lindgren. Labassistent: Jonas Lindgren Labassistent: Niklas Holma Labassistent: Erik Nilsson

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 3

Föreläsning 2, vecka 8: Repetition

Kapitel 6. Hakparenteser fšr att ange index MŒnga všrden av samma typ

Outline. Objektorienterad Programmering (TDDC77) En frukt har ett namn. Man kan lägga en frukt i en korg... Hashing. Undantag. Ahmed Rezine.

Objekt-orienterad programmering och design. DIT953 Niklas Broberg, 2018

Objektorienterad Programmering (TDDC77)

Föreläsning 6: Metoder och fält (arrays)

Föreläsnings 9 - Exceptions, I/O

Klassdeklaration. Metoddeklaration. Parameteröverföring

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Objekt-orienterad Programmering och Design. TDA551 Alex Gerdes, HT-2016

Föreläsning 8: Exempel och problemlösning

Föreläsning 3. Stack

Chapter 4: Writing Classes/ Att skriva egna klasser.

Obligatorisk uppgift 5

Principles of subclasses Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Testning av program. Verklig modell för programutveckling

Tentamen, EDAA10 Programmering i Java

JUnit 4 - användning. Grunderna. org.junit. org.junit.test. Henrik Bergström DSV SU/KTH. Innehåller bland annat:

Att skriva till och läsa från terminalfönstret

Institutionen för datavetenskap HT /2008. Testning med JUnit

Modeller, Objekt och Klasser

Vad handlar kursen om? Algoritmer och datastrukturer. Vad handlar kursen om? Vad handlar kursen om?

Objekt-orienterad Programmering och Design. TDA552 Alex Gerdes, HT-2018

F5 Enkel Design, Refaktorisering. EDAF45 Programvaruutveckling i grupp Projekt Görel Hedin, Boris Magnusson,Datavetenskap, LTH

Föreläsning 3. Stack

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Tentamen i Programmering

Arrayer. results

TDDE10 TDDE11, 725G90/1. Objektorienterad programmering i Java, Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Objektorienterad Programkonstruktion. Föreläsning jan 2016

Föreläsning 15: Repetition DVGA02

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 14

DELPROV 1 I DATAVETENSKAP

public boolean containskey(string key) { return search(key, head)!= null; }

Exempel. Arrayer. Lösningen. Ett problem. Arrayer och hakparanteser. Arrayer

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

TENTAMEN OOP

Lösningsförslag. Programmeringsmetodik, KV: Java och OOP. 17 januari 2004

SI-pass 4. Johan Brook och Jesper Persson. 25 september Diskutera och svara på om påståendena nedan är äkta sanningar eller listiga lögner.

Rekursion. Att tänka rekursivt Att programmera rekursivt i Java Exempel. Programmeringsmetodik -Java 254

Objekt, klasser. Tillstånd Signatur Kommunikation Typ. Fält, parametrar och lokala variabler. Konstruktorer Metoder DAVA15

Föreläsning 3. Iteration while-satsen

Svaret kan ges i Javakod (eller i UML-klassdiagram). public class A { B minb;... } public class B { <B:s många variabler och metoder> } Lösning:

Mutability och State. Objekt-orienterad programmering och design (DIT953) Niklas Broberg / Johannes Åman Pohjola, 2018

Övning vecka 6. public void method2() { //code block C method3(); //code block D }//method2

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Objektorienterad programmering. Fält som funktionsresultat. Mer om fält: att uppdatera ett parameterfält. Kontrast: Parametrar av primitiv typ

Parsing med Recursive Descent, Avbildningsklasser. Syntaxdiagram. Syntaxdiagram och kodning expression. Betrakta följande uttryck

Vad kännetecknar en god klass. Vad kännetecknar en god klass. F12 Nested & Inner Classes

TENTAMEN OOP

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

Idag. Exempel, version 2. Exempel, version 3. Ett lite större exempel

Föreläsning 3: Booleans, if, switch

Föreläsning 3-4 Innehåll

Tentamen Programmeringsteknik II Skrivtid: Hjälpmedel: Java-bok (vilken som helst) Skriv läsligt! Använd inte rödpenna!

Tentamen, EDA501/EDAA20 Programmering M MD W BK L

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Föreläsning 1 Datastrukturer (DAT037)

List.java. List.java. Printed by Tom Smedsaas

Grundläggande programmering DVG A08 & ISG A04. Allmän information. Å vem är jag då. Karlstads Universitet, Johan Öfverberg 1

Generisk klass med typparameter Inre klass - ListIterator

JAVAUTVECKLING LEKTION 4

Testdriven utveckling. Teorin bakom testdriven utveckling. Bakgrund. Januari 2009, KTH. Alexander Tarnowski

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Typkonvertering. Java versus C

TDDE10 TDDE11, 725G90. Objektorienterad programmering i Java, Föreläsning 3 Erik Nilsson, Institutionen för Datavetenskap, LiU

LUNDS TEKNISKA HÖGSKOLA EDAA01 Programmeringsteknik fördjupningskurs Institutionen för datavetenskap HT 2015

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 1 Jonas Lindgren, Institutionen för Datavetenskap, LiU

TDDD78 Viktiga begrepp, del 2

Subtyping, co- och contra-variance. Objekt-orienterad programmering och design Alex Gerdes, 2016

Transkript:

Föreläsning 23 Tobias Wrigstad Refaktorering

Traditionell syn på systemutveckling Analys & Design Implementation Testning (V&V) Den s.k. vattenfallsmodellen Diskreta steg som bildar en pipeline varje steg ger indata till nästa steg som utdata

Modern syn på systemutveckling Implementation Analys & Design Testning (V&V) Utveckling är en iterativ process i regel lönlöst/suboptimalt att försöka förstå problemet innan man börjar implementera Använd istället implementationen för att driva fram förståelse Kontinuerlig validering & verifiering underlättas t.ex. genom att alltid ha ett körande system

Naiv syn på implementation Specifikation Design Implementation Samma problem som vattenfallsmodellen omöjligt att beakta allt jämt Korrekthet är endast en av många kvalitetsattribut (t.ex. underhållsbar, läsbar, ) Tidspress och dylikt medför ibland att programmerare skriver undermålig kod Kod produceras i en kollektiv process leder ibland till t.ex. dupliceringar (jmf. NIH) Behövs processteg för att gradvis förfina och ställa tillrätta refactoring

Implementationscykeln Specifikation Design Refaktorering Implementation Nytt steg refaktorering Förändringar i koden i sy!e att göra koden bättre utan att påverka vad den gör, eller systemets prestanda Ändra kodens struktur

Refactoring Sy!et med refaktorering är att göra kod och design Mer underhållsbart Lättare att förstå Lättare att ändra Enklare att utöka med ny funktionalitet Termen populariserades av Martin Fowler, se boken Refactoring (AW, 1997) Fowler lyckas fånga många refaktoreringsprocesser i namngivna mönster Traditionellt inte alltid tillåtet på alla arbetsplatser ( if it ain t broke, don t fix it )

Exempel: kodduplicering Via https://solidsourceit.wordpress.com/2012/08/03/does-source-code-duplication-matter/

Exempel: underhåll Det är i regel enklare att underhålla kod som du själv har skrivit Enklare att förstå, följer dina normala tankebanor Mindre respekt för koden Lejonparten av all systemutveckling är underhåll av existerande system Dvs. underhåll av kod som du inte skrivit själv ERGO: Alla bör bemöda sig om att skriva kod som är så enkel som möjligt att förstå

Bad smells och ruttnande kod Kod tenderar att ruttna över tid Många modifieringar under tidspress, med olika mentala modeller, etc. Vi säger att ruttnande kod luktar illa bad smells Som utvecklare är det vårt mål att identifiera kod som luktar illa och städa up den Vad avger dålig lukt? En igenkänningsbar indikator på att något i koden kan vara fel All kod kan ruttna även testkod (alltså inte bara produktionskod)

Typiska dåliga lukter Magiska konstanter Upprepningar Långa metoder Komplicerade villkorssatser Switchsatser Stora klasser Divergerande förändringar Shotgun-surgery Kodkommentarer

Typiska dåliga lukter Magiska konstanter Upprepningar Långa metoder Komplicerade villkorssatser Intra-klass-lukt Switchsatser Stora klasser Divergerande förändringar Shotgun-surgery Inter-klass-lukt Kodkommentarer

Upprepningar public class TUnit { public static void main(string[] args) throws Exception { for (String classname : args) { Class c = Class.forName(className); Object o = c.newinstance(); Method setup = null; Method teardown = null; if (m.getname().equals("setup")) { setup = m; break; if (m.getname().equals("teardown")) { teardown = m; break; if (m.getname().startswith("test") && m.getparametercount() == 0) { if (setup!= null) setup.invoke(o); m.invoke(o); if (teardown!= null) teardown.invoke(o);

Upprepningar public class TUnit { public static void main(string[] args) throws Exception { for (String classname : args) { Class c = Class.forName(className); Object o = c.newinstance(); Method setup = null; Method teardown = null; if (m.getname().equals("setup")) { setup = m; break; if (m.getname().equals("teardown")) { teardown = m; break; if (m.getname().startswith("test") && m.getparametercount() == 0) { if (setup!= null) setup.invoke(o); m.invoke(o); if (teardown!= null) teardown.invoke(o);

Magiska konstanter import java.lang.reflect.*; public class TUnit { public static void main(string[] args) throws Exception { if (args.length < 1) { System.out.println("Usage: java TUnit TestClass1... "); return; for (String classname : args) { Class c = Class.forName(className); Object o = c.newinstance(); Method setup = null; Method teardown = null; if (m.getname().equals("setup")) setup = m; if (m.getname().equals("teardown")) teardown = m; if (setup!= null && teardown!= null) break; if (m.getname().startswith("test") && m.getparametercount() == 0) { if (setup!= null) setup.invoke(o); m.invoke(o); if (teardown!= null) teardown.invoke(o);

Magiska konstanter import java.lang.reflect.*; public class TUnit { public static void main(string[] args) throws Exception { if (args.length < 1) { System.out.println("Usage: java TUnit TestClass1... "); return; for (String classname : args) { Class c = Class.forName(className); Object o = c.newinstance(); Method setup = null; Method teardown = null; if (m.getname().equals("setup")) setup = m; if (m.getname().equals("teardown")) teardown = m; if (setup!= null && teardown!= null) break; if (m.getname().startswith("test") && m.getparametercount() == 0) { if (setup!= null) setup.invoke(o); m.invoke(o); if (teardown!= null) teardown.invoke(o);

Långa metoder public class TUnit { public static void main(string[] args) throws Exception { if (args.length < 1) { System.out.println("Usage: java TUnit TestClass1... "); return; for (String classname : args) { Class c = Class.forName(className); Object o = c.newinstance(); Method setup = null; Method teardown = null; if (m.getname().equals("setup")) setup = m; if (m.getname().equals("teardown")) teardown = m; if (setup!= null && teardown!= null) break; if (m.getname().startswith("test") && m.getparametercount() == 0) { if (setup!= null) setup.invoke(o); m.invoke(o); if (teardown!= null) teardown.invoke(o);

När är en metod för lång egentligen? Nästlade kontrollstrukturer med djup större än 2 Tar många parametrar som radikalt ändrar hur metoden skall bete sig När dess logik är duplicerad i andra metoder Onödigt brus, t.ex. kommentarer som är uppenbara, bekvämlighetsmetoder som inte används, etc. Den ryms inte på en skärmsida När den som läser inte får en omedelbar och intuitiv förståelse för vad den gör

Refaktorerat program [partiell] public class TUnit { public static final String SETUP = setup ; public static final String TEAR_DOWN = teardown ; public static final String TEST_METHOD_PREFIX = test ; public static void main(string[] args) throws Exception { for (String classname : args) { Class c = loadclass(classname); runtestsuite(c); Upprepningar Långa metoder Magiska konstanter public Method findmethod(class c, String name) {... public Method findtestmethods(class c) {... public void runtest(method s, Method td, Method test) {... public static void runtestsuite(class c) { Method setup = findmethod(c, SETUP); Method teardown = findmethod(c, TEAR_DOWN); Method[] testmethods = findtestmethods(c); for (Method m : testmethods) runtest(setup, teardown, m);

Refaktoreringsmönster En refaktorering är en kodtransformation som utförs manuellt eller med verktygsstöd kod kod Skall tillämpas kontinuerligt, inte med en månads mellanrum En fungerande uppsättning tester är av stor vikt för att minska riskerna vid komplex refaktorering

Refaktoreringsprocessen 1. Se till att alla tester passerar (alla?) 2. Identifiera vad som luktar illa 3. Gör en plan för hur koden skall refaktoreras 4. Genomför planen 5. Kör alla tester för at se till att inga förändringar/buggar/etc. smög in 6. Gå till 1.

Refaktoreringsmönster [refactoring.com/catalogue] Add parameter Change bidirectional association to unidirectional Change reference to value Change unidirectional association to bidirectional Change Value to Reference Collapse Hierarchy Consolidate Conditional Expression Consolidate Duplicate Conditional Fragments Convert Procedural Design to Objects Decompose Conditional Duplicate Observed Data Encapsulate Collection Encapsulate Downcast Encapsulate Field Extract Class Extract Hierarchy Extract Interface Extract Method Extract Subclass Extract Superclass Hide Delegate Hide Method Inline Class Inline Method Rename Constant

Extract Method Method setup = null; if (m.getname().equals("setup")) {... Method teardown = null; if (m.getname().equals("teardown")) {... Method setup = findsetupmethod(c.getmethods()); Method teardown = null; if (m.getname().equals("teardown")) {...

Extract Method Method setup = null; if (m.getname().equals("setup")) {... Method teardown = null; if (m.getname().equals("teardown")) {... Method setup = findsetupmethod(c.getmethods()); Method teardown = null; if (m.getname().equals("teardown")) {... Method s = findsetupmethod(c.getmethods()); Method teardown = null; if (m.getname().equals("td")) {... Method s = findsetupmethod(c.getmethods()); Method td = findtdmethod(c.getmethods());

Så drar vi nytta av den bättre strukturen Method setup = null; if (m.getname().equals("setup")) {... Method teardown = null; if (m.getname().equals("teardown")) {... Method setup = findsetupmethod(c.getmethods()); Method teardown = null; if (m.getname().equals("teardown")) {... Method s = findsetupmethod(c.getmethods()); Method teardown = null; if (m.getname().equals("td")) {... Method s = findsetupmethod(c.getmethods()); Method td = findtdmethod(c.getmethods()); Method s = findsetupmethod(c.getmethods()); Method td = findtdmethod(c.getmethods()); Method s = findmethod(c.getmethods(), SETUP); Method td = findmethod(c.getmethods(), TD);

Pull Up Field Inlägg postare : Användare skapat : TimeStamp editerat : TimeStamp metadata : Metadata[] Inlägg postare : Användare skapat : TimeStamp editerat : TimeStamp metadata : Metadata[] text : String Statusuppdatering text : String komm. : Kommentar[] Kommentar text : String Statusuppdatering komm. : Kommentar[] Kommentar Denna typ av kod kan uppstå t.ex. för att olika programmerare har arbetat parallellt, eller för att någon skillnad mellan Statusuppdatering och Kommentarer tidigare har funnits men som inte längre gäller, etc.

Change unidirectional association to bidirectional Assignment Assignment parent left right left right parent SymbolicExpr Variable SymbolicExpr Variable Ursprungligen behövdes enbart ena riktningen, nu behövs båda Går att räkna ut, men om programmet o!a behöver båda riktningarna kan det vara en bra idé att göra relationen explicit Lösning i inlupp 3: lägg till SymbolicExpression parent; i rotklassen

Change unidirectional association to bidirectional Assignment Assignment parent left right left right Welcome to the symbolic calculator!? 2 * (3 + x) NRCheck: Not Reducible SymbolicExpr Variable Variable 'x' was used SymbolicExpr before instantiated! in 3.0 + x Ursprungligen behövdes enbart ena in riktningen, 2.0 * (3.0 nu + behövs x) båda parent Variable Går att räkna ut, men om programmet o!a behöver båda riktningarna kan det vara en bra idé att göra relationen explicit Lösning i inlupp 3: lägg till SymbolicExpression parent; i rotklassen

Single Responsibility Principle [Robert C. Martin] Varje modul (klass) har ansvar för en del av programmets funktion Ansvaret är inkapslat i modulen (klassen) Det skall bara finnas en anledning till att en klass ändras I inlämningsuppgi! 3 visitor pattern Bryta ut evalueringsfunktionen från AST-trädet Ersätt med generell princip för att besöka ett träd Tillåter oss att bygga flera olika visitors för ett träd (eval, check, etc.)

Rule of Three Första gången vi skall göra något bara gör det Andra gången vi skall göra nästan samma sak kopiera det Tredje gången vi skall göra nästan samma sak dags att refaktorera

Avslutning, refaktorering Att refaktorera är nödvändigt för att ett program inte skall ruttna ihop och behöva skrivas om från grunden Flera av er har upplevt detta under kursen den hårda vägen Refaktorering kan hjälpa, men kanske för mycket att göra för er just nu SIMPLE-metoden uppmuntrar till kontinuerlig (trivial) refaktorering nu vill jag uppmuntra er till att göra mer komplicerad refaktorering för högre vinster Inlupp 4 startar med testning för att sedan göra refaktorering och sedan utökningar! Titta på refactoring.com/catalogue för att läsa om olika mönster Man kan lära sig en del om programmering genom att göra det