<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Category Uncle Bob's Blatherings</title>
    <link>http://blog.objectmentor.com/articles/category/uncle-bobs-blatherings</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Clean Code.  Whew!</title>
      <description>&lt;p&gt;I&amp;#8217;ve been working on this book for several years now.  After a flurry of effort (you might have noticed I&amp;#8217;ve been quiet lately) I&amp;#8217;m very pleased to say that I&amp;#8217;m done with the writing and am preparing the manuscript for production. See &lt;a href="http://www.pearsonhighered.com/educator/academic/product/1,3110,0132350882,00.html"&gt;The Prentice Hall Listing&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://vig-fp.prenhall.com/bigcovers/0132350882.jpg" alt="" /&gt;&lt;/p&gt;


&lt;pre&gt;Table of Contents

Clean Code    1
    There Will Be Code    1
    Bad Code    2
    The Total Cost of Owning a Mess.    3
    Schools of Thought.    11
    We are Authors.    12
    The Boy Scout Rule    13
    Prequel and Principles    14
    Conclusion    14
    Bibliography    15
Meaningful Names by Tim Ottinger    17
    Introduction    17
    Use Intention-revealing Names    17
    Avoid Disinformation    19
    Make Meaningful Distinctions    20
    Use Pronounceable Names    21
    Use Searchable Names    22
    Avoid Encodings    23
    Avoid Mental Mapping    24
    Class Names    25
    Method Names    25
    Don't Be Cute    25
    Pick One Word Per Concept    26
    Don't Pun    26
    Use Solution Domain Names    27
    Use Problem Domain Names    27
    Add Meaningful Context    27
    Don't add Gratuitous Context    29
    Final Words ...    30
Functions    31
    Small!    34
    Do one thing.    35
    One level of abstraction per function.    36
    Switch Statements.    37
    Use descriptive names.    39
    Function Arguments.    39
    Have no side-effects.    43
    Command Query Separation    44
    Prefer exceptions to returning error codes.    45
    Don't Repeat Yourself.    47
    Structured Programming    48
    How do you write functions like this?    48
    Conclusion    49
    SetupTeardownIncluder    49
    Bibliography    52
Comments    53
    Comments do not make up for bad code.    55
    Explain yourself in code.    55
    Good Comments    55
    Bad Comments    59
    Example    71
    Bibliography    74
Formatting    75
    The Purpose of Formatting    76
    Vertical Formatting    76
    Horizontal Formatting    84
    Team Rules    89
    Uncle Bob's Formatting Rules.    90
Objects and Data Structures    93
    Data Abstraction    93
    Data/Object anti-symmetry.    95
    The Law of Demeter    97
    Data Transfer Objects    99
    Conclusion    101
    Bibliography    101
Error Handling by Michael Feathers    103
    Use Exceptions Rather than Return Codes    103
    Write Your Try-Catch-Finally Statement First    105
    Use Unchecked Exceptions    106
    Provide Context with Exceptions    107
    Define Exception Classes In Terms of a Caller's Needs.    107
    Define the Normal Flow    109
    Don't Return Null    110
    Don't Pass Null    111
    Conclusion    112
    Bibliography    112
Boundaries by James Grenning    113
    Bibliography    119
Unit Tests    121
    The Three Laws of TDD    122
    Keeping Tests Clean    123
    Clean Tests    124
    One Assert per Test    129
    F.I.R.S.T.    132
    Conclusion    132
    Bibliography    133
Classes    135
    Class Organization    135
    Classes should be Small!    136
    Organizing for Change    146
    Bibliography    150
Systems    By Dean Wampler 151
    How would you build a city?    151
    Separate constructing a system from using it    152
    Scaling Up    155
    Java Proxies    158
    Pure Java AOP Frameworks    160
    AspectJ Aspects    163
    Test-drive the system architecture    164
    Optimize decision making    165
    Use standards wisely, when they add demonstrable value    165
    Systems need Domain-Specific Languages    166
    Conclusion    166
    Bibliography    167
Emergence By Jeff Langr    169
    Getting Clean via Emergent Design    169
    Simple Design Rule 1: Runs all the tests    170
    Simple Design Rules 2-4: Refactoring    170
    No Duplication    170
    Expressive    173
    Minimal Classes and Methods    174
    Conclusion    174
    Bibliography    174
Concurrency    by Brett Schuchert 175
    Why Concurrency?    176
    Challenges    177
    Concurrency Defense Principles    178
    Know Your Library    180
    Know Your Execution Models    181
    Beware Dependencies between Syncrhonized Methods    182
    Keep Synchronized Sections Small    183
    Writing Correct Shut-Down Code is Hard    183
    Testing Threaded Code    184
    Conclusion    188
    Bibliography    189
Successive Refinement    191
    Args Implementation    192
    Args: the rough draft.    198
    String Arguments    212
     Conclusion    246
JUnit Internals    249
    Conclusion    262
Refactoring SerialDate    263
    Conclusion    280
    Bibliography    281
Smells and Heuristics    283
    Comments    283
    Environment    284
    Functions    285
    General    285
    Java    304
    Names    306
    Tests    310
    Conclusion    311
    Bibliography    312
Concurrency II    by Brett Schuchert 313
    Client/Server Example    313
    Possible Paths of Execution    317
    Knowing Your Library    322
    Dependencies between methods can break concurrent code    325
    Increasing Throughput    329
    Deadlock    331
    Testing Multi-Threaded Code    335
    Tool Support for Testing Thread-Based Code    337
    Conclusion    338
    Tutorial: Full Code Examples    339
org.jfree.date.SerialDate    345
Cross References of Heuristics    406
&lt;/pre&gt;</description>
      <pubDate>Tue, 08 Apr 2008 00:10:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0280362f-4830-42b9-84db-edaa724b41b1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/04/08/clean-code-whew</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Clean Code.  Whew!</title>
      <description>&lt;p&gt;I&amp;#8217;ve been working on this book for several years now.  After a flurry of effort (you might have noticed I&amp;#8217;ve been quiet lately) I&amp;#8217;m very pleased to say that I&amp;#8217;m done with the writing and am preparing the manuscript for production. See &lt;a href="http://www.pearsonhighered.com/educator/academic/product/1,3110,0132350882,00.html"&gt;The Prentice Hall Listing&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://vig-fp.prenhall.com/bigcovers/0132350882.jpg" alt="" /&gt;&lt;/p&gt;


&lt;pre&gt;Table of Contents

Clean Code    1
    There Will Be Code    1
    Bad Code    2
    The Total Cost of Owning a Mess.    3
    Schools of Thought.    11
    We are Authors.    12
    The Boy Scout Rule    13
    Prequel and Principles    14
    Conclusion    14
    Bibliography    15
Meaningful Names by Tim Ottinger    17
    Introduction    17
    Use Intention-revealing Names    17
    Avoid Disinformation    19
    Make Meaningful Distinctions    20
    Use Pronounceable Names    21
    Use Searchable Names    22
    Avoid Encodings    23
    Avoid Mental Mapping    24
    Class Names    25
    Method Names    25
    Don't Be Cute    25
    Pick One Word Per Concept    26
    Don't Pun    26
    Use Solution Domain Names    27
    Use Problem Domain Names    27
    Add Meaningful Context    27
    Don't add Gratuitous Context    29
    Final Words ...    30
Functions    31
    Small!    34
    Do one thing.    35
    One level of abstraction per function.    36
    Switch Statements.    37
    Use descriptive names.    39
    Function Arguments.    39
    Have no side-effects.    43
    Command Query Separation    44
    Prefer exceptions to returning error codes.    45
    Don't Repeat Yourself.    47
    Structured Programming    48
    How do you write functions like this?    48
    Conclusion    49
    SetupTeardownIncluder    49
    Bibliography    52
Comments    53
    Comments do not make up for bad code.    55
    Explain yourself in code.    55
    Good Comments    55
    Bad Comments    59
    Example    71
    Bibliography    74
Formatting    75
    The Purpose of Formatting    76
    Vertical Formatting    76
    Horizontal Formatting    84
    Team Rules    89
    Uncle Bob's Formatting Rules.    90
Objects and Data Structures    93
    Data Abstraction    93
    Data/Object anti-symmetry.    95
    The Law of Demeter    97
    Data Transfer Objects    99
    Conclusion    101
    Bibliography    101
Error Handling by Michael Feathers    103
    Use Exceptions Rather than Return Codes    103
    Write Your Try-Catch-Finally Statement First    105
    Use Unchecked Exceptions    106
    Provide Context with Exceptions    107
    Define Exception Classes In Terms of a Caller's Needs.    107
    Define the Normal Flow    109
    Don't Return Null    110
    Don't Pass Null    111
    Conclusion    112
    Bibliography    112
Boundaries by James Grenning    113
    Bibliography    119
Unit Tests    121
    The Three Laws of TDD    122
    Keeping Tests Clean    123
    Clean Tests    124
    One Assert per Test    129
    F.I.R.S.T.    132
    Conclusion    132
    Bibliography    133
Classes    135
    Class Organization    135
    Classes should be Small!    136
    Organizing for Change    146
    Bibliography    150
Systems    By Dean Wampler 151
    How would you build a city?    151
    Separate constructing a system from using it    152
    Scaling Up    155
    Java Proxies    158
    Pure Java AOP Frameworks    160
    AspectJ Aspects    163
    Test-drive the system architecture    164
    Optimize decision making    165
    Use standards wisely, when they add demonstrable value    165
    Systems need Domain-Specific Languages    166
    Conclusion    166
    Bibliography    167
Emergence By Jeff Langr    169
    Getting Clean via Emergent Design    169
    Simple Design Rule 1: Runs all the tests    170
    Simple Design Rules 2-4: Refactoring    170
    No Duplication    170
    Expressive    173
    Minimal Classes and Methods    174
    Conclusion    174
    Bibliography    174
Concurrency    by Brett Schuchert 175
    Why Concurrency?    176
    Challenges    177
    Concurrency Defense Principles    178
    Know Your Library    180
    Know Your Execution Models    181
    Beware Dependencies between Syncrhonized Methods    182
    Keep Synchronized Sections Small    183
    Writing Correct Shut-Down Code is Hard    183
    Testing Threaded Code    184
    Conclusion    188
    Bibliography    189
Successive Refinement    191
    Args Implementation    192
    Args: the rough draft.    198
    String Arguments    212
     Conclusion    246
JUnit Internals    249
    Conclusion    262
Refactoring SerialDate    263
    Conclusion    280
    Bibliography    281
Smells and Heuristics    283
    Comments    283
    Environment    284
    Functions    285
    General    285
    Java    304
    Names    306
    Tests    310
    Conclusion    311
    Bibliography    312
Concurrency II    by Brett Schuchert 313
    Client/Server Example    313
    Possible Paths of Execution    317
    Knowing Your Library    322
    Dependencies between methods can break concurrent code    325
    Increasing Throughput    329
    Deadlock    331
    Testing Multi-Threaded Code    335
    Tool Support for Testing Thread-Based Code    337
    Conclusion    338
    Tutorial: Full Code Examples    339
org.jfree.date.SerialDate    345
Cross References of Heuristics    406
&lt;/pre&gt;</description>
      <pubDate>Tue, 08 Apr 2008 00:10:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0280362f-4830-42b9-84db-edaa724b41b1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/04/08/clean-code-whew</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Clean Code.  Whew!</title>
      <description>&lt;p&gt;I&amp;#8217;ve been working on this book for several years now.  After a flurry of effort (you might have noticed I&amp;#8217;ve been quiet lately) I&amp;#8217;m very pleased to say that I&amp;#8217;m done with the writing and am preparing the manuscript for production. See &lt;a href="http://www.pearsonhighered.com/educator/academic/product/1,3110,0132350882,00.html"&gt;The Prentice Hall Listing&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://vig-fp.prenhall.com/bigcovers/0132350882.jpg" alt="" /&gt;&lt;/p&gt;


&lt;pre&gt;Table of Contents

Clean Code    1
    There Will Be Code    1
    Bad Code    2
    The Total Cost of Owning a Mess.    3
    Schools of Thought.    11
    We are Authors.    12
    The Boy Scout Rule    13
    Prequel and Principles    14
    Conclusion    14
    Bibliography    15
Meaningful Names by Tim Ottinger    17
    Introduction    17
    Use Intention-revealing Names    17
    Avoid Disinformation    19
    Make Meaningful Distinctions    20
    Use Pronounceable Names    21
    Use Searchable Names    22
    Avoid Encodings    23
    Avoid Mental Mapping    24
    Class Names    25
    Method Names    25
    Don't Be Cute    25
    Pick One Word Per Concept    26
    Don't Pun    26
    Use Solution Domain Names    27
    Use Problem Domain Names    27
    Add Meaningful Context    27
    Don't add Gratuitous Context    29
    Final Words ...    30
Functions    31
    Small!    34
    Do one thing.    35
    One level of abstraction per function.    36
    Switch Statements.    37
    Use descriptive names.    39
    Function Arguments.    39
    Have no side-effects.    43
    Command Query Separation    44
    Prefer exceptions to returning error codes.    45
    Don't Repeat Yourself.    47
    Structured Programming    48
    How do you write functions like this?    48
    Conclusion    49
    SetupTeardownIncluder    49
    Bibliography    52
Comments    53
    Comments do not make up for bad code.    55
    Explain yourself in code.    55
    Good Comments    55
    Bad Comments    59
    Example    71
    Bibliography    74
Formatting    75
    The Purpose of Formatting    76
    Vertical Formatting    76
    Horizontal Formatting    84
    Team Rules    89
    Uncle Bob's Formatting Rules.    90
Objects and Data Structures    93
    Data Abstraction    93
    Data/Object anti-symmetry.    95
    The Law of Demeter    97
    Data Transfer Objects    99
    Conclusion    101
    Bibliography    101
Error Handling by Michael Feathers    103
    Use Exceptions Rather than Return Codes    103
    Write Your Try-Catch-Finally Statement First    105
    Use Unchecked Exceptions    106
    Provide Context with Exceptions    107
    Define Exception Classes In Terms of a Caller's Needs.    107
    Define the Normal Flow    109
    Don't Return Null    110
    Don't Pass Null    111
    Conclusion    112
    Bibliography    112
Boundaries by James Grenning    113
    Bibliography    119
Unit Tests    121
    The Three Laws of TDD    122
    Keeping Tests Clean    123
    Clean Tests    124
    One Assert per Test    129
    F.I.R.S.T.    132
    Conclusion    132
    Bibliography    133
Classes    135
    Class Organization    135
    Classes should be Small!    136
    Organizing for Change    146
    Bibliography    150
Systems    By Dean Wampler 151
    How would you build a city?    151
    Separate constructing a system from using it    152
    Scaling Up    155
    Java Proxies    158
    Pure Java AOP Frameworks    160
    AspectJ Aspects    163
    Test-drive the system architecture    164
    Optimize decision making    165
    Use standards wisely, when they add demonstrable value    165
    Systems need Domain-Specific Languages    166
    Conclusion    166
    Bibliography    167
Emergence By Jeff Langr    169
    Getting Clean via Emergent Design    169
    Simple Design Rule 1: Runs all the tests    170
    Simple Design Rules 2-4: Refactoring    170
    No Duplication    170
    Expressive    173
    Minimal Classes and Methods    174
    Conclusion    174
    Bibliography    174
Concurrency    by Brett Schuchert 175
    Why Concurrency?    176
    Challenges    177
    Concurrency Defense Principles    178
    Know Your Library    180
    Know Your Execution Models    181
    Beware Dependencies between Syncrhonized Methods    182
    Keep Synchronized Sections Small    183
    Writing Correct Shut-Down Code is Hard    183
    Testing Threaded Code    184
    Conclusion    188
    Bibliography    189
Successive Refinement    191
    Args Implementation    192
    Args: the rough draft.    198
    String Arguments    212
     Conclusion    246
JUnit Internals    249
    Conclusion    262
Refactoring SerialDate    263
    Conclusion    280
    Bibliography    281
Smells and Heuristics    283
    Comments    283
    Environment    284
    Functions    285
    General    285
    Java    304
    Names    306
    Tests    310
    Conclusion    311
    Bibliography    312
Concurrency II    by Brett Schuchert 313
    Client/Server Example    313
    Possible Paths of Execution    317
    Knowing Your Library    322
    Dependencies between methods can break concurrent code    325
    Increasing Throughput    329
    Deadlock    331
    Testing Multi-Threaded Code    335
    Tool Support for Testing Thread-Based Code    337
    Conclusion    338
    Tutorial: Full Code Examples    339
org.jfree.date.SerialDate    345
Cross References of Heuristics    406
&lt;/pre&gt;</description>
      <pubDate>Tue, 08 Apr 2008 00:10:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0280362f-4830-42b9-84db-edaa724b41b1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/04/08/clean-code-whew</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Clean Code.  Whew!</title>
      <description>&lt;p&gt;I&amp;#8217;ve been working on this book for several years now.  After a flurry of effort (you might have noticed I&amp;#8217;ve been quiet lately) I&amp;#8217;m very pleased to say that I&amp;#8217;m done with the writing and am preparing the manuscript for production. See &lt;a href="http://www.pearsonhighered.com/educator/academic/product/1,3110,0132350882,00.html"&gt;The Prentice Hall Listing&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://vig-fp.prenhall.com/bigcovers/0132350882.jpg" alt="" /&gt;&lt;/p&gt;


&lt;pre&gt;Table of Contents

Clean Code    1
    There Will Be Code    1
    Bad Code    2
    The Total Cost of Owning a Mess.    3
    Schools of Thought.    11
    We are Authors.    12
    The Boy Scout Rule    13
    Prequel and Principles    14
    Conclusion    14
    Bibliography    15
Meaningful Names by Tim Ottinger    17
    Introduction    17
    Use Intention-revealing Names    17
    Avoid Disinformation    19
    Make Meaningful Distinctions    20
    Use Pronounceable Names    21
    Use Searchable Names    22
    Avoid Encodings    23
    Avoid Mental Mapping    24
    Class Names    25
    Method Names    25
    Don't Be Cute    25
    Pick One Word Per Concept    26
    Don't Pun    26
    Use Solution Domain Names    27
    Use Problem Domain Names    27
    Add Meaningful Context    27
    Don't add Gratuitous Context    29
    Final Words ...    30
Functions    31
    Small!    34
    Do one thing.    35
    One level of abstraction per function.    36
    Switch Statements.    37
    Use descriptive names.    39
    Function Arguments.    39
    Have no side-effects.    43
    Command Query Separation    44
    Prefer exceptions to returning error codes.    45
    Don't Repeat Yourself.    47
    Structured Programming    48
    How do you write functions like this?    48
    Conclusion    49
    SetupTeardownIncluder    49
    Bibliography    52
Comments    53
    Comments do not make up for bad code.    55
    Explain yourself in code.    55
    Good Comments    55
    Bad Comments    59
    Example    71
    Bibliography    74
Formatting    75
    The Purpose of Formatting    76
    Vertical Formatting    76
    Horizontal Formatting    84
    Team Rules    89
    Uncle Bob's Formatting Rules.    90
Objects and Data Structures    93
    Data Abstraction    93
    Data/Object anti-symmetry.    95
    The Law of Demeter    97
    Data Transfer Objects    99
    Conclusion    101
    Bibliography    101
Error Handling by Michael Feathers    103
    Use Exceptions Rather than Return Codes    103
    Write Your Try-Catch-Finally Statement First    105
    Use Unchecked Exceptions    106
    Provide Context with Exceptions    107
    Define Exception Classes In Terms of a Caller's Needs.    107
    Define the Normal Flow    109
    Don't Return Null    110
    Don't Pass Null    111
    Conclusion    112
    Bibliography    112
Boundaries by James Grenning    113
    Bibliography    119
Unit Tests    121
    The Three Laws of TDD    122
    Keeping Tests Clean    123
    Clean Tests    124
    One Assert per Test    129
    F.I.R.S.T.    132
    Conclusion    132
    Bibliography    133
Classes    135
    Class Organization    135
    Classes should be Small!    136
    Organizing for Change    146
    Bibliography    150
Systems    By Dean Wampler 151
    How would you build a city?    151
    Separate constructing a system from using it    152
    Scaling Up    155
    Java Proxies    158
    Pure Java AOP Frameworks    160
    AspectJ Aspects    163
    Test-drive the system architecture    164
    Optimize decision making    165
    Use standards wisely, when they add demonstrable value    165
    Systems need Domain-Specific Languages    166
    Conclusion    166
    Bibliography    167
Emergence By Jeff Langr    169
    Getting Clean via Emergent Design    169
    Simple Design Rule 1: Runs all the tests    170
    Simple Design Rules 2-4: Refactoring    170
    No Duplication    170
    Expressive    173
    Minimal Classes and Methods    174
    Conclusion    174
    Bibliography    174
Concurrency    by Brett Schuchert 175
    Why Concurrency?    176
    Challenges    177
    Concurrency Defense Principles    178
    Know Your Library    180
    Know Your Execution Models    181
    Beware Dependencies between Syncrhonized Methods    182
    Keep Synchronized Sections Small    183
    Writing Correct Shut-Down Code is Hard    183
    Testing Threaded Code    184
    Conclusion    188
    Bibliography    189
Successive Refinement    191
    Args Implementation    192
    Args: the rough draft.    198
    String Arguments    212
     Conclusion    246
JUnit Internals    249
    Conclusion    262
Refactoring SerialDate    263
    Conclusion    280
    Bibliography    281
Smells and Heuristics    283
    Comments    283
    Environment    284
    Functions    285
    General    285
    Java    304
    Names    306
    Tests    310
    Conclusion    311
    Bibliography    312
Concurrency II    by Brett Schuchert 313
    Client/Server Example    313
    Possible Paths of Execution    317
    Knowing Your Library    322
    Dependencies between methods can break concurrent code    325
    Increasing Throughput    329
    Deadlock    331
    Testing Multi-Threaded Code    335
    Tool Support for Testing Thread-Based Code    337
    Conclusion    338
    Tutorial: Full Code Examples    339
org.jfree.date.SerialDate    345
Cross References of Heuristics    406
&lt;/pre&gt;</description>
      <pubDate>Tue, 08 Apr 2008 00:10:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0280362f-4830-42b9-84db-edaa724b41b1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/04/08/clean-code-whew</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>The Quality of TDD</title>
      <description>&lt;p&gt;Kieth Braithwaite has made an interesting observation &lt;a href="http://peripateticaxiom.blogspot.com/2006/05/complexity-and-test-first-0.html"&gt;here.&lt;/a&gt;  The basic idea is that code that has been written with &lt;span class="caps"&gt;TDD&lt;/span&gt; has a lower Cyclomatic Complexity per function compared to code that has not been written with &lt;span class="caps"&gt;TDD&lt;/span&gt;.  If this is true then it could imply lower defects because of &lt;a href="http://www.enerjy.com/blog/?p=241"&gt;this.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Kieth&amp;#8217;s metric takes in the code for an entire project and boils it down to a single number.  His hypothesis is that a system written with &lt;span class="caps"&gt;TDD&lt;/span&gt; will always measure above a certain threshold, indicating very low CC; whereas systems written without &lt;span class="caps"&gt;TDD&lt;/span&gt; may or may not measure above that threshold.&lt;/p&gt;


	&lt;p&gt;Kieth has built a tool that you can get &lt;a href="http://www.keithbraithwaite.demon.co.uk/professional/software/measure/measure0.1.zip"&gt;here&lt;/a&gt; that will generate this metric for most java projects.  He and others have used this tool to measure many different systems.  So far the hypothesis seems to hold water.&lt;/p&gt;


	&lt;p&gt;The metric can&amp;#8217;t tell you if &lt;span class="caps"&gt;TDD&lt;/span&gt; was used; but it might just be able to tell you that it &lt;em&gt;wasn&amp;#8217;t used&lt;/em&gt;.&lt;/p&gt;</description>
      <pubDate>Sat, 16 Feb 2008 20:23:44 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:f69b083c-7868-4d59-84e6-b9185d82f7b8</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/02/16/the-quality-of-tdd</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>Generated Tests and TDD</title>
      <description>&lt;p&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt; has become quite popular, and many companies are attempting to adopt it.  However, some folks worry that it takes a long time to write all those unit tests and are looking to test-generation tools as a way to decrease that burden.&lt;/p&gt;


	&lt;p&gt;The burden is not insignificant.  FitNesse, an application created using &lt;span class="caps"&gt;TDD&lt;/span&gt;, is comprised of 45,000 lines of Java code, 15,000 of which are unit tests.  Simple math suggests that &lt;span class="caps"&gt;TDD&lt;/span&gt; increases the coding burden by a full third!&lt;/p&gt;


	&lt;p&gt;Of course this is a naive analysis.  The &lt;em&gt;benefits&lt;/em&gt; of using &lt;span class="caps"&gt;TDD&lt;/span&gt; are significant, and far outweigh the burden of writing the extra code.  But that 33% still feels &amp;#8220;extra&amp;#8221; and tempts people to find ways to shrink it without losing any of the benefits.&lt;/p&gt;


	&lt;h1&gt;Test Generators.&lt;/h1&gt;


	&lt;p&gt;Some folks have put their hope in tools that automatically generate tests by inspecting code.  These tools are very clever.  They generate random calls to methods and remember the results.  They can automatically build mocks and stubs to break the dependencies between modules.  They use remarkably clever algorithms to choose their random test data.  They even provide ways for programmers to write plugins that adjust those algorithms to be a better fit for their applications.&lt;/p&gt;


	&lt;p&gt;The end result of running such a tool is a set of &lt;em&gt;observations&lt;/em&gt;.  The tool observes how the instance variables of a class change when calls are made to its methods with certain arguments.  It notes the return values, changes to instance variables, and outgoing calls to stubs and mocks.  And it presents these observations to the user.&lt;/p&gt;


	&lt;p&gt;The user must look through these observations and determine which are correct, which are irrelevant, and which are bugs.  Once the bugs are fixed, these observations can be checked over and over again by re-running the tests.  This is very similar to the record-playback model used by &lt;span class="caps"&gt;GUI&lt;/span&gt; testers.  Once you have registered all the correct observations, you can play the tests back and make sure those observations are still being observed.&lt;/p&gt;


	&lt;p&gt;Some of the tools will even write the observations as JUnit tests, so that you can run them as a standard test suite.  Just like &lt;span class="caps"&gt;TDD&lt;/span&gt;, right?  Well, not so fast&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Make no mistake, tools like this can be very useful.  If you have a wad of untested legacy code, then generating a suite of JUnit tests that verifies some portion of the behavior of that code can be a great boon!&lt;/p&gt;


	&lt;h2&gt;The Periphery Problem&lt;/h2&gt;


On the other hand, no matter how clever the test generator is, the tests it generates will always be more naive than the tests that a human can write.  As a simple example of this, I have tried to generate tests for the bowling game program using two of the better known test generation tools.  The interface to the Bowling Game looks like this:
&lt;code&gt;&lt;pre&gt;
  public class BowlingGame {
    public void roll(int pins) {...}
    public int score() {...}
  }
&lt;/pre&gt;&lt;/code&gt;
The idea is that you call roll each time the balls gets rolled, and you call score at the end of the game to get the score for that game.  

	&lt;p&gt;The test generators could not randomly generate valid games.  It&amp;#8217;s not hard to see why.  A valid game is a sequence of between 12 and 21 rolls, all of which must be integers between 0 and 10.  What&amp;#8217;s more, within a given frame, the sum of rolls cannot exceed 10.  These constraints are just too tight for a random generator to achieve within the current age of the universe.&lt;/p&gt;


	&lt;p&gt;I could have written a plugin that guided the generator to create valid games; but such an algorithm would embody much of the logic of the BowlingGame itself, so it&amp;#8217;s not clear that the economics are advantageous.&lt;/p&gt;


	&lt;p&gt;To generalize this, the test generators have trouble getting &lt;em&gt;inside&lt;/em&gt; algorithms that have any kind of protocol, calling sequence, or state semantics.  They can generate tests around the &lt;em&gt;periphery&lt;/em&gt; of the classes; but can&amp;#8217;t get into the guts without help.&lt;/p&gt;


	&lt;h2&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt;?&lt;/h2&gt;


	&lt;p&gt;The real question is whether or not such generated tests help you with Test Driven Development.  &lt;span class="caps"&gt;TDD&lt;/span&gt; is the act of using tests as a way to drive the development of the system.  You write unit test code first, and then you write the application code that makes that code pass.  Clearly generating tests from existing code violates that simple rule.  So in some philosophical sense, using test generators is &lt;em&gt;not&lt;/em&gt; TDD.  But who cares so long as the tests get written, right?  Well, hang on&amp;#8230;&lt;/p&gt;


	&lt;p&gt;One of the reasons that &lt;span class="caps"&gt;TDD&lt;/span&gt; works so well is that it is similar to the accounting practice of dual entry bookkeeping.  Accountants make every entry twice; once on the credit side, and once on the debit side.  These two entries follow separate mathematical pathways. In the end a magical subtraction yields a zero if all the entries were made correctly.&lt;/p&gt;


	&lt;p&gt;In &lt;span class="caps"&gt;TDD&lt;/span&gt;, programmers state their intent twice; once in the test code, and again in the production code.  These two statements of &lt;em&gt;intent&lt;/em&gt; verify each other.  The tests, test the intent of the code, and the code tests the intent of the tests.  This works because it is a &lt;em&gt;human&lt;/em&gt; that makes both entries!  The human must state the intent twice, but in two complementary forms.  This vastly reduces many kinds of errors; as well as providing significant insight into improved design.&lt;/p&gt;


	&lt;p&gt;Using a test generator breaks this concept because the generator writes the test using the production code as input.  The generated test is not a human restatement, it is an automatic translation.  The human states intent only once, and therefore does not gain insights from restatement, nor does the generated test check that the &lt;em&gt;intent&lt;/em&gt; of the code was achieved.  It is true that the human must verify the observations, but compared to &lt;span class="caps"&gt;TDD&lt;/span&gt; that is a far more passive action, providing far less insight into defects, design and intent.&lt;/p&gt;


	&lt;p&gt;I conclude from this that automated test generation is neither equivalent to &lt;span class="caps"&gt;TDD&lt;/span&gt;, nor is it a way to make &lt;span class="caps"&gt;TDD&lt;/span&gt; more efficient.  What you gain by trying to generate the 33% test code, you lose in defect elimination, restatement of intent, and design insight. You also sacrifice depth of test coverage, because of the periphery problem.&lt;/p&gt;


	&lt;p&gt;This does not mean that test generators aren&amp;#8217;t useful.  As I said earlier, I think they can help to partially characterize a large base of legacy code.  But these tools are not &lt;span class="caps"&gt;TDD&lt;/span&gt; tools. The tests they generate are not equivalent to tests written using &lt;span class="caps"&gt;TDD&lt;/span&gt;.  And many of the benefits of &lt;span class="caps"&gt;TDD&lt;/span&gt; are not achieved through test generation.&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jan 2008 13:59:30 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:8528afa6-7e1b-406d-ab72-18557ff0912c</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/01/10/generated-tests-and-tdd</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>Business software is Messy and Ugly.</title>
      <description>&lt;p&gt;I was at a client recently.  They are a successful startup who have gone through a huge growth spurt.  Their software grew rapidly, through a significant hack-and-slash program.  Now they have a mess, and it is slowing them way down.  Defects are high.  Unintended consequences of change are high.  Productivity is low.&lt;/p&gt;


	&lt;p&gt;I spent two days advising them how to adopt &lt;span class="caps"&gt;TDD&lt;/span&gt; and Clean Code techniques to improve their code-base and their situation.  We discussed strategies for gradual clean up, and the notion that big refactoring projects and big redesign projects have a high risk of failure.  We talked about ways to clean things up over time, while incrementally insinuating tests into the existing code base.&lt;/p&gt;


	&lt;p&gt;During the sessions they told me of a software manager who is famed for having said:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;There&amp;#8217;s a clean way to do this, and a quick-and-dirty way to do this.  I want you to do it the quick-and-dirty way.&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The attitude engendered by this statement has spread throughout the company and has become a significant part of their culture.  If hack-and-slash is what management wants, then that&amp;#8217;s what they get!  I spent a long time with these folks countering that attitude and trying to engender an attitude of craftsmanship and professionalism.&lt;/p&gt;


	&lt;p&gt;The developers responded to my message with enthusiasm.  They &lt;em&gt;want&lt;/em&gt; to do a good job (of course!)  They just didn&amp;#8217;t know they were authorized to do good work.  They thought they had to make messes.  But I told them that the only way to get things done quickly, and keep getting things done quickly, is to create the cleanest code they can, to work as well as possible, and keep the quality very high.  I told them that quick-and-dirty is an oxymoron.  Dirty &lt;em&gt;always&lt;/em&gt; means slow.&lt;/p&gt;


	&lt;p&gt;On the last day of my visit the infamous manager (now the &lt;span class="caps"&gt;CTO&lt;/span&gt;) stopped into our conference room.  We talked over the issues.  He was constantly trying to find a quick way out.  He was manipulative and cajoling.  &amp;#8220;What if we did this?&amp;#8221; or &amp;#8220;What if we did that?&amp;#8221;  He&amp;#8217;d set up straw man after straw man, trying to convince his folks that there was a &lt;em&gt;time and place&lt;/em&gt; for good code, but this was not it.&lt;/p&gt;


	&lt;p&gt;I wanted to hit him.&lt;/p&gt;


	&lt;p&gt;Then he made the dumbest, most profoundly irresponsible statement I&amp;#8217;ve (all too often) heard come out of a CTOs mouth.  He said:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;Business software is messy and ugly.&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;em&gt;No, it&amp;#8217;s not!&lt;/em&gt;  The rules can be complicated, arbitrary, and ad-hoc; but the code does not need to be messy and ugly.  Indeed, the more arbitrary, complex, and ad-hoc the business rules are, the cleaner the code needs to be.  You cannot manage the mess of the rules if they are contained by another mess! The only way to get a handle on the messy rules is to express them in the cleanest and clearest code you can.&lt;/p&gt;


	&lt;p&gt;In the end, he backed down.  At least while I was there. But I have no doubt he&amp;#8217;ll continue his manipulations.  I hope the developers have the will to resist.&lt;/p&gt;


	&lt;p&gt;One of the developers asked the question point blank: &amp;#8220;What do you do when your managers tell you to make a mess?&amp;#8221;  I responded: &amp;#8220;You don&amp;#8217;t take it.  Behave like a doctor who&amp;#8217;s hospital administrator has just told him that hand-washing is too expensive, and he should stop doing it.&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Thu, 13 Dec 2007 09:41:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:3184c0e9-cf3c-48f1-a801-cc8ed8720ab9</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/12/13/business-software-is-messy-and-mgly</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Thinking about an Appendix.</title>
      <description>&lt;p&gt;No, not of Clean Code (look for it in Spring).  This monday evening (12/3) I got a stomach ache.&lt;/p&gt;


	&lt;p&gt;The stomach pain was a low level annoyance that I was able to ignore for most of the evening.  But it started to get pretty bad round midnight.  By 2AM I threw up and then felt better.  So I went back to bed and slept till morning.&lt;/p&gt;


	&lt;p&gt;Tuesday started well.  I had some residual pain, but figured it was waning.  I went to the office to get some work done there.  By the time I got there the waning pain had waxed and I turned right around and went home to bed.&lt;/p&gt;


	&lt;p&gt;The pain continued to grow until 3PM when I thew up again.  This made me feel a little better so I went back to bed.  But by 6PM the pain had localized to my lower right quadrant and I had had enough.  I asked my wife to take me to the immediate care facility.&lt;/p&gt;


	&lt;p&gt;They could tell by the grimace on my face that this was something to take care of quickly.  They put me on a bed, and started an IV.  They took blood and did an exam.  Then they packed me into an ambulance and sent me to the ER for a &lt;span class="caps"&gt;CAT&lt;/span&gt; scan.&lt;/p&gt;


	&lt;p&gt;During the 20 minute ride the pain was getting really bad.  I was giving it 8.5 on a scale of 1-10.  I have intimate knowledge of every pothole on the road the took.&lt;/p&gt;


	&lt;p&gt;At the ER they put me in a room and gave me a dose of Morphine.  Morphine is a very nice drug.  It had the effect of filing the pain away in a convenient subdirectory where I could access it if I needed it, but was otherwise out of the way.&lt;/p&gt;


	&lt;p&gt;By 11PM the &lt;span class="caps"&gt;CAT&lt;/span&gt; scan was complete and the doctor came and said: &amp;#8220;The good news is we know what&amp;#8217;s wrong.  The bad news is it&amp;#8217;s your appendix.  We just happen to have an OR ready.  Do you want to do it now?&amp;#8221;  How could I refuse an offer like that!&lt;/p&gt;


The rolled me into the OR and told me they were going to give me the juice. 
&lt;hr/&gt;
&lt;em&gt;&lt;span class="caps"&gt;DISCONTINUITY&lt;/span&gt;&lt;/em&gt;
&lt;hr/&gt;
I was in the recovery room with two smiling pretty nurses urging me to awaken to the news that my appendix had been removed.
&lt;hr/&gt;
&lt;em&gt;&lt;span class="caps"&gt;DISCONTINUITY&lt;/span&gt;&lt;/em&gt;
&lt;hr/&gt;
I was being wheeled into a hospital room. It was 3AM.  My exhausted wife was waiting for me there.  She kissed me goodbye and I went to sleep.

	&lt;p&gt;Wednesday was my birthday.  I spent is sleeping for the most part.  They fed me clear foods.  The pain was not horrible, but I did accept a vicodin around noon.  By 4PM the surgeon came in, looked me over, and said:  &amp;#8220;You look pretty good.  You should go home.&amp;#8221;  I went home gladly. On the way home my wife and I picked up a pizza.&lt;/p&gt;


	&lt;p&gt;Thursday was a bit sore, but not bad.  I took a couple of motrin and was &amp;#8220;smart&amp;#8221; about what muscles I used and when.  I got a lot of work-reading done.&lt;/p&gt;


	&lt;p&gt;Today I woke up and the incision pain was like a mild sunburn.  I can feel it, but I can ignore it.  I&amp;#8217;m not about to do 20 pushups, or run a marathon, but the day should be relatively normal.&lt;/p&gt;</description>
      <pubDate>Fri, 07 Dec 2007 09:27:04 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:ef5fd175-ebac-485c-94e2-6dea2e054118</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/12/07/thinking-about-an-appendix</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Active Record vs Objects</title>
      <description>&lt;p&gt;Active Record is a well known data persistence pattern.  It has been adopted by Rails, Hibernate, and many other &lt;span class="caps"&gt;ORM&lt;/span&gt; tools.  It has proven it&amp;#8217;s usefulness over and over again.  And yet I have a philosophical problem with it.&lt;/p&gt;


The Active Record pattern is a way to map database rows to objects.  For example, let&amp;#8217;s say we have an Employee object with name and address fields:
&lt;pre&gt;&lt;code&gt;public class Employee extends ActiveRecord {
  private String name;
  private String address;
  ...
} &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We should be able to fetch a given employee from the database by using a call like:&lt;/p&gt;


&lt;code&gt;Employee bob = Employee.findByName("Bob Martin");&lt;/code&gt;

	&lt;p&gt;We should also be able to modify that employee and save it as follows:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;bob.setName("Robert C. Martin");
bob.save();
&lt;/code&gt;&lt;/pre&gt;
In short, every column of the Employee table becomes a field of the Employee class.  There are static methods (or some magical reflection) on the ActiveRecord class that allow you to find instances.  There are also methods that provide &lt;span class="caps"&gt;CRUD&lt;/span&gt; functions.

	&lt;p&gt;Even shorter:  There is a 1:1 correspondence between tables and classes, columns and fields.  (Or very nearly so).&lt;/p&gt;


	&lt;p&gt;It is this 1:1 correspondence that bothers me.  Indeed, it bothers me about all &lt;span class="caps"&gt;ORM&lt;/span&gt; tools.  Why?  Because this mapping presumes that tables and objects are isomorphic.&lt;/p&gt;


	&lt;h2&gt;The Difference between Objects and Data Structures&lt;/h2&gt;


	&lt;p&gt;From the beginning of OO we learned that the data in an object should be hidden, and the public interface should be methods.  In other words: objects export behavior, not data.  An object has hidden data and exposed behavior.&lt;/p&gt;


	&lt;p&gt;Data structures, on the other hand, have exposed data, and no behavior.  In languages like C++ and C# the &lt;code&gt;struct&lt;/code&gt; keyword is used to describe a data structure with public fields.  If there are any methods, they are typically navigational.  They don&amp;#8217;t contain business rules.&lt;/p&gt;


	&lt;p&gt;Thus, data structures and objects are diametrically opposed.  They are virtual opposites.  One exposes behavior and hides data, the other exposes data and has no behavior.  But that&amp;#8217;s not the only thing that is opposite about them.&lt;/p&gt;


	&lt;p&gt;Algorithms that deal with objects have the luxury of not needing to know the kind of object they are dealing with.  The old example: &lt;code&gt;shape.draw();&lt;/code&gt; makes the point. The caller has no idea what kind of shape is being drawn.  Indeed, if I add new types of shapes, the algorithms that call &lt;code&gt;draw()&lt;/code&gt; are not aware of the change, and do not need to be rebuilt, retested, or redeployed.  In short, algorithms that employ objects are immune to the addition of new types.&lt;/p&gt;


	&lt;p&gt;By the same token, if I add new methods to the shape class, then all derivatives of shape must be modified.  So objects are &lt;em&gt;not&lt;/em&gt; immune to the addition of new functions.&lt;/p&gt;


Now consider an algorithm that uses a data structure.  
&lt;pre&gt;&lt;code&gt;
switch(s.type) {
  case SQUARE: Shape.drawSquare((Square)s); break;
  case CIRCLE: Shape.drawCircle((Circle)s); break;
}&lt;/code&gt;&lt;/pre&gt;
We usually sneer at code like this because it is not OO.  But that disparagement might be a bit over-confident.  Consider what happens if we add a new set of functions, such as &lt;code&gt;Shape.eraseXXX()&lt;/code&gt;.  None of the existing code is effected.  Indeed, it does not need to be recompiled, retested, or redeployed.  Algorithms that use data structures are immune to the addition of new functions.

	&lt;p&gt;By the same token if I add a new type of shape, I must find every algorithm and add the new shape to the corresponding switch statement.  So algorithms that employ data structures are &lt;em&gt;not&lt;/em&gt; immune to the addition of new types.&lt;/p&gt;


	&lt;p&gt;Again, note the almost diametrical opposition.  Objects and Data structures convey nearly opposite immunities and vulnerabilities.&lt;/p&gt;


	&lt;p&gt;Good designers uses this opposition to construct systems that are appropriately immune to the various forces that impinge upon them.  Those portions of the system that are likely to be subject to new types, should be oriented around objects.  On the other hand, any part of the system that is likely to need new functions ought to be oriented around data structures.  Indeed, much of good design is about how to mix and match the different vulnerabilities and immunities of the different styles.&lt;/p&gt;


	&lt;h2&gt;Active Record Confusion&lt;/h2&gt;


	&lt;p&gt;The problem I have with Active Record is that it creates confusion about these two very different styles of programming.  A database table is a data structure.  It has exposed data and no behavior.  But an Active Record appears to be an object.  It has &amp;#8220;hidden&amp;#8221; data, and exposed behavior.  I put the word &amp;#8220;hidden&amp;#8221; in quotes because the data is, in fact, not hidden.  Almost all ActiveRecord derivatives export the database columns through accessors and mutators.  Indeed, the Active Record is meant to be used like a data structure.&lt;/p&gt;


	&lt;p&gt;On the other hand, many people put business rule methods in their Active Record classes; which makes them appear to be objects.  This leads to a dilemma.  On which side of the line does the Active Record really fall?  Is it an object?  Or is it a data structure?&lt;/p&gt;


	&lt;p&gt;This dilemma is the basis for the oft-cited &lt;em&gt;impedance mismatch&lt;/em&gt; between relational databases and object oriented languages.  Tables are data structures, &lt;em&gt;not&lt;/em&gt; classes.  Objects are encapsulated behavior, &lt;em&gt;not&lt;/em&gt; database rows.&lt;/p&gt;


	&lt;p&gt;At this point you might be saying: &amp;#8220;So what Uncle Bob?  Active Record works great.  So what&amp;#8217;s the problem if I mix data structures and objects?&amp;#8221;  Good question.&lt;/p&gt;


	&lt;h2&gt;Missed Opportunity&lt;/h2&gt;


	&lt;p&gt;The problem is that Active Records &lt;em&gt;are&lt;/em&gt; data structures.  Putting business rule methods in them doesn&amp;#8217;t turn them into true objects.  In the end, the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type.  They are not immune to changes in type, the way algorithms that use objects are.&lt;/p&gt;


	&lt;p&gt;You can prove this to yourself by realizing how difficult it is to implement an polymorphic hierarchy in a relational database.  It&amp;#8217;s not impossible of course, but every trick for doing it is a hack.  The end result is that few database schemae, and therefore few uses of Active Record, employ the kind of polymorphism that conveys the immunity of changes to type.&lt;/p&gt;


	&lt;p&gt;So applications built around ActiveRecord are applications built around data structures.  And applications that are built around data structures are &lt;em&gt;procedural&lt;/em&gt;&amp;#8212;they are not object oriented.  The opportunity we miss when we structure our applications around Active Record is the opportunity to use object oriented design.&lt;/p&gt;


	&lt;h2&gt;No, I haven&amp;#8217;t gone off the deep end.&lt;/h2&gt;


	&lt;p&gt;I am not recommending against the use of Active Record.  As I said in the first part of this blog I think the pattern is very useful.  What I &lt;em&gt;am&lt;/em&gt; advocating is a separation between the application and Active Record.&lt;/p&gt;


	&lt;p&gt;Active Record belongs in the layer that separates the database from the application.  It makes a very convenient halfway-house between the hard data structures of database tables, and the behavior exposing objects in the application.&lt;/p&gt;


	&lt;p&gt;Applications should be designed and structured around &lt;em&gt;objects&lt;/em&gt;, not data structures.  Those objects should expose business behaviors, and hide any vestige of the database.  The fact that we have Employee tables in the database, &lt;em&gt;does not&lt;/em&gt; mean that we must have Employee classes in the application proper.  We may have Active Records that hold Employee rows in the database interface layer, but by the time that information gets to the application, it may be in very different kinds of objects.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;So, in the end, I am not against the use of Active Record.  I just don&amp;#8217;t want Active Record to be the organizing principle of the application.  It makes a fine transport mechanism between the database and the application; but I don&amp;#8217;t want the application knowing about Active Records.  I want the application oriented around objects that expose behavior and hide data.  I generally want the application immune to type changes; and I want to structure the application so that new features can be added by adding new types.  (See: &lt;a href="http://www.objectmentor.com/resources/articles/ocp.pdf"&gt;The Open Closed Principle&lt;/a&gt;)&lt;/p&gt;</description>
      <pubDate>Fri, 02 Nov 2007 11:29:31 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e278f630-f65c-415b-bf56-73de1706db94</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/11/02/active-record-vs-objects</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Dynamic Languages</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>A Rational Plan to Start using SOA</title>
      <description>&lt;p&gt;Many companies are thinking about adopting &lt;span class="caps"&gt;SOA&lt;/span&gt; as a way to reduce the cost of enterprise development.  The thought of diverse and reusable services, effortlessly communicating through an intelligent Enterprise Service Bus is  a powerful siren song for executives who see their development and maintenance budgets spiraling upwards.  What&amp;#8217;s more, vendors are displaying savory looking wares that promise to ease the transition.&lt;/p&gt;


	&lt;p&gt;Caveat Emptor!&lt;/p&gt;


	&lt;p&gt;The reality is that cramming an old and rickety enterprise system into services that communicate over a complex buss, is not an easy job.  The long and short of the problem can be seen in the following catch-22:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The benefit of &lt;span class="caps"&gt;SOA&lt;/span&gt; comes from the decoupled nature of the services.  But in order to create an &lt;span class="caps"&gt;SOA&lt;/span&gt; you have to decouple your services.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Decoupling your services is the issue.  Once you have decoupled them, then all the wonderful tools might be useful in facilitating an &lt;span class="caps"&gt;SOA&lt;/span&gt;.  On the other hand, if you have decoupled your services, you probably don&amp;#8217;t need all those wonderful tools.&lt;/p&gt;


	&lt;p&gt;I have a client that has implemented &lt;span class="caps"&gt;SOA&lt;/span&gt; to good effect. They avoided the vast majority of the tools.  For example, they are not using a big expensive buss.  They aren&amp;#8217;t using a &lt;span class="caps"&gt;BPEL&lt;/span&gt; engine, or message translators, or routing services.  About the only thing they have decided to use is &lt;span class="caps"&gt;SOAP&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;They are creating their services &lt;em&gt;from scratch&lt;/em&gt;, and wiring the system together manually.  Each service knows where each of it&amp;#8217;s client services is.  There is no registry service, no common dictionary, no fancy routing.&lt;/p&gt;


	&lt;p&gt;The system is simple, elegant, and it works.  It was &lt;em&gt;designed&lt;/em&gt; to work from the start.  It is not an old crufty system crammed under a soap layer and called a service provider.  Rather it is a nicely arrayed suite of services that were designed to work together from the get-go.&lt;/p&gt;


	&lt;p&gt;And that&amp;#8217;s really the moral of the story.  If you want an &lt;span class="caps"&gt;SOA&lt;/span&gt;, you are going to have to design that &lt;span class="caps"&gt;SOA&lt;/span&gt;.  It is not very likely that you will be able to cram you old, tightly-coupled code below &lt;span class="caps"&gt;SOAP&lt;/span&gt; interfaces and hope to gain the benefits of services.  What you&amp;#8217;ll more than likely end up with is just a bigger mess.&lt;/p&gt;</description>
      <pubDate>Sun, 21 Oct 2007 05:00:09 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6a75e3ea-a10d-4b81-b1ff-df00a57de6ed</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/10/21/a-rational-plan-to-start-using-soa</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Service Oriented Architecture</category>
    </item>
    <item>
      <title>Architecture is a Second Order Effect</title>
      <description>&lt;p&gt;We often argue that in order to achieve flexibility, maintainability, and reusability, it is important to have a good software architecture.  This is certainly true.  Without a well ordered architecture, software systems become masses of tangled modules and code.  However, the effect of architecture on the &amp;#8216;ilities is secondary to the effect that a good, fast, suite of tests has.&lt;/p&gt;


	&lt;p&gt;Why don&amp;#8217;t we clean our code?  When we see an ugly mass of code that we know is going to cause of problems, our first reaction is &amp;#8220;This needs to be cleaned up.&amp;#8221;  Our second reaction is: &amp;#8220;If I touch this code I&amp;#8217;ll be spending the next two weeks trying to get it to work again.&amp;#8221;  We don&amp;#8217;t clean code because we are afraid we&amp;#8217;ll break it.&lt;/p&gt;


	&lt;p&gt;In this way bad code hooks itself into our systems and refuses to go away.  Nothing stops clean code from going bad, but once it&amp;#8217;s bad, we seldom have the time, energy, or nerve to clean it.  In that sense, bad code is &lt;em&gt;permanent&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;What if you had a button?  If you push this button a little light &lt;em&gt;instantly&lt;/em&gt; turns red or green.  Green means your system works.  Red means it&amp;#8217;s broken. If you had a button like this, you could make small changes to the system, and prove that they didn&amp;#8217;t break anything.  If you saw a batch of tangled messy code, you could &lt;em&gt;start&lt;/em&gt; to clean it.  You&amp;#8217;d simply make a tiny improvement and then push the button.  If the light was green you&amp;#8217;d make the next tiny change, and the next, and the next.&lt;/p&gt;


	&lt;p&gt;I have a button like that!  It&amp;#8217;s called a test suite.  I can run it any time I like, and within seconds it tells me, with very high certainty, that my system works.&lt;/p&gt;


	&lt;p&gt;Of course, to be effective, that test suite has to cover all the code in the system.  And, indeed, that&amp;#8217;s what I have.  My code coverage tools tell me that 89% of the 45,000 lines in my system are covered by my test suite.  (89% is pretty good number given that my coverage tool counts un-executable lines like interfaces.)&lt;/p&gt;


	&lt;p&gt;Can I be absolutely sure that the green light means that the system works?  Certainly not.  But given the coverage of my test suite, I am &lt;em&gt;reasonably&lt;/em&gt; sure that the changes I make are not introducing any bugs. And that reasonable surety is enough for me to be fearless about making changes.&lt;/p&gt;


	&lt;p&gt;This fearlessness is something that needs to be experienced to understand.  I feel no reluctance at all about cleaning up the code in my system.  I frequently take whole classes and restructure them.  I change the names of classes, variables, and functions on a whim.  I extract super-classes and derivatives any time I like.&lt;/p&gt;


	&lt;p&gt;In short, the test suite makes it easy to make changes to my code. It makes my code flexible and easy to maintain.&lt;/p&gt;


	&lt;p&gt;So does my architecture of course.  The design and structure of my system is very easy to deal with, and allows me to make changes without undue impact.  The reason my architecture is so friendly, is that I&amp;#8217;ve been fearless about changing it.  And that&amp;#8217;s because I have a test suite that runs in seconds, and that I trust!&lt;/p&gt;


	&lt;p&gt;So the clean architecture of my system is a &lt;em&gt;result&lt;/em&gt; of on-going efforts supported by the test suite.  I can keep the architecture clean and relevant because I have tests.  I can improve the architecture when I see a better approach because I have tests.  It is the tests that enable architectural improvement.&lt;/p&gt;


	&lt;p&gt;Yes, architecture enables flexibility, maintainability, and reusability; but test suites enable architecture.  Architecture is a second order effect.&lt;/p&gt;</description>
      <pubDate>Sat, 20 Oct 2007 01:58:29 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:2b06de7f-540e-411f-97e4-c77a040f3b4a</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/10/20/architecture-is-a-second-order-effect</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>TDD with Acceptance Tests and Unit Tests</title>
      <description>&lt;p&gt;Test Driven Development is one of the most imperative tenets of Agile Software Development.  It is difficult to claim that you are Agile, if you are not writing lots of automated test cases, and writing them before you write the code that makes them pass.&lt;/p&gt;


	&lt;p&gt;But there are two different kinds of automated tests recommended by the Agile disciplines.  Unit tests, which are written by programmers, for programmers, in a programming language.  And acceptance tests, which are written by business people (and QA), for business people, in a high level specification language (like FitNesse www.fitnesse.org).&lt;/p&gt;


	&lt;p&gt;The question is, how should developers treat these two streams of tests?  What is the process?  Should they write their unit tests and production code first, and then try to get the acceptance tests to pass?  Or should they get the acceptance tests to pass and then backfill with unit tests?&lt;/p&gt;


	&lt;p&gt;And besides, why do we need two streams of tests.  Isn&amp;#8217;t all that testing awfully reduntant?&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s true that the two streams of tests test the same things.  Indeed, that&amp;#8217;s the point.  Unit tests are written by programers to ensure that the code does what they intend it to do.  Acceptance tests are written by business people (and QA) to make sure the code does what &lt;em&gt;they&lt;/em&gt; intend it to do.  The two together make sure that the business people and programmers intend the same thing.&lt;/p&gt;


	&lt;p&gt;Of course there&amp;#8217;s also a difference in level.  Unit tests reach deep into the code and test independent units.  Indeed, programmers must go to great lengths to decouple the components of the system in order to test them independently.  Therefore unit tests seldom exercise large integrated chunks of the system.&lt;/p&gt;


	&lt;p&gt;Acceptance tests, on the other hand, operate on much larger integrated chunks of the system.  They typically drive the system from it&amp;#8217;s inputs (or a point very close to it&amp;#8217;s inputs) and verify operation from it&amp;#8217;s outputs (or again, very close to it&amp;#8217;s outputs).  So, though the acceptance tests may be testing the same things as the unit tests, the execution pathways are very different.&lt;/p&gt;


	&lt;h2&gt;Process&lt;/h2&gt;


	&lt;p&gt;Acceptance tests should be written at the start of each iteration.  QA and Business analysts should take the stories chosen during the planning meeting, and turn them into automated acceptance tests written in FitNesse, or Selenium or some other appropriate automation tool.&lt;/p&gt;


	&lt;p&gt;The first few acceptance tests should arrive within a day of the planning meeting.  More should arrive each day thereafter.  They should all be complete by the midpoint of the iteration.  If they aren&amp;#8217;t, then some developers should change hats and help the business people finish writing the acceptance tests.&lt;/p&gt;


	&lt;p&gt;Using developers in this way is an automatic safety valve.  If it happens too often, then we need to add more QA or BA resources.  If it never happens, we may need to add more programmers.&lt;/p&gt;


	&lt;p&gt;Programmers use the acceptance tests as requirements.  They read those tests to find out what their stories are &lt;em&gt;really&lt;/em&gt; supposed to do.&lt;/p&gt;


	&lt;p&gt;Programmers start a story by executing the acceptance tests for that story, and noting what fails. Then they write unit tests that force them to write the code that will make some small portion of the acceptance tests pass.  They keep running the acceptance tests to see how much of their story is working, and they keep adding unit tests and production code until all the acceptance tests pass.&lt;/p&gt;


	&lt;p&gt;At the end of the iteration all the acceptance tests (and unit tests) are passing.  There is nothing left for QA to do.  There is no hand-off to QA to make sure the system does what it is supposed to.  The acceptance tests already prove that the system is working.&lt;/p&gt;


	&lt;p&gt;This does not mean that QA does not put their hands on the keyboards and their eyes on the screen.  They do!  But they don&amp;#8217;t follow manual test scripts!  Rather, they perform &lt;em&gt;exploratory testing&lt;/em&gt;.  They get &lt;em&gt;creative&lt;/em&gt;.  They do what QA people are really good at&amp;#8212;they find new and interesting ways to break the system.  They uncover unspecified, or under-specified areas of the system.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;ASIDE&lt;/span&gt;:&lt;/strong&gt; Manual testing is immoral.  Not only is it high stress, tedious, and error prone; it&amp;#8217;s just wrong to turn humans into machines.  If you can write a script for a test procedure, then you can write a program to execute that procedure.  That program will be cheaper, faster, and more accurate than a human, and will free the human to do what humans to best: &lt;em&gt;create!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;So, in short, the business specifies the system with automated acceptance tests.  Programmers run those tests to see what unit tests need to be written.  The unit tests force them to write production code that passes both tests.  In the end, all the tests pass.  In the middle of the iteration, QA changes from writing automated tests, to exploratory testing.&lt;/p&gt;</description>
      <pubDate>Wed, 17 Oct 2007 05:50:34 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:726aa984-5062-42df-a89f-4e02601d4f47</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/10/17/tdd-with-acceptance-tests-and-unit-tests</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>SOA, cuts the Gordian Knot -- Not.</title>
      <description>&lt;p&gt;In 333 B.C. Alexander the Great cut the Gordian Knot with his sword, breaking that symbol of ancient power and ushering in a new empire.  Some IT managers feel that &lt;span class="caps"&gt;SOA&lt;/span&gt; will finally cut the great Gordian Knot of their tangled and tumultuous software systems.  Will it?&lt;/p&gt;


	&lt;p&gt;No.&lt;/p&gt;


	&lt;p&gt;Let me restate that more clearly for those of you who may still have doubt.&lt;/p&gt;


	&lt;p&gt;No frickin way Jose!&lt;/p&gt;


	&lt;p&gt;Most software systems are a mess.  &lt;span class="caps"&gt;SOA&lt;/span&gt; is not the cure for that mess.  Indeed, &lt;span class="caps"&gt;SOA&lt;/span&gt; doesn&amp;#8217;t even start to be feasible until the mess has been cleaned up.&lt;/p&gt;


	&lt;p&gt;Again, let me restate that.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;SOA&lt;/span&gt; does not help you clean up the mess that your software is in.  In order to adopt &lt;span class="caps"&gt;SOA&lt;/span&gt; you must first clean up the mess you have made.  Once the mess is clean, then you can start to think about &lt;span class="caps"&gt;SOA&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Right now, at this very moment, some IT manager is reading about how the next release of some Enterprise Service Bus is going to solve all his woes.  All he has to do is install this wonderful piece of software, tie it into the new whippy-diddle business process modeling tool.  Get some clerks to write the &lt;span class="caps"&gt;XML&lt;/span&gt; files that describe their business processes, get some other clerks to write the message translators that drive that great interoperability Babel Fish in the sky.  Get some business process modelers to draw pretty pictures of all the interconnections between the systems.  Feed that all into the &lt;span class="caps"&gt;ESB&lt;/span&gt;, and shake vigorously with deadlines and threats.  This will cause fuzzy bunnies to hop happily over the green fields of his IT systems.&lt;/p&gt;


	&lt;p&gt;Right.&lt;/p&gt;


	&lt;p&gt;The reality is that the first letter of &lt;span class="caps"&gt;SOA&lt;/span&gt;, namely &amp;#8220;S&amp;#8221;, stands for &amp;#8220;Service&amp;#8221;.  Not to put to fine a point on it, &lt;span class="caps"&gt;SOA&lt;/span&gt; means an Architecture Oriented around Services.  What is a service?  A Service is a piece of software with the characteristics of a service?  What are those characteristics?  They are: Low coupling, independently deployability, stable interface, etc.&lt;/p&gt;


	&lt;p&gt;Most software professionals (if that term is not oxymoronic) will recognize this set of attributes as being identical with that of the &amp;#8220;Components&amp;#8221; of the 90s.  Indeed, Services are the new Components.  The words are synonyms.&lt;/p&gt;


	&lt;p&gt;This means that &lt;span class="caps"&gt;SOA&lt;/span&gt; is just as hard to do as &lt;span class="caps"&gt;COA&lt;/span&gt;.  (Component Oriented Architecture for those of you who are acronym challenged).  Indeed, &lt;span class="caps"&gt;SOA&lt;/span&gt; &lt;em&gt;is&lt;/em&gt; COA!&lt;/p&gt;


	&lt;p&gt;Now, I know it&amp;#8217;s been a long time.  But does anybody remember what it took to do &lt;span class="caps"&gt;COA&lt;/span&gt;?  No?  Then let me tell you a little story to jog your memory.&lt;/p&gt;


	&lt;p&gt;In the mid &amp;#8216;90s I had a client who had a 250MB executable written in C++.  (Yes, I know this seems like a hello world program today, but back then 250MB was a &lt;em&gt;big&lt;/em&gt; program).  This client was vexed because every time he changed even a single line of code, he had to rebuild the entire executable, burn it onto a CD, and ship the CDs to his installed base.  This was costing him lots of time and money.&lt;/p&gt;


	&lt;p&gt;What he wanted was a way to break his application into components and then ship only those components that changed.  His hope was that he could ship them over the internet because they&amp;#8217;d all be small enough to email or &lt;span class="caps"&gt;FTP&lt;/span&gt;.  (This was back when people did not regularly download 4GB movies, or backup 100GB disks over the internet every night).&lt;/p&gt;


	&lt;p&gt;So he adopted &lt;span class="caps"&gt;COA&lt;/span&gt;, and the popular implementation platform of for &lt;span class="caps"&gt;COA&lt;/span&gt;, COM+ (Otherwise known as void**: Nothing to the power of nothing.)  He slaved away for months breaking his application up into components that could be dynamically loaded in DLLs.  And in the end, he succeeded.  His application was completely&amp;#8212;&lt;em&gt;componentized&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;However, there was one little snag. He forgot to decouple the components from one another.  Each component depended on several others.  There were &lt;em&gt;cycles&lt;/em&gt; in the dependency graph of components.  (Aside to the architecturally challenged:  &amp;#8220;That&amp;#8217;s bad.&amp;#8221;)  So in the end, when he changed a line of code in one component, he had to rebuild and redeploy all the components.  He had to burn all those components onto a CD.&lt;/p&gt;


	&lt;p&gt;In short, nothing had changed.&lt;/p&gt;


	&lt;p&gt;Long long ago, I watched a software developer write complicated macro in his highly powerful text editor.  It converted all tabs to spaces.  I remember watching him start it.  The code he was transforming was on the screen.  He ran the macro, which took several minutes to run.  It displayed a series of dots running across the screen.  It was very impressive, and looked like it was doing something significant.  And then when it finished, the code was redisplayed on the screen.  I laughed, because after all that work of translating tabs into spaces, and putting dots on the screen, the displayed code looked exactly the same as when he started. It was as if nothing had happened.&lt;/p&gt;


	&lt;p&gt;My client&amp;#8217;s reaction to his inability to independently deploy his components had nothing to do with laughter.&lt;/p&gt;


	&lt;p&gt;The point?  &lt;span class="caps"&gt;SOA&lt;/span&gt; will not cut the Gordian Knot.  Indeed, it will pull that Knot even tighter.  The Knot can&amp;#8217;t be cut.  There is no magic that will make the mess go away, or make the mess less of an issue.  If you want the flexibility of &lt;span class="caps"&gt;SOA&lt;/span&gt;, then you must clean up the mess you have and then slowly and gradually build services from those cleaned up systems.&lt;/p&gt;


	&lt;p&gt;The real point?  &lt;span class="caps"&gt;TANSTAASB&lt;/span&gt;.  (There ain&amp;#8217;t no such thing as a Silver Bullet).&lt;/p&gt;</description>
      <pubDate>Wed, 03 Oct 2007 13:31:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3043ac32-fad6-4201-b2ca-1b7c54c7caf5</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/10/03/soa-cuts-the-gordian-knot-not</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Service Oriented Architecture</category>
    </item>
    <item>
      <title>Schools of Thought</title>
      <description>&lt;p&gt;In some sense we software developers are all too tolerant.  We know there is no single &amp;#8220;right&amp;#8221; way to write software, and so we tolerate many different opinions and styles.  In the industry at large, this is a good thing.  But inside a project it&amp;#8217;s chaos.&lt;/p&gt;


	&lt;p&gt;A project with 10 different developers cannot withstand 10 different styles of coding, 10 different architectural visions, 10 different philosophies of OO design, or 10 different software development methods.  To prevent the chaos of anarchy, one style, one vision, one philosophy and one method must be adopted.&lt;/p&gt;


	&lt;p&gt;The problem is, we know that no one style, vision, philosophy, or method is &amp;#8220;right&amp;#8221;.  This knowledge makes us timid.  We tolerate other people&amp;#8217;s styles and attitudes rather than insisting on a single style and vision for the project.  We feel that we have no right to insist on one particular way of doing things, and so we adopt a &lt;em&gt;politically correct&lt;/em&gt; viewpoint regarding software.&lt;/p&gt;


	&lt;p&gt;Politically correct projects are muddles.  They find it difficult to get traction because the team members are all pulling in different directions. This muddling continues until someone puts a stake in the ground and says &amp;#8220;We&amp;#8217;re doing it &lt;strong&gt;this&lt;/strong&gt; way&amp;#8221;, and makes it stick by sheer force of will.  Then the team moves on and makes progress.&lt;/p&gt;


	&lt;p&gt;Was his way right?  The question is irrelevant.  The stake in the ground provided focus.  It eliminated the chaos of too much &amp;#8220;rightness&amp;#8221;, of too much political correctness.&lt;/p&gt;


	&lt;p&gt;There are many different schools of martial arts.  Karate, Tai Kwon Do, Jiu Jitsu, Judo, etc.  Which is right?  Of course the question is absurd.  Right and wrong are not adjectives that apply to individual martial arts.  And yet, each martial art attracts dedicated adherents.  The intensity of their devotion to their art is almost religious.&lt;/p&gt;


	&lt;p&gt;Students of Karate have no rational reason to prefer it to Tai Kwon Do.  Indeed, the initial decision to study one vs the other was almost certainly arbitrary.  Perhaps there was a Karate studio near their home.  Perhaps a friend invited them to a session.  Perhaps they saw something on TV, or in the paper.  In most cases the initial decision was trivial.&lt;/p&gt;


	&lt;p&gt;But that&amp;#8217;s where the triviality ends.  From then on the new student gets immersed into a set of styles, disciplines, philosophies, and methods to the exclusion of all others.  There is no political correctness at this level.  Teachers tolerate no dissent from their teachings.  It&amp;#8217;s the Sen Sei&amp;#8217;s way, or the highway.  Within a dojo, there &lt;em&gt;is&lt;/em&gt; a right and a wrong.&lt;/p&gt;


	&lt;p&gt;At a larger level, everyone knows that no one martial art is clearly better than all the others.  There is no &amp;#8220;right&amp;#8221; school of martial art.  And yet, students invest huge efforts into becoming masters of one particular arbitrary discipline.&lt;/p&gt;


	&lt;p&gt;Why would a student focus on one particular school of martial art to the exclusion of all others for years of his or her life?  Simple.  To become a master.  You can&amp;#8217;t become a master of all martial arts at the same time.  You have to separate and focus.  You have to dedicate yourself to one and learn it inside and out.  You have to be politically incorrect.  That&amp;#8217;s how you gain mastery.&lt;/p&gt;


	&lt;p&gt;Once a degree of mastery is attained, it becomes beneficial to study other martial arts.  A karate black belt will find it beneficial to study Jiu Jitsu, or Akido.  The Judo black belt will gain insights into his own art by studying Karate.  So, at the level of the master, political correctness and tolerance is re-established.&lt;/p&gt;


	&lt;p&gt;There are many diverse attitudes about software.  For example there are many different kinds of agile methods.  Indeed, there are methods that aren&amp;#8217;t agile at all.  There&amp;#8217;s the American vs the European style of OO.  There&amp;#8217;s functional vs OO vs procedural programming.  There are those who practice hungarian notation.  There are those who practice test driven development.  There are those who believe in C and C++ and those who believe in Ruby.  None of these attitudes and preferences are right.  None of them are wrong.  But without some kind of organizing principle, like a dojo, or a Sen Sei, they are chaos.&lt;/p&gt;


	&lt;p&gt;There has been a lot of talk about certification lately.  Companies need to know if the people they hire are good developers or not.  The problem is, there is no standard of certification.  There is no right or wrong, and so there&amp;#8217;s little to certify. We can certify that someone took a particular course, or that they have certain knowledge of C++ or Java.  We can measure someone&amp;#8217;s ability to read a book, or write a dumb example program.  What we cannot do is certify whether someone is a good developer or not, because we don&amp;#8217;t have a definition of &amp;#8220;good&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;The different schools of martial arts have solved this problem of certification quite effectively.  No school will certify that their student is a master martial artist.  But they &lt;em&gt;will&lt;/em&gt; certify that they are a master of one particular discipline.  You cannot be a general black-belt, but you &lt;em&gt;can&lt;/em&gt; be a black-belt in one particular school of Karate.&lt;/p&gt;


	&lt;p&gt;The award of rank is not based on a casual test, or the taking of a two day course.  It is based on months of exposure and participation in practice sessions.  It is based on the teacher&amp;#8217;s intimate knowledge of the student&amp;#8217;s skill.  What&amp;#8217;s more the teacher&amp;#8217;s right to convey rank is based on &lt;em&gt;his&lt;/em&gt; teacher&amp;#8217;s authority.  Thus, there is a chain of trust from teacher to teacher.&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t know if a martial-arts ranking system could ever be established in software.  The problems seem significant.  For example, how would teachers gain the kind of prolonged access they&amp;#8217;d need to bestow ranks on students?&lt;/p&gt;


	&lt;p&gt;However, I do think it&amp;#8217;s possible for experienced practitioners to put a stake in the ground and establish a school of software discipline.  In effect the practitioner says:  &amp;#8220;I&amp;#8217;ve done it my way, and it worked for me.  I&amp;#8217;ll teach you my way, perhaps it will work for you.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Such a school would be precise and exclusive.  Students would adopt a certain coding style, a certain philosophy of design, a certain architectural vision, and a certain set of methods and practices.  They would adhere to those certain teachings to the exclusion of all others until they mastered them.&lt;/p&gt;</description>
      <pubDate>Wed, 03 Oct 2007 12:37:21 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9181a3bf-8f5e-40e5-b9ef-a6366209582c</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/10/03/schools-of-thought</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Thread Local: A Convenient Abomination.</title>
      <description>&lt;p&gt;ThreadLocal variables are a wonderfully convenient way to associate data with a given thread.  Indeed, frameworks like Hibernate take advantage of this to hold session information.  However, the practice depends upon assumption that a thread is equivalent to a unit-of-work.  This is a &lt;em&gt;faulty&lt;/em&gt; assumption&lt;/p&gt;


	&lt;p&gt;Thirteen years ago, while working on my first book, Jim Coplien and I were having a debate on the nature of threads and objects.  He made a clarifying statement that has stuck with me since.  He said: &lt;em&gt;&amp;#8220;An object is an abstraction of function.  A thread is an abstraction of schedule.&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;It has become the norm, in Java applications, to assume that there is a one-to-one correspondence between a thread, and a unit-of-work.  This appears to make sense since every Servlet request has it&amp;#8217;s own particular thread.  Framework authors have built on this assumption by putting unit-of-work related information (e.g. session) into ThreadLocal variables.&lt;/p&gt;


	&lt;p&gt;Clearly, the more ThreadLocal variables that hold unit-of-work related information, the more that the thread and the unit-of-work are related.  While very convenient, the basic assumption is dead wrong.&lt;/p&gt;


	&lt;p&gt;A unit-of-work is a task to be performed.  There is no rule that says that this task must be single threaded.  Nor is there any rule that says that the components of the task must run at the same priority.  Indeed, it is not uncommon for a task to have a high-priority event driven part, and a low priority compute-bound part.&lt;/p&gt;


	&lt;p&gt;Consider, for example, a unit-of-work that makes a request from a third-party-service, and then processes the response with a complex number-crunching algorithm.  We want the request to run at a high priority so that it is not waiting for other low priority compute-bound tasks to finish.  On the other hand, we want the number-cruncher to run at a low priority so that it yields the processor as soon as possible whenever one of the high priority requests needs a few cycles.&lt;/p&gt;


	&lt;p&gt;Clearly these two tasks form a complete unit-of-work, but just as clearly they should run as two different threads&amp;#8212;probably with a queue in between them in a standard producer-consumer model.&lt;/p&gt;


	&lt;p&gt;Where are the unit-of-work related variables?  They can&amp;#8217;t be kept in a ThreadLocal since each part of the task runs in a separate thread.  They can&amp;#8217;t be kept in static variables since there is more than one thread.  The answer is that they have to be passed around between the threads as function arguments on the stack, and recorded in the data structured placed on the queue.&lt;/p&gt;


	&lt;p&gt;So, though convenient, ThreadLocal variables confuse the issue of separating function from schedule.  They tempt us to couple function and schedule together.  This is unfortunate since the correspondence of function and schedule is weak and accidental.&lt;/p&gt;


	&lt;p&gt;What we&amp;#8217;d really like is to be able to create UnitOfWorkLocal variables.&lt;/p&gt;</description>
      <pubDate>Tue, 04 Sep 2007 10:16:31 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:911e858a-8063-4029-adba-a4db194054e3</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/09/04/thread-local-a-convenient-abomination</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Craftsman #51: Brown Bag VIII - Ruby Visitor</title>
      <description>&lt;p&gt;&amp;#8220;A new speaker talks to the team and illuminates the differences between Ruby and Java by implementing the Visitor pattern in both languages.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Get the &lt;a href="http://www.objectmentor.com/resources/articles/Craftsman51.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Or to see all the craftsman articles:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;go to &lt;a href="www.objectmentor.com"&gt;www.objectmentor.com&lt;/a&gt;, &lt;/li&gt;
		&lt;li&gt;click the &lt;em&gt;resources&lt;/em&gt; tab, &lt;/li&gt;
		&lt;li&gt;click &lt;em&gt;published articles&lt;/em&gt; link, &lt;/li&gt;
		&lt;li&gt;click the &lt;em&gt;Craftsman&lt;/em&gt; topic, &lt;/li&gt;
		&lt;li&gt;scroll down to #51: Brown Bag &lt;span class="caps"&gt;VIII&lt;/span&gt; &amp;#8211; Ruby Visitor.&lt;/li&gt;
	&lt;/ol&gt;</description>
      <pubDate>Wed, 08 Aug 2007 06:54:23 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:4243e323-8805-408c-b7b7-4f308460c3d9</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/08/08/craftsman-51-brown-bag-viii-ruby-visitor</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>The Founding of the Agile Alliance</title>
      <description>&lt;p&gt;These are my own personal recollections.  I&amp;#8217;m probably wrong about some of it.  If any of the other folks involved have a clearer memory of the events, please don&amp;#8217;t hesitate to comment.&lt;/p&gt;


	&lt;p&gt;In the spring of 2000 Kent Beck called a meeting at the Rogue River Lodge near his home in Medford, Oregon.  He called it the &lt;em&gt;Extreme Programming Leadership Conference&lt;/em&gt;.  In attendance were: myself, Ron Jeffries, Ken Auer, Martin Fowler, and several others who had been instrumental in getting the XP movement off the ground.&lt;/p&gt;


	&lt;p&gt;In one of the sessions we discussed the creation of an organization to drive and support the adoption of XP.  This was an idea that I argued in favor of.  It seemed to me that the industry would benefit from a body who promoted the ideas of lightweight methods like XP.  However, the idea was not met with enthusiasm amongst many of the other attendees. The session turned into a collection of painful reminiscences about a previous attempt at creating an organization around the &lt;em&gt;Patterns&lt;/em&gt; movement. I came away convinced that a different group of people would have to drive the creation of such an organization.&lt;/p&gt;


	&lt;p&gt;Apparently I was not alone.  Martin Fowler had noticed the arguments I had made in the session, and approached me during a break.  We briefly discussed the idea of broadening the scope of the proposed organization to all the various &amp;#8220;lightweight methods&amp;#8221; such as &lt;em&gt;Scrum&lt;/em&gt; and &lt;em&gt;Crystal Light&lt;/em&gt;.  We felt that the folks who espoused these methods would have a lot to add, and could form the core of a comprehensive movement.  Martin and I determined to meet a few weeks later to work out the details.&lt;/p&gt;


	&lt;p&gt;In the meantime I contacted my friend and advisor Dave Thomas of &lt;span class="caps"&gt;OTI&lt;/span&gt; fame.  (We call him &amp;#8220;Big Dave&amp;#8221; to differentiate him from the &lt;em&gt;Pragmatic Programmer&lt;/em&gt; of the same name.) I mentioned the notion of a &lt;em&gt;Lightweight Methods Summit&lt;/em&gt;.  We put a tentative invitation list together.  Dave suggested that we meet in February at his winter home in Anguilla.&lt;/p&gt;


	&lt;p&gt;Later that fall I met with Martin at a cafe in Chicago.  We added to the invitation list and outlined the invitation email.  The invitation stated the goal of creating a manifesto describing what all the various lightweight methods had in common.  I sent the email that evening.&lt;/p&gt;


	&lt;p&gt;The &lt;em&gt;Lightweight Process Summit&lt;/em&gt; invitation drew an enthusiastic response from the invitees.  Alistair Cockburn was especially interested.  As it happened, he was on the verge of sending out his own invitation for a similar event.  His comment to me was: &amp;#8220;Your invitation list was better than mine&amp;#8221;.  The two invitation lists were merged, and the discussion of logistics began.&lt;/p&gt;


	&lt;p&gt;Alistair became the de-facto organizer.  He suggested that we change the venue from Anquilla to Snowbird in Salt Lake City.  Almost all the other invitees agreed because the flights would be easier.  Alistair and Jim Highsmith did the leg-work to arrange the rooms, meals, and activities.  Things came together rapidly.&lt;/p&gt;


	&lt;p&gt;The meeting was very well attended by 17 out of ~20 invitees.  (See www.agilemanifesto.org to see the list of attendees.)  Unfortunately neither Grady Booch nor Big Dave Thomas were able to make it.  However, their influence was strongly felt in the subsequent discussions.&lt;/p&gt;


	&lt;p&gt;I kicked off the meeting with a brief introduction and an appeal to the similarities between all the various lightweight processes.  I reaffirmed that the goal of our two day meeting was to create a manifesto that outlined those similarities.  This was to be a document, addressed to the industry at large, describing our views about the process of creating useful software.&lt;/p&gt;


	&lt;p&gt;Martin Fowler and Ward Cunningham quickly became the de-facto facilitators of the meeting.  With their help we quickly worked out an agenda for the two days, and a method for making decisions.&lt;/p&gt;


	&lt;p&gt;It was actually quite a thrill to see all these people with disparate ideas working together so well.  I don&amp;#8217;t think I&amp;#8217;ve ever been to a meeting that stayed on point and met it&amp;#8217;s goals with such ease and with so little conflict.  It was as though the pieces just somehow fell together.&lt;/p&gt;


	&lt;p&gt;One of the early discussions was about a &lt;em&gt;name&lt;/em&gt;.  No one liked the term &lt;em&gt;Lightweight&lt;/em&gt;.  Several other options were suggested, including &lt;em&gt;Lean&lt;/em&gt;, and &lt;em&gt;Adaptive&lt;/em&gt;.  But the name &lt;em&gt;Agile&lt;/em&gt; won the day.&lt;/p&gt;


	&lt;p&gt;The structure of the manifesto was mutually agreed; I recall that Ward played a big part framing the idea of pairs of &lt;em&gt;relative&lt;/em&gt; value, but it may have been Martin and Pragmatic Dave Thomas who came up with the idea.  Here&amp;#8217;s PragDave&amp;#8217;s recollection:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;Actually, that was Martin and me, noodling on the whiteboard over lunch. I think we came up with the initial three. The group that then formed took it up to five, and that was then pruned down to four.  In fact, Ward took the picture of everyone discussing the idea that now adorns his manifesto site.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;By the end of the two days in Snowbird, the manifesto was done, the principles were outlined, and the Agile Alliance had been born.  Much more would need to be done before there would be a true legal entity with a board and members, but that&amp;#8217;s a story for another time.&lt;/p&gt;


	&lt;p&gt;For another version of this history see Jim Highsmith&amp;#8217;s description at http://www.agilemanifesto.org/history.html&lt;/p&gt;</description>
      <pubDate>Tue, 10 Jul 2007 08:43:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6a26d61e-9373-415c-9187-4bae19241ff0</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/07/10/the-founding-of-the-agile-alliance</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Craftsman #50: Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://www.objectmentor.com/resources/articles/The_Craftsman_50_Brown_Bag_VII.pdf"&gt;Here&lt;/a&gt; is my latest &lt;em&gt;Craftsman&lt;/em&gt; article.  Aphonse, Jerry, Jasmine, and the crew learn a little bit about Ruby, and fight about it&amp;#8217;s benefits and dangers.&lt;/p&gt;</description>
      <pubDate>Thu, 14 Jun 2007 23:30:12 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fa37ed93-0aa1-499e-bc34-994e7fd70017</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/06/14/craftsman-50-ruby</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Craftsman #50: Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://www.objectmentor.com/resources/articles/The_Craftsman_50_Brown_Bag_VII.pdf"&gt;Here&lt;/a&gt; is my latest &lt;em&gt;Craftsman&lt;/em&gt; article.  Aphonse, Jerry, Jasmine, and the crew learn a little bit about Ruby, and fight about it&amp;#8217;s benefits and dangers.&lt;/p&gt;</description>
      <pubDate>Thu, 14 Jun 2007 23:30:12 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fa37ed93-0aa1-499e-bc34-994e7fd70017</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/06/14/craftsman-50-ruby</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Craftsman #50: Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://www.objectmentor.com/resources/articles/The_Craftsman_50_Brown_Bag_VII.pdf"&gt;Here&lt;/a&gt; is my latest &lt;em&gt;Craftsman&lt;/em&gt; article.  Aphonse, Jerry, Jasmine, and the crew learn a little bit about Ruby, and fight about it&amp;#8217;s benefits and dangers.&lt;/p&gt;</description>
      <pubDate>Thu, 14 Jun 2007 23:30:12 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fa37ed93-0aa1-499e-bc34-994e7fd70017</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/06/14/craftsman-50-ruby</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>The Hidiocy of XML Languages</title>
      <description>&lt;p&gt;I&amp;#8217;ve been reading up on some of the newer aspects of &lt;span class="caps"&gt;SOA&lt;/span&gt;, and came across &lt;span class="caps"&gt;BPEL&lt;/span&gt;.  It&amp;#8217;s &lt;em&gt;another&lt;/em&gt; language you are supposed to write in &lt;span class="caps"&gt;XML&lt;/span&gt;.  Get ready for a rant.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve had it.  What is the matter with these people?  How, after all the experience we&amp;#8217;ve had with &lt;span class="caps"&gt;XSLT&lt;/span&gt;, Ant, &lt;span class="caps"&gt;WSDL&lt;/span&gt;, etc., etc., could they create &lt;span class="caps"&gt;YET ANOTHER XML&lt;/span&gt; language.  Are they dolts?  Are they idiots?  What gives.&lt;/p&gt;


	&lt;p&gt;Look, writing in &lt;span class="caps"&gt;XML&lt;/span&gt; is hideous.  It&amp;#8217;s wordy, it&amp;#8217;s error-prone, it&amp;#8217;s arcane, it&amp;#8217;s redundant, it&amp;#8217;s redundant, it&amp;#8217;s redundant, it&amp;#8217;s&amp;#8230; &lt;span class="caps"&gt;HIDEOUS&lt;/span&gt;!  To make matters worse, we have been embedding &lt;span class="caps"&gt;OTHER&lt;/span&gt; languages &lt;span class="caps"&gt;INSIDE&lt;/span&gt; this horrible container.  &lt;span class="caps"&gt;EGAD&lt;/span&gt;!  &lt;span class="caps"&gt;YIKES&lt;/span&gt;!  &lt;span class="caps"&gt;ZOUNDS&lt;/span&gt;!  &lt;span class="caps"&gt;FORSOOTH&lt;/span&gt;!  This is just plain nuts, stupid, idiotic, retarded, poo-poo-headed, silliness!&lt;/p&gt;


	&lt;p&gt;Haven&amp;#8217;t these people heard of &lt;em&gt;economy of expression&lt;/em&gt;?  Haven&amp;#8217;t they heard of &lt;span class="caps"&gt;YACC&lt;/span&gt;?  Don&amp;#8217;t they know that domain specific languages &lt;span class="caps"&gt;SHOULD BE LANGUAGES&lt;/span&gt;?  Don&amp;#8217;t they know that languages have specific &lt;span class="caps"&gt;GRAMMARS&lt;/span&gt;?&lt;/p&gt;


	&lt;p&gt;Besides, have they ever tried to write an interpreter or compiler that uses &lt;span class="caps"&gt;XML&lt;/span&gt; as it&amp;#8217;s source?  It&amp;#8217;s not any easier than writing a &lt;span class="caps"&gt;YACC&lt;/span&gt; parser!  Indeed, it&amp;#8217;s a lot, lot, harder.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;EMBEDDING THE GRAMMAR OF YOUR DSL IN XML IS&lt;/span&gt; &lt;strong&gt;&lt;span class="caps"&gt;STUPID&lt;/span&gt;&lt;/strong&gt;!!!  
&lt;strong&gt;&lt;span class="caps"&gt;DON&lt;/span&gt;&amp;#8217;T &lt;span class="caps"&gt;DO IT&lt;/span&gt;!!!!!&lt;img src="@" alt="" /&gt;&lt;code&gt;#$#&lt;/code&gt;$!&lt;img src="@#%" alt="" /&gt;!!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;em&gt;I hereby declare a revolt.&lt;/em&gt;&lt;/strong&gt;  From now on anyone who considers themselves to be a serious professional must refuse to write another line of &lt;span class="caps"&gt;XML&lt;/span&gt;.  When asked, say NO.  Instead, write a little &lt;span class="caps"&gt;YACC&lt;/span&gt; grammar that is nice, and small, and translates into that hideous &lt;span class="caps"&gt;XML&lt;/span&gt;.  You&amp;#8217;ll save yourself &lt;span class="caps"&gt;GOBS&lt;/span&gt; of time if you do!  What&amp;#8217;s more, if you sell your parser for $5 per download, you&amp;#8217;ll probably be able to buy a new boat!  Maybe a fleet!&lt;/p&gt;</description>
      <pubDate>Thu, 17 May 2007 22:01:22 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:7caa6edd-f657-402d-a766-d2abdb8dffa7</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/05/17/the-hidiocy-of-xml-languages</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Coding Standards</title>
      <description>&lt;p&gt;Coding Standards are a good idea.  Every team should adopt a coding style and standard, and stick to it.  The code produced by that team should have a consistent look and feel that is devoid of individual preferences and fetishes.&lt;/p&gt;


	&lt;p&gt;Of course this means that the members of the team will have to be mature enough to realize that it doesn&amp;#8217;t really matter where they put their braces, or how they adorn their member variables.  What matters is that they all use the same conventions.&lt;/p&gt;


	&lt;h2&gt;Consistency&lt;/h2&gt;


	&lt;p&gt;My goal for a good coding standard is to eliminate individual styles in favor of a &lt;em&gt;team&lt;/em&gt; style.  The code produced by a team should look like the &lt;em&gt;team&lt;/em&gt; produced it.  I don&amp;#8217;t want any code recognizable as Bob&amp;#8217;s or Bill&amp;#8217;s.&lt;/p&gt;


	&lt;p&gt;This is not some egalitarian fantasy to hide individuality for the sake of the collective.  Rather, it is a raw necessity.  We&amp;#8217;ve all seen products that look like they were designed by a committee.  We&amp;#8217;ve all used software products where the look and feel changed depending on which part of the application you were using.  The result feels messy, clumsy, inefficient.&lt;/p&gt;


	&lt;p&gt;Individuals, used to their own particular style, will reformat other people&amp;#8217;s code when forced to work on it, further shuffling the patchwork of styles.  Over time, as each team member touches different parts of the code, and team members come and go from the team, the code begins to look like a jumbled Rubick&amp;#8217;s cube of different styles.&lt;/p&gt;


	&lt;p&gt;Code is a product, in and of itself.  The team producing it needs to take pride in the elegance of it&amp;#8217;s structure, and the expressiveness of it&amp;#8217;s presentation.  This kind of pride is infeasible when the code is crisscrossed with a patchwork of individual styles.  Without this pride, there is no drive to keep the overall product clean.  Without that cleanliness, messes build up at the boundaries.  And, as we all know, messes slow us down, and they spread.&lt;/p&gt;


	&lt;h2&gt;Style not Substance&lt;/h2&gt;


	&lt;p&gt;A good coding standard should be about style and form, not about substance.  It should not attempt to legislate good design.  It should not, for example, proscribe &lt;code&gt;goto&lt;/code&gt; or &lt;code&gt;public&lt;/code&gt; variables.  Those rules are part of the body of knowledge that all software developers should have, and are not a matter of style.&lt;/p&gt;


	&lt;p&gt;Coding standards should be about the things that don&amp;#8217;t matter.  They should be about brace placement, naming conventions, the use of blank lines, indentation levels, etc.  A coding standard should describe the way code &lt;em&gt;looks&lt;/em&gt;, not the substance the code is made from.&lt;/p&gt;


	&lt;p&gt;It is important to keep style and substance separate because they matter for different reasons.  Issues of style matter only for consistency.  It does not matter whether your indent depth is 2 or 4, so long as everyone uses the same depth.  It &lt;em&gt;does&lt;/em&gt; matter if you use &lt;code&gt;public&lt;/code&gt; variables inappropriately.&lt;/p&gt;


	&lt;h2&gt;Oral/Code Tradition&lt;/h2&gt;


	&lt;p&gt;Documents that describe coding standards tend to be useless.  They often become a bloated battleground for many different competing ideas.  My advice is to avoid writing them.&lt;/p&gt;


	&lt;p&gt;The real document that describes your coding standard is your code.  If you want to know how to name a variable, look at how they are named in the code.  If you want to know what the standard indent depth is, look in the code.  The code is the living document that describes the coding standard.&lt;/p&gt;


	&lt;p&gt;Oral tradition plays a role as well; especially when communicating issues of substance vs. style.  Teams should make use of code reviews and pair programming to communicate with each other about issues of style and substance.  New members of the team should have frequent exposure to the more seasoned members, so that the issues of style and substance are inculcated with moral authority.  Nothing is quite as persuasive to a young programmer than pairing with the lead programmer and hearing him say: &amp;#8220;We don&amp;#8217;t do things that way; we do things &lt;em&gt;this&lt;/em&gt; way.&amp;#8221;&lt;/p&gt;


	&lt;h2&gt;The Tyranny of Tools&lt;/h2&gt;


	&lt;p&gt;I have seen teams attempt to enforce a style through the use of tools.  Some tools are benign and helpful.  Many IDEs, for example, allow you to specify things like indent level, brace placement, etc.  With a single keystroke you can ensure that a batch of code conforms to the team style.  I use tools like this, an depend upon them.  I make sure that all the team members set their IDEs to use the conventions.&lt;/p&gt;


	&lt;p&gt;Other tools can be more intrusive.  Some tools can act like compilers, generating errors if the style is not adhered to.  Such tools might be useful for an occasional scan of the code; but I think you have to be very careful if you put them into the normal build cycle.&lt;/p&gt;


	&lt;p&gt;Automatic enforcement is power; and power corrupts.  We do not want a well-meaning bureaucrat deciding, one day, to enforce the style that every function argument must have a javadoc comment.  This leads to comments of the form: &lt;code&gt;//required comment.&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;This is not to say that tools like &lt;code&gt;findbugs&lt;/code&gt; and &lt;code&gt;checkstyle&lt;/code&gt; should be avoided.  Indeed, I find them very useful.  However, I think they should be run &lt;em&gt;occasionally&lt;/em&gt; and &lt;em&gt;manually&lt;/em&gt;, not as part of every build.  The issues that these tools discover should be dealt with on a case-by-case basis.&lt;/p&gt;


	&lt;p&gt;Many tools like this allow you to insert special meta-comments that override the warnings.  If these tools are placed in the build process; then the code will become cluttered with these meta-comments.&lt;/p&gt;


	&lt;p&gt;I have a pathological distaste for meta-comments.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Coding style is a matter of team pride and team identity.  Teams should be free to adopt their own styles, and to change those styles as the spirit moves them.  Each member of the team should follow the team style, and work to ensure that the body of code is a consistent statement of that style.  If this sounds too artsy-fartsy, keep in mind that pride of workmanship is a powerful motivator.  We want teams to be proud of their creations.&lt;/p&gt;</description>
      <pubDate>Wed, 18 Apr 2007 08:55:24 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:83b131ff-9495-4097-b789-2df41c03340d</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/04/18/coding-standards</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>What is SOA, really?</title>
      <description>&lt;p&gt;The good news is, you probably already know.  The bad news is, you probably know too much.  This article describes Service Oriented Architecture in a simple and easy to understand way that is devoid of buzzwords and vendor spin.  It&amp;#8217;s the introduction to &lt;span class="caps"&gt;SOA&lt;/span&gt; that you haven&amp;#8217;t been able to find anywhere else.&lt;/p&gt;


	&lt;p&gt;There are things in a business that don&amp;#8217;t change very often.  Gas stations in the U.S., for example, still sell gasoline by the gallon.  Restaurants still sell meals from a menu.  Dentists still sell cleanings every 6 months.   Every business has these aspects that don&amp;#8217;t change very frequently. They often represent a huge part of the business.  We&amp;#8217;ll call these things the _core business functions.&lt;/p&gt;


	&lt;p&gt;There are other things in a business that change very frequently.  Prices, tax rates, catalogs, new products, new marketing campaigns, advertising, new business areas, new customer areas, etc.  Indeed, businesses must be able to change, and change quickly, in order to survive.  And yet, it is vital that those changes do not adversely affect the core business functions.&lt;/p&gt;


	&lt;p&gt;Software developers have known for years that software that changes frequently should be decoupled from software that changes infrequently.  When applied to individual programs and systems this principle is sometimes called &lt;a href="http://www.objectmentor.com/omSolutions/oops_what.html"&gt;&lt;em&gt;The Common Closure Principle&lt;/em&gt;&lt;/a&gt;.  When it is applied to the information management of an enterprise, it is called &lt;span class="caps"&gt;SOA&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;SOA&lt;/span&gt; is the practice of sequestering the &lt;em&gt;core business functions&lt;/em&gt; into independent services that don&amp;#8217;t change frequently.  These services are glorified functions that are called by one or more presentation programs.  The presentation programs are volatile bits of software that present data to, and accept data from, various users.&lt;/p&gt;


	&lt;p&gt;To make this clear, imagine an internet store-front.  Customers use a browser to talk to the presentation software that displays the store&amp;#8217;s website.  The presentation software interprets the gestures of the customer and invokes services that do things like acquiring the data for the current catalog, or registering the customer&amp;#8217;s order.  Note that the services have no idea they are talking to a website.  They could just as well be talking to a thick client, or a 3270 green screen.  They simply accept and return data in a standard format that the web system happens to be able to use.&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s really all there is to it.  The rest of &lt;span class="caps"&gt;SOA&lt;/span&gt; is just a matter of details. At the highest level, &lt;span class="caps"&gt;SOA&lt;/span&gt; is nothing more (and nothing less) than separating changeable elements from unchangeable elements. But why is this important?&lt;/p&gt;


	&lt;p&gt;Consider that internet store-front again.  It presents the user with a catalog, allows the user to move items into, and out of a shopping cart, and accepts the eventual order.  The presentation of these concepts is very volatile.  Marketing people are likely to want to change it frequently.  For example, they might want to change from a shopping cart metaphor to scrollable receipt on the sidebar.  They may wish to present more or less descriptive data in the product list.  They may want to experiment with different colors, font-faces, and layouts.  Indeed, it&amp;#8217;s feasible that they&amp;#8217;ll want to try applets, JStart clients, Ajax, and a myriad of other presentation options.  But none of this has anything to do with the core business functions encapsulated by the services.  Those services that acquire catalogs and register orders remain unchanged despite all the presentation thrashing.  That&amp;#8217;s why the separation is important.  It protects the information processing assets of the business from the constant jitter and spin of the presentation.&lt;/p&gt;


	&lt;p&gt;But presentation is not the only thing that jitters and spins.  So do the &lt;em&gt;business processes&lt;/em&gt;.  Again, consider our store-front.  Perhaps our business has decided to offer fine wines as one of the products it sells.  Selling alcohol requires that the age of the customer be verified.  Let us say that we have a service that provides this verification.  This service must be called for any order that contains alcohol products.  The decision to call this service is neither a presentation decision, nor a service decision.  Rather it is part of the business process for a particular kind of order. Business processes are volatile and they breed like rabbits.  As businesses evolve they add more and more steps and forks to their business processes.  The services being used by those processes don&amp;#8217;t change much; but the pathways through the processes do.  Therefore we want to separate the business process from the services and from the presentation.  Smalltalkers had a name for this separation when it appeared in a single program.  They called it Model-View-Controller.&lt;/p&gt;


	&lt;p&gt;Notice that we have yet to mention even one of the plethora of technologies that are so commonly associated with &lt;span class="caps"&gt;SOA&lt;/span&gt;.  That&amp;#8217;s because &lt;span class="caps"&gt;SOA&lt;/span&gt; is not about any particular technology.  Rather it is a design philosophy that decouples well heeled business functions from volatile processes and presentations.  It is the &lt;span class="caps"&gt;MVC&lt;/span&gt; of enterprise software.&lt;/p&gt;


	&lt;p&gt;In my next blog on this topic, we&amp;#8217;ll look at the next level of detail in an attempt to understand &lt;span class="caps"&gt;HOW&lt;/span&gt; services can be constructed, and how the decoupling of presentation, process, and functions can be achieved.&lt;/p&gt;</description>
      <pubDate>Wed, 11 Apr 2007 07:17:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3c659451-8961-4329-85bd-7b109639ec1a</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2007/04/11/what-is-soa-really</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Service Oriented Architecture</category>
    </item>
    <item>
      <title>Testing GUIs Part II: JSP</title>
      <description>&lt;p&gt;How do you test JSPs &lt;em&gt;outside&lt;/em&gt; the container, with no web server running&amp;#8230;&lt;/p&gt;


	&lt;h1 style="text-align:center;"&gt;Testing &lt;span class="caps"&gt;JSP&lt;/span&gt; pages.&lt;/h1&gt;


	&lt;p&gt;One of the more annoying aspects of working on a web application is that you have to deploy it in order to test it.  This doesn&amp;#8217;t apply to everything of course; if you are careful with your design you can test the business rules in plain old java objects.  You can test database access, interface layers, and stored procedures without the web server running.  But testing the &lt;span class="caps"&gt;GUI&lt;/span&gt; &amp;#8211; the &lt;span class="caps"&gt;HTML&lt;/span&gt; produced from the &lt;span class="caps"&gt;JSP&lt;/span&gt; files &amp;#8211; is very hard to do unless the system has been deployed.&lt;/p&gt;


	&lt;p&gt;Lot&amp;#8217;s of teams fall back on Selenium, Mercury, or other tools that test GUIs &lt;em&gt;through&lt;/em&gt; the web server.  However, this leads to very fragile tests that break when the &lt;em&gt;format&lt;/em&gt; of a page changes, even though it&amp;#8217;s content remains unchanged.  Other teams solve the fragility problem by using Cactus, or the somewhat more primitive tools in &lt;code&gt;HtmlUnit&lt;/code&gt; and &lt;code&gt;HttpUnit&lt;/code&gt;, to inspect the generated &lt;span class="caps"&gt;HTML&lt;/span&gt; delivered to them by the running web application.  We&amp;#8217;ll talk about those techniques in another blog in this series.&lt;/p&gt;


	&lt;p&gt;In this article I will demonstrate a simple technique for testing &lt;span class="caps"&gt;JSP&lt;/span&gt; pages using &lt;code&gt;JUnit&lt;/code&gt; and &lt;code&gt;HtmlUnit&lt;/code&gt;, &lt;em&gt;completely outside&lt;/em&gt; the container.  The advantages of such a technique should be clear.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;You don&amp;#8217;t have to have the container running, or even working.  You can test your JSPs before you have even chosen a particular webserver.  &lt;/li&gt;
		&lt;li&gt;You can spin around the edit/compile/test loop much more quickly because you don&amp;#8217;t have to redeploy after every edit.&lt;/li&gt;
		&lt;li&gt;You can build your JSPs incrementally using Test Driven Development to guide their construction.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The reason that testing JSPs outside the container isn&amp;#8217;t more common is because JSPs are &lt;em&gt;designed&lt;/em&gt; to run inside the container.  The designers never gave a lot of thought to running them outside the container.  So the code generated by the &lt;span class="caps"&gt;JSP&lt;/span&gt; compiler depends on facilities supplied by the container.  Even the tools that generate the &lt;span class="caps"&gt;JSP&lt;/span&gt; code expect that you already have a webapp that can be deployed.  Therefore, in order to run outside the container, you somehow have to fake these facilities and tools.&lt;/p&gt;


	&lt;h3 style="color:blue;text-align:center;"&gt;Dependency Management Rant.&lt;/h3&gt;


&lt;div style="background:lightgrey;color:blue;margin-left:1cm;margin-right:1cm;font-family:times;font-size:150%"&gt;Why do so many designers of frameworks and tools expect you to live within their narrow world view?  Why must I have a fully functional web app before I can &lt;em&gt;compile&lt;/em&gt; my JSPs?  Why must they run within the container?  Information hiding has been one of the foundational tenets of good software design for decades.  When will our industry begin to take it seriously?&lt;/div&gt;

	&lt;h3&gt;Compiling JSPs&lt;/h3&gt;


	&lt;p&gt;The first step to testing JSPs is to compile them into servlets.  To do that, we first have to translate them from &lt;span class="caps"&gt;JSP&lt;/span&gt; format to &lt;span class="caps"&gt;JAVA&lt;/span&gt;.  The &lt;em&gt;apache&lt;/em&gt; project provides a tool named &lt;em&gt;Jasper&lt;/em&gt; that does this.  Invoking &lt;em&gt;Jasper&lt;/em&gt; on a &lt;span class="caps"&gt;JSP&lt;/span&gt; named &lt;code&gt;MyPage.jsp&lt;/code&gt; creates a &lt;span class="caps"&gt;JAVA&lt;/span&gt; source file named &lt;code&gt;MyPage_jsp.java&lt;/code&gt;.  This file can then be compiled into a servlet using your favorite &lt;span class="caps"&gt;IDE&lt;/span&gt;.  (Mine is IntelliJ).&lt;/p&gt;


	&lt;p&gt;Unfortunately &lt;em&gt;Jasper&lt;/em&gt; was not designed to be run from the command line.  Or rather, half of it was, and half of it wasn&amp;#8217;t.  &lt;em&gt;Jasper&lt;/em&gt; does in fact have a main function that takes standard command line arguments.  And it is &lt;em&gt;feasible&lt;/em&gt; to issue the command &lt;code&gt;java org.apache.jasper.JspC&lt;/code&gt; to invoke it.  However, &lt;em&gt;Jasper&lt;/em&gt; expects the environment it runs in to be consistent with the environment of the container.  It expects many the &lt;em&gt;apache&lt;/em&gt; JAR files to be in the &lt;span class="caps"&gt;CLASSPATH&lt;/span&gt;.  It also expects to see a &lt;code&gt;web.xml&lt;/code&gt; file that describes the web application, and it wants to see a &lt;span class="caps"&gt;WEB&lt;/span&gt;-INF directory with all the appropriate web application &lt;span class="caps"&gt;JAR&lt;/span&gt; files and &lt;span class="caps"&gt;TLD&lt;/span&gt; files present.  In short, &lt;em&gt;Jasper&lt;/em&gt; expects there to be a webapp.&lt;/p&gt;


	&lt;p&gt;To make matters worse, there appear to be bugs in the version of &lt;em&gt;Jasper&lt;/em&gt; that I am using (tomcat 5.5.20) that cause it to generate slightly incorrect code unless it is invoked in a manner that is consistent with the way that &lt;span class="caps"&gt;TOMCAT&lt;/span&gt; invokes it.&lt;/p&gt;


The first issue is inconvenient but is just a matter of creating the appropriate directories and files and then invoking &lt;em&gt;Jaser&lt;/em&gt; from &lt;span class="caps"&gt;ANT&lt;/span&gt; so that the classpaths are easy to control.  The second issue required a fair bit of research and experimentation to get working right.  But in the end, the following ant file seems to work quite nicely.  Look at the last task to see the &lt;code&gt;JspC&lt;/code&gt; invocation.
&lt;pre&gt;&lt;code&gt;
&amp;lt;project name="Library" default="compile" basedir="."&amp;gt;
  &amp;lt;property environment="env"/&amp;gt;
  &amp;lt;property name="build.home" value="${basedir}/build"/&amp;gt;
  &amp;lt;property name="build.war.home" value="${build.home}/war"/&amp;gt;
  &amp;lt;property name="build.classes.home" value="${build.home}/classes"/&amp;gt;
  &amp;lt;property name="build.jar.home" value="${build.home}/jars"/&amp;gt;
  &amp;lt;property name="catalina.home" value="${env.CATALINA_HOME}"/&amp;gt;
  &amp;lt;property name="dist.home" value="${basedir}/dist"/&amp;gt;
  &amp;lt;property name="web.home" value="${basedir}/web"/&amp;gt;

  &amp;lt;path id="compile.classpath"&amp;gt;
    &amp;lt;fileset dir="lib"&amp;gt;
      &amp;lt;include name="*.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
    &amp;lt;pathelement location="${catalina.home}/common/classes"/&amp;gt;
    &amp;lt;fileset dir="${catalina.home}/common/endorsed"&amp;gt;
      &amp;lt;include name="*.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
    &amp;lt;fileset dir="${catalina.home}/common/lib"&amp;gt;
      &amp;lt;include name="*.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
    &amp;lt;pathelement location="${catalina.home}/shared/classes"/&amp;gt;
    &amp;lt;fileset dir="${catalina.home}/shared/lib"&amp;gt;
      &amp;lt;include name="*.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;target name="clean"&amp;gt;
    &amp;lt;delete dir="${build.home}"/&amp;gt;
    &amp;lt;delete dir="${dist.home}"/&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="compile"&amp;gt;
    &amp;lt;mkdir dir="${build.classes.home}"/&amp;gt;
    &amp;lt;javac srcdir="${src.home}" destdir="${build.classes.home}" excludes="**/*Test.java"&amp;gt;
      &amp;lt;classpath refid="compile.classpath"/&amp;gt;
    &amp;lt;/javac&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="jar" depends="compile"&amp;gt;
    &amp;lt;mkdir dir="${build.jar.home}"/&amp;gt;
    &amp;lt;jar jarfile="${build.jar.home}/application.jar" basedir="${build.classes.home}" includes="**/application/**/*.class" /&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="dist" depends="jar"&amp;gt;
    &amp;lt;copy todir="${build.war.home}"&amp;gt;
      &amp;lt;fileset dir="${web.home}"/&amp;gt;
    &amp;lt;/copy&amp;gt;

    &amp;lt;copy todir="${build.war.home}/WEB-INF/lib"&amp;gt;
      &amp;lt;fileset dir="${build.jar.home}" includes="*.jar"/&amp;gt;
    &amp;lt;/copy&amp;gt;

    &amp;lt;mkdir dir="${dist.home}"/&amp;gt;
    &amp;lt;jar jarfile="${dist.home}/${app.name}.war" basedir="${build.war.home}"/&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="jsp" depends="dist"&amp;gt;
    &amp;lt;delete dir="${basedir}/testjsp"/&amp;gt;
    &amp;lt;java classname="org.apache.jasper.JspC" fork="true"&amp;gt;
      &amp;lt;arg line="-v -d ${basedir}/testjsp -p com.objectmentor.library.jsp -mapped -compile -webapp ${build.war.home}"/&amp;gt;
      &amp;lt;arg line="WEB-INF/pages/patrons/books/loanRecords.jsp"/&amp;gt;
      &amp;lt;classpath&amp;gt;
        &amp;lt;fileset dir="${catalina.home}/common/lib"&amp;gt;
          &amp;lt;include name="*.jar"/&amp;gt;
        &amp;lt;/fileset&amp;gt;
        &amp;lt;fileset dir="${catalina.home}/server/lib"&amp;gt;
          &amp;lt;include name="*.jar"/&amp;gt;
        &amp;lt;/fileset&amp;gt;
        &amp;lt;fileset dir="${catalina.home}/bin"&amp;gt;
          &amp;lt;include name="*.jar"/&amp;gt;
        &amp;lt;/fileset&amp;gt;
        &amp;lt;fileset dir="${build.war.home}/WEB-INF/lib"&amp;gt;
          &amp;lt;include name="*.jar"/&amp;gt;
        &amp;lt;/fileset&amp;gt;
        &amp;lt;pathelement location="/Developer/Java/Ant/lib/ant.jar"/&amp;gt;
      &amp;lt;/classpath&amp;gt;
    &amp;lt;/java&amp;gt;
    &amp;lt;jar jarfile="${build.jar.home}/jsp.jar" basedir="${basedir}/testjsp" 
         includes="**/jsp/**/*.class" 
      /&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Of course you need all the standard files and directories beneath &lt;code&gt;${build.war.home}&lt;/code&gt; to make this work.  If you are using custom tags in your JSPs, make sure you have all the appropriate &lt;span class="caps"&gt;TLD&lt;/span&gt; files in your &lt;code&gt;tld&lt;/code&gt; directory.&lt;/p&gt;


	&lt;p&gt;Notice that the &lt;span class="caps"&gt;ANT&lt;/span&gt; file invokes the JspC command line, rather than using the JspC ant task that comes with &lt;span class="caps"&gt;TOMCAT&lt;/span&gt;.  All the docs will tell you to use that ant task.  However, I found that it doesn&amp;#8217;t work well when you have custom tags.  Maybe I&amp;#8217;m just dumb, or maybe there is a bug in &lt;em&gt;Jasper&lt;/em&gt;; but the only way I found to get &lt;em&gt;Jasper&lt;/em&gt; to generate the right code was to invoke it from the command line &lt;em&gt;and explicitly pass the &lt;span class="caps"&gt;JSP&lt;/span&gt; files in as command line argument!&lt;/em&gt;.  If you depend on either the ant task or the command line to scan the whole web app for all the &lt;span class="caps"&gt;JSP&lt;/span&gt; files, it seems to generate the wrong code.  (See: &lt;a href="http://blog.objectmentor.com/articles/2007/02/08/jasper-problem-resolved"&gt;this blog&lt;/a&gt;)&lt;/p&gt;


	&lt;p&gt;Now that we have a &lt;span class="caps"&gt;JAVA&lt;/span&gt; file, let&amp;#8217;s take a look at it.  First, here&amp;#8217;s the &lt;span class="caps"&gt;JSP&lt;/span&gt; file.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;%@ page import="com.objectmentor.library.utils.DateUtil" %&amp;gt;
&amp;lt;%@ page import="com.objectmentor.library.web.controller.patrons.LoanRecord" %&amp;gt;
&amp;lt;%@ page import="java.util.List" %&amp;gt;
&amp;lt;%
  List loanRecords = (List) request.getAttribute("loanRecords");
  if (loanRecords.size() &amp;gt; 0) {
%&amp;gt;
&amp;lt;table class="list" id="loanRecords"&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;ID&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Due date&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Fine&amp;lt;/th&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;%
    for (int i = 0; i &amp;lt; loanRecords.size(); i++) {
      LoanRecord loanRecord = (LoanRecord) loanRecords.get(i);
  %&amp;gt;
  &amp;lt;tr class="&amp;lt;%=i%2==0?"even":"odd"%&amp;gt;"&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=loanRecord.id%&amp;gt;
    &amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=loanRecord.title%&amp;gt;
    &amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=DateUtil.dateToString(loanRecord.dueDate)%&amp;gt;
    &amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=loanRecord.fine.toString()%&amp;gt;
    &amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;%
    }
  %&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;%
  }
%&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And here is the code that &lt;em&gt;Jasper&lt;/em&gt; created from this file.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;package com.objectmentor.library.jsp.WEB_002dINF.pages.patrons.books;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import com.objectmentor.library.utils.DateUtil;
import com.objectmentor.library.web.controller.patrons.LoanRecord;
import java.util.List;

public final class loanRecords_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static java.util.List _jspx_dependants;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\n');
      out.write('\n');
      out.write('\n');

  List loanRecords = (List) request.getAttribute("loanRecords");
  if (loanRecords.size() &amp;gt; 0) {

      out.write("\n");
      out.write("&amp;lt;table class=\"list\" id=\"loanRecords\"&amp;gt;\n");
      out.write("  &amp;lt;tr&amp;gt;\n");
      out.write("    &amp;lt;th&amp;gt;ID&amp;lt;/th&amp;gt;\n");
      out.write("    &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;\n");
      out.write("    &amp;lt;th&amp;gt;Due date&amp;lt;/th&amp;gt;\n");
      out.write("    &amp;lt;th&amp;gt;Fine&amp;lt;/th&amp;gt;\n");
      out.write("  &amp;lt;/tr&amp;gt;\n");
      out.write("  ");

    for (int i = 0; i &amp;lt; loanRecords.size(); i++) {
      LoanRecord loanRecord = (LoanRecord) loanRecords.get(i);

      out.write("\n");
      out.write("  &amp;lt;tr class=\"");
      out.print(i%2==0?"even":"odd");
      out.write("\"&amp;gt;\n");
      out.write("    &amp;lt;td&amp;gt;");
      out.print(loanRecord.id);
      out.write("\n");
      out.write("    &amp;lt;/td&amp;gt;\n");
      out.write("    &amp;lt;td&amp;gt;");
      out.print(loanRecord.title);
      out.write("\n");
      out.write("    &amp;lt;/td&amp;gt;\n");
      out.write("    &amp;lt;td&amp;gt;");
      out.print(DateUtil.dateToString(loanRecord.dueDate));
      out.write("\n");
      out.write("    &amp;lt;/td&amp;gt;\n");
      out.write("    &amp;lt;td&amp;gt;");
      out.print(loanRecord.fine.toString());
      out.write("\n");
      out.write("    &amp;lt;/td&amp;gt;\n");
      out.write("  &amp;lt;/tr&amp;gt;\n");
      out.write("  ");

    }

      out.write("\n");
      out.write("&amp;lt;/table&amp;gt;\n");

  }

    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null &amp;#38;&amp;#38; out.getBufferSize() != 0)
          out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3 style="color:blue;text-align:center;"&gt;Rant About Final.&lt;/h3&gt;


&lt;div style="background:lightgrey;color:blue;margin-left:1cm;margin-right:1cm;font-family:times;font-size:150%"&gt;Why is this class declared &lt;code&gt;final&lt;/code&gt;?  What if I had wanted to derive from it to create a testing stub?  Why would &lt;em&gt;anyone&lt;/em&gt; think that generated code is so sacrosanct that I wouldn&amp;#8217;t want to override it.&lt;/div&gt;

	&lt;p&gt;&lt;br/&gt;
A quick perusal of this code tells us that in order to use an instance of this servlet we need an &lt;code&gt;HttpServletRequest&lt;/code&gt; instance, and an &lt;code&gt;HttpServletResponse&lt;/code&gt; instance.&lt;/p&gt;


	&lt;p&gt;Looking a little closer we find that the servlet writes all the &lt;span class="caps"&gt;HTML&lt;/span&gt; to an instance of &lt;code&gt;JspWriter&lt;/code&gt; that it gets from something called a &lt;code&gt;PageContext&lt;/code&gt;.  So, if we could create a mocked up version of &lt;code&gt;JspWriter&lt;/code&gt; that saves all this &lt;span class="caps"&gt;HTML&lt;/span&gt;, and a mocked up version of &lt;code&gt;PageContext&lt;/code&gt; that delivers the mocked &lt;code&gt;JspWriter&lt;/code&gt;, then we could access the written &lt;span class="caps"&gt;HTML&lt;/span&gt; from our tests.&lt;/p&gt;


	&lt;p&gt;Fortunately the &lt;span class="caps"&gt;TOMCAT&lt;/span&gt; designers decoupled the creation of the &lt;code&gt;JspWriter&lt;/code&gt; into a factory named &lt;code&gt;JspFactory&lt;/code&gt;.  That factory can be overridden!  This means that we can get our mocked up &lt;code&gt;JspWriter&lt;/code&gt; into the servlet without modifying the servlet.  All we need is something like the following code:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;  class MockJspFactory extends JspFactory {
    public PageContext getPageContext(Servlet servlet, ServletRequest servletRequest, ServletResponse servletResponse, String s