<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://awesomeprincess.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"><channel><title>Awesome Princess</title><link>http://awesomeprincess.com/blogs/</link><description /><dc:language>en-US</dc:language><generator>CommunityServer 2008 SP1 (Build: 30619.63)</generator><item><title>Nerdy Projects</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/12/26/nerdy-projects.aspx</link><pubDate>Sat, 27 Dec 2008 02:00:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:104</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I am nerd at heart and I constantly find myself getting wrapped up nerdy projects. Lately, I&amp;#39;ve been nerding out on:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt;: a side-project of two well-known bloggers, Jeff Atwood and Spolsky. Weirdly addicting website where you can ask and answer questions about programming and software development. I post as &lt;a href="http://stackoverflow.com/users/40516/princess"&gt;Princess&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikibooks.org/wiki/Programming:F_Sharp"&gt;Wikibooks: F# Programming&lt;/a&gt;: I&amp;#39;m writing a wikibook on the F# programming language. I been working on this book in my free time, and its coming along fairly well. It still has a long way to go, but F# newbies should find the first few chapter relatively accessible and easy to read.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;In all of the years I&amp;#39;ve been programming, I&amp;#39;ve only ever used arrays, linked lists, and hash tables, due in part because I&amp;#39;ve only ever written trivial forms-over-data applications. I&amp;#39;ve never bothered to learn about red-black trees, splay heaps, triangular arrays, or any other uncommon datastructures. Additionally, I&amp;#39;ve never learned about implementing any datastructures in functional programming languages. I&amp;#39;m taking the time to read &lt;a href="http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504"&gt;Purely Functional Datastructures&lt;/a&gt; and &lt;a href="http://www.amazon.com/F-Scientists-Jon-Harrop/dp/0470242116"&gt;F# for Scientists&lt;/a&gt; to bulk up my nerdiness.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=104" width="1" height="1"&gt;</description></item><item><title>Now that's depressing</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/12/26/now-that-s-depressing.aspx</link><pubDate>Sat, 27 Dec 2008 01:13:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:102</guid><dc:creator>Princess</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;So, I&amp;#39;ve been at my new job for the 2 weeks. I was mucho happy with my first paycheck, and I&amp;#39;m happy with my job.&lt;/p&gt;
&lt;p&gt;My company sells insurance software, sells warranties, processes claims, provides claims estimates, etc. However, much of the processing is manual: whenever clients want to buy a warranty, they call one of our data centers to have a form faxed over, the form is filled out, faxed or mailed back, and the details are manually keyed in by people in our accounting department. Similarly, payments are mailed and the details are manually keyed in. There are 20 to 30 people working full-time as keyers for the thousands of documents which pass through accounting everyday.&lt;/p&gt;
&lt;p&gt;On Monday, I attended a meeting with all of the members of the dev team + the top IT managers to discuss the direction of development of our software in 2009. I&amp;#39;m writing a web app which is intended to automate most of the processing above: users can buy and pay insurance online, and the web app will push data directly from the user to the database. The lag-time between buying insurance and making payments will drop from two or three weeks to a few milliseconds.&lt;/p&gt;
&lt;p&gt;I really look forward to the new development, but I just had to open my mouth and ask during the meeting, &amp;quot;so what&amp;#39;s going to happen to all of our keyers?&amp;quot;. The response I got was a little more blunt than I expected, &amp;quot;we won&amp;#39;t need them anymore&amp;quot;.&lt;/p&gt;
&lt;p&gt;3 months from now, when my software rolls into production, a boatload of jobs will be canned. Now that&amp;#39;s depressing.&lt;/p&gt;
&lt;p&gt;And, uh, Merry Christmas? Yeah, merry Christmas.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=102" width="1" height="1"&gt;</description></item><item><title>Financing transition and the love of money</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/12/05/financing-transition-and-the-love-of-money.aspx</link><pubDate>Fri, 05 Dec 2008 12:42:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:99</guid><dc:creator>Princess</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;To put this as blunt as I can, I am a miser. That&amp;#39;s not an exaggeration -- many people know me for being so frugal that I forego basic &amp;quot;necessities&amp;quot; that most people take for granted:&amp;nbsp;I don&amp;#39;t own any furniture, I minimize the electric bill by sitting in the dark and refusing to turn on the AC/heater, I have the cheapest cellphone plan on the market, I don&amp;#39;t have cable TV, I can feed myself for less than $3/day, I buy off-brand food and thrift-store clothing, and my entire wardrobe&amp;nbsp;clothing consists of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One pair of jeans for home, three pairs of slacks for work.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;One shirt for home, two shirts for work.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;One pair of tennis shoes for home, one pair of work shoes.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;A few pairs of black socks, one coat, one belt.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;That&amp;#39;s just the tip of the iceburg, but you get the idea: I&amp;#39;m a money-motivated person. Its not the best personality trait to have, but my lifelong habits have allowed me to save a small fortune.&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;For the most part, the compulsion to hoard everything I earn is due to finance my transition. I made a conscious effort early in my life to accumulate as much money as possible to finance SRS and FFS as soon as possible. As a result, I tend to set pretty high bars for myself, and I have a tendency to job-hop to get higher salaries. To describe my recent job history:&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;- At 18, I worked from Apr &amp;#39;06 - June &amp;#39;07 at a grocery store for&amp;nbsp;$7.50/hr.&lt;/div&gt;
&lt;div&gt;- At 19, I worked from June &amp;#39;07 - Oct &amp;#39;08 as an entry-level computer programmer for $13/hr (an unacceptably low wage, by the way, even at my skill level). This job was intended to get my foot in the door to the IT world, just a stepping stone to better opportunities after I earned a year of work experience.&lt;/div&gt;
&lt;div&gt;- At 21, I just signed a contract today as a .NET contractor making $27/hr, a &lt;a href="http://en.wikipedia.org/wiki/Omaha,_Nebraska#Demographics"&gt;respectable wage where I live&lt;/a&gt;. Every 6 months, I get a bonus equal to $2/hr * hours worked, which is otherwise equivalent to $29/hr.&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;em&gt;&lt;strong&gt;Note: &lt;/strong&gt;You&amp;#39;ll notice there&amp;#39;s a gap between Oct &amp;#39;08 and Dec &amp;#39;08 where I&amp;#39;m unemployed. The story behind that is kinda funny: I did not recieve any raises or reviews at my $13/hr job for the entire time I&amp;#39;d worked there, so I started applying for new jobs. A recruiting agency replied to my application, got me an interview with a major company in Omaha. I got a second interview which went really well. The recruiting agency said &amp;quot;good news, [company] wants to make you an offer this Friday&amp;quot;, so I put in my two weeks notice. When that Friday came, I didn&amp;#39;t get a call. I contacted the recruiters, and they told me that the company will make the offer next Wednesday instead. Well, I didn&amp;#39;t get a call on Wednesday. I waited for the offer, but it didn&amp;#39;t happen. By the time I found out the recruiting agency was feeding me bad information, I was no longer at my company.&lt;br /&gt;&amp;nbsp;&lt;/em&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;em&gt;I acted too hastily by quitting my job before I&amp;#39;d signed any papers saying I had another offer, and ended up unemployed for a month. We call this &amp;quot;jumping the gun&amp;quot;, and I&amp;#39;ve learned a valuable character building lesson about quitting your job too soon as a result. I put my resume on Monster.com on November 14, and less than 3 weeks later I had two successful interviews, got an offer, signed my contract, and I start my new job on December 15 making twice as much as my previous employment.&lt;/em&gt;&lt;/div&gt;
&lt;div style="padding-left:30px;"&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;It&amp;#39;s extraordinarily difficult to be competitive in my line of work, especially given my age, the fact I have no degrees, and my relatively limited work experience. However, I was able to do well for myself through consistent hard work, smart planning, and maturity.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;My objective is to save $30,000 this year. My budget for next year rounds out as follows:&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;- $27/hr * 2080 work hours per year = $56,160&lt;/div&gt;
&lt;div&gt;- Less 21% that the government will tax away = $44,366&lt;/div&gt;
&lt;div&gt;- Less $300/mo car payment = $40766&lt;/div&gt;
&lt;div&gt;- Less $500/mo rent = $34766&lt;/div&gt;
&lt;div&gt;- Less $100/mo food = $33566&lt;/div&gt;
&lt;div&gt;- Less $40/mo phone + tax = $33086&lt;/div&gt;
&lt;div&gt;- Less estimated $6000 to complete my 4-year degree by May = $27086&lt;/div&gt;
&lt;div&gt;- Less $150/mo miscellaneous = $25286&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;This is a rough estimate, but it should be reasonably close. Excluding any bonuses I earn from my job, it looks like I&amp;#39;m going to be&amp;nbsp;~$5000 short of my objective, so I need an additional source of income to meet my objective.&amp;nbsp;After I get my degree in May, I&amp;#39;ll have some free time to get a part-time job. &amp;nbsp;So, this gives me 7-8 months to earn $5000, or $625/mo. I want to work no more than 2 days a week, so need to find a part-time job which pays a minimum of $9.77/hr. I think I can do that.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;If I balance my budget appropriate, pinch every penny as I&amp;#39;m already prone to doing, I should be able to finance my transition out-of-pocket, and I will be able to move things along very rapidly in the next 12 months. w00t!&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=99" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/money/default.aspx">money</category></item><item><title>Abusing IEnumberables in C#</title><link>http://awesomeprincess.com/blogs/programming/archive/2008/08/21/abusing-ienumberables-in-c.aspx</link><pubDate>Thu, 21 Aug 2008 17:00:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:86</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;The IEnumerable&amp;lt;&amp;gt; class&amp;nbsp;is cool because it can be used to represent lazy lists. A lazy lists is just a sequence of data calculated on demand, rather than calculated at the time you create a list. Lazy sequences can represent arbitrarily large datastructures, even lists containing an infinite amount of data, without consuming an infinite amount of memory.&lt;/p&gt;
&lt;p&gt;The match of IEnumerable comes from the &lt;a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx"&gt;yield operator&lt;/a&gt;, and it works thing like this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;int&amp;gt; list = GetNumbers();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;int&amp;gt; enumerator = list.GetEnumerator();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(enumerator);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(enumerator);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(enumerator);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(enumerator);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(enumerator);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(&amp;quot;\nPress any key to continue. . .&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Print(IEnumerator&amp;lt;int&amp;gt; enumerator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; enumerator.MoveNext();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Print: enumurator.Current: {0}&amp;quot;, enumerator.Current);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; GetNumbers()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;GetNumbers: Returning 1&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return 1;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;GetNumbers: Returning 2&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return 2;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;GetNumbers: Returning 3&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return 3;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;When you call GetNumbers(), you get an IEnumerable&amp;lt;int&amp;gt; back.&lt;/p&gt;
&lt;p&gt;When you call MoveNext(), the code in the GetNumbers() method executes until it gets to the first &amp;#39;yield return&amp;#39;, then it returns from the method and assigns enumerator.Current to whatever what returned from the method. In this case, the first time you called MoveNext(), the function returns 1.&lt;/p&gt;
&lt;p&gt;The next call to MoveNext() causes the GetNumbers() method to resume its execution on the line immediately following &amp;#39;yield 1&amp;#39;, it continues on until it hits &amp;#39;yield 2&amp;#39;. Another call to MoveNext() resumes where it left off until it hits &amp;#39;yield 3&amp;#39;.&lt;/p&gt;
&lt;p&gt;Every &amp;#39;yield&amp;#39; tells the method to pause execution, and every call to MoveNext() tells the method to resume execution from where it has paused.&lt;/p&gt;
&lt;p&gt;The output of the program above is:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 3&lt;/p&gt;
&lt;p&gt;Notice when the method finally exits and there is nothing left to yield, the enumerator.Current simply holds the last returned value of the function. Since the enumerator.MoveNext() method returns true if a value was yielded from the method, and false otherwise, we can enumerate manually through our list using a simple while loop:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;int&amp;gt; list = GetNumbers();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;int&amp;gt; enumerator = list.GetEnumerator();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (enumerator.MoveNext())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Print: enumurator.Current: {0}&amp;quot;, enumerator.Current);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(&amp;quot;\nPress any key to continue. . .&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;This prints:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNumbers: Returning 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print: enumerator.Current: 3&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Of course, there&amp;#39;s almost never any reason to enumerate manually through our list when we can use a foreach to do the same job:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (int i in GetNumbers(5, 10))&lt;br /&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;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;i: {0}&amp;quot;, i);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(&amp;quot;\nPress any key to continue. . .&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; GetNumbers(int start, int max)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = start; i &amp;lt;= max; i++)&lt;br /&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;&amp;nbsp;&amp;nbsp; yield return i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;This prints:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 5&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 6&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 7&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 8&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 9&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i: 10&lt;/p&gt;
&lt;p&gt;Notice you can pass in parameters to your IEnumerable method and return a sequence of numbers. If you follow control flow of the program, notice that each item in the list was calculated on demand, rather than all at once; this is a lazy list.&lt;/p&gt;
&lt;p&gt;Lazy lists are fascinating because they can, in principle, represent an infinite series of items. Here is an infinite list of primes:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;int&amp;gt; primes = Primes();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;int&amp;gt; primeEnumerator = primes.GetEnumerator();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(5, primeEnumerator);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(7, primeEnumerator);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(&amp;quot;\nPress any key to continue. . .&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Print(int numberOfPrimes, IEnumerator&amp;lt;int&amp;gt; primeEnumerator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Next {0} primes&amp;quot;, numberOfPrimes);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 1; i &amp;lt;= numberOfPrimes; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; primeEnumerator.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp; Console.WriteLine(primeEnumerator.Current);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; Primes()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; int max = (int)Math.Sqrt((double)i);&lt;br /&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;&amp;nbsp;&amp;nbsp; bool isPrime = true;&lt;br /&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;&amp;nbsp;&amp;nbsp; for (int count = 2; count &amp;lt;= max; count++)&lt;br /&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;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (i % count == 0)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isPrime = false;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&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;&amp;nbsp;&amp;nbsp; if (isPrime)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return i;&lt;br /&gt;&amp;nbsp;&lt;br /&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;&amp;nbsp;&amp;nbsp; i++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;This prints:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next 5 primes:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next 7 primes:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 13&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 17&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 23&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 29&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 31&lt;/p&gt;
&lt;p&gt;Now, if we wanted to, we can really abuse the hell out of our prime generator by making it recursive and using it like a prime sieve.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING: the code above is for entertaniment purposely only.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If you use this in production code, you will &lt;strong&gt;lose your job&lt;/strong&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; and&lt;strong&gt; shame your family&lt;/strong&gt;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;int&amp;gt; primes = getPrimes().GetEnumerator();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; 20; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; primes.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp; Console.WriteLine(primes.Current);&lt;br /&gt;&amp;nbsp;&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&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(&amp;quot;\nPress any key to continue. . .&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; counter()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i = 2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;br /&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;&amp;nbsp;&amp;nbsp; yield return i++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; filter(int prime, IEnumerator&amp;lt;int&amp;gt; listen)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; listen.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp; int i = listen.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp; if (i % prime != 0)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static IEnumerable&amp;lt;int&amp;gt; getPrimes()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;int&amp;gt; myCounter = counter().GetEnumerator();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; myCounter.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp; int num = myCounter.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp; yield return num;&lt;/p&gt;
&lt;p&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;&amp;nbsp;&amp;nbsp; myCounter = filter(num, myCounter).GetEnumerator();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;This returns:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 13&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 17&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 23&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 29&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/p&gt;
&lt;p&gt;I have to give credit where credit is due: the inspiration the prime sieve implementation above is ripped from &lt;a href="http://video.google.pl/videoplay?docid=810232012617965344"&gt;Rob Pike&amp;#39;s talk&lt;/a&gt; on NewSqueak. I noticed that Pike used channels as sequence generators, which can be represented as IEnumerables in C#.&lt;/p&gt;
&lt;p&gt;My code runs out of stack space after the first 50,000 primes of so. Pike&amp;#39;s implementation, on the other hand,&amp;nbsp;efficiently&amp;nbsp;exploits a feature in NewSqueak that allows a programmer to literally replace the current stack frame with a call to another method (a remarkable feature to find outside of functional languages), a luxury that doesn&amp;#39;t exist in C#.&lt;/p&gt;
&lt;p&gt;This is an inefficient way to generate primes, but a remarkable exercise in generating sequences.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=86" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>The Interview That Sucked</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/08/12/the-interview-that-sucked.aspx</link><pubDate>Wed, 13 Aug 2008 01:40:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:74</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&lt;strong&gt;And it begins...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every so often when you&amp;#39;re searching for a new job, you find one or two companies that seem a little shady. You know if you submit an application, you&amp;#39;re going to get an interview; and if you get an interview, you&amp;#39;re going to get hired; and if you get hired, you&amp;#39;re going to kill yourself in 3 months.&lt;/p&gt;
&lt;p&gt;Most of us know what kind of red flags to look for when a job will really truly suck. I was not so informed.&lt;/p&gt;
&lt;p&gt;When I was making the move from stocking shelves to professional&amp;nbsp;programming, I started searching for entry-level programming positions. I happened across an ad for a small startup saying something along the lines of: &amp;quot;URGENT HELP NEEDED! Looking for 2&amp;nbsp;VB.Net Programmers With SQL Server Experience. ALL LEVELS OF EXPERIENCE CONSIDERED!!!!!&amp;quot;&lt;/p&gt;
&lt;p&gt;Now, one of the red flags in any help wanted ad is the word &amp;quot;URGENT&amp;quot; in all caps. Another one is where the ratio of exclamation points to sentences exceeds a threshold of 1.75:1. But still, I decided I&amp;#39;d learn&amp;nbsp;what this company was all&amp;nbsp;about if it needed programmers so urgently; apparently they write ASP.Net&amp;nbsp;content-management software&amp;nbsp;used all over the world.&amp;nbsp;Sounds fun, right? I applied at this job, and was asked to come into an interview a week later. I figure I have a shot because I have 7 years of prior web development of experience,&amp;nbsp;used SQL Server 2000 and 2005 for the better part of 4 years, and&amp;nbsp;have been working with VB.Net since 2003; I think I have the technical skill to fill an &amp;quot;ANY LEVEL OF EXPERIENCE CONSIDERED&amp;quot; position.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Interviewees from Lala Land&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When I get to the building, I&amp;#39;m directed to a waiting room. There are two other guys there who have applied for the same position. One of the guys is a grizzled,&amp;nbsp;older-type fella; the other was a young guy, early 20s, and very sharply dressed -- wearing what appeared to be a tuxedo, actually.&lt;/p&gt;
&lt;p&gt;I really hate sitting in quiet rooms with other people, so I make small talk with these guys. I ask the older guy about his programming experience, and he makes a comment that he last worked on an&amp;nbsp;old COBOL system sometime in 1987; afterward, he was a mechanic, but was laid off; and presently he works in a factory assembly line screwing plastic caps on bottles of shampoo. Sweet mother of Christ, what a sad story. What kind of mistakes in your life do you have to make to slide from software developer, to mechanic, to screwing caps on bottles for a living? One thing&amp;#39;s for sure: this guy is no threat to me; he has no relevant work experience.&lt;/p&gt;
&lt;p&gt;Tuxedo guy introduces himself as a college student at one of the nearby universities, and I make a comment that he is remarkably&amp;nbsp;well-spoken for a college student. He&amp;nbsp;replies that he&amp;nbsp;was a national champion in a public speaking / forensics competition (it certainly shows). I start talking to him about programming, and then I notice he&amp;#39;s looking at me with the most idiotic dog-faced expression I&amp;#39;ve ever seen in my life. I decided to test&amp;nbsp;Tuxedo guys technical knowledge:&lt;/p&gt;
&lt;p style="PADDING-LEFT:30px;"&gt;Do you at least know SQL?&lt;br /&gt;&amp;quot;Nope.&amp;quot;&lt;/p&gt;
&lt;p style="PADDING-LEFT:30px;"&gt;Are you familiar with object oriented programming? For example, do you know what a class is?&lt;br /&gt;&amp;quot;Nope.&amp;quot;&lt;/p&gt;
&lt;p style="PADDING-LEFT:30px;"&gt;Have you ever heard of the word &amp;#39;boolean&amp;#39;? Do you know what variables are?&lt;br /&gt;&amp;quot;I &lt;em&gt;think&lt;/em&gt; so,&amp;nbsp;its&amp;nbsp;kinda like&amp;nbsp;Java, right?&amp;quot;&lt;/p&gt;
&lt;p&gt;Fuck me sideways! Somehow I managed to keep myself from falling on the floor laughing.&amp;nbsp;Tuxedo guy was beyond clueless. Utterly, appallingly braindead.&lt;/p&gt;
&lt;p&gt;The interview gods were clearly smiling upon me: on the one hand, I have Shampoo Lid whose 20-year outdated expertise is overshadowed by his&amp;nbsp;career as a professional screw capper, and Tuxedo guy who can&amp;#39;t tell the difference between a fast fourier transformation and a bifunctor&amp;nbsp;catamorphism on a monoidal category.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Interview&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After a few minutes of chit-chat, I man asks all three of us in the waiting room to join him in an office for the group interview.&lt;/p&gt;
&lt;p&gt;Group interview? I&amp;#39;ve heard of these things. These are the kinds of interviews where an interviewer asks a question like &amp;quot;why are you better than the guy to the left of you&amp;quot; and you have to try topping the answers of everyone around you. I&amp;#39;ve NEVER heard of anything good coming out of these interviews, and I consider them to be deeply unprofessional. Normally, I would just say &amp;quot;sorry, I&amp;#39;m not going to play any games during this interview&amp;quot; and walk out, but given my opponents Shampoo Lid and Tuxedo guy, I figured there&amp;#39;s no point passing up an interview that I will definitely &amp;quot;win&amp;quot;.&lt;/p&gt;
&lt;p&gt;In the interviewing room, there are two other interviewers. Apparently, all three of us were going to interviewed by these three judges. Weird. I&amp;#39;ve never seen or heard of this before.&lt;/p&gt;
&lt;p&gt;Everyone sits down and the judges ask Shampoo Lid the basic interview questions: &amp;quot;where do you see yourself in 5 years&amp;quot;, &amp;quot;what can you contribute to the company&amp;quot;, &amp;quot;why did you leave your last job&amp;quot;, etc. Altogether, this question/answer session lasts about 10 minutes. It was a very mundane, even boring interview.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m next. The judges pull out a copy of my resume. They make a comment that some parts of it were not very clear --- and to a certain extent, they were right. I&amp;#39;d never written a resume or&amp;nbsp;applied for a technical position before, so it was probably not the best resume ever written. They ask me an odd question: &amp;quot;what do you mean when you say you have experience writing software for end-users&amp;quot;. The judges basically read a sentence from my resume and asked to explain it... I&amp;#39;m not really sure what they need explaining, it says I have experience writing end-user software, what else can I say? The judges prod me for an answer, so I explain to them that there is all different kinds of software, such as end-user software, middleware, system software, and all of these different tiers of software require different skills to pull off effectively. Applications like Notepad vs SQL Server vs ethernet drivers vs system kernal represent software in each different tier, and my specialization is writing applications that your average computer user interacts with on an everyday basis. I thought I gave a decent answer, at least one that shows off my technical knowlege.&lt;/p&gt;
&lt;p&gt;The judges precede to the next sentence in my resume and ask me to explain it. And then they asked me to explain the next sentence. And the next one. They read my resume out loud word for word and asked me to explain every sentence. Seriously, they asked me &amp;quot;what does &amp;#39;O&amp;#39;-&amp;#39;O&amp;#39;-&amp;#39;P&amp;#39; mean here?&amp;quot; It was pathetic. My &amp;quot;interview&amp;quot;, consisting of the judges regurgitating every line of my resume back at me, lasted 6&amp;nbsp;minutes. 7 tops. It was embarrassing and pathetic.&lt;/p&gt;
&lt;p&gt;The judges talk to Tuxedo guy last. They start by commenting on how well he was dressed, and Tuxedo guy makes a comment about wearing the same outfit that he wore when he won his speech competition. He goes off on a tangent about how, after he won, he earned a scholarship to help pay for a missionary trip to Africa. He talks about how he&amp;#39;s known his girlfriend since elementary school, how much he likes bathing dogs, and just all sorts of irrelevant anecdotes. Not a single moment of his 40 minute interview did he say anything about writing code.&lt;/p&gt;
&lt;p&gt;After everyone interview, the judges leave the room for a few minutes. They come back and thank Shampoo Lid and I for our time; however, they say&amp;nbsp;to Tuxedo Guy,&amp;nbsp;&amp;quot;we think you&amp;#39;ll fit in really well here, and we&amp;#39;d like to make you&amp;nbsp;an offer&amp;quot;. I was absolutely furious, I swear to god I was ready to start cracking skulls and breaking bodies. The interview was an embarrassing, mocking waste of my time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Job Hunting Again&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Back to the job search. I noticed the ad at the software company I interviewed for that day had been updated to say &amp;quot;Looking for&amp;nbsp;1&amp;nbsp;VB.Net Programmers With SQL Server Experience&amp;quot;. Eventually, the ad disappeared altogether.&lt;/p&gt;
&lt;p&gt;It took about a month, but I was fortunate enough to apply for&amp;nbsp;a different job and get an interview, which went extremely well. This interview was&amp;nbsp;extremely technical in nature, consisting of&amp;nbsp;questions like&amp;nbsp;&amp;quot;heres a database schema, now write a query to get this set of data&amp;quot;, instead of bullshit throwaway questions like &amp;quot;where do you see yourself in 5 years&amp;quot;.&amp;nbsp;I nailed the interview and&amp;nbsp;got the job.&lt;/p&gt;
&lt;p&gt;Now, I normally heed the advice, &amp;quot;as soon as you find a job, start looking for a new one&amp;quot; just a safety net; I don&amp;#39;t plan on getting fired from my jobs, but it helps to know who&amp;#39;s hiring and whats in demand just in case.&lt;/p&gt;
&lt;p&gt;So, as I&amp;#39;m paging through job listings, I come across a help eerily familiar help wanted ad from the same small startup company&amp;nbsp;who&amp;nbsp;royally fucked up interview 4 weeks prior: &amp;quot;URGENT HELP NEEDED! Looking for 2&amp;nbsp;VB.Net Programmers With SQL Server Experience. ALL LEVELS OF EXPERIENCE CONSIDERED!!!!!&amp;quot; I laughed so hard I shat myself.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=74" width="1" height="1"&gt;</description></item><item><title>Communicating Between User Controls In ASP.Net Pages</title><link>http://awesomeprincess.com/blogs/programming/archive/2008/08/10/communicating-between-user-controls-in-asp-net-pages.aspx</link><pubDate>Sun, 10 Aug 2008 03:02:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:62</guid><dc:creator>Princess</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;In general, when I&amp;#39;m creating websites in ASP.Net, I tend to create a lot of user controls. More or less, all of the user interface of embedded in user controls, so that I can encapsulate and reuse specific functionality on any page of my website.&lt;/p&gt;
&lt;p&gt;For example, lets say I have a screen that asks a user to login: on a successful login, the screen displays a welcome message to the user. I would create two user controls, one for the login panel and one for the welcome message, and display them like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://awesomeprincess.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/programming/Layout1.gif" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The diagram above is a fairly simple layout, and a fairly typical way of designing controls. You might imagine that, on a successful login, the LoginPanel disappears, and the WelcomeMessage displays something along the lines of &amp;quot;Welcome, Bob! You have two new messages.&amp;quot;; maybe on an unsuccessful login, the WelcomeMessage displays something along the lines of &amp;quot;Oops, wrong username or password.&amp;quot;&lt;/p&gt;
&lt;p&gt;Since our LoginPanel is contained in its own usercontrol, it does not know of the existence of the WelcomeMessage control; since the WelcomeMessage usercontrol is also self-contained, it does not know about the LoginPanel. Yet, we have to make the WelcomeMessage change its state when a user is successfully authenticated from the LoginPanel -- somehow, our LoginPanel and WelcomeMessage controls need to communicate with one another.&lt;/p&gt;
&lt;p&gt;Here is some sourcecode to show the problem in a more concrete sense:&lt;/p&gt;
&lt;p&gt;-----------&lt;/p&gt;
&lt;p&gt;LoginPanel.ascx&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;%@ Control Language=&amp;quot;C#&amp;quot; ClassName=&amp;quot;LoginPanel&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsAuthenticated&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ViewState[&amp;quot;IsAuthenticated&amp;quot;] == null&lt;br /&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;&amp;nbsp;&amp;nbsp; ? false&lt;br /&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;&amp;nbsp;&amp;nbsp; : (bool)ViewState[&amp;quot;IsAuthenticated&amp;quot;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private set&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ViewState[&amp;quot;IsAuthenticated&amp;quot;] = value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void btnLogin_Click(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsAuthenticated =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (txtUsername.Text == &amp;quot;user&amp;quot; &amp;amp;&amp;amp; txtPassword.Text == &amp;quot;secret&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Username: &amp;lt;asp:TextBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;txtUsername&amp;quot; /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Password: &amp;lt;asp:TextBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;txtPassword&amp;quot;&lt;br /&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;&amp;nbsp;&amp;nbsp; TextMode=&amp;quot;Password&amp;quot; /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:Button runat=&amp;quot;server&amp;quot; ID=&amp;quot;btnLogin&amp;quot; Text=&amp;quot;Login&amp;quot; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onclick=&amp;quot;btnLogin_Click&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;WelcomeMessage.ascx&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;%@ Control Language=&amp;quot;C#&amp;quot; ClassName=&amp;quot;WelcomeMessage&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void SetMsg(string msg)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblMsg.Text = msg;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:Literal runat=&amp;quot;server&amp;quot; ID=&amp;quot;lblMsg&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Default.aspx&lt;br /&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;%@ Register src=&amp;quot;LoginPanel.ascx&amp;quot; tagname=&amp;quot;LoginPanel&amp;quot; tagprefix=&amp;quot;uc1&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;%@ Register src=&amp;quot;WelcomeMessage.ascx&amp;quot; tagname=&amp;quot;WelcomeMessage&amp;quot; tagprefix=&amp;quot;uc2&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&lt;/span&gt;&lt;a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;html xmlns=&amp;quot;&lt;/span&gt;&lt;a href="http://www.w3.org/1999/xhtml"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://www.w3.org/1999/xhtml&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Untitled Page&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;uc1:LoginPanel ID=&amp;quot;LoginPanel1&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;uc2:WelcomeMessage ID=&amp;quot;WelcomeMessage1&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;-----------&lt;/p&gt;
&lt;p&gt;(The WelcomeMessage control is admittedly pretty lame.)&lt;/p&gt;
&lt;p&gt;So, we have two user controls. When a user logs in, we need to display the correct view in mviewControlPanel and set the welcome message appropriately. Now, there are a few &amp;quot;obvious&amp;quot; solutions to this problem; I&amp;#39;ll run through a list of possible solutions and comment on them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#1)&lt;/strong&gt; You could simply check the LoginPanel1.Authenticated property on Page_Load, and set everything appropriately. For example, on Default.aspx, you could replace the Page_Load event with the following:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Page.IsPostBack)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (LoginPanel1.IsAuthenticated)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; LoginPanel1.Visible = false;&lt;br /&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;&amp;nbsp;&amp;nbsp; WelcomeMessage1.SetMsg(&amp;quot;Hello, User!&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That looks like it should do the trick, but it doesn&amp;#39;t actually work because the code exceutes in the wrong order. Oops! The ASP.Net page life cycle processes the events in the following order:&lt;/p&gt;
&lt;p&gt;- Default.aspx.Page_Load&lt;br /&gt;- LoginPanel.aspx.btnLogin_Click&lt;/p&gt;
&lt;p&gt;Since the Page_Load event reads the IsAuthenticated property *before* it gets assigned, your page processes incorrectly.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;#2)&lt;/strong&gt; To solve the the little &amp;quot;events not executing in the right order&amp;quot; problem above, you might be tempted to move the code above out of the Page_Load event, and into the Page_PreRender event so that it happens later in the page lifecycle.&lt;/p&gt;
&lt;p&gt;This works, but its a notoriously bad work around. The Page_PreRender event gets called on every postback, and its not reasonable to check the LoginPanel.IsAuthenticated variable and re-setup all of the dependent user controls everytime. Setting up a user control for Authenticated/Unauthenticated mode might require a number of database queries or heavy data processing of some kind.&lt;/p&gt;
&lt;p&gt;Additionally, this solution simply scale very well. If we had a large number of interacting controls, the Page_PreRender event would begin to get very bloated. Similarly, if we had a requirement to make the WelcomeMessage talk back to the login control (for example, by putting a logout button in the WelcomeMessage), it would simply be a nightmare to program correctly: on the one hand, you hide the LoginPanel when its IsAuthenticated property is true, on the other you show the LoginPanel when the WelcomeMessage&amp;#39;s LoggedOut property is true. What happens when a user logs in, then logs back out? How do you know which order to check the variables?&lt;/p&gt;
&lt;p&gt;Ideally, when a user logs in (or logs out), you want all of your controls to respond appropriately on demand.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;#3)&lt;/strong&gt; We want the WelcomeMessage text to be set on demand whenever we log in, so the WelcomeMessage needs to respond to an event raised by the LoginPanel. Since ASP.Net is an event-driven language, its trivial to create an event handler&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public event EventHandler UserLoggedIn;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ,..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void btnLogin_Click(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsAuthenticated =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (txtUsername.Text == &amp;quot;user&amp;quot; &amp;amp;&amp;amp; txtPassword.Text == &amp;quot;secret&amp;quot;);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (UserLoggedIn != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserLoggedIn(this, EventArgs.Empty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now, we can wire up Default.aspx to this event handler:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;%@ Register src=&amp;quot;LoginPanel.ascx&amp;quot; tagname=&amp;quot;LoginPanel&amp;quot; tagprefix=&amp;quot;uc1&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;%@ Register src=&amp;quot;WelcomeMessage.ascx&amp;quot; tagname=&amp;quot;WelcomeMessage&amp;quot; tagprefix=&amp;quot;uc2&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&lt;/span&gt;&lt;a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void LoginPanel1_UserLoggedIn(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (LoginPanel1.IsAuthenticated)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoginPanel1.Visible = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WelcomeMessage1.SetMsg(&amp;quot;Welcome, User!&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoginPanel1.Visible = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WelcomeMessage1.SetMsg(&amp;quot;Bad username or password&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;html xmlns=&amp;quot;&lt;/span&gt;&lt;a href="http://www.w3.org/1999/xhtml"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://www.w3.org/1999/xhtml&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Untitled Page&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;uc1:LoginPanel ID=&amp;quot;LoginPanel1&amp;quot; runat=&amp;quot;server&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnUserLoggedIn=&amp;quot;LoginPanel1_UserLoggedIn&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;uc2:WelcomeMessage ID=&amp;quot;WelcomeMessage1&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;The event-driven approach is definitely superior to the methods enumerated above: we change the state of our WelcomeMessage the very moment we click the &amp;#39;login&amp;#39; button, and we don&amp;#39;t have to worry about the page lifecycle. Additionally, if the WelcomeMessage needed to trigger some kind of response in the LoginPanel.aspx control, we could just create an event on WelcomeMessage, catch it on Default.aspx, and call the right methods LoginPanel.&lt;/p&gt;
&lt;p&gt;Notice that LoginPanel and WelcomeMessage do not talk directly to one another. Since they don&amp;#39;t know about each others existence, the web page itself acts as a kind of proxy to channel communication from one control to the next.&lt;/p&gt;
&lt;p&gt;Now, while the code above looks pretty good, it is not scalable in the least:&lt;/p&gt;
&lt;p&gt;- Since the web page is our proxy, we can only we can only notify WelcomeMessage of events triggered in LoginPanel through WelcomeMessage&amp;#39;s public methods. This forces us to expose a lot of implementation detail to our web page whenever we need two controls to communicate.&lt;/p&gt;
&lt;p&gt;- The example above is somewhat contrived because LoginPanel and WelcomeMessage located on the same container. In the real world, there are probably going to be multiple layers of containers between your LoginPanel and your WelcomeMessage control, similar to this:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://awesomeprincess.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/programming/Layout2.gif" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It is too cumbersome and tedious to raise your UserLoggedIn event up through all of its parent user controls, then pass the information back down through all of the nested user controls. As a result, your pages become bloated with code to pass events up and down through controls, and your pages become difficult to modify because moving or deleting any control on your website causes a compilation error.&lt;/p&gt;
&lt;p&gt;- What if, for some reason, you wanted to add another control, such as a NewMessages control, which listened for the UserLoggedIn event? Well, now you have to write more code to funnel events to the WelcomeMessage control and NewMessages control at the same time.&lt;/p&gt;
&lt;p&gt;- Even the graphic above is too generous. For example, if your LoginPanel control is on a master page, and your WelcomeMessage control is on a child page, you don&amp;#39;t have the luxury of even knowing what controls exist on a page to funnel messages through, you don&amp;#39;t even know if an instance of WelcomeMessage exists to handle your events.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Hopefully now we can see the problem with the method above. We need a more robust message-passing interface to satisfy the following conditions:&lt;/p&gt;
&lt;p&gt;- We don&amp;#39;t want to go through hierarchies of controls. No matter where controls are placed on a page, no matter how deeply nested inside other controls they are, we never want more than one proxy of communication between any two controls at a time.&lt;/p&gt;
&lt;p&gt;- We cannot assume that our controls are conveniently embedded into our user interfaces at design time, rather than dynamically created on the fly at runtime.&lt;/p&gt;
&lt;p&gt;- We do not want to expose the internal implementation of our controls if we can avoid it.&lt;/p&gt;
&lt;p&gt;- We need to accomodate new controls who need to listen for events transparently; that is, without needing to change any lines of code in our message-passing interface&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;#4)&lt;/strong&gt; We can satisfy all of the requirements above very easily if we just think about the problem a little differently. It really helps to seperate out message-passing logic from our user interface, so we should create a class which serves the role as a proxy between our LoginNotifier and any other controls:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.SessionState;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;namespace Notification&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface ILoginListener&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void NotifyUserLoggedIn(bool authenticated);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class LoginNotifier&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static LoginNotifier SessionInstance&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; HttpSessionState session = HttpContext.Current.Session;&lt;br /&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;&amp;nbsp;&amp;nbsp; if (session[&amp;quot;LoginNotifier&amp;quot;] == null)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session[&amp;quot;LoginNotifier&amp;quot;] = new LoginNotifier();&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&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;&amp;nbsp;&amp;nbsp; return (LoginNotifier)session[&amp;quot;LoginNotifier&amp;quot;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private LinkedList&amp;lt;ILoginListener&amp;gt; notifiers = new LinkedList&amp;lt;ILoginListener&amp;gt;();&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private LoginNotifier() { }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Register(ILoginListener listener)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; notifiers.AddLast(listener);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Unregister(ILoginListener listener)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; notifiers.Remove(listener);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Notify(bool authenticated)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (ILoginListener listener in notifiers)&lt;br /&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;&amp;nbsp;&amp;nbsp; listener.NotifyUserLoggedIn(authenticated);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now we have an adequate proxy to notify controls of the UserLoggedIn event. To use this class, we need to re-write the LoginPanel.btnLogin_Click event as follows:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family:courier new,courier;"&gt;public bool IsAuthenticated&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ViewState[&amp;quot;IsAuthenticated&amp;quot;] == null&lt;br /&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;&amp;nbsp;&amp;nbsp; ? false&lt;br /&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;&amp;nbsp;&amp;nbsp; : (bool)ViewState[&amp;quot;IsAuthenticated&amp;quot;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private set&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ViewState[&amp;quot;IsAuthenticated&amp;quot;] = value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void btnLogin_Click(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsAuthenticated =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (txtUsername.Text == &amp;quot;user&amp;quot; &amp;amp;&amp;amp; txtPassword.Text == &amp;quot;secret&amp;quot;);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Notification.LoginNotifier.SessionInstance.Notify(IsAuthenticated);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Now, we need to register WelcomeMessage.ascx with the notifier. I&amp;#39;d prefer to implement the ILoginListener interface on my control; however, since I originally wrote the WelcomeMessage.ascx file using inline script blocks, but I want to provide my own constructor and implement an interface, which means I need to convert to the code-behind model.&lt;/p&gt;
&lt;p&gt;WelcomeMessage.ascx:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;%@ Control Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CodeFile=&amp;quot;WelcomeMessage.ascx.cs&amp;quot; Inherits=&amp;quot;WelcomeMessage&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:Literal runat=&amp;quot;server&amp;quot; ID=&amp;quot;lblMsg&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;WelcomeMessage.ascx.cs:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;using System;&lt;br /&gt;using System.Web.UI.WebControls;&lt;br /&gt;using Notification;&lt;br /&gt;public partial class WelcomeMessage : System.Web.UI.UserControl, ILoginListener&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public WelcomeMessage()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoginNotifier.SessionInstance.Register(this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void Dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoginNotifier.SessionInstance.Unregister(this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.Dispose();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void NotifyUserLoggedIn(bool authenticated)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string msg = authenticated&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ? &amp;quot;Welcome, User!&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &amp;quot;Bad username or password&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetMsg(msg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void SetMsg(string msg)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblMsg.Text = msg;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Everything simply works like magic. My default.aspx page never needs to know or care about the LoginPanel or the WelcomeMessage controls anymore. More imporantly, this code is reusable; an indefinite number of controls can register themselves with this notifier, and I don&amp;#39;t need to add any new code to pass messages up and down through any control hierarchies whatsoever.&lt;/p&gt;
&lt;p&gt;As of right now, if we wanted to create a new event to listen on, we&amp;#39;d have to create a new interface and listener class. There are a lot of ways to make the pattern above a little more generic and reusable, for example:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;public class Notifier&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static Notifier SessionInstance&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; HttpSessionState session = HttpContext.Current.Session;&lt;br /&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;&amp;nbsp;&amp;nbsp; if (session[&amp;quot;EventNotifier&amp;quot;] == null)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session[&amp;quot;EventNotifier&amp;quot;] = new Notifier();&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&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;&amp;nbsp;&amp;nbsp; return (Notifier)session[&amp;quot;EventNotifier&amp;quot;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Dictionary&amp;lt;string, EventHandler&amp;gt; eventPool;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Notifier()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eventPool = new Dictionary&amp;lt;string, EventHandler&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Register(string eventID, EventHandler handler)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler temp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (eventPool.TryGetValue(eventID, out temp))&lt;br /&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;&amp;nbsp;&amp;nbsp; eventPool[eventID] = temp + handler;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&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;&amp;nbsp;&amp;nbsp; eventPool.Add(eventID, handler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Unregister(string eventID, EventHandler handler)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler temp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (eventPool.TryGetValue(eventID, out temp))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp; temp -= handler;&lt;br /&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;&amp;nbsp;&amp;nbsp; if (temp != null)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eventPool[eventID] = temp;&lt;br /&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;&amp;nbsp;&amp;nbsp; else&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eventPool.Remove(eventID);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Notify(string eventID, object sender)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Notify(eventID, sender, EventArgs.Empty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Notify(string eventID, object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler temp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (eventPool.TryGetValue(eventID, out temp) &amp;amp;&amp;amp; temp != null)&lt;br /&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;&amp;nbsp;&amp;nbsp; temp(sender, e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The class above allows a client to register named events. For example:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Notifier.SessionInstance.Register(&amp;quot;UserLoggedIn&amp;quot;, SomeEventHandler);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are many variations on the pattern above, such as notifying listeners asyncronously, using generics to pass more specific type information than the EventArgs base class, etc.&lt;/p&gt;
&lt;p&gt;As a final note: none of the code above is threadsafe. Make sure that you put locks around any code that adds, removes, or enumerates through items in a collection.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=62" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/ASP.Net/default.aspx">ASP.Net</category></item><item><title>Beautiful Code and The Beast</title><link>http://awesomeprincess.com/blogs/programming/archive/2008/08/06/beautiful-code-and-the-beast.aspx</link><pubDate>Wed, 06 Aug 2008 22:37:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:52</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;div class="snap_preview"&gt;
&lt;p&gt;I&amp;rsquo;m one of those programmers who emphasizes heavily on the aesthetic appeal of code. I describe certain pieces of well-written code as beautiful and elegant, and poorly written code as ugly or dirty. I like &lt;a href="http://www.linuxjournal.com/article/3882"&gt;&lt;span style="color:#004276;"&gt;Eric Raymond&amp;rsquo;s explanation of beautiful code&lt;/span&gt;&lt;/a&gt;: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Writing these [large Perl programs of significant complexity] left me progressively less satisfied with Perl. Larger project size seemed to magnify some of Perl&amp;rsquo;s annoyances into serious, continuing problems. The syntax that had seemed merely eccentric at a hundred lines began to seem like a nigh-impenetrable hedge of thorns at a thousand. &amp;ldquo;More than one way to do it&amp;rdquo; lent flavor and expressiveness at a small scale, but made it significantly harder to maintain consistent style across a wider code base. And many of the features that were later patched into Perl to address the complexity-control needs of bigger programs (objects, lexical scoping, &amp;ldquo;use strict&amp;rdquo;, etc.) had a fragile, jerry-rigged feel about them. &lt;/p&gt;
&lt;p&gt;These problems combined to make large volumes of Perl code seem unreasonably difficult to read and grasp as a whole after only a few days&amp;rsquo; absence. Also, I found I was spending more and more time wrestling with artifacts of the language rather than my application problems. And, most damning of all, the resulting code was ugly&amp;mdash;this matters. Ugly programs are like ugly suspension bridges: they&amp;rsquo;re much more liable to collapse than pretty ones, because the way humans (especially engineer-humans) perceive beauty is intimately related to our ability to process and understand complexity. A language that makes it hard to write elegant code makes it hard to write good code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The elegance of code seems to coincide with its readability, brevity, and intuitively obvious implementation.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Ultimate Measure of Software is User Experience&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;From a realistic point of view, the ultimate goal of writing software should be to satisfy users. Users only care about their user experience, they &lt;a href="http://www.codinghorror.com/blog/archives/001022.html"&gt;&lt;span style="color:#004276;"&gt;couldn&amp;rsquo;t care less what your beautiful code looks like&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Its tempting to think that there&amp;rsquo;s no point to writing elegant code if users are never going to appreciate it. I used to agree with this sentiment before I started developing software professionally, before I really saw the effects of bad code in the real world.&lt;/p&gt;
&lt;h2&gt;Thank you, come again&lt;/h2&gt;
&lt;p&gt;Every year, my company attempts to start selling a new piece of banking software. Two years ago, the company wrote up specs on a piece of teller software, eTeller [actual name of software changed to project job], and decided it would be easiest to outsource this software to contracters in India. Our relationship with India was simple: my company would make the business decisions and request features, and India would deliver the code.&lt;/p&gt;
&lt;p&gt;After a year of unsupervised development, we started selling version 1.0 of eTeller. As we expect in the normal lifecycle of&amp;nbsp;any&amp;nbsp;software, we got bug reports, enhancement and new feature requests, etc. India was happy to make the changes...&lt;/p&gt;
&lt;p&gt;... until around 6 months into the project when&amp;nbsp;India began to slip; they simply&amp;nbsp;weren&amp;#39;t able to keep pace with the change requests.&amp;nbsp;After v1.0 was installed, the list of known bugs was on the rise, development of new features came to a stagnant halt, and&amp;nbsp;user satisfaction was taking a&amp;nbsp;dive. The application had serious stability problems, such as crashing or freezing 40 to 50 times a day (not an exaggeration) and a general inability to keep cash drawers balanced.&lt;/p&gt;
&lt;p&gt;When bank presidents started putting the president of my company on speed-dial to demand bug fixes or threaten to find a new software vendor, we realized we had a problem. Since India was unable to make changes to the software, we decided that we simply couldn&amp;#39;t rely on&amp;nbsp;India to do their jobs right;&amp;nbsp;we requested access to their sourcecode repository to&amp;nbsp;make the changes ourselves. And that&amp;rsquo;s when we saw it for the first time:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:16pt;color:#ff0000;font-family:Mistral, Chiller, Impact, Arial Bold;"&gt;The Beast&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every programmer will eventually encounter &lt;b&gt;The Beast&lt;/b&gt;: an application exceeding 10,000 or 100,000 or 1,000,000 lines of the worst, most twisted, most utterly evil, fantastically wicked, atrociously written code on the planet.&lt;/p&gt;
&lt;p&gt;These multi-megabyte monsters are born when large companies attempt to save a few pennies by hiring unskilled amateurs to do professional work. Beasts often rear their heads most often in mission-critical systems such as banks, hospitals, insurance companies, air-traffic controllers, grocery stores, routers.&lt;/p&gt;
&lt;p&gt;Even for a Beast, eTeller was a fright to behold. Here is a brief list of evil:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More than 130,000+ lines of tangled, completely unmodularized C#. &lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Excluding form files, there were only 2 classes used in the entire application:&lt;br /&gt;1) A static class called &amp;ldquo;Globals&amp;rdquo;, which held 1000s of variables to maintain the state of application. There were no other datatypes used in the Globals class apart from bool, string, decimal, and dataset.&lt;br /&gt;2) This&amp;nbsp;&lt;a href="http://www.sharpdeveloper.net/source/SqlHelper-Source-Code-cs.html"&gt;&lt;span style="color:#004276;"&gt;SQLHelper class&lt;/span&gt;&lt;/a&gt; copy/pasted from the internet. &lt;br /&gt;&lt;/li&gt;
&lt;li&gt;20,000 lines of code embedded in a single file called frmMain.cs. All other code in the application accessed frmMain directly in this fashion:
&lt;pre&gt;((frmMain)this.MDIParent).UpdateStatusBar(hstValues);&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;To look up accounts, the programmers did something like this:
&lt;pre&gt;bool blnAccountExists =
    new frmAccounts().GetAccountInfo().blnAccountExists&lt;/pre&gt;
&lt;p&gt;As bad as it already is creating an invisible form to perform business logic, how do you think the form knew which account to look up? That&amp;rsquo;s easy: the form could access Globals.lngAcctNum and Globals.strAcctType. (Hungarian&amp;nbsp;notation? What is this, 1997 all over again?)&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Parameters were rarely passed between functions, since all state was held in the Globals class. In the rare instance that parameters were passed, they were passed as strings for convenience.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Nearly all methods and functions had side-effects, no matter the purpose the function, usually modifying 1 or more variables in the Globals namespace. For example, one of the form validation methods had a mysterious side effect of calculating over and short payments on loans for whatever account was stored Globals.lngAcctNum. &lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Some forms had invisible labels. The programmers used the .Text and .Tag properties to hold miscellaneous data. &lt;br /&gt;&lt;/li&gt;
&lt;li&gt;No objects existed in the application. The only datastructures used were ArrayLists, HashTables, and DataSets &amp;mdash; none of which guarantee type safety. The programmers actually invented bizarre pseudo-objects using just ArrayLists, HashTables, and DataSets:&lt;br /&gt;- ArrayLists of hashtables&lt;br /&gt;- HashTables using arraylists as keys and other hashtables as values&lt;br /&gt;- Arraylists of arraylists&lt;br /&gt;- HashTables using DataRows as keys and ArrayLists as values&amp;nbsp;&amp;nbsp;
&lt;p&gt;For a static Accounts class in particular, the programmer created a seperate HashTable for each concievable property of an account: a HashTable called hstAcctExists, hstAcctNeedsOverride, hstAcctFirstName.&lt;/p&gt;
&lt;p&gt;The keys for all of those hashtables was a &amp;ldquo;|&amp;rdquo; seperated string. Concievable keys included &amp;ldquo;123456|DDA&amp;rdquo;, &amp;ldquo;24100|SVG&amp;rdquo;, &amp;ldquo;100|LNS&amp;rdquo;, etc. (Most of these hashtables were easy to convert to typed Dictionary objects at first, and eventually into a unified Account object.) &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CTRL-C, CTRL-V was a favorite key combination employed by India. For example, the 500 lines of code required to print receipts was copied across 7 forms. The code required to implement the &amp;quot;customizable grid&amp;quot; feature was copy/pasted verbatim across 12 different forms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;There was an unusual threading model, which I call the Thread-And-Timer model. Every form that used threading had 1 or more timers on it (1 timer per thread). The Thread-And-Timer model looks like this:
&lt;pre&gt;bool finished = false;
Thread backgroundThread;
public void SomePublicMethodThatsEnevitablyInvokedRandomlyByAnotherForm()
{
     try
     {
         backgroundThread.Abort();
     }
     catch { // swallow }
     finished = false;
     backgroundThread = new Thread(someMethod);
     timer1.Enabled = true;
}

publiv void someMethod()
{
    // do stuff in the background
    finished = true;
}

private void timer1_Tick(object sender, TimerEventArgs e)
{
    try
    {
        if (finished == true)
            backgroundThread.Abort();
    }
    catch { // swallow }
}
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;Each time you click a button, it would start a new thread. If you click the button before the thread finishes its job, then the thread is aborted so that another new job is started. After starting a thread, a timer would check some bool at intervals of 100 milliseconds. When the bool is set to true, the timer aborts the thread for some reason and the resulting ThreadAbortException is ignored.&lt;/p&gt;
&lt;p&gt;This bizarre pattern was found in a dozen different places throughout the application. Naturally, every thread in the application freely accessed any variable, including the ones in the Globals class, without locking. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Spectacular abuse of the ternary operator. Here are some actual snippets of code pulled from the application:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new,courier;"&gt;strDrCr = chkCredits.Checked &amp;amp;&amp;amp; chkDebits.Checked ? string.Empty : chkDebits.Checked ? &amp;quot;D&amp;quot; : chkCredits.Checked ? &amp;quot;C&amp;quot; : &amp;quot;N&amp;quot;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;if (strDefaultVals == strNowVals &amp;amp;&amp;amp; (dsTranHist == null ? true : dsTranHist.Tables.Count == 0 ? true : dsTranHist.Tables[0].Rows.Count == 0 ? true : false))&lt;br /&gt;&lt;br /&gt;if (Validations(parPostMode == &amp;quot;ADD&amp;quot; ? true : false))&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is only a small tip of the iceburg, barely a fraction of all of the errors in eTeller. The most damning part of the application was the total absence of unit tests. Not a single test, for a single one of the 130,000 lines of code. It was evident why the programmers were unable to make changes.&lt;/p&gt;
&lt;h2&gt;Crisis-Driven Development&lt;/h2&gt;
&lt;p&gt;After seeing the state of eTeller&amp;rsquo;s ugly code, my dev team became heavily involved with the development and maintenance of this application. From Nov 2007 to Jan 2008, we entered a state of crisis-driven development.&lt;/p&gt;
&lt;p&gt;Banks were demanding to have bugs fixed on the same day they were reported. Each new bug sent us into crisis-mode: we fixed bugs as fast as possible and send a new release to QA almost immediately. Inevitably, 5 new bugs would be documented within minutes of QA testing, so we&amp;rsquo;d fix those up as quickly as possible.&lt;/p&gt;
&lt;p&gt;Against the recommedations of QA and developers, we were releasing new versions of eTeller once every 2 to 3 days for a couple of months. There were many occasions where we&amp;rsquo;d be writing bug fixes to a release &lt;i&gt;minutes&lt;/i&gt; before updates at a bank.&lt;/p&gt;
&lt;p&gt;Over time, we stablized our product just enough to add new features and respond to bug reports at a reasonable pace. eTeller is continuously being refactored, piece by piece, into a better application everyday.&lt;/p&gt;
&lt;h2&gt;What did I learn from The Beast&lt;/h2&gt;
&lt;p&gt;While my team was working on eTeller, I discovered how ugly code has a psychological effect on programmers. The amount of frustration working with the code simply sucks the vitality out of programmers, it makes programmers ashamed of their own creations. Unhappy programmers don&amp;rsquo;t produce quality code or good tests, which holds back the development of application in the long run. Unahppy programmers tend to look for new, less stressful jobs, which also hurts development.&lt;/p&gt;
&lt;p&gt;My team has been hacking through the jungle of eTeller code since Nov 2007. We&amp;rsquo;ve made significant improvements (especially with regard to type-safe objects and seperation of business logic from UI). We&amp;rsquo;ve re-written about 25% of the code in eTeller (which, fortunately, corresponds to about 90% of the core eTeller functionality) to the point where the code is marginally palatable.&amp;nbsp;The application&amp;nbsp;line-count is down to around 53,000 non-trivial lines of code, and drops at a rate of 20kb per week. We estimate the final &amp;#39;gold&amp;#39; version of this application will drop to around 25,000 non-trivial&amp;nbsp;lines of code.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t let anyone tell you that the beauty of code does not matter to users. High quality code, more often than not, corresponds to a high quality product and satisfying user experience. If programmers want to satisfy our users, then we&amp;rsquo;re obliged to write high quality, beautiful code in all of our applications.&lt;/p&gt;
&lt;p&gt;(In case you&amp;#39;re wondering,&amp;nbsp;we eventually terminated our contract with India.)&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=52" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/India/default.aspx">India</category><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/CodeSod/default.aspx">CodeSod</category></item><item><title>Jesus Who? (Redux)</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/08/04/jesus-who-redux.aspx</link><pubDate>Mon, 04 Aug 2008 20:47:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:30</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Yesterday&amp;#39;s post &lt;a href="http://awesomeprincess.com/blogs/princess/archive/2008/08/03/jesus-who.aspx"&gt;Jesus Who&lt;/a&gt; was so full of awesome and win, I decided to give it another go:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ehealthforum.com/health/topic11288.html"&gt;Jesus was a demon&lt;/a&gt;: I have talked to jesus. I was baptised catholic. Spoke with the angels in the cathedrals, they taught me how to pray. Then I found out jesus was a demon. He&amp;#39;s a very big one, a warden in the prison that contains the demons. And if you want the life of comfort, then bow down to him, worship him and swear to abort and exclude other demons, and he will give you pleasure and comfort. But stand up and fight him, and he fights just like a demon.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.atheists.org/christianity/didjesusexist.html"&gt;Jesus never existed&lt;/a&gt;: For most of my life, I had taken it for granted that Jesus, although certainly not a god, was nevertheless an historical personage - perhaps a magician skilled in hypnosis. To be sure, I knew that some of the world&amp;#39;s greatest scholars had denied his existence. Nevertheless, I had always more or less supposed that it was improbable that so many stories could have sprung up about someone who had never existed.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://counago-and-spaves.blogspot.com/2005/06/he-should-have-worn-stockings.html"&gt;Jesus died of a blood clot&lt;/a&gt;: An Israeli researcher has challenged the popular belief that Jesus died of blood loss on the cross, saying he probably succumbed to a sometimes fatal disorder now associated with long-haul air travel. &lt;/p&gt;
&lt;p&gt;Professor Benjamin Brenner wrote in The Journal of Thrombosis and Haemostasis that Jesus&amp;#39;s death, traditionally believed to have occurred 3-6 hours after crucifixion began, was probably caused by a blood clot that reached his lungs.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.necronomi.com/projects/amor/"&gt;Jesus wants to eat your soul&lt;/a&gt;: Does God love you? Of course not. &lt;/p&gt;
&lt;p&gt;God &lt;em&gt;hates&lt;/em&gt; you; but God is hungry and needs you to help Him eat your soul. He chuckles to himself that He cannot only suck out your life and being, but He can make you believe the lie as well.&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;The remaining items are a list of messianic theories collected a few years ago by a poster on the Randi.org forums by the name of Dr Adequate (&lt;a href="http://forums.randi.org/showthread.php?t=40133"&gt;clicky&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.nashvillecitypaper.com/news.php?viewStory=36603"&gt;Jesus hates fags and environmentalists, votes Republican&lt;/a&gt;: So how would Jesus vote? I believe that Jesus would have issues with some of the liberal stances. I don&amp;#39;t think Jesus would under any circumstances tell any woman, &amp;quot;It&amp;#39;s OK to have an abortion this time.&amp;quot; I don&amp;#39;t think Jesus would agree with homosexuals having any rights simply due to the fact that they choose to be homosexual. Lastly, I&amp;#39;m pretty sure Jesus would want prayer in school, and His commandments in every courtroom.&lt;/p&gt;
&lt;p&gt;So to answer your question, I believe Jesus would vote Republican. And I believe His response to your global warming fear would be, &amp;quot;Don&amp;#39;t worry, I am in control and I don&amp;#39;t need to rely on you to &amp;#39;save the planet.&amp;#39;&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.worldmagblog.com/blog/archives/007647.html"&gt;Jesus supports public prayer, whatever he may have said in the gospels to the contrary&lt;/a&gt;&amp;nbsp;(dead link):&amp;nbsp; I am sure Jesus would vote Republican because he would is against abortion, supporting people who refused to support themselves, he is into investing wisely, public prayer, and standing up for the 10 commandments.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.worldmagblog.com/blog/archives/007647.html"&gt;Jesus is against public healthcare because it&amp;#39;s a blasphemous interference with god&amp;#39;s plan. Private health care isn&amp;#39;t, for some reason&lt;/a&gt;&amp;nbsp;(dead link):&amp;nbsp; Jesus did not come to earth to offer free medical care. He used healing as a way to prove His Godliness to those He wanted to so that people would be drawn to Him as Lord and Savoir. He also fed the hungry for the same reason... As to health care entitlement, where do you see that in the Bible? It is not there. The Bible is full of stories of suffering and death, as the natural consequence of our sinfullness. If along the way you are able to ease your suffering or cure your illness due to God&amp;#39;s gift of medicine to our world, that is fine, but no where does the Bible state that it is available to all nor that life should be extended beyond God&amp;#39;s planned timing, because of our lack of faith in the gifts of heaven that await us after we leave this earth.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.usmessageboard.com/forums/showthread.php?t=13570"&gt;Jesus likes small government&lt;/a&gt; : Jesus was all about &amp;#39;less&amp;#39; government (Church) in man&amp;#39;s life...That&amp;#39;s not very &amp;#39;democrat&amp;#39;, is it?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://209.157.64.200/focus/f-news/793390/posts"&gt;Jesus supports a flat rate income tax, hates &amp;quot;demon scum rats&amp;quot;&lt;/a&gt;: Would Jesus steal? Ask others to covet what &amp;quot;the rich&amp;quot; have? Would he condone murder of innocent children in partial birth abominations? Would he put up government as a god to be worshipped? How many of the 10 commandments can a democrat break before rolling out of bed? &lt;/p&gt;
&lt;p&gt;Governments are supposed to be subject to God. Blessed is the nation whose god is the Lord. The king is supposed to hand write a personal copy fo the Bible for his his personal use - to keep it fresh in his mind. . He is not supposed to screw around with every intern and rape women. He is not supposed... ok enough already... The govt is supposed to get by on a flat 20%.... but don&amp;#39;t let facts or truth get in the way of these demon scum rats.&lt;/p&gt;
&lt;p&gt;
&lt;hr /&gt;
&lt;/p&gt;
&lt;p&gt;That&amp;#39;s everything I can find on Jesus.&amp;nbsp;I am still looking for:&lt;/p&gt;
&lt;p&gt;Jesus was from Michigan&lt;/p&gt;
&lt;p&gt;Jesus was a Jiffy Lube employee&lt;/p&gt;
&lt;p&gt;Jesus was a Klingon (although &lt;a href="http://clancmsf.tripod.com/KlingonsForChrist.html"&gt;this&lt;/a&gt; is close)&lt;/p&gt;
&lt;p&gt;Jesus was a bitch (a lover, a child, a mother, a sinner, a saint...)&lt;/p&gt;
&lt;p&gt;Jesus was an embryo&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=30" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/WTF/default.aspx">WTF</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/Jesus/default.aspx">Jesus</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/Christianity/default.aspx">Christianity</category></item><item><title>Jesus Who?</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/08/03/jesus-who.aspx</link><pubDate>Mon, 04 Aug 2008 01:22:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:29</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Who was Jesus? Lord and savior of the world? That&amp;#39;s only half the story...&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.religioustolerance.org/chr_jegay.htm"&gt;Jesus was gay&lt;/a&gt;: Some commentators argue from silence. They note that there is no passage in the Christian Scriptures (New Testament) that directly describes anything about Jesus&amp;#39; sexuality. There are many direct and indirect references to Jesus&amp;#39; sensuality. He was accused of being a &amp;quot;drunkard and a glutton&amp;quot; and of partying with &amp;quot;prostitutes and sinners.&amp;quot; He apparently enjoyed a tender foot massage from a woman. Yet, neither Jesus&amp;#39; sexuality nor his celibacy is mentioned. Yet, sex is referred to, elsewhere in the Bible, quite often. One might argue that the books in the Christian Scriptures might have once described Jesus&amp;#39; sexual relationships, but that these passages have been vigorously censored by the later church because they were unconventional.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://web.ukonline.co.uk/buddhism/jesus.htm"&gt;Jesus was a Buddhist&lt;/a&gt;: Jesus had expounded his doctrine of patience, non-violence and compassion which was seemingly an opposite view to that of the God according to the Old Testament. Jesus preached and asked his followers to turn the other cheek when somebody slapped you, whist an eye for an eye and a tooth for a tooth in the Mosaic Law clearly denoted retaliation and vengeance which were regarded as justice.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.caribvoice.org/Opinions/M.Roberts/christ.html"&gt;Jesus was black&lt;/a&gt;: And lastly, by making Christ Black, it identified him with oppressed Black folks. For in all of religious history Christ had always sided with the poor, the downtrodden and disenfranchised. His ministry was one of liberation. Since Blacks have been on the receiving end of white racism, it stands to reason that Christ, not only identified with their plight but became their image and likeness. &lt;br /&gt;There is sound reason to believe that Jesus Christ was Black.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://media.www.themichigantimes.com/media/storage/paper620/news/2004/12/06/Opinion/Jesus.Was.A.Democrat-827151.shtml"&gt;Jesus was a democrat&lt;/a&gt;:&amp;nbsp;I have also heard that President Bush now has political currency. He has a strong majority that has a clear mandate. Supporters of the President have demanded religion over rhetoric. These opinions made me think, &amp;ldquo;What would Jesus do?&amp;rdquo; I am not a biblical scholar so I pulled out a Bible. I couldn&amp;rsquo;t believe what I found! Jesus was a democrat!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.wnd.com/news/article.asp?ARTICLE_ID=44563"&gt;Jesus was a woman&lt;/a&gt;: A publisher is touting a new edition of the Gospels that identifies Christ as a woman named Judith Christ of Nazareth.&lt;/p&gt;
&lt;p&gt;LBI Institute says its version, Judith Christ of Nazareth, The Gospels of the Bible, Corrected to Reflect that Christ Was a Woman, Extracted from Matthew, Mark, Luke and John, takes Thomas Jefferson&amp;#39;s edited Gospel one step futher by &amp;quot;correcting&amp;quot; the gender of Christ and God.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.moonsweb.com/ifjesus.shtml"&gt;Jesus was a witch&lt;/a&gt;: If Jesus were here today, he would be a witch! No single one of these reasons prove the Witchiness of Jesus; but taken as a whole, they make for a compelling case.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.fstdt.com/fundies/comments.aspx?q=13583"&gt;Jesus was a white nationalist&lt;/a&gt;: God hates therefore I hate. God only cares about the Adamic white race therefore I only care for the Adamic white race, bastard.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.samarthbharat.com/dhiruquestion.htm"&gt;Jesus was a Hindu&lt;/a&gt;: Christianity has changed in the past three hundred years and is still in a state of flux. You must realize that Jesus Christ did not write the Bible, which was written a couple of centuries after the death of Jesus. Old Testament was opposed by Jesus and yet the Christians accepted it. In my opinion Jesus was a Hindu saint who was persecuted in the land of his birth. His followers made some compromises with the ruling classes and built a religion. The renaissance brought Christianity closer to Hinduism as I understand it. Please download my article &amp;quot;Hinduism - A global Religion of the Modern World&amp;quot; to read more about it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.mailarchive.ca/lists/alt.bible/2004-05/1684.html"&gt;Jesus was an anti-Semite&lt;/a&gt;: Since Jesus called the Jews of his day liars, vipers, sons of Satan, etc., you should also consider Jesus antisemitic. Consequently, you should immediately cease and desist trying to claim Jesus was Jewish. Jesus was not a Jew; Jesus was an antisemite.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.sprengmeister.org/nsfw/jesusishitler/"&gt;Jesus was Hitler&lt;/a&gt; (spoof): Jesus is an evil, anti-Semitic coward. Just look at how fake he is. He claims to be the son of &amp;quot;God&amp;quot;, and that he stands for good will towards men, but what he doesn&amp;#39;t want you to know is that he is God&amp;#39;s diabolical prodigal son. He spends all of his spare time killing Jews and punching babies. He tricked us all into believing that he was the &amp;quot;messiah&amp;quot;, and that him being crucified was merely a sacrifice to absolve mankind for all of their sins. When in reality he was crucified by the Jews as a result of years of showboating and being a straight up dick.&lt;/p&gt;
&lt;p&gt;Jesus first developed his severe hatred of Jews when he submitted a dreidel with a swastika painted on one of the four sides. The idea was rejected by the Jewish community because they thought the symbol was &amp;quot;stupid&amp;quot; and this hurt Jesus&amp;#39;s feelings. The swastika was later used by Jesus as Hitler and is now known as a symbol of hatred toward Jews. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.poetrycritical.net/read/13766/"&gt;Jesus was an alcoholic&lt;/a&gt;: Kissing the nape of my neck,&lt;br /&gt;I can smell the whiskey on his beard.&lt;br /&gt;Jesus was an alcoholic.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dionysus.org/x0101.html"&gt;Jesus was Emmanuel Swedenborg&lt;/a&gt;: Contrary to popular belief, The Last Judgment, as foretold in the book of Revelation, occurred in the year 1757, and under the auspices of Emanuel Swedenborg, a gifted scientist, theologian&amp;mdash;and, mystic. All of which has been thoroughly detailed in his work, The Apocalypse Revealed, a verse for verse account to the book of Revelation.&lt;/p&gt;
&lt;p&gt;Therefore when the Bible speaks of Christ&amp;#39;s second coming, it&amp;#39;s actually referring to Emanuel Swedenborg and his work&amp;mdash;as Swedenborg claims. And, while it may sound farfetched, it&amp;#39;s all there. Much in the way Emanuel is another name for Jesus and means, &amp;quot;God with us&amp;quot; Matthew 1:23&amp;nbsp; with its familiar ring to John the Baptist: who wasn&amp;#39;t really Elija (Elias), yet this was who he signified.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.macphoenix.com/creative/vix/jesuschristwasacoolcat.html"&gt;Jesus was a cool cat&lt;/a&gt;: Jesus Christ was a cool cat&lt;br /&gt;I say the things that&amp;rsquo;ll make you think&lt;br /&gt;so think about that&lt;br /&gt;Break out your sandals and grow your hairs long&lt;br /&gt;Live in a civilization where whores belong&lt;br /&gt;... helping the poor get on&lt;br /&gt;... healing the sores&amp;rsquo; on&lt;br /&gt;all those engrossed by that leprosy.&lt;br /&gt;Your problem&amp;rsquo;s with all them that lack verity:&lt;br /&gt;He wasn&amp;rsquo;t talkin&amp;rsquo; about no heresy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=29" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/WTF/default.aspx">WTF</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/Jesus/default.aspx">Jesus</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/Christianity/default.aspx">Christianity</category></item><item><title>Opinions on Animal Rights</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/08/02/opinions-on-animal-rights.aspx</link><pubDate>Sun, 03 Aug 2008 00:36:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:20</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;For once, I&amp;#39;m actually satisified with the quality of a video&amp;nbsp;I published on youtube:&lt;/p&gt;
&lt;p&gt;(Please visit the site to view this media)&lt;/p&gt;
&lt;p&gt;As most people know, I&amp;#39;ve been a vegan and animal rights activist for 4 or 5 years now. I&amp;#39;m even a card-carrying member of PETA.&lt;/p&gt;
&lt;p&gt;The video above is a little crude, and certainly not a comprehensive account of my own moral philosophy (if you&amp;#39;ve ever followed the debates I&amp;#39;ve participated in over the past couple of years, you&amp;#39;ll notice the amount of material I&amp;#39;ve written on the topic could fill a Stephen King novel), but its at least a pre-emptive reply to people who believe that species is&amp;nbsp;a moral characteristic or believe that evolution is a moral theory.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=20" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/animal+rights/default.aspx">animal rights</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/youtube/default.aspx">youtube</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/PETA/default.aspx">PETA</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/veganism/default.aspx">veganism</category></item><item><title>Coming Out Story - Before and After</title><link>http://awesomeprincess.com/blogs/princess/archive/2008/07/27/coming-out-story-before-and-after.aspx</link><pubDate>Sun, 27 Jul 2008 14:40:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:8</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;(Please visit the site to view this media)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=8" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/coming+out/default.aspx">coming out</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/family/default.aspx">family</category><category domain="http://awesomeprincess.com/blogs/princess/archive/tags/homophobia/default.aspx">homophobia</category></item><item><title>__doPostBack throws error 'object doesn't support this property or method' </title><link>http://awesomeprincess.com/blogs/programming/archive/2008/07/26/dopostback-throws-error-object-doesn-t-support-this-property-or-method.aspx</link><pubDate>Sat, 26 Jul 2008 19:06:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:6</guid><dc:creator>Princess</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;When I was setting up Community Server on this site, I modified the site templates to include a&amp;nbsp;PayPal&amp;nbsp;donation button. After getting positioned where I wanted it, everything seemed to work fine and dandy. Today, I attempted signing out and back in to test some other changes, and Community Server started throwing a javascript error:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;object doesn&amp;#39;t support this property or method (line 39, char 9)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Which happened to correspond to the line of code highlighted in red:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;
&lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;//&amp;lt;![CDATA[&lt;br /&gt;var theForm = document.forms[&amp;#39;aspnetForm&amp;#39;];&lt;br /&gt;if (!theForm) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; theForm = document.aspnetForm;&lt;br /&gt;}&lt;br /&gt;function __doPostBack(eventTarget, eventArgument) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!theForm.onsubmit || (theForm.onsubmit() != false)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theForm.__EVENTTARGET.value = eventTarget;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theForm.__EVENTARGUMENT.value = eventArgument;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theForm.submit();&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;//]]&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It was a strange error, because the code is autogenerated by ASP.Net. I&amp;nbsp;thought my browser was screwed up, so I tried restarting it, testing the page in different browsers,&amp;nbsp;looking for malformed HTML, but no luck.&lt;/p&gt;
&lt;p&gt;I happened to have a copy of Community Server that actually worked. I diff&amp;#39;ed a page from my working copy against a page of my non-working Community Server and didn&amp;#39;t notice the error at first, The only changes between the two pages was the addition of a URL and IMG tag for my donation button. I took a closer look at HTML and noticed the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif&amp;quot; border=&amp;quot;0&amp;quot; name=&amp;quot;&lt;span style="color:#ff0000;"&gt;submit&lt;/span&gt;&amp;quot; alt=&amp;quot;PayPal - The safer, easier way to pay online!&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The code I copy/pasted from PayPal include an item with a name attribute with the value &amp;quot;submit&amp;quot;. The __doPostBack function calls the &amp;#39;submit&amp;#39; method on the form... howver, there&amp;#39;s an HTML element already on my form called submit. Javascript thinks the code is trying to do something with the IMG element, but it gets confused and throws a fit.&lt;/p&gt;
&lt;p&gt;Solution to the error: remove the superfluous &amp;#39;name&amp;#39; attribute from the IMG tag.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://awesomeprincess.com/aggbug.aspx?PostID=6" width="1" height="1"&gt;</description><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/ASP.Net/default.aspx">ASP.Net</category><category domain="http://awesomeprincess.com/blogs/programming/archive/tags/PayPal/default.aspx">PayPal</category></item><item><title>Managing Open Forms in an Multi-Form Application</title><link>http://awesomeprincess.com/blogs/programming/archive/2008/07/26/managing-open-forms-in-an-multi-form-application.aspx</link><pubDate>Sat, 26 Jul 2008 05:15:00 GMT</pubDate><guid isPermaLink="false">5b2b8b95-f2ad-492a-86e5-c44566407b1e:7</guid><dc:cre