-
Notifications
You must be signed in to change notification settings - Fork 0
/
ase-party.html
1809 lines (1479 loc) · 46.2 KB
/
ase-party.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8"/>
<title>TDD, Clean Code, Software Craftmanship und so'n Zeug</title>
<meta name="author" content="(mitch@cgarbs.de)"/>
<style type="text/css">
.underline { text-decoration: underline; }
</style>
<link rel="stylesheet" href="./reveal.js/css/reveal.css"/>
<link rel="stylesheet" href="./reveal.js/css/theme/crt.css" id="theme"/>
<!-- If the query includes 'print-pdf', include the PDF print sheet -->
<script>
if( window.location.search.match( /print-pdf/gi ) ) {
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = './reveal.js/css/print/pdf.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
}
</script>
<!-- Copyright (C) 2017 Christian Garbs <mitch@cgarbs.de> -->
<!-- Licensed under Creative Commons Attribution-ShareAlike 4.0 International License -->
<!-- see https://creativecommons.org/licenses/by-sa/4.0/ -->
</head>
<body>
<div class="reveal">
<div class="slides">
<section id="sec-title-slide"><h1 class="title">TDD, Clean Code, Software Craftmanship und so'n Zeug</h1><h2 class="author">mitch@cgarbs.de</h2><h2 class="date">Hackover 2017</h2>
</section>
<section id="table-of-contents">
<div id="table-of-contents">
<h2>Inhaltsverzeichnis</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#/slide-org9d63814">1. disclaimer</a></li>
<li><a href="#/slide-org7699710">2. ad hominem</a></li>
<li><a href="#/slide-org58a4684">3. Software Craftmanship</a></li>
<li><a href="#/slide-orgf10a1ab">4. Infrastuktur</a></li>
<li><a href="#/slide-orge9311ba">5. Tests</a></li>
<li><a href="#/slide-org1e953e3">6. Clean Code</a></li>
<li><a href="#/slide-orgc225052">7. im Team</a></li>
<li><a href="#/slide-org4f97872">8. Test Driven Development</a></li>
<li><a href="#/slide-org6494c5a">9. for further study</a></li>
<li><a href="#/slide-org342f507">10. Ende</a></li>
</ul>
</div>
</div>
</section>
<section>
<section id="slide-org9d63814">
<h2 id="org9d63814"><span class="section-number-2">1</span> disclaimer</h2>
<ul>
<li>Es gibt Literatur zu den Themen. Ich habe sie nicht gelesen.</li>
<li>Das alles stammt aus Praxiserfahrung und aus dem Internet.</li>
<li>Dargestellt aus Entwicklersicht für Entwickler.</li>
<li>Ich bin nur ein Quereinsteiger.</li>
</ul>
<p>
Have fun!
</p>
</section>
</section>
<section>
<section id="slide-org7699710">
<h2 id="org7699710"><span class="section-number-2">2</span> ad hominem</h2>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides" width="100%">
<colgroup>
<col class="org-right" />
<col class="org-left" />
<col class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-right">1986</td>
<td class="org-left">CPC 664</td>
<td class="org-left">Locomotive Basic</td>
</tr>
<tr>
<td class="org-right">1989</td>
<td class="org-left">Atari ST</td>
<td class="org-left">GfA Basic</td>
</tr>
<tr>
<td class="org-right">1994</td>
<td class="org-left">DOS</td>
<td class="org-left">Turbo Pascal</td>
</tr>
<tr>
<td class="org-right">1996</td>
<td class="org-left">Linux</td>
<td class="org-left">Perl, Shell</td>
</tr>
<tr>
<td class="org-right">1998</td>
<td class="org-left">zOS</td>
<td class="org-left">COBOL $$</td>
</tr>
<tr>
<td class="org-right">2000</td>
<td class="org-left">Windows</td>
<td class="org-left">Java $$</td>
</tr>
</tbody>
</table>
</section>
<section id="slide-orgfb0bfcd">
<h4 id="orgfb0bfcd">2015: Jahr des Umsturzes</h4>
<ul>
<li>von Java 1.5 auf Java 8</li>
<li><i>Continus Integration</i> kennengelernt</li>
<li>neue Frameworks (<i>Vaadin</i> + diverse interne)</li>
<li>in den ASE-Zaubertopf gefallen</li>
</ul>
<p>
Effektiv in den letzten 2 Jahren mehr neues gelernt als die 10 Jahre
davor. Toll!
</p>
</section>
</section>
<section>
<section id="slide-org58a4684">
<h2 id="org58a4684"><span class="section-number-2">3</span> Software Craftmanship</h2>
<p>
ist der Gedanke, Softwareentwicklung wie ein Handwerk zu betrachten
und nicht als industrielle Massenproduktion. Damit einher geht ein
gewisser Qualitätsanspruch an sich selbst und seine Arbeit sowie die
Reflexion darüber:
</p>
<ul>
<li>Was habe ich gelernt?</li>
<li>Was lief gut? Was lief weniger gut?</li>
<li>Was mache ich nochmal so? Was lieber nicht?</li>
</ul>
<p>
Diese Werte vertritt unter anderem die <a href="https://www.softwerkskammer.org/">Softwerkskammer</a>.
</p>
</section>
</section>
<section>
<section id="slide-orgcedde6b">
<h3 id="orgcedde6b"><span class="section-number-3">3.1</span> Lernen</h3>
<p>
Ein Weg zu Qualität ist, sich fortzubilden, und zwar auf
verschiedensten Ebenen:
</p>
<ul>
<li>technisches Wissen (neue Frameworks, neue Sprachen, ...)</li>
<li>Fachwissen (ggf. branchenspezifisch)</li>
<li>Handwerkszeug (IDEs, Design-Pattern, ...)</li>
<li>Arbeitstechniken (Zeitmanagement, "Agile", ...)</li>
<li>Softskills (Wissensvermittlung, Konfliktmanagement, ...)</li>
</ul>
</section>
</section>
<section>
<section id="slide-org27cd096">
<h3 id="org27cd096"><span class="section-number-3">3.2</span> Katas</h3>
<p>
sind kleine, überschaubare Programmieraufgaben, die sich flexibel
verwenden lassen, um Dinge auszuprobieren oder zu vertiefen:
</p>
<ul>
<li>Entwicklungstechniken (Refactoring, Design-Patterns, Test Driven Development,
Type Driven Development, ...)</li>
<li>Programmiersprachen oder -konzepte (z.B. Streams und Optionals in Java 8)</li>
<li>IDEs (ohne Maus, vi-Keybindings, ...)</li>
<li>Frameworks (ggf. auch nur neue Features in neuen Versionen)</li>
<li>das neue Keyboardlayout</li>
<li>schon mal <i>Pair Programming</i> gemacht?</li>
</ul>
</section>
<section id="slide-orgeadb94a">
<h4 id="orgeadb94a">Warum Katas?</h4>
<ul>
<li>Lernen durch Machen bleibt am besten hängen</li>
<li>Ausprobieren festigt - Fehler mal zulassen
<ul>
<li>das geht aber nicht im Arbeitsalltag!</li>
<li>ergo: Zeiten und Räume dafür schaffen</li>
</ul></li>
</ul>
<blockquote nil>
<p>
Wir haben keine Zeit, die Axt zu schärfen, wir müssen Bäume fällen.
</p>
</blockquote>
<p>
Es lohnt sich, sich die Zeit zu nehmen!
</p>
</section>
<section id="slide-org61338c4">
<h4 id="org61338c4">Constraints</h4>
<p>
machen Katas interessanter, thembenbezogener und schwieriger. Damit
lohnt dann auch eine Wiederholung. Nicht für Produktivcode gedacht!
</p>
<ul>
<li>keine Maus (IDE kennenlernen)</li>
<li>nur Methoden ohne Rückgabeparameter</li>
<li>keine einfachen Datentypen erlaubt (-> <i>Type Driven Development</i>)</li>
<li>keine Methode länger als 5 Zeilen</li>
<li>nur eine Blocktiefe pro Methode</li>
<li>...</li>
</ul>
<p>
Hardcore-Modus: <a href="https://gist.github.com/bobuss/6534934">Object Calesthenics</a>
</p>
</section>
</section>
<section>
<section id="slide-org73edcf3">
<h3 id="org73edcf3"><span class="section-number-3">3.3</span> in extremo</h3>
<ul>
<li><i>Katas</i> im <i>Pair Programming</i> übers Internet mit Leuten, die man
nicht kennt (Chatroulette Developer Edition)</li>
<li>"Software-Walz": "Hallo $FIRMA, ihr zahlt mir Mittagessen und ein
Hotelzimmer, dafür mache ich zwei Tage lang je drei <i>Pair
Programming</i>-Sessions mit euren Entwicklern, dann ziehe ich weiter."</li>
</ul>
</section>
</section>
<section>
<section id="slide-orgf10a1ab">
<h2 id="orgf10a1ab"><span class="section-number-2">4</span> Infrastuktur</h2>
<p>
heißt dieses Kapitel, weil es hier um zentrale Dinge geht, die der
Entwickler zwar braucht, aber nicht unbedingt selbst in der Hand hat.
</p>
</section>
</section>
<section>
<section id="slide-org114984b">
<h3 id="org114984b"><span class="section-number-3">4.1</span> Source Repository</h3>
<p>
ist die Stelle, an der der Quellcode zentral abgelegt wird.
</p>
<ul>
<li>Vorteile liegen auf der Hand
<ul>
<li>Nachvollziehbarkeit</li>
<li>Branching</li>
<li>Backupfähigkeit</li>
<li>verteiltes Arbeiten</li>
</ul></li>
<li>heutzutage <i>state of the art</i>
<ul>
<li>damit vmtl. sogar rechtlich relevant</li>
</ul></li>
</ul>
<p>
Bekannte Tools wären <a href="https://git-scm.com/">git</a>, <a href="https://subversion.apache.org/">SVN</a>, ...
</p>
<aside class="notes">
<ul>
<li><b>Commit-Nachrichten!</b></li>
<li><b>PFUI SVN!</b>
<ul>
<li>Merge auf eine Datei, die zwischdurch umbenannt wurde
<ul>
<li>kein Fehler</li>
<li>Merge completed</li>
<li><i>aber nichts gemacht</i></li>
</ul></li>
<li>offen seit mindestens 8 Jahren</li>
<li>war es dieser <a href="https://issues.apache.org/jira/browse/SVN-898">Bug</a>? (der ist 15 Jahre alt...)</li>
<li>vor drei(?) Jahren Begeisterung in der Fachpresse: "wird mit Version
1.10 gefixt!"
<ul>
<li>die ist nur leider immer noch nicht erschienen oder so</li>
</ul></li>
</ul></li>
</ul>
</aside>
</section>
</section>
<section>
<section id="slide-orgfa8d02b">
<h3 id="orgfa8d02b"><span class="section-number-3">4.2</span> Continuous Integration</h3>
<p>
bedeutet, dass man seine Software regelmäßig baut und testet. Je
schneller man neu eingebaute Fehler findet, um so eher weiß man noch,
was man gerade getan hat. Oder wer es war.
</p>
<p>
Lieber 3x pro Woche mit einem einzelnen Fehler den Build kaputtmachen
als zum Releasetermin mit 50 Problemen auf einmal zu kämpfen.
</p>
<p>
Tools dafür wären z.B. <a href="https://jenkins.io/">Jenkins</a> oder <a href="https://travis-ci.org/">TravisCI</a>.
</p>
</section>
<section id="slide-org9bd3ccb">
<h4 id="org9bd3ccb">Build</h4>
<ul>
<li>regelmäßig und <i>oft</i> bauen
<ul>
<li>nicht nur 1x pro Woche oder pro Monat</li>
</ul></li>
<li>kurzfristig bauen
<ul>
<li>direkt nach jedem Commit</li>
</ul></li>
</ul>
<p>
Dafür ist ein manueller Build zu aufwändig und teuer, daher braucht
man einen <i>automatischem Buildprozess</i>. Das führt zu
<i>reproduzierbaren Ergebnissen</i> und vergessene bzw. fehlerhafte
Schritte im Build werden als Fehlerquelle ausgeschlossen.
</p>
</section>
<section id="slide-org7d1f105">
<h4 id="org7d1f105">Test</h4>
<ul>
<li>regelmäßig und <i>oft</i> testen
<ul>
<li>nicht nur 1x pro Woche oder pro Monat</li>
</ul></li>
<li>kurzfristig testen
<ul>
<li>direkt nach jedem Commit</li>
</ul></li>
</ul>
<p>
Dafür sind manuelle Tests zu aufwändig und teuer, daher braucht man
<i>automatisierte Tests</i>. Nebenbei fallen dann auch regelmäßig
Test-Metriken ab (Testabdeckung, Testanzahl, Fehlerquoten,
Problem-Hotspots, ...).
</p>
<p>
Manuelle Tests sind weiterhin nötig, aber nicht als Teil von
<i>Continuous Integration</i>.
</p>
</section>
</section>
<section>
<section id="slide-org672b118">
<h3 id="org672b118"><span class="section-number-3">4.3</span> Continuous Inspection</h3>
<p>
ist dann, wenn man regelmäßig (z.B. im CI-Build oder über Nacht)
automatisiert Metriken ermittelt (z.B. <code>// FIXME</code> zählen) und/oder den
Code auf mögliche Fehler und Warnungen überprüft (z.B. fehlende
NullPointer-Prüfungen oder <code>==</code> statt <code>equals()</code>).
</p>
<p>
Tools dafür wären z.B. <a href="http://findbugs.sourceforge.net/">FindBugs</a>, <a href="https://www.sonarqube.org/">SonarQube</a>, <a href="https://pmd.github.io/">PMD/CPD</a> oder <a href="https://metacpan.org/pod/Perl::Critic">Perl::Critic</a>.
</p>
</section>
</section>
<section>
<section id="slide-org7a90e34">
<h3 id="org7a90e34"><span class="section-number-3">4.4</span> Continuous Delivery</h3>
<p>
ist dann, wenn man erzeugte Buildergebnisse automatisiert in eine
Testumgebung einspielt.
</p>
<p>
Anders als <i>Continuous Integration</i> hat das nicht nur Vorteile,
sondern hier ist eine Abwägung nötig, weil verschiedene negative
Effekte auftreten können.
</p>
</section>
<section id="slide-org5fff1f6">
<h4 id="org5fff1f6">Continuous Delivery</h4>
<ul>
<li>gut: laufend aktualisierter Stand in Testumgebung</li>
<li>aber: Deployment/Auslieferung/Aufspielung unterbricht laufende Tests</li>
<li>Fehler in zentralen Komponenten (z.B. Login) haben durchschlagende
Wirkung auf andere
<ul>
<li>vielleicht doch nicht alles sofort automatisch deployen?</li>
<li>eigene Testumgebung für jede Komponente?</li>
<li>mehrstufiges Testkonzept?</li>
</ul></li>
</ul>
</section>
<section id="slide-org803ca67">
<h4 id="org803ca67">Continuous Delivery</h4>
<ul>
<li>grundsätzlich nicht mehr Fehler als vorher zu erwarten, aber
<ul>
<li>zeitlich verteilter</li>
<li>höhere Änderungsrate</li>
<li>immer mal wieder was andere</li>
</ul></li>
</ul>
</section>
</section>
<section>
<section id="slide-orge9311ba">
<h2 id="orge9311ba"><span class="section-number-2">5</span> Tests</h2>
<p>
verifizieren, dass Code nach einer Änderung (noch) das tut, was er
soll.
</p>
<p>
Je früher im Software-Lifecycle Fehler gefunden werden, um so billiger
sind sie zu beheben.
</p>
<aside class="notes">
<p>
Beispiel:
Während der Erfassung der Requirements ist ein "das kann ja gar nicht
funktionieren" deutlich billiger als wenn das erst nach zwei Monaten
Programmierarbeit festgestellt wird. Oder gar erst in Produktion.
</p>
</aside>
</section>
</section>
<section>
<section id="slide-org39773c2">
<h3 id="org39773c2"><span class="section-number-3">5.1</span> Testpyramide</h3>
<p>
Es gibt verschiedene Arten von Tests:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides" width="100%">
<colgroup>
<col class="org-left" />
<col class="org-left" />
<col class="org-left" />
<col class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Art</th>
<th scope="col" class="org-left">Anzahl</th>
<th scope="col" class="org-left">Häufigkeit</th>
<th scope="col" class="org-left">Kosten</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">manuelle Tests</td>
<td class="org-left"><code>#</code></td>
<td class="org-left"><code>I</code></td>
<td class="org-left"><code>$$$$</code></td>
</tr>
<tr>
<td class="org-left">automatisierte Oberflächentests</td>
<td class="org-left"><code>##</code></td>
<td class="org-left"><code>II</code></td>
<td class="org-left"><code>$$$</code></td>
</tr>
<tr>
<td class="org-left">Integrationstests</td>
<td class="org-left"><code>###</code></td>
<td class="org-left"><code>III</code></td>
<td class="org-left"><code>$$</code></td>
</tr>
<tr>
<td class="org-left">Unit-Tests</td>
<td class="org-left"><code>####</code></td>
<td class="org-left"><code>IIII</code></td>
<td class="org-left"><code>$</code></td>
</tr>
</tbody>
</table>
<p>
Desweiteren <i>Lasttests</i>, <i>Fuzzying</i>, <i>Smoke-Tests</i> etc.
</p>
<aside class="notes">
<dl>
<dt>Lasttests</dt><dd>Testet Laufzeitverhalten und Ressourcenverbrauch unter
Last, meist durch viele parallele simulierte User oder
große Datenmengen. Benötigt meist eine besonders
produktionsnahe Umgebung für sinnvolle Aussagen (eher
nicht der lokale Entwicklerrechner). Wird im
Normalfall automatisiert getestet (Gegenbeispiel wäre
ein Free-for-all-Beta-Wochenende bei einem
Online-Spiel).</dd>
<dt>Fuzzying</dt><dd>Versucht, Programmfehler durch ungültige Eingabedaten
herauszukitzeln (ursprünglich mit zufälligen Daten,
inzwischen aber schon sehr gezielt - interessanter
Forschungsbereich). Meist geht es um Security-Probleme
(Buffer-Overflows etc.). Bei interaktiven Programmen
reicht es manchmal schon, eine Katze über die Tastatur
laufen zu lassen. Oder <i>millions of Monkeys banging on
typewriters</i>. Wird im Normalfall automatisiert
getestet.</dd>
<dt>Smoke-Tests</dt><dd>Kurztest nach dem Deployment einer neuen Version in
eine (Test-)Umgebung. Wird meist aus kostengründen
automatisiert, je nach Deploymenthäufigkeit kann aber
auch ein manueller Test ausreichen - der Test selbst
geht ja schnell und testet nur das wichtigste
(z.B. Logon und eine Query).</dd>
</dl>
</aside>
</section>
</section>
<section>
<section id="slide-org7ab9d32">
<h3 id="org7ab9d32"><span class="section-number-3">5.2</span> Unit-Tests</h3>
<p>
Unit-Tests sind Tests, die ein einzelnes Stück Code (ein Modul, eine
Klasse) testen und dabei möglichst unabhängig von allem anderen sind.
Sie testen explizit nicht das Zusammenspiel mehrerer Komponenten.
</p>
<p>
Gute Unit-Tests sollten <i>fast</i>, <i>isolated</i>, <i>repeatable</i>,
<i>self-validating</i> und <i>timely</i> sein.
</p>
</section>
<section id="slide-orgf77fd88">
<h4 id="orgf77fd88">FIRST</h4>
<dl>
<dt>Fast</dt><dd>Schnelle Ausführung. Wer z.B. ernsthaft mit <i>TDD</i> arbeiten
möchte, muss in die Größenordnung "unter drei Sekunden für mehrere
hundert Tests" kommen.</dd>
<dt>Isolated</dt><dd>Die Tests hängen nicht voneinander ab. Jeder ist für sich
einzeln ausführbar. Die Reihenfolge der Testfälle ist egal.
Notwendiges Setup ist Teil des jeweilgen Tests.</dd>
</dl>
</section>
<section id="slide-org28c2cc6">
<h4 id="org28c2cc6">FIRST</h4>
<dl>
<dt>Repeatable</dt><dd>Eine erneute Durchführung auf der gleichen Codebasis
muss exakt das gleiche Ergebnis bringen.</dd>
<dt>Self-Validating</dt><dd>Der Test prüft, ob das Ergebnis falsch oder korrekt
ist. Es werden nicht einfach Daten zusammengesucht, die dann im
Anschluss ein Mensch bewerten muss.</dd>
<dt>Timely</dt><dd>Tests sollten zeitnah geschrieben (siehe <i>TDD</i>) und zeitnah
ausgeführt werden (siehe <i>Continuous Integration</i>).</dd>
</dl>
</section>
<section id="slide-org3b7c37e">
<h4 id="org3b7c37e">Allgemeines</h4>
<ul>
<li>Tests sind <i>first-class</i>-code
<ul>
<li>Clean Code, Wartbarkeit, Wiederverwendung...</li>
</ul></li>
<li>Tests müssen bei Änderungen angepasst werden
<ul>
<li>in Schätzungen direkt mit einpreisen</li>
<li>getrennt ausgewiesen wird es gestrichen ;-)</li>
</ul></li>
<li>Tests regelmäßig ausführen, sonst veralten sie
<ul>
<li>siehe <i>Continuous Integration</i></li>
</ul></li>
<li>Tests sind Dokumentation...
<ul>
<li>...die bei Änderungen angepasst werden <b>muss</b></li>
<li>bei guten Tests kann eine Komponente allein auf Basis der Tests
reimplementiert werden</li>
</ul></li>
</ul>
</section>
<section id="slide-org82b2906">
<h4 id="org82b2906">Abhängigkeiten</h4>
<blockquote nil>
<p>
Ich kann das aber nicht einzeln testen, ich brauche den Server und die
Datenbank und das Netzwerk...
</p>
</blockquote>
<p class="fragment">
Standardlösung: <i>teile und herrsche</i>
</p>
</section>
<section id="slide-org5cc2c9b">
<h4 id="org5cc2c9b">Abhängigkeiten</h4>
<ul>
<li>Methode/Klasse/Komponente/Codestück feiner unterteilen in
<ul>
<li>testbaren Teil</li>
<li>nicht (einfach) testbaren Teil</li>
</ul></li>
<li>testbaren Teil testen!
<ul>
<li>Durchführen Datenbank-Requests fällt halt weg</li>
<li>Verarbeitung künstliches <code>ResultSet</code> trotzdem testbar</li>
</ul></li>
</ul>
<p>
Benötigte Abhängigkeiten ersetzen durch Dummys/Stubs/Mocks.
</p>
<aside class="notes">
<p>
Beispiel für statische Helper: Instanziierten Wrapper bauen, der kann
dann weggestubt werden.
</p>
</aside>
</section>
<section id="slide-orgecb7be8">
<h4 id="orgecb7be8">Innereien</h4>
<blockquote nil>
<p>
Ich würde das gerne testen, aber dafür müsste ich an $Detail herankommen,
das soll aber intern bleiben dran.
</p>
</blockquote>
<ul class="fragment">
<li>Unit-Tests sind <i>keine</i> Black-Box-Tests</li>
<li>Tests der Innereien sind erlaubt</li>
<li>Zugriffe darauf auch</li>
</ul>
</section>
<section id="slide-org359ab63">
<h4 id="org359ab63">Innereien</h4>
<p>
Standardlösung: <i>Sichtbarkeit erhöhen</i>
</p>
<ul>
<li>Problem
<ul>
<li><code>private</code>-Variable für Abhängigkeit</li>
<li>gefüllt per <code>@Inject</code> zur Laufzeit</li>
</ul></li>
<li>Lösung
<ul>
<li>Sichtbarkeit auf <code>package</code> erhöhen</li>
<li>Test kann direkt ein Dummy/Stub/Mock setzen</li>
<li>Injection-Framework muss nicht für den Test initialisiert werden</li>
</ul></li>
</ul>
</section>
</section>
<section>
<section id="slide-orge952f74">
<h3 id="orge952f74"><span class="section-number-3">5.3</span> Test your tests</h3>
<blockquote nil>
<p>
Schöne Unit-Tests haben Sie da, wäre doch schade, wenn die gar nichts tun.
</p>
</blockquote>
<ul>
<li>100% Codeabdeckung == sinnvolle Tests?</li>
</ul>
</section>
<section id="slide-org6e4a741">
<h4 id="org6e4a741">Beispielcode</h4>
<div class="org-src-container">
<pre class="src src-java"><span style="color: #00ffff;">private</span> <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">calc</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">a</span>, <span style="color: #98fb98;">b</span>, <span style="color: #98fb98;">c</span>) {
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">d</span> = a + b * c;
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">e</span> = a * b + c;
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">f</span> = d * e;
<span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i < <span style="color: #98fb98;">c</span>; i++) {
f += a;
e += d--;
}
<span style="color: #00ffff;">return</span> 3;
}
</pre>
</div>
</section>
<section id="slide-org72498b6">
<h4 id="org72498b6">Beispieltest</h4>
<div class="org-src-container">
<pre class="src src-java"><span style="color: #7fffd4;">@Test</span>
<span style="color: #00ffff;">public</span> <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">testCalc</span>() {
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">given</span>
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">a</span> = 3;
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">b</span> = 2;
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">c</span> = 1;
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">when</span>
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">result</span> = calc(a, b, c);
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">then</span>
assertThat(<span style="color: #00ffff;">new</span> <span style="color: #98fb98;">Date</span>(), notNullValue());
}
</pre>
</div>
<ul>
<li>Test grün</li>
<li>Codeabdeckung 100%</li>
<li>Testaussage == 0</li>
</ul>
</section>
<section id="slide-org3dde548">
<h4 id="org3dde548">Mutation Testing</h4>
<ul>
<li><i>mutiert</i> den Code:
<ul>
<li>Bedingungen umdrehen</li>
<li>Methodenaufrufe weglassen</li>
<li><code>return null</code> statt Objekten (und <code>RuntimeException</code> statt <code>null</code>)</li>
<li>usw.</li>
</ul></li>
<li>nur eine Änderung je Mutation
<ul>
<li>viele! Mutationen</li>
</ul></li>
<li>jede Mutation wird getestet</li>
<li>grüner Test -> Problem!</li>
<li>Java: <a href="http://pitest.org/">PIT mutation testing</a></li>
<li>Perl: <a href="https://metacpan.org/pod/Devel::Mutator">Devel::Mutator</a></li>
</ul>
</section>
</section>
<section>
<section id="slide-org1e953e3">
<h2 id="org1e953e3"><span class="section-number-2">6</span> Clean Code</h2>
<blockquote nil>
<p>
Der nächste Rewrite kommt bestimmt.
</p>
</blockquote>
<ul>
<li>denn: je schlimmer der Code, um so teurer jede Änderung</li>
<li>irgendwann ist Wegwerfen und Neumachen billiger</li>
<li>lässt sich das verhindern?
<ul>
<li>nein!</li>
<li>aber deutlich verzögern</li>
</ul></li>
</ul>
</section>
</section>
<section>
<section id="slide-org66aa249">
<h3 id="org66aa249"><span class="section-number-3">6.1</span> Nichtfunktionale Anforderungen</h3>
<p>
Code sollte...
</p>
<ul>
<li>gut lesbar</li>
<li>sprechend</li>
<li>leicht zu erweitern</li>
<li>wartungsfreundlich</li>
<li>so einfach wie möglich</li>
<li>so kompliziert wie nötig</li>
</ul>
<p>
...sein.
</p>
<p>
Dann klappt das auch mit der Haltbarkeit.
</p>
</section>
</section>
<section>
<section id="slide-org12bbaff">
<h3 id="org12bbaff"><span class="section-number-3">6.2</span> Clean-Code-Toolbox</h3>
<p>
Ähnlich den bekannten Design-Patterns gibt es auch im
Clean-Code-Bereich verschiedene Prinzipien und Techniken für bestimmte
Situationen, aus denen man sich nach Bedarf bedienen kann und die man
gezielt üben, ausprobieren und lernen kann.
</p>
<p>
Eine schöne Sammlung der einzenen Prinzipien findet sich auf <a href="http://clean-code-developer.de/">Clean
Code Developer</a> in der Auflistung der einzelnen Grade.
</p>
</section>
</section>
<section>
<section id="slide-org00f8c75">
<h3 id="org00f8c75"><span class="section-number-3">6.3</span> Pfadfinderregel</h3>
<blockquote nil>
<p>
Hinterlasse den Zeltplatz sauberer, als Du ihn vorgefunden hast.
</p>
</blockquote>
<p>
Das gilt auch für Code. Und wenn man sich eh gerade genau hier
eingelesen hat, weil man einen Bug gesucht oder etwas erweitert hat,
kann man auch nochmal fünf Minuten investieren, statt nur den Kopf zu
schütteln.
</p>
<ul>
<li>nur <i>Refactoring</i>, keine Funktionserweiterungen</li>
</ul>
</section>
</section>
<section>
<section id="slide-orgd0d3082">
<h3 id="orgd0d3082"><span class="section-number-3">6.4</span> don't repeat yourself (DRY)</h3>
<p>
Wiederholungen zu vermeiden ist ein Grundanliegen der Informatik,
sonst würden wir alle noch direkt mit Maschinencode arbeiten.
</p>
<ul>
<li>Duplikate können bei Änderungen vergessen oder übersehen werden.
<ul>
<li>daher: Code in Methoden/Klassen auslagern und mehrfach aufrufen</li>
<li>Nebeneffekt: Methodenaufrufe sind meist kürzer und übersichtlicher
und haben eine höhere Abstraktionsebene (fachliche Funktion)</li>
</ul></li>
<li>Der Aufruf vorhandener Methoden ist schneller als den Code selbst neu
zu schreiben und neu zu testen.</li>
</ul>
<aside class="notes">
<p>
Wikipedia sagt: Das Gegenteil ist <i>WET</i>:
</p>
<ul>
<li>write everything twice</li>
<li>we enjoy typing</li>
<li>waste everyone's time</li>
</ul>
</aside>
</section>
</section>
<section>
<section id="slide-org3ffef8b">
<h3 id="org3ffef8b"><span class="section-number-3">6.5</span> don't lie</h3>
<p>
Eine Variable/Methode/Klasse sollte möglichst passend benamst sein.
</p>
<ul>
<li>Bei einem Aufruf <code>konto.getKontonummer()</code> erwartet niemand, dass im
Hintergrund ein neues Konto angelegt wird, wenn noch keines
existiert.</li>
<li>Bei <code>nettoPreis = nettoPreis * 1.19</code> ist irgendwas faul.</li>
</ul>
<aside class="notes">
<p>
Benamsungsschema:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-left" />
<col class="org-left" />
<col class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Typ</th>
<th scope="col" class="org-left">public/global scope</th>
<th scope="col" class="org-left">private/local scope</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">Method</td>
<td class="org-left">short and generic</td>
<td class="org-left">long and detailed</td>