<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-556852436618020611</id><updated>2011-11-27T15:32:10.782-08:00</updated><title type='text'>renprogrammering</title><subtitle type='html'>Vad är bra kod? Vilka regler bör man följa? Jag började att läsa boken Clean code och började skriva om mina tankar runt den boken. Men det är historia och nu skriver jag vidare...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-8197506535105398733</id><published>2011-10-08T02:38:00.000-07:00</published><updated>2011-10-08T03:10:15.998-07:00</updated><title type='text'>Olika typer av xUnit-tester</title><content type='html'>Jag fick ett ett uppdrag av jobbet för någon dag sedan och har funderat lite på det och tänkte att jag skulle skriva ner lite tankar runt detta så att jag kanske kan komma ihåg det. Det vi ska försöka att åstadkomma är ett gemensamt tänk runt automatiska tester på xUnit-formen.&lt;br /&gt;&lt;br /&gt;Som de flesta som har läst lite om tester automation vet är det mycket billigare att rätta ett fel direkt än om man väntar en dag, eller en månad. Tar det tid innan man rättar felet har man hunnit glömma mycket om vad det var man skulle lösa och hur man resonerade när man skulle lösa det. Koden som blir kvar blir ett dokument på hur det är löst men säger inte så mycket om varför du valde den ena av två lösningar. Det skulle bli hela romaner i kommentarerna om man skulle få med de typen av information.&lt;br /&gt;&lt;br /&gt;Hur drabbar detta dina tester. Jo, det ger att du vill ha snabba tester som du kan se till att de körs i samband med kompilering. Det är då du vet vad du har gjort och vad det är du har ändrat. Det finns en regel som säger att du bör kunna köra åtminstone tusen tester på en sekund för att de ska räknas som snabba. Det innebär i de allra flesta fall att dina tester inte har tid att vänta på en sql-fråga eller webbservice-anrop.&lt;br /&gt;&lt;br /&gt;Men ibland vill man trots allt testa sina integrationer och även få en "hela vägen" känsla för att det fungerar. De snabba testerna kommer att per definition bara testa små fragment av din applikation. Många små tester kan testa hela applikationen men om du inte börjar med en strikt tdd-approch kommer det målet vara väldigt svårt att uppnå och många gånger även väldigt dyrt. Det kan alltså vara idé att ha en uppsättning med tester som där det är tillåtet att testerna får ta tid. Dessa skulle förslagsvis köras på natten i en bygg-server.&lt;br /&gt;&lt;br /&gt;Vi har alltså behov av två testbibliotek för våra xUnit-tester. Snabba och långsamma. Jag kan dock se behov av ett tredje bibilotek med tester och det är integrationstester. Med integration i detta fall menar jag den integration som inte kan fungera likadant i utvecklar, byggmiljö som i produktionsmiljö. Saker som skulle kunna separera ett test från de andra är att ett anrop måste göras över en vpn-tunnel och att detta inte går att lösa i de långsamma testerna. Alltså att ett manuellt arbete måste utföras vilket man inte kan kräva att det görs varje natt.&lt;br /&gt;&lt;br /&gt;Så för att summera. Jag kommer att rekomendera att vi från nästa beslutspunkt har två obligatoriska xUnit-projekt i våra lösningar och i dessa organiserar våra tester. Detta för att kunna fånga så många fel som möjligt i tidigast möjliga skede utan att för den skull offra möjligheten till att ha långsamma "täcker allt" tester där de kan vara lämpliga.  Om man önskar kan man naturligtvis ha flera av varje testtyp men det är testprestanda som bestämmer i första hand.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-8197506535105398733?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/8197506535105398733/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/10/olika-typer-av-xunit-tester.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8197506535105398733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8197506535105398733'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/10/olika-typer-av-xunit-tester.html' title='Olika typer av xUnit-tester'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-245679405979123993</id><published>2011-05-12T08:31:00.000-07:00</published><updated>2011-05-13T13:38:35.117-07:00</updated><title type='text'>Seven languages in seven weeks - Erlang</title><content type='html'>Det femte språket i boken Seven Languages in Seven weeks av Bruce Tate är Erlang. Ett språk som togs fram av Ericsson då inga andra var bra nog. Erlang har ett par designmål som skiljer det från andra språk. Det hanterar väldigt många saker parallellt. Språket är tar även ett annat grepp på felhantering som kort och gott går ut på att det är helt ok att en process dör ibland.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Erlang - dag 1&lt;/span&gt;&lt;br /&gt;Erlang har fått en del inspiration från Prolog. Faktum är att man började med att modifiera Prolog för att få det resultat man önskade. Så mycket av syntaxen är relativt lik. Man har tuples, atoms. Men inga objekt.&lt;br /&gt;&lt;br /&gt;Erlang är trots att det är ett högnivå-språk lämpligt att köra hårdvarunära då det finns stöd för att manipulera bits och bytes. Erlang dessutom ruskigt stora tal naturligt. Så många siffror du får plats med i minnet.&lt;br /&gt;&lt;br /&gt;Precis som med Prolog använder man rekursiva strukturer för att lösa problem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Erlang - dag 2&lt;/span&gt;&lt;br /&gt;För en Java-utvecklare är annonyma funktioner inget nytt. Även om det skiljer en del mellan den objektorienterade approchen och den i Erlang. Dock blir det lite mer spännande i Erlang som som är dynamiskt typat. Funktionen du får kan ju vara vilken funktion som helst.&lt;br /&gt;&lt;br /&gt;En styrka med annonyma funktioner är att du precis som i Ruby kan skriva en funktion som du kör på varje element i en lista och du kan enkelt återanvända dina funktioner på vilken lista som helst.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Erlang - dag 3&lt;/span&gt;&lt;br /&gt;Dag tre går igenom de parallella verktyg som Erlang har. Principen är väldigt enkel och bygger på koncepten om Actors och Messages som vi sett tidigare. Det finns några inbyggda sätt att skapa processer och att skicka meddelanden till den kö som varje process är utrustad med. Sedan kommer processen att beta av kön ett meddelande i taget.  Det är höggradigt asynkrona meddelanden som skickas så vill man åstadkomma synkrona meddelanden får man ta till lite trick, men i princip får man vänta på att man får ett asynkront meddelande tillbaka. I princip kanske man kan säga att alla applikationer man bygger i princip blir som en liten svärm med webservrar som löser var sin uppgift.&lt;br /&gt;&lt;br /&gt;Felhantering i Erlang går i mångt och mycket ut på att låta saker dö. Tricket är att inte hantera något tillstånd. Alla funktionsanrop bär med sig all information den behöver och nästa anrop kommer, förutsatt att samma information skickas in,  ge samma resultat. Poängen med detta är att det lättare att döda en process och starta den igen om något blivit sjukt än att försöka att hantera fel. Den nya processen kommer att ge samma resultat som den gamla så det är ingen som kommer att bry sig kort och gott.&lt;br /&gt;&lt;br /&gt;Jag är lite besviken på kapitlet om Erlang. Jag känner att jag saknar kopplingen till verkligheten. Kapitlet kändes akademiskt. Jag förstår att tillstånd är något som är dåligt om man vill hantera många saker samtidigt men samtidigt så har de flesta applikationer jag träffat på små beroenden på vad klockan är, eller hur många som är inloggade. Var tar all denna information vägen i en Erlangapplikation?&lt;br /&gt;&lt;br /&gt;Jag har en teori om den här boken. Den är inte till för att ge en översikt på ett antal språk så att man ska kunna jämföra dem och kanske välja ut ett för att lära sig "på riktigt". Bokens syfte är att lära ut funktionell programmering, men genom att sockra med Ruby som objektorienterat språk och Io som är likt javascript så märker man inte hur man sakta lär sig funktionsbaserat tänkande.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-245679405979123993?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/245679405979123993/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/05/seven-languages-in-seven-weeks-erlang.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/245679405979123993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/245679405979123993'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/05/seven-languages-in-seven-weeks-erlang.html' title='Seven languages in seven weeks - Erlang'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-2520045631827351389</id><published>2011-05-06T13:31:00.000-07:00</published><updated>2011-05-08T12:45:21.992-07:00</updated><title type='text'>Seven languages in seven weeks - Scala</title><content type='html'>Dags för språk nummer fyra ur boken Seven languages in seven weeks. Nu  blir det Scala. Ett språk som många ser som språket som kommer att Java  som huvudspråk till JVM. En av fördelarna med Scala är att det är  kompatibelt med Java. Har du 10 år av kod med dig från Java så behöver  du inte börja med att skriva om den utan du kan återanvända dina  favoritfunktioner från Scala.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scala - dag 1&lt;/span&gt;&lt;br /&gt;Första  dagen med Scala var rätt trist, lite syntax varav det mesta känns igen  från de flesta c-derivat. Så det var inte mycket som kändes nytt. Det  som var lite intressant var att man valt att ha mixins eller moduler  (ruby resp io) och för att förvirra lite kallar dem för traits. Jag  hoppas på en roligare dag två :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt; Scala - dag 2&lt;/span&gt;&lt;br /&gt;Idag har vi  gått igenom Scalas nyckelord var och val. Skillnaden mellan dessa är om  variabeln som deklareras är mutable (kan förändras) eller inmutable (kan  inte förändras). Genom att ha stora delar av sin kod inmutable kan man  utradera mycket av de problem som objektorienterade språk har med  parallell körning, tex över flera processorer.&lt;br /&gt;&lt;br /&gt;En stor del av  kapitlet ägnas åt Scalas collections. Dessa är i mångt och mycket också  uppbygda runt inmutable objects. Tex om du lägger till ett objekt i en  lista får du tillbaka en helt ny lista i stället för att behöva oroa dig  för om din lista har förändrats på oväntat sätt. Jag uppfattar det som  kanske något ineffektivt men förstår att vinsten kommer när man börjar arbeta med parallell bearbetning.&lt;br /&gt;&lt;br /&gt;Scalas collections kan användas i vanliga for-loopar men tanken är att  man ska använda dem funktionellt. Alltså finns det sätt att skicka in en  funktion som ska köras på alla objekt tex på din lista.&lt;br /&gt;&lt;br /&gt;Scala - dag 3&lt;br /&gt;Under dag 3 visades den inbyggda xml-hanteringen där xml kan definieras som vilken variabel som helst.&lt;br /&gt;&lt;br /&gt;Patternmatching är en funktion som lite kan jämföras med de logiska vilkoren i prolog.&lt;br /&gt;&lt;br /&gt;Parallellism i Scala liknar till viss del den i Io då den använder actors och meddelanden.&lt;br /&gt;&lt;br /&gt;Lite sammanfattning om Scala.&lt;br /&gt;Jag uppfattar Scala som en utveckling av Java där man kunnat släppa kravet på bakåtkompabilitet som finns. Så att byta ut trådbaserad parallellsim mot actors. Införa inmutable objects och functionalism m.m. Trots allt detta nya så kan man ändå återanvända sina gamla javabibliotek. Det är ganska trevligt tycker jag.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-2520045631827351389?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/2520045631827351389/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/05/seven-languages-in-seven-weeks-scala.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2520045631827351389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2520045631827351389'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/05/seven-languages-in-seven-weeks-scala.html' title='Seven languages in seven weeks - Scala'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4432652165771437909</id><published>2011-04-30T14:46:00.000-07:00</published><updated>2011-05-04T13:34:55.075-07:00</updated><title type='text'>Seven languages in seven weeks - Prolog</title><content type='html'>Det tredje språket i boken Seven languages in seven weeks är Prolog och det är det första språk i boken som jag faktskt provat då det var en av programmeringskurserna på högskolan. Då tyckte jag prolog var ganska roligt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Prolog - dag 1&lt;/span&gt;&lt;br /&gt;Prolog är baserat på fakta och regler. Det som skiljer prolog från de tidigare språken i boken är att du inte talar om för Prolog hur dessa fakta och regler ska behandlas. Det fixar Prolog själv. Det enda du behöver göra efter ha matat Prolog med fakta och regler är att ställa frågor och Prolog svarar. För ett antal applikationer ger detta fantastiskt små och överskådliga program.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Prolog - dag 2&lt;/span&gt;&lt;br /&gt;Dag 2 handlade mest om rekursiva anrop och listor. Att med hjälp av en rekursiv logisk regel summera ihop värdena i en array ställer begreppen lite på huvudet. Jag förstår vad som händer men jag känner att jag har en lång resa innan jag skulle komma på själv att jag skulle behandla en array på det sättet. Det ser synnerligen inneffektivt ut med alla rekursiva anrop men man har tydligen lyckats att optimera för det.&lt;br /&gt;&lt;br /&gt;Prolog - dag 3&lt;br /&gt;Prolog har några styrkor och en av de mest uppenbara visades med ett exempel av hur kort ett program blir som löser soduko. 25-30 rader med logiska regler, sedan är det bara att köra. Det är så att jag kommer på mig att undra om det inte finns prolog-motorer för java eller .net som man skulle kunna använda på de problem som man kan beskriva med logiska regler. För på rätt problem hinner du inte starta kompilatorn i Visual Studio innan Prolog har levererat en färdig applikation.&lt;br /&gt;&lt;br /&gt;Allt är inte lätt och smidigt i Prolog men jag kan definitivt se att det finns många problem där man skulle ha mycket att vinna på att hitta en prolog-inspirerad väg till lösningen. Att inte beskriva lösningen utan att beskriva problemet är ibland mycket enklare helt enkelt.&lt;br /&gt;&lt;br /&gt;Tyvärr är Prolog gammalt och inte speciellt utvecklat för att köras över flera trådar, flera processer etc etc. Det gör att jag känner att det här kapitlet mest har varit en teoretisk övning. En mycket intressant tankeexperiment men jag kommer nog inte att ta den vidare till någon mer användbar nivå.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4432652165771437909?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4432652165771437909/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks-prolog.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4432652165771437909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4432652165771437909'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks-prolog.html' title='Seven languages in seven weeks - Prolog'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5371558210686173717</id><published>2011-04-21T12:11:00.000-07:00</published><updated>2011-04-30T14:46:12.336-07:00</updated><title type='text'>Seven languages in seven weeks - Io</title><content type='html'>Då var det dags för språk nummer två. Jag tror väl inte att jag klarar att hålla ett språk i veckan nu jag har det första språket som facit. Det andra språket heter Io, ett namn som gör det svårt att söka på. Io Language ger lite bättre träffar men det är ett illa valt namn.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Io - dag 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Io är inte ett objektorienterat språk som Ruby, Java eller C# även om det finns objekt. Io är likt Javascript protoyp-baserat. I sak handlar det om att man i stället för att skriva klasser som man har som fabrik för att skapa objekt så kopierar man existerande objekt och använder dessa som mall.&lt;br /&gt;&lt;br /&gt;Precis som med första dagen för Ruby så har vi gått igenom lite syntax. Precis som med Ruby så använder Io få paranteser och något som gör Io lite mer annorlunda syntaxmässigt är att man inte heller håller ihop objekt och egenskap med punkt. Det gör det lite svårt att läsa Io-kod för mig då jag inte riktigt lyckas lista ut om det är objekt, metod eller egenskap som jag tittar på. Något som osökt leder mig in på nästa egenskap för Io.&lt;br /&gt;&lt;br /&gt;Allt är objekt. Man gör kort och gott inte skillnad på om det är en metod eller egenskap som du arbetar på. Kanske något förenklat man kan säga när du begär att få ett värde från en egenskap så körs det en liten metod som returnerar den egenskapen och om en metoden är en rad eller hundra som i sin tur anropar hundra andra spelar ingen roll.&lt;br /&gt;&lt;br /&gt;Vad mer att säga från första dagen med Io. Jo, syntaxen är väldigt avskalad. Syntaxsocker existerar inte eller kommer i väldigt små mängder.&lt;br /&gt;&lt;br /&gt;Dags för dag två.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Io - dag 2&lt;/span&gt;&lt;br /&gt;Dag två handlade mycket om att använda de slots och även att ge en insikt i att allt som sker i Io är en form av meddelanden.&lt;br /&gt;&lt;br /&gt;En av konsekvenserna av att Io är uppbyggt som det är ger att du kan modifiera väldigt mycket, tex är alla operatorer som ==, &amp;lt; etc metoder, något speciella metoder men i princip som vilken annan metod som helst.&lt;br /&gt;&lt;br /&gt;Meddelanden tog mig en stund att förstå, jag läste sidorna både tre och fyra gånger innan jag lyckades förstå vad det var som hände. Känns ganska självklart nu så jag kanske hade en dålig dag :-). Kort och gott är i princip alla anrop i Io ett meddelande och meddelanden har en avsändare, mottagare, namn och argument. Att ha kunskapen om vem som anropar, och vad som anropades och med vilka parametrar kan ge en del spännande lösningar.&lt;br /&gt;&lt;br /&gt;Io - dag 3&lt;br /&gt;Dag 3 börjar med en diskussion om domänspecifika språk. En av uppgifterna i slutet av dagen gick ut på att man skulle ta en text-fil och mer eller mindre behanda innehållet i text-filen som kod. Samtidigt som jag blir imponerad över möjligheterna blir jag också lite rädd över om någon kommer att förstå vad som händer.&lt;br /&gt;&lt;br /&gt;Io har precis som Ruby en method-missing metod och den erbjuder mer eller mindre samma möjligheter som i Ruby&lt;br /&gt;&lt;br /&gt;Io har funktioner för Concurrency där jag bitvis förstår storheten men för vissa saker går den mig helt förbi. Där jag inte förstår är varför cooperativ multitasking är bra. Anledningen till att den inte är bra att utvecklaren måste komma ihåg att lägga in anrop som släpper kontrollen på lämpliga ställen. Preemtive multitasking befriar oss från den uppgiften och vi slipper bekymra oss om att vår applikation kommer att göra systemet oresponsivt. Men Io har en kooperativ modell. Syftet är kort och gott att om inte en "tråd" inte kan avbrytas när som helst så blir systemen förutsägbara då din process inte kan avbrytas hur som helst. Jag kan förstå men det känns som ett steg tillbaka.&lt;br /&gt;&lt;br /&gt;En annan sak som har jag lite lättare att ta till mig är att man har en Actor-baserad modell för trådarna. I princip innebär det att varje tråd äger sitt eget data. Jämför man med C# eller Java så delar alla trådar i en process på samma minne och kan därmed också ställa till problem för varandra på oväntade sätt.&lt;br /&gt;&lt;br /&gt;Efter har testat lite med Io känner jag att jag förstår Javascript bättre. Men jag kan inte säga att jag på något sätt känner mig hugad att använda språket. Den avskalade syntaxen som gör det enkelt att göra domänspecifika språk skulle kunna vara intressant men jag känner inte att jag kan komma på något projekt där Io styrkor skulle få mig att välja bort "standard"-språken.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5371558210686173717?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5371558210686173717/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks-io.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5371558210686173717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5371558210686173717'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks-io.html' title='Seven languages in seven weeks - Io'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-538523490404042250</id><published>2011-04-09T09:30:00.000-07:00</published><updated>2011-04-16T13:16:59.165-07:00</updated><title type='text'>Seven languages in seven weeks - Ruby</title><content type='html'>Jag har börjat läsa Bruce Tates bok, 7 languages in 7 weeks och tänke skriva lite "dagbok" om upplevelsen.&lt;br /&gt;&lt;br /&gt;Sju språk är ett ganska mastigt projekt att ge sig på men boken aspirerar inte på att göra dig till mästare på något sätt utan snarare att ge en översikt de olika språkens styrkor och svagheter så att man kan utvärdera vilket språk som lämpar sig för vilken uppgift.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruby - dag 1&lt;/span&gt;&lt;br /&gt;Första går igen lite av den grundläggande syntaxen. Installation av Ruby var smidig och med språkreferensen på nätet så löste jag till och med extrauppgiften utan någon större utmaning. Jag hoppas att det blir lite svårare framåt, även om självförtroendet mådde bra av första dagen. Som java/C# programmerare kände jag igen mig väldigt mycket och det var bara avsaknaden av parenteser som kändes lite konstig.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruby - dag 2&lt;/span&gt;&lt;br /&gt;Den andra dagen gav en betydligt större utmaning än dag ett och jag får erkänna att jag har fuskat med övningsuppgifterna. Jag får gå tillbaka och göra ett nytt försök på dem lite senare när begreppen har trillat ner lite bättre.&lt;br /&gt;&lt;br /&gt;Dagen började lite stilla med syntax för funktioner, arrayer och hashmaps. Att hashmaps är implementerade direkt i syntax kändes lite konstigt men när jag tänker efter så är det inte ofta som jag använt något annat än standardvarianten i vare sig Java eller C# och då kanske man lika gärna kan stöjda dem direkt i syntax.&lt;br /&gt;&lt;br /&gt;Code blocks är ett av de begrepp jag ännu inte lyckats ta till mig helt och hållet. Det kanske i viss mån kan liknas vid delegater i C#. Kort och gott kan du definiera ett block med kod som argument till en metod. Nyckelordet yield agerar som en platshållare för blocket. Lite som att skriva en Template Method.&lt;br /&gt;&lt;br /&gt;Mixin kan liknas vid Visitor-pattern. Man implementerar en mixin genom att skriva en module. Denna modul kan sedan inkluderas i vilken klass som helst, i princip. Två vanliga mixins är enumerable och comparable som man använda i sina klasser för att iterera och jämföra.&lt;br /&gt;&lt;br /&gt;Nu är jag lite lätt skräckslagen inför dag 3. :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruby - Dag 3&lt;/span&gt;&lt;br /&gt;Dag tre börjar vi titta var det är som Ruby speciellt och inte bara en annan syntax. I Rubys fall är det speciella metaprogrammering. Alltså att kunna skriva kod som bygger annan kod.&lt;br /&gt;&lt;br /&gt;Öppna klasser är något som går emot mycket av det jag lärt mig tidigare där open-closed-priciple har varit en grundsten. Att en klass i Ruby är öppen innebär att du när som helst kan definiera om hur en klass fungera. Det är bara att definiera om metoden till att göra det du vill att den ska göra just nu. Men som Bruce skriver i boken. Har du bett om en vass kniv kan du skära dig rejält. I C# är det nog närmast method extensions som till viss del utför samma funktionallitet, fast mycket mer begränsat.&lt;br /&gt;&lt;br /&gt;En annan vanlig metaprogrammerings metod är att använda en "systemmetod" som heter method_missing. Denna metod skulle jag jämföra med en 404 i html och precis som med en 404 där du kan ha en handler som utför någon operation så kan du välja att implementera vad som ska hända när någon försöker att anropa en metod som inte finns. Detta verkar vara användbart när man har scenarion där man i java eller c# hade använt en parameter för att hantera att det finns för många varianter för att det ska gå att hantera med metoder. Kraftfullt i en del situationer kan jag tänka mig.&lt;br /&gt;&lt;br /&gt;Det tredje begreppet är modul och jag är inte riktigt säker på vad som skiljer det från en mixin från dag två. Konceptet är att lägga till funktionalitet till sin klass.&lt;br /&gt;&lt;br /&gt;Övningen upplevde jag som enklare än för dag 2 av någon anledning. Men nu får det gå någon dag innan jag ger mig på nästa språk, Io.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-538523490404042250?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/538523490404042250/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/538523490404042250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/538523490404042250'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/seven-languages-in-seven-weeks.html' title='Seven languages in seven weeks - Ruby'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-9099243763967879226</id><published>2011-04-06T11:56:00.000-07:00</published><updated>2011-04-12T13:01:29.035-07:00</updated><title type='text'>SDC2011</title><content type='html'>Jag var på Swedish Developer Conference 2011 tidigare i veckan och tänkte försöka att skriva ihop en liten sammanfattning av vad jag såg. För att vi skulle få med så många som möjligt på jobbet var vi bara där på måndagen om det var på tisdagen allt roligt hände missade jag det.&lt;br /&gt;&lt;br /&gt;Det första som är värt att nämnas är att konferensen har vuxit en del sedan jag var där för två år sedan. Både antalet besökare, spår och dagar hade ökat. Kanske i viss mån på bekostnad av kvalitet tyvärr. Man förväntar sig trots allt ett visst mått av show. Men SDC kanske fungerar lite som plantskola för blivant stjärnor.&lt;br /&gt;&lt;br /&gt;Som en generell notering så verkar samtliga föreläsare som jag såg förespråka &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; i en form eller annan.&lt;br /&gt;&lt;br /&gt;Första passet:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Alistair Cockburn - On Beyond Agile: The New Face Of Software Engineering&lt;/span&gt;&lt;br /&gt;Alistar höll i årets keynote och pratade om mjukvaruutvecklings framtid utifrån 5 delar. Tyvärr kände jag att han höll sig lite över mitt huvud så jag hade svårt att ta till mig det han sa. Det blev lite för inriktat på ledning och jag tappade intresset.  Det som fastnade var runt de olika typer av spel som han menar att vi är med i. Där projektet är ett spel med tydligt slut. Jämför med tex att leda ett företag där spelet närmast går ut på att befinna sig i spelet, utan något annat mål än att befinna sig i spelet. Beroende på vilket spel man spelar så kan det ge olika resultat, tex om man spelar spelet för att befinna sig i det kanske man inte är så intresserad av att komma till avslut.&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;br /&gt;Niel Ford - Functional Thinking&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tyvärr var jag tvungen att hjälpa kollegor som inte hade förmånen under denna session så jag kände att jag missade lite men några noteringar fick jag med.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Till skillnad från objektorienterade språk försöker man i möjligaste mån att undvika att hantera tillstånd.&lt;/li&gt;&lt;li&gt;Man vill ha rena funktioner som inte har bieffekter. Om du kör funktionen på din lokala dator eller i ett kluster över 1000 processorer ska inte spela roll. Funktionen skall oavsett omständigheter ge samma resultat utifrån varje givet input.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Resultatet i stället för stegen för att åstadkomma resultatet.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;En intressant anekdot som Niel berättade var att Google hade bett 100 forskarstudenter att ta fram en lösning som skulle fungera effektivt över 100 cpu:er. De misslyckades. Lösningen på problemet blev senare &lt;a href="http://en.wikipedia.org/wiki/MapReduce"&gt;MapReduce&lt;/a&gt; som bygger på funktionella begrepp.&lt;br /&gt;&lt;br /&gt;Niel hävdade också att tendensen inom programspråksutveckling går mot att implementera funktionella begrepp snarare än att vidareutveckla objektorientering.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mini coding dojo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Detta var den session som jag valde utifrån personligt intresse. En kata, närmare bestämmt FizzBuzz. Tydligen är det en lek som man kan få göra på mattelektionerna i skolan på mellanstadiet. Man räknar 1, 2, 3, 4, 5 etc. Om det talet man ska säga är delbart med 3 så säger man inte 3 utan Fizz, om ett tal är delbart med 5 säger man Buzz, och om talet är delbart både med 3 och 5 så säger man FizzBuzz. Detta som ett exempel på hur man kan leka leken.&lt;br /&gt;&lt;br /&gt;Det vi gjorde var att implementera en klass som fungerade som fusk för den stackars elev som är nervös för att säga fel och därmed få klasskamraternas hån.&lt;br /&gt;&lt;br /&gt;Reglerna för katan var att det var en person som programmerarade, med en person som stöd och alla andra tittade på. Vi hade en timer som stod på 7 minuter. När klocka pep så fick den som programmerade gå och sätta sig, bisittaren fick börja programmera och en ur "publiken" fick sätta sig som bisittare. Det sättet att lösa katan skiljde sig en del från de kator jag varit med som mer har varit av typen gruppövning där alla löst samma uppgift och först efteråt jämfört lösningarna. Men det var TDD som gällde. "Publiken" fick kommentera lösningen när testerna lyste grönt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ivar Nilsen och Anders Karlsen - Pair programming and TDD in practice&lt;/span&gt;&lt;br /&gt;Detta var dagens flopp för min del. För även om det var intresssant att se hur de arbetade sig fram till en lösning genom att använda TDD och parprogrammering så kände jag att jag behövde få någon form av teori för varför de gjorde som de gjorde. Kanske hänvisa till någon studie som kunde säga när man ska och när man inte ska osv. Det blev lite tradigt med 40 minuter där de står och kodar med lite enstaka kommentarer till varandra.&lt;br /&gt;&lt;br /&gt;Jag frågade efteråt hur lång tid de hade trott att de 40 minuterna kodning hade tagit om de hade gjort den ensamma och för första gången och de uppskattade det till 6-8 timmar. Tillsammans trodde de att de hade löst det på 2-3 timmar. Något jag hade lite svårt att tro. Att koden blir bättre och har färre buggar kan jag kanske köpa in på som argument för parprogrammering men att den initiala lösningstiden skulle vara hälften låter som fantasier i mina öron.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Gojko Adzic - Winning big with specification by example&lt;/span&gt;&lt;br /&gt;Om den förra sessionen var lågvattenmärket så var Gojko dagens höjdpunkt. Han berättade om vilka mönster han kunde utläsa efter att ha studera 50 framgångsrika agila projekt. Många av de slutsatser han kom fram till föll mig i smaken med "test som specifikation" och "frekventa tester".&lt;br /&gt;&lt;br /&gt;En sak som jag inte tänkt så mycket på är att vi ofta slänger oss med olika uttryck på saker som är relativt lika. A-TTD och BDD tex är relativt lika och har i mångt och mycket samma mål, även om metoden är lite olika. Gojko beskrev det som det största problemet med att dra slutsatser från de 50 projekten, att se vad de faktiskt gör bakom termerna.&lt;br /&gt;&lt;br /&gt;Kort och gott kommer jag att köpa hans bok när den kommer ut. Det var 50 minuter som skapade en hel del nyfikenhet hos mig.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Thomas Lundström - Railsify your web development&lt;/span&gt;Thomas gav ett stelt och nervöst intryck. Att han hade en titel som förmodligen skrämde borde de flesta som skulle kunna vara intresserade gjorde att det var ganska tomt i lokalen. "Vad MS borde ha lärt från Ruby" kanske hade varit en bättre titel. Det var i alla fall vad det handlade om.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;BDD i kulturen. Tex har de flesta projekt körbara specifikationer. Kommer delvis från att Ruby är en dynamiskt språk så den (falska?) säkerheten som kompilatorn ger behöver säkras upp med tester i högre grad och det är något som finns i kulturen menade Thomas på.&lt;/li&gt;&lt;li&gt;TDD - Även här förmodligen för att Ruby är dynamiskt. Men jag har inte sett ett exempel från MS där loggning, tester etc är en naturlig del av exemplen.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;MVC behöver kanske inte presenteras så mycket men "code behind" har en tendens att bli rätt mycket soppa i.&lt;/li&gt;&lt;li&gt;Colloborative database development, varje utvecklare har en privat databas så man kan mecka runt utan att störa andra utvecklare. Har verktyg för att "merga" databaser. För .Net skulle man tex kunna använda Migrator.Net för att komma ifrån den gemensamma databasen.&lt;/li&gt;&lt;li&gt;App-Private Database. Detta koncept gör att varje Ruby-app har sin egen databas och man undviker att jobba mot samma databas. Om en applikation behöver tillgång till en annan applikations databas får man bygga webservices. Idén är att göra små moduler som kan förändras oberoende av varandra. Behöver man ändra i databasen så är det bara den egna applikationen som berörs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;RESTful -&lt;/li&gt;&lt;li&gt;DevOps - beskrevs som att ta in driftavdelningen i projekten på samma sätt som man i agila team tagit in testare som en del av teamet.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Convention over Configuration - Varför ska default-alternativ konfigureras. Syftet är att ta bort alla val som man "måste" göra för att kunna få igång applikationen. Måste man inte göra dem gör man inte fel förrän man faktiskt behöver göra något och då har man en hanterbar konfiguration att förhålla sig till.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;DRY - Don't repeat yourself....&lt;/li&gt;&lt;li&gt;Scaling out - Dela inget data, inga sessioner gör att det inte spelar någon roll om applikationen körs på 1 eller 100 datorer.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;OSS - var främst riktat till .Net-utvecklarna. Don't be afraid.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Reference management - även denna till .Nettare. NuGet eller OpenWrap för att hantera olika versioner av dll:er som behövs i applikationer.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h1&gt;&lt;span style="font-size:100%;"&gt;Staffan Nöteberg - Regex&lt;/span&gt;&lt;/h1&gt;Staffan gick igenom grunden i RegEx och visade skillnaderna mellan NonDeterministiska och Deterministiska Finita Automata och vilka konsekvenser. Han visade också de tre kommandon som finns i RegEx och förklarade dessa så att de gick att förstå och vilka typer av applikationer där RegEx är lämpliga att användas.&lt;br /&gt;&lt;br /&gt;Dock förstörde han min vilja att faktiskt lära mig genom att säga att varje plattform har sin implementation av RegEx och bristen på standard är synnerligen besvärlig. Man måste i princip lära sig hur varje RegEx-kompilator fungerar och vilka vägval som de tar för att kunna förutse vilka resultat man kommer att få ut.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Till sist&lt;/span&gt;&lt;br /&gt;Dagen avslutades med att jag fick ett sms, jag hade vunnit. Vunnit ganska stort också tycker jag. En gratis utbildning på ProgramUtvikling i Norge. Tyvärr verkar det som att de två utbildningarna som jag är mest intresserad av inte har några planerade datum så vi får se vad jag hittar på. Att lära sig TDD och A-TDD med Bob Martin himself hade varit ganska stort tycker jag... men så bra verkar det inte bli. Men jag är glad ändå!&lt;br /&gt;&lt;br /&gt;Så på det stora hela var jag nöjd med dagen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-9099243763967879226?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/9099243763967879226/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/sdc2011.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/9099243763967879226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/9099243763967879226'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2011/04/sdc2011.html' title='SDC2011'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4202248001276170026</id><published>2010-06-05T11:47:00.000-07:00</published><updated>2010-06-05T13:09:53.934-07:00</updated><title type='text'>Exempel på dålig kod</title><content type='html'>Det var ett tag sedan jag skrev och nu några dagar innan Jönköping Developer Dojo har sin stora träff med Dag König från Microsoft kanske jag ska plocka upp bollen igen.&lt;br /&gt;&lt;br /&gt;Den här gången tänkte jag ge några exempel på dålig kod. Exemplen ligger publikt på internet och går säkert att leta upp om man vet hur man ska använda en sökmotor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exempel 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: arial; font-size: 12px; border: 1px dashed rgb(204, 204, 204); width: 99%; height: auto; overflow: auto; background: url(&amp;quot;http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif&amp;quot;) repeat scroll 0% 0% rgb(240, 240, 240); padding: 0px; color: rgb(0, 0, 0); text-align: left; line-height: 20px;"&gt;&lt;code style="color: rgb(0, 0, 0); word-wrap: normal;"&gt; if ((campaignTypeInfoCarrier.Key != CampaignVoucherSpecialPrice.EXCEED_AMOUNT) &amp;amp;&amp;amp;&lt;br /&gt;  (campaignTypeInfoCarrier.Key != CampaignVoucherSpecialPrice.AMOUNT_DISCOUNT) &amp;amp;&amp;amp;&lt;br /&gt;  (campaignTypeInfoCarrier.Key != CampaignVoucherSpecialPrice.PERCENTAGE_DISCOUNT) &amp;amp;&amp;amp;&lt;br /&gt;  (campaignTypeInfoCarrier.Key != CampaignVoucherSpecialPrice.NO_OF_VOUCHER_CODES) &amp;amp;&amp;amp;&lt;br /&gt;  (campaignTypeInfoCarrier.Key != CampaignVoucherSpecialPrice.PRICE_LIST_NAME) &amp;amp;&amp;amp;&lt;br /&gt;  (campaignTypeInfoCarrier.Key != BaseCampaign.CURRENCY_CODE))&lt;br /&gt;     {&lt;br /&gt;         campaignTypeInfoCarrier.CarrierState.IsMarkedForDeleting = true;&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Så vad är fel med den kodsnutten? Jo, den är ju riktigt osmidig att läsa vad den syftar på. Bättre hade varit att bryta ut vilkoret i if-satsen i en metod som kanske skulle kunna heta isCampainTypeReadyForDeletion.  Då behöver jag inte lusläsa koden för att förstå vad som ska hända. Som en generell rekomendation skulle jag säga att man mycket noga ska välja de tillfällen som man har &amp;amp;&amp;amp; eller || i en if-sats. Det gör livet mycket svårare för läsaren.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exempel 2&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: arial; font-size: 12px; border: 1px dashed rgb(204, 204, 204); width: 99%; height: auto; overflow: auto; background: url(&amp;quot;http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif&amp;quot;) repeat scroll 0% 0% rgb(240, 240, 240); padding: 0px; color: rgb(0, 0, 0); text-align: left; line-height: 20px;"&gt;&lt;code style="color: rgb(0, 0, 0); word-wrap: normal;"&gt; foreach (CampaignTypeInfoCarrier campaignTypeInfo in campaign.CampaignTypeInfos)&lt;br /&gt;{&lt;br /&gt; if (campaignTypeInfo.Key == CampaignVoucherSpecialPrice.EXCEED_AMOUNT)&lt;br /&gt; {&lt;br /&gt;     c_textBoxExceedAmount.Text = campaignTypeInfo.Value;&lt;br /&gt; }&lt;br /&gt; else if (campaignTypeInfo.Key == CampaignVoucherSpecialPrice.AMOUNT_DISCOUNT)&lt;br /&gt; {&lt;br /&gt;     c_textBoxAmountDiscount.Text = campaignTypeInfo.Value;&lt;br /&gt;     c_textBoxAmountDiscount.Enabled = true;&lt;br /&gt;     c_radioButtonAmountDiscount.Checked = true;&lt;br /&gt;     c_requiredFieldValidatorAmountDiscount.Enabled = true;&lt;br /&gt;     c_textBoxPercentageDiscount.Text = string.Empty;&lt;br /&gt;     c_textBoxPercentageDiscount.Enabled = false;&lt;br /&gt;     c_radioButtonPercentageDiscount.Checked = false;&lt;br /&gt;     c_requiredFieldValidatorPercentageDiscount.Enabled = false;&lt;br /&gt; }&lt;br /&gt; else if (campaignTypeInfo.Key == CampaignVoucherSpecialPrice.PERCENTAGE_DISCOUNT)&lt;br /&gt; {&lt;br /&gt;     c_textBoxPercentageDiscount.Text = campaignTypeInfo.Value;&lt;br /&gt;     c_textBoxPercentageDiscount.Enabled = true;&lt;br /&gt;     c_radioButtonPercentageDiscount.Checked = true;&lt;br /&gt;     c_requiredFieldValidatorPercentageDiscount.Enabled = true;&lt;br /&gt;     c_textBoxAmountDiscount.Text = string.Empty;&lt;br /&gt;     c_textBoxAmountDiscount.Enabled = false;&lt;br /&gt;     c_radioButtonAmountDiscount.Checked = false;&lt;br /&gt;     c_requiredFieldValidatorAmountDiscount.Enabled = false;&lt;br /&gt; }&lt;br /&gt; else if (campaignTypeInfo.Key == CampaignVoucherSpecialPrice.NO_OF_VOUCHER_CODES)&lt;br /&gt; {&lt;br /&gt;     c_textBoxVoucherCode.Text = campaignTypeInfo.Value;&lt;br /&gt; }&lt;br /&gt; else if (campaignTypeInfo.Key == CampaignVoucherSpecialPrice.PRICE_LIST_NAME)&lt;br /&gt; {&lt;br /&gt;   c_textBoxPriceListName.Text = campaignTypeInfo.Value;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Så vad är fel här då? Här är det de långa if-satsen som är problemet. Här kollar man ett och samma data flera gånger och utifrån vad som står agerar man på olika sätt. Bättre hade varit om man hade haft en klass för varje fall och anropat en metod i den klassen som hade gjort rätt jobb enbart utifrån det data som klassen själv äger. Slutresultatet skulle kanske kunna se ut så här:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: arial; font-size: 12px; border: 1px dashed rgb(204, 204, 204); width: 99%; height: auto; overflow: auto; background: url(&amp;quot;http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif&amp;quot;) repeat scroll 0% 0% rgb(240, 240, 240); padding: 0px; color: rgb(0, 0, 0); text-align: left; line-height: 20px;"&gt;&lt;code style="color: rgb(0, 0, 0); word-wrap: normal;"&gt; foreach (CampaignTypeInfoCarrier campaignTypeInfo in campaign.CampaignTypeInfos) { &lt;br /&gt;     campaignTypeInfo.setParameters(this); &lt;br /&gt;} &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Naturligtvis har man gjort en del jobb för att nå det här resultatet men jag skulle nog säga att det är väl spenderad tid.&lt;br /&gt;&lt;br /&gt;Det var allt för denna gång.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4202248001276170026?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4202248001276170026/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2010/06/exempel-pa-dalig-kod.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4202248001276170026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4202248001276170026'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2010/06/exempel-pa-dalig-kod.html' title='Exempel på dålig kod'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-8524930172366531481</id><published>2010-03-03T23:14:00.000-08:00</published><updated>2010-03-03T23:17:05.111-08:00</updated><title type='text'>Första träff med Jönköping Developer Dojo</title><content type='html'>Då var det bestämt. Jönköping Developer Dojo ska ha sin första träff torsdagen den 18:e mars.&lt;br /&gt;&lt;br /&gt;Jönköping Developer Dojo är tänkt att bli en träffpunkt för programmerare i Jönköping med omnejd där vi ska kunna lära av varandra, utbyta erfarenheter och kanske till och med ha lite kul samtidigt.&lt;br /&gt;&lt;br /&gt;Om du vill vara med så registrerar du dig på LinkedIn (om du inte redan har ett konto) och söker sedan upp gruppen "Jönköping Developer Dojo" och går med i den.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-8524930172366531481?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/8524930172366531481/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2010/03/forsta-traff-med-jonkoping-developer.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8524930172366531481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8524930172366531481'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2010/03/forsta-traff-med-jonkoping-developer.html' title='Första träff med Jönköping Developer Dojo'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5669959514546382996</id><published>2009-12-18T13:05:00.000-08:00</published><updated>2009-12-18T13:18:16.939-08:00</updated><title type='text'>Jönköping Developer Dojo</title><content type='html'>&lt;div&gt;&lt;p&gt;Jag skrev sist om att ta ansvar för sin egen kompetens och jag avslutade med att beställa en bok för att läsa på kvällarna. De som känner mig vet att jag har läst jobbrelaterade böcker hemma länge så det är inget revolutionerande att jag lägger lite av min fritid för att hålla mig ajour. Nu har jag dock tagit nästa steg, eller försök till nästa steg i alla fall lite beroende på vad jag får för respons. &lt;/p&gt;&lt;p&gt;Mitt nästa steg i att ta ansvar för min egen kompetens är att försöka bygga ett nätverk av andra programmerare. Detta i syfte att förhoppningsvis få lära av dem och kanske eventuellt få dela med mig av mina erfarenheter. Men hur ska nu detta gå till? &lt;/p&gt;&lt;p&gt;Jag började med att se om jag kunde hitta något på google och sedan på linkedin men jag var helt utan framgång. Detta leder till att jag får försöka att starta något på egen hand. Så sagt och gjort. Jag har skapat upp en sida med hjälp av Google Sites och en grupp på linked in, och så skriver jag det här. Det jag försöker att komma till är jag nu finns det en användargrupp i Jönköping, eller i alla fall ett embryo av något som kan bli en användargrupp. Jag har valt att kalla den Jönköping Developer Dojo.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Jönköping Developer Dojo hoppas jag kan bli en mötesplats för programmare som bor eller jobbar i Jönköping.  Än så länge är planerna för hur gruppen ska träffas och vad vi ska göra när vi träffas ganska flytande men det är inget som vi behöver spika på en gång. &lt;/p&gt;&lt;p&gt;Tycker du att det låter intressant, gå med i gruppen Jönköping Developer Dojo på &lt;a target="_blank" href="http://www.linkedin.com/"&gt;linkedin&lt;/a&gt; eller skriv en kommentar om att du är intresserad av att vara med.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5669959514546382996?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5669959514546382996/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/jonkoping-developer-dojo.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5669959514546382996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5669959514546382996'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/jonkoping-developer-dojo.html' title='Jönköping Developer Dojo'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4848310011285037578</id><published>2009-12-10T11:45:00.000-08:00</published><updated>2009-12-10T12:48:22.684-08:00</updated><title type='text'>Ta ansvar för din kompetens!</title><content type='html'>&lt;div&gt;&lt;p&gt;Företaget du jobbar för vill inte betala för att du ska utbilda dig. De förstår inte att du förlorar kompetens jämfört med omvärlden varje dag som du inte förkovrar dig och lär dig något nytt. Din arbetsplats är dömd att dö en långsam död för att de inte hänger med i utvecklingen och du kommer att vara värdelös på arbetsmarknaden när företaget kursar. Känner du igen dig i resonemanget?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ett företag som inte förstår att du som programmerare behöver kontinuerlig vidareutbildning är inte det bästa företag man kan tänka sig. Dina chanser att vara attraktiv på arbetsmarknaden hänger mycket ihop med de arbetsuppgifter du har haft. Det är inte många företag som anställer cobolprogrammerare längre och det dröjer inte länge innan den teknik du jobbar på är lika antik som cobol. Men företaget du jobbar på kanske inte planerar att göra sig av med sitt "cobolsystem" de närmaste åren och tycker att det vore bortkastade pengar att du ska lära dig något som är av lite modernare snitt. Ska du då skylla på företaget att du inte har fått någon utbildning? Du kan ju det du behöver kunna för att kunna utföra dina uppgifter och även om du tycker att det skulle vara bra med en kurs iLinq eller Wicket så tycker ju uppenbarligen inte dina chefer det.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Så nu har du några val. Du kan söka jobb och med lite tur får du tag dina drömmars arbetsgivare som ger dig det du behöver och lagom mycket utmaningar för att du ska utvecklas som både personligt och i din yrkesroll. Eller så resignerar du och ger upp väntar på bättre tider. Den tredje varianten är att du börjar ta tag i din utbildning själv, för egna pengar och på egen tid. Du slutar skylla på omgivningen och tar gör det du behöver för att upprätthålla och förbättra din kompetens. I stället för att vänta på att någon annan ska bestämma vad du ska kunna så väljer du dig det som du själv tror på.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Att betala för en utbildning är ganska dyrt så det kanske man inte kommer att betala själv. Men att lägga ett par hundra på en bok som man kan ha på nattduksbordet och läsa ett kapitel innan man somnar på kvällen, det är ingen större ansträngning. Om man bor i större städer finns det användargrupper som träffas lite då och då för diverse olika tekniker.  Med andra ord behöver det inte bli dyrt. Det som blir den stora uppoffringen är att gå upp ett par timmar i veckan i arbetstid. Det tycker jag att det kan vara värt men det är ett val som är upp till var och en naturligtvis. Men gör det till ett val ochifrågasätt valet ett par gånger om året.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Nu med detta skrivet ska jag beställa en &lt;a target="_blank" href="http://www.adlibris.com/se/product.aspx?isbn=0131177052"&gt;bok&lt;/a&gt;, utan att bry mig om jobbet kommer att betala den. Jag kommer att läsa den för att jag tror på att det boken tar upp är viktigt. Inte för att någon annan säger till mig att jag måste göra det. Det är mitt val. Nu kanske man ska ta och se om orten jag bor i är stor nog för att se om det finns fler som resonerar som jag och kanske träffas någon gång i månaden för att prata programmering.&lt;span class="__wave_paste" __wave_annotations="2593,2596,link%2Fmanual,http%3A%2F%2Fwww.adlibris.com%2Fse%2Fproduct.aspx%3Fisbn%3D0131177052:" __wave_xml=""&gt;&lt;line&gt;&lt;/line&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4848310011285037578?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4848310011285037578/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/ta-ansvar-for-din-kompetens.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4848310011285037578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4848310011285037578'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/ta-ansvar-for-din-kompetens.html' title='Ta ansvar för din kompetens!'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-3265285495586435640</id><published>2009-12-08T12:39:00.000-08:00</published><updated>2009-12-08T21:56:32.196-08:00</updated><title type='text'>Patterns of Enterprise Application Architecture</title><content type='html'>&lt;p&gt;Martin Fowler är en i programeringskretar ganska känd person. Framför allt när det kommer till de mera agila grenarna systemutvecklingsprocessen. Boken jag har läst har dock ganska lite med XP, TDD eller parprogrammering att göra. Det är en bok där vi får ta del av Martins erfarenheter i form av olika patterns han har tagit till sig. Många hade jag hört talas om sedan tidigare och några är nya. &lt;/p&gt;&lt;p&gt;En bok av den här typen är inte helt lämpligt att försöka att sträckläsa utan man skummar igenom den för att kunna slå upp i vid senare tillfälle. För värdet som en bok av den här typen har är inte i första hand de idéer som samlats ihop utan att de som har läst boken får en gemensamt ordförråd. Precis som när man läst Design Patterns (GoF) och lärt sig vad en Facade eller en Abstract Factory är så får man i Martins bok fler ord för att beskriva mer eller mindre vanligt förekommande mönster man stöter på i livet som programmerare.&lt;/p&gt;&lt;p&gt;Boken är uppdelad i två större delar. Den första beskrivs de många val man har vid utvecklingen av en större applikation. Denna del är uppdelad i de olika delar applikationen består av. Web, sessioner, domänobjekt, databasaccess. De strategier som Martin ger är i denna del inte beskrivna på ett djuplodande sätt utan övergripande och hur de olika mönstrena hänger ihop. &lt;/p&gt;&lt;p&gt;Den andra delen är mer av referenstyp. Här får man läsa om varje pattern igenom för sig. Vilka fördelar och nackdelar de har och även vilka andra patterns som kan vara relevanta. &lt;/p&gt;&lt;p&gt;Jag tror att det här är en bok som man bör ha läst eller i var fall ha någon i närheten som läst. För även om det kommer nya framework så är det sällan de faktiskt har uppfunnit något riktigt nytt. Microsoft MVC är en Front Controller precis som Struts så inget nytt under himlen där. Lite mer hårdvara och erfarenhet har naturligvis drivit utvecklingen frammåt men det finns bara så många sätt att ta hand om ett http-anrop och göra något vettigt med det. &lt;/p&gt;&lt;p&gt;Boken har exempel i C# och Java vilket i princip borde göra att alla kan läsa den med god behållning även om man skulle ha drag av religon. &lt;/p&gt;&lt;p&gt;Nu en kort ordlista som kanske kan motivera någon att ta upp boken och börja läsa ett kapitel eller två:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Active Record&lt;/li&gt;&lt;li&gt;Application Controller&lt;/li&gt;&lt;li&gt;Accociation Table Mapping&lt;/li&gt;&lt;li&gt;Class Table Inheritance&lt;/li&gt;&lt;li&gt;Client Session State&lt;/li&gt;&lt;li&gt;Coarse-Grained Lock&lt;/li&gt;&lt;li&gt;Concrete Table Inheritance&lt;/li&gt;&lt;li&gt;Data Mapper&lt;/li&gt;&lt;li&gt;Data Transfer Object&lt;/li&gt;&lt;li&gt;Database Session State&lt;/li&gt;&lt;li&gt;Dependent Mapping&lt;/li&gt;&lt;li&gt;Domain Model&lt;/li&gt;&lt;li&gt;Embedded Value&lt;/li&gt;&lt;li&gt;Foreign Key Mapping&lt;/li&gt;&lt;li&gt;Front Controller&lt;/li&gt;&lt;li&gt;Gateway&lt;/li&gt;&lt;li&gt;Identify Field&lt;/li&gt;&lt;li&gt;Identify Map&lt;/li&gt;&lt;li&gt;Implicit Lock&lt;/li&gt;&lt;li&gt;Inheritance Mapper&lt;/li&gt;&lt;li&gt;Layer Supertype&lt;/li&gt;&lt;li&gt;Lazy Load&lt;/li&gt;&lt;li&gt;Mapper&lt;/li&gt;&lt;li&gt;Metadata Mapping&lt;/li&gt;&lt;li&gt;Model View Controller&lt;/li&gt;&lt;li&gt;Money&lt;/li&gt;&lt;li&gt;Optimistic Offline Lock&lt;/li&gt;&lt;li&gt;Page Controller&lt;/li&gt;&lt;li&gt;Pessimistic Offline Lock&lt;/li&gt;&lt;li&gt;Plugin&lt;/li&gt;&lt;li&gt;Query Object&lt;/li&gt;&lt;li&gt;Record Set&lt;/li&gt;&lt;li&gt;Registry&lt;/li&gt;&lt;li&gt;Remote Facade&lt;/li&gt;&lt;li&gt;Repository&lt;/li&gt;&lt;li&gt;Row Data Gateway&lt;/li&gt;&lt;li&gt;Separated Interface&lt;/li&gt;&lt;li&gt;Serialized LOB&lt;/li&gt;&lt;li&gt;Server Session State&lt;/li&gt;&lt;li&gt;Service Layer&lt;/li&gt;&lt;li&gt;Service Stub&lt;/li&gt;&lt;li&gt;Single Table Inheritance&lt;/li&gt;&lt;li&gt;Special Case&lt;/li&gt;&lt;li&gt;Table Data Gateway&lt;/li&gt;&lt;li&gt;Table Module&lt;/li&gt;&lt;li&gt;Template View&lt;/li&gt;&lt;li&gt;Transaction Script&lt;/li&gt;&lt;li&gt;Transform View&lt;/li&gt;&lt;li&gt;Two Step View&lt;/li&gt;&lt;li&gt;Unit Of Work&lt;/li&gt;&lt;li&gt;Value Object&lt;span class="__wave_paste" __wave_annotations="" __wave_xml=""&gt;&lt;line&gt;&lt;/line&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-3265285495586435640?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/3265285495586435640/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/patterns-of-enterprise-application.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3265285495586435640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3265285495586435640'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/patterns-of-enterprise-application.html' title='Patterns of Enterprise Application Architecture'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-1314107495341103282</id><published>2009-12-06T00:43:00.000-08:00</published><updated>2009-12-08T22:09:41.119-08:00</updated><title type='text'>Test Driven Development</title><content type='html'>Jag har lekt lite med TDD (Test Driven Development) vilket har varit ganska intressant. Att skriva testdriven kod är först och främst en vanefråga, att vänja sig vid ett sätt att tänka. Det är en sorts förändring som jag tror kräver en hel del övning innan man börjar försöka att applicera tekniken på skarpa projekt där man faktiskt ska leverera kundnytta. Utan någon form av ledarskap och erfarenhet att luta sig mot finns det många fällor man kan hoppa in i och därmed göra livet betydligt svårare än det behöver vara.&lt;br /&gt;&lt;br /&gt;Test driven utveckling följer en cykel med tre steg&lt;br /&gt;&lt;br /&gt;1) Fundera ut ett test och implementera det i testkoden, testet ska falera.&lt;br /&gt;2) Implementera produktionskod för att få testet att fungera&lt;br /&gt;3) Refaktorera, både produktionskod och testkod.&lt;br /&gt;&lt;br /&gt;När man skriver testet ska man försöka att göra det så litet som möjligt. Tanken är inte att testet ska täcka in allt som kan inträffa utan enbart ett scenario. Man ska alltså skriva så lite som möjligt för att åstadkomma ett falerande test. Det får till följd att en serie av tester kan ses som en specifikation av programmet du skriver. Varje nytt test bygger på de tidigare. Varje nytt test beskriver en liten bit ny funktionalitet. När man läser en testklass ska man intoduceras i problemet och test för test få de mer komplicerade användningsområdena presenterade.&lt;br /&gt;&lt;br /&gt;När man skriver produktionskod ska man inrikta dig på att få testet att gå igenom med minsta möjliga insats. Även om du kan lösa tusen problem genom att implementera ett helt framework i din produktionskod så behöver du sannolikt inte det för att få ett test att gå igenom. De första testerna löser man sannolikt genom att returera null, eller textkonstanter i produktionskoden. Syftet med att man vill lösa minsta möjliga del av problemet är att man ofta vill ta fram lösningar som är betydligt komplexare än vad man faktiskt har behov av. Genom att lösa ett test i taget med minsta möjliga förändring går man inte händelserna i förväg. Många problem har väldigt enkla lösningar om man kan undvika att börja med att bygga stora arvsheirakier och domänmodeller.&lt;br /&gt;&lt;br /&gt;Det tredje och sista steget är att refaktorera koden man har skrivit. Någon skrev att man ska genomföra detta steg skoningslöst. Med testerna som stöd för refaktoreringen så får man snabbt reda på om man har förstört någon existerande funktionallitet och genomgripande förändringar i koden. Men man ska också refaktorera sina tester. Det är förmodligen viktigare att testerna är i bra skick än produktionskoden.&lt;br /&gt;&lt;br /&gt;Jag har gjort tre små experiment med TDD så här långt. PrimfactorsKata, BowlingGameKata och så en PostfixMiniräknare. Det jag har lärt mig är att man bör ha ganska bra koll på problemet man löser. För skriver du dina tester fel är det inte riktigt lika lätt att ändra i dem som det är att ändra i produktionskoden. Tex missuppfattade jag reglerna för hur man beräknar poäng i BowlingGameKatan vilket inte var helt smidigt att rätta till. Däremot att byta ut den rekursiva kod jag använde i PrimefactorsKatan till en algoritmisk dito gjorde med lätthet, testerna talade om när något inte var som det skulle och testerna förändrades inte bara för att jag bytte lösning, api:et var det samma. Så om man har en god idé om hur api:et ska se för det problem man ska lösa är TDD utmärkt. Om man har mer svävande uppfattning om vilket api problemet döljer sig bakom får man nog ganska omfattande förändringar i både tester och i produktionskod, något som gör livet lite besvärligare.&lt;br /&gt;&lt;br /&gt;En lösning för att ta fram vilket api man vill utgå från i testerna kan vara att göra en prototyp där man kan experimentera sig fram till hur problemets api ser ut. Man behöver inte implementera problemet i detalj men man kan testa ett par möjliga gränssnitt mot problemet. När man sedan har sin idé om hur man vill använda funktionen kan man börja implementera med hjälp av TDD.&lt;br /&gt;&lt;br /&gt;Nu skulle säkert en renlärig TDD:are säga att det api man tagit fram utan TDD inte är optimalt eller att man har försökt att lösa problemen i fel ordning. För om du utgår från sådant du inte kan ändra, tex ett utseendet på en miniräknare så har du inte så stora möjligheter att ändra API:et. Sedan för varje steg du jobbar dig ner i lagren av kod så skulle api:et redan mer eller mindre vara förutbestämt. Jag kan köpa in på det resonemanget också men har inte hittills någon erfarenhet av att det faktiskt fungerar på det sättet utan skulle behöva få tag på ett lämpligt scenario att testa det på. De jag har gjort hittills har ju varit av ganska trivial natur för att begränsa tidsåtgången.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-1314107495341103282?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/1314107495341103282/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/test-driven-development.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1314107495341103282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1314107495341103282'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/12/test-driven-development.html' title='Test Driven Development'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-828058073420358248</id><published>2009-11-16T12:29:00.001-08:00</published><updated>2009-11-18T07:01:00.925-08:00</updated><title type='text'>Refaktorering</title><content type='html'>Jag ska hålla i en kodkata på jobbet och tänkte försöka att samla mina tankar lite inför denna händelse skriftligt. Det brukar bli lite lättare att komma ihåg saker och ting när jag skrivet ner det. Ämnet är refaktorering och det blir inte mitt mest strukturerade inlägg och jag kommer säkert att fylla på det tills kodkatan är genomförd.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Varför vill man refaktorera sin kod? &lt;/span&gt;&lt;br /&gt;För att den alltid kan bli bättre.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Vad är bättre kod? &lt;/span&gt;&lt;br /&gt;Kod som du själv och andra kan förstå snabbare. Små tricks som att använda beskrivande metodnamn eller låta klasser utföra en sak i taget kan göra underverk för hur snabbt du kan ta till dig hur koden fungerar. Att dölja det som läsaren inte är intresserad av och göra det enkelt att hitta den kod han/hon faktiskt vill se minskar mängden kod man behöver för att förstå lösningen. Att dela upp lösningarna i små samverkande moduler kan göra även komplicerade sysslor triviala.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Extract method&lt;br /&gt;&lt;/span&gt;Ta en metod och dela upp den i flera mindre genom att markera ett antal rader kod och ge dessa en egen metod. Fördelen är att man kan ge de markerade raderna en betydelse i metodnamnet som inte självklart kan utläsas ur koden. Vad betyder det att ett objekt är null?&lt;br /&gt;&lt;br /&gt;När man bryter ut metoder kan man ha tre idéer om vad koden ska göra. Om man seperarar dessa blir koden enklare att förstå och i en hel del fall även enklare att modifiera efteråt.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;metoden kan delegera till andra metoder&lt;/li&gt;&lt;li&gt;metoden kan skapa andra objekt&lt;/li&gt;&lt;li&gt;metoden kan göra något.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;En metod som delegerar sitt uppdrag kan sägas förklara uppgiften. Genom att inte blanda in kod som gör något "arbete" blir metoden en beskrivning av de steg som måste tas för att uppgiften ska kunna lösas.&lt;br /&gt;&lt;br /&gt;En metod som enbart skapar objekt gör det enkelt att förändra vilka objekt som skapas. Den begränsar på det sättet klassens beroende på de klasser som skapas och kan sannolikt användas av andra klasser för att skapa objekt. Alternativet är att skapa objekten där man ska använda dem och då begraver man beroendet på dessa objekt djupt och gör det svårt att ändra.&lt;br /&gt;&lt;br /&gt;En metod som gör något gör det som blir kvar efter de två första metodtyperna. Om man använt delegerande metoder och skapande metoder blir den arbetande metoden oftast ganska kort och enkel att förstå. Den uppgift som utförs är förmodligen redan uppdelad i lämpliga delar av en delegerande metod och de objekt som metoden jobbar på är redan skapade vilket tar bort en hel del komplexitet.&lt;br /&gt;&lt;br /&gt;Naturligtvis går det inte helt vattentäta skott mellan de tre metoderna. Tex kan en arbetande metod som innehåller ett antal if-else-satser delegera jobbet som ska utföras för varje utfall i respektive if-else. Men att tänka på en metod som skapande, delegerande eller arbetande tycker jag hjälper till med att strukturera koden så att den blir lättare att förstå.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Globalt tillstånd&lt;/span&gt;&lt;br /&gt;Vi vet att globala variabler är dåliga men att statiska metoder och singletons är minst lika illa är det kanske färre som har koll på. Globala variabler avskaffade med objektorienterade programmeringsspråk. Statiska variabler och metoder blev dock kvar vilket nog måste ses som en eftergift åt alla procedurella programmerare i världen. Singletons är ett återskapande av globala variabler i form av objekt vilket ger samma problem som globala variabler.&lt;br /&gt;&lt;br /&gt;Statisk kod är procedurell och procedurell kod är svår bygga vidare på utan att göra utbyggnaden procedurell. Det blir som cancer i din kod. Precis som med all annan procedurell kod är det lite knepigt att hantera objectorienterade begrepp med statisk kod.&lt;br /&gt;&lt;br /&gt;Problemet med singletons är det samma som med globala variabler. En singleton är ett globalt objekt, inget mer inget mindre. Singletons är dessutom ett utmärkt sätt att dölja klassers beroenden. Eftersom klassen kan hämta objektet den behöver precis där den behöver det behöver vi aldrig visa att vår metod som ser ut att beräkna 1+1 anropar en webservice på Nasa för att utföra beräkningen. Dessutom är det svårt att skriva små snabba tester som man faktiskt kan köra ofta om det finns singletons i koden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Gör en sak och gör den bra&lt;/span&gt;&lt;br /&gt;En bra metod utför en uppgift. I en bra klass utför en metod beräkningar på det data som klassen håller internt, ett data som enbart räcker till för att lösa den uppgift som klassen ska hantera. Den största anledningen till att man vill ha det på det sättet är att vi inte vill behöva spendera tid på att fundera på vad klassen har för uppgift. Om en klass eller metod gör flera saker krävs det en större ansträngning för att förstå vad som händer. En ansträngning som kan användas till viktigare frågor. Klasser med en tydlig uppgift tenderar till att lösa den uppgiften bra vilket gör att den blir lätt att använda ifrån andra klasser.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Visa beroenden&lt;/span&gt;&lt;br /&gt;Som jag skrev ovan är Singletons bra på att gömma sig i klasser och ställa till problem där man minst väntar sig. Anledningen till att det blir problem är när en metod som man förväntar sig ska göra en sak på ett sätt visar sig lösa den på ett helt annat sätt, tex genom att anropa en webservice i stället för göra operationen lokalt. I exemplet är det inte att man använder en webservice som är problemet, det kan mycket väl vara rätt lösning. Det som blir ett problem är när användaren av klassen inte enkelt kan se att operationerna har ett beroende på nämnda webservice. Därför bör man deklarera sina beroenden genom konstruktorn eller metodsignaturerna. Webservicen bör tex skickas in i konstruktorn så att beroendet blir tydligt. Ingen beräkning utan att en webservicehandler skickas in. En annan poäng med att skicka in de objekt behöver i konstruktorn i stället för att använda globala objekt är att det blir lätt att byta ut webservicehandlern mot en annan handler som implementerar det gränssnitt som webservicehandler definierar. Bra för test och när man kommer på att det det går snabbare att utföra beräkningen lokalt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-828058073420358248?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/828058073420358248/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/11/refaktorering.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/828058073420358248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/828058073420358248'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/11/refaktorering.html' title='Refaktorering'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-7648106441672224877</id><published>2009-07-28T13:10:00.000-07:00</published><updated>2009-07-28T13:20:41.061-07:00</updated><title type='text'>Unlocking Android</title><content type='html'>Nu en bit in på semestern har jag läst igenom Unlocking Adroid från Manning. Jag tyckte den var bra och informativ även om det är långt till en Head First bok. Upplägget går ut på att visa de olika begreppen genom små exempelapplikationer. Upplägget med exempelapplikationer tror jag passade bra för att visa hur Android fungerar och hänger ihop då det är en del konfiguration som hänger ihop med koden. Alla exempel finns att ladda ner.&lt;br /&gt;&lt;br /&gt;Kort och gott, för den som vill lära sig android och få en lite mer sammanhängande bild av vad man kan göra än vad man kan få genom att söka exempel på internet är detta en bra bok.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-7648106441672224877?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/7648106441672224877/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/07/unlocking-android.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7648106441672224877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7648106441672224877'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/07/unlocking-android.html' title='Unlocking Android'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-2674466496867264787</id><published>2009-06-20T12:39:00.000-07:00</published><updated>2009-06-20T12:49:13.207-07:00</updated><title type='text'>Head First Design Patterns</title><content type='html'>Ibland träffar man på saker där man inte kan tänka sig hur det skulle göra bättre. Den bok jag håller på att läsa är ett bra exempel på detta. Head First från O'Relly är en serie av böcker där de har utgått från lite forskning om hur hjärnan fungerar och sedan skrivit böckerna med den kunskapen i första rummet.&lt;br /&gt;&lt;br /&gt;Design Patterns är inget som får safterna att flöda hos många. Men i denna bok är det faktiskt riktigt roligt. Inte bara det, en förståelse växer fram. Jag har läst ett par böcker i ämnet sedan tidigare men trots det lyckas jag lära mig något av den här boken.&lt;br /&gt;&lt;br /&gt;Jag är inte på långa vägar färdig med boken utan måste bara säga. Om ni har ett val när ni ska köpa en bok. Kolla upp O'Relly's Head First och kolla om det finns en bok i ämnet ni är intresserade av. Jag har svårt att tro att ni kommer att ångra er.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-2674466496867264787?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/2674466496867264787/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/06/head-first-design-patterns.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2674466496867264787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2674466496867264787'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/06/head-first-design-patterns.html' title='Head First Design Patterns'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-767544211105017746</id><published>2009-06-19T02:41:00.000-07:00</published><updated>2009-06-19T04:32:08.501-07:00</updated><title type='text'>Förändringsbar kod</title><content type='html'>Det var ett tag sedan jag skrev. Lusten har inte funnits... men nu är det dags att rapportera mina senaste erfarenheter. Jag har under en tid roat mig med ett litet hobbyprojekt som springer ur ett experimentet som ni kan läsa om &lt;a href="http://jsolutions.se/?p=424"&gt;här&lt;/a&gt;. Experimentet går kort och gott ut på att visa att det är lättare att förändra en applikations beteende om koden är bra. Min personliga tolkning av detta experiment landade i följande hobbyprojekt.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Skriv en enkel applikation (tictactoe).&lt;/li&gt;&lt;li&gt;Refaktorera koden så att du även kan spela luffarschack.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Refaktorera koden så att du kan spela othello.&lt;/li&gt;&lt;/ol&gt;Hur gjorde jag då detta? Till att börja med så visste jag att jag skulle behöva hantera förändring så jag beslutade mig för att skriva tester och dessutom dra det ett steg längre och skriva testerna innan jag skriver implementationskoden. Detta för att testerna i möjligaste mån ska agera specifikation och dessutom tvinga mig till att skriva testbar kod i stället för att slacka och skriva tester där det är enkelt.&lt;br /&gt;&lt;br /&gt;Nästa steg var att skriva första varianten av spelet. Här försökte jag så gott det nu gick att ignorera att jag visste att jag skulle få skriva om mycket av koden. Så en hel del av koden blev bunden mot siffran 3. Men eftersom hela poängen med övningen är att det ska finnas lite att skriva om för att stödja funktionallitet som jag "inte visste" skulle komma så var det i princip som det skulle vara.&lt;br /&gt;&lt;br /&gt;Nästa steg blev nu att försöka att skriva om Tictactoe till luffarschack. Då jag hade ett enkelt GUI (i konsoll) så beslutade jag mig för att se till att det koden som utgjorde GUI inte skulle röras. Detta beslut tog jag av två anledningar. 1) Det är lätt att kolla om jag har några luckor i mina tester genom att provspela det som fungerade. 2) I verkligheten är det ofta så att man kan ha applikationer som är beroende av ens egen kod som inte kan förändras.&lt;br /&gt;&lt;br /&gt;Nu håller jag på med steg tre (Othello) och börjar i viss mån uppleva lite deja vu så vi får se om jag slutför det hela. Jag har beställt en bok om Android så kanske jag försöker att göra spelen njutningsbara med ett riktigt GUI. Men det är nog några API:er som jag ska lära mig innan det händer.&lt;br /&gt;&lt;br /&gt;Men har jag lärt mig något då? Jo, det första är att den här övningen är svår att göra själv. Tex det tredje steget i TDD är lätt att förhandla bort (skriv testet, implementera koden, &lt;span style="font-weight: bold;"&gt;refaktorera&lt;/span&gt;). De vägval man gör blir även lite färgade av att man skrivit koden för det förra steget och därför kan koden ganska bra. Det minskar viljan (i alla fall hos mig) att skriva om det som fungerar bara för att det ska bli bättre. Om någon annan skrivit koden så tror jag att jag hade haft det lättare att identifiera vad som är knöligt och vad som är bra.&lt;br /&gt;&lt;br /&gt;Det leder mig till slutsatsen att om kod ska skivas om så bör man inte låta samma programmerare som skrev applikationen en gång i tiden delta i refaktoreringen, i alla fall inte ensam.  Det blir lite av en paradox att kunskap om hur en applikation är byggd kan bidra till applikationens förfall. Jag antar det ligger någon form av psykologi att att förneka att en investering är dålig och behöver revideras, att vilja tro på att allt är bra.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-767544211105017746?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/767544211105017746/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/06/forandringsbar-kod.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/767544211105017746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/767544211105017746'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/06/forandringsbar-kod.html' title='Förändringsbar kod'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-2407552638901987447</id><published>2009-05-04T11:30:00.001-07:00</published><updated>2009-05-04T12:07:01.481-07:00</updated><title type='text'>Två böcker lästa (nästan)</title><content type='html'>Jag har läst två böcker nu på sistone. &lt;a href="http://www.amazon.com/NET-Domain-Driven-Design-Solution-Programmer/dp/0470147563/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1241461898&amp;amp;sr=8-1"&gt;.Net Domain-Driven Design with C#&lt;/a&gt; och &lt;a href="http://www.amazon.com/ASP-NET-3-5-Application-Architecture-Design/dp/1847195504/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1241461936&amp;amp;sr=1-1"&gt;ASP.NET 3.5 Application Architecture and Design&lt;/a&gt;. Ingen av böckerna gav mig speciellt mycket men av olika skäl.&lt;br /&gt;&lt;br /&gt;Vi börjar med &lt;span style="font-weight: bold;"&gt;.Net Domain-Driven Design with C#&lt;/span&gt;.&lt;br /&gt;För det första förstår jag inte varför någon köper böcker från &lt;a href="http://www.wrox.com/WileyCDA/"&gt;Wrox&lt;/a&gt;. Jag har läst ett par böcker från det förlaget tidigare och maken till tråkigt upplägg finns inte. Bara det är en anledning att inte läsa denna bok. Gamla böcker som &lt;a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1241462204&amp;amp;sr=8-1"&gt;Design Patterns&lt;/a&gt; framstår som under av läsbarhet och upplyftande grafik. Men det ska jag inte lasta Tim McCarty för. Nu till boken.&lt;br /&gt;&lt;br /&gt;Boken är en beskrivning av ett projekt som Tim varit med i där han fick möjlighet att avända &lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?ie=UTF8&amp;amp;qid=1241462348&amp;amp;sr=1-1"&gt;Domain Driven Design&lt;/a&gt; som beskrevs i boken med samma namn. Det hade kunnat varit väldigt intressant. Dock faller Tom i fällan med att visa långa kodexempel. Tar vi kapitel tre som exempel så har 44 sidor kod på sig. Kanske inte låter så farligt men kapitlet är på 52 sidor och majoriteten av sidorna har mycket kod på sig. Inte små enkla exempel för att påvisa poänger utan bara långa rapningar av hur klasserna ser ut.&lt;br /&gt;&lt;br /&gt;I mina ögon är boken ett typiskt exempel på när en författare får betalt för varje sida som han lyckas pressa in i boken. Att skriva en bok på 50 sidor och ha en zip-fil för nerladdning hade varit bättre.&lt;br /&gt;&lt;br /&gt;Nästa bok är &lt;span style="font-weight: bold;"&gt;ASP.NET 3.5&lt;/span&gt; boken.&lt;br /&gt;För att jämföra förlagens strategi så har &lt;a href="http://www.packtpub.com/"&gt;Packt&lt;/a&gt; ett betydligt roligare upplägg i sina böcker. Allt från val av typsnitt till bilder känns roligare.&lt;br /&gt;&lt;br /&gt;Denna bok hade jag ganska stora förhoppningar på. Jag har bytt arbetsgivare från ett företag där vi skrev i Java till ett där vi använder .Net. Så en bok som beskriver hur allt hänger ihop utifrån ett design och arkitekturperspektiv lät väldigt lovande. Problemet är att boken i bästa fall kan beskrivas som en nybörjarbok i arktektur och design. Men jag upplevde boken som pedagogisk och välskriven i övrigt. Men den var inte skriven för mig.&lt;br /&gt;&lt;br /&gt;Slutsatsen är att jag har läst större delen av två dåliga böcker. Men kanske jag har lärt mig något? Vem vet?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-2407552638901987447?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/2407552638901987447/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/05/tva-bocker-lasta-nastan.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2407552638901987447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2407552638901987447'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/05/tva-bocker-lasta-nastan.html' title='Två böcker lästa (nästan)'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-619518631420651794</id><published>2009-04-17T22:34:00.000-07:00</published><updated>2009-04-17T23:53:13.344-07:00</updated><title type='text'>Min föreläsning</title><content type='html'>I torsdags höll jag en föreläsning för mina kollegor på jobbet om Clean code, eller nåja, min uppfattning av det viktigast runt vad som gör kod enkel att underhålla.&lt;br /&gt;&lt;br /&gt;Först pratade jag lite teori. Kanske inte så mycket kontrekta råd men ändå lyfta ett antal begrepp så att de finns på kartan.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Law of demeter&lt;/li&gt;&lt;li&gt;Open closed principle&lt;/li&gt;&lt;li&gt;Liskows substition principle&lt;/li&gt;&lt;li&gt;Single responsiblity principle&lt;/li&gt;&lt;li&gt;Don't ask, tell&lt;/li&gt;&lt;li&gt;Duplicering&lt;/li&gt;&lt;/ul&gt;Inga av begreppen är revolutionerande men att bygga ett gemensamt språk om koden vi skriver känns angeläget så att alla kan referera till samma utttryck och alla andra förstår vad uttrycket betyder. Några av uttrycken är motsägande, tex Law of Demeter och Single Responsibiltiy principle där LoD lätt resulterar i GOD-objects medans SRP lätt skapar långa kedjor av objekt som man måste navigera.&lt;br /&gt;&lt;br /&gt;Den andra delen av föreläsningen tog upp något mer konkreta tips på hur man kan få bättre och renare kod.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Beskrivande namn&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Förklarande variabler&lt;/li&gt;&lt;li&gt;Tvingande anropsordning (beroende på ordning)&lt;/li&gt;&lt;li&gt;Abstract factory&lt;/li&gt;&lt;li&gt;Template method&lt;/li&gt;&lt;li&gt;Dependency injection&lt;/li&gt;&lt;li&gt;Tester&lt;/li&gt;&lt;li&gt;Refaktorering&lt;/li&gt;&lt;/ul&gt;Jag kände att tiden inte riktigt räckte till för att kunna förklara tex Abstract Factory tillräkligt väl men förhoppningvis kommer de som lyssnar ihåg uttrycket och slår upp det.&lt;br /&gt;&lt;br /&gt;Till sist pratade jag lite om "the boyscout rule" om att alltid försöka att lämna saker i bättre skick än man fann dem. Vi pratade även lite om de små klockor man bör försöka att träna upp till att ringa i bakhuvudet när man tex ser en metod som är mer än 10 rader lång. Inte för att man nödvändigtvis ska bryta ut en mindre metod utan för att man ska se om det faktiskt finns en metod där.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-619518631420651794?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/619518631420651794/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/04/min-forelasning.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/619518631420651794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/619518631420651794'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/04/min-forelasning.html' title='Min föreläsning'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-3204864046602811414</id><published>2009-04-14T10:03:00.000-07:00</published><updated>2009-04-14T10:12:43.964-07:00</updated><title type='text'>Team anti-patterns</title><content type='html'>Läste lite på Ola Ellnestams &lt;a href="http://ellnestam.wordpress.com/"&gt;blog&lt;/a&gt; och såg att han skrivit ner de patterns som han hade med på sin föreläsning på SDC2009 som jag skrivit om &lt;a href="http://renprogrammering.blogspot.com/2009/03/swedish-developer-conference-2009.html"&gt;tidigare&lt;/a&gt;. Ni hittar dokumentet här. Läs och fundera på om ni har något att ta till er.&lt;br /&gt;&lt;br /&gt;De "team antipatterns" som jag känner mest för är "The code napper" och "The hidden backlog", men det kanske beror på att det är de två som jag har upplevt senast.&lt;br /&gt;&lt;br /&gt;Det är bra läsning för de som ibland kanske intresserar sig för de något mjukare delarna av programmering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-3204864046602811414?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/3204864046602811414/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/04/team-anti-patterns.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3204864046602811414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3204864046602811414'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/04/team-anti-patterns.html' title='Team anti-patterns'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-1092309734661061680</id><published>2009-03-27T14:30:00.000-07:00</published><updated>2009-03-27T16:46:35.227-07:00</updated><title type='text'>Swedish developer conference 2009</title><content type='html'>Nu så här några dagar senare kommer det en liten rapport av mina äventyr från Swedish Developer Conference 2009. På det stora tyckte jag att besöket var väl värt tiden även om jag framför allt på Emliy Bache seminarie led ganska hårt av att jag läst boken Clean Code och reflekterat en hel del på ämnet här på bloggen. Här kommer ett litet referat av de seminarium som jag gick på.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Keynote: Kent Beck - Responsive design&lt;/span&gt;&lt;br /&gt;Handlade i första hand om de vanor som skiljer de team som lyckas från de som misslyckas. Tex att vara action-inriktad, alltså att våga prova nya tekniker och att hantera en föränderlig verklighet genom att gå till handling och inte vänta på att något ska hända. Men man får inte bara gå till handling, lämpligtvis måste man också stanna upp när man nått någon form av resultat, framgång eller ej, och reflektera och fundera på hur man kan dra nytta av erfarenheten. Kanske lite förenklat så våga prova nya vägar. Värdera varje experiment förutsättningslöst och dra lärdomar.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Chris Hedgate: From good developer to great developer&lt;/span&gt;&lt;br /&gt;Chris pratade bland annat om &lt;a href="http://en.wikipedia.org/wiki/Four_stages_of_competence"&gt;"The four steps of competence"&lt;/a&gt; och vilka konsekvenser det har för möjligheterna att kunna dela med sig kunskap och mottagarens förmåga att kunna ta till sig denna kunskap.&lt;br /&gt;&lt;br /&gt;Några småsaker jag noterade var att Chris menade på att underhåll av kod börjar samtidigt som man skriver koden. För varje rad du skriver så tar du hänsyn till den tidigare och om inte den är välskriven och genomtänkt så blir nästa svårare att skriva.&lt;br /&gt;&lt;br /&gt;Chris menade också att det är en god vana att för varje klass man är och skriver i försöker att göra den lite bättre i stället för att bara nå upp till den existerande kodens standard. Även om du inte hinner göra några större refaktoreringar så kanske det finns ett dåligt valt variabelnamn eller förtydliga ett flöde genom att bryta isär en metod i två.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Markus Widerberg - Refactoring .Net-code towards readability&lt;/span&gt;&lt;br /&gt;Detta seminarie handlade till stora delar om hjärnans förmåga att ta till sig information. Tex nämndes att den mänskliga hjärnan klarar 7 (+-2) saker utan att först bygga en struktur. Därför är det viktigt att döpa saker på ett sådant sätt att läsaren kan koppla ihop texten med existerande strukturer. Med hjälp av dessa strukturer kan vi hålla många saker i huvudet. Utan dem trillar vi ner på 7 (+-2).&lt;br /&gt;&lt;br /&gt;Markus konsterade att Visual Studio suger fett när det kommer till refactorering och att en plugin som tex Resharper är absolut nödvändigt. Han hade försökt att göra sin demo utan Resharper men fick ge upp. Kan tilläggas att de exempel som han visade inte var avancerade på något sätt.&lt;br /&gt;&lt;br /&gt;Jag frågade Markus om han, som respresentant för det enda .Net fokuserade seminariet jag gick på under dagen, uppfattade om användande av m_ och I på interface är ungersk notation. Svaret på frågan var ja. Det skulle vara kul att få höra en officiell Microsoft representant resonera om detta då många verktyg i Visual studio generar kod som i mina ögon är ganska ungersk så att säga.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ola Ellnestam - Software development team antipattern&lt;/span&gt;&lt;br /&gt;Detta var inget bra seminarie. Inte för att Ola inte hade bra saker att berätta om utan för att framförandet var misslyckat.&lt;br /&gt;&lt;br /&gt;Det viktigast som fastnade hos mig var ansvaret för kod och hur det ofta tenderar till att landa på en person. "Det var Kalle som implementerade det så fråga honom". Om Kalle är sjuk, på semester eller har slutat från jobbet så finns det ingen annan som vet hur det fungerar och Kalle kan ha skrivit saker på ett sätt som ingen annan förstår. Att rotera uppgifter och ansvar i ett projekt kan vara en lösning på problemet.&lt;br /&gt;&lt;br /&gt;Todo:er var något som Ola också tog upp i kontextet att det är lätt att todo:er blir en form av inofficiell backlogg i projektet. Uppgifter som ingen igentligen vet att de borde göras och ingen heller kan ta ansvar för att de blir gjorda. Att regelbundet söka efter todo och att säga att todoer inte hör hemma i koden utan i backloggen kan vara ett par lösningar för att komma bort från det problemet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Niclas Nilsson - Black Belt TDD/BDD&lt;/span&gt;&lt;br /&gt;För några månader sedan så kom &lt;a href="http://blog.stackoverflow.com/2009/01/podcast-38/"&gt;Stackflow #38&lt;/a&gt; där det påstods att det är lätt att göra en liten förändring i en kodbas och genom den lilla förändringen tvinga fram förändringar i 10% av testerna. För de som kör TDD där i det närmaste halva kodbasen kan bestå av testkod är det en alarmerande siffra. Niclas beskred inte att det är möjligt att skriva kod på det sättet men menade att problemet med att många spruckna tester vid små förändringar kommer av dålig kod i första rummet. Han menade kort och gott på att om koden är välskriven i första rummet utan onödiga beroenden kommer inte heller testerna att ha det problemet. Niclas hade en teori om att mycket dålig kod beror på att den är skriven ur fel förutsättningar, att man har börjat fundera på detaljerna först. Problemet med att beskriva detaljerna först är att för varje abstraktionsnivå man flyttar sig uppåt (utåt?) så har man redan koden för de undre lagren redan skrivna och då använder man den i stället för att tänka efter hur det abstraktionslagret borde fungera.&lt;br /&gt;&lt;br /&gt;Nicklas lösning är att man börjar på toppen (utsidan) med att gå över kundens krav och börjar skriva toplevel-funktionalliteten först. Eftersom detaljerna inte är skrivna ännu måste man skriva mock-implementationer. Något som i praktiken leder till Dependency Injection. De tester man skriver (före eller efter) produktionskoden kommer om man skriver utsidan först att testa mycket mindre delar av koden och risken för att de ska spricka i onödan minskar drastiskt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Emily Bache - Clean code&lt;/span&gt;&lt;br /&gt;Tyvärr så har jag läst boken. Utöver den hade inte Emily så hemskt mycket matnyttigt att erbjuda mig. Jag hade gärna sett lite kodexempel på när man dragit Uncle Bobs regler för långt, eller inte tillräkligt långt. Eller exempel på hur man kan bena ut existernade kod till något clean.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Niclas Nilsson - The unintuitive part of agile&lt;/span&gt;&lt;br /&gt;Detta var för mig dagens bästa seminarie. Niclas tog upp några av de delar som vid en snabb titt kan verka slösa på tid faktiskt fungerar i praktiken.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Täta iterationer borde innebära att man lägger ner massor med energi på att få något fungerade väldigt ofta, tid som man skullel kunnat skriva kod. Men poängen med de täta iterationerna är att man ger produktägaren en möjlighet att se vad som händer med applikationen och kunna prioritera utifrån de affärsvärden som ska betala arbetet i slutändan.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Täta releaser borde innebära att man spenderar tid på att lägga ut applikationen i produktion och dessutom utsätta verksamheten för en risk för problem i samband med uppdateringen. Niklas menar att risken är imaginär, om man uppdaterar ofta vill man automatisera processen och buggar kommer att gå ur deploymentprocessen då den körs så ofta. Om man bara gör uppdatering var 6:e månad så är risken större då man är mindre benägen att automatisera processen.&lt;/li&gt;&lt;li&gt;Parprogrammering borde innebära att man får hälften så mycket gjort då det bara en är person som faktiskt skriver kod. Dock är det så att man uppnår ökad effektivitet i from av ett antal sociala kontrakt. Man kollar inte mail med någon brevid, det är svårare att störa om någon ser ut som att de sitter i ett möte. Dessa sociala bitar menade Niclas att de skulle ge en produktivitetshöjning mer än väl motsvarande den extra kostnaden. Att man dessutom slipper ett antal buggar och feltänk gör det attraktivt att parprogrammera.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Niclas pratade om tester där han på ett ganska svart-vitt sätt menade på att testdriven utveckling fungerar. Dock bör man vara uppmärksam när man inför TDD, det finns fällor som man kan gå in i. Betalar sig inte TDD i form av minskade problem med buggar, ja då ska man stanna upp och fundera på vad man gör för fel.&lt;br /&gt;&lt;br /&gt;Jag frågade hur man ska tänka om man vill införa TDD i en organisation. Niclas hänvisade till &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;BDD&lt;/a&gt; som ett sätt att lära sig tänka utifrån tankebanor som gör TDD naturligt.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ola Ellnestam, Daniel Brolund: Start paying your technical dept&lt;/b&gt;&lt;br /&gt;De visade på ett sätt att lösa komplicerade refactoreringar utifrån ett mål i form av att nå ett affärsvärde. Metoden gick ut på att rita upp en graf över vad som ska göras och sedan rekursivt rita upp de beroenden som beroendena har tills man kommer till en punkt där man kan börja lösa upp beroenden. Fördelden med den modell de visade är att den går att avbryta mitt i arbetet. De förändringar man gör får aldrig kräva att man samtidigt ska lösa något annat beroende i grafen så för varje steg man tar på vägen tillbaka mot affärsvärdet ger bättre och mer flexibil kod. Skulle affärsvärdet förändras så har man  förhoppningivis löst upp beroendena på ett sådant sätt att det nya affärsvärdet är bekänt av de förändringar man gjort på vägen.&lt;br /&gt;&lt;br /&gt;På det stora tyckte jag att dagen var bra. Det som kanske var lite trist var att de som föreläste om process och metod alla körde java. Hade varit kul med någon .Nettare som kanske kunnat berätta något om Clean Code i .Net tex.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-1092309734661061680?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/1092309734661061680/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/swedish-developer-conference-2009.html#comment-form' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1092309734661061680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1092309734661061680'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/swedish-developer-conference-2009.html' title='Swedish developer conference 2009'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5860370979115690779</id><published>2009-03-22T06:00:00.000-07:00</published><updated>2009-03-22T07:00:34.142-07:00</updated><title type='text'>Ungersk notation</title><content type='html'>Ungersk notation (hungarian notation) är något som jag uppfattat att de flesta reflexmässigt säger att det är något dåligt. Men jag tror att det är färre som faktiskt vet varför det är något dåligt och som är villiga att ta konsekvenserna av att undvika att använda Ungersk notation.&lt;br /&gt;&lt;br /&gt;Vad är då ungersk notation? Ursprungligen kommer det från programmeringsspråk som var otypade. Det enda sättet att se att en variabel innehåller en text var helt enkelt att kalla variabeln textName och för nummer numberSalary. Så kort och gott, ungersk notation är en deltext i en variables namn som ger namnet en betydelse som stäcker sig utanför applikationens logik. Det var ett nödvändigt ont förr men idag med moderna verktyg onödigt.&lt;br /&gt;&lt;br /&gt;Det är att ge variabeln en betydelse som inte beskriver applikationens funktion som är det som anses vara dåligt. Men varför är det dåligt? I första hand gör det en applikation svår att underhålla genom att man stoppar in implementationsdetaljer på ställen i koden där de inte hör hemma. En variabels betydelse ska inte förändras bara för att man förändrar dess typ.&lt;br /&gt;&lt;br /&gt;Finns det undantag från regeln? Självklart, få regler som inte har undantag. GUI programmerare brukar ofta uppskatta att de kan gruppera alla textfält genom att prefixa dem med txt. Dock bör man isolera dessa variabler i ett så tunt lager som möjligt och bearbeta dem på ställen där man har möjlighet ge saker riktiga namn.&lt;br /&gt;&lt;br /&gt;Några exempel på vad jag anser vara ungersk notation:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;IInterface - Här talar vi effektivt om att det är ett interface genom prefixet I. Någon som använder koden ska inte känna till implementationsdetaljer. Om det är en implementation av ett interface, en abstract klass eller en konkret klass är ointressant och störande information. Bättre då att att ge saker bra namn och om man inte kommer på något bra namn använda sig av ett suffix som tex impl, sub.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;m_, s_ eller bara _ är bra hjälp men med en bra IDE som kan färgkoda variablerna helt onödig. Skriver man små överskådliga klasser och metoder är det lätt att se vad som är vad. Att prefixa variablerna på det sättet är att försöka sätta plåster på dålig kod.&lt;/li&gt;&lt;/ul&gt;Vad är inte ungersk kod? Det finns ett scenario som man kanske kan säga gränsar mot ungersk notation utan att vara det. Det är vid användning av kända designpatterns. Tex vid användandet av en Factory är det lämpligt att sätta Factory som suffix, tex EmployeeFactory. Nyansen ligger i att det inte är en specifik klass som man sätter i namnet utan ett beteende. Riktigt lurigt blir det när man har en EmployeeList där List är något man hittar i ett antal språk som en klass men som också bara kan markera det att objektet i fråga beter sig som en lista utan att ha något med implementationen att göra.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5860370979115690779?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5860370979115690779/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/ungersk-notation.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5860370979115690779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5860370979115690779'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/ungersk-notation.html' title='Ungersk notation'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-6095236071081295566</id><published>2009-03-17T11:50:00.000-07:00</published><updated>2009-03-17T13:19:30.654-07:00</updated><title type='text'>Templatemethod</title><content type='html'>Fortsätter med strategier för att ta bort duplicerad kod. Förra var ett exempel på en abstract factory. Nu blir det en template method. Ett enkelt scenario där det är lätt att man börjar upprepa kod är när man ska använda en extern resurs, tex en fil. Man måste öppna filen för läsning och kanske läsa in den till minnet, man ska bearbeta filen och till sist ska man stänga filen. Avsett vad man ska göra med innehållet i filen så måste man utföra det första och sista steget. Följande metod är ett exempel:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void handleContent(File file){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  InputStream stream = getInputStreamFromFile(file)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  processStreamData(stream);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  closeStreamAndFile(stream, file);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Något förenklat säkert, men att skriva en variant på &lt;span style="font-style: italic;"&gt;processStreamData&lt;/span&gt; utan att behöva använda upprepa anropen till &lt;span style="font-style: italic;"&gt;getInputStreamFromFile(File file)&lt;/span&gt; och &lt;span style="font-style: italic;"&gt;closeStreamAndFile(InputStream stream, File file)&lt;/span&gt; har sina sidor. Exemplet ovan ser inte så illa ut men det är nog inte varje metod som implementerar ett motsvarande mönster som har brutit ner det till tre rader.&lt;br /&gt;&lt;br /&gt;Så hur komma ifrån duplicering om man vill skriva en varant på &lt;span style="font-style: italic;"&gt;handleContent&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;Vi vet att två av metoderna kommer att upprepas, öppna och stänga. Vi vet dessutom att vi vill stoppa in något mellan. Följande klass är första steget.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public abstract class TemplateMethodExample{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// Method för att öppna strömmen/filen&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  private InputStream getInputStreamFromFile(File file){ .... }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// Metod för att städa efter sig&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  private void closeStreamAndFile(InputStream stream, File file){ ....}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// Den metod som vi kommer att anropa och som öppnar&lt;br /&gt;// processar och stänger&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  public handleContent(InputStream stream){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    InputStream stream = getInputStreamFromFile(file)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     processStreamData(stream);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     closeStreamAndFile(stream, file);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// Den metod vi ska overrida med specifik funktionallitet&lt;br /&gt;// i en konkret klass&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   protected abstract processStreamData(InputStream stream);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tricket här är att vi gör en abstrakt klass med en abstrakt metod som där vi kan implementera den specifika funktionallitet vi önskar. När vi sedan vill använda vår specifika implementation så anropar vi &lt;span style="font-style: italic;"&gt;handleContent(File file)&lt;/span&gt; som är klassens enda publika funktion och den i sin tur använder den implementation av &lt;span style="font-style: italic;"&gt;processStreamData(InputStream stream)&lt;/span&gt; som har den specifika funktionallitet vi önskar.&lt;br /&gt;&lt;br /&gt;Som extra vinst har vi dessutom effektivt hindrat att någon glömmer stänga filen efter sig.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-6095236071081295566?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/6095236071081295566/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/templatemethod.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6095236071081295566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6095236071081295566'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/templatemethod.html' title='Templatemethod'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-1862581961848751364</id><published>2009-03-16T13:22:00.000-07:00</published><updated>2009-03-16T13:59:11.536-07:00</updated><title type='text'>Don't ask, tell</title><content type='html'>En liten utveckling på G5 som är beskriven tidigare. Mycket duplicering kan lösas genom att koda på en annan abstraktionsnivå. Genom att byta abstraktionsnivå kan dupliceringen förvinna. Låter lite småflummigt så jag skriver ner ett exempel:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public String getName(Example e){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  String name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  if(e.type.equals("private customer"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    name =  e.firstName + " " + e.lastName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }else if(e.type.equals("supplier"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    name = e.companyName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }else if(e.type.equals("creditor"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    name = e.creditName + "@" + e.companyName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  return name;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Koden ovanför är något krystad men beskriver ett objekt där "type" kan ha minst tre värden. Värdet på "type" bestämmer hur man ska bygga upp objektets &lt;span style="font-style: italic;"&gt;name&lt;/span&gt;. Antag nu att den här koden är copy'n pastad på några ställen och du kommer på att name inte ska vara &lt;span style="font-style: italic;"&gt;creditName + "@" + companyName&lt;/span&gt; utan i stället bara &lt;span style="font-style: italic;"&gt;companyName&lt;/span&gt;. Då är risken ganska stor att man bara ändrar på första stället och lämnar en otrevlig bugg efter sig. Men hur ska man då hantera situationen? Vi ska byta plats för var man bygger namnet. I stället för att ha en Example-klass ska vi ha tre stycken subklasser till Example som var och en vet hur den skapar sitt eget namn.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public String getName(Example e){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  return e.getName();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Vänta nu, hur gick det där till?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Gör den existerande publika konstruktorn protected så att bara subklasser kan använda den. Det genererar ett gäng kompilieringsfel men det gör inget. &lt;/li&gt;&lt;li&gt;Skapa en klass som heter ExampleFactory.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lägg till en metod createExample i ExampleFactory som tar samma argument som den nu protected konstruktorn i Examle. Implementera metoden enligt följande 4.&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;public Example createExample(String type, .... ){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  Example example&lt;/span&gt; = null;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  if(e.type.equals("private customer"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    example = &lt;/span&gt;new PrivateCustomer(....);&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }else if(e.type.equals("supplier"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    example = new Supplier(....);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }else if(e.type.equals("creditor"){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    example = new Creditor(....);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  return example;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;PrivateCustomer, Supplier och Creditor ärver samtliga från Example och samtliga implemeterar sin version av getName()&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;Nu har vi dolt den fula if-satsen i en factory. Det är det enda stället vi behöver den. Genom att skapa objekt på en bättre abstraktionsnivå har vi fått bort dupliceringen.&lt;br /&gt;&lt;br /&gt;.... noteringen är för att jag är för lat för att skriva exemplet komplett.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-1862581961848751364?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/1862581961848751364/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/dont-ask-tell.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1862581961848751364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1862581961848751364'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/03/dont-ask-tell.html' title='Don&apos;t ask, tell'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-2693519010095665632</id><published>2009-02-27T08:56:00.000-08:00</published><updated>2009-02-27T09:09:17.980-08:00</updated><title type='text'>10 artiklar som alla borde ha läst (minst två gånger)</title><content type='html'>&lt;span style="font-family:verdana;"&gt;Läste på &lt;a href="http://blog.objectmentor.com/"&gt;http://blog.objectmentor.com/&lt;/a&gt; ett inlägg av Michael Feathers. Han skriver tydligen på en ny bok och hade konstaterat att han hade tappat fokus på vilken publik han skriver för. Vad kan de som lässer boken. Kort och gott så kom han på sig med att förklara förklaringarna vilket inte var så bra. Så han plockade fram en lista på tio artiklar som i sin tur skulle förklara de begrepp han tänkte använda sig av. Några av dem är ganska gamla så det är ingen revolutionerande kunskap på något sätt. Ibland kan det vara bra att titta på annat än det som är hypat idag. Jag tänkte försöka mig på att läsa dessa tio artiklar och dessutom försöka att skriva ihop en kort sammanfattning här (om jag förstår tillräkligt mycket av dem).&lt;br /&gt;&lt;br /&gt;De tio artiklarna är:&lt;br /&gt;&lt;li&gt;&lt;a href="http://sunnyday.mit.edu/16.355/parnas-criteria.html"&gt;On the criteria to be used in decomposing systems into modules&lt;/a&gt; – David Parnas&lt;/li&gt;&lt;li&gt;&lt;a href="http://research.sun.com/techrep/1994/abstract-29.html"&gt;A Note On Distributed Computing&lt;/a&gt; – Jim Waldo, Geoff Wyant, Ann Wollrath, Sam Kendall&lt;/li&gt;&lt;li&gt;&lt;a href="http://portal.acm.org/citation.cfm?id=365257"&gt;The Next 700 Programming Languages&lt;/a&gt; – P. J. Landin&lt;/li&gt;&lt;li&gt;&lt;a href="http://portal.acm.org/citation.cfm?id=359579"&gt;Can Programming Be Liberated from the von Neumann Style?&lt;/a&gt; – John Backus&lt;/li&gt;&lt;li&gt;&lt;a href="http://cm.bell-labs.com/who/ken/trust.html"&gt;Reflections on Trusting Trust&lt;/a&gt; – Ken Thompson&lt;/li&gt;&lt;li&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.6083"&gt;Lisp: Good News, Bad News, How to Win Big&lt;/a&gt; – Richard Gabriel&lt;/li&gt;&lt;li&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.29.363"&gt;An experimental evaluation of the assumption of independence in multiversion programming&lt;/a&gt; – John Knight and Nancy Leveson&lt;/li&gt;&lt;li&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.7565"&gt;Arguments and Results&lt;/a&gt; – James Noble&lt;/li&gt;&lt;li&gt;&lt;a href="http://c2.com/doc/oopsla89/paper.html"&gt;A Laboratory For Teaching Object-Oriented Thinking&lt;/a&gt; – Kent Beck, Ward Cunningham&lt;/li&gt;&lt;li&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.31.562"&gt;Programming as an Experience: the inspiration for Self&lt;/a&gt; – David Ungar, Randall B. Smith&lt;/li&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-2693519010095665632?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/2693519010095665632/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/10-artiklar-som-alla-borde-ha-last.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2693519010095665632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2693519010095665632'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/10-artiklar-som-alla-borde-ha-last.html' title='10 artiklar som alla borde ha läst (minst två gånger)'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4154409496193035412</id><published>2009-02-22T07:03:00.000-08:00</published><updated>2009-02-22T08:48:22.131-08:00</updated><title type='text'>Legacy code</title><content type='html'>Enligt wikipedia betyder "Legacy code" följande: &lt;span class="tyda_other_language"&gt;&lt;span style="font-style: italic;"&gt;source code that relates to a no-longer supported or manufactured operating system or other computer technology&lt;/span&gt;. Läser man Michel Feathers artikel "&lt;a href="http://objectmentor.com/resources/articles/WorkingEffectivelyWithLegacyCode.pdf"&gt;Working effectivly with legacy code&lt;/a&gt;" får man följande till livs: &lt;span style="font-style: italic;"&gt;The main thing that distinguishes legacy code from non-legacy code is tests, or rather a lack of tests&lt;/span&gt;. Michel Feathers hävdar att man inte behöver vänta på att support för koden ska försvinna, man kan skriva legacy code, alltså koden du ser på skärmen kan uppfylla definitionen innan du ens tryckt på sparaknappen eller kompilerat den första gången.&lt;br /&gt;&lt;br /&gt;Gammal kod är ofta svår att arbeta med. Ingen som längre jobbar med koden kommer ihåg varför man gjorde på ena eller andra sättet och ännu värre, det är inte någon som vet vad som är rätt eller fel längre, särskilt med hänsyn taget till eventuella förändrade krav från omvärden på vad koden ska göra. Detta är dock brister man kan se efter någon vecka i projekt som har fått börja från början. "Det är N som har skrivit koden, han vet hur den fungerar" är något&lt;/span&gt;&lt;span class="tyda_other_language"&gt; det man kan höra ganska snart in i ett projekt. Något som kan vara ett första tecken på att man nyproducerar Legacy code.&lt;br /&gt;&lt;br /&gt;Varför är då tester boten mot Legacy code? Tester skapar ett förtroende för att man kommer att få reda på om man förstör existerande funktionallitet och med det försvinner det största problemet med Legacy code, rädlan för att man förstör något som idag fungerar. Så Michel Feathers har säkert funderat på varför man ska vänta på att koden blir gammal och osupportad innan man kallar den för legacy code när det största problemet med legacy code kommer redan vid nyproduktion, rädslan för att ändra det som fungerar.&lt;br /&gt;&lt;br /&gt;Men om man nu sitter med ett projekt där det inte finns några tester och ingen längre kan säga hur de tänkte när de skapade koden. Tanken på att sätta sig och börja dokumentera existernade funktionallitet kanske är så upplyftande men på något sätt måste det göras. Hur ska man annars veta om den förändringen man gör inte påverkar annan funktionallitet på ett oavsiktligt sätt.&lt;br /&gt;&lt;br /&gt;Vi dokumenterar den existerande funktionalliteten genom att skriva tester, att sitta och klicka i applikationen är en syssla som människor är dåligt rustad för . Dessa tester är dock något annorlunda. De är inte till för att verifera att den existerande koden gör rätt utan har som enda syfte att upptäcka om den existerande funktionalliteten förändras. Om en metod för ett givet input returnerar true, så har testet som uppgift att tala om när samma input ger false. Hurvida det är rätt att returnera true för det givna inputet är inte viktigt. Det som är viktigt är att det är som koden levererar idag.&lt;br /&gt;&lt;br /&gt;Att skriva tester för en hel applikation är inte riktigt genomförbart dock. Vi måste försöka att titta på var det är vi ska göra vår förändring och sedan försöka att ringa en "trång punkt" genom vilken funktionalliteten styrs idag och testa utifrån denna trånga punkt. Syftet är inte att ge oss en komplett bild utan något som genom en rimlig arbetsinsats kan ge oss en relativt god chans att bli informerade om att vi har förändratat vi borde hållt tassarna borta från.&lt;br /&gt;&lt;br /&gt;Men nu när vi skrivit de tester som verkar rimliga har vi en uppgift till innan vi faktiskt kan påbörja den uppgift som är vårt faktiskta uppdrag. Vi bör refaktorera den existerande koden. Detta genom att bryta ut se till att variabler och metodnamn är vettigt döpta, bryta ut metoder och sist se om vi kan struktuerar klasserna på ett bättre sätt, tex genom att byta ut if/else mot polymorphism. För varje steg kör vi våra tester så att vi inte oavsiktligt har ändrat något.&lt;br /&gt;&lt;br /&gt;Nu är vi äntligen framme. Vi har betalat en del av den skuld som tidigare utvecklare belastat applikationen med och kan utifrån de tester vi skrivit steg för steg skriva om testerna till att testa den funktionallitet vi önskar att applikationen ska ha och till sist anpassa applikationen så att testerna börjar lysa grönt.&lt;br /&gt;&lt;br /&gt;Lät det krångligt? Att förändra kod till nya krav är inte alltid enkelt. Men man kan göra det på  ett sätt som ger dålig nattsömn och kräver magsårs medicin eller så försäkrar man sig genom att installera larm som kan upptäcka felaktigheter.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4154409496193035412?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4154409496193035412/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/legacy-code.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4154409496193035412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4154409496193035412'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/legacy-code.html' title='Legacy code'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-728372973197392487</id><published>2009-02-19T11:50:00.000-08:00</published><updated>2009-02-20T13:23:28.331-08:00</updated><title type='text'>Design Principles and Design Patterns fortsättning</title><content type='html'>Tyckte att det blev lite långrandigt så jag bestämde mig för att dela upp min sammanställning av Bob Martins - "Design principles and Design Patterns".&lt;br /&gt;&lt;br /&gt;Nu blir det hur man kan hantera beroenden moduler i en applikation.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Packet Cohesion Priniciples&lt;/span&gt;&lt;br /&gt;Tre sätt att resonera runt hur man ska förpacka sina moduler&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Release Reuse Equivalency Priciple (REP)&lt;/span&gt; - REP kopplar ihop releasehantering med återanvändning. De klasser som behövs för att kunna skapa en release av en modul ska grupperas tillsammans och därmed återanvändas tillsammans. Det gör det smidigt tex för en kund att veta att det har hänt tillräkligt med koden för att det ska vara idé att uppdatera även om han/hon bara är intresserad av en liten delmängd av de funktioner som kommer med releasen. &lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Common Closure Principle (CCP)&lt;/span&gt; - Klasser som ändras tillsammans bör förpackas tillsammans. Om man befinner sig i utvecklingsfasen så vill man inte hantera många olika moduler och hålla koll på vilka andra moduler som man är beroende och hur vida de modulerna ändrats på ett sätt som kräver ändring i den egna modulen. Därför minimerar man antalet moduler som behöver uppdateras för en releasecykel.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Common Reuse Principle (CRP) &lt;/span&gt;- Klasser som inte används tillsammans ska inte förpackas tillsammans. Varför ska man behöva uppdradera ett operativsystem bara för att få tillgång till en funktion? Förpacka därför bara det som används tillsammans för att inte tvinga på användaren en större förändring än nödvändigt.&lt;/li&gt;&lt;/ul&gt;De tre principerna ovan utesluter varandra. REP och CRP gör livet lite lättare för de som vill återanvända kod. CCP tenderar till att ge stora moduler medans CRP ger små. Som tur är vilken princip man väljer att förpacka modulerna inte skrivna i sten. Medans man utvecklar kanske man väljer att använda CCP och sedan när modulerna kanske man går mot något som är lättare för användarna av modulerna att använda som REP eller CRP.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Packet Coupling Principles&lt;/span&gt;&lt;br /&gt;De tre kommande principerna styr hur relationerna mellan olika modulerna ska fungera.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Acyclic Dependencies Principle (ADP)&lt;/span&gt; - Ganska enkel och självklar. Modulerna ska inte ha cykliska relationer, tex Modul A -&gt; Modul B -&gt; Modul C -&gt; Modul A. Tänk dig att ha dataproviders som är beroende på GUI. Ha någon som håller koll på att cykliska relationer inte smyger sig in i applikationen.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Stable Dependencies Principle (SDP)&lt;/span&gt; - SDP säger att man ska försöka att rikta sina beroenden mot det som är stabilt. Vad är då stabilt? Det som är svårt att förändra av olika skäl kan sägas vara stabilt. Den viktigaste faktorn för att en modul är stabil är att den har många andra moduler som är beroende på den. Ska man ändra i modulen så får man ändra på många andra ställen. Herr Martin ställer upp en enkel formel för att beräkna om en modul är stabil eller ej.&lt;br /&gt;Ca = Inkommande beroenden (klasser utanför modulen som är beroende på modulen i fråga)&lt;br /&gt;Ce = Utgående beroenden (klasser som är beroende på andra klasser utanför modulen)&lt;br /&gt;I = Instabilitet - Beräknas I =  Ce / (Ca + Ce)&lt;br /&gt;Så med formeln ovan kan vi säga att SDP betyder: Din modul ska ha högre beroenden än de den har sina beroenden på. Men ska alla moduler vara stabila? Självklart inte, vi vill ju att våra program ska kunna följa med ovärldens krav utan stora arbetsinsatser. &lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The Stable Abstractions Principle (SAP) &lt;/span&gt;- SAP är svaret på problemet som uppstår med SDP där det blir svårare och svårare att utföra förändringar desto fler beroenden modulen har. SAP säger att stabila moduler ska vara abstrakta, alltså inte ha någon implementation. Det ger oss frihet att förändra byta ut implementation utan att påverka modulen som alla andra beror på. Alltså ska de mest stabila modulerna vara abstrakta. Herr Matrin råkar ha en liten formel på att mäta detta också:&lt;br /&gt;Nc = Antalet klasser i modulen&lt;br /&gt;Na = Antalet abstrakta klasser/interface&lt;br /&gt;A = Abstrakthet(?) A = Na/Nc&lt;br /&gt;&lt;br /&gt;Om man jämnför A med den tidigare I så bör de följa varandra. En modul med högt I bör också ha ett högt N och en modul med lågt I bör ha lågt N.&lt;br /&gt;&lt;br /&gt;Det finns en ideallinje som I och A följer och man kan räkna på hur långt ifrån denna ideallinje en modul ligger med hjälp av följande formel:&lt;br /&gt;D = (A + I - 1) / sqrt(2) (ger ett värde mellan 0 - 0.7 ungefär) där värden närmare noll är bättre.&lt;br /&gt;&lt;br /&gt;Naturligtvis är detta bara beräkningar och inget man ska se som absoluta fakta. Men har man gjort värdena kan man välja att tro på dem eller säga att man har gjort val som gör dem missvisande. Men då har man ett värde att resonera runt vilket förmodligen är något bättre än att bara gissa.&lt;/li&gt;&lt;/ul&gt;Resten av dokumentet handlar om designpatters som jag tror alla är representerande i GOF bok som heter &lt;a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=pd_bbs_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1235164969&amp;amp;sr=8-1"&gt;Design Patterns&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-728372973197392487?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/728372973197392487/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/design-principles-and-design-patterns_19.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/728372973197392487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/728372973197392487'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/design-principles-and-design-patterns_19.html' title='Design Principles and Design Patterns fortsättning'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5588872318752124223</id><published>2009-02-16T11:15:00.000-08:00</published><updated>2009-02-19T10:29:48.674-08:00</updated><title type='text'>Design Principles and Design Patterns</title><content type='html'>Hittade &lt;a href="http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf"&gt;ett kul dokument&lt;/a&gt; som Bob Matrin skriv i början av 2000-talet. Känner igen mycket av innehållet från &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt; fast i kortare form. Tar upp några av sakerna där ifrån.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruttnade kod&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Jag har inte varit med i något projekt där man inte har försökt att utgå från de bästa av principer och sett fram emot hur bra allt ska bli. Hur alla problem man har haft i tidigare projekt ska lösas och man ska göra allt rätt en gång för alla. Men när projektet har pågått ett tag så har de rosafluffiga drömmarna gått i kras och projektet är samma gamla ruttna soppa som de alltid blir. Man tycker att man borde ha lärt sig. En liten tröst i sammanhanget kan vara att de flesta utvecklingsprojekt tycks gå samma väga. Goda intentioner som malts sönder och samman. Bob tar upp fyra symtom på ruttnande design:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Stelhet&lt;/span&gt; inträffar när varje förändring tycks sluta i att man har skrivit om halva applikationen. En förändring kräver en förändring någon annanstans som i sin tur behöver ytterligare en uppsättning med förändringar. När man ser att även små förändringar får veckor att försvinna vill man inte gärna ändra ens när det behövs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Skörhet&lt;/span&gt; inträffar när man utfört förändringar och man står inför en applikation som inte längre fungerar som den ska. Tillsynes helt orelaterade moduler slutar fungera pga ändringen. Vem vågar ändra när man vet att buggrapporterna kommer att hagla så fort man tagit applikationen i drift. Varje patch man gör tycks bara leda till fler problem än de fixade.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Orörlighet&lt;/span&gt; inträffar när man inte kan återanvända existerande kod trots att specifikationen borde passa som hand i handske. Det beror ofta på att modulen man ska använda har en stor ryggsäck i form av beroenden åt alla håll och kanter vars vikt överträffar vinsten i att återanvända den existerande funktionalliteten.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Tröghet&lt;/span&gt; kommer i två varianter, från design/arktektur och från utvecklingsmiljön. När trögheten kommer av design har man gjort vägval som kräver stora insatser om man ska göra "rätt". Då blir det ofta lätt att skriva ett hack eller två. Tröghet från utvecklingsmiljön kan vara långa kompileringstider. Då kan det tex vara frestande att checka in kod utan att ha kompilerat först. Dumt men frestande.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Vad är orsakerna till dessa symtom då? Enligt Bob Martin är förändrade krav den stora källan till att symptomen ovan uppstår. För att det ska bli riktigt bra så kanske man har utvecklare som ska lösa en uppgift under tidspress utan att känna till hur den befintliga arkitekturen är tänkt att fungera. Bit för bit löses de ursprungliga goda intentionerna upp till en ohanterlig massa likt en sönderkokt potatis. Men vi utvecklare kan ju inte gärna skylla på förändrade krav. Vi vet att krav förändras.&lt;br /&gt;&lt;br /&gt;Lösningen för att hantera förändrade krav är att hantera de beroenden som finns i koden. Nedan kommer några av de principer som föreslås i dokumentet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Open closed principle (OCP)&lt;/span&gt;&lt;br /&gt;Alla "moduler" ska vara öppna för att byggas ut men stängda för att modifieras. Låter lite motsägelsefullt men är en av de viktigaste principerna för objektorienterad systemutveckling. Man ska kunna förändra vad modulen gör utan att behöva förändra modulens kod. Nedan kommer några tekniker för att hantera OCP.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Dynamic polymorphism&lt;/span&gt; - Går kort och gott ut på att man ska definiera ett gränssnitt, tex ett interface som man sedan kan lägga till implementationer som löser de specifika uppgifter som olika omständigheter.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Static polymorphism&lt;/span&gt; - Genom användning av templates eller generics kan man bygga ut funktionalliteten utan att behöva röra den existerande koden (exemplet i pappret känns lite gammalt och jag ser dem mer eller mindre som likadana).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Genom att följa OCP kan vi skapa moduler som är lätta att bygga vidare på utan att man behöver ändra den existerande koden. Det är ett ideal som ibland kan vara svårt att nå men även om man bara delvis når målet är det något som gör din applikation betydligt enklare att underhålla. Det är alltid bättre om ändringar inte nästlar sig sin i existerande kod som fungerar.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;The Liskov Substitution Principle (LSP)&lt;/span&gt;&lt;br /&gt;Varje subklass ska kunna ersättas av sin basklass. Låter trivialt och med dagens moderna programmeringsspråk något som vi som vi får nästan gratis. Vi kan tex ta vilket objekt från en subklass och lägga det i en array typad för basklassen. Inget konstigt med det. Det finns dock några saker som vi fortfarande bör ha i bakhuvudet.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Cirkel/Oval dilemmat&lt;/span&gt; - Jag översätter detta till det något mer lätthanterliga Rektangel/Kvadrat. I skolan fick jag lära mig att en kvadrat är ett specialfall av en rektangel vars höjd och bredd råkar vara lika långa. Men så enkelt är det inte i programmeringens underbara värld. Om vi väljer att låta kvadrat vara en subklass till rektangel tvingar vi på en metod som en kvadrat inte har användning för. Höjd och bredd på en kvadrat är oviktigt, en längd på en sida räcker. Så för att kunna ha kvadraten som en subklass till rektangeln måste vi fuska till kvadraten så att om vi sätter höjden så kopierar vi det till bredden så att de alltid har samma värde. Men alternativet är inte mycket roligare. Om vi använder kvadraten som basklass kan vi inte manipulera rektangeln utan att behöva kolla vilken typ av objekt vi har och sedan kasta den till lämplig subtyp som vi sedan kan manipulera. Att ha rektangeln som basklass är lämpligare än kvadraten i detta fall. Nu tror vi att vi har tänkt på allt men betänk följande testmetod:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public testSquare(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Rectangle rectangle = new Square();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  rectangle.setHeight(5);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  rectangle.setWidth(3);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  AssertEquals(rectangle.getHeight(), 5);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  AssertEquals(rectangle.getWidth(), 3);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hur ska testet gå igenom om vi dolt baken kulisserna kopierar bredden till höjden på kvadraten för att lösa vår arvsheariki?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Berättelsen ovan illustrerar att Rektangel enligt RSP är en dålig basklass för en Kvadrat, i alla fall om man vill sätta höjd och bredd. Om man sent i utvecklingscykeln hittar ett dyligt misstag kan det vara väldigt svårt att rätta till och man får börja skriva diverse mer eller mindre fula undantag från regeln vilket inte direkt gör koden lättare att förstå för den som ska läsa den vid en senare tidpunkt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Dependency Inversion Principle (DIP)&lt;/span&gt;&lt;br /&gt;Många tekniker använder DIP (COM, CORBA, EJB för att nämna några). Om OCP är målet som ska uppnås kan man säga att DIP är den primära metoden att nå målet. DIP säger att man ska använda interface eller abstrakta klasser i sina gränsnitt i stället för att anropa de mer rörliga konkrekta klasserna direkt. Om man använder de konkreta klasserna är det svårt att ändra den underliggande funktionalliteten utan att behöva ge sig in och ändra i redan fungerande kod. Om det skulle uppstå en situation tex av licensskäl som innebär att du måste byta ut en existerande modul så ska du inte behöva ändra i din existerande kod utan bara plugga in den nya modulen mot det existerande gränssnittet. Genom att använda tex en Abstract Factory kan du dessutom i runtime bestämma vilket implementation av interfacet som ska användas.&lt;br /&gt;&lt;br /&gt;Det stora motivet för DIP är att skydda sig mot förändringar och jag tycker nog att man bör skriva så många klasser som möjligt mot interface, men inte alla. Där man kan lita på att det inte kommer att uppstå förändringar är det naturligtvis inte nödvändigt att förvänta sig förändring. Problemet är att det inte är så mycket man kan lita på här i världen. För en .Net-utvecklare kanske det verkar onödigt att dölja hanteringen av sökvägar bakom ett interface för att de alltid har börjat med C: men nu med Mono kanske det inte är så självklart längre.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Interface Segregation Principle (ISP)&lt;/span&gt;&lt;br /&gt;Tänk att du har en webtjänst med tio metoder. Denna webtjänst används av tre andra applikationer (klienter). Om du nu måste ändra i någon metod för att stödja ett nytt behov hos en av klienterna så måste du ändra på de andra två klienterna också för att de alla ser samma gränssnitt mot tjänsten. Ingen rolig tanke tycker i alla fall jag.  En bättre metod hade varit att dölja din webtjänst bakom tre stycken gränssnitt som kan förändras oberoende av varandra. Om en ändring sker i webtjänsten så kommer den bara att synas för de som får tjänsten publicerad genom sitt klientgränssnitt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5588872318752124223?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5588872318752124223/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/design-principles-and-design-patterns.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5588872318752124223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5588872318752124223'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/design-principles-and-design-patterns.html' title='Design Principles and Design Patterns'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-6800218175307368123</id><published>2009-02-15T04:48:00.000-08:00</published><updated>2009-02-16T10:45:19.502-08:00</updated><title type='text'>T1-T9</title><content type='html'>Kanske borde dela upp denna men det är de sista reglerna. De berör testning och ger råd om hur man ska förhålla sig till dem. Jag får skriva detta ganska närma vad som står i boken då min personliga erfarenhet med att jobba med tester inte är så hög jag skulle önska. Tyvärr är tester något som projektledare tror att det är okej att strunta i tron om att vi programmerare skulle leverera mera fungerande kod som kan tas i produktion.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T1: Otillräkliga tester&lt;/span&gt;&lt;br /&gt;Det är en fråga som det är väldigt enkelt att ge ett enkelt svar på. Om det existerar vägar genom koden som inte har utforskats med hjälp av tester vet du inte att din kod fungerar som den ska. Framför allt vet inte andra utvecklare att de måste ta upp en webapplikation, skriva i sökfältet, dubbelklicka på listan och sedan ändra i postnumret och sedan spara för att han/hon ska se att just den funktionen fortfarande fungerar efter de sista ändringarna. Så även om du vet hur du ser att funktionen fungerar så är testerna även en specifikation hur funktionen ska fungera.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T2: Använd test-täcknings verktyg&lt;/span&gt;&lt;br /&gt;Tog upp lite av detta på T1 men vi människor är inte gjorda för vissa typer av uppgifter. Använd därför ett verktyg för att påvisa vad som är testat och viktigare, vad som inte är testat.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T3: Strunta inte i triviala tester&lt;/span&gt;&lt;br /&gt;De är enkla att skriva och värdet i form av dokumentation av hur de ska fungera är ovärderligt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T4: Ett ignorerat test är en fråga om tveksamheter&lt;/span&gt;&lt;br /&gt;Om du inte har skrivit ett test runt en funktion visar du att du inte har förstått hur funktionen ska fungera och lämnar dessutom de andra utvecklarna med ett stort frågetecken om hur funktionen ska uppföra sig.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T5: Testa gränsfall&lt;/span&gt;&lt;br /&gt;Vi har gått igenom gränsfall tidigare. Att testa att gränsfallen fungerar är extra viktigt. Att metoden fungerar i de flesta fall är inte tillräkligt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T6: Testa mer runt buggar&lt;/span&gt;&lt;br /&gt;Det finns ett ordspråk som säger att en olycka sällan är ensam. Det samma gäller för utvecklare. En trött utvecklare som har missförstått något har förmodligen inte bara gjort ett fel. Skriv inte bara ett test för att verifiera buggens existens. Undersök testtäckningen på näraliggande kod och se till att den är testad. Det är ett betydligt effektivare sätt att upptäcka fel än att invänta nästa bugg och åter igen sätta sig in i vad det är koden antas leverera.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T7: Se mönster för varför tester falerar&lt;/span&gt;&lt;br /&gt;Om du har ett stort antal tester kan man ofta se mer  mönster som man inte har förstått att man måste testa för. Tex kanske man har en begränsning på hur lång en textsträng får vara som man inte var medveten om när man skrev testerna initialt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T8: Testtäckning påvisar mönster&lt;/span&gt;&lt;br /&gt;Varför man testat viss kod men inte annan kod kan visa på intressanta mönster hur utvecklarna tänker. Att viss kod kanske anses vara så stabil att man inte behöver testa på den kan vara en källa till att andra tester falerar. För man vet ju trots allt inte att koden fungerar.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T9: Tester ska vara snabba&lt;/span&gt;&lt;br /&gt;Detta är nog den viktigaste reglen för testerna. Om inte testerna är snabba är det ingen som vill köra dem. Det är också den enskilt viktigaste anledningen till varför man inte ska använda xUnit (jUnut, nUnit etc) till att skriva integationstester som springer igenom hela applikationen. Desto mindre varje enskilt test testar desto snabbare är det och desto mindre är risken att någon utvecklare tröttnar på att vänta på dem och slutar att köra testerna.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-6800218175307368123?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/6800218175307368123/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/t1-t9.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6800218175307368123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6800218175307368123'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/t1-t9.html' title='T1-T9'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-6639057331679688617</id><published>2009-02-14T11:14:00.000-08:00</published><updated>2009-02-14T12:11:53.193-08:00</updated><title type='text'>N1 - N7</title><content type='html'>Nu när vi är klara med de generella reglerna så tittar vi på de som rör namnsättning.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N1: Använd beskrivande namn&lt;/span&gt;&lt;br /&gt;Vi har alla sett kod som ser ut ungefär så här:&lt;br /&gt;&lt;br /&gt;public void doCalculation(){&lt;br /&gt;  i = j + k;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Det är kod där man kan fråga sig vad för beräkning doCalculation gör, letar upp den sista siffran i PI? Variablerna i, j och k säger inte heller så mycket om varför de ska finnas. Bättre då hade varit att skriva metoden så här (om nu metoden skulle beräkna löner)&lt;br /&gt;&lt;br /&gt;public void calculateTotalSalary(){&lt;br /&gt;  totalSalary =  baseSalary + overTime;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Här behöver ingen fundera på vad vare sig variablerna eller metoden har för syfte.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N2: Välj rätt namn på rätt abstraktionsnivå&lt;/span&gt;&lt;br /&gt;Denna är lite lurig. När ska man kalla ett telefonnummer för telefonnummer och när är det en kopplingssträng eller riktnummer? Att fundera på hur abstrakt namnsättningen ska vara är oerhört viktigt då det begränsar fantasin på läsaren om vad en funktion kan ha för användningsområde. Kopplingssträng skulle kunna utnyttja vilken tjänst som helst (Skype, telefon eller två burkar med snöremellan. Telefonnummer har begränsat användningsområdet till bara telefonnummer. Ibland är det rätt att använda väldigt specifika namn på saker och ting och ibland är det bra att vara öppen för att det kan komma andra implementationer än den man ska skriva just nu. Att välja rätt är inte enkelt men oerhört viktigt. Fundera ett varv extra på varje namn om det är tillräkligt generellt eller inte.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N3: Använd standardiserad vokabulär&lt;/span&gt;&lt;br /&gt;Att använda ord för företeelser som alla känner igen är viktigt i alla språk. Kebab med deg kanske går att få till pizza med lite fantasi men det hade varit lättare att förstå om jag sagt pizza direkt. Om det heter webcontroll eller taglib är i sig självt oviktigt. Vad de som ska läsa din kod känner till det som är däremot viktigt. Om man pratar om en AbstractFactory  se då till att det är definitionen från GOF du hänvisar till för det är sannolikt den som de flesta känner till. Om du gör ett projekt för styrning av mjölkmaskiner se då till att du använder ord från den domänen i stället för att hitta på egna uttryck. I stora projekt kan man kanske tillåta sig att ha en uppsättning med egna uttryck för ett antal företeelser som är specifika för projeket men i övrigt använd uttryck som alla kan googla definitionen på.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N4: Otvetydiga namn&lt;/span&gt;&lt;br /&gt;När man döper saker och ting ska man vara nogrann med att metoden inte kan tolkas till att den gör något annat än den gör. Metodnamn som uttrycker sig i svepande ordalag, tex rename säger inte så mycket om vad det är som ska döpas om eller hur objektet ska döpas om. Så var tydlig.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N5: Använd långa namn på stora "scope"&lt;/span&gt;&lt;br /&gt;Att använda en "i" som ett variabelnamn kan vara ok för väldigt korta metoder där betydelsen av "i" kan framgå tydligt ändå. Men i större sammanhang behöver man längre mer beskrivande namn som klarar av att beskriva den komplexitet som kommer med större sammanhang.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N6: Koda inte koden&lt;/span&gt;&lt;br /&gt;Detta är min favorit sedan jag började programmera i .Net-miljö där standarden (i alla fall på min arbetsplats) är att skriva variabler med m_ och s_ och prefixa interface med I. För mig är detta Ungersk kodning som är precis lika illa som btnMyTextStr. Om man nödvändigtvis måste koda sina variabler gör det som ett suffix och så långt bort från de publika gränssnitten som möjligt, tex på ett interface Company där den implementerande metoden skulle kunna kodas som CompanyImpl. Fast det bästa är om man kan ge riktiga namn utan att behöva lägga på koder. Unvik den Ungerska sjukan med all kraft.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N7: Namn ska beskriva sidoeffekter&lt;/span&gt;&lt;br /&gt;Har ni stött på en metod som ser ut något i still med detta:&lt;br /&gt;&lt;br /&gt;public void setName(String name);&lt;br /&gt;&lt;br /&gt;Men i stället för att bara sätta ett namn så sparas objektet också i databasen. Om du måste göra metoder som gör två saker, se då till att det framgår av namnet. SetNameAndSave skulle ha varit ett bättre namn som inte ger utvecklarna några överraskningar.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-6639057331679688617?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/6639057331679688617/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/n1-n7.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6639057331679688617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/6639057331679688617'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/n1-n7.html' title='N1 - N7'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4098399215705457624</id><published>2009-02-14T03:04:00.000-08:00</published><updated>2009-02-14T12:13:28.078-08:00</updated><title type='text'>G31-G36</title><content type='html'>Nu avslutar vi de generella reglerna (där av G). Det har varit tungt att ta sig igenom dem. Det som återstår efter detta inlägg är namnsättning och tester (kanske javareglerna också men de känns lite för specifika för min smak).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G31: Dolt beroende av tid/ordning&lt;/span&gt;&lt;br /&gt;Ofta är metodanrop beroende av den ordning de anropas. Att döpa metoderna till first, second och third är kanske inte riktigt idealiskt för att hjälpa läsaren att förstå vilken ordning som anropen måste göras. Dessutom är det inget som faktiskt hindrar en programmerare från att anropa second före first. Bättre att first returnerar ett objekt av någon typ som  second kan använda och att second i sin tur returnerar ett objekt som thrid tar som argument. Dessutom behöver man inte hänvisa till någon konvention (G27) utan tvingar användaren att följa anropsordningen, eller något som i alla fall tvingar den anropande klassen att se till att ha sina saker i ordning.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G32: Var inte godtycklig&lt;/span&gt;&lt;br /&gt;Ha en anledning till varför du strukturerar din kod på ett speciellt sätt och se sedan till att koden på ett tydligt sätt reflekterar den strukturen. Om du i kod lyckas komunicera varför dina val är som de är kommer andra utvecklare följa ditt exempel. Om din strukturen är otydlig och svävande kommer känna att de kan göra på andra och för dem bättre sätt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G33: Kapsla in gränsfall&lt;/span&gt;&lt;br /&gt;Gränsfall är svåra att hålla koll på. Se därför till att de enbart hanteras på ett ställe och inte sprider sig som en pest genom koden. Ett enkelt exempel är en koll där första objektet i en lista inte ska kolla om det finns något tidigare objekt i listan. Siffran noll som värde på att det är den första ska vara dold bakom en variabel tex döpt till firstObject (G25). Metoden som faktiskt vet att det är skillnad på första och andra objektet i listan bör också bara finnas på ett ställe. Övrig kod ska inte behöva veta att det är skillnad i hanteringen, det är en implementationsdetalj.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G34: Funktioner går enbart en abstraktionsnivå ner&lt;/span&gt;&lt;br /&gt;Denna har en del med G6 att göra och jag återanvänder bilexemplet. Bilen står still i en korsning och ska svänga vänster. Metoden för att hantera denna situaion ska öka farten och styra åt vänster och sedan när tillräklig riktningsförändring skett sluta svänga. Det är alltså tre anrop till tre andra metoder som tar hand om detaljerna med att bestämma bränsleblandning, mängd bränsle som ska sprutas in i cylindrarna och annat som faktiskt behövs för att bilen ska fungera. En enkel regel för att se när man går ner en abstraktionsnivå i koden är att man använder val eller snurror. Det som händer inne i valet eller snurran är oftast på en annan abstraktionsnivå och hör där med hemma i en egen metod och håller där med den första metoden kvar på "sin" abstraktionsnivå. Detta tillsammans med G30 gör det betydligt svårare att skriva komplicerad kod.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G35: Håll konfigurerbart data på hög abstraktionsnivå&lt;/span&gt;&lt;br /&gt;Konfiguration är viktigt, att gömma den typen av information långt ner är inte helt lyckat. Den ska vara enkel att hitta och enkel att förändra. Att gömma konfigurerbart data där det faktiskt används innebär att läsaren får leta länge efter hur man ändrar tex en ipadress till en webservice.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G36: Undvik beroenden på beroende&lt;/span&gt;&lt;br /&gt;I normalfallet vill vi att vår kod ska känna till så lite som möjligt om annan kod. Betänk följande metod i en klass:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void aMethod(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;a.getB().getC.doSomething()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Den här klassen har en medlemsvariabel som heter a. Vår klass känner till att a har en metod som heter getB och det är helt normalt. Men att klassen känner till att det som returneras från getB() också har en metod som heter getC() och att man på den kan anropa doSomething() är ganska illa. Varför det är dåligt. Om man nu skulle vilja förändra getA() så att den i stället för att returnera ett objekt som har en metod som heter getB() returnerar ett objekt som inte har den metoden så måste du även ändra på alla ställen där man gjort en anropskedja som ovan. Hur löser man problemet då? I första steget använder vi G19 (förklarande variabler) så att det går att se vad getA() och getB() och getC() returnerar för något. Nästa steg är att undvika duplicering och bryta ut anropskedjan så att den bara existerar på ett ställe. Det tredje steget är lite svårare men det går ut på är att steg för steg korta ner kedjan genom att i stället för att anropa getA() anropa doSomething() i som i sin tur anropar den del av kedjan som är kvar och sedan upprepar man tills kedjan inte längre existerar. Ser att texten blir knölig att läsa så jag skriver ett kodexempel:&lt;br /&gt;&lt;br /&gt;// i vår klass&lt;br /&gt;public void aMethod()&lt;br /&gt;a.doSomething();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// i klassen som som objektet a kommer ifrån&lt;br /&gt;public void doSomething(){&lt;br /&gt;b.getC().doSomething();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Här har jag tagit bort ett steg ur anropskedjan i första exemplet. Det kan dock bli många metoder i en del klasser om de ska ta hand om anrop den här vägen så det kan kan ibland vara idé att implementera speciella klasser som får vara en punkt i applikationen som kanske har lite mer kunskap om ett antal klasser än de borde ha.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4098399215705457624?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4098399215705457624/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g31-g36.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4098399215705457624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4098399215705457624'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g31-g36.html' title='G31-G36'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-7465854484110361318</id><published>2009-02-13T11:58:00.000-08:00</published><updated>2009-03-03T00:13:55.489-08:00</updated><title type='text'>G26 - G30</title><content type='html'>Inte många kvar på G efter den här...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G26: Var exakt&lt;/span&gt;&lt;br /&gt;Den här handlar om att inte slarva och göra halvhjärtade val. Om du tex fyller en ArrayList med ett antal värden och sedan sak returnera denna så bör du fundera på om returntypen faktisk ska vara ArrayList. Kanske det är bättre att returnera bastypen List. Det kanske inte är så att du vill att en anropande klass ska kunna modifiera listan så en enumeration kanske är bättre. Om du returnera en List måste du implementera din metod för att faktiskt kunna hantera att listan ändras. Om du returnera ArrayList så måste du ha en anledning till att visa den implementationsdetaljen. Så fundera på hur du vill att din metod ska användas och tänk igenom de konsekvenser dina val får.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G27: Struktur över konvention&lt;/span&gt;&lt;br /&gt;Dokument med konventioner kan vara bra ibland. Men att hindra de andra utvecklarna (och sig själv) från att missbruka koden är bättre. Får man inte anropa databaslagret från GUI-lagret se då till att det inte går genom att göra klasserna onåbara från GUI-lagret.  Om dina dataproviders måste ha en transaktion kontrollera  då det i koden så att de som försöker att använda dem får stora fula felmeddelanden om transaktionen inte är på plats. Struktur vinner över konvention alla gånger av alla (nästan).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G28: Dölj boolska uttryck&lt;/span&gt;&lt;br /&gt;Betänk följande metod:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void MyMethod(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if( a == running &amp;amp; b &lt;&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    // do something&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;och jämnför med följande:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void MyMethod(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  if(isTemperatureSafe()){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    // do something&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Boolska uttryck blir snabbt oläsbara och även om de är enkla och där med läsbara så är syftet av &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;variable &gt; 0&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; självklart alla gånger. Vad betyder det att värdet är större än noll? Kanske hade varit bättre med att ha en metod som faktiskt talar om vad vi testar.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:georgia;" &gt;G29: Undvik negativa booska uttryck&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Vi människor har lite svårare att ta till oss negativa uttryck. Inte sant är svårare att förstå än falskt. Att använda de små språkkonstrukten som utropstecken (!) för att markera att uttrycket är falskt gör inte saken lättare. Försök att hitta uttryck som inte behöver använda negationer och dölj uttroptecken bakom metoder som låter dig skriva i klartext.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:georgia;" &gt;G30: Funktioner bör göra en sak&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Denna är viktig. En metod ska göra en av två saker. Ta ett beslut eller utföra EN uppgift, till exempel populera ett objekt med värden från ett argument. Metoder som tar flera beslut är svårare att förstå. Metoder som tar ett beslut på om om argumentet är användbart, sedan populerar ett objekt och sedan tar ett annat beslut på om objektet är bra mycket svårare att förstå. Kanske så att man kan argumentera för att utvecklare är smartare än genomsnittsbefolkningen men det är förmodligen bättre ekonomi i att låta programmerare syssla med komplexa problem än komplex kod.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-7465854484110361318?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/7465854484110361318/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/inte-manga-kvar-pa-g-efter-den-har.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7465854484110361318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7465854484110361318'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/inte-manga-kvar-pa-g-efter-den-har.html' title='G26 - G30'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-4923325347908280260</id><published>2009-02-13T11:01:00.000-08:00</published><updated>2009-03-03T00:14:31.365-08:00</updated><title type='text'>G21 - G25</title><content type='html'>Mer mer mer mer ... aldrig tar de slut..&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G21: Förstå algoritmen&lt;/span&gt;&lt;br /&gt;Ofta kan man se klasser och metoder där det ser ut som om något spejat skärmen med if-satser och boolska variabler. Detta kan vara ett tecken på att personen som skrivit koden har skrivit något som kanske fungerar men igentligen inte har någon större koll på vad koden faktiskt ska göra.  Naturligtvis är det ofta så att man inte har riktigt koll på hur man ska lösa sin uppgift och mer eller mindre testar sig fram mot ett resultat och det är inget fel med det. Men innan du anser dig vara färdig refaktorera koden till något som faktiskt går att förstå och som faktiskt visar att du har förstått vad du gjort.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G22: Gör logiska beroenden fysiska&lt;/span&gt;&lt;br /&gt;Denna står i lite i motsatsförhållande till G13. Den är inte helt enkel att förklara och jag stjäl exemplet i boken då jag inte lyckas komma upp med ett eget. Exemplet beskriver en utskriftfunktion som där den anropande klassen bestämmer hur många rader som ska skrivas ut på en papper genom att själv bestämma när sidbrytningarna ska ske i stället för att tala om för utskriftsklassen att den borde lägga in en sidbrytning enligt ett visst intervall. Detta innebär att utskriftklassen har ett logiskt beroende på den anropande klassen. Det hade varit bättre att skriva in detta i utskriftklassen... Ja.. inte helt enkel...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G23: Föredra arv före if/else eller switch&lt;/span&gt;&lt;br /&gt;Jag om denna första gången i &lt;a href="http://www.pragprog.com/the-pragmatic-programmer"&gt;Pragmatic programmer&lt;/a&gt; under namnet "Don't ask, tell" och säger att man inte ska ta beslut efter vilket tillstånd en klass befinner sig i genom att fråga klassen vilket värdet variablen "type" har. I stället ska man när man skapar objektet ta beslut om vilken subtyp klassen ska vara och sedan be klassen "göra sin sak". Ser ni långa haranger med if/else som jämnför en variabel i klassen med ett antal värden är det sannolikt ett tillfälle där en polymorfisk lösning skulle vara bättre. If/else-satserna är dessutom lätta att klippa och klistra och blir där med svåra att underhålla.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G24: Följ konventioner enligt standard&lt;/span&gt;&lt;br /&gt;Kodkonvention är inte något man skriver på varje företag. Sun har en kodkonvention för java och jag antar att Microsoft har en för C#. Följ dessa. Om ni tar in en konsult så ska de känna igen sig och om du byter arbetsplats ska du inte behöva lusläsa ett dokument för att vara säker på att man gör rätt. Om det finns frågetecken ska den existerande koden i projektet vara grund. Detta förutsätter naturligtvis att alla i projektet är rimligt vuxna och förstår att det igentligen inte spelar någon roll var man sätter krusidullparanteserna så länge alla sätter dem på samma ställe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G25: Ersätt magiska nummer med konstanter&lt;/span&gt;&lt;br /&gt;Visst har vi alla funderat på varför en variabel är satt till 1 eller kanske 0 eller -1 eller i värsta fall till 217? Siffran som bara står där mitt i koden utan någon förklaring som något magiskt som alla bara borde förstå. Ersätt dessa magiska konstanter i koden med riktiga konstanter som har fått bra tydliga namn. Detta gäller naturligtvis inte bara för siffror utan även för text.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-4923325347908280260?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/4923325347908280260/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/mer-mer-mer-mer.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4923325347908280260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/4923325347908280260'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/mer-mer-mer-mer.html' title='G21 - G25'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-2356729606435382644</id><published>2009-02-11T12:04:00.000-08:00</published><updated>2009-02-11T13:10:55.586-08:00</updated><title type='text'>G16 - G20</title><content type='html'>Inte så mycket att säga om... G fortsätter&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G16: Kodat uppsåt&lt;/span&gt;&lt;br /&gt;Kod ska i möjligaste mån beskriva vad det är den gör. Att då skriva saker som m_variabel, eller strNameBtn är inte speciellt mycket till hjälp idag. En gång i tiden var man tvungen att använda förkortningar av olika slag för att man hade ett begränsat antal tecken att använda vid namngivning men idag existerar inte den anledningen. Förr hade man inte en IDE som Netbeans eller Eclipse som kan visa med färger om en variabel är lokal för metoden eller ej (vilket iofs borde vara uppenbart om man inte gjort långa oläsbara metoder). Låt din kod beskriva vad koden försöker att göra. Undvik att använda koden till att gå runt tekniska brister i din utvecklingsmiljö.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G17: Felaktigt placerat ansvar&lt;/span&gt;&lt;br /&gt;Den här punkten blir kanske lite flummig men det är nog den som är svårast att skriva något konkret om. Vad är det som gör att man placerar en variabel i den ena klassen eller den andra eller kanske till och med skapar en speciell klass för att hålla variabeln? I första hand handlar det om att placera sig in i läsarens position. Att försöka förstå var någon annan skulle förvänta sig att hitta variabeln i fråga. Det man bör försöka att unvika är att bli "smart" och hitta på smarta sätt. Som sagt.. en något flummig punkt men nog så viktig. Läs boken så förstår ni nog förhoppningvis denna bättre än vad jag har gjort. :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G18: Olämpligt användning av static&lt;/span&gt;&lt;br /&gt;Man skulle kunna tro att alla metoder som inte använder någon av klassens lokala variabler skulle vara lämpliga att göra static. Då skulle andra klasser kunna utnyttja den existerande funktionalliteten och man skulle kunna öka återmvinningen av kod. Dessvärre är det inte riktigt så enkelt. Underhåll försvåras av att man inte kan ärva från klassen i fråga för att lägga till funktionallitet. Tester blir svåra att skriva om den statiska metoden i sin tur anropar andra statiska metoder. Faktum är att det ska finnas mycket tydliga skäl till när en metod ska vara statisk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G19: Använd förklarande variabler&lt;/span&gt;&lt;br /&gt;Om du ska skriva en metod utför ett flertal operationer är följande kod inte speciellt enkel att förstå.&lt;br /&gt;&lt;br /&gt;public int calculateActualSalary(){&lt;br /&gt;  return getSalary() + addOverTime() - getTaxes()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Hur mycket påverkade addOverTime()? Vad är det för objekt som har en metod som heter withDrawTaxes()? Det bättre sättet att implementa metoden hade varit genom att visa vad som händer med hjälp av förklande variabler.&lt;br /&gt;&lt;br /&gt;public int caculateActulSalary{&lt;br /&gt;  int salary = getSalary();&lt;br /&gt;  int salaryWithOverTime = salary + addOverTime();&lt;br /&gt;  int salarayWithOverTimeAndTaxesRemoved = withOverTime - getTaxes();&lt;br /&gt;  remove salarayWithOverTimeAndTaxesRemoved;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Det blir några rader extra med kod men så mycket lättare att förstå vad det är som faktiskt händer. Ni kan säkert komma upp med bättre exempel där det skulle ha underlättat om man kunnat läsa ett tydligt bra namn på en variabel halvvägs in i beräkningen.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G20: Funktionsnamn ska säga vad de gör&lt;/span&gt;&lt;br /&gt;Betänk följande:&lt;br /&gt;&lt;br /&gt;Date date = Date.today.add(5);&lt;br /&gt;&lt;br /&gt;Vad gör add-metoden ovan? Den lägger till något men vad? 5 sekunder eller 5 år? Låt inte den som ska läsa din kod behöva fundera på vad dina metoder faktiskt gör utan skriv det tydligt i metodnamnet. I exemplet ovan hade det varit bättre att ha kallat metoden för addDays eller addYears eller vad nu metoden ovan faktiskt gör.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-2356729606435382644?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/2356729606435382644/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g16-g20.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2356729606435382644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/2356729606435382644'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g16-g20.html' title='G16 - G20'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-8049565153133000475</id><published>2009-02-07T03:45:00.000-08:00</published><updated>2009-02-09T12:42:28.032-08:00</updated><title type='text'>G11 - G15</title><content type='html'>Nästan halvvägs på G.....&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G11: Inkonsekvens&lt;/span&gt;&lt;br /&gt;Att inte överraska de som ska läsa din kod är inte oviktigt någonstans. Därför ska man följa de konventioner som finns (och gudarna ska veta att det är tråkigt att göra ibland). Så trots att denna blogg (eller ännu bättre Bob Martins bok) kan ge idéer om vad som är bra och vad som är mindre bra. Börja inte bara att följa regerna här för det kommer att förvirra de som inte förstår varför man gör på ena eller andra sättet. Det gäller inte bara det jag skrivit här utan rent generellt. Använder ni factories för att skapa alla domänobjekt sluta inte använda dem för att du har ett smarare sätt att göra det på. Det är tyvärr inte alltid så att det är rätt att använda de bästa lösningarna.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G12: Skräp&lt;/span&gt;&lt;br /&gt;C5, G9 m fl handlar om skräp. Skräp som är i vägen och hindrar dig från att göra ditt jobb. Skräp som du måste lägga tid på helt i onödan. Så jag upprepar vad jag skrivit tidigare. Bort med skiten. Versionhanteringsystemet ska vara tillräkligt bra för att enkelt låta dig titta tillbaka i tiden om skräpet faktiskt skulle visa sig vara något användbart. Men det är versionshanteringsystemet uppgift och inget som ska ligga som kommentarer, död kod eller vilken annan anledning ni kan komma på för att låta skräpet ligga i koden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G13: Artificiella kopplingar&lt;/span&gt;&lt;br /&gt;Kod som inte har faktiska beroenden på varandra ska inte vara sammankopplade. Det kan finnas många anledningar till att att man kopplar ihop två klasser fast de egentligen inte har har med varandra att göra. En url till en databas kan vara smidigt att återanvända där den ligger. Problemet är att man ger en klass kunskap om en annan klass en inte har något med att göra, förutom den där lilla konstanten. Det skulle vara bättre att upprätta en separat klass med konstanter som båda klasserna klasserna kan använda. Då har man inte skapat en artificiell koppling mellan de två klasserna som inte har med varandra att göra.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G14: Funktionsavundsjuka&lt;/span&gt;&lt;br /&gt;Feature envy låter mycket bättre men ska man skriva på svenska så... Metoder i en klass ska i första hand manipulera variabler i den egna klassen. När en metod manipulerar variabler (tex med hjälp av getters och setters) i en annan klass man kan säga att den första klassen önskar att den hade de där bra variablerna som den andra klassen har. Denna regel handlar i första hand om ansvarsfördelning. Varför har en klass just de variabler som den har varför ligger de inte i en annan klass. Det finns naturligvis tillfällen där det är lämpligt att bryta mot denna regel men du bör fundera ett var extra när du ser en klass som verkar avundsjuk på en annan.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G15: Val genom argument&lt;/span&gt;&lt;br /&gt;Man kan tycka att det är smidigt med en metod som löser flera uppgifter. Dock metoder inte göra mer än en sak och i stället göra det bra och på ett förståligt sätt. Booleska argument är ofta en tydlig signal på att metoden utför flera uppgifter och borde rent generellt brytas isär till två metoder. Det blir lättare att förstå vad det är som händer när man slipper fundera på vad olika inputargument ska ställa till med. Om man behöver en metod för att välja mellan två olika beräkningar så låter man en metod göra valet och andra metoder får stå för själva beräkningen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-8049565153133000475?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/8049565153133000475/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g11-g15.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8049565153133000475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8049565153133000475'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g11-g15.html' title='G11 - G15'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-1963795024614591560</id><published>2009-02-07T02:59:00.000-08:00</published><updated>2009-02-07T03:39:18.731-08:00</updated><title type='text'>G6 - G10</title><content type='html'>Om man nu trodde att det skulle vara nära slutet nu så har man fel... G6 till G10&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G6: Kod i fel abstraktions nivå&lt;/span&gt;&lt;br /&gt;Vi människor är duktiga på att blanda abstraktionsnivåer. Ta tex när vi kör bil så kan de flesta klara av uppgiften att styra bilen med gaspedal, broms och ratt. Dessutom gör vi en uppgift som inte har direkt med att framföra bilen. Vi reglerar varvtalet på motorn med hjälp av växelspaken. Tänk efter nu. Många bilar har automatlåda så varför har vi en växellåda. Att behöva lyssna efter vilket varv motorn har måste rimligtvis vara en distraktion från de uppgifter som rimligtvis måste vara viktigare, som att hålla bilen på vägen. Samma regel gäller när vi skriver klasser och API:er. Vi ska inte förvirra användarna genom att ge dem möjligheter att utföra perifiera uppgifter. Med metoder så ska vi bryta ut privata metoder tex för att hantera loopar och kompilicerade if.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G7: Klasser beroende av sina arvingar&lt;/span&gt;&lt;br /&gt;Denna regel får inte följas för bokstavstroget. Det finns undantag som vid användandet av Template-method där man faktiskt vill att subklassen ska anropas från basklassen. Men har man inte en riktigt bra motivation som i Template-method-fallet så är det dålig karma att bas-klasserna har beroenden i sina subklasser. Beroendet mellan bas och subklass bör vara enkelriktat.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G8: För mycket information&lt;/span&gt;&lt;br /&gt;Det är lätt att låta en klass göra allt för att den redan finns och det inte är något extra arbete med att fundera vad man faktiskt vill att klassen ska utföra och ännu viktigare än vad den inte ska utföra. Den generella regel är att desto mindre en klass visar i sitt publika api desto bättre. Desto färre metoder en klass har desto bättre. Desto färre variabler en klass har desto bättre.  Kan man hålla klasserna små tenderar de till ha färre beroenden och där med vara lättare att förändra. Splitta klasser som är stora och svåra att hantera till något som är lätt att hantera.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G9: Död kod&lt;/span&gt;&lt;br /&gt;Precis som med C5. Det som inte används ska inte finnas i den aktiva kodbasen. Punkt slut. If-satser som inte kan inträffa. Metoder som inte anropas. Allt ska bort. Det är distraktionen och programmering är tillräkligt svårt utan att bli distraherad av skräp.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G10: Vertikalt avstånd&lt;/span&gt;&lt;br /&gt;Denna handlar om hur man ska placera kod i förhållande till annan kod. Grundregeln är enkel. Allt ska vara så nära som möjligt från där det används. Jag upprepar det som står i boken mer eller mindre rakt upp och ner:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Lokala variabler ska deklareras raden ovan första användning&lt;/li&gt;&lt;li&gt;Privata metoder ska deklareras direkt efter första användning. Målet är att när man läser en metod ska man ha relaterad kod så nära som möjligt. Detta är inte helt enkelt när den privata metoden används av flera andra metoder men man får göra sitt bästa. :-)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-1963795024614591560?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/1963795024614591560/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g6-g10.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1963795024614591560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/1963795024614591560'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g6-g10.html' title='G6 - G10'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-3660387551099775435</id><published>2009-02-06T07:54:00.000-08:00</published><updated>2009-02-06T12:35:57.557-08:00</updated><title type='text'>G1 - G5</title><content type='html'>Då fortsätter vi ... många små regler kvar... men nu är det G1 till G5 som gäller.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G1: Flera språk i samma fil&lt;/span&gt;&lt;br /&gt;Det finns en anledning till att framework som Wicket och andra jobbar hårt på att inte blanda html och java utan att de som är bra på respektive sak kan jobba med sin sak utan att bli störda av sådant som för dem är irrelavant.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G2: Förväntat beetende är inte implementerat&lt;/span&gt;&lt;br /&gt;Tänk er följande metodsignatur:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;public int dayToString(String day)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Denna metod översätter texten "monday" till 1. Fundera nu på vilka textsträngar ni skulle förvänta er att metoden kan tolka. Visst är det så att vi förväntar oss att metoden ska kunna tolka resten av veckodagarna? Är det så att vi förväntar oss att en sådan metod ska kunna olika case som MONDAY och monday eller kanske till och med förkortningar? Vad mer borde vi kunna förvänta oss av metoden? Allt detta ni kan förvänta er borde ni också implementera. Om den som ska använda metoden inte får det resultat den förväntar sig (inom rimliga gränser naturligtvis) så kommer personen ifråga att börja fundera på om koden faktisk gör som han/hon förväntar sig i något fall.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G3: Felaktigt beteende vid gränser (boundaries, cornercases)&lt;/span&gt;&lt;br /&gt;Det låter självklart så att koden ska göra rätt i alla sammanhang. Men det är också väldigt enkelt att glömma bort att som programmerare glömma bort, eller vid stress "glömma bort" att faktiskt lägga tid på att försäkra sig om att koden faktiskt gör rätt om något annat data än det normala. Även om metoden gör rätt i 10 000 fall så är inte koden rätt förrän alla möjliga utfall är korrekta.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G4: Borttagna säkerhets funktioner&lt;/span&gt;&lt;br /&gt;Säkerhet är nästan alltid i vägen så är det. Men oftast finns det en anledning till att de finns där i första rummet. Att strunta i dem är i bästa fall dumdristigt. Glöm inte att säkerhet är mycket mer än bara inloggningar. Kompileringsvarningar tex upplyser om att du kan ha ett problem snart. Varningar om att ett program inte hittade sin konfigurationsfil och därför föll tillbaka på defaultvärden innebär att när det väl kommer en konfigurationsfil kan det få stora effekter på ditt program.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;G5: Duplicering&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Don't repet yourself (dry), Once and only once. Kärt barn har många namn. Allt går ut på att om man har kod som gör samma sak på två ställen så är det mer än dubbelt så svårt att underhålla koden och det blir lätt att få sin applikation att uppföra sig okonsekvent där vissa funktioner ibland fungerar och ibland inte fungerar berorende att vissa kopior har ändrats och vissa inte. Att vara nogrann med att söka efter existerande funktionallitet räcker långt men om du ska vara seriös skaffar du ett verktyg (inställt på högsta möjliga känslighet) och börjar åtgärda de värsta problemen och forsätter tills hela kodbasen är fri från dupliering. Ibland måste man skriva om koden till att tex använda Template method eller Strategy pattern för de fall där en metod återkommer i koden med små förändringar. Ibland måste man fundera på om man kanske ska byta ut if/else och switch mot polymorfism (don't ask, tell)&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-3660387551099775435?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/3660387551099775435/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g1-g5.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3660387551099775435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3660387551099775435'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/02/g1-g5.html' title='G1 - G5'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5727909908734505243</id><published>2009-01-31T01:15:00.000-08:00</published><updated>2009-02-01T21:55:09.465-08:00</updated><title type='text'>E1, E2 och F1 - F4</title><content type='html'>&lt;span style="font-family:georgia;"&gt;&lt;span style="font-family:lucida grande;"&gt;Går vidare med E1, E2 och F1 - F4&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:georgia;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;E1: Kräver mer än ett steg för att bygga&lt;/span&gt;&lt;br /&gt;Din arbetsplats ska vara så automatiserad som möjligt. Faktiskt tycker jag inte att denna punkt går tillräkligt långt. Kompilering och bygge borde ske i bakgrunden och aldrig behöva aktiveras manuellt, utan alltid vara klart. Men självklart ska man inte behöva köra olika skript, flytta filer manuellt för att kunna bygga applikationen. Jag skulle också vilja tillägga att allt ska gå snabbt. Att vänta i 2-3 minuter flera gånger i timmen för att kolla att något fungerar är en enorm tidstjuv.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;E2: Kräver mer än ett steg för att köra tester&lt;/span&gt;&lt;br /&gt;Inget konstigt och i samma anda som E1. Din arbetsplats skall vara så automatiserad som möjligt. Kommandot för att köra alla tester ska alltid ligga framme för enkel åtkomst och inte kräva att man följer en wizard etc. Snabbt, enkelt och självklart.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;F1: För många argument&lt;/span&gt;&lt;br /&gt;Metoder som inte tar några argument är bäst. En, två och undantagsvis tre variabler kan vara acceptabelt. Fler variabler i en metod bör utlösa en flod av förslag på förändringar som kan få koden att lösa sin uppgift på ett bättre sätt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;F2: "Output" argument&lt;/span&gt;&lt;br /&gt;När man använder outputargument tvingar man läsaren av koden att tänka baklänges. Många klarar att tänka baklänges men för nästan alla kräver det en extra insats. Det är bättre att returnera ett objekt som innehåller de variabler som ska vara tillgänglia efter metodanropet. Detta gäller även för att modifiera collections där det är tydligare om man returnerar den modifierade "samlingen" än lämnar läsaren av koden med frågan om något hände med objektet som stoppades in i metoden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;F3: Boolska flaggor som arguement&lt;/span&gt;&lt;br /&gt;En boolean som argument visar ofta att metoden har två uppgifter. Om argumentet är sant gör si och om det är falskt gör så. Bättre då att skriva två olika metoder eller kanske till och med tre metoder. Tre metoder förklaras med att den boolska flaggan bara påverkar en del av metoden och då kan man skriva den gemensamma delen som en metod och sedan två metoder för den delen som styrs av flaggan.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;F4: Oanvända funktioner&lt;/span&gt;&lt;br /&gt;Funktioner som inte används raderar vi självklart och tveklöst. Vi har versionshanteringssystem för att hitta kod som en gång i tiden funnits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5727909908734505243?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5727909908734505243/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/e1-e2-och-f1-f4.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5727909908734505243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5727909908734505243'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/e1-e2-och-f1-f4.html' title='E1, E2 och F1 - F4'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-3520304079380238820</id><published>2009-01-18T11:57:00.000-08:00</published><updated>2009-01-18T12:47:35.324-08:00</updated><title type='text'>C1-C5</title><content type='html'>Försöker att beskriva reglerna C1 till C5&lt;br /&gt;&lt;ul&gt;&lt;li&gt;C1: Fel information i fel system &lt;/li&gt;&lt;li&gt;C2: Felaktiga kommentarer&lt;/li&gt;&lt;li&gt;C3: Onödiga kommentarer&lt;/li&gt;&lt;li&gt;C4: Dåligt skrivna kommentarer&lt;/li&gt;&lt;li&gt;C5: Bortkommenterad kod&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;C1: Fel information i fel system&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Första frågan man måste fråga sig är vilka kommentarer som är lämpliga att ha i programmeringskod. Är det verkligen relevant att ha en kommentar som säger att ändringen utfördes för bugg #34 eller att ha en lista med de 20 senaste ändringarna? Regeln jag följer är att alla kommentarer i koden ska beskriva koden och inte versionenhantering, ärendehantering eller något annat som bör hanteras av system utanför koden. Tex bör ett bra ärendehanteringssystem hålla reda på vilka ändringar i källkoden som gjorts för ett ärende. Det borde inte vara något som ska stå i källkoden. &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;C2: Felaktiga kommentarer&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Vem av oss har inte läst en kommentar som har skickat ut oss på någon timme av felsökning i fel ände av problemet för att koden har förändrat men inte kommentarern. Felaktiga kommentarer förstör värdet av flera hundra bra då de rubbar förtroendet för hela applikationen. Vågar jag verkligen lita på det som står där? &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;C3: Onödiga kommentarer&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;De av er som använder Visual Studio har säkert hört talas om Ghostdoc. Det är en liten plugin som utifrån en metodsignatur skapar kommentar. Problemet med Ghostdoc är att de kommentarer som programmet skriver inte tillför något utan enbart är en upprepning av den information som står i metodsignaturer. Det enda som tillförs är fler rader av kod som måste underhållas. Fler kommentarer som efter en ändring riskerar att att ljuga för läsaren. Slutsatsen bör alltså vara att om du inte tänker bidra med något som inte redan står i koden bör du hellre låta bli att skriva kommentaren i första läget. Nu är det säkert något som undrar hur dokumentationssystem som tex javadoc ska hanteras, då de använder formaterade kommentarer för att extrahera ur infomation från källkoden. Svaret hittar vi i C1. Det vore kanske bättre att ha något annat system för att hantera den typen av information. &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;C4: Dåligt skrivna kommentarer&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;När man skriver kommentarer ska man inte göra det slentrianmässigt tex som vid användade av Ghostdoc. En kommentar bör värderas högt och man bör lägga en hel del möda på att skriva kommentaren så bra det går. Vad är en dålig kommentar? Den är ju inte felaktig som i C2. En dålig kommentar kan vara felaktigt placerad, vara oprecis och eller onyanserad. Den kanske bara delvis är relevant.Vad ska man göra med en dålig kommentar? Man lämnar den naturligtvis inte det dåliga skicket utan ser till att det antingen blir en bra kommentar eller en raderad kommentar (som man får hitta i versionshanteringssystemet).&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;C5: Bortkommenterad kod&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;Här finns det inga ursäkter. Använd ett versionshanteringssystem om ni har ringaste intresse av att den bortkommenterade koden ska gå att återfinna. Så kort och gott, bort med skiten, bortkommenterad kod har inte i en källkodsfil att göra.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-3520304079380238820?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/3520304079380238820/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/c1-c5.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3520304079380238820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/3520304079380238820'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/c1-c5.html' title='C1-C5'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-8374919611856448532</id><published>2009-01-17T13:59:00.000-08:00</published><updated>2009-01-17T15:31:55.166-08:00</updated><title type='text'>De största reglerna</title><content type='html'>De olika reglerna som Bob Martin beskriver i sin bok finns några som är "större" än de andra. De kanske är självklara på sitt sätt men är långt i från alltid självklart hur man faktiskt ska hantera dem.&lt;br /&gt;&lt;br /&gt;&lt;ol style="font-weight: bold;"&gt;&lt;li&gt;G5: Duplicering: &lt;span style="font-family: georgia; font-weight: normal;"&gt;Lätt att förstå men svår att faktisk genomföra. Det är så lätt att göra copy and paste. Det finns en mängd trick för att undvika att duplicera koden men vilket ska man använda i vilken situaion. Men som sagt, det är lätt att förstå att det är dåligt att ha samma kod på två ställen.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;N1: Använd beskrivande namn:&lt;span style="font-family: georgia; font-weight: normal;"&gt; En gång i tiden fick en variabel inte använda mer än åtta tecken, då var man tvungen att skriva btn i stället för Button. En gång i tiden hanterade vi bara bytes, då var det en god idé att ha med typen i variabelnamn för att veta hur man skulle hantera respektive byte. Idag kan vi skapa typer för varje behov. Så använd den frihet vi idag har till att faktiskt skriva vad saker är och ska göra så att det är så tydligt det någonsin kan bli. &lt;/span&gt;&lt;/li&gt;&lt;li&gt;G12: Skräp: &lt;span style="font-family: georgia; font-weight: normal;"&gt;Allt som inte tillför något är skräp. Det låter svepande men är grunden för flera av de andra reglerna, tex C2, C3, C4, C5, F4 och G9&lt;/span&gt;&lt;/li&gt;&lt;li&gt;G27: Struktur över konvention: &lt;span style="font-family: georgia; font-weight: normal;"&gt;Att tala om en procedur ska följas är enkelt. Att komma ihåg att man ska följa proceduren är svårare. Därför är det bättre att genom struktur tvinga efterlevnad. Får en klass bara instansieras en gång använd, implementera en singleton i stället för att skriva en kommentar som beskriver användningen.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;G6: Kod i fel abstraktions nivå: &lt;span style="font-family: georgia; font-weight: normal;"&gt;Vi människor är duktiga på att blanda abstraktionsnivå. Vi kan beskriva stora skeden en sekund och sedan hoppa ner på detaljer i nästa. Det är dock svårt att förstå kod som blandar abstraktionsnivåer. Detta är nog en av de svåraste reglerna att både förstå och sedan följa.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-8374919611856448532?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/8374919611856448532/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/de-strsta-reglerna.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8374919611856448532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/8374919611856448532'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/de-strsta-reglerna.html' title='De största reglerna'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5282462689780656318</id><published>2009-01-10T03:44:00.000-08:00</published><updated>2009-02-13T13:07:42.787-08:00</updated><title type='text'>Översättning</title><content type='html'>Jag ger mig på att försöka att översätta Robert C. Martins "kodregler"&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt; ur boken Clean Code lite kortfattat. De beskriver inte saker som nödvändigtvis är felaktiga eller dåliga men situationer och saker där man bör fundera ett varv extra på om man kanske har något som man kanske kan göra bättre.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Om kommentarer&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;C1: Fel information i fel system &lt;/li&gt;&lt;li&gt;C2: Felaktiga kommentarer&lt;/li&gt;&lt;li&gt;C3: Onödiga kommentarer&lt;/li&gt;&lt;li&gt;C4: Dåligt skrivna kommentarer&lt;/li&gt;&lt;li&gt;C5: Bortkommenterad kod&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Utvecklingsmiljö&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;E1: Kräver mer än ett steg för att bygga&lt;/li&gt;&lt;li&gt;E2: Kräver mer än ett steg för att köra tester&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Funktioner&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;F1: För många argument&lt;/li&gt;&lt;li&gt;F2: "Output" argument&lt;/li&gt;&lt;li&gt;F3: Boolska flaggor som arguement&lt;/li&gt;&lt;li&gt;F4: Oanvända funktioner&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Allmänna&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;G1: Flera språk i samma fil&lt;/li&gt;&lt;li&gt;G2: Förväntat beetende är inte implementerat&lt;/li&gt;&lt;li&gt;G3: Felaktigt beteende vid gränser (boundaries, cornercases)&lt;/li&gt;&lt;li&gt;G4: Borttagna säkerhets funktioner&lt;br /&gt;&lt;/li&gt;&lt;li&gt;G5: Duplicering&lt;/li&gt;&lt;li&gt;G6: Kod i fel abstraktions nivå&lt;/li&gt;&lt;li&gt;G7: Klasser beroende av sina arvingar&lt;br /&gt;&lt;/li&gt;&lt;li&gt;G8: För mycket information&lt;/li&gt;&lt;li&gt;G9: Död kod&lt;/li&gt;&lt;li&gt;G10: Vertikalt avstånd&lt;/li&gt;&lt;li&gt;G11: Inkonsekvens&lt;/li&gt;&lt;li&gt;G12: Skräp&lt;/li&gt;&lt;li&gt;G13: Artificiella kopplingar&lt;/li&gt;&lt;li&gt;G14: Funktionsavundsjuka&lt;/li&gt;&lt;li&gt;G15: Val genom argument&lt;/li&gt;&lt;li&gt;G16: Kodat uppsåt&lt;/li&gt;&lt;li&gt;G17: Felaktigt placerat ansvar&lt;/li&gt;&lt;li&gt;G18: Olämpligt användning av static&lt;/li&gt;&lt;li&gt;G19: Använd förklarande variabler&lt;/li&gt;&lt;li&gt;G20: Funktionsnamn ska säga vad de gör&lt;/li&gt;&lt;li&gt;G21: Förstå algoritmen&lt;/li&gt;&lt;li&gt;G22: Gör logiska beroenden fysiska&lt;/li&gt;&lt;li&gt;G23: Föredra arv före if/else eller switch&lt;/li&gt;&lt;li&gt;G24: Följ konventioner enligt standard&lt;/li&gt;&lt;li&gt;G25: Ersätt magiska nummer med konstanter&lt;/li&gt;&lt;li&gt;G26: Var exakt&lt;/li&gt;&lt;li&gt;G27: Struktur över konvention&lt;/li&gt;&lt;li&gt;G28: Dölj boolska uttryck&lt;/li&gt;&lt;li&gt;G29: Undvik negativa booska uttryck&lt;/li&gt;&lt;li&gt;G30: Funktioner bör göra en sak&lt;/li&gt;&lt;li&gt;G31: Dolt beroende av tid/ordning&lt;/li&gt;&lt;li&gt;G32: Var inte godtycklig&lt;/li&gt;&lt;li&gt;G33: Kapsla in gränsfall&lt;/li&gt;&lt;li&gt;G34: Funktioner går enbart en abstraktionsnivå ner&lt;/li&gt;&lt;li&gt;G35: Håll konfigurerbart data på hög abstraktionsnivå&lt;/li&gt;&lt;li&gt;G36: Undvik beroenden på beroende&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Namn&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;N1: Använd beskrivande namn&lt;/li&gt;&lt;li&gt;N2: Välj rätt namn på rätt abstraktionsnivå&lt;/li&gt;&lt;li&gt;N3: Använd standardiserad vokabulär&lt;br /&gt;&lt;/li&gt;&lt;li&gt;N4: Otvetydiga namn&lt;/li&gt;&lt;li&gt;N5: Använd långa namn på stora "scope"&lt;/li&gt;&lt;li&gt;N6: Koda inte koden&lt;/li&gt;&lt;li&gt;N7: Namn ska beskriva sidoeffekter&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Tester&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;T1: Otillräkliga tester&lt;/li&gt;&lt;li&gt;T2: Använd test-täcknings verktyg&lt;/li&gt;&lt;li&gt;T3: Strunta inte i triviala tester&lt;/li&gt;&lt;li&gt;T4: Ett ignorerat test är en fråga om tveksamheter&lt;/li&gt;&lt;li&gt;T5: Testa gränsfall&lt;/li&gt;&lt;li&gt;T6: Testa mer runt buggar&lt;/li&gt;&lt;li&gt;T7: Se mönster för varför tester falerar&lt;/li&gt;&lt;li&gt;T8: Testtäckning påvisar mönster&lt;/li&gt;&lt;li&gt;T9: Tester ska vara snabba&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5282462689780656318?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5282462689780656318/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/verstttning.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5282462689780656318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5282462689780656318'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/verstttning.html' title='Översättning'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-99692491284515828</id><published>2009-01-01T13:24:00.000-08:00</published><updated>2009-01-01T14:02:08.422-08:00</updated><title type='text'>Law of Demeter</title><content type='html'>Hur mycket ska ett objekt känna till om andra objekt. Svaret är enkelt, desto mindre desto bättre. Anledningen är lika enkel som svaret. Om den anropande klassen känner till hur den anropade klassen löser sin uppgift blir det svårt att ändra den anropade klassen. Tänk följande scenario:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public Employee getEmployeeSalary(int idNumber){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-family: courier new;"&gt;  Employee employee = Context.getInstance().getSearchService.getEmployeeById(idNumber);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  return employee.getCurrentSalary();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: georgia;"&gt;I metodenovan  har vi effektivt låst fast implementationen av hur Context levererar en Employee från dess Id. Om vi skulle göra en förändring av kedjan av anrop kan det bli många ställen att ändra på i koden.&lt;br /&gt;&lt;br /&gt;Hur bör man göra då? Den trista lösningen är vi ska lägga in en metod i Context och låta Context ta beslutet för hur Employee ska levereras. Om vi nu skulle vilja flytta getEmployeeById från SearchService till EmployeeService kan vi göra det utan att en mängd beroenden också måste ändras. Det är dock inte helt oproblematiskt att göra på detta sätt. Vi riskerar ett scenario där vi översvämmar Context-klassen med ett stort antal metoder.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-99692491284515828?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/99692491284515828/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/law-of-demeter.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/99692491284515828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/99692491284515828'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2009/01/law-of-demeter.html' title='Law of Demeter'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-5976727157113001118</id><published>2008-12-19T23:33:00.000-08:00</published><updated>2008-12-20T00:02:23.482-08:00</updated><title type='text'>Kommentarer</title><content type='html'>I mitt förra inlägg tog jag upp duplicering och mitt exempel kunde kortas ner väsentligt genom att ta bort kommentaren i metodsignaturen. Kommentaren i det exemplet var ren duplicering av det som stod i metodsignaturen och där med reduant.&lt;br /&gt;&lt;br /&gt;Så när, var och hur ska man kommentera. Svaret är enkelt. Det som inte kan uttryckas i kod skall kommenteras. Allt annat ska man låta bli att kommentera. Använd i stället lite mer beskrivande namn på saker och ting och framför allt förändra din kod så att den går att beskriva i kod. Det är i princip bara dålig kod som bör refaktoreras som behöver kommenterar. Trist men sant.&lt;br /&gt;&lt;br /&gt;Så låt oss ta ett exempel med kommenter och se om vi kan klara oss utan.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;* Creates a employee&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;**/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;public void CreateEmployee(Employee employee){}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Detta är samma exempel som jag hade i förra inlägget. Kommentaren tillför inget och kommer sannolikt bli felaktig vid första bästa förändring. Vi bygger ut exemplet lite med en body:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;public void CreateEmployee(Employee employee{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  // Check that name is not null&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  if(employee.name == null){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;    throw new Exception("Employee must have a name")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  // Check that employeeNumber is not already set&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  if(employee.number != 0){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;    throw new Exception("Employee number is already set");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  // Add into persistent storage&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  DataProvider.insert(employee);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Metoden ser rimligt ren ut men har tre kommentarer. Är dessa nödvändiga eller kan vi skriva metoden på ett annat sätt som skulle göra både koden mer lättläst och dessutom kunna ta bort kommentarerna. Mitt förslag är att dela upp metoden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;public void CreateEmployee(Employee employee){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  ValidateNewEmployee(employee);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;  PersistEmployee(employee);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;private void ValidateNewEmployee(Employee employee){&lt;br /&gt;  if(employee.name == null){&lt;br /&gt;    throw new Exception("Employee must have a name");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if(employee.number != 0){&lt;br /&gt;    throw new Exception("Employee number is already set");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void persistEmployee(Employee employee){&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;DataProvider.insert(employee);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Det som har hänt är att jag har brutit ut funktionaliteten i CreateEmployee till två privata metoder som står för all action. CreateEmployee har en kort lista på de logiska steg som skall genomföras men gör inget själv. Vi har inte vunnit kortare kod men vi har vunnit enormt i läsbarhet. Direkt när man tittar på CreateEmployee ser man vad metoden tänker sig att den ska göra och man kan gå direkt till den del man är intresserad av.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-5976727157113001118?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/5976727157113001118/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/kommentarer.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5976727157113001118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/5976727157113001118'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/kommentarer.html' title='Kommentarer'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-7942188426800523935</id><published>2008-12-19T22:59:00.000-08:00</published><updated>2008-12-19T23:32:08.826-08:00</updated><title type='text'>Huvudregel: Alla former av duplicering är av ondo</title><content type='html'>&lt;span style="font-family:georgia;"&gt;Sedan man började programmera har man infört fler och fler begrepp för att undvika redunans i koden. Man har brutit ut metoder, skapat object, patterns etc. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Vi tittar på en metod definierad i ett interface och funderar på vilken information som är duplicerad.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold;"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;* Create employee&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;**/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;public void createEmployee(Employee employee);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Det första vi kan stryka är kommentaren. Den tillför inget som inte metodsignaturern redan beskriver.&lt;br /&gt;&lt;br /&gt;Sedan kan man fundera på om metodnamnet är lämpligt. Vi duplicerar ordet employee två gånger. Vi testar att ta bort ordet Employee från CreateEmployee och tittar på resultatet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;public void create(Employee employee);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Metodsignaturer beskriver precis samma sak som det första exemplet. Den innehåller ingen kommentar av flera anledningar&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;Kommentaren i exemplet tillför inget mervärde för koden. Det enda del tillför är mer text att läsa.&lt;/li&gt;&lt;li&gt;Kommentaren kommer med hög sannolikhet att bli felaktig.Tex om man använda automatiskt refaktorering (ändra på ett ställe och alla ställen som använder samma kod uppdateras i hela kodbasen) är det inte troligt att kommentaren kommer att uppdateras. Alltså kommer koden snart innehålla felaktiga kommentarer&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-7942188426800523935?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/7942188426800523935/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/huvudregel-alla-former-av-duplicering-r.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7942188426800523935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7942188426800523935'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/huvudregel-alla-former-av-duplicering-r.html' title='Huvudregel: Alla former av duplicering är av ondo'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-556852436618020611.post-7142952393885121634</id><published>2008-12-19T22:58:00.000-08:00</published><updated>2008-12-19T22:59:24.385-08:00</updated><title type='text'>Clean code</title><content type='html'>Sitter och läser en bok som heter clean code och tänke försöka att få ner lite anteckningar och då verkar ju en blogg vara ett lämpligt ställe att göra det på.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/556852436618020611-7142952393885121634?l=renprogrammering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://renprogrammering.blogspot.com/feeds/7142952393885121634/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/clean-code.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7142952393885121634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/556852436618020611/posts/default/7142952393885121634'/><link rel='alternate' type='text/html' href='http://renprogrammering.blogspot.com/2008/12/clean-code.html' title='Clean code'/><author><name>daydreaming</name><uri>http://www.blogger.com/profile/04507631954124102076</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
