Varför är dessa Java projekt så avancerat skrivet?

Permalänk
Medlem
Skrivet av snajk:

Det är ju rätt bra med interfaces för enhetstestning också. Beroende på hur man skriver sina tester förstås, men jag tycker det är rätt trevligt att kunna ha "dummy"-klasser som använder samma interface som de faktiska klasserna i applikationen. Mocking är ju också trevligt förstås men det blir mycket duplicering om applikationen inte är helt trivial.

Såvida men inte främst skriver ren, funktionell kod. Då är ytan man behöver interfaces för testning för väldigt liten.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

Permalänk
Tangentbordskonnässör
Skrivet av Bryal:

Såvida men inte främst skriver ren, funktionell kod. Då är ytan man behöver interfaces för testning för väldigt liten.

Testing utan interfaces och mocks låter... spännande.
Hur bygger man tester för hela flödet?
Genom att köra en in memory databas som man seedar med data varje gång?
Hur gör man unittester där man mockar bort saker som är överflödigt?

Eller är det så att man rent av skiter i tester när man skriver "ren, funktionell kod" ?

Permalänk
Medlem
Skrivet av huttala:

Testing utan interfaces och mocks låter... spännande.
Hur bygger man tester för hela flödet?
Genom att köra en in memory databas som man seedar med data varje gång?
Hur gör man unittester där man mockar bort saker som är överflödigt?

Eller är det så att man rent av skiter i tester när man skriver "ren, funktionell kod" ?

En ren (eng. pure) funktion har inga sidoeffekter. Den tar ett argument och ger ett resultat, och den kommer alltid ge samma resultat för samma argument. Då de inte kan ha sidoeffekter, kan de inte heller interagera med databas. Allt som allt gör detta att rena funktioner är väldigt enkla att testa med till exempel property based testing.

Självklart är det poänglöst om hela programmet är en ren funktion -- då kan man ju inte göra något praktiskt! Men tanken är att man delar upp programmet i en funktionell kärna med affärslogiken etc., och ett imperativt skal med databasinteraktion etc. Idén kallas Functional Core, Imperative Shell. Det är mest bara i det imperativa skalet som man behöver mocka, och hela poängen är att man håller detta skalet så minimalt som möjligt.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

Permalänk
Tangentbordskonnässör
Skrivet av Bryal:

En ren (eng. pure) funktion har inga sidoeffekter. Den tar ett argument och ger ett resultat, och den kommer alltid ge samma resultat för samma argument. Då de inte kan ha sidoeffekter, kan de inte heller interagera med databas. Allt som allt gör detta att rena funktioner är väldigt enkla att testa med till exempel property based testing.

Självklart är det poänglöst om hela programmet är en ren funktion -- då kan man ju inte göra något praktiskt! Men tanken är att man delar upp programmet i en funktionell kärna med affärslogiken etc., och ett imperativt skal med databasinteraktion etc. Idén kallas Functional Core, Imperative Shell. Det är mest bara i det imperativa skalet som man behöver mocka, och hela poängen är att man håller detta skalet så minimalt som möjligt.

Ok ok, jag förstår. Men om du i denna funktion behöver lägga till något, eller ta bort något. Hur vet du då att de andra 200+ beroenden du har på funktionen fungerar som de ska utan tester? Är det då genom integrationstester enbart, själva funktionerna testas genom hela kedjan och Imperative Shell är då mockat, men allt annat live?

Förövrigt låter Functional Core och Imperative Shell som business layer och DAL. Så det verkar ju rent principiellt vara ungefär samma sak.

Det som får mina varningsklockor att ringa är att man inte testar och att "En ren funktion har inga sidoeffekter. Den tar ett argument och ger ett resultat, och den kommer alltid ge samma resultat för samma argument.", det låter som något som håller ungefär 1 vecka i ett större team, sen är det kört.

Permalänk
Medlem
Skrivet av huttala:

Ok ok, jag förstår. Men om du i denna funktion behöver lägga till något, eller ta bort något. Hur vet du då att de andra 200+ beroenden du har på funktionen fungerar som de ska utan tester? Är det då genom integrationstester enbart, själva funktionerna testas genom hela kedjan och Imperative Shell är då mockat, men allt annat live?

Kan inte riktigt relatera denna frågan till hur jag arbetar med funktionell kod, så kan inte ge dig ett bra svar.

Skrivet av huttala:

Förövrigt låter Functional Core och Imperative Shell som business layer och DAL. Så det verkar ju rent principiellt vara ungefär samma sak.

Ja, jag kan tänka mig att det i grova slängar blir ganska likt tänk även i OOP världen.

Skrivet av huttala:

Det som får mina varningsklockor att ringa är att man inte testar och att "En ren funktion har inga sidoeffekter. Den tar ett argument och ger ett resultat, och den kommer alltid ge samma resultat för samma argument.", det låter som något som håller ungefär 1 vecka i ett större team, sen är det kört.

Ja alltså, just i detta fallet tänkte jag på när jag arbetar i Haskell. Där garanterar typsystemet att funktionerna är rena, så det är inget som kräver programmerardisciplin eller tester. Till exempel så kan en funktion med typen Int -> Int inte logga, läsa från databas, eller nåt annat sånt. Den kan bara manipulera ett heltal på något rent sätt och spotta ut ett nytt eller samma heltal.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

Permalänk
Medlem
Skrivet av huttala:

Ok ok, jag förstår. Men om du i denna funktion behöver lägga till något, eller ta bort något. Hur vet du då att de andra 200+ beroenden du har på funktionen fungerar som de ska utan tester? Är det då genom integrationstester enbart, själva funktionerna testas genom hela kedjan och Imperative Shell är då mockat, men allt annat live?

Förövrigt låter Functional Core och Imperative Shell som business layer och DAL. Så det verkar ju rent principiellt vara ungefär samma sak.

Det som får mina varningsklockor att ringa är att man inte testar och att "En ren funktion har inga sidoeffekter. Den tar ett argument och ger ett resultat, och den kommer alltid ge samma resultat för samma argument.", det låter som något som håller ungefär 1 vecka i ett större team, sen är det kört.

Funktionella språk är en helt annan värld, du kan inte kalla på databasen och göra en ändring inuti en funktion, så det blir konstigt att använda det ordet för en helt annan sak i java eller något annat.

Permalänk
Skrivet av snajk:

Det är ju rätt bra med interfaces för enhetstestning också. Beroende på hur man skriver sina tester förstås, men jag tycker det är rätt trevligt att kunna ha "dummy"-klasser som använder samma interface som de faktiska klasserna i applikationen. Mocking är ju också trevligt förstås men det blir mycket duplicering om applikationen inte är helt trivial.

Hur fungerar enhetstestning?

Kan det vara så att om jag behöver funktionaliteter så skapar jag ett interface och där efter anvönder jag JUnit? För att skapa logik till mitt interface? Så när jag har mitt interface så kan jag använda det med koden min. När jag är klar med min kod så kopplar jag ihop den med andras kod?

Permalänk
Skrivet av Bryal:

Bra råd, i min åsikt. Gjorde själv flera liknande förenklingar på mitt förra jobb. Koden jag tog över var full med OOP patterns som var där mer "för sakens skull" än för att de faktiskt löste några problem. Ett speciellt vanligt pattern var att alla klasser också hade ett associerat interface, och all kod som använde klassen använde inte klassen direkt, utan interfacet. Tror tanken var att programmet skulle vara "utökningsbart" ifall man någonsin lade till en variant av en klass, men som implementerade samma interface. I praktiken hade de dock alltid bara en enda implementerare av varenda interface, så det var bara onödig komplexitet. Jag tycker man ska skriva kod först och främst för problemen man faktiskt har idag, och inte för de man möjligen kommer ha imorgon. Refaktorering är alltid ett alternativ.

Iallafall, skrev om koden, och tog bort allt jag ansåg vara övergenerellt bloat. När jag var klar var programmet ca. 8k rader, istället för ca. 40k som det var innan... Det nya programmet var betydligt mer lättläst, och man kunde faktiskt ha hela grejen i huvudet, utan att trassla in sig på alla de tomma abstraktionerna.

EDIT:
Var dock medveten om att långt ifrån alla bruk av interfaces är bloat. Abstraktion är absolut inte något dåligt per automatik. Ofta gör det koden mycket simplare om man kan identifiera rimliga abstraktioner i koden. Problemet tror jag mest är att många nyexade OOP-programmerare inte ännu har känslan för när abstraktion är passande, så de angriper problemet mer systematiskt, och klämmer in abstraktioner på alla ställen som deras favoritbok om OOP patterns säger att det är möjligt.

Känner igen problemet. Man skapar en kod som är så komplex så att den kan utföra allt. Mest bara för att man själv ska framstå som kompetent och pro.

Behövs ens OOP om man kan lösa problemet utan OOP?

Permalänk
Medlem
Skrivet av heretic16:

Hur fungerar enhetstestning?

Kan det vara så att om jag behöver funktionaliteter så skapar jag ett interface och där efter anvönder jag JUnit? För att skapa logik till mitt interface? Så när jag har mitt interface så kan jag använda det med koden min. När jag är klar med min kod så kopplar jag ihop den med andras kod?

Enhetstest är helt enkelt att du vill testa en klass och alla dess funktioner genom att anropa dom med given eller slumpad data och jämföra det mot det förväntade resultatet. Det hjälper framförallt vid komplexa projekt med hundratals klasser där en ändring på ett ställe kan påverka många andra, då kommer testerna (förhoppningsvis, om de är bra skrivna) upptäcka felet (ett gammal fall som ska fungera som inte längre gör det). Testerna körs vanligen så fort projektet sparas/kompileras/committas etc. Så att man upptäcker misstag så snart som möjligt.

Det finns många som förespråkar ’test-driven-design’ där man först skriver tester och sedan börjar utveckla för att matcha den förväntade, testbara, resultatet istället för att bara ’lösa problemet’ och strunta i tester.

Permalänk
Tangentbordskonnässör
Skrivet av heretic16:

Känner igen problemet. Man skapar en kod som är så komplex så att den kan utföra allt. Mest bara för att man själv ska framstå som kompetent och pro.

Behövs ens OOP om man kan lösa problemet utan OOP?

Jag får en svag känsla av att du blir överväldigad av allt nytt som OOP innebär och vill hitta en ursäkt att inte hålla på med det. Vilket är helt OK om man vill koda annat än Java, men ska du koda Java är det nog bara att bita i det sura och ta fram skolboken.

Det du kallar för komplext kallar jag för struktur. Förstår man inte strukturen och inte är villig att förstå den så kommer OOP föralltid vara "komplext". Nuförtiden kan jag kolla i de flesta projekt, ta reda på hur kodflödet ser ut och sedan veta exakt var vilken logik ska ligga och hur man har abstraherat bort beroenden från olika delar av logiken.

OOP behövs verkligen så fort det är större grejer som ska göras. Visst du kan bygga din todo-list utan OOP och hålla koll på allt, men så fort projektet blir större är det skönt att ha en grundläggande struktur att bygga på. Man bygger bara grunden en gång (vilket går jävligt snabbt när man vet hur man ska göra), sedan skalas applikationen upp utefter vad verksamheten vill ha för funktionalitet.

Du kan även skriva OOP som är helt åt skogen, vilket många gör (mig inkluderat, man är aldrig fullärd inom programmering) om de inte har någon som slår dem på fingrarna tills de förstår hur det funkar.
Det finns gott om skräckexempel där mindre team suttit själva i stora projekt i flera år där man missat fundamentala saker i början och den tekniska skulden är så stor att man måste bygga om allt från grunden.

Med det sagt går det alltid att overengineera projekt, att undvika det är något man får känsla för lite senare.

Permalänk
Medlem
Skrivet av heretic16:

Jag skulle nog säga att Java + Spring Boot + JPA är riktigt bra om man vill göra databaser för varje kund Så jag hade kört på det. Det blir ju lite OOP, men inte mycket.

Vill du ha ett exempel på Crud i Java?
https://github.com/alejandro-du/crudui/tree/master/demo/src/m...

Snyggt, elegant, mimialt med kod och man behöver bara specifiera entity för att skapa databasen. Alltså en klass. Bara en!

Så här ser databashantering ut i Java med Spring JPA.

Databasen:

@Entity @Getter @Setter public class CalibrationLogg { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long CID; // Comment for these calibration @NotNull private String comment; // y = S*AI + B private float SAI0; private float BAI0; private float SAI1; private float BAI1; private float SAI2; private float BAI2; private float SAI3; private float BAI3; }

Hur vi kommer åt databasen. Här kan man alltså lägga till getters och setters för att hitta rätt rad i databasen.
Exempel på en metod. Måste heta findByX, där X är namnet på fältet i entity-klassen.

public interface CalibrationLoggRepository extends JpaRepository<CalibrationLogg, Long>{ CalibrationLogg findByComment(String myComment); // Exempel }

Eller så kan man anropa databasen igenom att skriva detta fält.

@Autowired private CalibrationLoggRepository calibrationLoggRepository;

och sedan anropar man objektet "calibrationLoggRepository" så här:

List<CalibrationLogg> helaDatabasen = calibrationLoggRepository.findAll(); List<CalibrationLogg> allaRaderSomHarRadernaHejIDatabasen = calibrationLoggRepository.findByComment("Hej");

Supersmidigt i Spring Boot. Älskar verkligen detta. Java må vara tråkigt och stort, men så fort man börjar använda Spring Boot så blir livet enklare. Nu kan vi komma åt databsen och skriva till den. Inge SQL eller något sånt där.

Nu är ju det där väldigt förenklat. En verklig enterprise-applikation är väldigt sällan (aldrig?) så simpel att hela databasen endast skulle bestå av en enda tabell. Normalt sett skulle du skapa en Entity-class för varje tabell, sedan ett service-lager för manipulation av data, ett repository-lager för kommunikation mot datalagret, en controller för att hantera API-anrop från t.ex. en REST-klient o.s.v.

Sedan ska det sägas att Spring Boot och Spring Framework (som ditt exempel använder sig utav) är två skilda ting. Spring Boot kan förenklat jämföras med att du håller hela din applikationsserver i en container, vilket gör det lätt att snabbt bygga och köra din applikation utan att behöva sätta upp t.ex. en JBoss-instans och en webbserver etc.

Sedan, för att bidra till diskussionen, så bör man välja "rätt" verktyg för det jobb som ska utföras. Väljer du att programmera dina applikationer i Java (som främst är ett OOP-språk) så får du finna dig i att jobba enligt den paradigmen för att få ut full effekt av språket. Om man jobbar hårdvarunära kanske Java inte är rätt verktyg egentligen, utan där kanske C vore ett bättre val.

OOP är populärt i enterprise-världen då de problem som ska lösas enkelt kan förklaras m.h.a. objekt då det oftast är så pass abstrakt.
Nu har jag inte jobbat särskilt mycket med språk som är mer imperativa eller funktionella, men jag kan tänka mig att dessa lämpar sig bättre när det ska lösas problem som ligger närmare hårdvara då det sällan behöver vara särskilt abstrakt utan mer "pure", d.v.s. givet input A förväntas alltid output B.

Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk
Skrivet av noMad17:

Nu är ju det där väldigt förenklat. En verklig enterprise-applikation är väldigt sällan (aldrig?) så simpel att hela databasen endast skulle bestå av en enda tabell. Normalt sett skulle du skapa en Entity-class för varje tabell, sedan ett service-lager för manipulation av data, ett repository-lager för kommunikation mot datalagret, en controller för att hantera API-anrop från t.ex. en REST-klient o.s.v.

Nej. Detta var kod från min applikation. Den fungerar. Jag föredrar komponentstyrt(Vaadin) istället för REST. Men det har med att jag är så bekväm av mig.

Citat:

Sedan ska det sägas att Spring Boot och Spring Framework (som ditt exempel använder sig utav) är två skilda ting. Spring Boot kan förenklat jämföras med att du håller hela din applikationsserver i en container, vilket gör det lätt att snabbt bygga och köra din applikation utan att behöva sätta upp t.ex. en JBoss-instans och en webbserver etc.

Exakt. Spring Boot tycker jag bättre om. Allt bara fungerar.

Citat:

Sedan, för att bidra till diskussionen, så bör man välja "rätt" verktyg för det jobb som ska utföras. Väljer du att programmera dina applikationer i Java (som främst är ett OOP-språk) så får du finna dig i att jobba enligt den paradigmen för att få ut full effekt av språket. Om man jobbar hårdvarunära kanske Java inte är rätt verktyg egentligen, utan där kanske C vore ett bättre val.

Men känner jag att det är objekt jag jobbar med, dvs att jag vet att här kommer jag få upprepa massa kod som ska hantera t.ex. bankkonton eller bilmodeller. Redan här vet jag att OOP löser detta problem. Men är det att jag ska utföra mest bara instruktioner så känner jag att OOP har ingen nytta där.

Permalänk
Skrivet av huttala:

Jag får en svag känsla av att du blir överväldigad av allt nytt som OOP innebär och vill hitta en ursäkt att inte hålla på med det. Vilket är helt OK om man vill koda annat än Java, men ska du koda Java är det nog bara att bita i det sura och ta fram skolboken.

Jag skriva bara kod för att lösa problemet. Jag skriver inte kod för att lösa framtida problem, för dessa problem vet jag inte hur dom ser ut.
Tolka inte att jag skriver allt i en enda funktion. Jag strukturerar koden så varje funktion gör sin sak.

Men om man kommer från "den nya skolan" och inte vill bita i det sura äpplet? Jag menar, dagens teknik att lösa problem varierar för decennium. Det som är nytt idag, är helt ute om 10 år.

Skulle inte vara helt förvånade om REST-applikationer ses som föråldrat i framtiden.

Permalänk
Tangentbordskonnässör
Skrivet av heretic16:

1. Jag skriva bara kod för att lösa problemet.
2. Jag skriver inte kod för att lösa framtida problem, för dessa problem vet jag inte hur dom ser ut.
Tolka inte att jag skriver allt i en enda funktion. Jag strukturerar koden så varje funktion gör sin sak.

3. Men om man kommer från "den nya skolan" och inte vill bita i det sura äpplet? Jag menar, dagens teknik att lösa problem varierar för decennium. Det som är nytt idag, är helt ute om 10 år.

1. Du skapar bara mer problem för dig själv med den attityden.

2. Det är just för att du inte vet hur dina framtida problem ser ut som man ska strukturera koden rätt från början så att man lätt kan lägga expandera applikationen utan att röra den gamla koden som redan finns där.
Tester är väldigt viktigt i denna aspekt också, för då ser man direkt om man råkat sabba något beroende.

3. Du vill ju uppenbarligen inte lära dig hur det fungerar. Bara för att det kanske i framtiden ser ut på ett annat sätt så ska du skita i att lära dig fundamentala saker om hur man ska koda?
Då är det bara att hoppas på att du aldrig jobbar i team och får ta hand om din enorma tekniska skuld själv i så fall..

Java har funnits sen 1996, och är fortfarande väldigt populärt. Tror du det kommer försvinna inom snar framtid? Det tror inte jag. Kotlin som är lite som Javas lillebror har ju också samma tänk bakom språket i sig.
Samma sak med C#, det är väldigt likt Java, och blir ju inte mindre för var dag som går. Här i Örebro finns det knappt några jobb som inte kräver C# kunskaper.

Permalänk
Medlem
Skrivet av huttala:

1. Du skapar bara mer problem för dig själv med den attityden.

2. Det är just för att du inte vet hur dina framtida problem ser ut som man ska strukturera koden rätt från början så att man lätt kan lägga expandera applikationen utan att röra den gamla koden som redan finns där.
Tester är väldigt viktigt i denna aspekt också, för då ser man direkt om man råkat sabba något beroende.

3. Du vill ju uppenbarligen inte lära dig hur det fungerar. Bara för att det kanske i framtiden ser ut på ett annat sätt så ska du skita i att lära dig fundamentala saker om hur man ska koda?
Då är det bara att hoppas på att du aldrig jobbar i team och får ta hand om din enorma tekniska skuld själv i så fall..

Java har funnits sen 1996, och är fortfarande väldigt populärt. Tror du det kommer försvinna inom snar framtid? Det tror inte jag. Kotlin som är lite som Javas lillebror har ju också samma tänk bakom språket i sig.
Samma sak med C#, det är väldigt likt Java, och blir ju inte mindre för var dag som går. Här i Örebro finns det knappt några jobb som inte kräver C# kunskaper.

Bra och tydligt skrivet!

Nästan all programmering jag gör innehåller åtminstone till viss del OOP, eftersom nästan alla språk har sådan funktionalitet i kärnan och för att göra det enklare att testa och utöka som du nämner.

Jag tror dock (om jag läser mellan raderna) att TS vet detta och gör säkert delar av detta själv också, men gillar det inte och vill få medhåll

Permalänk
Medlem

Skulle inte vilja jobba i ett projekt ihop med TS. I verkligheten får man sällan ett enskilt litet problem som man blir färdig med vilket brukar vara fallet när man sitter hemma på kammaren och knackar kod. I industrin är det så att krav och scope ändras under projektets livstid och kodbasen kommer att växa och ska underhållas. Då är det ovärderligt att koden är strukturerad i isolerade utbytbara "moduler". Man ska t.ex. kunna byta databasleverantör utan att behöva göra ändringar genom hela kodbasen. Är det bra strukturerat så behöver man bara göra en ny implementering av ett interface som går att byta rakt av mot den gamla. Sen har vi så klart testningen som blir till ett helvete om allt sitter ihop "för hårt". Det blir dessutom besvärligt om man är flera som jobbar på samma kod eller om det kommer in nya utvecklare senare i projektet.

Även i funktionell programmering kan man ha ett liknande tankesätt även om det skiljer sig åt. Genom att skicka funktioner som parametrar till andra funktioner så kan man enkelt "mocka" olika delar och enhetstesta sin kod.

Att vara en bra utvecklare har inte så mycket att göra med att skriva fungerande kod som att skriva lättläst och välstrukturerad kod som gör det enkelt för andra utvecklare att jobba med.

Visa signatur

ASUS TUF Gaming B550M-PLUS ~ AMD Ryzen 5600 XT ~ ASUS TUF Gaming AMD Radeon RX 6800
Corsair Vengeance LPX Red 16GB (2x8GB) 2400MHz DDR4 ~ Samsung SSD 860 EVO M.2 1TB
Corsair RM750 750W 80+ Gold

Permalänk
Medlem
Skrivet av Netgear:

Skulle inte vilja jobba i ett projekt ihop med TS. I verkligheten får man sällan ett enskilt litet problem som man blir färdig med vilket brukar vara fallet när man sitter hemma på kammaren och knackar kod. I industrin är det så att krav och scope ändras under projektets livstid och kodbasen kommer att växa och ska underhållas. Då är det ovärderligt att koden är strukturerad i isolerade utbytbara "moduler". Man ska t.ex. kunna byta databasleverantör utan att behöva göra ändringar genom hela kodbasen. Är det bra strukturerat så behöver man bara göra en ny implementering av ett interface som går att byta rakt av mot den gamla. Sen har vi så klart testningen som blir till ett helvete om allt sitter ihop "för hårt". Det blir dessutom besvärligt om man är flera som jobbar på samma kod eller om det kommer in nya utvecklare senare i projektet.

Även i funktionell programmering kan man ha ett liknande tankesätt även om det skiljer sig åt. Genom att skicka funktioner som parametrar till andra funktioner så kan man enkelt "mocka" olika delar och enhetstesta sin kod.

Att vara en bra utvecklare har inte så mycket att göra med att skriva fungerande kod som att skriva lättläst och välstrukturerad kod som gör det enkelt för andra utvecklare att jobba med.

Sedan ska man inte lösa problem som inte finns heller.
Tex klasser i hierarkin som inte används, i fall att man behöver den i framtiden vilket det banne mig aldrig gör i den formen.
Använda egna klasser istället för standardbibliotek bara i fall att.

Spendera inte 1 minut idag som kommer lösa ett problem som tar 2 minuter i framtiden, för det kommer ta timmar att titta igenom saker och ting för att konfirmera det inte finns några dumheter.