mboost-dp1

Spgsml til udvikling af større komplekse programmer??


Gå til bund
Gravatar #51 - Mort
19. okt. 2011 21:04
#49

Det giver god mening at teste private metoder, også selvom de kun benyttes internt. En af fordelen ved at gøre det er at du får testet din kode på et niveau hvor kompleksiteten stadig er lav.

Det er markant lettere og sikrere at teste en metode som har een funktion (Den private metode) end at teste en metode som kalder 100 andre metoder (Den public metode) og så håbe at man kan overskue hele den private implementation nok til at sikre at man har fået testet det hele, gennem unit testen af den public metode.
Gravatar #52 - kasperd
20. okt. 2011 00:14
arne_v (38) skrev:
Man tester ikke for at få 100% coverage, men fordi at det er nødvendigt.
100% coverage er ikke nogen garanti for at koden er fejlfri. Og på den anden sider er coverage på mindre end 100% heller ikke en garanti for at der er fejl i koden.

Coverage procenten er ikke et endegyldigt mål for hvor godt koden er testet, men det er nok den bedste approksimation som kan sætte et tal på hvor grundigt koden er testet.

En ting kan i hvert fald siges med sikkerhed. Unit tests fanger ikke fejl i de kodelinier, der ikke bliver afviklet af unit tests.

Så jeg synes at 100% unit test coverage er et fornuftigt mål at stræbe efter. Der er forskellige måder hvorpå coverage kan beregnes. Jeg bruger selv det gcc/gcov kan gøre for mig, selvom jeg ikke synes det er den optimale måde at beregne coverage. Risikoen for at en uopdaget fejl gemmer sig pga. for dårlig dækning som jeg overså pga. måden dækningsgraden blev beregnet på er ret beskeden. Hvis jeg selv skrev kode til at beregne coverage på den måde jeg hellere ville se det, er der betydeligt større risiko for bugs i den kode jeg skrev til det formål.

Der hvor jeg synes gcc/gcov kommer til kort er at der tælles linier og ikke branches. F.eks.


statement1;
if (condition) {
statement2;
}
statement3;


Hvis aldrig denne kode testes hvor condition evaluerer til falsk vil gcov stadig rapportere 100% coverage. Lidt uhensigtsmæssigt. Et mere problematisk eksempel er:


statement1;
if (condition) statement2;
statement3;


Fordi if og statement2 står på samme linie vises det som en samlet enhed. Det betyder at selvom condition altid er falsk og statement2 aldrig er blevet afviklet vil man stadig se 100% coverage fordi linien som statement2 står på har været afviklet.

Og hvis man har en for eller while løkke mener jeg også man bør dække det grænsetilfælde hvor betingelsen er falsk første gang. Det er dog et lidt upraktisk kriterie fordi der kan være løkker hvor betingelsen aldrig kan være falsk første gang. Det er en udfordring lidt lig med kodefragmenter hvis formål er at rapportere interne fejl i koden.


if (condition) {
fprintf(stderr,"This is not supposed to happen\n");
abort();
}


Man kan selvfølgelig bruge assert(), men assert() kan føre til heisenbugs, og nogle gange vil man gerne have bedre output i tilfælde af en fejlende assertion end hvad assert() kan levere. Ovenstående kode har en linie som kun kan nås hvis der er en bug i koden. I dette tilfælde betyder det altså at coverage skal være under 100% fordi 100% coverage ville betyde at der var en bug i koden.

Bortset fra linier som per design ikke skal kunne nås er det en god idé at stræbe efter 100% coverage. Den største fordel ved at have 100% coverage er at det reducerer risikoen for at introducere nye fejl når man ændrer koden for at tilføje features eller rette fejl.

En 100% coverage betyder at der er en god chance for at alt den funktionalitet man har implementeret også er dækket af unit tests. Dermed er der beskeden risiko for at ødelægge eksisterende funktionalitet ved tilføjelse af nye features.

arne_v (39) skrev:
C) en fysisk opdeling af deployable code
Om man overhovedet er interesseret i en opdeling er afhængigt af omstændighederne. Der er ikke som sådan noget forkert i at compilere en stor kodebase til en enkelt programfil. Der kan være besparelse af RAM og diskplads hvis man har en fornuftig opdeling i libraries der kan genbruges. Og det kan være nemmere at udsende fejlrettelser hvis man kun skal opdatere de dele af koden der er fejl i.

Men det er simplere at administrere en stor programfil, så hvis ikke man har grund til at bekymre sig om resourceforbruget er det helt fint at have en stor programfil. Man bør så vidt mulig undgå at linke standard libraries ind i sin programfil fordi der kan komme sikkerhedsopdateringer til de libraries, og eksemplarer der er linket ind i et større program bliver nemt glemt når der skal opdateres.

arne_v (41) skrev:
Man skriver stadig unit test af API'et ikke af implementationen.
Det kommer an på om man skriver white box eller black box tests. Hvis man laver testdrevet udvikling vil man i sagens natur lave black box tests af den simple grund at tests ikke kan afhænge af strukturen af koden når tests skrives før man overhovedet overvejer hvordan implementationen skal se ud.

Men jeg mener faktisk man bør skrive både white box og black box tests. Lave black box tests ud fra APIen. Og lav white box tests der dækker hele koden. Tilsammen vil de to metoder dække langt de fleste tilfælde.

Jeg vil dog sige at hvis man har white box tests med 100% coverage, så har man med god sandsynlighed testet hele APIen. Og det er nemmere at afgøre om man har 100% coverage af implementationen end at afgøre om et udvalg af tests dækker hele APIen.

Darwind (47) skrev:
Har du nogle gode eksempler på læsestof til at komme igang med TDD?
Desværre ikke. Jeg erindrer at have hørt lidt i en forelæsning og et foredrag. Derudover er det meste erfaring jeg har med det fra den tid hvor jeg arbejdede ved Google. Der var noget intern dokumentation af hvordan man burde teste kode, men det kan jeg af gode grunde ikke vise dig. Selv hvis jeg kunne huske URLen kan den jo ikke tilgås udefra.

Det var ikke fordi jeg lavede særlig meget testdrevet udvikling. Jeg arbejdede godt nok på at min kode skulle være godt dækket af tests, men for det meste skrev jeg alligevel koden før jeg skrev tests til den. Jeg husker kun en enkelt gang hvor jeg var meget bevidst om at skrive test cases før jeg skrev koden, og det kom der godt nok noget mærkelig kode ud af, men det var også skrevet i et obskurt sprog.

Flere gange har jeg været nødt til at skrive unit tests til eksiterende kode som ikke var dækket af tests. Jeg har haft brug for at refaktorere kode som ikke var testet. Jeg måtte først refaktorere koden absolut minimalt for at kunne tilføje unit tests. Når jeg så havde unit tests af den eksisterende kode kunne jeg gå i gang med mere omfattende refaktorering, som også involverede at rette fejl der havde været til stede i den oprindelige kode.
Gravatar #53 - myplacedk
20. okt. 2011 07:24
Windcape (35) skrev:
På datamatiker uddannelsen forklares der lidt om det. Men ikke meget om faktisk strukturing af større projekter / eller strukturing af kode.

Huh?
Da jeg gik på datamatiker brugte vi temmeligt meget tid på faget "systemudvikling", som netop handler om strukturering af koden i metoder, klasser og pakker, og hvad det ellers hedder i de forskellige sprog. MEGET mere tid end vi brugte på programmering. Det vigtigste jeg synes vi lærte var patterns. At dele op i lag osv, altså hvad man bruger pakker, interfaces osv. til.

Det gav viden nok til at strukturere projekter til datamatiker-niveau, dvs. måske op til en håndfuld udviklere. Store projekter (fx. hundredevis af udviklere) kræver naturligvis at nogen som er specialister i at organisere så store mængder koder - arkitekter.

Windcape (35) skrev:
På ingeniør- og datalogi studiet, forklares der stort set intet, da det forventes at være op til de studerende selv at finde ud af.

Jeg kender ikke detaljerne af de uddannelser, men universiteterne underviser naturligvis i arkitektur mv. til udvikling af større systemer. At påstå det er noget folk bare selv finder ud af, er da noget af en fornærmelse af vores højtuddannede arkitekter. (Uanset om det er dig eller skolerne der har den holdning.)

Windcape (35) skrev:
Problemet er nok også, at det er meget teknologi-specifikt. I Java tvinges du til at træffe nogle valg, som ikke nødvendigvis er ideele, og i .NET har du større frihed, men forsøger stadigvæk at integere med dit udviklingsmiljø.

Jo større projektet er, jo højere abstraktionsniveau er det nødvendigt at organisere. Og jo højere abstraktionsniveauet er, jo mere sproguafhængigt er det.

Windcape (35) skrev:
Og så er der folk som kasper, der bruger emacs og en masse seperate filer i en mappe, og synes det er en fornuftig projektstruktur :p

Huh? Du mener ikke at koden skal putters i filer, og filerne i mapper? Du har bare det hele i et Word-dokument eller hvad?

Windcape (35) skrev:
Overordnet set, må det vel være op til erfarne udviklere (nb. erfaring kan fåes andre steder end en arbejdsplads!), at forklare de nye hvordan tingene foregår.

Lidt teoretisk viden fra bøger kan erstatte erfaring fra mange fejlslagne projekter.

Teori uden erfaring er ikke meget værd, men erfaring uden teori tager MEGET lang tid at opbygge, og det koster MANGE spildte ressourcer. Du er nødt til at lære af andres fejl, livet er for kort til at du kan nå at lave alle fejlene selv. Og teori er IKKE noget man lære af at arbejde sammen med en klog, osmose er en rigtig dårlig måde at lære teori.
Gravatar #54 - Windcape
20. okt. 2011 07:41
myplacedk (53) skrev:
Det vigtigste jeg synes vi lærte var patterns. At dele op i lag osv, altså hvad man bruger pakker, interfaces osv. til.
Desværre lærer de folk alt for mange ubrugelige antipatterns. En af mine venner læser datamatiker nu, og der er alt for meget fokus på Singleton, Factory, og Strategy.

Og de lærer stadigvæk ikke dependency injection, selvom jeg imo. mener det er det vigtigste design-pattern i moderne programmering!

myplacedk (53) skrev:
kræver naturligvis at nogen som er specialister i at organisere så store mængder koder - arkitekter.
En god arkitekt kan også finde ud af at kode. Og jeg mener godt man kunne have haft mere fokus på arkitektur.

Vi havde mere fokus på udviklingsmodeller, udover det rent tekniske.

myplacedk (53) skrev:
men universiteterne underviser naturligvis i arkitektur mv. til udvikling af større systemer
Jeg er uenig. Det er ikke min oplevelse. På datalogi undervises der i distributed computing, men fra et mere matematisk synspunkt.

Se bare artiklen om de 2 dataloger, der brugte node.js, fordi de ikke kunne få Java til at skalere.

myplacedk (53) skrev:
Huh? Du mener ikke at koden skal putters i filer, og filerne i mapper?
Det var lidt pun på et typisk C projekt.

Tit er det bare en masse C filer hulter til bulter, og nogle build scripts.

Gravatar #55 - Mort
20. okt. 2011 07:55
Windcape (54) skrev:
Desværre lærer de folk alt for mange ubrugelige antipatterns. En af mine venner læser datamatiker nu, og der er alt for meget fokus på Singleton, Factory, og Strategy.


Siden hvornår er Singleton, Factory og Strategy blevet antipatterns ?
Gravatar #56 - Spiderboy
20. okt. 2011 07:57
Jeg tror han mener forkert brug af disse patterns.

F.eks. er singleton pattern glimrende - til det den er beregnet til. Men mange bruger den forkert.
Gravatar #57 - myplacedk
20. okt. 2011 08:25
Windcape (54) skrev:
Og de lærer stadigvæk ikke dependency injection, selvom jeg imo. mener det er det vigtigste design-pattern i moderne programmering!

Jeg synes nu det lyder som om du snakker om en eller flere konkrete lærere, og ikke uddannelsens niveau generelt.

Windcape (54) skrev:
En god arkitekt kan også finde ud af at kode.

Ja selvfølgelig. Men man bliver ikke arkitekt på en udvikler-uddannelse.

Windcape (54) skrev:
Vi havde mere fokus på udviklingsmodeller, udover det rent tekniske.

Udviklingsmodeller er også vigtige, og vi lærte da også hvorfor vandfaldsmodellen er en dårlig ide og fik en introduktion til iterativ udvikling. Men det er altså kun viden til husbehov, en metode-ekspert har mere i rygsækken en bare en datamatiker-afdeling.

Bare for at illustrere at det ikke bare er en sideting for udviklere: På min arbejdsplads har både arkitektur og metoder hver sin afdeling. Udviklere skal have lidt forstand på det, men i større systemer skal der specialister til.

Windcape (54) skrev:
Jeg er uenig. Det er ikke min oplevelse.

Du fik fat i at jeg ikke snakker om specifikke uddannelser, ikke? Som sagt så HAR du kurser/moduler som specifikt handler om den slags, uanset hvad du mener. Hvem der så tager dem er en helt anden snak.
Gravatar #58 - zcuba
20. okt. 2011 08:26
Tilbage til spørgeren.
Qw_freak lader til at have lidt baggrund i elektronik, og derfor er jeg bare nød til at spørge hvad formålet med dit "program" er.


Eksempel:
Selv skriver jeg software der har til formål at lave feedback kontrol, på systemer der tit er open ended. F.eks. selvkørende robotter..
Det betyder grundlæggende at jeg ikke kender kravene til softwaren før end softwaren er testet i praksis og har vist sine svagheder.

I praksis har det tit vist sig at selv grundige use-case analyser ikke har taget højde for problemer i omgivelserne.
Det betyder at designet, uanset hvor grundig man laver det, aldrig er fyldestgørende, og ofte falder til jorden ved første system test.
Unit testing afslører kun om modulerne overholder kravspec, men det giver ingen mening når kravene er diffuse, og designet tit gennemgår grundlæggende forandringer når en test fejler.

Derfor har det hidtil vist sig at den effektive vej til et system design er, analyser en simpel case, implementer den, test den i praksis, se hvilke udfordringer der er tilbage, udvid programmet til at kunne håndtere endnu en udfordring.
når spaghetti koden nærmer sig noget der virker, analyser hvad der faktisk sker, (typisk et miskmask af state machines, og lineær programmering), lav et design der har nogenlunde samme opførsel, men er pakket væk i fine objekter, og kan skalere til samme type opgaver.
fortsæt med at identificere uløste udfordringer, og tilføj kode.
På et tidspunkt er du kommet langt nok til at forstå opgaven og skrive kravspec..

programmerne kan blive enormt store, og enormt komplekse, da mine brugere er fritgående dyr / mennesker, og derfor ikke er begrænsede af de knapper brugerfladen har..
------

set fra et elektronik perspektiv:
Et program er forhåbentlig ikke mere komplekst end det behøver at være.

Hvis du kan løse opgaven med 1 fil så gør du det

Hvis du har behov for en brugerflade, så prøv at skille den fra din core funktionalitet.

Filer er bare filer, du kan splitte din kode over så mange du har lyst, du kan altid få en compiler til at samle dem for dig, hold et tema i en fil, f.eks. alt der har med at bruge I/O i en fil, alt der har med at lave beregninger på geometri i en anden.

hvis du har muligheden for at bruge klasser og objekter er det en smart måde at sortere din kode, men du skal være opmærksom på at du kan have flere instanser af dine objekter, og at de ikke nødvendigvis har kendskab til hinanden..

hvis du har forskellige krav til afviklingstid, så brug tråde. De kan hjælpe til at holde kravene på f.eks. signal behandlingen, uden at du skal lave interrupt handling selv.
HVIS du er på en embedded maskine, så lad være, overheadet til operativ system og scheduler er som regel for dyrt, skriv istedet dine tidskritiske ting som interrupt drevede kald.. det er lidt sværere, og du skal selv manage memory, men det kan potentielt gå voldsomt hurtigere..

Hvis du skal lave tunge beregninger som billedbehandling, så brug en tråd, og snak med den via noget nemt, f.eks. sockets. På den måde kan du have en tråd til at håndtere GUI, og en anden til det processor tunge arbejde, det gør at din GUI ikke fryser, men også at du skal tænke dig lidt mere om så du f.eks. ikke starter flere beregningstråde samtidigt..

brug evt. low level ting som Assembly til DSP opgaver, og C til lidt mere komplekse ting, brug C++ hvis du tror at det vil være en fordel at opdele koden efter tema, og brug klasser. Brug C# eller Java eller python eller whatever højniveau til bruger interaktionen..
Gravatar #59 - myplacedk
20. okt. 2011 08:36
Mort (55) skrev:
Siden hvornår er Singleton, Factory og Strategy blevet antipatterns ?

Lige præcis singleton er efterhånden blevet et antipattern. Fx. umuliggør det dependency injection, hvilket er vigtigt i en moderne arkitektur, især hvis man vil unit-teste.

http://en.wikipedia.org/wiki/Singleton_pattern#Drawbacks skrev:
This pattern makes unit testing far more difficult,as it introduces global state into an application.

It should also be noted that this pattern reduces the potential for parallelism within a program, because access to the singleton in a multi-threaded context must be serialised, e.g., by locking.

Advocates of dependency injection would regard this as an anti-pattern, mainly due to its use of private and static methods.


Forestil dig fx. en metode som bla. skal indsætte noget i en database. Hvis den gør noget i denne stil:

Database.getInstance().insert(...)

Så vil den altid arbejde med den rigtige database. Men ved unit-testing vil du gerne have at den bruge en mock-database, altså en anden database.

I stedet giver du unit'en en database eller en factory:

Database database = new RealDatabase()
eller
Database database = new MockDatabase()

Og så:

new Something(database);

Inde i Something gemmer man så databasen, så eksemplet bliver til:

database.insert(...)

Vupti, problem løst. Something-klassen har ingen anelse om hvilken database der arbejdes med, og det skal den også være ligeglad med.
Gravatar #60 - Mort
20. okt. 2011 09:07
myplacedk (59) skrev:
Lige præcis singleton er efterhånden blevet et antipattern. Fx. umuliggør det dependency injection, hvilket er vigtigt i en moderne arkitektur, især hvis man vil unit-teste.


En singleton umuliggør da ikke dependency injection, det kommer helt an på hvor du implementerer din singleton.

Hvis du vil bruge dependency injection på dit database eksempel, så kan du stadig injecte en singleton ind i den klasse du vil teste. Din singleton kan feks blive returneret af et service locator pattern, som i din unit test i stedet returnerer et mocking object.
Gravatar #61 - Windcape
20. okt. 2011 10:10
Mort (60) skrev:
Din singleton kan feks blive returneret af et service locator pattern, som i din unit test i stedet returnerer et mocking object.
Nej. En singleton har per definition en private constructor, og kan derfor ikke oprettes af en service locator.

(Og direkte brug af en Service Locator er også et anti-pattern)

Derudover er en singleton meningsløst, da man med dependency injection, netop nemt kan genbruge samme instans.
Gravatar #62 - Windcape
20. okt. 2011 10:14
myplacedk (57) skrev:
Som sagt så HAR du kurser/moduler som specifikt handler om den slags, uanset hvad du mener. Hvem der så tager dem er en helt anden snak.
Det er tilfældigt om de bliver udbudt fra semester til semester.

Software arkitektur var ikke et muligt tilvalg på ingeniør-uddannelsen. Der så de hellere at folk skrev slamkode i C, uden den mindste overvejelse om kode design.
Gravatar #63 - myplacedk
20. okt. 2011 10:24
#60
Jeg tror vi skal differentiere mellem "singleton" og "singleton pattern".

Der er masser af ting som i sin natur kun må eksistere én gang, og det hedder en "singleton". Det giver ingen mening at arbejde imod dette.

"Singleton pattern" er mere end det. Det er også en måde at tilgå denne singleton. Formuleret i én sætning: "Ensure a class has only one instance, and provide a global point of access to it." - det er del 2 der er problematisk.
Gravatar #64 - myplacedk
20. okt. 2011 10:29
Windcape (62) skrev:
Det er tilfældigt om de bliver udbudt fra semester til semester.

Det er meget almindeligt på universiteterne. Vil du have et bestemt kursus, må du vente til det kommer. Kun de aller mest populære er der hvert semester.

Windcape (62) skrev:
Software arkitektur var ikke et muligt tilvalg på ingeniør-uddannelsen.

Jeg er STADIG ligeglad, det er STADIG irrelevant.
Gravatar #65 - Windcape
20. okt. 2011 10:35
myplacedk (64) skrev:
Jeg er STADIG ligeglad, det er STADIG irrelevant.
Det er da ikke irrelevant.

Pointen er jo at der IKKE som en del af den aleme grundundervisning, undervises i arkitektur.

Det nævnes *MÅSKE* som en del af programmeringsundervisningen, afhængigt af underviseren.

Gravatar #66 - myplacedk
20. okt. 2011 10:41
Windcape (65) skrev:
Pointen er jo at der IKKE som en del af den aleme grundundervisning, undervises i arkitektur.

What? Troller du nu igen, eller har du glemt hvad vi snakker om?

myplacedk (53) skrev:
Jeg kender ikke detaljerne af de uddannelser, men universiteterne underviser naturligvis i arkitektur mv. til udvikling af større systemer.


og:

myplacedk (57) skrev:
man bliver ikke arkitekt på en udvikler-uddannelse.


Hvis ikke du kan forstå at softwarearkitektur ER noget der bliver undervist i, så er det ikke noget jeg gider gøre mere ud af.
Gravatar #67 - arne_v
20. okt. 2011 11:17
#51

Det er langt nemmere.

Men da du ikke kan udlede noget hvis unit testen fejler, så er der ligesom ikke noget formål med det.
Gravatar #68 - arne_v
20. okt. 2011 11:26
kasperd (52) skrev:
Coverage procenten er ikke et endegyldigt mål for hvor godt koden er testet, men det er nok den bedste approksimation som kan sætte et tal på hvor grundigt koden er testet.


Nej.

Det rigtige mål er hvorvidt alle path gennem koden er udført ikke om al kode er udført.

Derfor windcape snakker om cyklomatisk kompleksitet.

kasperd (52) skrev:
En ting kan i hvert fald siges med sikkerhed. Unit tests fanger ikke fejl i de kodelinier, der ikke bliver afviklet af unit tests.


Det er rigtigt.

Man kan ikke teste alle path uden at udføre alle kode linier,

kasperd (52) skrev:
Så jeg synes at 100% unit test coverage er et fornuftigt mål at stræbe efter.


Det er ikke en garanti for at alle path er testet.

Og i det tilfælde at man ikke har resourcer til at teste alt og skal prioritere, så vil det formentligt være bedre at teste alle path i kode med høj cyklomatisk kompleksitet og springe noget af den simplere kode over end at opnå 100% coverage.

Code coverage procent er ikke ligegyldig men det er en metric som skal spises med et kilo salt til.
Gravatar #69 - arne_v
20. okt. 2011 11:30
kasperd (52) skrev:
Om man overhovedet er interesseret i en opdeling er afhængigt af omstændighederne. Der er ikke som sådan noget forkert i at compilere en stor kodebase til en enkelt programfil. Der kan være besparelse af RAM og diskplads hvis man har en fornuftig opdeling i libraries der kan genbruges. Og det kan være nemmere at udsende fejlrettelser hvis man kun skal opdatere de dele af koden der er fejl i.


Diskplads er som oftest ligegyldig.

Men det er vigtigt at kunne opdatere.

Og at kunne unit teste separat.

kasperd (52) skrev:
Men det er simplere at administrere en stor programfil, så hvis ikke man har grund til at bekymre sig om resourceforbruget er det helt fint at have en stor programfil. Man bør så vidt mulig undgå at linke standard libraries ind i sin programfil fordi der kan komme sikkerhedsopdateringer til de libraries, og eksemplarer der er linket ind i et større program bliver nemt glemt når der skal opdateres.


Der kommer også opdateringer til ens egen kode.

Om koden kommer fra Big OS Inc eller Big App Inc bør ikke gøre den store forskel.
Gravatar #70 - arne_v
20. okt. 2011 11:37
kasperd (52) skrev:
Det kommer an på om man skriver white box eller black box tests. Hvis man laver testdrevet udvikling vil man i sagens natur lave black box tests af den simple grund at tests ikke kan afhænge af strukturen af koden når tests skrives før man overhovedet overvejer hvordan implementationen skal se ud.


kasperd (52) skrev:
Men jeg mener faktisk man bør skrive både white box og black box tests. Lave black box tests ud fra APIen. Og lav white box tests der dækker hele koden. Tilsammen vil de to metoder dække langt de fleste tilfælde.


Jeg ser unit test som ren black box test.

Ved en ny version af et lib skal alle de gamle unit tests virke for at give client kode en vis tillid til at deres kode vil virke med den nye version.

Hvis der er rettet i unit tests fordi den har testet interne ting forsvinder den tillid.

Hvis X er så kompleks at det er ønskværdigt at teste noget internt, så er det bedre at splitte X op i XA og XB. Unit test af XA kan så bibeholdes uændret selvom XB udskiftes med XBNEW (XB og XBNEW har så deres egne unit tests).
Gravatar #71 - kasperd
20. okt. 2011 21:09
arne_v (68) skrev:
Det rigtige mål er hvorvidt alle path gennem koden er udført ikke om al kode er udført.

Derfor windcape snakker om cyklomatisk kompleksitet.
Hvis man sætter en lang række if statements efter hinanden vokser antallet af paths exponentielt, men den cyklomatiske kompleksitet vokser kun lineært.

Hvor mange testkørsler der skal til for at få den kode rigtig dækket vil jeg ikke regne på klokken 23 om aftenen.

Under alle omstændigheder har jeg aldrig hævdet at det afgørende var at få alle kodelinier afviklet. Men det er det mål som de værktøjer jeg har arbejdet med har brugt.

arne_v (70) skrev:
Hvis der er rettet i unit tests fordi den har testet interne ting forsvinder den tillid.
For det første er white box tests og test af interne funktioner ikke det samme.

Hvis du tager en API specifikation og skriver unit tests ud fra API specifikationen har du ingen anelse om hvorvidt alt koden er testet. Det er situationen med en black box test.

Hvis du kigger på koden vil du ofte opdage at der er forgreninger der kun kan nås hvis bestemte kombinationer af kriterier er opfyldt. Så kan du skrive en test der sikrer at det er opfyldt og verificere at koden gør som APIen specificerer også i det tilfælde.

Selvom du kiggede på koden for at skrive den unit test er den stadig gyldig for enhver implementation af den pågældende API. Hvis du laver en ny implementation vil de gamle white box tests stadig skulle passere med den nye implementation.

Hvis specialtilfældene var absolut nødvendige må den nye implementation også have brug for lignende specialtilfælde, og det er en god idé at genbruge de tests man har skrevet. Hvis den nye tests på en eller anden smart måde undgår specialtilfælde i koden er det stadig en god idé at genbruge sine tests for at se at den nye smarte metode stadig fungerer.

En white box test af en ny implementation vil måske afsløre at der er ikke er 100% dækning af den nye kode. Så kan man skrive flere unit tests for at lave komplet test af den nye implementation. Det vil så være en udmærket idé at teste de unit tests imod den gamle implementation for at sikre sig at testene giver mening.
Gravatar #72 - arne_v
29. okt. 2011 02:13
kasperd (71) skrev:
Hvis man sætter en lang række if statements efter hinanden vokser antallet af paths exponentielt,


Ja. Desværre. Pointen gælder dog stadig,

kasperd (71) skrev:
Under alle omstændigheder har jeg aldrig hævdet at det afgørende var at få alle kodelinier afviklet. Men det er det mål som de værktøjer jeg har arbejdet med har brugt.


Det er ret udbredt. Men det gør ikke metric'en bedre.
Gravatar #73 - arne_v
29. okt. 2011 02:18
kasperd (71) skrev:

For det første er white box tests og test af interne funktioner ikke det samme.

Hvis du tager en API specifikation og skriver unit tests ud fra API specifikationen har du ingen anelse om hvorvidt alt koden er testet. Det er situationen med en black box test.

Hvis du kigger på koden vil du ofte opdage at der er forgreninger der kun kan nås hvis bestemte kombinationer af kriterier er opfyldt. Så kan du skrive en test der sikrer at det er opfyldt og verificere at koden gør som APIen specificerer også i det tilfælde.

Selvom du kiggede på koden for at skrive den unit test er den stadig gyldig for enhver implementation af den pågældende API. Hvis du laver en ny implementation vil de gamle white box tests stadig skulle passere med den nye implementation.

Hvis specialtilfældene var absolut nødvendige må den nye implementation også have brug for lignende specialtilfælde, og det er en god idé at genbruge de tests man har skrevet. Hvis den nye tests på en eller anden smart måde undgår specialtilfælde i koden er det stadig en god idé at genbruge sine tests for at se at den nye smarte metode stadig fungerer.

En white box test af en ny implementation vil måske afsløre at der er ikke er 100% dækning af den nye kode. Så kan man skrive flere unit tests for at lave komplet test af den nye implementation. Det vil så være en udmærket idé at teste de unit tests imod den gamle implementation for at sikre sig at testene giver mening.


Denne subtråd startede med diskussion om test af internal inden den bevægede sig lidt over i whitebox/blackbox.

Jeg er voldsomt imod unit tests som kun kan køre mod en specifik implementation.

Jeg har ikke noget imod unit tests som er interessante for en specifik implementation men virker for alle implementationer.
Gravatar #74 - arne_v
29. okt. 2011 02:24
Windcape (54) skrev:
En god arkitekt kan også finde ud af at kode.


En software arkitekt er nødt til at kunne kode for at være god til sit job.

Infrastruktur arkitekter, enterprise arkitkter, security arkitekter etc. har ikke det behov.

Solution arkitekter er lidt mere åben for diskussion, men jg vil mene ja.
Gravatar #75 - arne_v
29. okt. 2011 02:31
Windcape (61) skrev:

Og direkte brug af en Service Locator er også et anti-pattern


Nogen som har læst:

http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAn...

:-)

Men prøv og læs den meget grundigt og prøv og træk essensen ud og generaliser den.

Resultatet vilnok overraske dig!
Gravatar #76 - arne_v
29. okt. 2011 02:43
#Singleton

For 10 år siden var det hipt at kunne alle GoF patterns.

Idag er det hipt at mene at Singleton er skidt.

Ofte er argumenterne særdeles tvivlsomme. Eksempel fra den allerede citerede wikipedia artikel:


It should also be noted that this pattern reduces the potential for parallelism within a program, because access to the singleton in a multi-threaded context must be serialised, e.g., by locking.


Hm.

Hvis al tilgang er readonly behøver man ikke serialisering af tilgangen. Udover det som er nødvendig for visibility - men det er ens uanset om det er singleton eller ikke singleton.

Hvis flere tråde modificerer skal tilgangen naturligvis synkroniseres - men det er ens uanset om det er singleton eller ikke singleton.

Det er skidt for performance at serialisere tilgang til et delt objekt fremfor at have et objekt per tråd, hvis det sidste er muligt. Men det har heller ikke noget med singleton at gøre.

Det er rigtigt at singleton per definition er umulig at mocke.

Så hvis man:
- skal unit teste via mocking
- det er umuligt/upraktisk at mocke det som bruger singleton
- det er umuligt/upraktisk at mocke det som singleton bruger
så er singleton et dårligt valg.

Det er imidlertid en del hvis'er. Og jeg mener ikke at det er tilstrækkeligt til at kalde det for et anti pattern.

Det er naturligvis tilstrækkeligt til at man skal tænke sig lidt om!


Gravatar #77 - arne_v
29. okt. 2011 02:46
Windcape (54) skrev:

Desværre lærer de folk alt for mange ubrugelige antipatterns. En af mine venner læser datamatiker nu, og der er alt for meget fokus på Singleton, Factory, og Strategy.

Og de lærer stadigvæk ikke dependency injection, selvom jeg imo. mener det er det vigtigste design-pattern i moderne programmering!


Nu består de fleste DI frameworks jo af factory og strategy pattern kombineret med en lille rekursiv finesse ....

:-)
Gravatar #78 - arne_v
29. okt. 2011 02:49
Windcape (54) skrev:
På datalogi undervises der i distributed computing, men fra et mere matematisk synspunkt.

Se bare artiklen om de 2 dataloger, der brugte node.js, fordi de ikke kunne få Java til at skalere.


Nu mner jeg ikke at deres problemer var relateret til distribueret computing.

Men jg er helt enig i at deres tilgang til software udvikling var super pinlig.
Gravatar #79 - arne_v
29. okt. 2011 02:54
Windcape (61) skrev:
Derudover er en singleton meningsløst, da man med dependency injection, netop nemt kan genbruge samme instans.


Singleton pattern og diverse DI framework singleton er lidt forskellige.

Med singleton pattern enforcer programmøren af klassen at der kun findes en instans.

Diverse DI framework singleton giver kalderen mulighed for at få samme instans.
Gravatar #80 - Windcape
29. okt. 2011 07:39
arne_v (79) skrev:
Med singleton pattern enforcer programmøren af klassen at der kun findes en instans.
Hvilket i ordenlige programmeringssprog, vil være en statisk klasse.

arne_v (79) skrev:
Diverse DI framework singleton giver kalderen mulighed for at få samme instans
Hvilket er den hyppigste grund til at man valgte at bruge singleton i første omgang.

Jeg kan godt forstå folk synes at skulle ctor injecte 10 dependencies kunne blive ret skræmmende, men med IoC frameworks i dag, er der jo ikke rigtig nogen undskyldning for at lade være.

At genbruge en database instans, uden at skulle wrappe den i en singleton er nemt og smertefrit med IoC. Og netop database er nok det hyppigste eksempel på (mis)brug af singleton som jeg har set.
Gravatar #81 - Windcape
29. okt. 2011 07:43
arne_v (75) skrev:
Men prøv og læs den meget grundigt og prøv og træk essensen ud og generaliser den.
Jeg kan ikke lige fange din pointe her.

Men jeg synes da at Mark har ret. Derudover så har jeg oplevet mange som har misforstået DI/IoC, ved at bruge container.Resolve over alt frem for ctor/property injection.

Det er allerværst når der bruges en statisk container. Men selv med f.eks. Unity, hvor der injectes en IContainer er det ikke særlig meget bedre.

Man kunne jo ligeså godt have injected de dependencies man skulle bruge i første omgang.

Med IoC sparer man jo også flere linjers kode på den måde! Og det er jo dejligt.


Gravatar #82 - arne_v
30. okt. 2011 02:00
Windcape (80) skrev:

Hvilket i ordenlige programmeringssprog, vil være en statisk klasse.


Hvis det skal gøres rigtigt således at der kan extendes/implementeres, så ender det jo med at blive lidt syntaktisk sukker over at man henter en instans via noget static.

Windcape (80) skrev:
Og netop database er nok det hyppigste eksempel på (mis)brug af singleton som jeg har set.


Database connection pool kan laves som singleton. Men database connection som singleton er meget slem.
Gravatar #83 - arne_v
30. okt. 2011 02:01
Windcape (81) skrev:
Jeg kan ikke lige fange din pointe her.


Du kan ikke se muligheden for at generalisere?
Gravatar #84 - ploeh
30. okt. 2011 08:23
Da jeg ikke er interesseret i at blive taget til indtægt for noget jeg aldrig har sagt vil jeg lige rette en misforståelse: Jeg har aldrig sagt at man ikke behøver at test kode med en cyklomatisk kompleksitet på 1. Tværtimod mener jeg at det er vigtigt at teste al kode - bl.a. fordi man jo ikke ved om den cyklomatiske kompleksitet vil vedblive at være 1.

Det ville være white box testing hvis man undlod at teste på baggrund af sådan et kriterium.

Hvad jeg har sagt (og står ved) er at (i det mindste i .NET) vil der være kode, man ikke kan unit teste, og at sådan kode bør reduceres så den har en cyklomatisk compleksitet på 1.
Gravatar #85 - arne_v
4. nov. 2011 16:58
#84

Tak - det afklarer ihvertfald hvor ideen ikke kommer fra.

Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login