Agila utvecklare måste även skriva sin kod på ett agilt sätt för att vara helt agila

”Writing good code is very challenging. Writing good code in an Agile environment is even harder. At least, that’s what it might look like. Because Agile teams have to be economic with their time, so they require strategies that allow them to maintain their flexibility throughout the sprint. Thankfully, many developers have gone before us and there’s a lot we can learn from their experiences”

Översikt över agila designprinciper och strategier för agila team

Inom agilt jobbar man agilt med krav, arkitektur, design och utveckling då det är ett effektivt sätt att jobba på där man iterativ och inkrementellt del för del gör färdigt systemet, och idealet är att varje del (inkrement) ska vara fullt användbar för kunden och releasad till produktion så systemets produktionssatta funktionalitet växer fram.

Agilt är ett mer flexibelt och dynamiskt sätt att jobba på än rigida och mekaniska vattefallsmetodiker som kan vara mer eller mindre omfattande, så det är ett annorlunda sätt att jobba på som kan ta tid att lära sig för dem som är nya inom det.

Inom traditionell projektledning och vattenfallsmetodik använder man oftast ett Gantt chart där man har start och stop datum för allt, alla features som ska göras, alla beroenden mellan features och vilka personer som ska göra dessa och när, så innan genomförandefasen börjar så allt är specificerat och planerat från ax till limpa.

Sen tillkommer oftast andra detaljstyrande dokument, checklistor, standards och rutiner för att försöka säkra kvaliteten vilket kan göra det onödigt tungrott i många fall.

I i värsta fall får man även oerhört detaljerade UML diagram och till och med skelettkod av arkitektfunktionen som det är tänka att utvecklare bara ska fylla i kod och funktionalitet i metoderna på, vilket har visat sig vara en illa fungerande och dåligt ide.

Jobbar man agilt har man bara user stories på boarden sorterade i prioritetsordning som tas fram allteftersom då man jobbar iterativ och inkrementellt med utredning/genomförande, och det finns en konstant feedbackloop mellan utvecklare, kravfångare, kravställare och användare så man snabbt kan justera kursen och gör rätt sak på rätt sätt vilket också är att kvalitetssäkra.

Ett annat vanligt sätta att kvalitetssäkra på i agilt som komplement till ovan är automatiserade tester i den utsträckning som det är lämpligt för den aktuella appen eller featuren, och möjliggör även automatiserade deployments via CI/CD.

Sen sköter teamet och den person som tar uppgiften om vem och hur (ibland inom vissa givna ramar som t.ex vilket språk/ramverk, driftsplattform och kanske ett minimum av inte mer än nödvändigt detaljerade UML artefakter för designen) och lägger till detaljer om det behövs innan implementering.

Man jobbar enligt just-in-time design principen (så nära inpå implementeringen som möjligt då man vet så mycket som möjligt om uppgiften) och emergent design principen (inte mer design eller mer detaljerad än absolut nödvändigt innan implementering för man kan inte förutsäga allt och designen kommer oftast förändras när man börjar koda och göra det på riktigt)

Sen gör man inte mer avancerade lösningar än vad som behövs för att lösa problemet just nu och försöker inte ta hänsyn till varenda liten omständighet som möjligen har en liten sannolikhet att inträffa i framtiden utan låter tiden utvisa om dessa verkligen behövs (KISS och YAGNI principerna), eller prioritera återanvändbarhet då det oftast inte lönar sig.

Det är ett betydligt mindre toppstyrt och mer flexibelt och dynamiskt sätt att jobba på, men ibland kanske det måste vara lite mer toppstyrt om det finns många juniora utvecklare i teamet som är ovana vid att jobba agilt.

Förplanering inom agil systemutveckling

”Upfront thinking on software projects can take a number of forms. It can be someone thinking about the architecture of the system. It could be a UI designer sketching wireframes. It could be an analyst building detailed scenarios and confirming all manner of edge cases conditions through workflows. Or it could be a database designer thinking about the structure of the database. I’m not saying any of these are bad (or that they’re good). They are merely examples of upfront thinking.”

Upfront Thinking Is Like Insurance

När det gäller förplanering kan man faktiskt göra sådant inom agilt med för det system eller delare av ett system man bedömer att det behövs, men bara i den utsträckning som det är absolut nödvändigt för att inte lägga ner onödigt arbete innan man vet tillräckligt mycket om problemet som ska lösas och hur man bäst ska lösa det, för sådana saker förändras oftast under arbetets gång.

Inom agil design kan man om det är nödvändigt på ett tidigt stadium ta fram t.ex. en konceptuell övergripande arkitektur för ett system eller del av system om det är frågan om stora system som en startpunkt, som sedan vidareutvecklas, förändras och blir mer färdig allteftersom projektet framskrider och man gör färdigt fler delar.

Agil design är emergent design

”We perceived, back at Snowbird, that the code needed to influence the design. It wasn’t a one-way street. No matter how much design we did on its own, as soon as we began to express it in code, the design needed to change. We expressed it as the code telling us what the design wanted to be.”

”And voila! There are the people. I was sure they’d turn up. The people need to be self-organizing. And they need to have the ability, not just the right, to improve the design. They improve the design over time. It changes. It emerges.”

Emergent design

Vad gäller konceptet emergent design så innebär det inte att man aldrig ska göra någon design innan man sätter sig ner och börjar implementera för det är inte emergent design utan ad-hoc design (vilket man i.o.f. kan använda de gånger det gäller mindre komplexa system/applikationer som man har bra koll på hur man ska göra).

Med emergent design menas att den växer fram allteftersom då det inte är någon ide att göra en för detaljerad och omfattande design innan implementeringen påbörjas eftersom man så gott som alltid blir tvungen att ändra på designen i efterhand när verkligheten tränger sig på.

Man gör därför en mer lättviktigt och konceptuell design som ligger på en högre nivå än man t.ex gjorde på den gamla RUP tiden, och tar det del för del så när inpå implementeringen av en feature eller ett delsystem som möjligt.

I vattenfallmetodiken (ex. RUP) försöker man ta fram alla krav för hela systemet så detaljerad som möjligt innan framtagande av arkitekturen påbörjas och gör sedan designen så detaljerad som möjligt för hela systemet innan utvecklingen sätter igång.

Att man sen kanske jobbar inkrementellt och iterativt inom varje fas i vattenfall är inte samma sak som att jobba agilt, för agilt är så mycket mer än det och inom agilt jobbar man inkrementellt och iterativt med alla faser parallellt.

För att ta klassdiagram som exempel så kan man göra dem med olika detaljnivå från att bara ha boxar med klassnamnen, ev interface och associationerna mellan dem till extremt detaljerade sådana med exakta associationstyperna, alla attribut med specificerade typer och metoder för hela systemet på en gång som man sen kan generera skelettkod ifrån som programmeraren ska fylla med funktionalitet.

Inom RUP är det sistnämnda vanligast men inom agilt är det förstnämnda vanligast, för man gör inte designen mer detaljerad än den behöver vara och inte fler diagram (artefakter) än absolut nödvändigt för att ge en tillräckligt bra startpunkt för den del av systemet man ska börja implementera, eftersom den ändå skulle behöva förändras under arbetets gång.

Agila designmetoder

”These strategies are critical for scaling agile software development to meet the real-world needs of modern IT organizations. The Agile approach to design is very different than the traditional approach, and apparently more effective too. It is important to understand:”

  • Agile Design Practices
  • Agile Design Philosophies
  • Design Throughout The Agile Lifecycle

Agile Design

Se även ovan artikel för en översiktligt och pedagogisk introduktion till agil design och hur man kan jobba agilt med designen inom agil systemutveckling.

”If the team is taking a Test-Driven Development (TDD) approach the detailed design is effectively specified as developer tests, not as detailed models. Because you write a test before you write enough production code to fulfill that test you in effect think through the design of that production code as you write the test. Instead of creating static design documentation, which is bound to become out of date, you instead write an executable specification which developers are motivated to keep up to date because it actually provides value to them.”

Särskilt intressant är hans reflektion över syftet med att använda TDD inom agil utveckling för förutom att testa koden så blir testerna i praktiken JIT design som specificerar hur något ska fungera, och ersätter i princip designmodeller på det implementationsnära stadiet.

Men man behöver inte använda TDD utan kan göra lite lättviktiga JIT designmodeller med om man föredrar att skriva tester efter att den initiala versionen av en metod är gjord, fast många agila utvecklare gillar att jobba enligt TDD så man bör ha det som en option för utvecklarna.

Agila arkitekter och agila team

”Alternatively, architects can be embedded in teams, either as a dedicated person #2) or distributed across team members via a shared responsibility #3). What doesn’t work is teams claiming that they are “doing architecture” but no one knows for sure how it’s done #4).”

Agile and Architecture: Friend, not Foe

Visst behövs arkitektur när man utveckla applikationer agilt med, men i hur hög grad beror helt på vilken sorts system man utvecklar.

Den stora skillnaden mot det traditionella sättet är att arkitekten inte äger arkitekturen och toppstyr utvecklarna, utan utvecklar arkitekturen tillsammans med dem som en medlem i teamet om det finns dedicerade arkitekter, och i agil anda allteftersom och inte som en big bang design i klassisk vattenfallsanda.

Sen kan nog en dedicerad arkitekt var medlem i många team samtidigt då design görs löpande i mindre portioner, och i så nära anslutning till implementationen av den delen eller komponenten som möjligt, och jag personligen tycker inte det spelar så stor roll om arkitekten är en dedicerad person som hoppar in vid behov eller ett delat ansvar mellan flera permanenta personer i teamet.

Inom agilt jobbar man som sagt även iterativt och inkrementell med alla faser parallellt och gör inte mer design eller dokumentation än vad som är nödvändigt för just det projektet (t.ex. styrsystem för kärnkraftverk som är väldigt kritiska kommer kräva mer än ett inmatningsformulär för en konferensanmälan).

Inom agilt kan man t.ex. börja med att ta fram en konceptuell övergripande arkitektur som en sorts visualisering av produktvisionen, och sedan detaljerade krav i form av user stories och kompletterande umldiagram (baserade på de formella kraven) för den del av systemet man kommer börrja implementera i nästkommande 2 sprintar, som man sedan sätter igång med samtidigt som man fortsätter ta fram mer detaljerade krav på arkitekturen för nästa del av systemet så man hela tiden har detaljerade user stories för 2 sprintar framåt.

Baserat på input från utveckling, test och user feedback kan sen kraven och arkitekturen förändras ända tills produkten är färdig vilket kanske låter osäkert, men i själva verket är det ett sätt att försäkra sig om att man gör rätt sak på rätt sätt så effektivt som möjligt och hela tiden anpassar kartan till terrängen.

Agil systemutveckling och programmering

Agila team som jobbar enligt t.ex. scrum och jobbar agilt avseende planering, kravhantering, och design, använder TDD och CI/CD kan lätt tro att de jobbar helt agilt, men det går att skriva överkomplicerad kod och göra överkomplicerade arkitekturer även då.

Det många utvecklare missat är att agil utveckling även innebär att man skriver sin kod och lösning på ett så enkelt sätt som möjligt, och inte gör överarbetade och överkomplicerade ”perfekta” lösningar som tar hänsyn till allt som kan behövas i framtiden och använder varenda designmönster och cool finess som finns, eller för den delen motsatsen och gör obegriplig spagettikod.

3 grundprinciper för all systemutveckling och programmering

3 grundprinciper för all systemutveckling är:

  1. Don’t Repeat Yourself (DRY)
  2. Keep it Simple Stupid (KISS)
  3. You ”Ain’t Gonna Need It (YAGNI)

3 Key Software Principles You Must Understand

DRY principen

Man ska försöka följa DRY principen som först nämndes i den klassiska boken The Pragmatic Programmer.

The DRY Principle Explained: Its Benefit and Cost with Examples

När det gäller DRY principen ska ni försöka hålla er till den för i de allra flesta fall är duplicerad kod inte bra, men det kan finnas undantagsfall som ni kan lära er mer om i nedan artikel.

When to avoid the DRY principle

KISS och YAGNI principerna

En agil utvecklare ska inte heller sub-optimera sin kod in i absurdum och försöka göra bästa möjliga tekniska lösning för alla tänkbara framtida scenarion eller osannolika scenarion med liten risk att inträffa, utan låta tiden utvisa om det verkligen behövs.

Tillkommer nya krav eller omständigheter i framtiden så löser man dem då.

KISS och YAGNI principerna

Din kod ska vara enkel att förstå

”A good developer creates things that are easy to understand so that it’s really easy to shake out all the bugs.”

KISS och YAGNI principerna är ingen ursäkt för att skriva obegriplig spagettikod så din kod ska även vara enkel att förstå och förvalta.

Learn the fundamentals of a good developer mindset in 15 minutes

The Zen of Pythons 20 regler

Tycker även själv The Zen of Pythons 20 regler ger en bra bild av hur man kan skriva enkel kod på ett bra sätt, och ser dem som ett komplement till de tidigare nämnda principerna.

What do different aphorisms in The Zen of Python mean?

When programming in Python, you should…

PEP 20 (The Zen of Python) by example

Sträva inte efter att skriva återanvändningsbar kod

”Code reuse is not a worthwhile goal. Avoiding duplication is a worthwhile goal. Avoiding waste is a worthwhile goal. And you do both of these things by looking out for and eliminating repetition of your labor and of functionality in code. So write the code you need and keep doing that, right up to the point that you start repetitively solving the same problem. Then refactor that solution out into a common place and refer to it. When you do this, you’re not reusing code — you’re reusing valuable functionality.”

Code Reuse is Not a Good Goal

Inom agilt ska man ska inte göra mer än vad som behövs för att lösa problemet just nu med rimlig hänsyn tagen till förvaltningsbarhet, utökningsbarhet och återanvändbarhet, vilket kan uppnås med SOLID principerna.

Återanvändbarhet är däremot oftast svårt att uppnå, så skriv för det specifika fallet och återanvänd det som råkar passa till det enligt råden i artikeln, om det inte är uppenbart att något är återanvändningsbart från början.

Detta kanske många traditionella arkitekter vänder sig emot men erfarenheten har visat att det inte lönar sig att prioritera återanvändningsbar kod i de allra flesta fall.

Fem huvudprinciper för agil systemutveckling och programmering

Följande artikel tycker jag på ett väldigt bra sätt summerar hur man kan tänka och jobba som agil utvecklare, för det är lika viktigt som att jobba agilt med kraven och user stories, och den andra sidan av det agila myntet.

De 5 huvudprinciperna för agil systemutveckling är:

  1. Just in Time Design & coding
  2. Think, write, test, refactor
  3. Unit testing
  4. Write Object-Oriented code (OO), not procedural code
  5. Apply Agile Design Patterns and Principles

5 Principles for (Agile) Software Development that improve Agility (and make you a better developer)

Exempel på de 5 SOLID principerna i C#

There are five SOLID principles:

  1. Single Responsibility Principle (SRP)
  2. Open Closed Principle (OCP)
  3. Liskov Substitution Principle (LSP)
  4. Interface Segregation Principle (ISP)
  5. Dependency Inversion Principle (DIP)

SOLID Design Principles Explained – C#

Punkt 5 ovan handlar om SOLID principerna och är ni C# utvecklare kan det var lämplig att börja med att läsa igenom ovanstående artikel som lite översiktligt går igenom de 5 SOLID principerna med exempel i C# kod.

Man kanske inte alltid ska följa alla SOLID principerna fullt ut som punkt 5 i artikeln handlar om då det tenderar att skapa ett system som innehåller väldigt många små delar som kan bli svåra att överblicka och hantera, och kan vara overkill för mindre system som inte kommer ändras så mycket i framtiden.

Do SOLID design principles make code slow?

Man ska alltså vara pragmatisk och inte dogmatiskt när det gäller SOLID principerna, för det är inte alltid berättigat eller nödvändigt att använda dem alla fullt ut.

Videos om de 5 SOLID principerna och DRY pricipen

Nedan en bra videoserie på YouTube som förklarar de 5 SOLID principerna, och den 6:e och sista videon förklarar DRY principen.

Viktigaste principerna att använda inom all systemutveckling och programmering

Separation Of Concerns principen och Single Responsibility principen (som är S’et i SOLID) är de mest essentiella, så ni kan börja med att använda dem och klassisk OOP och ha det som miniminivå.

Försök även hålla er till composition before inheritance, max två nivåer av arv, god namnsättning och skriv så att koden blir lätt att förstå och följ DRY, KISS & YAGNI principerna.

Separation of concerns

Rent praktiskt kan ni åstadkomma separation of concerns genom att designa era applikationer enligt klassiska N-layer arkitekturen.

Traditional ”N-Layer” architecture applications

Eller MVC arkitekturen som är två olika sätt att åstadkomma det på.

Understanding Separation Of Concern in ASP.NET MVC

Best practices för ASP.NET MVC arkitekturer

Genom att även tillämpa best practices för ASP.NET MVC arkitekturer uppnår ni en bra nivå på separation of concerns, single resonsibility principerna och lös koppling även för större system.

ASP.NET MVC Solution Architecture – Best Practices

För mindre applikationer som inte kommer förändras så mycket kan en enklare arkitektur räcka som till exempel det ni får out-of-the-box när ni skapar ett MVC projekt.

Overview of ASP.NET Core MVC

Vanliga webbarkitekturer

I andra fall kanske en microservice arkitektur, domain driven design, ett razor pages projekt som använder den klassiska code behind arkitekturen, eller blazor som använder en komponentbaserad arkitektur är bättre, så allt beror på (kom ihåg KISS & YAGNI).

Common web application architectures

Dependency injection i C# och Asp.Net Core

I Asp.Net Core 2.1 och framåt finns redan en dependency injection container inbyggt så ni behöver inte alltid använda Autofac där, men det beror på hur avancerade behov ni har.

.NET Core project without Autofac. Is it viable?

Dependency injection in ASP.NET Core

Ibland behöver man inte använda IoC containar alls utan kan nöja sig med gammal hederlig manuell dependency injection i stället, eller kanske ingen dependency injection alls om applikationen är väldigt enkel och inte behöver enhetstester.

Dependency Injection in C#

TDD och automatiserade enhetstester

”Whether you’re practicing TDD (Test-Driven Development) or writing your tests after your application code, there’s no doubt that unit testing is essential for web application development. ”

Unit Testing in ASP .NET Core

Sen ska man självklart ha bra tester som kan vara enhetstester, integrationstester eller acceptanstester som ska vara så automatiserade som möjligt.

När det gäller enhetstester finns två skolor och vilket skola man följer är kanske en smaksak.

Den dogmatiska TDD linjen som förespråkar att man alltid ska skriva enhetstester först och enligt vissa även testa 100% av koden, och en pragmatisk som anser att man bara behöver testa den viktigaste affärslogiken med enhetstester, och kan skriva enhetstester efter man är klar med den initiala versionen av en metod eller klass och har fått bättre förståelse för problemet.

Hur omfattande tester som behövs beror också på, så även där ska ni tillämpa KISS och YAGNI som är agila grundprinciper, vilket de som förespråkar 100% täckningsgrad verkar ha missat.

Praktiska exempel på många av principerna

Här en artikel som i kod ger praktiska exempel på många av principerna så ni får en mer handfast förståelse. Kodexemplen är i TYPESCRIPT så det är lätt för er att testa dem själva oavsett vilket som är ert huvudspråk.

How to become a better programmer ?