<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3227963714264318937</id><updated>2024-09-01T05:30:35.996-07:00</updated><category term=".net"/><category term="code"/><category term="ruby"/><category term="functional programming"/><category term="chrome"/><category term="patterns"/><category term="ergonomics"/><category term="geek humor"/><category term="javascript"/><category term="miscellany"/><category term="object orientation"/><category term="rails"/><title type='text'>Coding Patterns</title><subtitle type='html'>If you never make the same mistake twice, you&#39;ll still never run out.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-8898102370264953752</id><published>2009-06-03T18:56:00.000-07:00</published><updated>2009-06-03T20:48:36.481-07:00</updated><title type='text'>Exploring the Fibonacci Numbers</title><content type='html'>Recently I decided to teach myself Haskell by using it to solve &lt;a href=&quot;http://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt; problems. This kills two birds with one stone, since I&#39;ve been wanting to tackle both. Also, it sounded like a lot of fun.&lt;br /&gt;&lt;br /&gt;Project Euler problem #2 is simple enough:&lt;br /&gt;&lt;blockquote&gt;Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:&lt;br /&gt;&lt;br /&gt; 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...&lt;br /&gt;&lt;br /&gt; Find the sum of all the even-valued terms in the sequence which do not exceed four million.&lt;br /&gt;&lt;/blockquote&gt;But, since I&#39;m doing this for personal enrichment I decided to investigate in more detail. I did not notice this before solving it the first time (asking a &lt;a href=&quot;http://stackoverflow.com/questions/736495/haskell-script-running-out-of-space&quot;&gt;stupid question&lt;/a&gt; in the process), but it turns out that every third fibonacci number is even. Furthermore, there is a surprising relationship between every third fibonacci number: &lt;span style=&quot;font-family:courier new;&quot;&gt;f(n) = 4*f(n-3) + f(n-6)&lt;/span&gt;[1]. So it is possible to solve the problem efficiently by enumerating &lt;span style=&quot;font-style: italic;&quot;&gt;just&lt;/span&gt; the even fibonacci numbers. In this post I&#39;ll use &lt;span style=&quot;font-family:courier new;&quot;&gt;g(n)&lt;/span&gt; to denote the nth even fibonacci number. The sequence can be implemented in Haskell, using list comprehension syntax, like so:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; -- g(n) = 4*g(n-1) + g(n-2)&lt;br /&gt; g :: [Integer]&lt;br /&gt; g =  2 : 8 : [ a + 4*b | (a,b) &lt;- zip g (tail fibs2)] &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;But can we do better? I remembered one of Raganwald&#39;s &lt;a href=&quot;http://github.com/raganwald/homoiconic/blob/master/2008-12-12/fibonacci.md&quot;&gt;homoiconic posts&lt;/a&gt; about computing fibonacci numbers efficiently using a matrix multiplication technique (pardon the ascii-art notation):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; m^n, where m = (1 1) , is equivalent to: ( f(n)   f(n-1) )&lt;br /&gt;                (1 0)                     ( f(n-1) f(n-2) )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So the nth fibonacci number is the upper-left element in the matrix obtained by multiplying m by itself n times[2].&lt;br /&gt;&lt;br /&gt;Also interesting is that a &lt;a href=&quot;http://expertvoices.nsdl.org/cornell-cs322/2008/03/25/sum-of-fibonacci-numbers/200/&quot;&gt;source article&lt;/a&gt; of the post at homoiconic gives an efficient algorithm for calculating the &lt;span style=&quot;font-weight: bold;&quot;&gt;sum&lt;/span&gt; of fibonacci numbers using the matrix representation of the sequence. Now we&#39;re getting somewhere! It should be possible to modify the matrix approach so that it generates only the even fibonacci numbers, using the formula described above[3]. And if we can do that, we can calculate their sum efficiently with the provided algorithm.&lt;br /&gt;&lt;br /&gt;You can do exactly that using these two matrices:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; b = (8 2)   m = (4 1)&lt;br /&gt;     (2 0)       (1 0)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;where b is the base case and m is the multiplier. Notice that if you multiply a generic fibonacci matrix (where a,b,c are consecutive even fibonaccis) by m, you get:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; (a b) * (4 1) = (4a+b, a)&lt;br /&gt; (b c)   (1 0)   (4b+c, b)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Which generates the matrix containing the next consecutive even fibonacci number (recall that the nth even fib &lt;span style=&quot;font-family:courier new;&quot;&gt;g(n)&lt;/span&gt; is equal to &lt;span style=&quot;font-family:courier new;&quot;&gt;4*g(n-1) + g(n-2)&lt;/span&gt;, which is &lt;span style=&quot;font-family:courier new;&quot;&gt;4a+b&lt;/span&gt; if &lt;span style=&quot;font-family:courier new;&quot;&gt;a&lt;/span&gt; and &lt;span style=&quot;font-family:courier new;&quot;&gt;b&lt;/span&gt; are the two previous even fibs). Using the matrix b to bootstrap the multiplication (because it contains 2 and 8, the first two even fibs), it follows that &lt;span style=&quot;font-family:courier new;&quot;&gt;b*m&lt;/span&gt; should produce the 3rd even fibonacci number, &lt;span style=&quot;font-family:courier new;&quot;&gt;b*m*m&lt;/span&gt; should produce the fourth, &lt;span style=&quot;font-family:courier new;&quot;&gt;b * m^3&lt;/span&gt; the fifth, and in general:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; g(1) = 2&lt;br /&gt; g(n) = b * m^(n-2) [4]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;So, now we have an equation for using matrix multiplication to compute even fibonacci numbers. How can we use it to efficiently compute the sum of the first n numbers in that sequence? Let&#39;s use a concrete example, n=7. We want to calculate&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; g(1) + g(2) + ... + g(7)  =  2 + b + b*m + b*m^2 + ... + b*m^5&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;factoring out the common b term, we have&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; 2 + b(m^0 + m^1 + m^2 + m^3 + m^4 + m^5)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;where &lt;span style=&quot;font-family:courier new;&quot;&gt;m^0&lt;/span&gt; evaluates to the identity matrix. For convenience, let&#39;s define a function &lt;span style=&quot;font-family:courier new;&quot;&gt;sum(n,m)&lt;/span&gt; that computes  the sum &lt;span style=&quot;font-family:courier new;&quot;&gt;m^0 + ... + m^n&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;/span&gt;, so the above equation can be written &lt;span style=&quot;font-family:courier new;&quot;&gt;2 + b*sum(5,m)&lt;/span&gt; We can see that the bulk of the computation for large values of n will be in calculating each of the matrices &lt;span style=&quot;font-family:courier new;&quot;&gt;m^2, m^3,...,m^n&lt;/span&gt;. But notice the following equivalence:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; m^0 + m^1 + ... + m^5  =  (m^0 + m^1 + m^2) + m^3(m^0 + m^1 + m^2)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;by expanding the equation in this manner, we can calculate &lt;span style=&quot;font-family:courier new;&quot;&gt;sum(5,m)&lt;/span&gt; with considerably less work. Notice the recursive structure of the equation: &lt;span style=&quot;font-family:courier new;&quot;&gt;sum(5,m) = sum(2,m) + m^3 * sum(2,m)&lt;/span&gt;. In general pseudocode:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; sum(n,m) =&lt;br /&gt;   if n == 0  then return i //the identity matrix&lt;br /&gt;   if odd(n)  then let s = sum(floor(n/2), m)&lt;br /&gt;                   return s + m^ceil(n/2) * s&lt;br /&gt;   if even(n) then let s = sum(n/2, m)&lt;br /&gt;                   return s + m^(n/2) * s + m^n&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the &#39;even&#39; case is slightly more complicated because it needs to take into account that the sequence &lt;span style=&quot;font-family:courier new;&quot;&gt;m^0 + ... m^n&lt;/span&gt; is not evenly divisible into two pieces. The algorithm can be further optimized by having our sum function return &lt;span style=&quot;font-family:courier new;&quot;&gt;m^n&lt;/span&gt; &lt;span style=&quot;font-style: italic;&quot;&gt;as well as&lt;/span&gt; the current running sum. This unfortunately obfuscates the algorithm with extra bookkeeping, but it ensures that we aren&#39;t wasting any work from one call to the next, and &lt;span style=&quot;font-family:courier new;&quot;&gt;sum(n,m)&lt;/span&gt; must calculate &lt;span style=&quot;font-family:courier new;&quot;&gt;m^n&lt;/span&gt; or &lt;span style=&quot;font-family:courier new;&quot;&gt;m^n/2&lt;/span&gt; anyway, so it is not much overhead. The &#39;odd&#39; step from the above algorithm would then look something like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; let s, m_exp = sum(floor(n/2), m) //m_exp is m^floor(n/2)&lt;br /&gt; return s + (m_exp * m) * s, m_exp*m_exp*n //return both the sum and m^n&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;One final optimization. Raganwald noted in &lt;a href=&quot;http://github.com/raganwald/homoiconic/blob/master/2008-12-12/fibonacci.md&quot;&gt;his original post&lt;/a&gt; that there is redundancy in the matrix representation, and we can easily re-write our matrices as tuples of 3 elements:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; b = (8, 2, 0)    m = (4, 1, 0)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Multiplication on these tuples is essentially the same as matrix multiplication (details at homoiconic). Putting it all together, we have the final, executable haskell:&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/123403.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;The naive implementation is faster for small n, but once you get above n=5-10k this optimized version overtakes it and never looks back. The full code, including multiple solutions to the project Euler question and benchmarking of the naive implementation against this one, is available &lt;a href=&quot;http://github.com/gmoothart/euler.hs/blob/7b4299af9f222fb5b28da35616874bf599d68ba5/2.hs&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;[1] This is easy to verify yourself. Start with &lt;span style=&quot;font-family:courier new;&quot;&gt;4*f(n-3) + f(n-6)&lt;/span&gt; and keep simplifying until you get &lt;span style=&quot;font-family:courier new;&quot;&gt;f(n)&lt;/span&gt;&lt;br /&gt;[2] For convenience, define the first two fibonacci numbers to be 1,2. Take some time to convince yourself of this, if you like. The computation can be done in O(log n) multiplications (instead of n multiplications) by multiplying in a clever order. See the source articles for details.&lt;br /&gt;[3] &lt;span style=&quot;font-family:courier new;&quot;&gt;g(n) = 4*g(n-1) + g(n-2)&lt;/span&gt;&lt;br /&gt;[4] I&#39;m abusing notation slightly here. Technically this is the 2x2 matrix containing &lt;span style=&quot;font-family:courier new;&quot;&gt;g(n)&lt;/span&gt;, not &lt;span style=&quot;font-family:courier new;&quot;&gt;g(n)&lt;/span&gt; itself. Also, note that when n=2, &lt;span style=&quot;font-family:courier new;&quot;&gt;m^0&lt;/span&gt; evaluates to the identity matrix. &lt;span style=&quot;font-family:courier new;&quot;&gt;b * m^0 = b * i = b&lt;/span&gt;, so no special case is needed for 8.</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/8898102370264953752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/8898102370264953752?isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/8898102370264953752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/8898102370264953752'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2009/06/exploring-fibonacci-numbers.html' title='Exploring the Fibonacci Numbers'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-7322025221417893843</id><published>2008-12-03T21:19:00.000-08:00</published><updated>2008-12-07T22:07:24.416-08:00</updated><title type='text'>Data as code: Storing Configuration in C# &amp; Asp.net</title><content type='html'>I&#39;ve been thinking about the best way to store configuration information in c# since I &lt;a href=&quot;http://codingpatterns.blogspot.com/2007/10/executable-configuration-files.html&quot;&gt;started this blog&lt;/a&gt; more than a year ago. I&#39;m a little embarrased that it&#39;s taken me so long, but I think I&#39;ve hit on the best way of doing it (largely inspired by &lt;a href=&quot;http://ayende.com/Blog/archive/2008/08/21/Enabling-change-by-hard-coding-everything-the-smart-way.aspx&quot;&gt;Ayende&#39;s JFHCI&lt;/a&gt;). Here it is:&lt;br /&gt;&lt;br /&gt;Just use c#&lt;br /&gt;&lt;br /&gt;That&#39;s right! No xml. No web.config. No database. Just use c#.&lt;br /&gt;&lt;br /&gt;The benefits are pretty obvious. The reason configuration is a pain is because you have to spend several lines of code extracting information from some foreign (and usually weakly-typed) source, and loading it into c#. You have to worry about checking for null &quot;just in case&quot;, etc. Keeping everything in c# saves a lot of code and is radically simpler. This approach is popular in scripting languages like Ruby.&lt;br /&gt;&lt;br /&gt;It&#39;s less obvious why the apparent drawbacks aren&#39;t actually drawbacks. Some typical objections:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot;  style=&quot;font-family:inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight: bold;&quot;&gt;But then the configuration is compiled-in. You can&#39;t modify it on the fly!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;This is &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style: italic;&quot;&gt;false&lt;/span&gt; in Asp.net. Although there is a pre-compilation option, ever since 2.0 the default has been to read the source files and compile them into temporary assemblies on the fly. This would be a valid criticism for a WinForms app. But seriously, who uses WinForms?&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight: bold;&quot;&gt;But that&#39;s just hard-coding!&lt;/span&gt;&lt;br /&gt;Yes, it is! Embrace it.&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-weight: bold;&quot;&gt;Storing configuration data in c# is ugly and unintuitive because c# isn&#39;t a good data format.&lt;/span&gt;&lt;br /&gt;True, c# is not lisp or json or xml. Initializing a complex data type the traditional way would involve declaring the type, then initializing it imperatively in a constructor. This separation means that the code does not look like data in the way that traditional config files do.&lt;br /&gt;&lt;br /&gt;But with c# 3.0, I think the language is good enough at representing data to overcome this objection. Collection initializers and object initializers are expressive enough that you should never need a constructor to do initialization.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Let&#39;s run with this a little bit. Say you need to add a list of email addresses for generating error emails. Just pop open &lt;span class=&quot;Apple-style-span&quot;  style=&quot;font-family:&#39;Courier New&#39;,Courier,monospace;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;  style=&quot;font-size:small;&quot;&gt;config.cs&lt;/span&gt;&lt;/span&gt;, and type this:&lt;br /&gt;&lt;/div&gt;&lt;code style=&quot;font-family: courier new;&quot;&gt;&lt;br /&gt;public static var ErrorEmails = new List&amp;lt;string&amp;gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;joe@bob.com&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;jane@bob.com&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;julie@bob.com&quot;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That&#39;s not so bad, is it? Clear, strongly typed, native c#, at least as easy to modify on-the-fly as xml or database configuration. Let&#39;s take a more complicated example: Suppose our application allows the user to submit different types of Requests, and each Request has a bunch of metadata associated with it: a code, request group, name, and description. Also suppose we want to look up the Request metadata given a code. We can do something like this:&lt;br /&gt;&lt;code style=&quot;font-family:courier new;&quot;&gt;&lt;br /&gt;public static var Codes = new Dictionary&amp;lt;string, CodeData&amp;gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &quot;Code1&quot;, new CodeData { Group=&quot;...&quot;, Name=&quot;...&quot;, Desc=&quot;...&quot; } },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &quot;Code2&quot;, new CodeData { Group=&quot;...&quot;, Name=&quot;...&quot;, Desc=&quot;...&quot; } },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &quot;Code3&quot;, new CodeData { Group=&quot;...&quot;, Name=&quot;...&quot;, Desc=&quot;...&quot; } },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ &quot;Code4&quot;, new CodeData { Group=&quot;...&quot;, Name=&quot;...&quot;, Desc=&quot;...&quot; } }&lt;br /&gt;}&lt;/code&gt;&lt;div&gt;That is the sort of information that I probably would have placed in a database before. The benefits of doing it this way should be obvious. Instead of dropping down into SQL to query the data and loading it into c#, I can now start off in c#. I can use LINQ to easily query the data to return anything I need.&lt;br /&gt;&lt;br /&gt;Yes, it&#39;s unconventional. Do it anyway.&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/7322025221417893843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/7322025221417893843?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/7322025221417893843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/7322025221417893843'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2008/12/data-as-code-storing-configuration-in-c.html' title='Data as code: Storing Configuration in C# &amp; Asp.net'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-1122064890582972075</id><published>2008-06-03T20:23:00.000-07:00</published><updated>2008-07-04T16:25:36.223-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Javascript Dom Builder</title><content type='html'>I hate the Dom. So I decided to fix it.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;basic usage&lt;/h4&gt;&lt;br /&gt;&lt;pre style=&quot;COLOR: #ddbb00;font-family:Consolas, Monaco, &#39;Lucida Console&#39;, &#39;Courier New&#39;, monospaced;font-size:10pt;background-color:#000000;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   1 &lt;/span&gt;        &lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;domBuilder&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;$&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;basic&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   2 &lt;/span&gt;        &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;id&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;div1&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; style&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;height:50px;border-style:solid;border-width:4px;padding:1px;&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   3 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;style&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;float: left;&#39;&lt;/span&gt; &lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   4 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;purple, &#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   5 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;href&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;http://www.google.com&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;google&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   6 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   7 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;style&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;float: right;&#39;&lt;/span&gt; &lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   8 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;cat&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   9 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Adding event handlers&lt;/h4&gt;&lt;br /&gt;&lt;pre style=&quot;COLOR: #ddbb00;font-family:Consolas, Monaco, &#39;Lucida Console&#39;, &#39;Courier New&#39;, monospaced;font-size:10pt;background-color:#000000;&quot;   &gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   1 &lt;/span&gt;        &lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;domBuilder&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;$&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;event&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   2 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   3 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;some text&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   4 &lt;/span&gt;             &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;input&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;id&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;evt_test&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;text&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   5 &lt;/span&gt;               &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;blur&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;FONT-WEIGHT: bold;color:#ffed8a;&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;() {&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;alert&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;blur!!&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;);})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   6 &lt;/span&gt;               &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;focus&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;FONT-WEIGHT: bold;color:#ffed8a;&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;() {&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;alert&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;focus!&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;)})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   7 &lt;/span&gt;             &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;using custom (not pre-defined) tags&lt;/h4&gt;&lt;pre style=&quot;COLOR: #ddbb00;font-family:Consolas, Monaco, &#39;Lucida Console&#39;, &#39;Courier New&#39;, monospaced;font-size:10pt;background-color:#000000;&quot;   &gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   30 &lt;/span&gt;        &lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;domBuilder&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;$&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;custom&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;), [&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;select&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;optgroup&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;option&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;])&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   31 &lt;/span&gt;        &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;select&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;id&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;select_test&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   32 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;optgroup&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;label&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;swedish cars&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   33 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;option&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;v&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;Volvo&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   34 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;option&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;s&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;Saab&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   35 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;option&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   36 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   37 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;optgroup&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;label&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;german cars&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   38 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;option&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;m&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;Mercedes&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   39 &lt;/span&gt;            &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;option&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;}).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#dedede;&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&#39;Audi&#39;&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#898989;&quot;&gt;   40 &lt;/span&gt;          &lt;span style=&quot;color:#ababab;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;FONT-WEIGHT: bold;color:#ddbb00;&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#ababab;&quot;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Essentially the &lt;span style=&quot;font-family:courier new;&quot;&gt;DomBuilder&lt;/span&gt; function takes a dom element and returns an object that lets you add nodes to it easily. The most common html tags are pre-defined. You can also insert an arbitrary tag with the &#39;add&#39; method: &lt;span style=&quot;font-family:courier new;&quot;&gt;.add(&#39;foo&#39;, {id: &#39;foo&#39;}&lt;/span&gt;, although the expected usage is to tell dom-builder about the custom tags you want to use and let it create helper methods for you, as in the third example above. One gotcha of the fluent-interface style is that you may be tempted to leave off the &lt;span style=&quot;font-family:courier new;&quot;&gt;end()&lt;/span&gt; calls - proper indentation can make the code look correct when it is not. &lt;span style=&quot;font-family:courier new;&quot;&gt;end()&lt;/span&gt; is only optional at the end of the method chain - in other words, final &lt;span style=&quot;font-family:courier new;&quot;&gt;end()&lt;/span&gt;s are implicit.&lt;/p&gt;&lt;p&gt;One benefit of the fluent interface style is that it is easy to extend. For example, you could add a &lt;span style=&quot;font-family:courier new;&quot;&gt;css() &lt;/span&gt;method, some sort of auto-close method or parameter (analagous to &lt;span style=&quot;font-family:courier new;&quot;&gt;&amp;lt;tag /&amp;gt;&lt;/span&gt;) so that an explicit &lt;span style=&quot;font-family:courier new;&quot;&gt;end()&lt;/span&gt; is not required, etc.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;dom-builder is built on top of the YUI library, and is inspired slightly by Ruby&#39;s &lt;a href=&quot;http://builder.rubyforge.org/&quot;&gt;xml-builder&lt;/a&gt;. It is not an original idea - it has been &lt;a href=&quot;http://www.eng.ajaxian.com/archives/dom-builder-a-nicer-dom&quot;&gt;done&lt;/a&gt; &lt;a href=&quot;http://github.com/madrobby/scriptaculous/wikis/builder&quot;&gt;before&lt;/a&gt; in similar ways and by smarter people. Still, it&#39;s always helpful to work something out for yourself, and from an aesthetic point of view I prefer my API decisions over those solutions anyway. Examples, tests, and source are available &lt;a href=&quot;http://code.google.com/p/gabe-lib/source/browse/trunk/js-dom-builder/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/1122064890582972075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/1122064890582972075?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1122064890582972075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1122064890582972075'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2008/06/javascript-dom-builder.html' title='Javascript Dom Builder'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-1673065189407891190</id><published>2008-04-18T21:40:00.000-07:00</published><updated>2008-04-22T21:32:29.725-07:00</updated><title type='text'>Pluggable Type Systems and the future of Programming Languages</title><content type='html'>Programming languages come and go at an astonishing pace, and few enjoy the spotlight of geek popularity for long. Heck, &lt;span style=&quot;font-style: italic;&quot;&gt;Java&lt;/span&gt; used to be cool. And so did Perl. The pace at which technology moves sometimes makes me wonder if we are actually getting anywhere, or if we are just moving to be moving.  There&#39;s a sort of elite snobbery among hackers that shuns popularity. Did Java fall out of favor simply because it became too popular?&lt;br /&gt;&lt;br /&gt;Although I certainly wouldn&#39;t put it past some corners of hackerdom to shun something just because it is popular, I do not think this is what is happening in the mad race for newer and shinier programming languages. After all, Isn&#39;t Java &lt;span style=&quot;font-style: italic;&quot;&gt;better&lt;/span&gt; than c++? And aren&#39;t Python and Ruby &lt;span style=&quot;font-style: italic;&quot;&gt;better&lt;/span&gt; than Perl? And isn&#39;t Javascript... well, never mind about that.&lt;br /&gt;&lt;br /&gt;The point is that languages don&#39;t fall out of favor among hackers simply because they become popular. They fall out of favor because hackers are very promiscuous about their programming languages and move on to something better when they find it. And since there is a whole lot of creativity in that community, something better comes along pretty regularly.&lt;br /&gt;&lt;br /&gt;I don&#39;t expect innovation to continue at this pace forever, though. Many of the good ideas making their way into the mainstream today were invented in academia 30 or 60 years ago. Eventually the popular languages are going to converge around a more-or-less standard set of features, and there will be less need for such rapid innovation.&lt;br /&gt;&lt;br /&gt;Encouragingly, I think we&#39;re catching a glimpse of one area around which programming languages are going to converge in the near future: &lt;a href=&quot;http://www.google.com/search?q=pluggable+type+systems&quot;&gt;pluggable type systems&lt;/a&gt; (that is, optional type systems which are dynamic in nature and can be removed, modified, or extended). This is happening from both directions: dynamic languages are adding optional static features, and static languages are becoming more dynamic. Consider the signs:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://www.ecmascript.org&quot;&gt;Javascript 2&lt;/a&gt; will have optional typing&lt;/li&gt;&lt;li&gt;Python 3 will have &lt;a href=&quot;http://www.python.org/dev/peps/pep-3107/&quot;&gt;function annotations&lt;/a&gt;, which have no semantic meaning on their own but can be interpreted by 3rd-party libraries.&lt;/li&gt;&lt;li&gt;One of the JRuby developers is working on a &lt;a href=&quot;http://headius.blogspot.com/search?q=duby&quot;&gt;toy Ruby dialect&lt;/a&gt; that adds type annotation to the language. Interestingly, the type annotations are valid Ruby and would just be ignored (or immediately garbage-collected) by a normal Ruby interpreter - giving them a pluggable flavor.&lt;/li&gt;&lt;li&gt;The next version of c# will support &lt;a href=&quot;http://blogs.msdn.com/charlie/archive/2008/01/25/future-focus.aspx&quot;&gt;dynamic method lookup&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.lambdassociates.org/qilisp.htm&quot;&gt;Qi&lt;/a&gt;, an interesting lisp-like language, has an optional type system.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://boo.codehaus.org/&quot;&gt;Boo&lt;/a&gt;, a statically-typed scripting language for the CLR, has a &quot;duck&quot; type which allows method lookups to be done at runtime.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Granted, some of these examples are obscure. But the number which are not is pretty remarkable. It shows that with regard to type systems, we as community of programmers are learning to be &lt;a href=&quot;http://ola-bini.blogspot.com/2008/04/pragmatic-static-typing.html&quot;&gt;pragmatic&lt;/a&gt; rather than purist. I think this is a real sign of maturity because it means we are transcending the static/dynamic holy wars. The Java design philosophy of  ruthless consistency is no more. We&#39;ve been down that road, and we don&#39;t like what we saw. We know that &lt;a href=&quot;http://weblog.raganwald.com/2007/10/too-much-of-good-thing-not-all.html&quot;&gt;not everything is an object&lt;/a&gt; and that gee, it would be nice to be able to &lt;a href=&quot;http://gafter.blogspot.com/2007/05/removing-language-features.html&quot;&gt;remove checked exceptions&lt;/a&gt; if we wanted to. And although I don&#39;t know where we will end up, I do know that it will be better than where we are today.</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/1673065189407891190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/1673065189407891190?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1673065189407891190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1673065189407891190'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2008/04/pluggable-type-systems-and-future-of.html' title='Pluggable Type Systems and the future of Programming Languages'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-1476946128716544448</id><published>2008-01-28T08:05:00.001-08:00</published><updated>2008-01-28T08:15:08.193-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ergonomics"/><title type='text'>Switching Keyboard Layouts: Colemak</title><content type='html'>&lt;p&gt;In an effort to preserve my hands, I&#39;ve switched my keyboard layout from the contorted-and-inexplicable Qwerty to the comfortable, ergonomic upstart &lt;a href=&quot;http://colemak.com/&quot;&gt;Colemak&lt;/a&gt;. I spent a day using &lt;a href=&quot;http://www.google.com/search?hl=en&amp;amp;q=dvorak+keyboard&quot;&gt;Dvorak&lt;/a&gt; before doing some more research and settling on Colemak. Both layouts require startlingly less hand motion than Qwerty, and greatly reduce awkward finger motions. The best way to get a feel for the magnitude of the difference is to go to &lt;a href=&quot;http://hi-games.net/typing-test/&quot;&gt;this typing-test site&lt;/a&gt; and replay one of the high scores. You can toggle between Qwerty, Dvorak, and Colemak, and see visually how much your hands would be moving in that layout. &lt;a href=&quot;http://colemak.com/Compare&quot;&gt;This applet&lt;/a&gt; will let you compare layout statistics on a given piece of text.&lt;/p&gt;  &lt;p&gt;All in all, I think Colemak is the clear winner over Dvorak. Here they are, for reference:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Dvorak:&lt;/h3&gt;  &lt;p&gt;&lt;img src=&quot;http://www.mwbrooks.com/dvorak/layout.gif&quot; width=&quot;550px;&quot; /&gt; &lt;/p&gt;  &lt;h3&gt;Colemak:&lt;/h3&gt;  &lt;p&gt;&lt;img src=&quot;http://colemak.com/wiki/images/e/ef/Colemak_fingers.png&quot; width=&quot;550px;&quot; /&gt; &lt;/p&gt;  &lt;p&gt;I was initially skeptical of Colemak because one of its main selling points is that it is much more similar to Qwerty than Dvorak is, and therefore easier to learn. I was afraid that it might have sacrificed ergonomics for similarity to Qwerty. This is not the case. Dvorak is optimized for alternating work between the left and right hand, and using it felt like a delicate left-right dance. Colemak on the other hand is optimized for grouping common letter pairs (digraphs) together so that you can hit them with one smooth hand motion. I find this more comfortable than the focus on alternation in Dvorak. Colemak also remedies two minor annoyances I had with Dvorak: &amp;quot;R&amp;quot; isn&#39;t on the home row, and &amp;quot;L&amp;quot; is delegated to the right pinkie, making it harder to reach than it&#39;s frequency warrants. Other Colemak benefits:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Caps Lock is mapped to backspace. Brilliant!&lt;/li&gt;    &lt;li&gt;The punctuation keys are in the same place as in Qwerty. I didn&#39;t find the top-row Dvorak placement any worse, but I didn&#39;t find it any better either, and this is one less thing to relearn.&lt;/li&gt;    &lt;li&gt;The Z/X/C/V keys don&#39;t move, so the most common shortcut keys don&#39;t need to be relearned.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pretty much the only thing I liked better about Dvorak is the convenient placement of the &amp;quot;-/_&amp;quot; key, which as a programmer I use a lot. But nothing is perfect, I guess.&lt;/p&gt;  &lt;p&gt;One of the most interesting (to me) aspects of switching was getting an insight into how the body learns to type quickly (I got up to about 80 WPM in Qwerty, although typing that fast is so uncomfortable that I rarely do it). It happens largely by burning common words and letter combinations into your muscles, not by stringing together individual keys. After almost 3 weeks on Colemak, I find that my most common mistakes aren&#39;t on particular letters but in particular &lt;em&gt;contexts&lt;/em&gt;. I may get &amp;quot;I&amp;quot; right most of the time, but I still invariably type the Qwerty &amp;quot;I&amp;quot; in certain words. Because of the Colemak emphasis on digraphs, I get the feeling that as I burn it into my fingers it will make for more comfortable and smoother typing.&lt;/p&gt;  &lt;p&gt;All things considered I&#39;m very glad I made the switch, and I&#39;d recommend it to anyone who makes a living on a keyboard. Your hands have to last you the rest of your life, and Colemak will help them to.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/1476946128716544448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/1476946128716544448?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1476946128716544448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1476946128716544448'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2008/01/switching-keyboard-layouts-colemak.html' title='Switching Keyboard Layouts: Colemak'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-2175156615587766598</id><published>2008-01-04T13:13:00.001-08:00</published><updated>2008-01-04T13:18:05.688-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><title type='text'>Code Organization</title><content type='html'>&lt;p&gt;Even though I read Steve McConnell&#39;s seminal &lt;em&gt;&lt;a href=&quot;http://cc2e.com/&quot;&gt;Code Complete&lt;/a&gt;&lt;/em&gt; years ago, there is one piece of advice in it that I use every day. In the section &lt;em&gt;Making Code Read from Top to Bottom&lt;/em&gt;, he presents a poorly organized code fragment and reorganizes it:&lt;/p&gt;  &lt;div style=&quot;font-weight: bold; font-size: 12pt; background: black; overflow: auto; color: #ffc56c; font-family: consolas, &amp;#8216;lucida console&amp;#8217;, &amp;#8216;courier new&amp;#8217;, monospace&quot;&gt;   &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: silver&quot;&gt;/* C Example of Bad Code That Jumps Around */&lt;/span&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeAnnualMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeAnnualMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputerAnnualAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: silver&quot;&gt;/* C Example of Good, Sequential Code That Reads from Top to Bottom */&lt;/span&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeAnnualMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintMarketingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MarketingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeAnnualMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintMSIData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;MSIData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 29&lt;/span&gt;&amp;#160;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 30&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;InitAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 31&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputeQuarterlyAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 32&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;ComputerAnnualAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;font-weight: normal; color: #2b91af&quot;&gt;&amp;#160;&amp;#160; 33&lt;/span&gt;&amp;#160;&lt;span style=&quot;color: #fffafa&quot;&gt;PrintAccountingData&lt;/span&gt;( &lt;span style=&quot;color: #fffafa&quot;&gt;AccountingData&lt;/span&gt; );&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;McConnell explains why the refactored layout is superior:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;This code is better in several ways. References to each variable are &amp;quot;localized&amp;quot;: they&#39;re kept close together. Values are assigned to variables close to where they&#39;re used. The number of lines of code in which the variables are &amp;quot;live&amp;quot; is small. And perhaps most important, the code now looks as if it could be broken into separate routines for marketing, MIS, and accounting data. The first code fragment gave no hint that such a decomposition was possible.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The idea is to structure your code so that statements are grouped by the data they operate on, not the operations they perform. I&#39;m often tempted to organize code so that grouped statements &amp;quot;line up&amp;quot; as in the first example. This may be something that I have particular trouble with because a lot of my early coding was done in Pascal, which enforces poor layout in the language syntax. Variables must all be declared in one place, at the start of a method. In class definitions fields must come before properties and methods, when it is clearly better to group related private fields, properties, and getter/setter methods together. &lt;/p&gt;  &lt;p&gt;At any rate, this idea can be extended beyond code layout. Just one example: the Rails directory structure is organized by file kind. All the models go in one directory, all the controllers go in another, the tests in another, etc. This is analogous to grouping statements so they &amp;quot;line up&amp;quot;, and is exactly backwards. The file groups that belong together logically are those which all relate to the same concept. Folders in Rails ought to be organized by model name (or controller name, for model-less controllers). One folder should hold the model, its controller, tests, and views. &lt;em&gt;This&lt;/em&gt; is the important relationship between files: what data they operate on, not what type of file they are.&lt;/p&gt;  &lt;p&gt;Because developing in Rails forces you to frequently jump between related files in different directories, every Rails editor or IDE has shortcuts to help you do it. Essentially these editors are plastering the proper logical organization on top of the Rails folder structure, which alleviates the problem. The uniform structure imposed by the the fixed folder layout in Rails is a stroke of genius, but having to use a nonstandard, editor-specific abstraction layer on top of it for actual development limits its awesomeness somewhat.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/2175156615587766598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/2175156615587766598?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/2175156615587766598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/2175156615587766598'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2008/01/code-organization.html' title='Code Organization'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-4479583346949121168</id><published>2007-12-24T11:26:00.001-08:00</published><updated>2008-07-04T16:25:36.223-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><category scheme="http://www.blogger.com/atom/ns#" term="patterns"/><title type='text'>Encapsulating the Lazy-Load Pattern</title><content type='html'>&lt;p&gt;In a previous post I suggested a helper method to &lt;a href=&quot;http://codingpatterns.blogspot.com/2007/10/exploiting-closures-what-i-learned-from.html&quot;&gt;wrap the Lazy-Load pattern&lt;/a&gt;. I&#39;m now convinced that this was the wrong approach to take. For the specific case I mentioned (lazy-loading a property value), the straightforward test for nil is irreducibly simple. Trying to wrap it in a generic procedure introduces more complexity than it alleviates.&lt;/p&gt;  &lt;p&gt;For the more general case in which you have a value which you don&#39;t want to compute more than once, the correct pattern is to create a generic wrapper class or method which bolts added functionality onto the type in question. This is a common pattern in the .Net framework: some examples are &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/b3h38hb0.aspx&quot;&gt;Nullable&amp;lt;T&amp;gt;&lt;/a&gt;&lt;/span&gt;, &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/bb308966.aspx&quot;&gt;Expression&amp;lt;T&amp;gt;&lt;/a&gt;&lt;/span&gt;, and &lt;a href=&quot;http://blogs.remobjects.com/blogs/mh/2007/12/04/p193&quot;&gt;&lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Future&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/a&gt; in the next version of Chrome.&lt;/p&gt;  &lt;p&gt;So what we want is some sort of &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Lazy&lt;t&gt;&lt;/t&gt;&lt;/span&gt; which will wrap the lazy evaluation. There is one &lt;a href=&quot;http://msdn2.microsoft.com/en-us/vcsharp/bb870976.aspx&quot;&gt;example implementation here&lt;/a&gt;. You can consult the article for the (mostly trivial) implementation details. But it enables you to write code like this:&lt;/p&gt;&lt;br /&gt;&lt;div style=&quot;font-family: Consolas, ‘Lucida Console’, ‘Courier New’, monospace; font-size: 12pt; color: #ffc56c; background: black; font-weight: bold; overflow:auto;&quot;&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #cc7832;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;a&lt;/span&gt; = &lt;span style=&quot;color: #6897bb;&quot;&gt;22&lt;/span&gt;, &lt;span style=&quot;color: #fffafa;&quot;&gt;b&lt;/span&gt; = &lt;span style=&quot;color: #6897bb;&quot;&gt;20&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #cc7832;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt; = &lt;span style=&quot;color: #fffafa;&quot;&gt;Lazy&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;New&lt;/span&gt;(() =&amp;gt; {&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;(&lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;calculating...&quot;&lt;/span&gt;);&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #cc7832;&quot;&gt;new&lt;/span&gt; { &lt;span style=&quot;color: #fffafa;&quot;&gt;Mul&lt;/span&gt; = &lt;span style=&quot;color: #fffafa;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;b&lt;/span&gt;, &lt;span style=&quot;color: #fffafa;&quot;&gt;Sum&lt;/span&gt; = &lt;span style=&quot;color: #fffafa;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;b&lt;/span&gt; };&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;});&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;(&lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;Mul = {0}, Sum = {1}&quot;&lt;/span&gt;,&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Mul&lt;/span&gt;, &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Sum&lt;/span&gt;);&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The block passed to &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Lazy.New&lt;/span&gt; is evaluated only once, in the first call to &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;lazy.value&lt;/span&gt;. The &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Lazy.New&lt;/span&gt; function is a helper which basically exists to trick the compiler into providing type inference for us so that we don&#39;t have to specify the generic parameter.&lt;/p&gt;  &lt;p&gt;The main downside to this is that &lt;code&gt;Lazy&amp;lt;T&amp;gt;&lt;/code&gt; is a custom class. In order for a function to accept one of these lazy objects as a parameter, it needs to be written specifically with that type in mind. Wouldn&#39;t it be cleaner if &lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Lazy.New&lt;/span&gt;&lt;/span&gt; returned an &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Func&amp;lt;T&amp;gt;&lt;/span&gt; delegate instead?&lt;/p&gt;  &lt;p&gt;Well, it can. What we basically want to do is &lt;a href=&quot;http://en.wikipedia.org/wiki/Memoization&quot;&gt;memoize&lt;/a&gt; a function of no arguments. And for that the &lt;a href=&quot;http://blogs.msdn.com/wesdyer/archive/2007/01/26/function-memoization.aspx&quot;&gt;solution presented here&lt;/a&gt; is much cleaner:&lt;/p&gt;&lt;br /&gt;&lt;div style=&quot;font-family: Consolas, ‘Lucida Console’, ‘Courier New’, monospace; font-size: 12pt; color: #ffc56c; background: black; font-weight: bold; overflow:auto;&quot;&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #cc7832;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #cc7832;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #ffc66d;&quot;&gt;FuncLib&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #cc7832;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #6897bb;&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Memoize&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;this&lt;/span&gt; &lt;span style=&quot;color: #6897bb;&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;f&lt;/span&gt;)&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #fffafa;&quot;&gt;R&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;value&lt;/span&gt; = &lt;span style=&quot;color: #cc7832;&quot;&gt;default&lt;/span&gt;(&lt;span style=&quot;color: #fffafa;&quot;&gt;R&lt;/span&gt;);&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;hasValue&lt;/span&gt; = &lt;span style=&quot;color: #cc7832;&quot;&gt;false&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;return&lt;/span&gt; () =&amp;gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;if&lt;/span&gt; (!&lt;span style=&quot;color: #fffafa;&quot;&gt;hasValue&lt;/span&gt;)&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #fffafa;&quot;&gt;hasValue&lt;/span&gt; = &lt;span style=&quot;color: #cc7832;&quot;&gt;true&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #fffafa;&quot;&gt;value&lt;/span&gt; = &lt;span style=&quot;color: #fffafa;&quot;&gt;f&lt;/span&gt;();&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;value&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Let&#39;s walk through this. &lt;span style=&quot;;font-family:courier new;font-size:85%;&quot;  &gt;Memoize&amp;lt;T&amp;gt;&lt;/span&gt; takes a function with no parameters, and returns a function of the same signature. Here&#39;s where it gets sneaky: whereas &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Lazy&amp;lt;T&amp;gt;&lt;/span&gt; defined a new class to hold the cached function value, &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Memoize&amp;lt;T&amp;gt;&lt;/span&gt; takes advantage of the fact that closures have access to their containing scope. The return function carries around a pointer to the local variables &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;value&lt;/span&gt; and &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;hasValue&lt;/span&gt;, which allows it to remember if the result has been calculated or not. &lt;/p&gt;  &lt;p&gt;As an added bonus &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Memoize&amp;lt;T&amp;gt;&lt;/span&gt; is an extension method, which allows us to use it in two ways: either as a helper method similar to &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Lazy.New&lt;/span&gt;, or as a method on a &lt;span style=&quot;;font-family:Courier New;font-size:85%;&quot;  &gt;Func&amp;lt;T&amp;gt;&lt;/span&gt; object. We can then create lazily-evaluated functions like so:&lt;/p&gt;&lt;br /&gt;&lt;div style=&quot;font-family: Consolas, ‘Lucida Console’, ‘Courier New’, monospace; font-size: 12pt; color: #ffc56c; background: black; font-weight: bold; overflow:auto;&quot;&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: silver;&quot;&gt;//using Memoize as a helper method, with type inference&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #cc7832;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt; = &lt;span style=&quot;color: #ffc66d;&quot;&gt;FuncLib&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Memoize&lt;/span&gt;( () =&amp;gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;( &lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;calculating...&quot;&lt;/span&gt; );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #6897bb;&quot;&gt;42&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;} );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: silver;&quot;&gt;//using Memoize as an extension method, &lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: silver;&quot;&gt;//&amp;nbsp; but without type inference&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #6897bb;&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;lazy2&lt;/span&gt; = ( () =&amp;gt;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;( &lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;calculating...&quot;&lt;/span&gt; );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #cc7832;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #6897bb;&quot;&gt;42&lt;/span&gt;;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;} );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #fffafa;&quot;&gt;lazy2&lt;/span&gt; = &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy2&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Memoize&lt;/span&gt;();&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;( &lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;starting...&quot;&lt;/span&gt; );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;( &lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;result = {0}&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt;() );&lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;WriteLine&lt;/span&gt;( &lt;span style=&quot;color: #a5c25c;&quot;&gt;&quot;result (again) = {0}&quot;&lt;/span&gt;, &lt;span style=&quot;color: #fffafa;&quot;&gt;lazy&lt;/span&gt;() ); &lt;/p&gt;&lt;p style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: #2b91af; font-weight: normal;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #ffc66d;&quot;&gt;Console&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #fffafa;&quot;&gt;Read&lt;/span&gt;();&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;This can&#39;t be beaten for elegance, in my opinion.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/4479583346949121168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/4479583346949121168?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/4479583346949121168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/4479583346949121168'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/12/encapsulating-lazy-load-pattern.html' title='Encapsulating the Lazy-Load Pattern'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-1663632827362397796</id><published>2007-10-26T12:06:00.000-07:00</published><updated>2007-10-26T12:36:14.265-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="object orientation"/><title type='text'>Thinking Well about OO Design</title><content type='html'>Good object-oriented design is hard. Unfortunately, most people don&#39;t know how hard it is. The best way to improve your OO design is to ask hard questions about it. And the best way to know which questions to ask is to read people who have thought deeply about where OO sits in the design space: what it is good at and what it is not good at, what you can do to minimize the effects of the things it is not good at, and how best to use the tools it gives you. &lt;a href=&quot;http://www.amazon.com/dp/0201633612/&quot;&gt;Design Patterns&lt;/a&gt; is a great place to start (read it more than once), and I&#39;ve found these recent articles to be helpful in getting me to think well about OO design:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.berniecode.com/writing/inheritance/&quot;&gt;Inheritance is Evil&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://weblog.raganwald.com/2007/10/too-much-of-good-thing-not-all.html&quot;&gt;Not All Functions should be Object Methods&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/1663632827362397796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/1663632827362397796?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1663632827362397796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/1663632827362397796'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/thinking-well-about-oo-design.html' title='Thinking Well about OO Design'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-6192075255472957397</id><published>2007-10-26T09:31:00.000-07:00</published><updated>2007-10-26T12:00:33.131-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="geek humor"/><title type='text'>Reflection joke</title><content type='html'>In the spirit of Steve Yegge&#39;s &lt;a href=&quot;http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html&quot;&gt;Kingdom of Nouns&lt;/a&gt;, Scott Bellware &lt;a href=&quot;http://codebetter.com/blogs/scott.bellware/archive/2007/10/02/169121.aspx&quot;&gt;pokes fun&lt;/a&gt; at the .Net reflection API compared to Ruby&#39;s:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;I say &lt;span style=&quot;font-family:courier new;&quot;&gt;:tomato&lt;/span&gt;&lt;br /&gt;You say &lt;span style=&quot;font-family:courier new;&quot;&gt;typeof(Fruit).GetField(&#39;tomato&#39;, BindingFlags.Instance | BindingFlags.Public)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;I say &lt;span style=&quot;font-family:courier new;&quot;&gt;:potato&lt;/span&gt;&lt;br /&gt;You say &lt;span style=&quot;font-family:courier new;&quot;&gt;typeof(Tuber).GetField(&#39;potato&#39;, BindingFlags.Instance | BindingFlags.Public)&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot;font-family: courier new;&quot;&gt;:tomato&lt;br /&gt;typeof(Fruit).GetField(&#39;tomato&#39;, BindingFlags.Instance | BindingFlags.Public)&lt;/p&gt; &lt;p style=&quot;font-family: courier new;&quot;&gt;:potato&lt;br /&gt;typeof(Tuber).GetField(&#39;potato&#39;, BindingFlags.Instance | BindingFlags.Public)&lt;/p&gt; &lt;p&gt;Let&#39;s call the whole thing off&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;Priceless! Be sure to read the comments on Scott&#39;s post.</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/6192075255472957397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/6192075255472957397?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/6192075255472957397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/6192075255472957397'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/reflection-joke.html' title='Reflection joke'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-6017524768085562258</id><published>2007-10-22T22:57:00.000-07:00</published><updated>2008-07-04T16:25:36.224-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>Parsing Enterprise Library Trace Output in Ruby</title><content type='html'>The Enterprise Library Tracer class is really handy, and I use it all the time for profiling slow pieces of code. The only problem is that its output is illegible. Using the default formatter, this is what one trace looks like:&lt;br /&gt;&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red255\green255\blue255;\red0\green0\blue0;}??\fs24 \cf1\cb2\highlight2 ----------------------------------------\par ??Timestamp: 10/24/2007 12:42:00 AM\par ??Message: Start Trace: Activity &#39;03952c36-9e3c-4175-bd5a-9f2ea108ae7e&#39; in method &#39;App.Results.LoadData&#39; at 1981206585161 ticks\par ??Category: GetPhotoQuery\par ??Priority: 5\par ??EventId: 1\par ??Severity: Start\par ??Title:TracerEnter\par ??Machine: GABE-THINKPAD\par ??Application Domain: /LM/W3SVC/1/Root/App-11-128376599444062500\par ??Process Id: 3564\par ??Process Name: C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\aspnet_wp.exe\par ??Win32 Thread Id: 4164\par ??Thread Name: \par ??Extended Properties: \par ??----------------------------------------\par ??----------------------------------------\par ??Timestamp: 10/24/2007 12:42:09 AM\par ??Message: End Trace: Activity &#39;b7b7c71f-30ae-486c-8206-4d87dd44e2fc&#39; in method &#39;App.Results.LoadData&#39; at 1981236796826 ticks (elapsed time: 0.07 seconds)\par ??Category: GetPhotoQuery\par ??Priority: 5\par ??EventId: 1\par ??Severity: Stop\par ??Title:TracerExit\par ??Machine: GABE-THINKPAD\par ??Application Domain: /LM/W3SVC/1/Root/App-11-128376599444062500\par ??Process Id: 3564\par ??Process Name: C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\aspnet_wp.exe\par ??Win32 Thread Id: 4164\par ??Thread Name: \par ??Extended Properties: \par ??----------------------------------------\par ??} --&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; overflow: auto; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas,‘Lucida Console’,‘Courier New’,monospace;font-size:12pt;color:white;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; ----------------------------------------&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; Timestamp: 10/24/2007 12:42:00 AM&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; Message: Start Trace: Activity &#39;03952c36-9e3c-4175-bd5a-9f2ea108ae7e&#39; in method &#39;App.Results.LoadData&#39; at 1981206585161 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt; Category: GetPhotoQuery&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt; Priority: 5&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt; EventId: 1&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt; Severity: Start&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt; Title:TracerEnter&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt; Machine: GABE-THINKPAD&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt; Application Domain: /LM/W3SVC/1/Root/App-11-128376599444062500&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt; Process Id: 3564&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; Process Name: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_wp.exe&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   13&lt;/span&gt; Win32 Thread Id: 4164&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   14&lt;/span&gt; Thread Name: &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   15&lt;/span&gt; Extended Properties: &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   16&lt;/span&gt; ----------------------------------------&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   17&lt;/span&gt; ----------------------------------------&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   18&lt;/span&gt; Timestamp: 10/24/2007 12:42:09 AM&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   19&lt;/span&gt; Message: End Trace: Activity &#39;b7b7c71f-30ae-486c-8206-4d87dd44e2fc&#39; in method &#39;App.Results.LoadData&#39; at 1981236796826 ticks (elapsed time: 0.07 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   20&lt;/span&gt; Category: GetPhotoQuery&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   21&lt;/span&gt; Priority: 5&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   22&lt;/span&gt; EventId: 1&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   23&lt;/span&gt; Severity: Stop&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   24&lt;/span&gt; Title:TracerExit&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   25&lt;/span&gt; Machine: GABE-THINKPAD&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   26&lt;/span&gt; Application Domain: /LM/W3SVC/1/Root/App-11-128376599444062500&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   27&lt;/span&gt; Process Id: 3564&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   28&lt;/span&gt; Process Name: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_wp.exe&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   29&lt;/span&gt; Win32 Thread Id: 4164&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   30&lt;/span&gt; Thread Name: &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   31&lt;/span&gt; Extended Properties: &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   32&lt;/span&gt; ----------------------------------------&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;If you are using multiple nested traces, it&#39;s impossible to interpret. A custom log formatter can help.&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;\red255\green0\blue0;\red255\green255\blue0;}??\fs24 \cf1\cb2\highlight2     &lt;formatters&gt;\par ??\cf3       ...\par ??\cf1       &lt;add cf1 =&quot;\cf5&quot; cf1 =&quot;\cf5&quot; version=&quot;3.1.0.0,&quot; culture=&quot;neutral,&quot; publickeytoken=&quot;b03f5f7f11d50a3a&quot; cf1 =&quot;\cf5&quot;&gt;\par ??    &lt;/formatters&gt;} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; overflow: auto; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas,‘Lucida Console’,‘Courier New’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; &amp;lt;formatters&amp;gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;  ...&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;   &amp;lt;add &lt;span style=&quot;color:red;&quot;&gt;template&lt;/span&gt;=&lt;span style=&quot;color:yellow;&quot;&gt;&quot;{category}({timestamp}): {message}&quot;&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     &lt;span style=&quot;color:red;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color:yellow;&quot;&gt;&quot;Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;     &lt;span style=&quot;color:red;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color:yellow;&quot;&gt;&quot;Short Text Formatter&quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt; &amp;lt;/formatters&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Each entry is now compressed onto one line, and I&#39;ve gotten rid of the information I don&#39;t need:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red255\green255\blue255;\red0\green0\blue0;}??\fs24 \cf1\cb2\highlight2 GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.Results.LoadData&#39; at 2228474435074 ticks\par ??GetRecords, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228474857791 ticks\par ??GetRecords, GetPhotoQuery(8/24/2007 12:16:48 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228475263799 ticks (elapsed time: 0.113 seconds)\par ??CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228475271352 ticks\par ??LoadAdditionalImages, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475285334 ticks\par ??LoadAdditionalImages, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475413732 ticks (elapsed time: 0.035 seconds)\par ??LoadPhotoList, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475416500 ticks\par ??LoadPhotoList, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491499906 ticks (elapsed time: 4.493 seconds)\par ??SortingResults, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491505534 ticks\par ??SortingResults, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491518346 ticks (elapsed time: 0.003 seconds)\par ??CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228491520681 ticks (elapsed time: 4.539 seconds)\par ??GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.Results.LoadData&#39; at 2228491521707 ticks (elapsed time: 4.773 seconds)\par ??} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; overflow: auto; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas,‘Lucida Console’,‘Courier New’,monospace;font-size:12pt;color:white;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.Results.LoadData&#39; at 2228474435074 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; GetRecords, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228474857791 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; GetRecords, GetPhotoQuery(8/24/2007 12:16:48 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228475263799 ticks (elapsed time: 0.113 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt; CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228475271352 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt; LoadAdditionalImages, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475285334 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt; LoadAdditionalImages, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475413732 ticks (elapsed time: 0.035 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt; LoadPhotoList, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:48 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228475416500 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt; LoadPhotoList, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491499906 ticks (elapsed time: 4.493 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt; SortingResults, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): Start Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491505534 ticks&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt; SortingResults, CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.PhotoRecList..ctor&#39; at 2228491518346 ticks (elapsed time: 0.003 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt; CreatePhotoRecList, GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.DataLayer.getPhotoQuery&#39; at 2228491520681 ticks (elapsed time: 4.539 seconds)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; GetPhotoQuery(8/24/2007 12:16:52 AM): End Trace: Activity &#39;466569a2-9713-4e66-aeca-d7d9f87aaae5&#39; in method &#39;App.Results.LoadData&#39; at 2228491521707 ticks (elapsed time: 4.773 seconds)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Better, but still hard to interpret. If you squint you can tell that this is a series of nested traces. Execution time is at the end of the line. I used to be in the habit of manually reformatting these files: adding indentation to show nesting and removing the attributes I didn&#39;t care about. But this kind of busywork is the problem computers were invented to solve. 37 lines of Ruby later, I had a script which would parse trace output like so:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red255\green255\blue255;\red0\green0\blue0;}??\fs24 \cf1\cb2\highlight2 GetPhotoQuery\par ??    GetRecords\par ??    GetRecords completed at 8/24/2007 12:16:48 AM (0.113 seconds elapsed)\par ??    CreatePhotoRecList\par ??        LoadAdditionalImages\par ??        LoadAdditionalImages completed at 8/24/2007 12:16:48 AM (0.035 seconds elapsed)\par ??        LoadPhotoList\par ??        LoadPhotoList completed at 8/24/2007 12:16:52 AM (4.493 seconds elapsed)\par ??        SortingResults\par ??        SortingResults completed at 8/24/2007 12:16:52 AM (0.003 seconds elapsed)\par ??    CreatePhotoRecList completed at 8/24/2007 12:16:52 AM (4.539 seconds elapsed)\par ??GetPhotoQuery completed at 8/24/2007 12:16:52 AM (4.773 seconds elapsed)\par ??} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; overflow: auto; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas,‘Lucida Console’,‘Courier New’,monospace;font-size:12pt;color:white;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; GetPhotoQuery&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt;     GetRecords&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;     GetRecords completed at 8/24/2007 12:16:48 AM (0.113 seconds elapsed)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     CreatePhotoRecList&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;         LoadAdditionalImages&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;         LoadAdditionalImages completed at 8/24/2007 12:16:48 AM (0.035 seconds elapsed)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt;         LoadPhotoList&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt;         LoadPhotoList completed at 8/24/2007 12:16:52 AM (4.493 seconds elapsed)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt;         SortingResults&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt;         SortingResults completed at 8/24/2007 12:16:52 AM (0.003 seconds elapsed)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt;     CreatePhotoRecList completed at 8/24/2007 12:16:52 AM (4.539 seconds elapsed)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; GetPhotoQuery completed at 8/24/2007 12:16:52 AM (4.773 seconds elapsed)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Which shows me exactly where the bottleneck is. Some highlights of the script:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It chooses the file to parse based on the the script&#39;s own filename. Just copy it to the directory your trace file is in and rename it to, eg., &lt;span style=&quot;font-family: courier new;&quot;&gt;mytraces.log.trace_parser.rb&lt;/span&gt; to parse the file &lt;span style=&quot;font-family: courier new;&quot;&gt;mytraces.log&lt;/span&gt;. This piece of convention over configuration was inspired by Rails.&lt;/li&gt;&lt;li&gt;It generates the readable trace and automatically opens it in notepad for you, so getting the parsed output is a one-step process.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The Ruby source looks like this:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red192\green192\blue192;\red0\green0\blue0;\red255\green255\blue255;\red0\green255\blue255;\red255\green255\blue0;\red128\green128\blue128;\red0\green255\blue0;}??\fs24 \cf1\cb2\highlight2 {\b #outputs a file with the trace information in a more readable format}\par ??\par ??{\b #convention: the log filename is the script filename minus}\par ??{\b #   the trailing name and rb extension }\par ??\cf3 src_filename\cf4  = __FILE__.\cf3 chomp\cf4  \cf5 &quot;.trace_parser.rb&quot;\par ??\cf3 dest_filename\cf4  = \cf5 &quot;#\{src_filename\}.readable&quot;\par ??\cf3 dest\cf4  = \cf3 File\cf4 .\cf3 open\cf6 (\cf3 dest_filename\cf4 , \cf5 &quot;w&quot;\cf6 )\par ??\par ??\cf3 File\cf4 .\cf3 open\cf4  \cf3 src_filename\cf4  do |\cf3 src\cf4 |\par ??  \cf1 {\b #need to keep track of how deeply nested we are}\par ??\cf4   \cf3 indent_level\cf4  = -\cf7 1\par ??\par ??\cf4   \cf1 {\b #print a line with the correct indent}\par ??\cf4   \cf3 print_line\cf4  = \cf3 lambda\cf4  \cf6 \{\cf4  |\cf3 s\cf4 | \cf3 dest\cf4 .\cf3 puts\cf6 (\cf5 &quot; &quot;\cf4  * \cf7 4\cf4  * \cf3 indent_level\cf4  + \cf3 s\cf6 )\cf4  \cf6 \}\par ??\par ??\cf4   while \cf3 line\cf4  = \cf3 src\cf4 .\cf3 gets\cf4  do\par ??    \cf1 {\b ##### try to capture the start of a trace #####}\par ??\cf4     \cf3 _\cf4 , \cf3 name\cf4  = \cf5 /^(\\w+).*\\Start\\sTrace/\cf4 .\cf3 match\cf6 (\cf3 line\cf6 )\cf4 .\cf3 to_a\par ??\cf4     if \cf3 name\cf4  then\par ??      \cf3 indent_level\cf4  += \cf7 1\par ??\cf4       \cf3 print_line\cf4 .\cf3 call\cf6 (\cf3 name\cf6 )\par ??\cf4       next \cf1 {\b # move along to the next line}\par ??\cf4     end\par ??\par ??    \cf1 {\b ##### try to capture the end of a trace #####}\par ??\cf4     \cf3 _\cf4 , \cf3 name\cf4 , \cf3 time\cf4 , \cf3 sec\cf4  = \cf5 /^(\\w+).*\\((.*)\\).*End\\sTrace.*elapsed time: (\\d+\\.?\\d*) seconds/\cf4 .\cf3 match\cf6 (\cf3 line\cf6 )\cf4 .\cf3 to_a\cf4  \par ??    if \cf3 name\cf4  then\par ??      \cf3 print_line\cf4 .\cf3 call\cf6 (\cf5 &quot;#\{name\} completed at #\{time\} (#\{sec\} seconds elapsed)&quot;\cf6 )\par ??\cf4       \cf3 indent_level\cf4  -= \cf7 1\par ??\cf4       next \cf1 {\b # move along to the next line}\par ??\cf4     end\par ??  end\par ??end\par ??\par ??\cf3 dest\cf4 .\cf3 close\par ??\par ??\cf5 `notepad #\{dest_filename\}`} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; overflow: auto; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas,‘Lucida Console’,‘Courier New’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;#outputs a file with the trace information in a more readable format&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;#convention: the log filename is the script filename minus&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt; &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;#   the trailing name and rb extension &lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;src_filename&lt;/span&gt; = __FILE__.&lt;span style=&quot;color:white;&quot;&gt;chomp&lt;/span&gt; &lt;span style=&quot;color:yellow;&quot;&gt;&quot;.trace_parser.rb&quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;dest_filename&lt;/span&gt; = &lt;span style=&quot;color:yellow;&quot;&gt;&quot;#{src_filename}.readable&quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;dest&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;File&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;dest_filename&lt;/span&gt;, &lt;span style=&quot;color:yellow;&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;File&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;open&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;src_filename&lt;/span&gt; do |&lt;span style=&quot;color:white;&quot;&gt;src&lt;/span&gt;|&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt;   &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;#need to keep track of how deeply nested we are&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt;   &lt;span style=&quot;color:white;&quot;&gt;indent_level&lt;/span&gt; = -&lt;span style=&quot;color:lime;&quot;&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   13&lt;/span&gt;   &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;#print a line with the correct indent&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   14&lt;/span&gt;   &lt;span style=&quot;color:white;&quot;&gt;print_line&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;lambda&lt;/span&gt; &lt;span style=&quot;color:gray;&quot;&gt;{&lt;/span&gt; |&lt;span style=&quot;color:white;&quot;&gt;s&lt;/span&gt;| &lt;span style=&quot;color:white;&quot;&gt;dest&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;puts&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:yellow;&quot;&gt;&quot; &quot;&lt;/span&gt; * &lt;span style=&quot;color:lime;&quot;&gt;4&lt;/span&gt; * &lt;span style=&quot;color:white;&quot;&gt;indent_level&lt;/span&gt; + &lt;span style=&quot;color:white;&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color:gray;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   15&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   16&lt;/span&gt;   while &lt;span style=&quot;color:white;&quot;&gt;line&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;src&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;gets&lt;/span&gt; do&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   17&lt;/span&gt;     &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;##### try to capture the start of a trace #####&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   18&lt;/span&gt;     &lt;span style=&quot;color:white;&quot;&gt;_&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;name&lt;/span&gt; = &lt;span style=&quot;color:yellow;&quot;&gt;/^(\w+).*\Start\sTrace/&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;line&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;to_a&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   19&lt;/span&gt;     if &lt;span style=&quot;color:white;&quot;&gt;name&lt;/span&gt; then&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   20&lt;/span&gt;       &lt;span style=&quot;color:white;&quot;&gt;indent_level&lt;/span&gt; += &lt;span style=&quot;color:lime;&quot;&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   21&lt;/span&gt;       &lt;span style=&quot;color:white;&quot;&gt;print_line&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   22&lt;/span&gt;       next &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;# move along to the next line&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   23&lt;/span&gt;     end&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   24&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   25&lt;/span&gt;     &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;##### try to capture the end of a trace #####&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   26&lt;/span&gt;     &lt;span style=&quot;color:white;&quot;&gt;_&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;name&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;time&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;sec&lt;/span&gt; = &lt;span style=&quot;color:yellow;&quot;&gt;/^(\w+).*\((.*)\).*End\sTrace.*elapsed time: (\d+\.?\d*) seconds/&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;line&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;to_a&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   27&lt;/span&gt;     if &lt;span style=&quot;color:white;&quot;&gt;name&lt;/span&gt; then&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   28&lt;/span&gt;       &lt;span style=&quot;color:white;&quot;&gt;print_line&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:yellow;&quot;&gt;&quot;#{name} completed at #{time} (#{sec} seconds elapsed)&quot;&lt;/span&gt;&lt;span style=&quot;color:gray;&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   29&lt;/span&gt;       &lt;span style=&quot;color:white;&quot;&gt;indent_level&lt;/span&gt; -= &lt;span style=&quot;color:lime;&quot;&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   30&lt;/span&gt;       next &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;# move along to the next line&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   31&lt;/span&gt;     end&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   32&lt;/span&gt;   end&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   33&lt;/span&gt; end&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   34&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   35&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;dest&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;close&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   36&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   37&lt;/span&gt; &lt;span style=&quot;color:yellow;&quot;&gt;`notepad #{dest_filename}`&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/6017524768085562258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/6017524768085562258?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/6017524768085562258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/6017524768085562258'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/parsing-enterprise-library-trace-output.html' title='Parsing Enterprise Library Trace Output in Ruby'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-2277423103733749601</id><published>2007-10-17T22:19:00.001-07:00</published><updated>2007-10-17T23:19:41.347-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="chrome"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>Exploiting Closures: What I learned from Ruby that made me a better .Net Developer</title><content type='html'>&lt;p&gt;The .Net framework has had closures (anonymous delegates) for quite a while, but it never occurred to me how I could utilize them until I was exposed to Ruby. Ruby has a beautifully clear and concise syntax for passing a closure to a method, and its libraries make extensive use of them.&lt;/p&gt;  &lt;p&gt;The .Net languages I use (c# and Chrome) are statically typed, which introduces some restrictions and syntactic overhead that Ruby doesn&#39;t have. But both c# (3.0) and Chrome are fairly good at type inference, so the overhead isn&#39;t as high as you might think. Some examples of how my Ruby-inspired appreciation for closures has allowed me to encapsulate common .Net patterns:&lt;/p&gt;  &lt;h3&gt;Data Access&lt;/h3&gt;  &lt;p&gt;My usual data access pattern looks something like this:&lt;/p&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red255\green255\blue255;}??\fs24 \cf1\cb2\highlight2             using (\cf3 IDataReader\cf1  \cf4 rdr\cf1  = \cf4 db\cf1 {\b .}\cf4 ExecuteReader\cf1 (\cf3 CommandType\cf1 {\b .}\cf4 Text\cf1 , \par ??                string.\cf4 Format\cf1 (\cf4 sql\cf1 , \cf4 Chainkey\cf1 )))\par ??            \{\par ??                while (\cf4 rdr\cf1 {\b .}\cf4 Read\cf1 ())\par ??                \{\par ??                    \cf4 result\cf1 {\b .}\cf4 Add\cf1 ( new \cf3 DeliveryHoursRec\cf1 (\cf4 rdr\cf1 , \cf3 TimeSpan\cf1 {\b .}\cf4 Zero\cf1 , false) );\par ??                \}\par ??            \}\par ??            return \cf4 result\cf1 ;} --&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;   &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; using (&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;IDataReader&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;rdr&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;ExecuteReader&lt;/span&gt;(&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;CommandType&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Text&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;sql&lt;/span&gt;))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     while (&lt;span style=&quot;color:white;&quot;&gt;rdr&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Read&lt;/span&gt;())&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;         &lt;span style=&quot;color:white;&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Add&lt;/span&gt;( new &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;BusinessObject&lt;/span&gt;(...) );&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt; }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt; return &lt;span style=&quot;color:white;&quot;&gt;result&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Execute the query, loop through the result set, and return a collection of business objects. Rinse. Repeat. Not only does this get repetitive, but I have trouble remembering the &lt;span style=&quot;font-family:Courier New;&quot;&gt;using&lt;/span&gt; statement. It&#39;s not uncommon for me to just forget to dispose the reader when I&#39;m done, which means leaving a database connection open in memory until the garbage collector gets around to cleaning up. Enter  &lt;span style=&quot;font-family:Courier New;&quot;&gt;GetList&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red255\green255\blue255;}??\fs24 \cf1\cb2\highlight2         public static \cf3 List\cf1 {\b &lt;}\cf4 T\cf1 {\b&gt; }\cf4 GetList\cf1 {\b &lt;}\cf4 T\cf1 {\b&gt;(}\cf3 Database\cf1  \cf4 db\cf1 , string \cf4 sql\cf1 , \cf3 Func\cf1 {\b &lt;}\cf3 IDataReader\cf1 , \cf4 T\cf1 {\b&gt; }\cf4 create\cf1 )\par ??        \{\par ??            \cf3 List\cf1 {\b &lt;}\cf4 T\cf1 {\b&gt; }\cf4 list\cf1  = new \cf3 List\cf1 {\b &lt;}\cf4 T\cf1 {\b&gt;();}\par ??            using(\cf3 IDataReader\cf1  \cf4 rdr\cf1  = \cf4 db\cf1 {\b .}\cf4 ExecuteReader\cf1 (\cf3 CommandType\cf1 {\b .}\cf4 Text\cf1 , \cf4 sql\cf1 ))\par ??            \{\par ??                while(\cf4 rdr\cf1 {\b .}\cf4 Read\cf1 ())\par ??                \{                    \par ??                    \cf4 list\cf1 {\b .}\cf4 Add\cf1 (\cf4 create\cf1 (\cf4 rdr\cf1 ));\par ??                \}\par ??            \}\par ??\par ??            return \cf4 list\cf1 ;\par ??        \}} --&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; public static &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;GetList&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Database&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;db&lt;/span&gt;, string &lt;span style=&quot;color:white;&quot;&gt;sql&lt;/span&gt;, &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;IDataReader&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;create&lt;/span&gt;)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;     &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;list&lt;/span&gt; = new &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     using(&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;IDataReader&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;rdr&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;ExecuteReader&lt;/span&gt;(&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;CommandType&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Text&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;sql&lt;/span&gt;))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;         while(&lt;span style=&quot;color:white;&quot;&gt;rdr&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Read&lt;/span&gt;())&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt;         {                    &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt;             &lt;span style=&quot;color:white;&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Add&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;create&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;rdr&lt;/span&gt;));&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt;     return &lt;span style=&quot;color:white;&quot;&gt;list&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   13&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;span style=&quot;font-family:Courier New;&quot;&gt;&lt;br /&gt;GetList&lt;t&gt;&lt;/t&gt;&lt;/span&gt; needs a &lt;span style=&quot;font-family:Courier New;&quot;&gt;Database&lt;/span&gt; object, the sql to work with, and a closure describing how to turn a row in the result set into a business object. It then returns a typesafe collection representing the query. An example use might be to get a list of name/id pairs, and would look something like this:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red192\green192\blue192;\red255\green255\blue255;\red255\green255\blue0;}??\fs24 \cf1\cb2\highlight2   \cf3 {\b //Get the results from the database}\par ??\cf1   result := \cf4 DbUtils\cf1 .\cf4 GetList\cf1 {\b &lt;}\cf4 KeyValuePair\cf1 {\b &lt;}\cf4 Integer\cf1 , \cf4 String\cf1 {\b&gt;&gt;(}\cf4 sql\cf1 , \par ??    \cf4 row\cf1  -&gt; new \cf4 KeyValuePair\cf1 {\b &lt;}\cf4 Integer\cf1 , \cf4 String\cf1 {\b&gt;(}\par ??             \cf4 DbUtils\cf1 .\cf4 AsInt\cf1 (\cf4 row\cf1 .\cf4 Item\cf1 [\cf5 &#39;SuperCat_ID&#39;\cf1 ]),\par ??             \cf4 DbUtils\cf1 .\cf4 AsString\cf1 (\cf4 row\cf1 .\cf4 Item\cf1 [\cf5 &#39;SuperCat_Name&#39;\cf1 ]))\par ??  );} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;//Get the results from the database&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; return &lt;span style=&quot;color:white;&quot;&gt;DbUtils&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;GetList&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;KeyValuePair&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;&amp;gt;(&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;db&lt;/span&gt;, &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;sql&lt;/span&gt;, &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;   &lt;span style=&quot;color:white;&quot;&gt;row&lt;/span&gt; =&amp;gt; new &lt;span style=&quot;color:white;&quot;&gt;KeyValuePair&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;           &lt;span style=&quot;color:white;&quot;&gt;DbUtils&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;AsInt&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;row&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;Item&lt;/span&gt;[&lt;span style=&quot;color:yellow;&quot;&gt;&quot;id&quot;&lt;/span&gt;]),&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;           &lt;span style=&quot;color:white;&quot;&gt;DbUtils&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;AsString&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;row&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;Item&lt;/span&gt;[&lt;span style=&quot;color:yellow;&quot;&gt;&quot;name&quot;&lt;/span&gt;]))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt; );&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Where &lt;span style=&quot;font-family:Courier New;&quot;&gt;AsInt&lt;/span&gt; and &lt;span style=&quot;font-family:Courier New;&quot;&gt;AsString&lt;/span&gt; are utility methods of mine to handle cases with null fields.&lt;br /&gt;&lt;p&gt;This is, by the way, one example of a very handy use for closures: encapsulating resource allocation and disposal so that you, the developer, don&#39;t have to remember to do it. Anyplace you acquire a resource (file access, database access, network operations, etc.) is a candidate for a method like this.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Lazy Loading&lt;/h3&gt;Another common pattern of mine is lazy loading: a business object may have some properties which are rarely used and expensive to calculate. In that case, the object defers calculation until they are needed:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red255\green255\blue255;}??\fs24 \cf1\cb2\highlight2 private \cf3 List\cf1 {\b &lt;string&gt; }\cf4 names\cf1 ;\par ??public \cf3 List\cf1 {\b &lt;string&gt; }\cf4 Names\par ??\cf1 \{\par ??    get\par ??    \{\par ??        if (\cf4 names\cf1  != null)\par ??        \{\par ??            \cf4 names\cf1  = \cf4 ExpensiveComputationToGetNames\cf1 ();\par ??        \}\par ??\par ??        \cf3 SysUtils\cf1 {\b .}\cf4 LazyLoad\cf1 (ref \cf4 names\cf1 , \par ??            () =&gt; \cf4 ExpensiveComputationToGetNames\cf1 ()\par ??        );\par ??\par ??        return \cf4 names\cf1 ;\par ??    \}\par ??\}} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; private &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;string&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; public &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;string&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Names&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     get&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;         if (&lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt; != null)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt;             &lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;ExpensiveComputation&lt;/span&gt;();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt;         return &lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Using closures, I&#39;ve extracted this pattern into the library function &lt;span style=&quot;font-family:Courier New;&quot;&gt;LazyLoad&lt;t&gt;&lt;/t&gt;&lt;/span&gt;:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;}??\fs24 \cf1\cb2\highlight2         public static void \cf3 LazyLoad\cf1 {\b &lt;}\cf3 T\cf1 {\b&gt;(ref }\cf3 T\cf1  \cf3 stateVar\cf1 , \cf4 Func\cf1 {\b &lt;}\cf3 T\cf1 {\b&gt; }\cf3 generateVal\cf1 )\par ??        \{\par ??            if ( \cf3 stateVar\cf1  == null || \cf3 stateVar\cf1 {\b .}\cf3 Equals\cf1 (default(\cf3 T\cf1 )) )\par ??            \{\par ??                \cf3 stateVar\cf1  = \cf3 generateVal\cf1 ();\par ??            \}\par ??        \}} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; public static void &lt;span style=&quot;color:white;&quot;&gt;LazyLoad&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;(ref &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;stateVar&lt;/span&gt;, &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;generateVal&lt;/span&gt;)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;     if ( &lt;span style=&quot;color:white;&quot;&gt;stateVar&lt;/span&gt; == null || &lt;span style=&quot;color:white;&quot;&gt;stateVar&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Equals&lt;/span&gt;(default(&lt;span style=&quot;color:white;&quot;&gt;T&lt;/span&gt;)) )&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;         &lt;span style=&quot;color:white;&quot;&gt;stateVar&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;generateVal&lt;/span&gt;();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Which transforms the &lt;span style=&quot;font-family:Courier New;&quot;&gt;Names&lt;/span&gt; property into:&lt;br /&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; private &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;string&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt; public &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;string&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Names&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     get&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   6&lt;/span&gt;         &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;SysUtils&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;LazyLoad&lt;/span&gt;(ref &lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt;, &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   7&lt;/span&gt;             () =&amp;gt; &lt;span style=&quot;color:white;&quot;&gt;ExpensiveComputation&lt;/span&gt;()&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   8&lt;/span&gt;         );&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   9&lt;/span&gt;         return &lt;span style=&quot;color:white;&quot;&gt;names&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice that even though &lt;span style=&quot;font-family:Courier New;&quot;&gt;LazyLoad&lt;t&gt;&lt;/t&gt;&lt;/span&gt; is a generic method, I am calling as if it were a normal method. The type is inferred from the &lt;span style=&quot;font-family:Courier New;&quot;&gt;names&lt;/span&gt; parameter, so I can leave out the angle brackets. Type inference wasn&#39;t smart enough to figure out the type in the &lt;span style=&quot;font-family:Courier New;&quot;&gt;GetList&lt;t&gt;&lt;/t&gt;&lt;/span&gt; case, but it is here.&lt;br /&gt;&lt;p&gt;The jury is still out for me on whether or not &lt;span style=&quot;font-family:Courier New;&quot;&gt;LazyLoad&lt;t&gt;&lt;/t&gt;&lt;/span&gt; is really a good idea. On the one hand, it encapsulates something I do a lot and gives it a name. On the other hand, it isn&#39;t actually much shorter than explicitly testing for null and requires passing the private field by reference, which I try to avoid (although in this case I think it&#39;s pretty clear what is happening).&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Sort By&lt;/h3&gt;Finally, an example that &lt;a href=&quot;http://jcheng.wordpress.com/2007/08/23/schwartzian-transform-in-c-30/&quot;&gt;was someone else&#39;s idea&lt;/a&gt;, but which was also inspired by Ruby: an extension method that implements &lt;span style=&quot;font-family:Courier New;&quot;&gt;SortBy&lt;/span&gt; on &lt;span style=&quot;font-family:courier new;&quot;&gt;List&lt;t&gt;&lt;/t&gt;&lt;/span&gt; collections:&lt;br /&gt;&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red255\green255\blue255;\red192\green192\blue192;}??\fs24 \cf1\cb2\highlight2 public static \cf3 List\cf1 {\b &lt;}\cf4 TElement\cf1 {\b &gt; }\cf4 SortBy2\cf1 {\b &lt;}\cf4 TElement\cf1 , \cf4 TSortBy\cf1 {\b &gt;(}\par ??    this \cf3 List\cf1 {\b &lt;}\cf4 TElement\cf1 {\b &gt; }\cf4 coll\cf1 ,\par ??    \cf4 Converter\cf1 {\b &lt;}\cf4 TElement\cf1 , \cf4 TSortBy\cf1 {\b &gt; }\cf4 converter\cf1 ,\par ??    \cf3 Comparison\cf1 {\b &lt;}\cf4 TSortBy\cf1 {\b &gt; }\cf4 comparison\cf1 )\par ??\{\par ??    return \cf4 coll\par ??\cf1         .\cf4 ConvertAll\cf1 (\cf4 el\cf1  =&gt; new \{ \cf4 Key\cf1  = \cf4 converter\cf1 (\cf4 el\cf1 ), \cf4 Value\cf1  = \cf4 el\cf1  \})\par ??        .\cf4 Sort\cf1 ((\cf4 a\cf1 , \cf4 b\cf1 ) =&gt; \cf4 comparison\cf1 (\cf4 a\cf1 {\b .}\cf4 Key\cf1 , \cf4 b\cf1 {\b .}\cf4 Key\cf1 ))\par ??        .\cf4 ConvertAll\cf1 (\cf4 x\cf1  =&gt; \cf4 x\cf1 {\b .}\cf4 Value\cf1 );\par ??\}\par ??{\b ...}\par ??\cf5 {\b //sample use:}\par ??\cf4 List\cf1 {\b &lt;string&gt; }\cf4 files\cf1  = \cf5 {\b //Get some files}\par ??\cf4 files\cf1 {\b .}\cf4 SortBy\cf1 (\cf4 x\cf1  =&gt; \cf4 GetDate\cf1 (\cf4 x\cf1 )); \cf5 {\b //sort by modified date}} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas,‘lucida console’,‘courier new’,monospace;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    1&lt;/span&gt; public static &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;TElement&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;SortBy&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;TElement&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;TSortBy&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    2&lt;/span&gt;     this &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;TElement&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;coll&lt;/span&gt;,&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    3&lt;/span&gt;     &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Converter&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;TElement&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;TSortBy&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;converter&lt;/span&gt;,&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    4&lt;/span&gt;     &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Comparison&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;TSortBy&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;comparison&lt;/span&gt;)&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    5&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    6&lt;/span&gt;     return &lt;span style=&quot;color:white;&quot;&gt;coll&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    7&lt;/span&gt;         .&lt;span style=&quot;color:white;&quot;&gt;ConvertAll&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;el&lt;/span&gt; =&amp;gt; new { &lt;span style=&quot;color:white;&quot;&gt;Key&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;converter&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;el&lt;/span&gt;), &lt;span style=&quot;color:white;&quot;&gt;Value&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;el&lt;/span&gt; })&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    8&lt;/span&gt;         .&lt;span style=&quot;color:white;&quot;&gt;Sort&lt;/span&gt;((&lt;span style=&quot;color:white;&quot;&gt;a&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span style=&quot;color:white;&quot;&gt;comparison&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Key&lt;/span&gt;, &lt;span style=&quot;color:white;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Key&lt;/span&gt;))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;    9&lt;/span&gt;         .&lt;span style=&quot;color:white;&quot;&gt;ConvertAll&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;x&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:white;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;Value&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   10&lt;/span&gt; }&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   11&lt;/span&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;...&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   12&lt;/span&gt; &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;//sample use:&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   13&lt;/span&gt; &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;string&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;files&lt;/span&gt; = ...&lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;//Get some files&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:lime;&quot;&gt;   14&lt;/span&gt; &lt;span style=&quot;color:white;&quot;&gt;files&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:white;&quot;&gt;SortBy&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;x&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:white;&quot;&gt;GetDate&lt;/span&gt;(&lt;span style=&quot;color:white;&quot;&gt;x&lt;/span&gt;)); &lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;//sort by modified date&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice how type inference cleans up the syntax. This function is as elegant (I think) as the Ruby equivalent, but is still fully type-safe.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;The point of all this is that closures provide powerful, additional ways of encapsulating common patterns in code. They are fairly new to .Net, but we can look to other languages to gain clues about how to use them best.</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/2277423103733749601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/2277423103733749601?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/2277423103733749601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/2277423103733749601'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/exploiting-closures-what-i-learned-from.html' title='Exploiting Closures: What I learned from Ruby that made me a better .Net Developer'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-3595362841865107171</id><published>2007-10-11T21:54:00.001-07:00</published><updated>2007-10-11T21:54:17.429-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>New Asp.Net MVC Framework</title><content type='html'>&lt;p&gt;At the recently-concluded Alt.Net conference, &lt;a href=&quot;weblogs.asp.net/scottgu/&quot;&gt;ScottGu&lt;/a&gt; demoed a new &lt;a href=&quot;http://www.hanselman.com/blog/ScottGuMVCPresentationAndScottHaScreencastFromALTNETConference.aspx&quot;&gt;pre-pre-alpha MVC framework for Asp.Net&lt;/a&gt;. The presentation is definitely worth a look.&lt;/p&gt;  &lt;p&gt;This is a great example of why Rails is such a good thing even for those of us who don&#39;t get to use it professionally. Something as subversive as Rails is bound to have wide-reaching effects far beyond the actual framework. It&#39;s already motivated MVC frameworks in just about every language imaginable - including the open source MonoRail implementation built on top of Asp.Net.&lt;/p&gt;  &lt;p&gt;Microsoft seems to be consistently a few years behind the state of the art (in unit testing, ajax, mvc web frameworks, etc.) and they have this irresistible urge to write their own versions of perfectly good open-source tools. But at least they realize a good idea when they see one. The next version of the .Net framework has some really exciting new features like &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx&quot;&gt;extension methods&lt;/a&gt; and &lt;a href=&quot;http://blah.winsmarts.com/2006/05/19/demystifying-c-30--part-4-lambda-expressions.aspx&quot;&gt;lambda expressions&lt;/a&gt;, which make them look almost (dare I say it) as clean as Ruby blocks.&lt;/p&gt;  &lt;p&gt;Some scattered thoughts from the presentation:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The whole talk was giving me Rails flashbacks. All the terminology seemed to be borrowed from rails, as was the default routing format. Visual Studio was even set up with a dark color scheme&amp;#xA0; that evoked the popular textmate theme. &lt;/li&gt;    &lt;li&gt;Routing uses a tokenized-string format. I like the syntax: it&#39;s very intuitive and clean. But Scott mentioned that an earlier version used Regular Expressions, and that was changed because they found that, while Regular Expressions are super-powerful, only like 10% of people actually understand them (~10:30 in the video). This shows some of the self-imposed constraints Microsoft is working under. No Regular Expressions because &lt;em&gt;they are too hard to understand?&lt;/em&gt;       &lt;br /&gt;      &lt;br /&gt;This mentality is, I think, the source of most of the problems with Asp.Net in the first place. The drive to make web programming &amp;quot;just like&amp;quot; windows programming and cater to the lowest common denominator is behind some of asp.net&#39;s worst features: The page lifecycle. and viewstate(love it/hate it) are the two biggest offenders, IMHO. Getting closer to the html and http metal means knowing more about them, yes, but it also makes the framework vastly simpler. You won&#39;t get an &lt;font face=&quot;Courier New&quot;&gt;OnChange&lt;/font&gt; event on your texboxes. But I&#39;ll bet that the time you save learning about html and http is spent debugging page lifecycle issues or figuring out that you need to use &lt;font face=&quot;Courier New&quot;&gt;Control.UniqueID&lt;/font&gt; instead of &lt;font face=&quot;Courier New&quot;&gt;Control.ClientID&lt;/font&gt;. &lt;/li&gt;    &lt;li&gt;Scott emphasized many times that the entire architecture was designed to be very pluggable (don&#39;t like it? change it!) and easily unit-testable. There will be support for mock objects using common frameworks (Rhino mocks/Typemock were mentioned by name). Very cool. &lt;/li&gt;    &lt;li&gt;The community seems to be very excited about this. You can see a lot of enthusiasm, both in the audience for Scott&#39;s talk and in &lt;a href=&quot;http://www.hanselman.com/blog/ScottGuMVCPresentationAndScottHaScreencastFromALTNETConference.aspx&quot;&gt;the comments to this blog post&lt;/a&gt;. You can also tell what (this part of) the community cares about. Scott fielded a lot of &amp;quot;is that class sealed?&amp;quot; questions (to which his answer was always no), and lots of people seem to be happy about getting rid of the postback model. &lt;/li&gt;    &lt;li&gt;Along with all the extensibility points that Scott mentioned, he gave some specific examples of alternate implementations that could be plugged in. At just about ever point, there was a Castle/Monorail alternative that could be used. It left me wondering, if you plug in all the Monorail components, how much of the MS framework would be left? Doesn&#39;t seem like much. &lt;/li&gt;    &lt;li&gt;Model classes take a hash, just like in Rails, so that you can update them directly from form parameters: &lt;font face=&quot;Courier New&quot;&gt;Customer.UpdateFrom(Request.Form)&lt;/font&gt;. &lt;/li&gt;    &lt;li&gt;The framework will ship with a bunch of MVC-specific controls, but many of the standard ones (the Repeater was mentioned by name) apparently do not require webforms and can be used as-is. Master pages and user controls can also be used. &lt;/li&gt;    &lt;li&gt;The first public release should be in 6-8 weeks, with a final release in spring 2008. &lt;/li&gt; &lt;/ul&gt; </content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/3595362841865107171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/3595362841865107171?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3595362841865107171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3595362841865107171'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/new-aspnet-mvc-framework.html' title='New Asp.Net MVC Framework'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-3936899703048772445</id><published>2007-10-09T16:50:00.001-07:00</published><updated>2008-07-04T16:25:36.225-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chrome"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><title type='text'>YCombinator in Chrome</title><content type='html'>&lt;p&gt;When Chrome 2.0 was released I spent some time playing with its new support for anonymous methods. One of the things I did was to derive the Y Combinator, which lets you generate recursive anonymous methods. &lt;/p&gt;  &lt;p&gt;Anyway, I wrote a series of blog posts about the experience over on the company blog. Low on usefulness, but high on bizarre, esoteric, and fun! Enjoy:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/10/04/69.aspx&quot;&gt;Anonymous Methods in Chrome&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/10/05/71.aspx&quot;&gt;Y in Chrome Part 1: Currying&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/10/08/72.aspx&quot;&gt;Y in Chrome Part 2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/10/09/73.aspx&quot;&gt;Y in Chrome Part 3&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/3936899703048772445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/3936899703048772445?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3936899703048772445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3936899703048772445'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/ycombinator-in-chrome.html' title='YCombinator in Chrome'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-3105772842720106824</id><published>2007-10-03T19:12:00.001-07:00</published><updated>2008-01-28T13:07:35.431-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>Executable Configuration Files</title><content type='html'>&lt;p&gt;Ever since I got my start in Delphi with ye olde ini file, I&#39;ve had this feeling that there must be a better way of storing application configuration information. Even with a good API, there is just too much boilerplate code involved in parsing the file, loading it into a data structure so it can be operated on, and then converting it back to text so it can be saved. Writing boilerplate code makes me feel braindead, and I don&#39;t like feeling braindead.&lt;/p&gt;  &lt;p&gt;My company&#39;s move from Delphi to .Net a few years ago brought incremental improvement: a built-in api for reading/writing custom settings in app.config. In .Net 2 you can even have a config class auto-generated for you, which provides type-safe and intellisensy access to your configuration settings. And, of course, there&#39;s the .Net support for serializing objects to Xml. I confess I don&#39;t have much experience with that.&lt;/p&gt;  &lt;p&gt;Life was easier, but there were still significant restraints: you need to design your configuration in just such a way in order to get the boilerplate auto-generated. For an example of the issues, see &lt;a href=&quot;http://www.codinghorror.com/blog/archives/000656.html&quot;&gt;this blog post&lt;/a&gt; about storing configuration in .Net, and read the caveats pointed out by the commenters. The solution presented is a pretty good one, but there&#39;s still bookkeeping: copy this here, add that there, store in the app.config and hope you have read access, use public fields in your settings class.&lt;/p&gt;  &lt;p&gt;It wasn&#39;t until I learned Ruby that I realized these restrictions are largely inherent in the strongly-typed, compiled languages I&#39;ve been using. I had two configuration epiphanies using Ruby:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;The Yaml parser in Ruby blew me away. Yaml is a lightweight configuration language meant to be easier on the eyes than Xml. Here&#39;s a snippet:&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green255\blue255;\red0\green0\blue0;}??\fs24 \cf1\cb2\highlight2 development:\par ??  adapter: mysql\par ??  database: members\par ??  username: root\par ??  password: pwd\par ??  host: localhost} --&gt;&lt;div style=&quot;background: black none repeat scroll 0% 50%; font-family: Consolas,Courier New; font-size: 12pt; color: aqua; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;development:&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;  adapter: mysql&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;  database: members&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;  username: root&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;  password: pwd&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;  host: localhost&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;With the ruby Yaml parser this can be loaded with one line of code, and accessed as a hash table: &lt;span style=&quot;;font-family:Courier New;font-size:100%;&quot;  &gt;config[&quot;development&quot;][&quot;adapter&quot;]&lt;/span&gt; would return &lt;span style=&quot;;font-family:Courier New;font-size:100%;&quot;  &gt;&quot;mysql&quot;&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Because ruby is an interpreted language, you may be able to write all of your configuration in ruby itself. One of the main reasons for using a config file (to update settings without having to recompile) doesn&#39;t exist in ruby. This is done a lot in Ruby on Rails, for instance. Here&#39;s a short snippet of &lt;span style=&quot;;font-family:Courier New;font-size:100%;&quot;  &gt;production.rb&lt;/span&gt;:&lt;!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red192\green192\blue192;\red0\green0\blue0;\red255\green255\blue255;\red0\green255\blue255;}??\fs24 \cf1\cb2\highlight2 {\b # Code is not reloaded between requests}\par ??\cf3 config\cf4 .\cf3 cache_classes\cf4  = true\par ??\par ??\cf1 {\b # Use a different logger for distributed setups}\par ??\cf3 config\cf4 .\cf3 logger\cf4  = \cf3 SyslogLogger\cf4 .\cf3 new} --&gt;&lt;br /&gt;&lt;div    style=&quot;background: black none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:consolas;font-size:12pt;color:aqua;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;# Code is not reloaded between requests&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:white;&quot;&gt;config&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;cache_classes&lt;/span&gt; = true&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;font-weight: bold;color:silver;&quot; &gt;# Use a different logger for distributed setups&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:white;&quot;&gt;config&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;logger&lt;/span&gt; = &lt;span style=&quot;color:white;&quot;&gt;SyslogLogger&lt;/span&gt;.&lt;span style=&quot;color:white;&quot;&gt;new&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;beautifully simple, isn&#39;t it?&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Just recently I came across &lt;a href=&quot;http://steve.yegge.googlepages.com/the-emacs-problem&quot;&gt;an&lt;/a&gt; &lt;a href=&quot;http://debasishg.blogspot.com/2007/04/executable-xml-aka-lisp.html&quot;&gt;idea&lt;/a&gt; that pushes the executable-configuration envelope even further: using Lisp as a data representation. Lisp is the ideal format: hierarchical like Xml, cleaner than Xml, executable. As &lt;a href=&quot;http://steve.yegge.googlepages.com/the-emacs-problem&quot;&gt;Steve Yegge points out&lt;/a&gt;, if Xml was really sufficient why would we keep adding extensions to make it more programmable? Might as well start off with a real language, like Lisp.&lt;/p&gt;&lt;p&gt;This is really only a proof-of-concept, of course. You can&#39;t use Lisp in a real project because nobody knows Lisp. And besides, I&#39;m not sure that communicating between Java and Lisp would be any easier than communicating between Java and Xml. What you &lt;em&gt;can&lt;/em&gt; do is use that example to show you how easy configuration ought to be. It prevents you from being really satisfied with a suboptimal solution, which is good even if all of your options are suboptimal. You at least know what you&#39;re aiming at.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, where does that leave someone using a statically type language? What lessons can you take away from Lisp and Ruby that will make life easier in C#?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;To be honest, I&#39;m really not sure yet. Nothing in C# prevents you from writing an Xml or Yaml parser that loads the data into nested hashes/arrays. That&#39;s one option. And the support for storing settings in the app.config really is pretty good. But I&#39;m on the lookout for a better way, and that is the point.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;hr /&gt;[1] Of course there&#39;s no reason that Xml couldn&#39;t be interpreted in the same way, and there is a Ruby library, XmlSimple, which does exactly this.&lt;p&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/3105772842720106824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/3105772842720106824?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3105772842720106824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/3105772842720106824'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/executable-configuration-files.html' title='Executable Configuration Files'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3227963714264318937.post-955727338535309167</id><published>2007-10-03T08:31:00.001-07:00</published><updated>2007-10-04T13:26:55.292-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="miscellany"/><title type='text'>Welcome</title><content type='html'>&lt;p&gt;By way of introduction, I intend Coding Patterns to be a repository for the various patterns and practices that I come across - either on my own or via the great hive mind that is the blogsphere - which make my programs easier to develop, easier to read, and easier to use. As I am using it, this phrase extends beyond the particulars of good software design to include good user-interface design and the tools/utilities that remove the &lt;a href=&quot;http://info.computer.org/portal/site/computer/menuitem.eb7d70008ce52e4b0ef1bd108bcd45f3/index.jsp?&amp;amp;pName=computer_level1&amp;amp;path=computer/homepage/misc/Brooks&amp;amp;file=index.xml&amp;amp;xsl=article.xsl&amp;amp;;jsessionid=HCdTbFzn4W1dBKWJyrQhFD6PGrpq6w4M5mnNlgDj1HTrBHnHyh7l%21316462484&quot;&gt;accidental difficulties&lt;/a&gt; of software development.&lt;/p&gt;  &lt;p&gt;In addition, I&#39;ll likely throw in anything that strikes my fancy, particularly regarding Chrome (a .Net Pascal dialect), Ruby, .Net, and the future of technology.&lt;/p&gt;  &lt;p&gt;I also contribute to the periodically-updated &lt;a href=&quot;http://blogs.imaginesystems.net/dev&quot;&gt;Imagine Systems Dev blog&lt;/a&gt;, and may cross-link from time to time. A few highlights:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/09/08/66.aspx&quot;&gt;Synchronizing Computers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2007/03/21/59.aspx&quot;&gt;Getting rid of Batch files&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://blogs.imaginesystems.net/dev/archive/2006/09/07/43.aspx&quot;&gt;Simplify&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;By the way, I apologise for the pretentious title. It isn&#39;t meant to make me sound like an expert or an authority on the subject, just to describe what I&#39;m trying to do here.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingpatterns.blogspot.com/feeds/955727338535309167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3227963714264318937/955727338535309167?isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/955727338535309167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3227963714264318937/posts/default/955727338535309167'/><link rel='alternate' type='text/html' href='http://codingpatterns.blogspot.com/2007/10/welcome.html' title='Welcome'/><author><name>Gabe Moothart</name><uri>http://www.blogger.com/profile/16926123100967129905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>