-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathold.xml
8529 lines (7835 loc) · 450 KB
/
old.xml
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
<?xml version="1.0" encoding="UTF-8"?>
<!--
This is a WordPress eXtended RSS file generated by WordPress as an export of your site.
It contains information about your site's posts, pages, comments, categories, and other content.
You may use this file to transfer that content from one site to another.
This file is not intended to serve as a complete backup of your site.
To import this information into a WordPress site follow these steps:
1. Log in to that site as an administrator.
2. Go to Tools: Import in the WordPress admin panel.
3. Install the "WordPress" importer from the list.
4. Activate & Run Importer.
5. Upload this file using the form provided on that page.
6. You will first be asked to map the authors in this export file to users
on the site. For each author, you may choose to map to an
existing user on the site or to create a new user.
7. WordPress will then import each of the posts, pages, comments, categories, etc.
contained in this file into your site.
-->
<!-- generator="WordPress.com" created="2016-02-08 12:56"-->
<rss version="2.0" xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="http://wordpress.org/export/1.2/">
<channel>
<title>The Maintenance Coder</title>
<link>https://maintenancecoder.wordpress.com</link>
<description>Hell is your own code - 12 months later</description>
<pubDate>Mon, 08 Feb 2016 12:56:06 +0000</pubDate>
<language>en</language>
<wp:wxr_version>1.2</wp:wxr_version>
<wp:base_site_url>http://wordpress.com/</wp:base_site_url>
<wp:base_blog_url>https://maintenancecoder.wordpress.com</wp:base_blog_url>
<wp:author>
<wp:author_login>Jim Burger</wp:author_login>
<wp:author_email>the-burge@outlook.com</wp:author_email>
<wp:author_display_name><![CDATA[Jim Burger]]></wp:author_display_name>
<wp:author_first_name><![CDATA[]]></wp:author_first_name>
<wp:author_last_name><![CDATA[]]></wp:author_last_name>
</wp:author>
<wp:category>
<wp:term_id>309</wp:term_id>
<wp:category_nicename>reviews</wp:category_nicename>
<wp:category_parent/>
<wp:cat_name><![CDATA[Reviews]]></wp:cat_name>
</wp:category>
<wp:category>
<wp:term_id>2301</wp:term_id>
<wp:category_nicename>software-development</wp:category_nicename>
<wp:category_parent/>
<wp:cat_name><![CDATA[Software Development]]></wp:cat_name>
<wp:category_description><![CDATA[All things software development related]]></wp:category_description>
</wp:category>
<wp:category>
<wp:term_id>1</wp:term_id>
<wp:category_nicename>uncategorized</wp:category_nicename>
<wp:category_parent/>
<wp:cat_name><![CDATA[Uncategorized]]></wp:cat_name>
</wp:category>
<wp:category>
<wp:term_id>2427</wp:term_id>
<wp:category_nicename>net</wp:category_nicename>
<wp:category_parent>software-development</wp:category_parent>
<wp:cat_name><![CDATA[.NET]]></wp:cat_name>
<wp:category_description><![CDATA[.NET related articles]]></wp:category_description>
</wp:category>
<wp:category>
<wp:term_id>54</wp:term_id>
<wp:category_nicename>general</wp:category_nicename>
<wp:category_parent>software-development</wp:category_parent>
<wp:cat_name><![CDATA[General]]></wp:cat_name>
</wp:category>
<wp:tag>
<wp:term_id>2427</wp:term_id>
<wp:tag_slug>net</wp:tag_slug>
<wp:tag_name><![CDATA[.NET]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>141</wp:term_id>
<wp:tag_slug>ajax</wp:tag_slug>
<wp:tag_name><![CDATA[AJAX]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>2290</wp:term_id>
<wp:tag_slug>architecture</wp:tag_slug>
<wp:tag_name><![CDATA[Architecture]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>9817</wp:term_id>
<wp:tag_slug>asp</wp:tag_slug>
<wp:tag_name><![CDATA[ASP]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>48992345</wp:term_id>
<wp:tag_slug>asp-mvc-3</wp:tag_slug>
<wp:tag_name><![CDATA[ASP MVC 3]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>10216727</wp:term_id>
<wp:tag_slug>back2basics</wp:tag_slug>
<wp:tag_name><![CDATA[Back2Basics]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>75400</wp:term_id>
<wp:tag_slug>bdd</wp:tag_slug>
<wp:tag_name><![CDATA[BDD]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>16995</wp:term_id>
<wp:tag_slug>change-management</wp:tag_slug>
<wp:tag_name><![CDATA[Change management]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>40513538</wp:term_id>
<wp:tag_slug>check-in-policies</wp:tag_slug>
<wp:tag_name><![CDATA[Check In Policies]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>514761</wp:term_id>
<wp:tag_slug>clr</wp:tag_slug>
<wp:tag_name><![CDATA[CLR]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>332</wp:term_id>
<wp:tag_slug>coding</wp:tag_slug>
<wp:tag_name><![CDATA[Coding]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>11414</wp:term_id>
<wp:tag_slug>com</wp:tag_slug>
<wp:tag_name><![CDATA[COM]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>45809</wp:term_id>
<wp:tag_slug>configuration</wp:tag_slug>
<wp:tag_name><![CDATA[Configuration]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>21681582</wp:term_id>
<wp:tag_slug>content-controls</wp:tag_slug>
<wp:tag_name><![CDATA[Content Controls]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>2363040</wp:term_id>
<wp:tag_slug>cors</wp:tag_slug>
<wp:tag_name><![CDATA[CORS]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>20740</wp:term_id>
<wp:tag_slug>csharp</wp:tag_slug>
<wp:tag_name><![CDATA[CSharp]]></wp:tag_name>
<wp:tag_description><![CDATA[C# Programming Language]]></wp:tag_description>
</wp:tag>
<wp:tag>
<wp:term_id>38696409</wp:term_id>
<wp:tag_slug>documentgeneration</wp:tag_slug>
<wp:tag_name><![CDATA[DocumentGeneration]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>1294027</wp:term_id>
<wp:tag_slug>fsharp</wp:tag_slug>
<wp:tag_name><![CDATA[FSharp]]></wp:tag_name>
<wp:tag_description><![CDATA[F# Programming Language]]></wp:tag_description>
</wp:tag>
<wp:tag>
<wp:term_id>116486</wp:term_id>
<wp:tag_slug>functional-programming</wp:tag_slug>
<wp:tag_name><![CDATA[functional programming]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>10518</wp:term_id>
<wp:tag_slug>http</wp:tag_slug>
<wp:tag_name><![CDATA[HTTP]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>133657</wp:term_id>
<wp:tag_slug>kata</wp:tag_slug>
<wp:tag_name><![CDATA[kata]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>2761</wp:term_id>
<wp:tag_slug>languages</wp:tag_slug>
<wp:tag_name><![CDATA[Languages]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>1821</wp:term_id>
<wp:tag_slug>laptop</wp:tag_slug>
<wp:tag_name><![CDATA[Laptop]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>366</wp:term_id>
<wp:tag_slug>memes</wp:tag_slug>
<wp:tag_name><![CDATA[Memes]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>295211</wp:term_id>
<wp:tag_slug>openxml</wp:tag_slug>
<wp:tag_name><![CDATA[OpenXml]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>38696408</wp:term_id>
<wp:tag_slug>openxmlsdk</wp:tag_slug>
<wp:tag_name><![CDATA[OpenXMLSdk]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>178495</wp:term_id>
<wp:tag_slug>powershell</wp:tag_slug>
<wp:tag_name><![CDATA[Powershell]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>141911</wp:term_id>
<wp:tag_slug>prototyping</wp:tag_slug>
<wp:tag_name><![CDATA[Prototyping]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>99869</wp:term_id>
<wp:tag_slug>resharper</wp:tag_slug>
<wp:tag_name><![CDATA[Resharper]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>15314</wp:term_id>
<wp:tag_slug>rest</wp:tag_slug>
<wp:tag_name><![CDATA[REST]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>1745</wp:term_id>
<wp:tag_slug>review</wp:tag_slug>
<wp:tag_name><![CDATA[Review]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>53511</wp:term_id>
<wp:tag_slug>source-control</wp:tag_slug>
<wp:tag_name><![CDATA[Source control]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>164684</wp:term_id>
<wp:tag_slug>svn</wp:tag_slug>
<wp:tag_name><![CDATA[SVN]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>76604</wp:term_id>
<wp:tag_slug>tdd</wp:tag_slug>
<wp:tag_name><![CDATA[TDD]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>202925</wp:term_id>
<wp:tag_slug>telerik</wp:tag_slug>
<wp:tag_name><![CDATA[Telerik]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>342877</wp:term_id>
<wp:tag_slug>tfs</wp:tag_slug>
<wp:tag_name><![CDATA[TFS]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>540</wp:term_id>
<wp:tag_slug>themes</wp:tag_slug>
<wp:tag_name><![CDATA[Themes]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>1981</wp:term_id>
<wp:tag_slug>tools</wp:tag_slug>
<wp:tag_name><![CDATA[Tools]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>2774581</wp:term_id>
<wp:tag_slug>vb9</wp:tag_slug>
<wp:tag_name><![CDATA[VB9]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>833</wp:term_id>
<wp:tag_slug>vbscript</wp:tag_slug>
<wp:tag_name><![CDATA[VBScript]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>18060</wp:term_id>
<wp:tag_slug>vim</wp:tag_slug>
<wp:tag_name><![CDATA[vim]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>6678</wp:term_id>
<wp:tag_slug>visual-studio</wp:tag_slug>
<wp:tag_name><![CDATA[Visual Studio]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>162</wp:term_id>
<wp:tag_slug>word</wp:tag_slug>
<wp:tag_name><![CDATA[Word]]></wp:tag_name>
</wp:tag>
<wp:tag>
<wp:term_id>363132</wp:term_id>
<wp:tag_slug>xss</wp:tag_slug>
<wp:tag_name><![CDATA[XSS]]></wp:tag_name>
</wp:tag>
<generator>http://wordpress.com/</generator>
<image>
<url>https://s2.wp.com/i/buttonw-com.png</url>
<title>The Maintenance Coder</title>
<link>https://maintenancecoder.wordpress.com</link>
</image>
<item>
<title>About</title>
<link>https://maintenancecoder.wordpress.com/about/</link>
<pubDate>Wed, 16 Dec 2009 06:49:51 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false"/>
<description/>
<content:encoded><![CDATA[Thanks for reading my blog!
I've been coding for nearly 20 years, most recently in .NET. I'm no expert, but I share what I learn.
]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>2</wp:post_id>
<wp:post_date>2009-12-16 06:49:51</wp:post_date>
<wp:post_date_gmt>2009-12-16 06:49:51</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>about</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>page</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<wp:postmeta>
<wp:meta_key>_edit_last</wp:meta_key>
<wp:meta_value><![CDATA[11285636]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_page_template</wp:meta_key>
<wp:meta_value><![CDATA[default]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>nervoustych-xml.txt</title>
<link>https://maintenancecoder.wordpress.com/nervoustych-xml-txt/</link>
<pubDate>Wed, 16 Dec 2009 07:11:35 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">http://maintenancecoder.files.wordpress.com/2009/12/nervoustych-xml.txt</guid>
<description/>
<content:encoded><![CDATA[http://maintenancecoder.files.wordpress.com/2009/12/nervoustych-xml.txt]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>3</wp:post_id>
<wp:post_date>2009-12-16 07:11:35</wp:post_date>
<wp:post_date_gmt>2009-12-16 07:11:35</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>nervoustych-xml-txt</wp:post_name>
<wp:status>inherit</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>attachment</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<wp:attachment_url>https://maintenancecoder.files.wordpress.com/2009/12/nervoustych-xml.txt</wp:attachment_url>
</item>
<item>
<title>nervoustych-wxr.txt</title>
<link>https://maintenancecoder.wordpress.com/nervoustych-wxr-txt/</link>
<pubDate>Wed, 16 Dec 2009 07:12:10 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">http://maintenancecoder.files.wordpress.com/2009/12/nervoustych-wxr.txt</guid>
<description/>
<content:encoded><![CDATA[http://maintenancecoder.files.wordpress.com/2009/12/nervoustych-wxr.txt]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>4</wp:post_id>
<wp:post_date>2009-12-16 07:12:10</wp:post_date>
<wp:post_date_gmt>2009-12-16 07:12:10</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>nervoustych-wxr-txt</wp:post_name>
<wp:status>inherit</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>attachment</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<wp:attachment_url>https://maintenancecoder.files.wordpress.com/2009/12/nervoustych-wxr.txt</wp:attachment_url>
</item>
<item>
<title>wordpress-2009-12-16-xml.txt</title>
<link>https://maintenancecoder.wordpress.com/wordpress-2009-12-16-xml-txt/</link>
<pubDate>Wed, 16 Dec 2009 07:35:46 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">http://maintenancecoder.files.wordpress.com/2009/12/wordpress-2009-12-16-xml.txt</guid>
<description/>
<content:encoded><![CDATA[http://maintenancecoder.files.wordpress.com/2009/12/wordpress-2009-12-16-xml.txt]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>9</wp:post_id>
<wp:post_date>2009-12-16 07:35:46</wp:post_date>
<wp:post_date_gmt>2009-12-16 07:35:46</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>wordpress-2009-12-16-xml-txt</wp:post_name>
<wp:status>inherit</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>attachment</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<wp:attachment_url>https://maintenancecoder.files.wordpress.com/2009/12/wordpress-2009-12-16-xml.txt</wp:attachment_url>
</item>
<item>
<title>1post-xml.txt</title>
<link>https://maintenancecoder.wordpress.com/1post-xml-txt/</link>
<pubDate>Wed, 16 Dec 2009 07:57:23 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">http://maintenancecoder.files.wordpress.com/2009/12/1post-xml.txt</guid>
<description/>
<content:encoded><![CDATA[http://maintenancecoder.files.wordpress.com/2009/12/1post-xml.txt]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>10</wp:post_id>
<wp:post_date>2009-12-16 07:57:23</wp:post_date>
<wp:post_date_gmt>2009-12-16 07:57:23</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>1post-xml-txt</wp:post_name>
<wp:status>inherit</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>attachment</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<wp:attachment_url>https://maintenancecoder.files.wordpress.com/2009/12/1post-xml.txt</wp:attachment_url>
</item>
<item>
<title>Throw your code away</title>
<link>https://maintenancecoder.wordpress.com/2009/10/01/permalinkguide84ab527-a146-430d-852d-04646ad1ba5b/</link>
<pubDate>Thu, 01 Oct 2009 03:54:06 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,e84ab527-a146-430d-852d-04646ad1ba5b.aspx</guid>
<description/>
<content:encoded><![CDATA[So every now and again I hear about developers doing a thing called <em>prototyping. </em>It sounds intriguing enough, you code out a bunch of functionality <strong>quickly. </strong>What happens next is even more intriguing: apparently the idea is to now go and use this code as the basis for your production code. Not rewrite it per se, actually reuse this rapidly, sloppily developed code and ultimately deploy it.
If this is your idea of prototyping, you're <strong>doing it wrong.</strong>
This, dear readers, is a prototype:
<a href="http://www.flickr.com/photos/daveoflogic/3579407924/"> <img style="display:inline;border-width:0;" title="2004 Ferrari 612 Scalietti - 1:3 Wind Tunnel Prototype. Photo taken by daveoflogic. Courtesy of Flickr" src="http://farm4.static.flickr.com/3305/3579407924_898fbfe1e0_m_d.jpg" border="0" alt="2004 Ferrari 612 Scalietti - 1:3 Wind Tunnel Prototype. Photo taken by daveoflogic. Courtesy of Flickr" width="244" height="184" /></a>
Now you could try selling this car, I’m sure somebody would buy it, but it won’t drive on any road. What is the point of such a thing? It is a 1:3 scale model presumably made from some cheap plastic like material, that was never intended to hit the roads. It isn’t made according to any design standards to do with structural integrity, there are no seats, and no steering wheel. There is no engine, it doesn’t move, it just sits there. It doesn’t even look good, in fact it looks terrible.
Prototyping as an engineering practice is about what you learn, not what you create. In the above case the point is learning about the aerodynamic properties of the cars shape. Nothing more. You wont see the car manufacturer take this object and turn it into a road vehicle. The very thing that makes it a prototype makes it unsuitable for the true purpose of the final product.
They key feature of any prototype is that they make assumptions about their environment; for code this means things like hard-coded connection strings, XML test data instead of SQL tables, Balsamiq UIs, OO design principles are thrown out the window, faking out unneeded side effects and so forth.
Taking this code and using it is a mistake, because invariably you will forget to remove all the assumptions and leave something behind. You might also paint yourself into an architectural corner you could have otherwise avoided. The point is folks: <strong>tomorrow never comes. </strong>The attitude of, “I’ll just refactor this later into something that is more suitable for production” is based around the fallacious idea that you will have time later.
What happens is that when someone sees this prototype who doesn’t really know its in fact made from duct tape* and balsa wood, <strong>they assume that you're finished and give you more work to do.</strong>
Failing that, we often fall into the trap of convincing ourselves that this piece of work is done, and we can get to building some more cool functionality. Lets face it, discovering new things and producing cool new features is the fun part of what we do. It's tempting to leave things at the prototype stage and build other components around them.
Recently I was asked, if you prototype without TDD then are you in fact practicing <em>real</em> TDD? My reaction to that is that depends on what you do *after* you throw away your prototype. You shouldn’t be doing prototyping and production coding at the same time, regardless of your thoughts on TDD. Throw your prototypes in the bin where they belong.
As an aside, I recently became aware of <a href="http://www.21apps.com/development/daily-tdd-kata/">TDD</a> <a href="http://www.21apps.com/development/daily-tdd-kata/">Kata</a> which in effect, is a way of using a prototype (read throwaway) <strong>problem domain,</strong> to learn something about the act of TDD itself. Also very useful by the sounds, I might try it out.
* Some people clearly make a living out of being <a href="http://www.joelonsoftware.com/items/2009/09/23.html">duct</a> <a href="http://www.joelonsoftware.com/items/2009/09/23.html">tape coders</a>. I just feel sorry for the legions of ‘maintenance developers’ that invariably follow in the wake of their greatness.]]></content:encoded>
<excerpt:encoded><![CDATA[So every now and again I hear about developers doing a thing called prototyping.]]></excerpt:encoded>
<wp:post_id>12</wp:post_id>
<wp:post_date>2009-10-01 03:54:06</wp:post_date>
<wp:post_date_gmt>2009-10-01 03:54:06</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>permalinkguide84ab527-a146-430d-852d-04646ad1ba5b</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="post_tag" nicename="coding"><![CDATA[Coding]]></category>
<category domain="post_tag" nicename="prototyping"><![CDATA[Prototyping]]></category>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<category domain="post_tag" nicename="tdd"><![CDATA[TDD]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[12]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[12]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>What me, cheap?</title>
<link>https://maintenancecoder.wordpress.com/2009/03/11/permalinkguid2bef4dc3-0ea9-4c55-b77f-846c54431fca/</link>
<pubDate>Tue, 10 Mar 2009 23:03:46 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,2bef4dc3-0ea9-4c55-b77f-846c54431fca.aspx</guid>
<description/>
<content:encoded><![CDATA[In <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/08/why-are-we-so-cheap-with-software.aspx"></a><a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/08/why-are-we-so-cheap-with-software.aspx">a recent post,</a> <a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx">Jimmy</a><a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx">Bogard</a> goes on the offensive and asks why are we, as developers so cheap when it comes to buying tools for software development?
Jimmy points out as soon as a dev wants to use a productivity tool, the requisition department seems to kick in and find a reason why not to spend money on it. Sometimes that department is the developers LHS of their brain kicking in, other times it's a whole team of accountants waving their bottom lines at the dev team in dismay.
I’m going to defend my frugality. And the LHS of my brain. <strong>I’m not cheap</strong>, I just have a <a href="http://www.secretgeek.net/lft.asp">low</a> <a href="http://www.secretgeek.net/lft.asp">tolerance for frustration</a>, <a href="http://blogoscoped.com/archive/2005-08-24-n14.html">am</a> <a href="http://blogoscoped.com/archive/2005-08-24-n14.html">lazy & dumb</a>, and have a surplus of free stuff <a href="http://sourceforge.net/">available</a><a>to</a><a href="http://codeplex.com">me</a>. <a href="http://ayende.com/Blog/archive/2009/02/06/closing-the-xheo-saga.aspx">Like</a> <a href="http://ayende.com/Blog/archive/2009/02/06/closing-the-xheo-saga.aspx">many others,</a> I’ve also been burned by snake oil merchants more times than I care to remember. If that makes me cheap then chuck me in the deep fryer and throw me to the capitalists.
<img style="display:inline;margin:0;" title="Alfred E Neuman on the face of a US three dollar bill" src="http://farm1.static.flickr.com/218/469212512_907d717827.jpg" alt="Alfred E Neuman on the face of a US three dollar bill" width="472" height="314" />
Jimmy is completely correct though, the issue lies with the people <strong>who set the budgets </strong>for tooling. Their job is to save the company money on paper, so when asked for a fancy diff tool, they automatically extrapolate that cost over every desktop and come up with some scary figure.
I think this could represent the incorrect approach. Give each developer control over the tools they are going to need to automate their daily work. They are as power tools are to a tradesperson. Each developer will need different tools. Let them sort out the overlap and find the bulk deals if they exist.
I’ll tell you what I consider cheap:
<ol>
<li>Employers who expect developers to ‘just do it’. Serious development requires serious power tools.</li>
<li>Employers who don’t allow developers to augment their own tool set. ‘You will use the standard toolkit and NOT deviate from it.’</li>
<li>Developers who think that their employers should fork out for every tool that their heart desires.</li>
</ol>
I know point three is going to put some noses out of joint. I don’t care. I’ve long been a believer that a developer should be in charge of their own toolkit. In a very real sense, this means you are in charge of your own productivity. I also believe that a developer should be given a regular tool allowance by their
employer. Tools break or become obsolete; they need replacing or upgrading. The best person to decide when and what, is the developer.
Finally, in the case of a dispute, a developer should be encouraged to buy the tool of their dreams, and upon proving its worth to the employer, be reimbursed. Oh…and besides all that…. I don’t personally see what’s wrong with being cheap anyhow ;)]]></content:encoded>
<excerpt:encoded><![CDATA[In a recent post, JimmyBogard goes on the offensive and asks why are we, as developers so cheap when it comes to buying tools for software development?]]></excerpt:encoded>
<wp:post_id>13</wp:post_id>
<wp:post_date>2009-03-11 08:33:46</wp:post_date>
<wp:post_date_gmt>2009-03-10 23:03:46</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>permalinkguid2bef4dc3-0ea9-4c55-b77f-846c54431fca</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<category domain="post_tag" nicename="tools"><![CDATA[Tools]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[13]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[13]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>My –isms</title>
<link>https://maintenancecoder.wordpress.com/2009/02/10/my-isms/</link>
<pubDate>Mon, 09 Feb 2009 16:36:02 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,826827b3-3f22-47cf-a034-5c127578977c.aspx</guid>
<description/>
<content:encoded><![CDATA[<h3>
</h3>
<h3>I AM<p></p>
</h3>
<p>Dogmatic about <a href="http://www.pragprog.com/">pragmatism</a>. </p>
<p>Cynical of <a href="http://www.i-cynic.com/whatis.asp">cynicism</a>.</p>
<p>Prone to <a href="http://imgs.xkcd.com/comics/conspiracy_theories.png">scepticism</a>.</p>
<p>Attracted to <a href="http://en.wikipedia.org/wiki/Absurdism"><span class="mceItemHidden"><span class="hiddenSpellError">absurdism</span></span></a>.</p>
<p>Suspicious of <a href="http://www.imdb.com/title/tt0094291/">capitalism</a>.</p>
<p></p><hr>
<p></p>
<p>My feeble attempt at a blog meme. Go <a href="http://www.morewords.com/ends-with/ism/">here</a> and</p>
<p>pick 5 of your –isms. Its poetry made easy :P</p>
<p>If you’ve read this and have a blog of your own - consider yourself tagged!</p>
<p> <img src="http://www.nervoustych.com/blog/aggbug.ashx?id=826827b3-3f22-47cf-a034-5c127578977c" width="0" height="0"></p><p><br></p>]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>826827</wp:post_id>
<wp:post_date>2009-02-10 02:06:02</wp:post_date>
<wp:post_date_gmt>2009-02-09 16:36:02</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>my-isms</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="post_tag" nicename="memes"><![CDATA[Memes]]></category>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[permalinkguid826827b3-3f22-47cf-a034-5c127578977c]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[826827]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[826827]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Giving a damn about the broken windows</title>
<link>https://maintenancecoder.wordpress.com/2009/02/09/giving-a-damn-about-the-broken-windows/</link>
<pubDate>Sun, 08 Feb 2009 22:58:27 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,cfae6577-d301-42bb-a4bc-7952586c7249.aspx</guid>
<description/>
<content:encoded><![CDATA[Leon Bambrick has written some great posts lately, and two things have really struck a chord with me. Firstly, in 6 ways to become a better programmer in 8 minutes <a href="http://www.secretgeek.net/6min_program.asp">(or was it the other way around)</a> he drives home the point that attempting to increase code coverage in your project by 1% is a Good Thing. Especially given the fact that its likely that your code coverage is 0% hmm? The biggest gain in unit testing probably arises from that first attempt to bring your code base under some semblance of control.
Secondly, <a href="http://www.secretgeek.net/give_take.asp">in an earlier post</a> he finishes up by espousing the importance of passion.
<blockquote>You've got to give a shit about the code you write and the people who use it. If you
don't care about it, you're never going to enjoy it properly.</blockquote>
“Give a shit” about your code – otherwise coming to work is pointless. Go home and find out how to care about the project before coming back. I care about unit testing, because I care about my code. It saddens me to think that most code bases out there have a code coverage of 0%. More so, it saddens me that there are people who don’t even try to understand unit testing and how it can work for you, and not against you.
IMNSHO if you haven’t wrapped your head around unit testing by now, then <a href="http://www.codinghorror.com/blog/archives/000640.html">you’re are not doing your job properly</a>. You can’t possibly remember all the permutations of a complex problem, nor can you verify them all. So when you figure one out, you should verify it, code it and check it in.
It is also a shame that <a href="http://www.joelonsoftware.com/items/2009/01/31.html">prominent members</a> of the coding community can’t get their story straight. There are still plenty of people out there who just don’t seem to get it. Even with a test suite in place, it may become neglected. Progressively it too, falls into the category of legacy code.
So how do we improve the efficacy of our test suite if we have one? First and foremost:
<strong>Have tests run as part of the build, and fail the build if the tests do not pass.</strong>
This is a no brainer. There are so many benefits to having tests and automating them that I cannot begin to summarize them here. <a href="http://martinfowler.com/articles/continuousIntegration.html#MakeYourBuildSelf-testing">Just</a><a href="http://www.codeproject.com/KB/architecture/onunittesting.aspx">do</a><a href="http://www.codeproject.com/KB/architecture/onunittesting.aspx">it.</a> Of course this is no good, if other team members aren’t compelled to fix the build. Which lead Leon to the conclusion that some form of build monitor is a definite improvement. If you don’t have a <a href="http://www.thinkgeek.com/geektoys/warfare/8bc4/?cpg=ab">laser</a> <a href="http://www.thinkgeek.com/geektoys/warfare/8bc4/?cpg=ab">guided USB missile launcher</a> pointed at the person who broke the build, then your still fighting an uphill battle to <strong>make people care</strong>.
So, failing office warfare, you can try lowering the cognitive effort of understanding unit testing in the first place. The testing newbie usually finds learning about mock objects, test fakes, test runners and testing frameworks up front all a bit too much.
<strong>Writing neat test code helps testing newbies.</strong> I like to impose the following rules on myself.
<ol>
<li>Use plain English when naming test classes, methods and variables</li>
<li>Avoid obnoxious acronyms</li>
<li>Clearly name test fakes and mocks</li>
<li>Differentiate between the ‘expected’ and the ‘actual’ value</li>
<li>Minimize the asserts in your tests</li>
<li>Use language features to full effect to improve readability</li>
<li>Refactor your tests as ruthlessly as your code</li>
</ol>
<h3>Use plain English when naming</h3>
Testing is about specification, and should read as such. Having a class called FooFixture makes sense to some, but everybody understands WhenEmailingACustomer. Similarly, a test named ShouldThrowWhenNullParm(), is too obscure. Should throw what exception? Which ‘parm’… schnitzel or olive parm? Avoid such cryptograms and defer to a more English style. ShouldThrowANullReferenceExceptionWhenProvidedANullFooParameter might be a little long, but at least it doesn’t need deciphering. Hell, we are all coding on <a href="http://www.codinghorror.com/blog/archives/000012.html">24” widescreens and better</a> right? :P
Some people say that the code should document the test and the method name is a little superfluous. Sorry, but I say: <strong>nuts</strong>. I want to skim a list of test methods and fixtures to learn how a program works, as well as what it does, without reading the code, and so should my team members.
I also advocate using underscores, to further improve readability, however I realise this is a personal preference. For example:
[sourcecode language="csharp"]
[TestClass]
public&nbsp;class Concerning_the_person_controller
{
[TestMethod]
public&nbsp;void It_should_retrieve_the_tallest_person_from_the_person_model()
{
//TODO: Write a READABLE test
}
}
[/sourcecode]
<h3>Avoid acronyms </h3>
I’m a fan of marking the “system under test” and I used to use the acronym, SUT to do so. However, I’ve come full circle and realized that having a CreateSUT method is taking it all too far. You will only serve to confuse the masses who aren’t up to speed on the latest BDD TLA.
<h3>Clearly name fakes and mocks</h3>
<em>You</em> might remember that you faked out the FooService in the TestInitialize (Setup) method, but by the 5th test, I can guarantee you that the testing newbie will have forgotten. Keep reminding yourself and others by sticking ‘fake’ in the name of the variable somewhere. Please do name the fake class as such also. If you are going to hide behind an interface, call it out explicitly. Remember, you are coding a specification.
[sourcecode language="csharp"]
[TestClass]
public class Concerning_the_person_controller
{
[TestMethod]
public void It_should_retrieve_the_tallest_person_from_the_person_model()
{
IPersonModel fakePersonModel = new FakePersonModel();
//...
}
}
[/sourcecode]
<h3>Differentiate the expected and actual value </h3>
Similarly, if you are going to cache an expected or actual value, make it clear to what its purpose is. People who haven’t memorized every overload of Assert.AreEqual will quickly forget where what goes where. Keep reminding them with verbose naming.
[sourcecode language="csharp"]
[TestClass]
public class Concerning_the_person_controller
{
[TestMethod]
public void It_should_retrieve_the_tallest_person_from_the_person_model()
{
IPersonModel fakePersonModel = new fakePersonModel();
var expectedPerson = new Person() {
FirstName = "Joe",
LastName = "Hill",
Height = 203.00,
};
fakePersonModel.Persons.Add(expectedPerson);
//..
}
}
[/sourcecode]
<h3>Minimize your asserts </h3>
I’m no ‘1 assert per test’ nazi; sometimes it makes sense to group asserts. However, aiming to keep them to a minimum will further help the readability. Newbie's (and refactoring tools) don’t always realise that Asserts are really potential method exit points so keeping them close to the bottom of the test helps a lot too.
[sourcecode language="csharp"]
[TestClass]
public class Concerning_the_person_controller
{
[TestMethod]
public void it_should_retrieve_the_tallest_person_from_the_person_model()
{
IPersonModel fakePersonModel = new FakePersonModel();
var expectedPerson = new Person();
var expectedPerson = new Person() {
FirstName = "Joe",
LastName = "Hill",
Height = 203.00,
};
fakePersonModel.Persons.Add(expectedPerson);
var personController = new PersonController(fakePersonModel);
Assert.AreSame(expectedPerson, personController.RetrieveTallestPerson());
}
}
[/sourcecode]
<h3>Use language features to improve readability</h3>
Extension methods are a boon to readable tests. Practice a little language oriented programming and write a more readable testing interface for your colleagues to grok quicker. Or use a test framework that has done some of the work for you. For instance I have put together a library for internal use that has extension methods for common assertions to make them more English Readable®. Every time I come up with a new sentence, the test drives out development of my internal library, which has a nice side benefit of being useful in other projects.
[sourcecode language="csharp"]
[TestClass]
public class Concerning_the_person_controller
{
[TestMethod]
public void It_should_retrieve_the_tallest_person_from_the_person_model()
{
IPersonModel fakePersonModel = new FakePersonModel();
var expectedPerson = new Person
{
FirstName = "Joe",
LastName = "Hill",
Height = 203.00
};
fakePersonModel.Persons.Add(expectedPerson);
var personController = new PersonController(fakePersonModel);
var actualPerson = personController.RetrieveTallestPerson();
actualPerson.should().be_the_same_as_the(expectedPerson);
}
}
[/sourcecode]
You might even consider going one step further and providing a project specific DSL to really capture your intent. However the further you go down this route, the further you might obscure things, so be cautious.
<h3>Refactor your tests as ruthlessly as your code</h3>
Don’t repeat yourself, and refactor your tests when you see opportunity. By all means, take full advantage of the testing framework - as long as it works to your advantage. [TestInitialize/TestCleanup] or [SetUp/TearDown]routines will get missed, but explicit calls to a function will not. Furthermore, allowing for reading ‘top-down’ will win you extra brownie points.
[sourcecode language="csharp"]
[TestClass]
public class Concerning_the_person_controller
{
private Person TallestPerson;
private Person FirstPerson;
private PersonController CreatePersonControllerWithDependencies()
{
IPersonModel fakePersonModel = <span style="color: blue;">new</span> FakePersonModel();
var person = new Person {
FirstName = "Joe",
LastName = "Hill"
Height = 203.00
&nbsp;};
TallestPerson = person;
fakePersonModel.Persons.Add(person);
person = new Person {
FirstName = "John",
LastName = "Alfred",
Height = 200.00
&nbsp;};
FirstPerson = person;
fakePersonModel.Persons.Add(person);
return new PersonController(fakePersonModel);
}
[TestMethod]
public void It_should_retrieve_the_tallest_person_from_the_person_model()
{
var personController = CreatePersonControllerWithDependencies();
var actualPerson = personController.RetrieveTallestPerson();
actualPerson.should().be_the_same_as_the(TallestPerson);
}
[TestMethod]
public void It_should_retrieve_all_people_in_alphabetical_order_of_last_name()
{
var personController = CreatePersonControllerWithDependencies();
var allPeople = personController.RetrieveAllPeople();
allPeople.Count.should().equal(2);
allPeople[0].should().be_the_same_as_the(FirstPerson);
}
}
[/sourcecode]
If you haven’t figured it out already, then what all these suggestions amount to, is this: Treat your tests as well as your production code if you want people to bother keeping them up to date.
It is simply the <a href="http://www.artima.com/intv/fixit.html">broken windows idea from pragmatic programmer</a>. If you haven’t got some sort of mechanism to hold people accountable for build breakages, then simply getting in there and caring enough to fix the broken windows might be all you have left.
Broken windows? Don’t live with them. Give a damn.]]></content:encoded>
<excerpt:encoded><![CDATA[Leon Bambrick has written some great posts lately, and two things have really struck a chord with me. ]]></excerpt:encoded>
<wp:post_id>826828</wp:post_id>
<wp:post_date>2009-02-09 08:28:27</wp:post_date>
<wp:post_date_gmt>2009-02-08 22:58:27</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>giving-a-damn-about-the-broken-windows</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="net"><![CDATA[.NET]]></category>
<category domain="post_tag" nicename="coding"><![CDATA[Coding]]></category>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<category domain="post_tag" nicename="tdd"><![CDATA[TDD]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[826828]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[826828]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Software changes</title>
<link>https://maintenancecoder.wordpress.com/2009/02/05/software-changes/</link>
<pubDate>Wed, 04 Feb 2009 22:18:51 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,cb9eace6-83e5-452e-b847-a46ca09dda0b.aspx</guid>
<description/>
<content:encoded><![CDATA[How you react and prepare for change is very important; it can make or break a project. Allow for changes that wont come and you’ve written too much code. Forget to allow for other types of change and your application becomes either brittle or unwieldy in the face of change.
Software change <a href="http://www.comp.lancs.ac.uk/computing/resources/IanS/SE7/ElectronicSupplements/SWChange.pdf">has been divided into 3 flavours in the past:</a>
<h2>Re-architecture</h2>
Re-architecture is a more ruthless variety of change that involves changing the very foundations of the software to cope with new requirements. A classic move would be from a single tier application to an n-tier design in order to allow for multiple users.
<h2>Re-engineering</h2>
Re-engineering is essentially refactoring; the process of re-writing software to make it easier to understand, without adding new functionality. Its the type of change
developers love, but project managers hate, and architects put up with. Simplification, removal of duplication, consistency etc. All the good stuff.
<h2>Software Maintenance</h2>
Maintenance is the act of reacting to a change in software requirements, however the fundamental software structure is not changed. This is the change we tend to deal with the most as developers, requirements are forever changing from the end user, to the very platforms we work on. I’m mainly picking on this kind of change, however I’m going to split hairs even further.
<h2>2 Kinds of Requirements Change</h2>
There are possibly more, but I’m thinking of two types in particular:
<ul>
<li>Changes that are unilateral</li>
<li>Changes that… aren’t</li>
</ul>
What I mean is this. <strong>If you cannot avoid changing something in all layers of your software in order to accommodate a new or updated requirement, then you have a unilateral change.</strong> An example would be in a typical line of business application.
The product owner would like you to add support for a second telephone number. The software currently supports one. No matter how many layers you have, you will likely need to change all of them to support this change. <strong>Having a PersonDTOFactoryServiceManagerProvider class might get in the way of a good time here.</strong>
In this same application, the user now informs you that the business rules for the concept of “Deferred” has changed. This is a localizable change – handled properly. Good apps will have this sort of logic tucked away in its own layer, and will not need to be replicated in either the UI or the DB. <strong>Badly written, tightly coupled apps will have you writing code in UI event handlers and SQL change scripts.</strong>
Localizable changes happen daily and they cost developers time by the bucket load. I expect them to occur and I lovingly call reacting to these changes as ‘my job’. Unilateral changes on the other hand, tend to come en masse with deadlines attached. <strong>They can be mistakenly given too much weight in the design process as a result.</strong> It’s these changes that can cause a developer to contract a phobia of layers. Personally, I expect these changes to occur almost as often as the former, however I like to call these changes ‘version next’ where at all possible.
<h2>Defence</h2>
<strong>The real issue is defending oneself from change and how much defence to put up, and how much that defence costs you. </strong>The method of protecting yourself from unilateral change, is to minimize the amount of layers you have to deal with when unilateral changes occur. Defending yourself against localizable changes, is often done by increasing the number of layer in your application, mainly to improve the chances of changes only effecting one layer at a time.
“Layer” is a difficult term, and I use it in the sense that they talk to one another via an interface. They do not depend on one another in order to perform their function. Think ‘abstraction layer’.
<h2>Conflict</h2>
The tension between these two types of change could be seen as a manifestation of <a href="http://en.wikipedia.org/wiki/Conway's_Law">Conway’s Law</a>. I also believe that this tension is why n-tier applications tend towards a <a href="http://en.wikipedia.org/wiki/Multitier_architecture">layer count of 3 and above</a>. Adding layers can be the simplest way to turn what appears to be a horrible sweeping change. For instance you can use the <a href="http://en.wikipedia.org/wiki/Multitier_architecture#Comparison_with_the_MVC_architecture">MVC pattern</a> to separate the UI from the DAL. The danger now is that you now have more work to do when a change comes along that will effect the endpoints of your application. If the user demands that second address, then the PersonView, the PersonController, the PersonModel, the PersonService, the AddressRepository, the AddressAdapter and the Address and Person Table will need to be changed. Oh I wish we had only 2 layers again.
However, the moment that the Address needs to be formatted differently, depending on which view the user is using, you will thank yourself for having that PersonController there.
<h2>Conclusion</h2>
It is clear to me that, both types of maintenance changes occur and both need to be allowed for. Dismissing one type over the other is a mistake. Favouring less layers to account for the 50 columns you know the user is going to add is as foolish as over engineering a solution to protect oneself from imaginary gremlins.
Another point is that there are already so many layers in an application, and that can be seen from two perspectives: that one more layer wont hurt, or that one more will be the straw that breaks the camels back. Its up to you.
However, a pragmatist will employ rigorous application of <a href="http://en.wikipedia.org/wiki/YAGNI">YAGNI</a>. Don’t create more layers until you absolutely need them, but do not shy away from creating layers when change is on the horizon. <a href="http://www.codinghorror.com/blog/archives/000705.html">Leaving design decisions as late as possible</a> will ensure you learn to Say No to frivolous layers of abstraction. <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> (When Used Correctly™), <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">SRP</a> and <a href="http://en.wikipedia.org/wiki/Inversion_of_Control">IOC</a>, will guide the developer to produce code that will cope better with change without over engineering it. Oh, and you’ll be able to join the <a href="http://en.wikipedia.org/wiki/Three-letter_abbreviation">TLA</a> club too.]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>826830</wp:post_id>
<wp:post_date>2009-02-05 07:48:51</wp:post_date>
<wp:post_date_gmt>2009-02-04 22:18:51</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>software-changes</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="post_tag" nicename="architecture"><![CDATA[Architecture]]></category>
<category domain="post_tag" nicename="change-management"><![CDATA[Change management]]></category>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[826830]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[826830]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Languages are tools, use them.</title>
<link>https://maintenancecoder.wordpress.com/2008/10/17/languages-are-tools/</link>
<pubDate>Thu, 16 Oct 2008 19:08:15 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,ab0fa2bd-62eb-4f3d-ae1b-e004a0f0528b.aspx</guid>
<description/>
<content:encoded><![CDATA[While I think its great that I can use C# to express functional concepts, I also think that for anything more than the odd lambda expression, that I'm using the wrong tool for the job.
If large portions of your code begin with:<code><Expression<Func<T, R>></code> Then have a think about what it is you are trying to achieve. Sure, the usage may look fine, the fact remains that you're trying to express concepts at a level of abstraction that C style languages aren't equipped to cope with. Personally I think the well rounded coder would feel more comfortable writing an F# or Scala Library.
Why bang your head against C# to write DSL's when Boo will go out of its way to make it easy for you? Found yourself falling in love with AOP techniques and have consumed 3rd party libraries to get it done? Did you provide an interface layer to decouple that dependency? Why aren't we just naturally breaking out into IronRuby/Python here?
The only reason I use C# 3 to write unit tests these days is there isn't really a viable testing language created yet. A few years ago and beyond we had an excuse. Each language usually had its chosen platform and it didn't play well with others. Using Erlang made sense for telecommunication work, but it would be considered counter productive to write a windows GUI in that language. Similarly, you simply wouldn't bother using VB to write code for massively multithreaded environments.
Today, we have no excuse. The fact is that the Common Language Runtime provides us a mechanism to use the right language for the task at hand, and not only that, compile in a cross language solution, such that the net result is completely seamless to the untrained eye. The 'core strengths' that the average business application developer is available for <a href="http://en.wikipedia.org/wiki/List_of_CLI_Languages">any CLI language</a>.
Today, we are only restricted by those who refuse to learn new languages, when in fact, learning has never been simpler.]]></content:encoded>
<excerpt:encoded><![CDATA[While I think its great that I can use C# to express functional concepts, I also think that for anything more than the odd lambda expression, that I'm using the wrong tool for the job.]]></excerpt:encoded>
<wp:post_id>826831</wp:post_id>
<wp:post_date>2008-10-17 04:38:15</wp:post_date>
<wp:post_date_gmt>2008-10-16 19:08:15</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>languages-are-tools</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password/>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="net"><![CDATA[.NET]]></category>
<category domain="post_tag" nicename="clr"><![CDATA[CLR]]></category>
<category domain="post_tag" nicename="coding"><![CDATA[Coding]]></category>
<category domain="post_tag" nicename="languages"><![CDATA[Languages]]></category>
<category domain="category" nicename="software-development"><![CDATA[Software Development]]></category>
<category domain="post_tag" nicename="tools"><![CDATA[Tools]]></category>
<wp:postmeta>
<wp:meta_key>_publicize_pending</wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>original_post_id</wp:meta_key>
<wp:meta_value><![CDATA[826831]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key>_wp_old_slug</wp:meta_key>
<wp:meta_value><![CDATA[826831]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Seriously, Why Test First?</title>
<link>https://maintenancecoder.wordpress.com/2008/10/01/why-test-first/</link>
<pubDate>Tue, 30 Sep 2008 22:04:17 +0000</pubDate>
<dc:creator>Jim Burger</dc:creator>
<guid isPermaLink="false">/blog/PermaLink,guid,ac323066-814e-4ae8-a81f-02d25a4dc648.aspx</guid>
<description/>
<content:encoded><![CDATA[Is <a href="http://en.wikipedia.org/wiki/Test_Driven_Development">TDD</a> over the top? Surely I can write my tests 'alongside' my code?
Short answer: No.
Long answer:
To borrow Michael Feathers, author of <a href="http://www.objectmentor.com/resources/articles/WorkingEffectivelyWithLegacyCode.pdf">"Working effectively with Legacy Code"</a> the definition of legacy code is code without tests. By writing a function without a test first, you've just banged out a whole bunch of legacy code. It might not feel like it, but you could have just wasted your precious time.
OK, so lets pretend we have some of this legacy code in front of us. We begin writing some tests to cover it. What you'll find is that many programmers do one of a few things:
<ul>
<li>Coder A will write four or five tests for every method and generally not have to change their implementation much, if at all.</li>
<li>Coder B writes less tests overall, but in order to get it there they had to change their code due to recognising some unnecessary coupling or logic.</li>
</ul>
The next few examples are people who would have used TDD or no tests at all...
<ul>
<li>Coder C used TDD but strangely the end result looks like Coder A's code.</li>
<li>Coder D thinks unit testing is a waste of time, and has already deployed to production by now and is currently smugly sipping on Kool Aid.</li>
<li>Coder E only wrote a few tests, each test concerned with what the code should do, not what the code currently does, or how it goes about doing it.</li>
</ul>
Now that we have brutally put everybody in a box with rash generalizations and assumptions, lets come up with a way to throw a cat amongst the pigeons. Generally the best way to do this to a developer, is to ask them to add a new feature to their code.
<ul>
<li>Coder A when finished, finds that all the old tests wont even compile let alone pass because the new requirements severely altered the required architecture. Time is wasted rewriting all the tests to facilitate the new architectural requirements.</li>
<li>Coder B finds that only half of the old tests build or pass after implementing the new code. Because they removed some coupling it was easy enough to add, but they wasted time on some old tests that were obsolesced by the new architecture.</li>
<li>Coder C decides that the existing test suite isn't going to facilitate the new requirements. After they rewrite most of their tests they rewrite the code to satisfy them. Its like much Coder A's experience just in reverse.</li>
<li>Coder D deploys the new code to production or QA, only to find that the new changes stomped all over old functionality. What do you mean it 'doesn't work'? <em>That's impossible! </em>Time for a week long debugging session.</li>
<li>Coder E on the other hand writes one more test to the test suite and adds as little code as necessary to make it pass, then brutally refactors anything possible. None of the tests needed rewriting in the process. All user requirements are met and the project is delivered on time and on budget. If your lucky that is...</li>
</ul>
What some people fail to understand, is that using TDD doesn't prevent you from writing bad code. On the contrary, <strong>it can encourage you to over specify things</strong>.
When you over specify, you increase the places in your test suite that depend on how your implementation is structured. The very same thing happens when you write a function, and then a test or write tests 'alongside' your code. This is the mistake that Coder C makes, taking the bull by the tail, instead of the horns.
Coder E has no idea that he/she is in part practicing <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>. Its a natural progression from blindly banging out tests to cover every feasible outcome. Eventually you get a feel for tests that give you maximum 'bang for buck'. These tests provide maximum (quality) coverage for the least effort. In other words, we aren't bothering with a test per function. We are writing one test per <em>desired behaviour</em>. OK so every now and again, you head down the wrong track and tear up a few behavioural tests. Usually that's because you misunderstood the requirements, not how to code it, and that's where the value lies.
<strong>If you cant write a behavioural test, then you haven't understood the problem fully</strong>. If you don't understand the users problem, why are you coding?
That's why initially, its tempting to TDD blindly, you can ignore certain aspects of the users problem and just simply code until you think you got it right. Of course there are a few other aspects to BDD that I'm sure you're either aware of, or hopefully discover after reading this, but its important to remember: