Tutorial - En liten bankapplikation

1. Introduktion

Detta är en tutorial för att lösa uppgiften en liten bankapplikation i kursen Programmering01. Genom att följa tutorial och genomföra uppgiften innebär att du löst uppgiften på lägsta nivå för ett godkänt betyg. Jag kommer under denna tutorial lägga fokus på hur du skall/kan tänka när du bygger en lite större applikation. Under arbetets gång kommer jag bygga banken steg för steg och ibland köra ett resonemang om vilka alternativ som finns och också varför jag väljer det ena sättet framför det andra.

Även de elever som strävar efter högre betyg rekommenderar jag att göra banken enligt min tutorial för att lära sig hur du skall tänka för att bygga en större applikation. När tutorial väl är färdig så finns det möjlighet att bygga vidare på den för att nå högre mål.

1.1 Uppgiften

Uppgiften är att skapa en liten bankapplikation. Uppgiften kommer vara tvådelad, först en grundläggande del som alla skall göra och sedan kommer det en lista med tilläggsfunktioner som gör applikationen lite mer avancerad och förbereder dig på högre betyg.

Innan du börjar hacka kod, gör en grovplanering av hur du skall lägga upp arbetet. Det är oftast mer effektivt att sedan lösa en deluppgift i taget. Koden för grundkraven är inga nyheter, det är saker du har gjort tidigare, det gäller bara att pussla ihop det på rätt sätt.

1.1.1 Grundkrav

Uppgiften är att skapa en fullt fungerande applikation som simulerar ett bankkonto. Det skall gå att sätta in pengar, ta ut pengar samt visa upp alla transaktioner. Transaktionerna skall lagras i en fil och saldot på kontot skall beräknas. Vid skapandet av ett bankkonto får kunden 1000kr insatt på kontot. Insättning och uttag får vara vilket belopp som helst, fast vi jobbar bara med hela kronor i grunduppgiften.

1.1.2 Genomförande

Även om du känner dig mogen att bygga banken efter eget huvud så vill jag att du bygger den tillsammans med mig steg för steg. Anledningen till detta är att jag under utvecklingens gång går igenom en del principer som kommer underlätta för dig senare i kursen.

Varje del kommer göras i olika etapper där du själv väljer hur mycket hjälp du vill ha av mig. Det kommer finnas en liten hjälp där du får tips av mig vad du skall tänka på och det finns en stor hjälp då du får hela koden som behövs för den delen. Du kommer sällan få hela koden utan endast den delen som jag belyser i just den delen. TIPS: Det kan vara smart att kolla på kodraden för att få ett hum om var koden skall placeras, fast du behöver tänka själv naturligtvis.

När grundkraven är genomförda så finns det möjlighet att bygga vidare på banken och använda dina nyvunna kunskaper för att bygga en mer utvecklad applikation.

2. Planering

När vi nu skall lösa en något större uppgift än vad vi tidigare har gjort så är det viktigt att vi börjar med att fundera på hur vi kan dela upp uppgiften i mindre delar och försöka lösa del för del. Senare, när vi är mer vana vi att lösa denna typ av uppgifter så kräver det mindre planering men om uppgiften är komplex och lösningen är komplicerad så kommer det krävas mer planering. Vi börjar med att punkta upp de saker som vi redan nu vet att vi skall lösa och försöker också sätta dem i rätt ordning, det gör det enklare senare. Denna planering kommer vi behöva gå tillbaka till med jämna mellanrum och bocka av färdiga delar men också lägga till och justera de punkter som då finns kvar. Se det som ett recept på hur vår lösning skall genomföras.

2.1 Grovplanering

Vi börjar med en grovplanering med de saker som vi redan nu vet. I samband med att jag lägger till punkter så lägger jag dem i rätt ordning utifrån i vilken ordning jag just nu tror att de skall skapas/lösas.

  • Eftersom det är en konsollapplikation vi bygger så kommer vi behöva en programloop som går runt så länge vi vill att den skall göra detta.
  • I programloopen kommer vi behöva bygga en meny och sedan ta emot ett val för att köra mindre delprogram som;
    • Skriva ut saldot
    • Göra en inmatning
    • Göra ett uttag
    • Skriva ut transaktioner
  • Vi behöver också kunna lagra transaktionerna i en fil för att inte kontot skall nollställas vid uppstart varje gång.

Där har vi några funktioner som vi redan vet att vi behöver, det dyker säkert upp fler saker under arbetets gång, men vi börjar här.

2.2 Skissa applikationen

Här skulle jag normalt göra en enklare skiss över applikationen om den hade varit grafisk. Nu skall hela applikationen vara textbaserad men det är ändå smart att göra någon form av skiss för att ha något att utgå ifrån.

Lilla hjälpen [klicka för att visa]

Bra, nu har du förhoppningsvis en skiss på hur din applikation skall se ut. Det kan kännas lite onödigt att göra detta på en enkel textbaserad applikation men min tanke är att vi utvecklar denna applikation på ett visst sätt så att du sedan kan dra nytta av de olika stegen även när du senare skall bygga egna projekt, oavsett om det är konsollapplikationer, grafiska applikationer, spel eller någon annan applikation. Ofta är det stor hjälp att ha en bild av applikationens utseende tidigt i utvecklingsprocessen.

Då känner vi oss klara så här långt. Än så länge har vi inte programmerat någonting men det kommer vi börja med i nästa del.

3. Kodens struktur

Nu har vi kommit så långt att det är dags att börja koda. Detta kan göras på flera olika sätt och ju duktigare du blir att bygga applikationer desto större steg kan du ta och direkt ge dig på lösningar som är avancerade och ligger nära den slutliga versionen. Eftersom detta är det första tillfället som vi bygger en större applikation så kommer vi bygga den steg för steg och sedan göra funktionerna mer och mer avancerade på vägen. Det innebär också att vi kommer bygga om vissa delar flera gånger men det är för att du skall förstå hela processen och känna att du hänger med i de olika stegen.

3.1 Bygga programloopen

Vi kommer börja med att bygga programloopen så att vi har en huvudmeny som visas och som vi sedan kan lägga alla delprogram i. Med delprogram så menar jag där vi visar saldo/transaktioner, gör en inmatning och utmatning. Till programloopen hör möjligheten att avsluta applikationen så den bygger vi med i denna delen.

Lilla hjälpen [klicka för att visa]

Testa nu applikationen och se att om du matar in något val så skrivs info det delprogrammet ut. Alla felaktiga val, som är numeriska, göra att felaktigt val skrivs ut och sedan slutligen så avslutas programloopen när användaren matar in talet 0. Just nu finns det ingen felhantering, att mata in något annat än ett heltal kommer krascha våran programloop. Detta kommer vi ta hand om senare.

4 Hantera saldo

Det blir ju ingen bra bankapplikation om vi inte jobbar med ett banksaldo.

4.1 Lagra saldo

Saldot måste lagras på något sätt, för att få igång applikationen så börjar vi med att göra detta på enklast möjliga sätt. Vi kommer senare bygga om och ut logiken kring detta.

Lilla hjälpen [klicka för att visa]

4.2 Skapa en insättning

Dags att fixa funktionalitet för att kunna sätta in pengar på kontot.

Lilla hjälpen [klicka för att visa]

4.3 Skapa ett uttag

Kan vi sätta in pengar på kontot så vill vi ju kunna ta ut pengar också. Dags att fixa funktionalitet för detta.

Lilla hjälpen [klicka för att visa]

Testar du applikationen nu så skall det förhoppningsvis inte ge några error. Men vad händer om du tar ut mer pengar än vad som finns på kontot? Jo det blir ett negativt saldo. Så kan vi ju inte ha det. Dags att göra en kontroll att vi inte kan ta ut mer pengar än vad vi har.

4.4 Förhindra negativt saldo

Skapa funktionalitet så att uttag inte kan vara större än det saldo som användaren har på sitt konto.

Lilla hjälpen [klicka för att visa]

Testa nu att det inte fungerar att ta ut mer pengar än vad du har på ditt saldo. Vad händer om du tar ut ett negativt saldo? Testa att ta ut ett större belopp än vad du har på kontot men gör det talet negativt.

Så kan vi ju inte ha det.

4.5 Förhindra negativa insättningar och uttag

Hela logiken kring vårt konto och saldo är att både insättningar och uttag matas in som positiva tal och sedan adderar eller subtraherar vi händelsen till saldot. Då måste vi neka användaren att mata in negativa tal.

Lilla hjälpen [klicka för att visa]

4.6 Testschema

Nu har du förhoppningsvis en fungerande enkel bank. Som du märker så behöver vi hela tiden testa olika delar av applikationen för att få koll på de saker som inte fungerar som det skall. När vi snart skall börja bygga om strukturen på banken så är det hela tiden viktigt att med jämna mellanrum testa applikationen så att det inte smyger sig in fel. När du blir mer rutinerad att bygga och testa applikationer så får du en känsla för vilka saker som kan behöva testas men fram tills du har den känslan så behöver du skapa ett testschema som vi utgår ifrån varje gång vi vill testa applikationen. Testschemat är ett levande dokument som vi fyller på allt eftersom vi bygger in ny funktionalitet. Det testschema vi tar fram nu ser ut så här.

Testschema

  • Skriv ut saldot. (saldo 1000kr)
  • Testa att sätt in 500kr. (saldo 1500kr)
  • Testa att ta ut 500kr. (saldo 1000kr)
  • Testa att sätta in -500kr. (går ej, felmeddelande)
  • Testa att ta ut -500kr. (går ej, felmeddelande)
  • Testa att ta ut 2000kr. (går ej, felmeddelande)
  • Testa att ta ut 1000kr. (saldo 0kr)
  • Skriv ut saldot. (0kr)
  • Mata in ett felaktigt värde i menyn. (heltal ger felmeddelande, decimaltal eller sträng ger error)
  • Skriv ett felaktigt värde vid insättning eller uttag. (decimaltal eller sträng ger error)

Testa igenom din applikation för att se att applikationen fungerar/reagerar enligt testschemat.

Som du ser i testschemat har jag redan listat saker som kraschar applikationen. Dessa måste vi bygga bort innan vi är helt klara med vår applikation. Det innebär dock inte att vi måste ta hand om detta redan nu men vi kan markera det lite extra i vårt testschema så att vi inte missar det senare.

Testschema

  • Skriv ut saldot. (saldo 1000kr)
  • Testa att sätt in 500kr. (saldo 1500kr)
  • Testa att ta ut 500kr. (saldo 1000kr)
  • Testa att sätta in -500kr. (går ej, felmeddelande)
  • Testa att ta ut -500kr. (går ej, felmeddelande)
  • Testa att ta ut 2000kr. (går ej, felmeddelande)
  • Testa att ta ut 1000kr. (saldo 0kr)
  • Skriv ut saldot. (0kr)
  • Mata in ett felaktigt värde i menyn. (heltal ger felmeddelande, decimaltal eller sträng ger error)
  • Skriv ett felaktigt värde vid insättning eller uttag. (decimaltal eller sträng ger error)

Säkerhetskopiera

Här kan det vara lämpligt att säkerhetskopiera de kodfiler du har skapat. Det enklaste sättet är troligtvis att spara alla filer i PyCharm och sedan ta en kopia på hela mappen i Finder. I nästa del så skall vi bygga om koden en del och då kan det vara skönt att gå tillbaka till en fungerande version ifall det skulle bli stora problem i koden.

5. Listor

I uppgiften står det att vi måste lagra alla transaktioner och inte bara saldot. Det innebär att vi behöver lagra transaktionerna i en lista.

5.1 Implementera lista

Då skapar vi en variabel som lagrar transaktionerna och gör den första insättningen på 1000kr.

Jag tar inte bort variabeln saldo ännu, den hjälper mig att tala om vad som skall göras och var. När jag senare fullt ut har implementerat funktionalitet kring denna listan så tar jag bort variabeln saldo.

Lilla hjälpen [klicka för att visa]

5.1.1 Lägg alla transaktioner i listan

Nu gäller det att flytta alla händelser till listan. Byt ut alla uppdateringar av saldo att också skapa ett nytt element i listan.

Lilla hjälpen [klicka för att visa]

Testa nu att du kan sätta in och ta ut pengar. Vi vill just nu se att applikationen inte kraschar, att det verkligen lagras korrekt kommer vi ta i nästa punkt.

5.2 Skriv ut transaktionerna

Det har blivit dags att skriva ut alla transaktioner. Då behöver jag skapa ett nytt menyval i programloopen om jag inte tar bort något av de befintliga valen. Jag tänker att det är onödigt att skriva ut både saldo och en lista över alla transaktioner. Dessutom borde saldot vara synligt hela tiden i menyn. Jag fixar det först.

5.2.1 Skriv ut saldot i menyn

Inom ramen i min meny (menyhuvudet) så ser jag till att skriva ut saldot.

Lilla hjälpen [klicka för att visa]

5.2.2 Skriv ut transaktionerna

Som det nya valet i menyn så skall vi nu skriva ut transaktionerna när användaren gör detta valet.

Lilla hjälpen [klicka för att visa]

Testa så att transaktionerna skrivs ut, testa också att sätta in och ta ut pengarna så att du tydligt ser att insättningar och uttag lagras rätt i listan.

Funkar det? Om svaret är ja så är det bra, om svaret blir nej så finns det ett fel som du behöver fixa innan du går vidare.

5.2.3 Skriv ut transaktionerna i formaterad lista

Som du såg så är ju inte listan med transaktioner speciellt snygg. Hade du fått ett sådant kvitto i din bankomat så hade du troligtvis inte blivit superlycklig. Vi behöver snygga till det med någon form av numrering, kanske en snyggare rubrikrad och sedan ett aktuellt saldo på varje rad.

Jag tänker mig något sådant här;

Utskrift av transaktioner

Alla transaktioner:
 Nr     Händelse        Saldo
-----------------------------
 1.      1000 kr      1000 kr
 2.       500 kr      1500 kr
 3.      -600 kr       900 kr
 4.      1000 kr      1900 kr
 5.      -700 kr      1200 kr

Lilla hjälpen [klicka för att visa]

Testkör nu applikationen. När jag gör det så ser utskriften ut på följande sätt.

Utskrift av transaktionslistan

kodexempel

5.4 Beräkna saldot

När vi ändå har listan så finns det ingen mening att lagra saldot i en egen variabel detta behöver vi beräkna utifrån transaktionslistans innehåll. Detta vill vi dock göra som en funktion och det blir nästa avsnitt.

5.5 Tester

Vi har redan testat att de saker som ändrats fungerar med vår lista så det finns ingen mening att testa mer just nu.

Säkerhetskopiera

Här kan det vara lämpligt att säkerhetskopiera de kodfiler du har skapat. I nästa del så skall vi bygga om koden en del och då kan det vara skönt att gå tillbaka till en fungerande version ifall det skulle bli stora problem i koden.

6. Funktioner

Jag har redan varit inne på att vi behöver skapa en funktion som räknar ut saldot från transaktionslistan men vi kommer också skapa några andra funktioner som förbättrar applikationen och hjälper oss med i arbetet.

6.1 Funktionen balance()

Vi behöver skapa en funktion som beräknar saldot, vi döper den till balance(), på vårt konto. När denna är gjord så kan vi förhoppningsvis ta bort variabeln saldo som inte längre behövs.

Lilla hjälpen [klicka för att visa]

6.1.1 Ersätt variabeln saldo

Nu är det dags att kolla om variabeln saldo finns på något mer ställe där den kan ersättas av funktionen balance(). Vi hittar ett ställe där den behöver ersättas och det är när vi gör ett uttag. När detta sker så måste vi kolla att uttaget inte är större än saldot.

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

Testa nu att kommentera bort alla ställen där variabeln saldo används och testa sedan igenom applikationen. För att vara säker på att alla tester fungerar så använd testschemat som vi använt tidigare.

För mig fungerar applikationen på samma sätt som tidigare, de buggar som jag visste om sedan tidigare har inte självläkt och inga nya har tillkommit. Det innebär att jag nu kan ta bort allt som har med variabeln saldo att göra. Att kommentera bort delar av koden först innan den tas bort är smidigt ifall något inte fungerar som det är tänkt.

6.2 Fler funktioner

Nu när vi ändå håller på med funktioner så kan det vara läge att fundera på att skapa andra funktioner. Att skapa funktioner kan vi göra av olika anledningar. Den funktionen vi redan har skapat skapade vi för att det var en funktionalitet som vi behöver använda oss av vid flera tillfällen. Det finns ytterligare en sådan funktionalitet och det rör inmatningar och de fel som kan bli om vi matar in ett felaktigt värde. Det jag tänker på är inmatningar av tal som görs vid inmatning, uttag och vid val i menyn. Där skulle vi behöva säkerställa med en try-except-sats att applikationen inte kraschar.

6.2.1 Funktionen validate_int()

Funktionen validate_int() skapas för att ta hand om inmatning av heltal och hantera de eventuella fel som kan ske vid en inmatning.

Denna funktionen bygger jag med lite speciell logik så den vill jag visa hur den fungerar.

Funktionen validate_int()

kodexempel

Denna funktionen kräver nog lite förklaring. Jag har två inparametrar, dels output som blir det meddelande som skrivs ut till användaren så att hen vet vad hen förväntas mata in. Den andra inparametern är det felmeddelande som skrivs ut om användaren har matat in ett felaktigt värde. Med felaktigt värde menas decimaltal eller text. Ett negativt tal kommer inte anses vara felaktigt och 0 är ej heller felaktigt i denna funktion. Det negativa talet skulle vi kunna bygga in en kontroll för eftersom vi inte vill ha negativa inmatningar i vårt system. Talet 0 däremot behöver användaren kunna mata in för att stänga av applikationen. Eftersom funktionen nu heter validate_int() så är det precis det vi gör, vi kollar att talet som matas in är ett heltal. Själva logiken vi använder oss av för det inmatade talet lägger vi på andra platser i koden.

En while-loop bygger upp valideringen och denna bryts när vi har lyckats göra om det inmatade värdet till ett heltal. Funkar inte konverteringen så skapas en exception och ett meddelande skrivs ut. Sedan får användaren en chans till att skriva ett korrekt värde. När ett korrekt värde är inmatat så returneras detta från funktionen.

Anrop till denna funktion görs på tre ställen, först vid inmatningen i menyn...

Anrop av validate_int()

kodexempel

... sedan vid insättning av pengar ...

Anrop av validate_int()

kodexempel

... och slutligen vid uttag av pengar.

Anrop av validate_int()

kodexempel

Jag förde tidigare ett kort resonemang om vilka orsaker det kan finnas att skapa en funktion. Vi har skapat funktioner för att det är kod/algoritmer som återkommer flera gånger men det kan också vara mening att skapa funktioner för att få en mer lättläst kod. När vi skall skriva ut alla transaktioner och bygga upp något som liknar ett kontoutdrag så är det kod som sträcker sig över ca 10 rader och som inte är så kompakt och lättläst som mycket av den andra koden vi har skrivit. Jag vill göra om detta till en funktion för att kunna rensa upp lite i den delen av koden.

6.2.2 Funktionen print_transactions()

Vi tar all kod som har att göra med utskriften av transaktionerna och lägger detta i funktionen print_transactions() och anropar denna funktion från det ställe där den koden ligger för tillfället.

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

Testa nu att applikationen fungerar som det är tänkt. Om vi kikar på vårt testschema så bör vi nu ha löst de två rödmarkerade buggarna som vi hade sedan tidigare. Testa och se om dessa har försvunnit och att inte några nya har dykt upp.

Testschema

  • Skriv ut saldot. (saldo 1000kr)
  • Testa att sätt in 500kr. (saldo 1500kr)
  • Testa att ta ut 500kr. (saldo 1000kr)
  • Testa att sätta in -500kr. (går ej, felmeddelande)
  • Testa att ta ut -500kr. (går ej, felmeddelande)
  • Testa att ta ut 2000kr. (går ej, felmeddelande)
  • Testa att ta ut 1000kr. (saldo 0kr)
  • Skriv ut saldot. (0kr)
  • Mata in ett felaktigt värde i menyn. (heltal ger felmeddelande, decimaltal eller sträng ger error)
  • Skriv ett felaktigt värde vid insättning eller uttag. (decimaltal eller sträng ger error)

Hos mig fungerar det och nu kan jag ta bort den röda markeringen på de buggar som vi tidigare hade.

Testschema

  • Skriv ut saldot. (saldo 1000kr)
  • Testa att sätt in 500kr. (saldo 1500kr)
  • Testa att ta ut 500kr. (saldo 1000kr)
  • Testa att sätta in -500kr. (går ej, felmeddelande)
  • Testa att ta ut -500kr. (går ej, felmeddelande)
  • Testa att ta ut 2000kr. (går ej, felmeddelande)
  • Testa att ta ut 1000kr. (saldo 0kr)
  • Skriv ut saldot. (0kr)
  • Mata in ett felaktigt värde i menyn. (ger felmeddelande)
  • Skriv ett felaktigt värde vid insättning eller uttag. (ger felmeddelande)

Skönt, nu kan vi gå vidare.

Säkerhetskopiera

Här kan det vara lämpligt att säkerhetskopiera de kodfiler du har skapat. I nästa del så skall vi bygga om koden en del och då kan det vara skönt att gå tillbaka till en fungerande version ifall det skulle bli stora problem i koden.

7. Funktioner i egen fil

Vi har just nu tre funktioner, även om det inte verkar så mycket så tar det upp ca 45 rader av koden. Vi kommer skapa fler funktioner senare i uppgiften och det är lika bra att göra lite bättre plats. Jag vill därför flytta alla funktioner till en fil som endast innehåller funktioner. Jag döper filen till functions.py

7.1 functions.py

Flytta alla funktioner till denna filen. Importera sedan functions.py i den filen där programmet ligger.

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

Testar du nu att köra bank.py så kommer du få några error som beror på att listan transactions inte går att komma åt från functions.py. Det finns nu tre sätt att lösa detta på;

  1. Att skicka in listan med transaktioner till varje funktion som behöver den.
  2. Att flytta deklarationen av listan till functions.py.
  3. Att lägga de variabler som behöver finnas i flera filer i en egen fil och sedan importera denna fil där det behövs.

Alla tre lösningarna har sina för- och nackdelar. Att skicka in listan till alla funktioner tar ju bort möjligheten att låta denna lista vara tillgänglig överallt i hela applikationen. Att deklarera alla globala variabler i

functions.py

vore enklast för när jag importerar functions.py i bank.py så skulle dessa variabler bli tillgängliga även i bank.py. Nackdelen med detta är ju att vi har skapat en fil för funktioner och inget annat. Därför väljer jag det tre sättet och det är att skapa filen config.py där jag deklarerar de globala variabler som jag vill skapa. En global variabeln är en variabel som jag vill kunna nå från kod oavsett i vilken fil denna kod finns.

7.2 config.py

Skapa nu en ny fil, jag döper den till config.py, deklarera transaktionslistan här. Importera sedan denna fil till functions.py, då kommer den vara tillgänglig även i bank.py eftersom den importerar allt från functions.py och då följer även allt som importerats till den filen också med.

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

7.3 Testschema

Inga nya koder är skrivna och det vore märkligt att det skulle smugit sig in nya buggar. Gör en kortare test om du vill där du ser att listan med transaktioner och någon funktion används. Funkar det så vet du att filerna functions.py och config.py läses in korrekt.

8. Att lagra transaktionerna i en fil

Det har blivit dags att lagra transaktionerna på ett sätt som gör att kontots saldo, och transaktioner, finns kvar även nästa gång vi öppnar applikationen. Att låta en applikation nollställas vid varje tillfälle den körs är ju inte så meningsfullt. Vi kommer lagra alla transaktioner i en fil och det är inga konstigheter, men vi behöver fundera på hur vår applikation skall fungera ihop med filen.

8.1 Planering av lösning

Följande frågor behöver vi svara på och det är dessa svar som avgör hur vi skall koda logiken kring filen.

  • Hur skall transaktionerna lagras permanent?
    • Datalagring kan ske på så många olika sätt, det enklaste sättet och den enda sättet vi har lärt oss är att lagra data i en fil. I andra kurser som har med programmering att göra kommer vi kika på olika former av databaser men det får bli senare.
  • Hur skall transaktionerna finnas tillgängliga när programmet körs?
    • Det skulle kunna gå att hela tiden läsa från filen varje gång saldot skall beräknas, varje gång transaktionerna skall listas. Det blir dock lite tidsödande eftersom den processen tar lite tid. Vi har redan en lista med alla transaktioner så det känns naturligt att bygga vidare på denna.
  • Hur skall vi göra med nya insättningar och uttag?
    • Här blir det lite mer intressant. Vi skulle kunna läsa in hela filen till vår lista och sedan låta alla nya insättningar och uttag endast lagras i listan. Fördelen med det är att listan innehåller all gällande information. Då skulle vi kunna spara ner listans transaktioner till filen när vi vill eller när programmet avslutas. Nackdelen är säkerheten, om vi har gjort några transaktioner, som inte sparats ner till listan, och applikationen kraschar då är ju dessa transaktioner borta. Detta är en lösning som kan fungera i fall där data är mindre viktigt än vad det är för oss i vår bankapplikation. Därför så måste vi se till att en transaktion både lagras i listan och i filen.
  • Vad händer om vi vill ta bort eller nollställa ett konto?
    • Den enklaste lösningen är att ta bort hela filen. Det går alltid att tömma en fil på allt innehåll men samtidigt vill vi inte ha massa tomma filer liggande. Om vi tänker ett steg längre och tänker oss att denna applikationen kan användas av flera användare och varje användare kan ha flera konton så skulle det sluta med att vi har ett gäng med helt tomma filer. Min rekommendation är att vi tar bort filen när ett konto skall tas bort eller tömmas.
  • Vad händer om transaktionsfil inte finns?
    • Eftersom vi i punkten innan tar bort en fil så måste vi ju skapa en fil om den inte finns och då skall vi också börja med att göra en insättning på 1000kr.

Sammanfattningsvis så vill jag att följande regler skall gälla för vår fil och listan med transaktioner.

  1. Vid uppstart av programmet
    • Om filen inte finns skapa filen och sätt in 1000kr.
    • Läs in hela filen till transaktionslistan.
  2. Transaktioner som görs under programmets gång skall lagras både i listan och i filen.
  3. Om konto tas bort skall
    • filen tas bort
    • listan tömmas
    • sedan skapas en ny fil, med 1000kr, och denna läses in till listan.

Med en bra planering så kan vi skriva effektivare kod och behöver inte testa oss fram allt för mycket.

Nu behöver man inte bygga in denna funktionalitet i precis den ordningen men eftersom vi ändå behöver skapa en fil för att kunna börja arbeta med den så känner jag att det är lämpligt att ta det i denna ordningen.

8.2 Skapa filen om den inte finns

Vi skall skapa en funktion som kollar om filen finns. Om den inte finns så skall den skapas.

Vi kan använda open() med parametern x för att endast skapa filen om den inte finns. Vi vill ju inte skriva över en befintlig fil vilket vi gör med parametern w. Om filen inte finns så skapas den, finns den så ger det ett error. Detta kan vi utnyttja genom att sätta det inom ett try-except-block. Eftersom jag redan nu vet att denna funktionalitet behöver användas flera gånger, vid uppstart av applikationen och vid borttagande av konto/fil, så lägger jag det som en funktion. Jag kommer också behöva skapa en global variabel som lagrar filnamnet.

Dags att skriva lite kod.

Lilla hjälpen [klicka för att visa]

Vi kommer senare behöva skriva om funktionen lite eftersom vi lägger en transaktion i filen och det kommer vi behöva göra vid andra tillfällen i koden också. Men vi återkommer till detta.

8.3 Läs in transaktioner från fil till transaktionslistan

Då tar vi tag i nästa punkt och det är att överföra alla transaktioner i filen till vår transaktionslista när applikationen startar upp. Lägg detta i en egen funktion.

Lilla hjälpen [klicka för att visa]

Några saker som slår mig kring denna funktionen och den koden jag har skrivit som vi behöver åtgärda eller förändra.

  1. Funktionen check_file_exists() kommer endast köras i samband med att funktionen read_file() skall köras. Därför kan vi anropa den funktionen innifrån funktionen read_file().
  2. När du testar applikationen så ser du att vi får 2000kr i startbelopp. Det beror på att 1000kr kommer från filen och sedan läggs det till 1000kr i transaktionslistan på rad 6 i bank.py. Ta bort den raden.

8.4 Skriv transaktioner till filen

Just nu lägger vi till en transaktion till listan vid tre tillfällen; insättning, uttag och när vi läser från fil. Eftersom vi gör samma sak många gånger borde vi lägga detta i en funktion, speciellt som vi nu både skall lägga en transaktion till listan och till filen. Vi skapar en funktion som heter add_transaction() som lägger till transaktionen till både listan och filen. Anropa sedan funktionen där vi lägger transaktioner till listan.

Lilla hjälpen [klicka för att visa]

Testa nu att göra insättningar och uttag för att se att transaktionerna i listan speglar transaktionerna i filen. För mig fungerar det bra.

Den funktionen som vi precis skapade innehåller logik som vi vill använda också när vi fyller listan från filen. Vi hade kunnat fortsätta had et som vi har det just nu men om vi vill göra något särskilt med de transaktionerna som skall läggas in i listan så vore det bra att ha all den logiken på samma ställe. Vi låter anropet från read_file() för att lägga in data i listan gå via funktionen add_transaction().

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

Testa att starta om applikation och testa.

För mig kommer inte applikationen igång och det beror på att jag har lyckats läsa in varje transaktion från filen, lägga dem i transaktionslistan och dessutom i filen vilket göra att filen kommer aldrig bli slut då jag hela tiden lägger till nya värden.

Var det så smart att förstöra något som fungerade? Det kan kännas lite onödigt men det blir ändå en bättre struktur. Det jag behöver lägga till just nu är att till funktionen add_transaction() tala om ifall just denna transaktion skall läggas till i filen och transaktionslistan eller bara i transaktionslistan. Det jag vet är att alla transaktioner skall lagras i listan men bara vissa skall skrivas till filen. Jag bygger om funktionen add_transaction() enligt följande.

add_transaction()

kodexempel

Här kan det behöva förklaras lite.

Funktionen tar emot två inparametrar, först transaktionen och sedan en parameter som jag har döpt till toFile som har fått ett defaultvärde som är False. Detta innebär att om jag inte skickar in någon andra parameter så kommer toFile få värdet False och då ser du på rad 85 att då kommer inte transaktionen skickas till funktionen write_transaction_to_file() som jag har skapat.

write_transaction_to_file()

kodexempel

På detta sätt kan jag nu styra vilka transaktioner som skall lagras i filen. add_transaction(500, True) kommer lagras i filen men inte add_transaction(1000).

Vi behöver då ändra alla anrop till funktionen add_transaction() så att de skriver till fil, där vi vill det, eller inte skriver till fil.

Den lilla hjälpen behövs inte här, det står i texten ovan vad som måste göras.

Stora hjälpen [klicka för att visa]

Testa nu igen. Har du lika tur som jag så finns det ett väldigt stort saldo och det kommer ju av att filen läste och skrev på samma gång tidigare. Kikar du på transaktionerna så lär du se ett mönster för transaktionerna.

8.5 Avsluta konto

Eftersom vi nu har en transaktionsfil som är korrupt så kan det vara lägligt att bygga in möjligheten att avsluta kontot vilket vi gör genom att ta bort filen. Att ta bort en fil gör vi med funktionen remove i paketet os, vilket vi når genom att skriva import os och sedan os.remove("filensnamn").

Lilla hjälpen [klicka för att visa]

8.6 Testschema

Det har blivit dags att testa applikationen ännu en gång. Vi kör vårt vanliga testschema men först måste vi se om det finns funktionalitet som behöver testas nu men som inte fanns tidigare.

Jag har lagt till tre punkter som har med filen att göra.

Testa nu igenom hela testschemat och se till så att allt fungerar som det skall.

Testschema

  • Skriv ut saldot. (saldo 1000kr)
  • Testa att sätt in 500kr. (saldo 1500kr)
  • Testa att ta ut 500kr. (saldo 1000kr)
  • Testa att sätta in -500kr. (går ej, felmeddelande)
  • Testa att ta ut -500kr. (går ej, felmeddelande)
  • Testa att ta ut 2000kr. (går ej, felmeddelande)
  • Testa att ta ut 1000kr. (saldo 0kr)
  • Skriv ut saldot. (0kr)
  • Mata in ett felaktigt värde i menyn. (ger felmeddelande)
  • Skriv ett felaktigt värde vid insättning eller uttag. (ger felmeddelande)
  • Skriv ut alla transaktioner och jämför med filen transactions.txt.
  • Testa att avsluta ett konto. (saldo 1000kr)
  • Testa att stänga ner applikationen, ta bort transactions.txt och starta sedan om applikationen. (saldo 1000kr)

Min applikation klarade sig igenom hela testschemat.

Det är dags att kika på uppgiften och se om vi har något kvar att göra på vår applikation. Jag läser igenom punkterna 1.1 och 1.1.1 längst upp i detta dokument och inser att vi faktiskt har gjort färdigt grundkraven för vår lilla bankapplikation.

9. Avslutning av tutorial

Dags att avrunda denna tutorial och det gör vi på samma sätt som du bör avrunda och genomföra en enklare kvalitetskontroll av alla projekt.

9.1 Gå igenom koden och städa upp

Snygga till och ta bort alla gamla kodsnuttar som du har kommenterat bort och alla testutskrifter du har gjort.

Kolla sedan igenom koden så att den är kommenterad och dokumenterad på det sätt som du vill kommentera, se till att strukturen är bra och att det är lagom luftigt.

9.2 Testa applikationen

Om du har behövt städa väldigt mycket i din kod så kanske du har tagit bort för mycket eller stökat till det lite med indentering och brutit iterationer, funktioner eller selektioner. Är du det minsta osäker så kan det vara bra att en gång till köra igenom testschemat. Allt för många elever tror att de har en fungerande applikation för de skulle ju bara ändra en liten grej, hur kan det ha gjort att hela applikationen inte längre fungerar?

9.3 Inför inlämning/redovisning

Dags att börja förbereda inlämning/redovisning. Kolla vad som gäller.

10. Koden för banken

Här finns all kod för den fungerande applikationen.

Hjälp [klicka för att visa]

bank.py

kod

functions.py

kod kod

config.py

kod