tag:blogger.com,1999:blog-68009344464578987932009-07-20T20:15:13.246-04:00MoserwareJeff Moser's software development adventures.Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.comBlogger41125tag:blogger.com,1999:blog-6800934446457898793.post-33300617646485644692009-07-20T08:00:00.003-04:002009-07-20T19:01:39.208-04:00Just Enough MBA to Be a Programmer<p>There's that awkward moment in your software development life when you realize that most of the people in your company <i>aren't</i> programmers. Scanning your address book reveals Marketing, Sales, Accounting, Human Resources, and yes, the "business people" with their Masters of Business Administration (MBAs).</p><p><a href="http://www.amazon.com/gp/product/0060799072?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060799072"><img style="margin: 0px 0px 0px 10px;" src="http://ecx.images-amazon.com/images/I/51SXTGSSDDL._SL160_.jpg" align="right" /></a>I've always been curious about what MBAs really do. In my weaker moments, I've even thought that the only reason people got an MBA was to demand a higher salary or to "move up the corporate ladder" into some management job. What did these MBA ninjas actually learn in school? Would having an MBA help me better understand how I affected my company's bottom line? Although I had the curiosity, I never acted on it. This changed when <a title="Chad Fowler" href="http://chadfowler.com/">another programmer</a> <a title="see page 53 of The Passionate Programmer" href="http://www.amazon.com/gp/product/1934356344?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356344">recommended</a> that I read <a title="The Ten-Day MBA" href="http://www.amazon.com/gp/product/0060799072?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060799072">The Ten-Day MBA</a> by <a href="http://www.harpercollins.com/authors/18530/Steven_A_Silbiger/index.aspx">Steven Silbiger</a>.</p><p>Sure, I knew that no one would anoint me with a real MBA at the end of the book any more than watching <a id="n.bd" title="MIT's Open Courseware" href="http://ocw.mit.edu/OcwWeb/web/home/home/index.htm"><span style="color: rgb(128, 0, 128);">MIT</span></a> lectures online would make me an MIT grad. Besides, going to a <a title="... like the Harvard Business School" href="http://www.hbs.edu/mba/">nice</a> <a title="or Wharton" href="http://www.wharton.upenn.edu/mba/">MBA</a> <a title="... or Stanford" href="http://www.gsb.stanford.edu/mba/">school</a> is more about being around other motivated people and professors. The real value in having an MBA is in applying the concepts, not the concepts themselves. </p><p>Disclaimers aside, I was determined to read the book and take notes on what a programmer should know about an MBA.</p><h4>Day 1 - Marketing</h4><p>Every developer painfully learns that technology doesn't win on its own. At best, it just <span style="color: rgb(128, 0, 128);"><a title="Fast forward to 2:50 to hear Seth talk about this" href="http://video.google.com/videoplay?docid=-6909078385965257294">gives you a shot at marketing</a></span>. Marketing is proof that software doesn't sell itself, <a title="Good programmers don't need no marketing by Alain Raynaud" href="http://blog.fairsoftware.net/2009/07/09/good-programmers-dont-need-no-marketing/">no matter how good it is</a>. </p><p>A software company might have a <a href="http://www.birds-eye.net/definition/m/mrd-market_requirements_document.shtml">Marketing Requirements Document</a> (MRD) that outlines what the next version will contain. This usually is the result of a standard marketing analysis that the book outlined: </p><ol><li>Consumer Analysis - Who are they? What do they want? How many different segments of people do you have? Is the buyer of your product different than the user? (The book gives the example that women buy the majority of men's socks and underwear, thus it's good to market appropriately).</li><li>Market Analysis - How big is your target market? Is it new? Is it growing? Where is the product in the life cycle?</li><li>Competitive Analysis - How do your <a href="http://en.wikipedia.org/wiki/SWOT_analysis">Strengths, Weaknesses, Opportunities, and Threats</a> (SWOTs) compare to your competition? </li><li>Distribution Analysis - What "channels" does your company use to reach your customer? Who are the intermediate players (e.g. the Apple Store, Amazon.com, etc)? What cuts do they take? What are their motivations?</li><li>Plan the Marketing Mix - How will you differentiate your products? How will you place it, promote it, and price it?</li><li>Determine the Economics - How long will it take before you break even? What are your fixed costs vs. margin costs? (Thankfully software has a low marginal cost)</li><li>Revise - Tweak and repeat as needed. </li></ol><p>One big marketing theme is to "own a word in the consumer's mind":</p><blockquote id="s3hx">If you establish one benefit in the consumer's mind, the consumer may attribute other positives as well to your product. FedEx means "overnight delivery." Only one company can own a word and it is tough to change it once it's established... The easiest way to own a word is to be first. Consumers tend to stick with products that work for them. Kleenex cleans runny noses. p.26</blockquote><p>This explains why your family still uses <a id="yvuv" title="MapQuest" href="http://www.mapquest.com/">MapQuest</a> despite your repeated attempts to show them how much better <a id="zkkz" title="Google Maps" href="http://maps.google.com/">Google Maps</a> is. It's also helpful if your product name matches what it does. "<a href="http://www.drano.com/">Drano</a>" is easier to remember than a "Web 2.0" name like <a href="http://www.qoop.com/">Qoop</a>. </p><p>I was surprised to learn that the popular online advertising term <a href="http://en.wikipedia.org/wiki/Cost_per_impression">Cost per Thousand</a> (CPM), is a relatively old term that has long existed in print media. In general, the more targeted a group is, the higher the CPM is. This explains why a programming ad on <a href="http://stackoverflow.com/">Stack Overflow</a> can probably fetch a better CPM than the same ad on a site like <a href="http://www.pandora.com/">Pandora</a>, even though programmers use both. </p><p>Marketing people typically have their reasons for doing things that frustrate us. For example, if your software will take a long time to get through a distribution channel or marketing foresees a long customer buying process, they might begin to "market" your code long before a beta is available with the belief that it'll hopefully be read by the time the customer is ready to buy.</p><p>Sometimes marketing has to make an extreme choice. When GTE faced rebuilding its tarnished brand in the 1990's, it was probably a clever marketing person who suggested that they <a id="s4-7" title="gave up on fixing their brand" href="http://blip.tv/file/319044/">give up on fixing their brand name</a> and re-brand themselves as <a href="http://en.wikipedia.org/wiki/Verizon_Communications">Verizon</a>.</p><p>Despite all the good advice, I was disappointed by the book's lack of coverage of the Apple/BMW style of "marketing" <a title="Watch at 20:27" href="http://video.google.com/videoplay?docid=-6909078385965257294&amp;ei=P5NiSvPbFIb2qAL9jLS-DA&amp;q=seth+godin">the engineering department can do</a> by creating a remarkable product. Creating a product that allows users to quickly jump over the "<a href="http://headrush.typepad.com/creating_passionate_users/2006/03/how_to_be_an_ex.html">suck threshold</a>" is just one example where a programmer can make a tremendous "marketing" contribution.</p><h4>Day 2 - Ethics</h4><p>Ethics seems easy to understand: "<a id="i7rk" title="Do to others as you would have them do to you" href="http://www.biblegateway.com/passage/?search=Luke%206:31">Do to others as you would have them do to you</a>." The hard part is realizing how the "others" are affected by your actions. Others include customers, executives, shareholders, suppliers, employees (and their families), the government, the planet, and the "future generations." </p><p>Unfortunately, when simplicity is lost, <a id="d4a3" title="Sarbanes-Oxley Act" href="http://en.wikipedia.org/wiki/Sarbanes-Oxley_Act">Sarbanes-Oxley Act</a>s are found.</p><h4>Day 3 - Accounting</h4><p>In theory, accounting is simple. Just answer these questions about your <a id="d3fl" title="entity" href="http://www.answers.com/topic/accounting-entity">entity</a>/business: </p><blockquote id="tdpx"><ul><li>What does a company own? </li><li>How much does a company owe others? </li><li>How well did a company's operations perform? </li><li>How does the company get the cash to fund itself? - p.72 </li></ul></blockquote><p>If you get nothing else out of accounting, know how to read a balance sheet. Although Microsoft CEO <a id="cnhl" title="Steve Ballmer" href="http://en.wikipedia.org/wiki/Steve_Ballmer">Steve Ballmer</a> dropped out of Stanford's MBA program to become employee #24, he <a id="pk2-" title="The quote begins around 10:50" href="http://ecorner.stanford.edu/authorMaterialInfo.html?mid=2242">knew balance sheets were important</a>:</p><blockquote id="v580">In 1980, I came in to "be a business person" whatever that meant. Didn't know much. Frankly all I'd ever really done is interview for jobs and market brownie mix. I wasn't exactly well credentialed. I'd taken the first year at Stanford Business School so <i>I can read a balance sheet -- that was pretty important</i>. We didn't have that much money back then so there wasn't much to read. But anyway those lessons were important.</blockquote><p>Balance sheets are simple to follow:</p><blockquote id="kkr6">As the name implies, the balance sheet is a "balance" sheet. The fundamental equation that rules over accounting balance is:<br /><p>Assets (A) = Liabilities (L) + Owners' Equity (OE) </p><p>What you own (assets) equals the total of what you borrowed (liabilities) and what you have invested (equity) to pay for it. This equation or "identity" explains <i>everything</i> that happens in the accounting records of a company over time. Remember it! - p.83</p></blockquote><p>For example, your work computer is a company asset (which explains the "asset" tag on it). Your company created an equal liability to pay for it. When your company started, the founders gave up some of their money to increase the new company's cash assets (left side) in exchange for stock in the company (right side). </p><p>For example, we can read <a href="http://www.google.com/finance?q=NASDAQ:GOOG&amp;fstype=ii">Google's balance sheet</a> for the first quarter of 2009 and see:</p><p>Assets = $33.51 Billion<br />Liabilities = $3.66 Billion<br />Owner Equity = $29.85 Billion (which includes $14.98 Billion in "retained earnings" that Google is keeping for growth rather than giving it back to the owners of its 315.75 million shares)</p><p>Sure enough, everything "balances":</p><div style="text-align: left;" id="ptq0"><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SmKJ_BwtVCI/AAAAAAAABfU/BAq3TOcY2UI/s1600-h/GoogleBalances.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SmKJ_BwtVCI/AAAAAAAABfU/BAq3TOcY2UI/s400/GoogleBalances.png" /></a></div><p>From basic data, we can derive a bunch of helpful ratios to see how healthy Google is: </p><ol><li>Liquidity/Current Ratio = (Current Assets / Current Liabilities) = 33.51 / 3.66 = 9.14 (Greater than 1 means there's room to pay for liabilities)</li><li>Financial Leverage = (Total Liabilities + Owners' Equity) / OE = (3.66 + 29.85) / 29.85 = 1.12 (Greater than 2 indicates a company is using a lot of debt to operate)</li><li><a id="ufzr" title="Return on Equity" href="http://en.wikipedia.org/wiki/Return_on_equity">Return on Equity</a> = (Net Income / Owners' Equity) = 1.42 / 29.85 = 4.77% (Which indicates how efficiently the company is using shareholder equity)</li><li>... and <a id="wcrh" title="many more" href="http://www.reuters.com/finance/stocks/ratios?symbol=GOOG.O&amp;rpc=66">many more</a> ...</li></ol><h4>Day 4 - Organizational Behavior</h4><p>The whole purpose of Organizational Behavior (OB) is to get you to think before you act around people. You want to motivate people? OB has an equation for that: </p><blockquote id="v8oz">Motivation = Expectation of Work will lead to Performance * Expectation Performance will lead to Reward * Value of Reward. </blockquote><p>Feel free to tweak the variables as you see fit. You can <a href="http://en.wikipedia.org/wiki/Management_by_objectives">Manage by Objective</a> (MBO) where you set goals and then get out of the way or you can <a href="http://www.futurecents.com/mainmbwa.htm">Manage by Walking Around</a> (MBWA) where you play a more active role in day-to-day execution. The best choice depends on your environment and culture. You might need to mix the two. Remember that we humans are delicate creatures with our own wants and desires. Be careful.</p><h4>Day 5 - Quantitative Analysis</h4><p>Quantitative Analysis (QA) explains why Excel has so many functions that I'd never heard of. A core idea is that "a dollar today is worth more than a dollar received in the future." (p.173). </p><p>Imagine that someone promises to pay you a dollar in a year if you give them money now. What is that worth to you today? Obviously, it matters on how much you trust them to pay you back. The more you trust them, the more you're willing to give them now. Similarly, the less you trust them, the more you might "discount" that dollar in the future because they're tying up money that could be used for better investments. This is called the "discount" or "hurdle" rate. Having a 10% discount rate means that the dollar in the future has a <a href="http://en.wikipedia.org/wiki/Net_present_value">net present value</a> of $0.91 today: </p><blockquote id="zlcz">$1 * (1 + 10%)<sup>-1</sup> = $0.91</blockquote><p>This simple idea has lots of consequences. For example, let's oversimplify things and say that you can spend $2,000 today to buy and maintain a server that will last for 3 years or you can lock in a price with Amazon for that same server for $800 a year for the same 3 years. A naïve person would just see that $2000 is less than $2400, but a QA person that assigns a 10% discount rate would see:</p><p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SmKMldPXhhI/AAAAAAAABfc/P2aBR0G4E2M/s1600-h/AmazonServerCost.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SmKMldPXhhI/AAAAAAAABfc/P2aBR0G4E2M/s400/AmazonServerCost.png" /></a></p><p>... and come to the conclusion that it's about $10 cheaper, <i>in today's dollars</i>, to have Amazon maintain the server.</p><p>You can also do the inverse calculation. Assume you're Amazon and that server costs you $1800 today and you can get someone to pay you $800 a year for it for 3 years. What is your <a href="http://en.wikipedia.org/wiki/Internal_rate_of_return">internal rate of return</a> for this investment?</p><p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SmKNk33IACI/AAAAAAAABfk/19rEcxVvJC4/s1600-h/IRR.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SmKNk33IACI/AAAAAAAABfk/19rEcxVvJC4/s400/IRR.png" /></a></p><p>Here we see an internal rate of return of about 16% on the server.</p><p>We could also use the time value of money to include valuing users. Early adopters of eBay and Twitter were worth more per user than late adopters because the early ones were more likely to tell their friends who hadn't used the service and thus attract more new people. </p><h4>Day 6 - Finance</h4><p><a id="ex0m" title="Finance" href="http://en.wikipedia.org/wiki/Finance">Finance</a> blends time, money, and risk. </p><p>To start, a business needs a structure that gives it some capital. Popular options include:</p><ul><li><a id="pk97" title="Sole Proprietorships" href="http://en.wikipedia.org/wiki/Sole_proprietorship">Sole Proprietorships</a> - An individual or a married couple. You are effectively your business. All earnings are treated as personal income and taxed appropriately. You take in all the profits but also have unlimited liability. You can't divide the company up. It's simple, but the downside is that it makes it hard to raise money. </li><li><a id="urnx" title="Partnerships" href="http://en.wikipedia.org/wiki/Partnership">Partnerships</a> - Involves more people than a proprietorship. Several people come together and can be <a id="xt93" title="general partners" href="http://en.wikipedia.org/wiki/General_partnership">general partners</a> (each having unlimited liability) or <a id="sjm:" title="limited partners" href="http://en.wikipedia.org/wiki/Limited_partnership">limited partners</a> (liable up to the investment). As a partner, you pay taxes on your percentage of the business's income on your personal taxes. </li><li><a id="yztz" title="Corporations" href="http://en.wikipedia.org/wiki/Corporation">Corporations</a> - Effectively you give birth to a new legal entity that is distinct from the <a id="xyzn" title="shareholders" href="http://en.wikipedia.org/wiki/Shareholder">shareholders</a>. Most large companies are "<a id="r1xw" title="C Corporations" href="http://en.wikipedia.org/wiki/C_Corporation">C Corporations</a>" and have a <a id="lifg" title="double taxation" href="http://en.wikipedia.org/wiki/Double_taxation">double taxation</a> issue where the corporation's income <a id="i78p" title="is taxed" href="http://en.wikipedia.org/wiki/Corporate_tax">is taxed</a> and the dividends it issues to shareholders <a id="rxpn" title="are taxed" href="http://en.wikipedia.org/wiki/Dividend_tax">are taxed</a> as well. If you have a smaller company with fewer than 100 shareholders, you may qualify for "<a id="h::m" title="S Corporation" href="http://en.wikipedia.org/wiki/S_corp">S Corporation</a>" status. S Corporations usually don't pay income tax and instead rely on shareholders to pay the associated tax on their percentage of the income. This tends to give S Corporations the legal liability benefit of corporation status and the single taxation benefit of partnerships. </li></ul><p>Corporations issue stock to raise money. Stock entitles the holder to a <a id="fzru" title="residual" href="http://en.wikipedia.org/wiki/Residual">residual</a> claim on earnings and assets after other debt obligations have been met. One obvious question is "what's a good stock price?" This has a lot of factors, such as a company's growth potential and the company's earnings. Popular metrics include a company's ratio of its stock price divided by its earnings (<a id="pv50" title="P/E ratio" href="http://en.wikipedia.org/wiki/P/E_ratio">P/E ratio</a>). Higher P/E ratios tend to indicate that shareholders have higher expectations the company will grow and eventually make more money in the future. Some examples:</p><p><table id="ob:4" border="1" bordercolor="#000000" cellpadding="3" cellspacing="0" width="193"><tbody><tr><td width="113"><b>Company</b></td><td width="78"><b>P/E Ratio</b></td></tr><tr><td width="115"><a id="tlgy" title="Google" href="http://www.google.com/finance?q=GOOG">Google</a></td><td width="78">31.47</td></tr><tr><td width="117"><a id="u7pc" title="Microsoft" href="http://www.google.com/finance?q=MSFT">Microsoft</a></td><td width="78">13.98</td></tr><tr><td width="118"><a id="d-xj" title="Amazon.com" href="http://www.google.com/finance?q=NASDAQ%3AAMZN">Amazon.com</a></td><td width="78">54.98</td></tr></tbody></table></p><p>After you raised some capital, you should carefully think how you'll spend it. There are many ways to do this. The <a id="d328" title="Payback Period Method" href="http://en.wikipedia.org/wiki/Payback_period">Payback Period Method</a> has you calculate how long it'll take to recover your investment. The shorter the payback period, the less risky the investment is. For example, adding RAM is so cheap that the productivity boost has a short payback period. In contrast, completely rewriting a huge codebase might have <a title="put your company out of business" href="http://www.joelonsoftware.com/articles/fog0000000069.html">put your company out of business</a> before you get your money back.</p><p>Another approach is to use the <a id="pdpm" title="Net Present Value Method" href="http://www.answers.com/topic/net-present-value-method">Net Present Value Method</a> to see how much the investment will return over its lifetime in terms of today's dollars. Once you determine the discount factor to reflect the risk, you only consider investments that have a positive Net Present Value.</p><h4>Day 7 - Operations</h4><p>Operations is about making stuff. Popular operations guys include <a id="x6xv" title="Frederick Taylor" href="http://en.wikipedia.org/wiki/Frederick_Winslow_Taylor">Frederick Taylor</a> from the late 1800's who is famous for breaking up tasks into small pieces and walking around factories with a stopwatch to find the "one right way" of doing them. <a id="f3bd" title="Elton Mayo" href="http://en.wikipedia.org/wiki/Elton_Mayo">Elton Mayo</a>'s bold claim was that caring about your employees mattered. You could even <a title="make terrible working conditions" href="http://en.wikipedia.org/wiki/Hawthorne_effect">make terrible working conditions</a> if the employees were otherwise treated well and felt important. </p><p>Although some MBAs might use some programming techniques like optimizing flow-charts to improve operations, it's more likely to see factory techniques used when managing programmers. Oversimplifying things, software development is a factory that turns <a id="bzo6" title="capital into code" href="http://www.joelonsoftware.com/articles/fog0000000074.html">capital into code</a>. To this end, you'll often see popular manufacturing processes like Toyota's <a id="pmh5" title="Kanban" href="http://en.wikipedia.org/wiki/Kanban">Kanban</a> method of using visual cards to control workflow <a id="pbge" title="sneaking into our offices" href="http://www.infoq.com/articles/hiranabe-lean-agile-kanban">making their way</a> into our world as "new" or "agile" software methodologies.</p><h4>Day 8 - Economics</h4><p>Economics is the magic that allows me to write software in exchange for steak burritos. As <a id="gjfk" title="Adam Smith" href="http://en.wikipedia.org/wiki/Adam_Smith">Adam Smith</a> <a id="k3k4" title="realized" href="http://en.wikipedia.org/wiki/The_Wealth_of_Nations">realized</a>, society as a whole becomes "wealthier" when we seek division of labor to specialize and do something well rather than trying to do everything ourselves poorly.</p><p>At a <a id="rui0" title="micro level" href="http://en.wikipedia.org/wiki/Microeconomics">micro level</a>, economics is a simple matter of supply equals demand. When you look at the larger/<a id="lqz3" title="macro economies" href="http://en.wikipedia.org/wiki/Macroeconomics">macro economies</a>, more complicated equations pop up like <a id="ibn5" title="this one" href="http://en.wikipedia.org/wiki/Equation_of_exchange">this one</a>: </p><blockquote id="vsxg"><a id="bzha" title="Money" href="http://en.wikipedia.org/wiki/Money_supply">Money</a> * <a id="zjn6" title="Velocity" href="http://en.wikipedia.org/wiki/Velocity_of_money">Velocity</a> = <a id="qxwn" title="Price Level" href="http://en.wikipedia.org/wiki/Price_level">Price Level</a> * <a id="e_-." title="Real Gross National Product" href="http://en.wikipedia.org/wiki/Measures_of_national_income_and_output">Real Gross National Product</a></blockquote><p>This equation shows that it's important that money is moving around (e.g. isn't hidden under your mattress) and that prices are stable or have reasonable growth.</p><p>One of the best things about the economics of software is that it has really low marginal costs (e.g. the cost to copy it). With processors, bandwidth, and storage all roughly following <a id="u-75" title="Moore's Law" href="http://en.wikipedia.org/wiki/Moore%27s_Law">Moore's Law</a> exponential curves, the capacity is doubling every 18 - 24 months which implies that the cost for a fixed amount is falling by half over the same period. </p><p>As Chris Anderson points out in his book <a id="kd5-" title="Free" href="http://www.scribd.com/doc/17135767/FREE-full-book-by-Chris-Anderson">Free</a>, it can sometimes makes sense to round these increasingly lower marginal costs down to zero and make money in different ways such as advertising or selling complements. It's hard to find other industries that have as many economic freedoms as software.</p><h4>Day 9 - Strategy</h4><p>Strategy should be simple: have a <a id="r43r" title="remarkable product" href="http://www.ted.com/talks/seth_godin_on_sliced_bread.html">remarkable product</a> <a id="b0zl" title="that people want" href="http://www.paulgraham.com/startuplessons.html">that people want</a>. <a id="o03m" title="Bad things happen" href="http://www.amazon.com/gp/product/1590597214?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590597214">Bad things happen</a> if you don't do this. It's especially helpful if you have a <a id="q4-u" title="cash cow" href="http://en.wikipedia.org/wiki/Cash_cow">cash cow</a> you can milk for lots of money to fund new initiatives. For example, Google makes so much money <a id="xv4_" title="AdSense" href="http://en.wikipedia.org/wiki/AdSense">from ads</a> that it can have <a id="s6ok" title="this" href="http://news.ycombinator.com/item?id=699460">this</a> <a id="sdm_" title="strategy" href="http://mashable.com/2009/07/11/google-equation/">strategy</a>: </p><blockquote id="ug2c">Revenue = Amount of Web Pages Viewed</blockquote><p>Google's strategy of getting you to view lots of pages (which conveniently have Google ads on them) explains a lot of what it does. From wanting to <a id="o6.l" title="speed up the web" href="http://googleblog.blogspot.com/2009/06/lets-make-web-faster.html">speed up the web</a>, to making a free <a id="hy3i" title="phone os" href="http://en.wikipedia.org/wiki/Android_%28operating_system%29">phone OS</a>, to creating a ton of <a id="atyt" title="free services" href="http://en.wikipedia.org/wiki/List_of_Google_products">free services to keep you hooked on the web</a>. Google really doesn't <i>care</i> what you do so long as you enjoy it and take in the targeted ads.</p><p>The book tended to focus on more traditional forms of strategy such as "cost leadership", "differentiation", and "focus on the customer" as well as applying <a id="r7rh" title="game theory" href="http://oyc.yale.edu/economics/game-theory/">lessons</a> from the famous <a title="prisoner's dilemma" href="http://en.wikipedia.org/wiki/Prisoner%27s_dilemma">prisoner's dilemma</a>. I acknowledge that these are important as well, but I think that at its core, strategy can be simple.</p><h4>Day 10 - Minicourses</h4><p>The book ended with "minicourses" in areas relevant to business such as:</p><ul><li>Property (<a id="wn-y" title="real estate" href="http://en.wikipedia.org/wiki/Real_estate">real estate</a>, <a id="fh.s" title="patents" href="http://en.wikipedia.org/wiki/Patent">patents</a>, <a id="n60z" title="copyright" href="http://en.wikipedia.org/wiki/Copyright">copyright</a>, etc)</li><li>Leadership (e.g. schools want to create 'leaders' because they'll be better future donors).</li></ul><p>Although those were interesting, the section I enjoyed the most was on business law. </p><p>In our jobs, we often bump into legal matters. We face <a id="vixg" title="End User License Agreements" href="http://en.wikipedia.org/wiki/Software_license_agreement">End User License Agreements</a> (EULAs) and <a id="i4d8" title="Non-Disclosure Agreements" href="http://en.wikipedia.org/wiki/Non-disclosure_agreement">Non-Disclosure Agreements</a> (NDAs) that we rarely read and often don't fully understand. It was interesting to see any proper <a id="ycgp" title="contract" href="http://en.wikipedia.org/wiki/Contract">contract</a> requires the following four conditions to be valid:</p><ol><li>Capacity of Parties - Parties must have legal authorization and be mentally capable to enter into the agreement.</li><li>Mutual Agreement (Assent) or Meeting of the Minds - There must be a valid offer and an acceptance.</li><li>Consideration Given - Value must be given for the promise to be enforceable.</li><li>Legality - You can't enforce a contract dealing with illegal goods or actions.</li></ol><p>When bad things happen, it can sometimes escalate to a "legal action" which has a <a id="evo2" title="standard procedure" href="http://en.wikipedia.org/wiki/Template:Civil_procedure_%28United_States%29">standard procedure</a> involving steps you sometimes hear in the news:</p><ol><li>Jurisdiction - For a court to hear a case, it must have "jurisdiction" to hear the case and power to bind the parties the decision. </li><li>Pleadings - The paperwork to start the trial process. The plaintiff (p) files a complaint asserting that the defendant (?) has done something wrong and requests a punishment or remedy.</li><li>Discovery - Lawyers gather witnesses and evidence before a trial. Each side is allowed to see the evidence held by the other side.</li><li>Pretrial Conference - The lawyers and judge try to focus the case on the most important issues. This is also good time for out-of-court settlements if possible.</li><li>Trial - Occurs before the court. The jury decides the factual disputes. The case can be thrown out by the judge with a "summary judgment" if it has no merit.</li><li>Jury Instruction by the Judge and the Verdict - The judge instructs the jury about the relevant law involved and the jury makes its decision about the facts and penalty within its authority.</li><li>Posttrial Motions - Options include asking for a retrial if an error of law or procedure occurred (e.g. jury misconduct).</li><li>Appeal - Each party in a lawsuit is entitled to one appeal at an appellate court where they can file a written brief with arguments for a new trial.</li><li>Secure or Enforce the Judgment - Send the person to jail and/or collect money.</li></ol><p>While the short overview was intriguing, it enforced my belief that it's important to have <a id="syvu" title="an attorney or a lawyer" href="http://wiki.answers.com/Q/What_is_the_difference_between_a_lawyer_and_an_attorney">an attorney or a lawyer</a> when it comes to the legal matters. At the very least, they usually have malpractice insurance if things go really bad.</p><h4>Conclusion</h4><p>The <a href="http://www.amazon.com/gp/product/0060799072?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060799072">Ten Day MBA</a> helped me move from being <a id="pmyp" title="unconscious incompetence" href="http://en.wikipedia.org/wiki/Four_stages_of_competence">unconsciously incompetent</a> about business administration to becoming consciously incompetent in just a few days. I think that alone made it worth the time. I don't have aspirations to get a real MBA, but I now have more respect for those that do.</p><p>And now, back to programming...</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-3330061764648564469?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com11tag:blogger.com,1999:blog-6800934446457898793.post-6804538679948562782009-06-10T08:57:00.011-04:002009-07-20T08:14:46.992-04:00The First Few Milliseconds of an HTTPS Connection<p>Convinced from spending hours reading <a href="http://www.amazon.com/Tuscan-Whole-Milk-Gallon-128/product-reviews/B00032G1S0/ref=dp_top_cm_cr_acr_txt?ie=UTF8&amp;showViewpoints=1">rave reviews</a>, Bob eagerly clicked "Proceed to Checkout" for his gallon of <a href="http://www.amazon.com/gp/product/B00032G1S0?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B00032G1S0">Tuscan Whole Milk</a> and...</p><p>Whoa! What just happened?</p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/ShgnOU1MihI/AAAAAAAABNI/BAF-YQdhkJU/s1600-h/securitysymbols.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/ShgnOU1MihI/AAAAAAAABNI/BAF-YQdhkJU/s400/securitysymbols.png" /></a> <p>In the 220 milliseconds that flew by, a lot of interesting stuff happened to make Firefox change the address bar color and put a lock in the lower right corner. With the help of <a href="http://www.wireshark.org/">Wireshark</a>, my favorite network tool, and a slightly modified debug build of Firefox, we can see <i>exactly</i> what's going on.</p><p>By agreement of <a href="http://tools.ietf.org/html/rfc2818">RFC 2818</a>, Firefox knew that "https" meant it should connect to <a href="http://tools.ietf.org/html/rfc2818#section-2.3">port 443</a> at Amazon.com:</p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8K9mA5QcI/AAAAAAAABOI/1agNWSS6NBE/s1600-h/httpsport.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8K9mA5QcI/AAAAAAAABOI/1agNWSS6NBE/s400/httpsport.png" /></a> <p>Most people associate HTTPS with <a id="fyrr" title="SSL" href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">SSL</a> (Secure Sockets Layer) which was <a id="yq6y" title="created by Netscape" href="http://www.mozilla.org/projects/security/pki/nss/history.html">created by Netscape in the mid 90's</a>. This is becoming less true over time. As Netscape lost market share, SSL's maintenance moved to the Internet Engineering Task Force (<a href="http://en.wikipedia.org/wiki/IETF">IETF</a>). The first post-Netscape version was re-branded as Transport Layer Security (<a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">TLS</a>) 1.0 which <a href="http://tools.ietf.org/html/rfc2246">was released</a> in January 1999. It's rare to see true "SSL" traffic given that TLS has been around for 10 years. </p><h4>Client Hello</h4><p>TLS wraps all traffic in "records" of different types. We see that the first byte out of our browser is the hex byte 0x16 = 22 which <a id="ihzy" title="means" href="http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml">means</a> that this is a "handshake" record:</p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si-df4pU51I/AAAAAAAABQg/A1flWimwg9M/s1600-h/clienthellowithannotations.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si-df4pU51I/AAAAAAAABQg/A1flWimwg9M/s400/clienthellowithannotations.png" /></a> <p>The next two bytes are 0x0301 which indicate that this is a version 3.1 record which shows that TLS 1.0 is essentially SSL 3.1. </p><p>The handshake record is broken out into several messages. The first is our "Client Hello" message (0x01). There are a few important things here:</p><ul><li>Random:<br /><br /><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8g9EXh8uI/AAAAAAAABOY/oBt1zr_n1XE/s1600-h/randomclientbytes.png"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8g9EXh8uI/AAAAAAAABOY/oBt1zr_n1XE/s400/randomclientbytes.png" /></a><br />There are four bytes representing the current Coordinated Universal Time (<a href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>) in the Unix epoch format, which is the number of seconds since January 1, 1970. In this case, 0x4a2f07ca. It's followed by 28 random bytes. This will be used later on. </li><li>Session ID:<br /><br /><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8iGgIk_gI/AAAAAAAABOg/NsPg9pMMpCw/s1600-h/sessionid.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8iGgIk_gI/AAAAAAAABOg/NsPg9pMMpCw/s400/sessionid.png" /></a><br />Here it's empty/null. If we had previously connected to Amazon.com a few seconds ago, we could potentially resume a session and avoid a full handshake. </li><li>Cipher Suites:<br /><br /><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8i6DwZDiI/AAAAAAAABOo/_Pv_1d-PbgU/s1600-h/ciphersuites.png"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8i6DwZDiI/AAAAAAAABOo/_Pv_1d-PbgU/s400/ciphersuites.png" /></a><br />This is a list of all of the encryption algorithms that the browser is willing to support. Its top pick is a very strong choice of "<a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">TLS</a>_<a href="http://en.wikipedia.org/wiki/Elliptic_Curve_Diffie-Hellman">ECDHE</a>_<a href="http://en.wikipedia.org/wiki/Elliptic_Curve_DSA">ECDSA</a>_WITH_<a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a>_256_<a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29">CBC</a>_<a href="http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-0_and_SHA-1">SHA</a>" followed by 33 others that it's willing to accept. Don't worry if none of that makes sense. We'll find out later that Amazon doesn't pick our first choice anyway. </li><li><a id="z8g0" title="server_name extension" href="http://tools.ietf.org/html/rfc4366#section-3.1">server_name extension</a>:<br /><br /><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8jtnutNFI/AAAAAAAABOw/Czowyq3F-6Y/s1600-h/server_name.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8jtnutNFI/AAAAAAAABOw/Czowyq3F-6Y/s400/server_name.png" /></a><br />This is a way to tell Amazon.com that our browser is trying to reach <a href="https://www.amazon.com/">https://www.amazon.com/</a>. This is really convenient because our TLS handshake occurs long before any HTTP traffic. HTTP has a <a id="v56x" title="" href="http://tools.ietf.org/html/rfc2616#section-14.23">"Host" header</a> which allows a cost-cutting Internet hosting companies to pile hundreds of websites onto a single IP address. SSL has traditionally required a different IP for each site, but this extension allows the server to respond with the appropriate certificate that the browser is looking for. If nothing else, this extension should allow an extra week or so of IPv4 addresses. </li></ul><h4>Server Hello</h4><p>Amazon.com replies with a handshake record that's a massive two packets in size (2,551 bytes). The record has version bytes of 0x0301 meaning that Amazon agreed to our request to use TLS 1.0. This record has three sub-messages with some interesting data:</p><ol><li>"Server Hello" Message (2):<br /><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si-euEnAA6I/AAAAAAAABQo/l4-KRrTyNWY/s1600-h/serverhello.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si-euEnAA6I/AAAAAAAABQo/l4-KRrTyNWY/s400/serverhello.png" /></a><br /><ul><li>We get the server's four byte time Unix epoch time representation and its 28 random bytes that will be used later.<br /></li><li>A 32 byte session ID in case we want to reconnect without a big handshake.<br /></li><li>Of the 34 cipher suites we offered, Amazon picked "TLS_RSA_WITH_RC4_128_MD5" (0x0004). This means that it will use the "<a href="http://en.wikipedia.org/wiki/RSA">RSA</a>" <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public key</a> algorithm to verify certificate signatures and exchange keys, the <a href="http://en.wikipedia.org/wiki/RC4">RC4</a> encryption algorithm to encrypt data, and the <a href="http://en.wikipedia.org/wiki/MD5">MD5</a> hash function to verify the contents of messages. We'll cover these in depth later on. I personally think Amazon had selfish reasons for choosing this cipher suite. Of the ones on the list, it was the one that was least CPU intensive to use so that Amazon could crowd more connections onto each of their servers. A much less likely <span style="font-size:85%;">possibility </span>is that they wanted to pay special tribute to <a href="http://en.wikipedia.org/wiki/Ronald_L._Rivest">Ron Rivest</a>, who created all three of these algorithms.<br /></li></ul></li><li>Certificate Message (11):<br /><br /><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8lTxR3m0I/AAAAAAAABPA/I-le95y0ldw/s1600-h/certificatemessage.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8lTxR3m0I/AAAAAAAABPA/I-le95y0ldw/s400/certificatemessage.png" /></a><br /><ul><li>This message takes a whopping 2,464 bytes and is the certificate that the client can use to validate Amazon's. It isn't anything fancy. You can view most of its contents in your browser:<br /><br /><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Sirx5XZBa5I/AAAAAAAABNo/Z-R75rsjCL8/s1600-h/AmazonBasicCertInfo.png"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Sirx5XZBa5I/AAAAAAAABNo/Z-R75rsjCL8/s400/AmazonBasicCertInfo.png" /></a><br /></li></ul></li><li>"Server Hello Done" Message (14):<br /><br /><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8l2fMvVlI/AAAAAAAABPI/QrxJ3S9ezOo/s1600-h/serverhellodone.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8l2fMvVlI/AAAAAAAABPI/QrxJ3S9ezOo/s400/serverhellodone.png" /></a><br /><ul><li>This is a zero byte message that tells the client that it's done with the "Hello" process and indicate that the server won't be asking the client for a certificate.<br /></li></ul></li></ol><h4>Checking out the Certificate</h4><p>The browser has to <a href="http://www.koders.com/c/fid340AB659241B7C717B5B3E0095BBA4245FCE34FD.aspx#L862">figure out</a> if it should trust Amazon.com. In this case, it's using certificates. It looks at Amazon's certificate and <a href="http://www.koders.com/c/fid9207CD3EB61F5F08E38858D14997264BEDB5B62C.aspx#L1091">sees</a> that the current time is between the "not before" time of August 26th, 2008 and before the "not after" time of August 27, 2009. It also <a href="http://www.koders.com/c/fid9207CD3EB61F5F08E38858D14997264BEDB5B62C.aspx?s=CERT_CheckCertValidTimes#L1211">checks</a> to make sure that the certificate's public key is authorized for exchanging secret keys. </p><p>Why should we trust this certificate? </p><p>Attached to the certificate is a "signature" that is just a really long number in <a href="http://en.wikipedia.org/wiki/Endianness#Big-endian">big-endian</a> format:</p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SihpJBoNeDI/AAAAAAAABNg/DgLY221ncEo/s1600-h/AmazonCertSigned.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SihpJBoNeDI/AAAAAAAABNg/DgLY221ncEo/s400/AmazonCertSigned.png" /></a> <p>Anyone could have sent us these bytes. Why should we trust this signature? To answer that question, need to make a speedy detour into <a id="tlez" title="mathemagic land" href="http://en.wikipedia.org/wiki/Donald_in_Mathmagic_Land">mathemagic land</a>:</p><h4>Interlude: A Short, Not <i>Too</i> Scary, Guide to RSA</h4><p>People <a href="http://stackoverflow.com/questions/575561/do-programmers-have-to-be-good-in-mathematics-closed">sometimes wonder</a> if math has any relevance to programming. Certificates give a very practical example of applied math. Amazon's certificate tells us that we should use the RSA algorithm to check the signature. <a id="e:y3" title="RSA" href="http://en.wikipedia.org/wiki/RSA">RSA</a> was created in the 1970's by MIT professors <a id="g825" title="Ron Rivest" href="http://people.csail.mit.edu/rivest/">Ron *R*ivest</a>, <a id="h87n" title="Adi Shamir" href="http://en.wikipedia.org/wiki/Adi_Shamir">Adi *S*hamir</a>, and <a id="m0.d" title="Len Adleman" href="http://en.wikipedia.org/wiki/Leonard_Adleman">Len *A*dleman</a> who found a <a id="vw55" title="tied together" href="http://people.csail.mit.edu/rivest/Rsapaper.pdf">clever way</a> to combine ideas spanning <a id="w5fp" title="Greek mathematician from 300 BC" href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">2000</a> <a id="i-7k" title="a third century AD Chinese mathematician" href="http://en.wikipedia.org/wiki/Chinese_remainder_theorem">years</a> <a id="ks_n" title="a 17th century French judge" href="http://en.wikipedia.org/wiki/Fermat%27s_little_theorem">of</a> <a id="o:ge" title="18th century math wizard" href="http://en.wikipedia.org/wiki/Euler_totient_function">math</a> development to come up with a <a href="http://mathworld.wolfram.com/RSAEncryption.html">beautifully simple algorithm</a>:</p><p>You <a id="si95" title="pick" href="http://en.wikipedia.org/wiki/Primality_test">pick</a> two huge prime numbers "p" and "q." Multiply them to get "n = p*q." Next, you pick a small public <a href="http://en.wikipedia.org/wiki/Exponentiation">exponent</a> "e" which is the "encryption exponent" and <a id="p_jx" title="a specially crafted inverse" href="http://en.wikipedia.org/wiki/Modular_multiplicative_inverse">a specially crafted inverse</a> of "e" called "d" as the "decryption exponent." You then <b>make "n" and "e" public and keep "d" as secret as you possibly can</b> and then throw away "p" and "q" (or keep them as secret as "d"). It's really important to remember that "e" and "d" are inverses of each other. </p><p>Now, if you have some message, you just need to interpret its bytes as a number "M." If you want to "encrypt" a message to create a "ciphertext", you'd calculate:</p><p>C ≡ M<sup>e</sup> (mod n)</p><p>This means that you multiply "M" by itself "e" times. The "mod n" means that we only take the remainder (e.g. "<a href="http://en.wikipedia.org/wiki/Modular_arithmetic">modulus</a>") when dividing by "n." For example, 11 AM + 3 hours ≡ 2 (PM) (mod 12 hours). The recipient knows "d" which allows them to invert the message to recover the original message:</p><p>C<sup>d</sup> ≡ (M<sup>e</sup>)<sup>d</sup> ≡ M<sup>e*d</sup> ≡ M<sup>1</sup> ≡ M (mod n)</p><p>Just as interesting is that the person with "d" can "sign" a document by raising a message "M" to the "d" exponent:</p><p>M<sup>d</sup> ≡ S (mod n)</p><p>This works because "signer" makes public "S", "M", "e", and "n." Anyone can verify the signature "S" with a simple calculation:</p><p>S<sup>e</sup> ≡ (M<sup>d</sup>)<sup>e</sup> ≡ M<sup>d*e</sup> ≡ M<sup>e*d</sup> ≡ M<sup>1</sup> ≡ M (mod n)</p><p>Public key cryptography algorithms like RSA are often called "asymmetric" algorithms because the encryption key (in our case, "e") is not equal to (e.g. "symmetric" with) the decryption key "d". Reducing everything "mod n" makes it impossible to use the easy techniques that we're used to such as normal <a href="http://en.wikipedia.org/wiki/Logarithm">logarithms</a>. The magic of RSA works because you can calculate/encrypt C ≡ M<sup>e</sup> (mod n) <a href="http://en.wikipedia.org/wiki/Modular_exponentiation">very quickly</a>, but it is <i>really hard</i> to calculate/decrypt C<sup>d</sup> ≡ M (mod n) without knowing "d." As we saw earlier, "d" is derived from <a href="http://en.wikipedia.org/wiki/Integer_factorization">factoring</a> "n" back to its "p" and "q", which is a <a href="http://en.wikipedia.org/wiki/NP_%28complexity%29">tough problem</a>.</p><h4>Verifying Signatures</h4><p>The big thing to keep in mind with RSA in the real world is that all of the numbers involved have to be <i>big</i> to make things really hard to break using the <a href="http://en.wikipedia.org/wiki/General_number_field_sieve">best algorithms that we have</a>. How big? Amazon.com's certificate was "signed" by "VeriSign Class 3 Secure Server CA." From the certificate, we see that this VeriSign modulus "n" is 2048 bits long which has this 617 digit base-10 representation:</p><blockquote>1890572922 9464742433 9498401781 6528521078 8629616064 3051642608 4317020197 7241822595 6075980039 8371048211 4887504542 4200635317 0422636532 2091550579 0341204005 1169453804 7325464426 0479594122 4167270607 6731441028 3698615569 9947933786 3789783838 5829991518 1037601365 0218058341 7944190228 0926880299 3425241541 4300090021 1055372661 2125414429 9349272172 5333752665 6605550620 5558450610 3253786958 8361121949 2417723618 5199653627 5260212221 0847786057 9342235500 9443918198 9038906234 1550747726 8041766919 1500918876 1961879460 3091993360 6376719337 6644159792 1249204891 7079005527 7689341573 9395596650 5484628101 0469658502 1566385762 0175231997 6268718746 7514321</blockquote><p>(Good luck trying to find "p" and "q" from this "n" - if you could, you could generate real-looking VeriSign certificates.)</p><p>VeriSign's "e" is 2^16 + 1 = 65537. Of course, they keep their "d" value secret, probably on a safe hardware device protected by retinal scanners and armed guards. Before signing, VeriSign checked the validity of the contents that Amazon.com claimed on its certificate using a real-world "handshake" that involved <a href="http://www.verisign.com/ssl/ssl-information-center/ssl-basics/index.html#a7">looking at several of their business documents</a>. Once VeriSign was satisfied with the documents, they used the <a href="http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-0_and_SHA-1">SHA-1</a> hash algorithm to get a hash value of the certificate that had all the claims. In Wireshark, the full certificate shows up as the "signedCertificate" part:</p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8nWe2TGdI/AAAAAAAABPY/E9qxHxjy0xA/s1600-h/certsignature.png"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8m5BF5D2I/AAAAAAAABPQ/Ljv8Jd0uBEE/s400/signedcertificate.png" /></a> <p>It's sort of a misnomer since it actually means that those are the bytes that the signer is <i>going to sign </i>and not the bytes that already include a signature.</p><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8nWe2TGdI/AAAAAAAABPY/E9qxHxjy0xA/s400/certsignature.png" /> <p>The actual signature, "S", is simply called "encrypted" in Wireshark. If we raise "S" to VeriSign's public "e" exponent of 65537 and then take the remainder when divided by the modulus "n", we get this "decrypted" signature hex value:</p><blockquote>0001FFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF00302130 0906052B0E03021A 05000414C19F8786 871775C60EFE0542 E4C2167C830539DB</blockquote><p><a href="http://tools.ietf.org/html/rfc2313#page-9">Per the PKCS #1 v1.5 standard</a>, the first byte is "00" and it "ensures that the encryption block, [when] converted to an integer, is less than the modulus." The second byte of "01" indicates that this is a private key operation (e.g. it's a signature). This is followed by a lot of "FF" bytes that are used to pad the result to make sure that it's big enough. The padding is terminated by a "00" byte. It's followed by "30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14" which is the <a id="at3m" title="PKCS #1 v2.1 way" href="http://tools.ietf.org/html/rfc3447#page-43">PKCS #1 v2.1 way</a> of specifying the <a href="http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-0_and_SHA-1">SHA-1</a> hash algorithm. The last 20 bytes are SHA-1 hash digest of the bytes in "signedCertificate."</p><p>Since the decrypted value <a href="http://www.matasano.com/log/558/public-key-signature-forgery-collected/">is properly formatted</a> and the last bytes are the same hash value that we can calculate independently, we can assume that whoever knew "VeriSign Class 3 Secure Server CA"'s private key "signed" it. We implicitly trust that only VeriSign knows the private key "d."</p><p>We can repeat the process to verify that "VeriSign Class 3 Secure Server CA"'s certificate was signed by VeriSign's "Class 3 Public Primary Certification Authority."</p><p>But why should we trust <i>that</i>? There are no more levels on the trust chain. </p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Sihn_4zmOYI/AAAAAAAABNY/di1a-vsPbYA/s1600-h/BuiltInCertificateHierarchy.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Sihn_4zmOYI/AAAAAAAABNY/di1a-vsPbYA/s400/BuiltInCertificateHierarchy.png" /></a> <p>The top "VeriSign Class 3 Public Primary Certification Authority" was signed by <i>itself</i>. This certificate has been built into Mozilla products as an implicitly trusted good certificate since version <a href="http://bonsai.mozilla.org/cvslog.cgi?file=mozilla/security/nss/lib/ckfw/builtins/certdata.txt&amp;rev=NSS_3_12_2_WITH_CKBI_1_73_RTM&amp;mark=1.51">1.4 of certdata.txt</a> in the Network Security Services (<a href="http://www.mozilla.org/projects/security/pki/nss/">NSS</a>) library. It was checked-in on September 6, 2000 by Netscape's Robert Relyea with the following comment:</p><blockquote><p>"Make the framework compile with the rest of NSS. Include a 'live' certdata.txt with those certs we have permission to push to open source (additional certs will be added as we get permission from the owners)." </p></blockquote><p>This decision has had a relatively long impact since the certificate has a validity range of January 28, 1996 - August 1, 2028.</p><p>As Ken Thompson explained so well in his "<a href="http://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf">Reflections on Trusting Trust</a>", you ultimately have to implicitly trust somebody. There is no way around this problem. In this case, we're implicitly trusting that Robert Relyea made a good choice. We also hope that <a href="http://www.mozilla.org/projects/security/certs/policy/">Mozilla's built-in certificate policy</a> is reasonable for the other built-in certificates.</p><p>One thing to keep in mind here is that all these certificates and signatures were simply used to form a trust chain. On the public Internet, VeriSign's root certificate is implicitly trusted by Firefox long before you go to any website. In a company, you can create your own root certificate authority (CA) that you can install on everyone's machine. </p><p>Alternatively, you can get around having to pay companies like VeriSign and avoid certificate trust chains altogether. Certificates are used to establish trust by using a trusted third-party (in this case, VeriSign). If you have a secure means of sharing a secret "key", such as whispering a long password into someone's ear, then you can use that pre-shared key (PSK) to establish trust. There are extensions to TLS to allow this, such as <a href="http://tools.ietf.org/html/rfc4279">TLS-PSK</a>, and my personal favorite, <a href="http://tools.ietf.org/html/rfc5054">TLS with Secure Remote Password (SRP) extensions</a>. Unfortunately, these extensions aren't nearly as widely deployed and supported, so they're usually not practical. Additionally, these alternatives impose a burden that we have to have some other secure means of communicating the secret that's more cumbersome than what we're trying to establish with TLS (otherwise, why wouldn't we use <i>that</i> for everything?).</p><p>One final check that we need to do is to verify that the host name on the certificate is what we expected. <a href="http://www.linkedin.com/in/nelsonbolyard">Nelson Bolyard</a>'s comment in the <a href="http://www.koders.com/c/fid1C807D78F4E4CA73466FEEAA78EA9F0B2D618199.aspx#L260">SSL_AuthCertificate function</a> explains why: </p><blockquote><pre><span style="COLOR: rgb(0,128,0)">/* cert is OK. This is the client side of an SSL connection.<br /> * Now check the name field in the cert against the desired hostname.<br /> * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! */</span></pre></blockquote><p>This check helps prevent against a <a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">man-in-the-middle</a> attack because we are implicitly trusting that the people on the certificate trust chain wouldn't do something bad, like sign a certificate claiming to be from Amazon.com unless it actually was Amazon.com. If an attacker is able to modify your DNS server by using a technique like <a href="http://en.wikipedia.org/wiki/DNS_cache_poisoning">DNS cache poisoning</a>, you might be fooled into thinking you're at a trusted site (like Amazon.com) because the address bar will look normal. This last check implicitly trusts certificate authorities to stop these bad things from happening.</p><h4>Pre-Master Secret</h4><p>We've verified some claims about Amazon.com and know its public encryption exponent "e" and modulus "n." Anyone listening in on the traffic can know this as well (as evidenced because we are using Wireshark captures). Now we need to create a random secret key that an eavesdropper/attacker can't figure out. This isn't as easy as it sounds. In 1996, researchers figured out that <a href="http://en.wikipedia.org/wiki/Netscape_Navigator">Netscape Navigator</a> 1.1 was <a id="cjg_" title="using only three sources" href="http://www.cs.berkeley.edu/~daw/papers/ddj-netscape.html">using only three sources</a> to seed their pseudo-random number generator (<a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">PRNG</a>). The sources were: the time of day, the process id, and the parent process id. As the researchers showed, these "random" sources aren't that random and were relatively easy to figure out.</p><p>Since everything else was derived from these three "random" sources, it was possible to "break" the SSL "security" in 25 seconds on a 1996 era machine. If you still don't believe that finding randomness is hard, just <a id="dfhi" title="ask the Debian OpenSSL maintainers" href="http://www.schneier.com/blog/archives/2008/05/random_number_b.html">ask the Debian OpenSSL maintainers</a>. If you mess it up, all the security built on top of it is suspect.</p><p>On Windows, random numbers used for cryptographic purposes are generated by calling the <a id="f9ln" title="CryptGenRandom function" href="http://msdn.microsoft.com/en-us/library/aa379942%28VS.85%29.aspx">CryptGenRandom function</a> that hashes bits <a id="qai9" title="sampled from over 125 sources" href="http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx#353493">sampled from over 125 sources</a>. Firefox uses this function along with some bits derived from <a id="a5vi" title="its own function" href="http://www.koders.com/c/fidBC778BD3666AA64522D1FD4F4EC3331E44B4D204.aspx?s=RNG_GetNoise">its own function</a> to seed its <a id="k982" title="pseudo-random number generator" href="http://www.koders.com/c/fidD184CA9064625C0ADF48025F3FA0588FCD664057.aspx">pseudo-random number generator</a>.</p><p>The 48 byte "pre-master secret" random value that's generated isn't used directly, but it's very important to keep it secret since a lot of things are derived from it. Not surprisingly, Firefox makes it hard to find out this value. I had to compile a debug version and set the <a id="is1y" title="SSLDEBUGFILE" href="http://www.koders.com/c/fidCFCD763A9E0B2BEF3FB9D4D6C17B4094CBF21548.aspx#L2092">SSLDEBUGFILE</a> and <a id="sstz" title="SSLTRACE" href="http://www.koders.com/c/fidCFCD763A9E0B2BEF3FB9D4D6C17B4094CBF21548.aspx#L2101">SSLTRACE</a> environment variables to see it. </p><p>In this particular session, the pre-master secret showed up in the SSLDEBUGFILE as: </p><blockquote><p>4456: SSL[131491792]: Pre-Master Secret [Len: 48]<br />03 01 bb 7b 08 98 a7 49 de e8 e9 b8 91 52 ec 81 ...{...I.....R..<br />4c c2 39 7b f6 ba 1c 0a b1 95 50 29 be 02 ad e6 L.9{......P)....<br />ad 6e 11 3f 20 c4 66 f0 64 22 57 7e e1 06 7a 3b .n.? .f.d"W~..z; </p></blockquote><p>Note that it's not completely random. The first two bytes are, <a id="ai16" title="by convention" href="http://tools.ietf.org/html/rfc2246#page-44">by convention</a>, the TLS version (03 01).</p><h4>Trading Secrets</h4><p>We now need to get this secret value over to Amazon.com. By Amazon's wishes of "TLS_RSA_WITH_RC4_128_MD5", we will use RSA to do this. You <em>could</em> make your input message equal to just the 48 byte pre-master secret, but the Public Key Cryptography Standard (PKCS) #1, version 1.5 RFC <a id="fw3:" title="states" href="http://tools.ietf.org/html/rfc2313#page-8">tells us</a> that we should pad these bytes with <i>random</i> data to make the input equal to exactly the size of the modulus (1024 bits/128 bytes). This makes it harder for an attacker to determine our pre-master secret. It also gives us one last chance to protect ourselves in case we did something really bone-headed, like reusing the same secret. If we reused the key, the eavesdropper would likely see a different value placed on the network due to the random padding.</p><p>Again, Firefox makes it hard to see these random values. I had to insert debugging statements into <a id="gyq6" title="the padding function" href="http://www.koders.com/c/fid1EB31A222A560045DBF9EC54457A1E0339825D58.aspx#L190">the padding function</a> to see what was going on:</p><blockquote><pre>wrapperHandle = fopen(<span style="COLOR: rgb(163,21,21)">"plaintextpadding.txt"</span>, <span style="COLOR: rgb(163,21,21)">"a"</span>);<br />fprintf(wrapperHandle, <span style="COLOR: rgb(163,21,21)">"PLAINTEXT = "</span>);<br /><span style="COLOR: rgb(0,0,255)">for</span>(i = 0; i &lt; modulusLen; i++)<br />{<br /> fprintf(wrapperHandle, <span style="COLOR: rgb(163,21,21)">"%02X "</span>, block[i]);<br />}<br />fprintf(wrapperHandle, <span style="COLOR: rgb(163,21,21)">"\r\n"</span>);<br />fclose(wrapperHandle);</pre></blockquote><p>In this session, the full padded value was:</p><blockquote>00 02 12 A3 EA B1 65 D6 81 6C 13 14 13 62 10 53 23 B3 96 85 FF 24 FA CC 46 11 21 24 A4 81 EA 30 63 95 D4 DC BF 9C CC D0 2E DD 5A A6 41 6A 4E 82 65 7D 70 7D 50 09 17 CD 10 55 97 B9 C1 A1 84 F2 A9 AB EA 7D F4 CC 54 E4 64 6E 3A E5 91 A0 06 00 03 01 BB 7B 08 98 A7 49 DE E8 E9 B8 91 52 EC 81 4C C2 39 7B F6 BA 1C 0A B1 95 50 29 BE 02 AD E6 AD 6E 11 3F 20 C4 66 F0 64 22 57 7E E1 06 7A 3B<br /></blockquote><p>Firefox took this value and <a href="http://www.koders.com/c/fid1B0E0F62F1B3DB6D7272F0BD781A1609D76FE6FE.aspx#L312">calculated</a> "C ≡ M<sup>e</sup> (mod n)" to get the value we see in the "<a id="whfx" title="Client Key Exchange" href="http://tools.ietf.org/html/rfc2246#page-43">Client Key Exchange</a>" record:</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8oafu_5aI/AAAAAAAABPg/r41rp34D1pw/s1600-h/clientkeyexchange.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8oafu_5aI/AAAAAAAABPg/r41rp34D1pw/s400/clientkeyexchange.png" /></a></p><p>Finally, Firefox sent out one last unencrypted message, a "<a id="f_on" title="Change Cipher Spec" href="http://tools.ietf.org/html/rfc2246#page-24">Change Cipher Spec</a>" record: </p><p><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8o_0Qi0HI/AAAAAAAABPo/M1cyaQ6le5A/s1600-h/clientchangecipherspec.png"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/Si8o_0Qi0HI/AAAAAAAABPo/M1cyaQ6le5A/s400/clientchangecipherspec.png" /></a></p><p>This is Firefox's way of telling Amazon that it's going to start using the agreed upon secret to encrypt its next message.</p><h4>Deriving the Master Secret</h4><p>If we've done everything correctly, both sides (and only those sides) now know the 48 byte (256 bit) pre-master secret. There's a slight trust issue here from Amazon's perspective: the pre-master secret just has bits that were generated by the client, they don't take anything into account from the server or anything we said earlier. We'll fix that be computing the "master secret." <a id="lf0j" title="Per the spec" href="http://tools.ietf.org/html/rfc2246#page-47">Per the spec</a>, this is done by calculating:</p><blockquote>master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)<br /></blockquote><p>The "pre_master_secret" is the secret value we sent earlier. The "master secret" is simply a string whose <a href="http://en.wikipedia.org/wiki/ASCII">ASCII</a> bytes (e.g. "6d 61 73 74 65 72 ...") are used. We then concatenate the random values that were sent in the ClientHello and ServerHello (from Amazon) messages that we saw at the beginning.</p><p>The PRF is the "Pseudo-Random Function" that's also <a id="vku-" title="defined in the spec" href="http://tools.ietf.org/html/rfc2246#page-11">defined in the spec</a> and is quite clever. It combines the secret, the ASCII label, and the seed data we give it by using the keyed-Hash Message Authentication Code (<a href="http://en.wikipedia.org/wiki/HMAC">HMAC</a>) versions of both <a id="remv" title="MD5" href="http://en.wikipedia.org/wiki/MD5">MD5</a> and <a id="syuh" title="SHA-1" href="http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-0_and_SHA-1">SHA-1</a> hash functions. Half of the input is sent to each hash function. It's clever because it is quite resistant to attack, even in the face of <a id="kir7" title="MD5" href="http://www.win.tue.nl/hashclash/rogue-ca/">weaknesses in MD5</a> <a id="x8dy" title="and SHA-1" href="http://www.schneier.com/blog/archives/2005/02/sha1_broken.html">and SHA-1</a>. This process can feedback on itself and iterate forever to generate as many bytes as we need. </p><p>Following this procedure, we obtain a 48 byte "master secret" of </p><blockquote>4C AF 20 30 8F 4C AA C5 66 4A 02 90 F2 AC 10 00 39 DB 1D E0 1F CB E0 E0 9D D7 E6 BE 62 A4 6C 18 06 AD 79 21 DB 82 1D 53 84 DB 35 A7 1F C1 01 19<br /></blockquote><h4>Generating Lots of Keys</h4><p>Now that both sides have a "master secrets", the spec <a id="qji3" title="shows us" href="http://tools.ietf.org/html/rfc2246#page-21">shows us</a> how we can derive all the needed session keys we need using the PRF to create a "key block" where we will pull data from:</p><blockquote><p>key_block = PRF(SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random);</p></blockquote><p>The bytes from "key_block" are used to populate the following:</p><blockquote>client_write_MAC_secret[SecurityParameters.hash_size]<br />server_write_MAC_secret[SecurityParameters.hash_size]<br />client_write_key[SecurityParameters.key_material_length]<br />server_write_key[SecurityParameters.key_material_length]<br />client_write_IV[SecurityParameters.IV_size]<br />server_write_IV[SecurityParameters.IV_size]<br /></blockquote><p>Since we're using a <a id="fgt_" title="stream cipher" href="http://en.wikipedia.org/wiki/Stream_cipher">stream cipher</a> instead of a <a id="xz.d" title="block cipher" href="http://en.wikipedia.org/wiki/Block_cipher">block cipher</a> like the Advanced Encryption Standard (<a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a>), we don't need the Initialization Vectors (<a id="aj5k" title="Initialization Vector" href="http://en.wikipedia.org/wiki/Initialization_vector">IV</a>s). Therefore, we just need two Message Authentication Code (<a id="eo8s" title="Message Authentication Code" href="http://en.wikipedia.org/wiki/Message_authentication_code">MAC</a>) keys for each side that are 16 bytes (128 bits) each since the specified MD5 hash digest size is 16 bytes. In addition, the RC4 cipher uses a 16 byte (128 bit) key that both sides will need as well. All told, we need 2*16 + 2*16 = 64 bytes from the key block.</p><p>Running the PRF, we get these values: </p><blockquote><p>client_write_MAC_secret = 80 B8 F6 09 51 74 EA DB 29 28 EF 6F 9A B8 81 B0<br />server_write_MAC_secret = 67 7C 96 7B 70 C5 BC 62 9D 1D 1F 4A A6 79 81 61<br />client_write_key = 32 13 2C DD 1B 39 36 40 84 4A DE E5 6C 52 46 72<br />server_write_key = 58 36 C4 0D 8C 7C 74 DA 6D B7 34 0A 91 B6 8F A7</p></blockquote><h4>Prepare to be Encrypted!</h4><p>The last handshake message the client sends out is the "<a id="n8-5" title="Finished messages" href="http://tools.ietf.org/html/rfc2246#page-46">Finished message</a>." This is a clever message that proves that no one tampered with the handshake and it proves that we know the key. The client takes all bytes from all handshake messages and puts them into a "handshake_messages" buffer. We then calculate 12 bytes of "verify_data" using the pseudo-random function (PRF) with our master key, the label "client finished", and an MD5 and SHA-1 hash of "handshake_messages": </p><blockquote>verify_data = PRF(master_secret, "client finished", MD5(handshake_messages) + SHA-1(handshake_messages)) [12]<br /></blockquote><p>We take the result and add a record header byte "0x14" to indicate "finished" and length bytes "00 00 0c" to indicate that we're sending 12 bytes of verify data. Then, like all future encrypted messages, we need to make sure the decrypted contents haven't been tampered with. Since our cipher suite in use is TLS_RSA_WITH_RC4_128_MD5, this means we use the MD5 hash function.</p><p>Some people get paranoid when they hear MD5 because it has some weaknesses. I certainly don't advocate using it as-is. However, TLS is smart in that it doesn't use MD5 directly, but rather the <a href="http://en.wikipedia.org/wiki/HMAC">HMAC</a> version of it. This means that instead of using MD5(m) directly, we calculate:</p><blockquote>HMAC_MD5(Key, m) = MD5((Key ⊕ opad) ++ MD5((Key ⊕ ipad) ++ m)</blockquote><p>(The ⊕ means <a href="http://en.wikipedia.org/wiki/Exclusive_or">XOR</a>, ++ means concatenate, "opad" is the bytes "5c 5c ... 5c", and "ipad" is the bytes "36 36 ... 36").</p><p>In particular, we calculate:</p><blockquote>HMAC_MD5(client_write_MAC_secret, seq_num + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment));<br /></blockquote><p>As you can see, we include a sequence number ("seq_num") along with attributes of the plaintext message (here it's called "TLSCompressed"). The sequence number foils attackers who might try to take a previously encrypted message and insert it midstream. If this occurred, the sequence numbers would definitely be different than what we expected. This also protects us from an attacker dropping a message. </p><p>All that's left is to encrypt these bytes.</p><h4>RC4 Encryption</h4><p>Our negotiated cipher suite was TLS_RSA_WITH_RC4_128_MD5. This tells us that we need to use <a href="http://people.csail.mit.edu/rivest/faq.html"><span style="COLOR: rgb(128,0,128)">Ron's Code</span></a> #4 (<a id="guhl" title="RC4" href="http://en.wikipedia.org/wiki/RC4">RC4</a>) to encrypt the traffic. <a href="http://en.wikipedia.org/wiki/Ron_Rivest">Ron Rivest</a> developed the RC4 algorithm to generate random bytes based on a 256 byte key. The algorithm is so simple you can actually memorize it in a few minutes. </p><p>RC4 begins by creating a 256-byte "S" byte array and populating it with 0 to 255. You then iterate over the array by mixing in bytes from the key. You do this to create a state machine that is used to generate "random" bytes. To generate a random byte, we shuffle around the "S" array.</p><p>Put graphically, it looks like this:</p><a href="http://en.wikipedia.org/wiki/RC4"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SihmoVyIg1I/AAAAAAAABNQ/Jl6kMd1z2hE/s320/RC4.png" /></a> <p>To encrypt a byte, we <a href="http://en.wikipedia.org/wiki/Exclusive_or">xor</a> this pseudo-random byte with the byte we want to encrypt. Remember that xor'ing a bit with 1 causes it to flip. Since we're generating random numbers, on average the xor will flip half of the bits. This random bit flipping is effectively how we encrypt data. As you can see, it's not very complicated and thus it runs quickly. I think that's why Amazon chose it. </p><p>Recall that we have a "client_write_key" and a "server_write_key." The means we need to create two RC4 instances: one to encrypt what our browser sends and the other to decrypt what the server sent us.</p><p>The first few random bytes out of the "client_write" RC4 instance are "7E 20 7A 4D FE FB 78 A7 33 ..." If we xor these bytes with the unencrypted header and verify message bytes of "14 00 00 0C 98 F0 AE CB C4 ...", we'll get what appears in the encrypted portion that we can see in Wireshark:</p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8ryrIoGrI/AAAAAAAABP4/1bSIRcRkERw/s1600-h/clientencryptedkeyexchange.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/Si8ryrIoGrI/AAAAAAAABP4/1bSIRcRkERw/s400/clientencryptedkeyexchange.png" /></a> <p>The server does almost the same thing. It sends out a "Change Cipher Spec" and then a "Finished Message" that includes all handshake messages, including the <em>decrypted</em> version of the client's "Finished Message." Consequently, this proves to the client that the server was able to successfully decrypt our message. </p><h4>Welcome to the Application Layer!</h4><p>Now, 220 milliseconds after we started, we're finally ready for the application layer. We can now send normal HTTP traffic that'll be encrypted by the TLS layer with the RC4 write instance and decrypt traffic with the server RC4 write instance. In addition, the TLS layer will check each record for tampering by computing the HMAC_MD5 hash of the contents.</p><p>At this point, the handshake is over. Our TLS record's content type is now 23 (0x17). Encrypted traffic begins with "17 03 01" which indicate the record type and TLS version. These bytes are followed by our encrypted size, which includes the HMAC hash. </p><p>Encrypting the plaintext of:</p><blockquote><p>GET /gp/cart/view.html/ref=pd_luc_mri HTTP/1.1<br />Host: www.amazon.com<br />User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009060911 Minefield/3.0.10 (.NET CLR 3.5.30729)<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br />Accept-Language: en-us,en;q=0.5<br />Accept-Encoding: gzip,deflate<br />Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7<br />Keep-Alive: 300<br />Connection: keep-alive<br />...</p></blockquote><p>will give us the bytes we see on the wire:</p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8s4nuKH8I/AAAAAAAABQA/feL3OBZV83s/s1600-h/firstclientappdataencrypted.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8s4nuKH8I/AAAAAAAABQA/feL3OBZV83s/s400/firstclientappdataencrypted.png" /></a> <p>The only other interesting fact is that the sequence number increases on each record, it's now 1 (and the next record will be 2, etc).</p><p>The server does the same type of thing on its side using the server_write_key. We see its response, including the tell-tale application data header:</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8tz1Y9BqI/AAAAAAAABQQ/B6_UN0lX7fM/s1600-h/firstserverappdata.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Si8tz1Y9BqI/AAAAAAAABQQ/B6_UN0lX7fM/s400/firstserverappdata.png" /></a></p><p>Decrypting this gives us: </p><blockquote><p>HTTP/1.1 200 OK<br />Date: Wed, 10 Jun 2009 01:09:30 GMT<br />Server: Server<br />...<br />Cneonction: close<br />Transfer-Encoding: chunked</p></blockquote><p>which is a normal HTTP reply that includes a non-descriptive "Server: Server" header and a misspelled "<a id="t7o1" title="Cneonction: close" href="http://www.nextthing.org/archives/2005/08/07/fun-with-http-headers">Cneonction: close</a>" header coming from Amazon's load balancers.</p><p>TLS is just below the application layer. The HTTP server software can act as if it's sending unencrypted traffic. The only change is that it writes to a library that does all the encryption. <a href="http://www.openssl.org/">OpenSSL</a> is a popular open-source library for TLS.</p><p>The connection will stay open while both sides send and receive encrypted data until either side sends out a "<a href="http://tools.ietf.org/html/rfc2246#page-25">closure alert</a>" message and then closes the connection. If we reconnect shortly after disconnecting, we can re-use the negotiated keys (if the server still has them cached) without using public key operations, otherwise we do a completely new full handshake.</p><p>It's important to realize that application data records can be <i>anything</i>. The only reason "HTTPS" is special is because the web is so popular. There are lots of other TCP/IP based protocols that ride on top of TLS. For example, TLS is used by <a id="a7fg" title="SFTP" href="http://tools.ietf.org/html/rfc4217">FTPS</a> and <a id="y0ps" title="extensions to SMTP" href="http://tools.ietf.org/html/rfc3207">secure extensions to SMTP</a>. It's certainly better to use TLS than inventing your own solution. Additionally, you'll benefit from a protocol that has withstood careful <a href="http://tools.ietf.org/html/rfc5246#appendix-F">security analysis</a>. </p><h4>... And We're Done!</h4><p>The very readable <a id="u9ya" title="TLS RFC" href="http://tools.ietf.org/html/rfc5246">TLS RFC</a> covers many more details that were missed here. We covered just one single path in our observation of the 220 millisecond dance between Firefox and Amazon's server. Quite a bit of the process was affected by the TLS_RSA_WITH_RC4_128_MD5 Cipher Suite selection that Amazon made with its ServerHello message. It's a reasonable choice that slightly favors speed over security. </p><p>As we saw, if someone could secretly factor Amazon's "n" modulus into its respective "p" and "q", they could effectively decrypt all "secure" traffic until Amazon changes their certificate. Amazon counter-balances this concern this with a short one year duration certificate:</p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8u2evehpI/AAAAAAAABQY/pFMUJ5-vmOU/s1600-h/amazoncertvalidity.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/Si8u2evehpI/AAAAAAAABQY/pFMUJ5-vmOU/s400/amazoncertvalidity.png" /></a> <p>One of the cipher suites that was offered was "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" which uses the <a id="y2_." title="Diffie-Hellman key exchange" href="http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange">Diffie-Hellman key exchange</a> that has a nice property of "<a id="jtxx" title="forward secrecy" href="http://en.wikipedia.org/wiki/Perfect_forward_secrecy">forward secrecy</a>." This means that if someone cracked the mathematics of the key exchange, they'd be no better off to decrypt another session. One downside to this algorithm is that it requires more math with big numbers, and thus is a little more computationally taxing on a busy server. The "Advanced Encryption Standard" (<a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a>) algorithm was present in many of the suites that we offered. It's different than RC4 in that it works on 16 byte "blocks" at a time rather than a single byte. Since its key can be up to 256 bits, many consider this to be more secure than RC4.</p><p>In just 220 milliseconds, two endpoints on the Internet came together, provided enough credentials to trust each other, set up encryption algorithms, and started to send encrypted traffic.</p><p>And to think, all of this just so Bob can buy milk.</p><p><strong>UPDATE:</strong> I wrote a program that walks through the handshake steps mentioned in this article. <a href="http://github.com/moserware/TLS-1.0-Analyzer/tree/master">I posted it to GitHub</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-680453867994856278?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com102tag:blogger.com,1999:blog-6800934446457898793.post-70808986412942422432009-04-24T08:37:00.004-04:002009-04-24T09:41:06.779-04:00Using Obscure Windows COM APIs in .NET<p>Most native Windows APIs are simple to call from .NET. For example, if you need to do something special when showing a window, you can use the <a href="http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx">ShowWindow</a> API using <a href="http://en.wikipedia.org/wiki/Platform_Invocation_Services">Platform Invocation Services</a> (P/Invoke) like this:</p><pre>[<span style="color: rgb(43, 145, 175);">DllImport</span>(<span style="color: rgb(163, 21, 21);">"user32.dll"</span>)]<br /><span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">extern</span> <span style="color: rgb(0, 0, 255);">bool</span> ShowWindow(<span style="color: rgb(43, 145, 175);">IntPtr</span> hWnd, <span style="color: rgb(0, 0, 255);">int</span> nCmdShow);</pre><p>When you call this function, here's roughly what happens:</p><ol><li>The CLR calls <a href="http://msdn.microsoft.com/en-us/library/ms684175%28VS.85%29.aspx">LoadLibrary</a> on the file (e.g. "user32.dll") </li><li>The CLR then calls <a href="http://msdn.microsoft.com/en-us/library/ms683212%28VS.85%29.aspx">GetProcAddress</a> on the function name (e.g. "ShowWindow") to get the address of where the function is located. </li></ol><p>For the most part, it just magically works. If we had used a function like "MessageBox", the CLR would notice that it doesn't exist and would then pick between the ANSI version (e.g. "MessageBoxA") or the Unicode version (e.g. "MessageBoxW"). </p><p>With the address in hand, it's easy to <a href="http://en.wikipedia.org/wiki/Branch_%28computer_science%29">jump</a> to it and you're all set. Simple and easy.</p><p>I was expecting a simple API like this when I was investigating how to register my program as the default handler for ".wav" files on Vista. In the pre-Vista days, most programs would write directly into a registry key for the file extension (e.g. "<a href="http://msdn.microsoft.com/en-us/library/ms724475%28VS.85%29.aspx">HKEY_CLASSES_ROOT</a>\.wav") and move on. Problems come when your program wants to register itself as a handler for a "popular" extension like .MP3 or .HTM. Some programs go into an all out arms race with other programs in a fight of wills to make sure they keep the extension.</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SfGs68ifNcI/AAAAAAAABNA/tJInxh8ezP0/s1600-h/SetFileAssociations.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SfGs68ifNcI/AAAAAAAABNA/tJInxh8ezP0/s320/SetFileAssociations.png" /></a> </p><p>In Windows Vista and later, Microsoft wants us to use the new "<a href="http://msdn.microsoft.com/en-us/library/bb756951.aspx">Default Programs</a>" feature. The idea is that you register what file extensions your program supports in the registry and then a nice UI allows people to easily pick which of those extensions they want to associate with your program. Digging around the documentation led me to discover that the bulk of the functionality was exposed via the <a href="http://msdn.microsoft.com/en-us/library/bb776332.aspx">IApplicationAssociationRegistration</a> COM interface.</p><p>Ah, COM. </p><p>Over the years, I've tried to keep my distance from it. This irrational fear came from wizards that "next, next, finish"'d your way into thousands of lines of inscrutable code. It took me years of passing glances to <a href="http://www.moserware.com/2008/01/finally-understanding-com-after.html">finally understand its basics</a>. Even then, when I needed to use it from .NET, I'd right click on my project references and click "Add Reference":</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SevLN4jNxKI/AAAAAAAABMw/14fMxyJI9Dg/s1600-h/AddComReference.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SevLN4jNxKI/AAAAAAAABMw/14fMxyJI9Dg/s400/AddComReference.png" /></a> </p><p>I'd pick the library I needed and then somehow I could use the types as if they were .NET objects. I didn't ask further questions and moved on.</p><p>Unfortunately, IApplicationAssociationRegistration was nowhere to be found on the "Add Reference" list since it doesn't seem to have a registered type library associated with it. Using my basic COM knowledge, I knew that if I wanted to use it I would need to know the interface identifier (IID) as well as a class identifier (CLSID) that pointed to a concrete implementation.</p><p>Following the MSDN documentation, I knew I'd probably find success in shobjidl.idl:</p><a href="http://msdn.microsoft.com/en-us/library/bb776332.aspx"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SevPpp-xVNI/AAAAAAAABM4/UD8xgiLPBCo/s400/InterfaceInformation.png" /></a> <p>Sure enough, shobjidl.idl was sitting in my "C:\Program Files\Microsoft SDKs\Windows\<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e6e1c3df-a74f-4207-8586-711ebe331cdc&amp;displaylang=en">v6.1</a>\Include" directory and had this interface definition:</p><pre>[<br /> <span style="color: rgb(0, 0, 255);">object</span>,<br /> <span style="color: rgb(0, 0, 255);">uuid</span>(4e530b0a-e611-4c77-a3ac-9031d022281b),<br /> <span style="color: rgb(0, 0, 255);">pointer_default</span>(<span style="color: rgb(0, 0, 255);">unique</span>),<br /> <span style="color: rgb(0, 0, 255);">helpstring</span>(<span style="color: rgb(163, 21, 21);">"Protocol URL and Extension File Application"</span>)<br />]<br /><span style="color: rgb(0, 0, 255);">interface</span> IApplicationAssociationRegistration : IUnknown<br />{<br /> HRESULT QueryCurrentDefault(<br /> [<span style="color: rgb(0, 0, 255);">in</span>, <span style="color: rgb(0, 0, 255);">string</span>] LPCWSTR pszQuery,<br /> [<span style="color: rgb(0, 0, 255);">in</span>] ASSOCIATIONTYPE atQueryType,<br /> [<span style="color: rgb(0, 0, 255);">in</span>] ASSOCIATIONLEVEL alQueryLevel,<br /> [<span style="color: rgb(0, 0, 255);">out</span>, <span style="color: rgb(0, 0, 255);">string</span>] LPWSTR* ppszAssociation);<br /><br />...<br />}</pre><p>A little further down was the declaration for the concrete class (coclass) and its associated class id (CLSID):</p><pre><span style="color: rgb(0, 128, 0);">// CLSID_ApplicationAssociationRegistration</span><br />[ <span style="color: rgb(0, 0, 255);">uuid</span>(591209c7-767b-42b2-9fba-44ee4615f2c7) ] <span style="color: rgb(0, 0, 255);">coclass</span> ApplicationAssociationRegistration<br />{<br /> <span style="color: rgb(0, 0, 255);">interface</span> IApplicationAssociationRegistration;<br />}</pre><p>In the IDL, we also see the definitions for the enums that the functions use:</p><pre><span style="color: rgb(0, 0, 255);">typedef</span> [v1_enum] <span style="color: rgb(0, 0, 255);">enum</span> tagASSOCIATIONLEVEL<br />{<br /> AL_MACHINE,<br /> AL_EFFECTIVE,<br /> AL_USER,<br />} ASSOCIATIONLEVEL;<br /><br /><span style="color: rgb(0, 0, 255);">typedef</span> [v1_enum] <span style="color: rgb(0, 0, 255);">enum</span> tagASSOCIATIONTYPE<br />{<br /> AT_FILEEXTENSION,<br /> AT_URLPROTOCOL,<br /> AT_STARTMENUCLIENT,<br /> AT_MIMETYPE,<br />} ASSOCIATIONTYPE;</pre><p>Getting this to work in .NET was surprisingly easy. The basic idea is that the CLR has to have just enough information to find the types:</p><ol><li>The "<a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.comimportattribute.aspx">ComImportAttribute</a>" is almost as simple to use as <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx">DllImportAttribute</a>. In addition, you need to use the <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.guidattribute.aspx">GuidAttribute</a> to specify the gigantic GUIDs. </li><li>You use the "<a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.interfacetypeattribute.aspx">InterfaceTypeAttribute</a>" to specify the basic interface(s) that the interface you're importing uses. In COM, all interfaces derive from <a href="http://msdn.microsoft.com/en-us/library/ms680509.aspx">IUnknown</a>. If the interface supports scripting then it implements <a href="http://msdn.microsoft.com/en-us/library/ms221608.aspx">IDispatch</a>. If you provide a speedy C++ way of accessing your interface (e.g. <a href="http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx">vtable definition</a>) and the scripting IDispatch interface, you've got a "<a href="http://msdn.microsoft.com/en-us/library/aa366807%28VS.85%29.aspx">dual</a>" interface. </li><li>You need to translate the parameter types to their .NET equivalents. This is an incredibly mechanical process that's straightforward. If there is a chance that the underlying bits are different between COM and .NET (e.g. they're not <a href="http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx">blittable</a>) then you need to use the <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx">MarshalAsAttribute</a> to tell the CLR how to convert the types as necessary. </li><li>You need to remember that COM handles errors by returning HRESULTs instead of natively using exceptions like .NET uses. By default, the CLR will make the last parameter that is an OUT parameter in the IDL to be the return value (it helps if it's marked by "retval"). Therefore, you can act as if the function really returns its last parameter and the CLR will automatically check the HRESULT and throw a corresponding .NET exception as needed.</li><li>Optionally, and perhaps most controversially, you're free de-<a href="http://en.wikipedia.org/wiki/Hungarian_notation">Hungarianize</a> the parameter names and PascalCase the enum names to make them much more friendly looking to people in .NET. It's optional since it might confuse people that use MSDN documentation and expecting the original names. </li></ol><p>In a minute or so, I translated the definitions and gladly got rid of the Hungarian prefixes by converting parameter names of "pszQuery" to just "query." I also converted all the enums and removed their unnecessary prefixes. The end result was this:</p><pre>[<span style="color: rgb(43, 145, 175);">ComImport</span>]<br />[<span style="color: rgb(43, 145, 175);">Guid</span>(<span style="color: rgb(163, 21, 21);">"4e530b0a-e611-4c77-a3ac-9031d022281b"</span>)]<br />[<span style="color: rgb(43, 145, 175);">InterfaceType</span>(<span style="color: rgb(43, 145, 175);">ComInterfaceType</span>.InterfaceIsIUnknown)]<br /><span style="color: rgb(0, 0, 255);">internal</span> <span style="color: rgb(0, 0, 255);">interface</span> <span style="color: rgb(43, 145, 175);">IApplicationAssociationRegistration</span><br />{ <br /> [<span style="color: rgb(0, 0, 255);">return</span>: <span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)]<br /> <span style="color: rgb(0, 0, 255);">string</span> QueryCurrentDefault( [<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> query,<br /> <span style="color: rgb(43, 145, 175);">AssociationType</span> queryType,<br /> <span style="color: rgb(43, 145, 175);">AssociationLevel</span> queryLevel);<br /> [<span style="color: rgb(0, 0, 255);">return</span>: <span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.Bool)]<br /> <span style="color: rgb(0, 0, 255);">bool</span> QueryAppIsDefault([<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> query,<br /> <span style="color: rgb(43, 145, 175);">AssociationType</span> queryType,<br /> <span style="color: rgb(43, 145, 175);">AssociationLevel</span> queryLevel,<br /> [<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> appRegistryName);<br /> [<span style="color: rgb(0, 0, 255);">return</span>: <span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.Bool)]<br /> <span style="color: rgb(0, 0, 255);">bool</span> QueryAppIsDefaultAll(<span style="color: rgb(43, 145, 175);">AssociationLevel</span> queryLevel,<br /> [<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> appRegistryName);<br /> <span style="color: rgb(0, 0, 255);">void</span> SetAppAsDefault([<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> appRegistryName,<br /> [<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> set,<br /> <span style="color: rgb(43, 145, 175);">AssociationType</span> setType);<br /> <span style="color: rgb(0, 0, 255);">void</span> SetAppAsDefaultAll([<span style="color: rgb(43, 145, 175);">MarshalAs</span>(<span style="color: rgb(43, 145, 175);">UnmanagedType</span>.LPWStr)] <span style="color: rgb(0, 0, 255);">string</span> appRegistryName);<br /> <span style="color: rgb(0, 0, 255);">void</span> ClearUserAssociations();<br />}</pre><p>Importing the concrete class that implements the interface was just a matter of specifying its CLSID:</p><pre>[<span style="color: rgb(43, 145, 175);">ComImport</span>]<br />[<span style="color: rgb(43, 145, 175);">Guid</span>(<span style="color: rgb(163, 21, 21);">"591209c7-767b-42b2-9fba-44ee4615f2c7"</span>)]<br /><span style="color: rgb(0, 0, 255);">internal</span> <span style="color: rgb(0, 0, 255);">class</span> <span style="color: rgb(43, 145, 175);">ApplicationAssociationRegistration</span><br />{<br /> <span style="color: rgb(0, 128, 0);">// coclass is implemented by the runtime callable wrapper</span><br />}</pre><p>With all of that goo out of the way, you can use the interface like a normal .NET type:</p><pre><span style="color: rgb(0, 0, 255);">var</span> aa = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(43, 145, 175);">ApplicationAssociationRegistration</span>();<br /><span style="color: rgb(0, 0, 255);">var</span> iaar = (<span style="color: rgb(43, 145, 175);">IApplicationAssociationRegistration</span>)aa;<br /><span style="color: rgb(0, 0, 255);">string</span> myCurrentMp3Player = iaar.QueryCurrentDefault(".mp3", <span style="color: rgb(43, 145, 175);">AssociationType</span>.FileExtension, <span style="color: rgb(43, 145, 175);">AssociationLevel</span>.Effective);</pre><p>Behind the scenes, the <a href="http://msdn.microsoft.com/en-us/library/8bwh56xe.aspx">runtime callable wrapper</a> has to do something like this:</p><ol><li>Load in ole32.dll where COM functions reside.</li><li>Call <a href="http://msdn.microsoft.com/en-us/library/ms678543.aspx">CoInitialize</a> to initialize COM. </li><li>Look up your CLSID and IID in the registry under HKEY_CLASSES_ROOT and find their associated DLL (in our case, "shell32.dll") </li><li><a href="http://msdn.microsoft.com/en-us/library/ms684007%28VS.85%29.aspx">Create a factory</a> for your class. </li><li>Use the factory to <a href="http://msdn.microsoft.com/en-us/library/ms682215%28VS.85%29.aspx">create an instance</a>. </li><li>Call <a href="http://msdn.microsoft.com/en-us/library/ms682521%28VS.85%29.aspx">QueryInterface</a> to get the specific interface we want (e.g. IApplicationAssociationRegistration) </li><li>Get a pointer to the function we want using the <a href="http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx">vtable</a>. </li></ol><p>After all that, we <em>finally</em> have a place to jump to like we did with P/Invoke.</p><p>Why bother with all of this? One reason is that Microsoft has a huge legacy investment in C and C++ in Windows. There's no compelling reason for them to rewrite things in .NET. A natural consequence is that the C++ code that implements their latest APIs will be exposed using COM for the foreseeable future. Recently, Microsoft has gone ahead and published .NET COM <a href="http://code.msdn.microsoft.com/Windows7Taskbar/Release/ProjectReleases.aspx?ReleaseId=2246">wrappers</a> for some of the popular new APIs like the <a href="http://windowsteamblog.com/blogs/developers/archive/2009/04/23/consuming-the-contents-of-windows-7-libraries.aspx">Libraries feature</a> in Windows 7. With just a little work, you don't have to wait on Microsoft to do this for you.</p><p>Given that .NET was designed as a successor to COM, it's no surprise that Microsoft has made interoperability with it very seamless. The <a href="http://msdn.microsoft.com/en-us/library/8bwh56xe.aspx">runtime callable wrapper</a> does a good job of hiding most of the messier details. The garbage collector handles much of the bookkeeping involved with memory management that used to be the bane of COM programming. The runtime is very aware of typical COM semantics of when to allocate and free memory. It's not always perfect. Sometimes you can be pre-emptive and force your COM object to be cleaned up via <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx">Marshal.ReleaseComObject</a> so you don't have to wait on the garbage collector, but you should <a href="http://blogs.msdn.com/cbrumme/archive/2003/04/16/51355.aspx">be careful</a>.</p><p>I just presented the basics of what I learned to get my job done. There's a lot more out there for more advanced scenarios. I've found the <a href="http://www.theserverside.net/tt/articles/showarticle.tss?id=ComAndDotNetInterop_Book">free book</a> "COM and .NET Interop" by Andrew Troelsen to be helpful.</p><p>There's plenty of obscure Windows APIs out there for the taking. Enjoy!</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2009%2f04%2fusing-obscure-windows-com-apis-in-net.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2009%2f04%2fusing-obscure-windows-com-apis-in-net.html" alt="kick it on DotNetKicks.com" border="0" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-7080898641294242243?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com4tag:blogger.com,1999:blog-6800934446457898793.post-83454704416643394922009-03-16T07:47:00.006-04:002009-03-17T09:39:40.212-04:00How .NET Regular Expressions Really Work<p>Remember when you first tried to parse text?</p><p>My early BASIC programs were littered with IF statements that dissected strings using LEFT$, RIGHT$, MID$, TRIM$, and UCASE$. It took me hours to write a program that parsed a simple text file. Just trying to support whitespace and mixed casing was enough to drive me crazy.</p><p>Years later when I started programming in Java, I discovered the <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/StringTokenizer.html">StringTokenizer</a> class. I thought it was a huge leap forward. I no longer had to worry about whitespace. However, I still had to use functions like &quot;substring&quot; and &quot;toUpperCase&quot;, but I thought that was as good as it could get. </p><p>And then one day I found <a href="http://www.regular-expressions.info/quickstart.html">regular</a>&#160;<a href="http://www.dijksterhuis.org/regular-expressions-in-csharp-the-basics/">expressions</a>.</p><p>I almost cried when I realized that I could replace parsing code that took me hours to write with a simple regular expression. It still took me several years to become comfortable with <a href="http://www.addedbytes.com/cheat-sheets/regular-expressions-cheat-sheet/">the syntax</a>, but the learning curve was worth the power obtained. </p><p>And yet with all of this love, I still had this nagging suspicion that I was doing it wrong. After <a href="http://www.moserware.com/2009/01/wetware-refactorings.html">reading Pragmatic Thinking and Learning</a>, I was determined to try to imagine what life was like inside the code I wrote. But I just couldn't connect with a regular expression. </p><p>The last straw came recently when I was trying to help a <a href="http://www.aaronlerch.com/blog/">coworker</a> craft a regex to properly handle name/value string pairs with escaped strings. In the end, our regex worked, but I felt that it was duct-taped together. I knew there was a better way.</p><p><a href="http://www.amazon.com/gp/product/0596528124?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596528124"><img style="margin: 0px 10px 5px 0px" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SbxVzXPjfxI/AAAAAAAABLY/o4BBJWjNWUo/s200/masteringregex.jpg" align="left" /></a>I picked up a copy of Jeffrey Friedl's book &quot;<a href="http://www.amazon.com/gp/product/0596528124?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596528124">Mastering Regular Expressions</a>&quot; and couldn't put it down. In less than a week, I had flown through 400+ pages and had finally started to feel like I understood how regular expressions worked. I finally had a sense for what backtracking really meant and I had a better idea for how a regex could go <a href="http://www.regular-expressions.info/catastrophic.html">catastrophically</a> out of control. </p><p>I had extremely high hopes for chapter 9 which covered the .NET regular expression &quot;flavor.&quot; Since I work with .NET every day, I thought this would be the best chapter. I did learn a few things like how to properly use <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions.aspx">RegexOptions.ExplicitCapture</a>, how to use the <a href="http://msdn.microsoft.com/en-us/library/ewy2t5e0.aspx">special per-match replacement sequences</a> that <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.replace.aspx">Regex.Replace</a> offers, how to <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.compiletoassembly.aspx">save compiled regular expressions to a DLL</a>, and how to <a href="http://weblogs.asp.net/whaggard/archive/2005/02/20/377025.aspx">match balanced parentheses</a> -a feat that's theoretically not possible with a regex. Despite learning all of this in the chapter, I still didn't feel that I could &quot;connect&quot; with the very .NET regular expression engine that I know and love.</p><p>To be fair, the vast benefit of the book comes from the first six chapters that deal with how regular expressions work <em>in general</em> since regex implementations share many ideas. The book laid a solid foundation, but I wanted more. </p><p>I wanted to stop all my hand-waving at regular expressions and actually understand how they <i>really</i> work.</p><p>I knew I wanted to drill into the code. Although tools like <a href="http://www.red-gate.com/products/reflector/">Reflector</a> are amazing, I knew I wanted to see the actual code. It's fairly easy now to <a href="http://weblogs.asp.net/scottgu/archive/2008/01/16/net-framework-library-source-code-now-available.aspx">step into the framework source code</a> in the debugger. Unlike <a href="http://www.moserware.com/2008/09/how-do-locks-lock.html">understanding the details of locking</a>, which had me dive into C++ and x86 assembly, it was refreshing to see that the .NET regular expression engine was written entirely in C#.</p><p>I decided to use a really simple regular expression and search string and then follow it from cradle to grave. If you'd like to follow along at home, I've <a href="http://www.koders.com/csharp/fid7F5AE3CBB76E9E51E24DEA0DB54B86C173369E88.aspx">linked</a> to relevant lines in the .NET regular expression source code.</p><p>My very simple regex consisted of looking for a basic URL:</p><blockquote><pre><span style="color: rgb(0,0,255)">string</span> textToSearch = <span style="color: rgb(0,96,128)">&quot;Welcome to http://www.moserware.com/!&quot;</span>;<br /><span style="color: rgb(0,0,255)">string</span> regexPattern = <span style="color: rgb(0,96,128)">@&quot;http://([^\s/]+)/?&quot;</span>;<br /><span style="color: rgb(43,145,175)">Match</span> m = <span style="color: rgb(43,145,175)">Regex</span>.Match(textToSearch, regexPattern); <br /><span style="color: rgb(43,145,175)">Console</span>.WriteLine(<span style="color: rgb(0,96,128)">&quot;Full uri = '{0}'&quot;</span>, m.Value);<br /><span style="color: rgb(43,145,175)">Console</span>.WriteLine(<span style="color: rgb(0,96,128)">&quot;Host ='{0}'&quot;</span>, m.Groups[1].Value);</pre></blockquote><p>Our journey begins at <a href="http://msdn.microsoft.com/en-us/library/0z2heewz.aspx">Regex.Match</a> where we <a href="http://www.koders.com/csharp/fid7F5AE3CBB76E9E51E24DEA0DB54B86C173369E88.aspx#L113">checking an internal cache</a> of the <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.cachesize.aspx">past 15</a> regex values to see if there a match for:</p><blockquote><p>&quot;0:ENU:http://([^\\s/]+)/?&quot;</p></blockquote><p>This is a compact representation of:</p><blockquote><p><a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions.aspx">RegexOptions</a> : <a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.threeletterwindowslanguagename.aspx">Culture</a> : Regex pattern</p></blockquote><p>The regex doesn't find this in the cache, so it starts <a href="ScanRegex">scanning the pattern</a>. Note that <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L21">out of respect for the authors</a>, our regex pattern doesn't have any comments or whitespace in it:</p><blockquote><pre><span style="color: rgb(0,128,0)">// It would be nice to get rid of the <a href="UseOptionX">comment modes</a>, since the <br />// <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L867">ScanBlank</a>() calls are just kind of duct-taped in.</span></pre></blockquote><p>We <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L265">start</a> creating an internal tree representation of the regex by <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L1869">adding</a> a multi-character (aka &quot;<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L83">Multi</a>&quot;) node to contain the &quot;http://&quot; part. Next, we see that the scanner made it to first real capture:</p><blockquote><p>http://<b>([^\s/]+)</b>/?</p></blockquote><p>This capture contains a <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx">character class</a> that says that we don't want to match spaces or a forward slash. It is converted into an obscure five character string:</p><blockquote><p>&quot;\x1\x2\x1\x2F\x30\x64&quot;</p></blockquote><p>Later we'll see why it had to all fit in one string, but for now we can use a <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L16">helpful comment</a> to decode each character:</p><table cellspacing="0" cellpadding="2" width="400" border="1"><tbody><tr><td valign="top" width="57">Offset</td><td valign="top" width="75">Hex Value</td><td valign="top" width="257">Meaning</td></tr><tr><td valign="top" width="62">0</td><td valign="top" width="75">0x01</td><td valign="top" width="257">The set should be negated</td></tr><tr><td valign="top" width="66">1</td><td valign="top" width="75">0x02</td><td valign="top" width="257">There are two characters in the character part of the set</td></tr><tr><td valign="top" width="70">2</td><td valign="top" width="75">0x01</td><td valign="top" width="257">There is one Unicode category</td></tr><tr><td valign="top" width="73">3</td><td valign="top" width="75">0x2F</td><td valign="top" width="257">Inclusive lower-bound of the character set. It's a '/' in Unicode</td></tr><tr><td valign="top" width="76">4</td><td valign="top" width="75">0x30</td><td valign="top" width="257">Exclusive upper-bound of the character set. It's a '0' in Unicode</td></tr><tr><td valign="top" width="77">5</td><td valign="top" width="75">0x64</td><td valign="top" width="257">This is a magic number that means the &quot;<a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L63">Space</a>&quot; category.</td></tr></tbody></table><p>Before I realized that this string had meaning, I was utterly confused.</p><p>As we continue scanning, we <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L373">find a '+' quantifier</a>:</p><blockquote><p>http://([^\\s/]<strong><span style="font-size:180%;">+</span></strong>)/?</p></blockquote><p>This is noted as a <a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L71">Oneloop</a> node since it's a &quot;loop&quot; of what came before (e.g. the character class set). It has arguments of 1 and <a href="http://msdn.microsoft.com/en-us/library/system.int32.maxvalue.aspx">Int32.MaxValue</a> to denote 1 or more matches. We see that the next character isn't a '?', so we can assert this is <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L406">not a lazy match</a> which means it's a <a href="http://en.wikipedia.org/wiki/Regular_expression#Lazy_quantification">greedy</a> match.&#160;</p><p>The first <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L301">group is recorded</a> when we hit the ')' character. At the end of the pattern, we note a <a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L79">One</a> (character) node for the '/' and we see it's followed by a '<a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L368">?</a>'&#160; which is just <a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L551">another quantifier</a>, this time with a minimum of 0 and a maximum of 1.</p><p>All those nodes come together to give us this &quot;<a href="http://www.koders.com/csharp/fidECC3E02EC33C0F92A3E24574A0673340C8A22B2C.aspx">RegexTree</a>:&quot;</p><p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SbcqJZeaP-I/AAAAAAAABKo/xD5zClg2S5I/s1600-h/RegexParseTree.png"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SbcqJZeaP-I/AAAAAAAABKo/xD5zClg2S5I/s400/RegexParseTree.png" /></a></p><p>We still need to <a href="http://www.koders.com/csharp/fid7F5AE3CBB76E9E51E24DEA0DB54B86C173369E88.aspx#L133">convert the tree to code</a> that the regular expression &quot;machine&quot; can execute later. The bulk of the work is done by an aptly named <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L223">RegexCodeFromRegexTree</a> function that has a decent <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L212">comment</a>:</p><blockquote><pre><span style="color: rgb(0,128,0)">/*<br /> * The top level RegexCode generator. It does a depth-first walk <br /> * through the tree and calls EmitFragment to emits code before <br /> * and after each child of an interior node, and at each leaf. <br /> * <br /> * It runs two passes, first to count the size of the generated <br /> * code, and second to generate the code. <br /> * <br /> * &lt;CONSIDER&gt;we need to time it against the alternative, which is <br /> * to just generate the code and grow the array as we go.&lt;/CONSIDER&gt; <br /> */</span></pre></blockquote><p>I love the anonymous &quot;CONSIDER&quot; comment and would have had a similar reaction. Instead of using an <a href="http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx">ArrayList</a> or <a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx">List</a>&lt;int&gt; to store the op codes, which can automatically resize as needed, the code diligently goes through the entire RegexTree <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L248"><i>twice</i></a>. The class is peppered with &quot;<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L126">if(_counting)</a>&quot; expressions that just increase a counter by the size they will use in the next pass.</p><p>As predicted by the comment, the bulk of the work is done by the 250 line switch statement that makes up the <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L305">EmitFragment function</a>. This function breaks up RegexTree &quot;fragments&quot; and converts them to a simpler <a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx">RegexCode</a>. The first fragment is:</p><blockquote><p>EmitFragment(nodetype=<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L450">RegexNode.Capture | BeforeChild</a>, node=[<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L113">RegexNode.Capture</a>, Group=0, Length=-1], childIndex=0)</p></blockquote><p>This is shorthand for emitting the RegexCode that should come before the children of the top level &quot;<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L113">RegexNode.Capture</a>&quot; node that represents group 0 and that goes until the end of the string (e.g. has length -1). The last 0 means that it's the 0th child of the parent node (this is sort of meaningless since it has no parent). The subsequent calls walk the rest of the tree:</p><blockquote><p>EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L321">RegexNode.Concatenate | BeforeChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=0)<br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L522">RegexNode.Multi</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L83">RegexNode.Multi</a>, string=&quot;http://&quot;], childIndex=0)<br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L322">RegexNode.Concatenate | AfterChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=0)<br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L321">RegexNode.Concatenate | BeforeChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=1)<br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L450">RegexNode.Capture | BeforeChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L113">RegexNode.Capture</a>, Group=1, -1], childIndex=0) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L513">RegexNode.SetLoop</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L73">RegexNode.SetLoop</a>, min=1, max=Int32.MaxValue], childIndex=0) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L454">RegexNode.Capture | AfterChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L113">RegexNode.Capture</a>, Group=1, Length=-1], childIndex=0) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L322">RegexNode.Concatenate | AfterChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=1) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L321">RegexNode.Concatenate | BeforeChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=2) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L503">RegexNode.Oneloop</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L71">RegexNode.Oneloop</a>, min=0, max=1, character='/'], childIndex=0) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L322">RegexNode.Concatenate | AfterChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L108">RegexNode.Concatenate</a>], childIndex=2) <br />EmitFragment(<a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L454">RegexNode.Capture | AfterChild</a>, [<a href="http://www.koders.com/csharp/fid0C0231291E4A7914C135C0A730D5A85182F872EB.aspx#L113">RegexNode.Capture</a>, Group=0, Length=-1], childIndex=0)</p></blockquote><p>The reward for all this work is an integer array that describes the RegexCode &quot;op codes&quot; and their arguments. You can see that some instructions like &quot;<a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L43">Setrep</a>&quot; take a string argument. These arguments point to offsets in a string table. This is why it was critical to pack everything about a set into the obscure string we saw earlier. It was the only way to pass that information to the instruction.</p><p>Decoding the code array, we see:</p><table cellspacing="0" cellpadding="2" width="712" border="1"><tbody><tr><td valign="top" width="92">Index</td><td valign="top" width="138">Instruction</td><td valign="top" width="148">Op Code/Argument</td><td valign="top" width="158">String Table Reference</td><td valign="top" width="174">Description</td></tr><tr><td valign="top" width="93">0</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L73">Lazybranch</a></td><td valign="top" width="148">23</td><td valign="top" width="158">&#160;</td><td valign="top" width="174" rowspan="2">Lazily branch to the <a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L91">Stop</a> instruction at offset 21.</td></tr><tr><td valign="top" width="93">1</td><td valign="top" width="138">&#160;</td><td valign="top" width="148">21</td><td valign="top" width="157">&#160;</td></tr><tr><td valign="top" width="93">2</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L81">Setmark</a></td><td valign="top" width="149">31</td><td valign="top" width="156">&#160;</td><td valign="top" width="174">Push our current state onto a stack in case we need to backtrack later.</td></tr><tr><td valign="top" width="93">3</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L57">Multi</a></td><td valign="top" width="149">12</td><td valign="top" width="156">&#160;</td><td valign="top" width="174" rowspan="2">Perform a multi-character match of string table item 0 which is &quot;http://&quot;.</td></tr><tr><td valign="top" width="93">4</td><td valign="top" width="139">&#160;</td><td valign="top" width="149">0</td><td valign="top" width="156">&quot;http://&quot;</td></tr><tr><td valign="top" width="93">5</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L81">Setmark</a></td><td valign="top" width="149">31</td><td valign="top" width="156">&#160;</td><td valign="top" width="174">Push our current state onto a stack in case we need to backtrack later.</td></tr><tr><td valign="top" width="94">6</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L43">Setrep</a></td><td valign="top" width="149">2</td><td valign="top" width="155">&#160;</td><td valign="top" width="174" rowspan="3">Perform a set repetition match of length 1 on the set stored at string table position 1, which represents [^\s/].</td></tr><tr><td valign="top" width="94">7</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">1</td><td valign="top" width="155">&quot;\x1\x2\x1\x2F\x30\x64&quot;</td></tr><tr><td valign="top" width="94">8</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">1</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">9</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L47">Setloop</a></td><td valign="top" width="149">5</td><td valign="top" width="155">&#160;</td><td valign="top" width="174" rowspan="3">Match the set [^\s/] in a loop at most Int32.MaxValue times.</td></tr><tr><td valign="top" width="94">10</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">1</td><td valign="top" width="155">&quot;\x1\x2\x1\x2F\x30\x64&quot;</td></tr><tr><td valign="top" width="94">11</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">2147483647</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">12</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L82">Capturemark</a></td><td valign="top" width="149">32</td><td valign="top" width="155">&#160;</td><td valign="top" width="174" rowspan="3">Capture into group #1, the string between the mark set by the last Setmark and the current position.</td></tr><tr><td valign="top" width="94">13</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">1</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">14</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">-1</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">15</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L45">Oneloop</a></td><td valign="top" width="149">3</td><td valign="top" width="155">&#160;</td><td valign="top" width="174" rowspan="3">Match Unicode character 47 (a '/') in a loop for a maximum of 1 time.</td></tr><tr><td valign="top" width="94">16</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">47</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">17</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">1</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">18</td><td valign="top" width="138"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L82">Capturemark</a></td><td valign="top" width="149">32</td><td valign="top" width="155">&#160;</td><td valign="top" width="174" rowspan="3">Capture into group #0, the contents between the first Setmark instruction and the current position.</td></tr><tr><td valign="top" width="94">19</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">0</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">20</td><td valign="top" width="138">&#160;</td><td valign="top" width="149">-1</td><td valign="top" width="155">&#160;</td></tr><tr><td valign="top" width="94">21</td><td valign="top" width="139"><a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx#L91">Stop</a></td><td valign="top" width="151">40</td><td valign="top" width="160">&#160;</td><td valign="top" width="174">Stop the regex.</td></tr></tbody></table><p>We can now see that our regex has turned into a simple &quot;program&quot; that will be executed later.</p><p><b>Prefix Optimizations</b></p><p>We could stop here, but we'd miss the fun &quot;optimizations.&quot; With our pattern and search string, the optimizations will actually slow things down, but the code generator is oblivious to that. The basic idea behind prefix optimizations is to quickly jump to where the match <i>might </i>start. It does this by <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L289">using</a> a <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx">RegexFCD</a> class that I'm guessing stands for &quot;Regex First Character Descriptor.&quot; </p><p>With our regex, the <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx#L53">FirstChars</a> functions <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx#L462">notices our &quot;http://&quot; 'Multi' node</a> and <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx#L524">determines</a> that any match must start with an 'h'. If we had alternations, the first character of each alternation would be added to make a limited set of potential first characters. With this optimization alone, we can skip all characters in the text that aren't in this approved &quot;white list&quot; of first characters without having to execute any of the above RegexCode.</p><p>But wait... there's an even trickier optimization! The optimizer <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L295">discovers</a> that the first thing the regex must match is a simple string literal: <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx#L106">a 'Multi' node</a>. This means that we can use the <a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx">RegexBoyerMoore</a> class which applies the <a href="http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm">Boyer-Moore</a> search algorithm. </p><p>The key insight is that we don't have to check each character of the text. We only need to look at last character to see if it's even worth checking the rest.</p><p>For example, if our sample text is &quot;Welcome to http://www.moserware.com/!&quot; and we're searching for &quot;http://&quot; which is 7 characters, we first look at the 7th character of the text which is 'e'. Since 'e' is not the 7th character of what we're looking for (which is a '/'), we know that there couldn't possibly be a match and so we don't need to bother checking all previous 6 characters because there isn't even an 'e' in what we're looking for. The tricky part is what to do if the what we find <i>is</i> in the string that we're trying to match, but it isn't the last '/' character. </p><p>The specifics are handled in <a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L91">straightforward</a>&#160;<a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L166">way</a> with some minor optimizations to reduce memory needs given 65,000+ possible Unicode characters. For each character, the maximum possible skip is calculated.</p><p>For &quot;http://&quot;, we come up with this skip table:</p><table cellspacing="0" cellpadding="2" width="195" border="1"><tbody><tr><td valign="top" width="74">Character</td><td valign="top" width="119">Characters to skip ahead</td></tr><tr><td valign="top" width="79">/</td><td valign="top" width="119">0</td></tr><tr><td valign="top" width="83">:</td><td valign="top" width="119">2</td></tr><tr><td valign="top" width="86">h</td><td valign="top" width="119">6</td></tr><tr><td valign="top" width="88">p</td><td valign="top" width="119">3</td></tr><tr><td valign="top" width="89">t</td><td valign="top" width="119">4</td></tr><tr><td valign="top" width="90">all others</td><td valign="top" width="119">7</td></tr></tbody></table><p>This table tells us that if we find an 'e' then we can skip ahead 7 characters without even checking the previous 6 characters. If we find a 'p', then we can skip ahead at least 3 characters before performing a full check, and if we find a '/' then we could be on the last character and need to check other characters (e.g. skip ahead 0).</p><p>There is one more optimization that <a href="http://www.koders.com/csharp/fid4F4894401F2873F7C00CC3CF96F851ED3ED10D69.aspx#L133">looks for anchors</a>, but none apply to our regex, so it's ignored.</p><p>We're done! We made it to the end of the <a href="http://www.koders.com/csharp/fidC6F7EB8E11A6BF080CFA281BEEE003B5FAAB4AD9.aspx#L302">RegexWriter phase</a>. The &quot;<a href="http://www.koders.com/csharp/fidF4B2B64D471D5B7401063DE2054CB33F28BDA026.aspx">RegexCode</a>&quot; internal representation consists of these critical parts:</p><ol><li>The regex code we created. </li><li>The string table derived from the regex that the code uses (e.g. our &quot;Multi&quot; and &quot;Setrep&quot; instructions have string table references). </li><li>The maximum size of our backtracking stack. (Ours is 7, this will make more sense later.) </li><li>A mapping of named captures to their group numbers. (We don't have any in our regex, so this is empty.) </li><li>The total number of captures. (We have 2.) </li><li>The RegexBoyerMoore prefix that we calculated. (This applies to us since we have a string literal at the start.) </li><li>The possible first characters in our prefix. (In our case, we calculated this to be an 'h'.) </li><li>Our anchors. (We don't have any.) </li><li>An indicator whether this should be a RightToLeft match. (In our case, we use the default which is false.) </li></ol><p>Every regex passes through this step. It applies to our measly regex with a code size of 21 as much as it does to a gnarly <a href="http://tools.ietf.org/html/rfc2822#section-3.4.1">RFC2822</a> <a href="http://www.regular-expressions.info/email.html">compliant regex</a> that has 175. These nine items completely describe <em>everything</em> that we'll do with our regex and they never change. </p><p><b>In need of an interpreter</b></p><p>Now that we have the RegexCode, the <a href="http://msdn.microsoft.com/en-us/library/twcw2f1c.aspx">match</a> method will <a href="http://www.koders.com/csharp/fid7F5AE3CBB76E9E51E24DEA0DB54B86C173369E88.aspx#L919">run</a> and create a <a href="http://www.koders.com/csharp/fidABFA3D15F7A596443DCE29D6AE984F1192048031.aspx">RegexRunner</a> which is the &quot;driver&quot; for the regex matching process. Since we didn't specify the &quot;Compiled&quot; flag, we'll use the <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx">RegexInterpreter</a> runner.</p><p>Before the interpreter starts <a href="http://www.koders.com/csharp/fidABFA3D15F7A596443DCE29D6AE984F1192048031.aspx#L81">scanning</a>, it <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L364">notices</a> that we have a valid Boyer-Moore prefix optimization and it <a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L269">uses it</a> to quickly locate the start of the regex:</p><table cellspacing="0" cellpadding="2" width="779" border="1"><tbody><tr><td valign="top" width="68">Index</td><td valign="top" width="19">0</td><td valign="top" width="15">1</td><td valign="top" width="14">2</td><td valign="top" width="14">3</td><td valign="top" width="15">4</td><td valign="top" width="18">5</td><td valign="top" width="15">6</td><td valign="top" width="14">7</td><td valign="top" width="14">8</td><td valign="top" width="15">9</td><td valign="top" width="21">10</td><td valign="top" width="21">11</td><td valign="top" width="21">12</td><td valign="top" width="21">13</td><td valign="top" width="21">14</td><td valign="top" width="21">15</td><td valign="top" width="21">16</td><td valign="top" width="21">17</td><td valign="top" width="21">18</td><td valign="top" width="21">19</td><td valign="top" width="21">20</td><td valign="top" width="21">21</td><td valign="top" width="21">22</td><td valign="top" width="21">23</td><td valign="top" width="21">24</td><td valign="top" width="21">25</td><td valign="top" width="21">26</td><td valign="top" width="21">27</td><td valign="top" width="21">28</td><td valign="top" width="21">29</td><td valign="top" width="21">30</td><td valign="top" width="21">31</td><td valign="top" width="21">32</td><td valign="top" width="21">33</td><td valign="top" width="21">34</td><td valign="top" width="21">35</td><td valign="top" width="10">36</td></tr><tr><td valign="top" width="68">Character</td><td valign="top" width="19">W</td><td valign="top" width="15">e</td><td valign="top" width="14">l</td><td valign="top" width="14">c</td><td valign="top" width="15">o</td><td valign="top" width="18">m</td><td valign="top" width="15">e</td><td valign="top" width="14">&#160;</td><td valign="top" width="14">t</td><td valign="top" width="15">o</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">h</td><td valign="top" width="21">t</td><td valign="top" width="21">t</td><td valign="top" width="21">p</td><td valign="top" width="21">:</td><td valign="top" width="21">/</td><td valign="top" width="21">/</td><td valign="top" width="21">w</td><td valign="top" width="21">w</td><td valign="top" width="21">w</td><td valign="top" width="21">.</td><td valign="top" width="21">m</td><td valign="top" width="21">o</td><td valign="top" width="21">s</td><td valign="top" width="21">e</td><td valign="top" width="21">r</td><td valign="top" width="21">w</td><td valign="top" width="21">a</td><td valign="top" width="21">r</td><td valign="top" width="21">e</td><td valign="top" width="21">.</td><td valign="top" width="21">c</td><td valign="top" width="21">o</td><td valign="top" width="21">m</td><td valign="top" width="21">/</td><td valign="top" width="10">!</td></tr><tr><td valign="top" width="68">Scan Order</td><td valign="top" width="19">&#160;</td><td valign="top" width="15">&#160;</td><td valign="top" width="14">&#160;</td><td valign="top" width="14">&#160;</td><td valign="top" width="15">&#160;</td><td valign="top" width="18">&#160;</td><td valign="top" width="15">1</td><td valign="top" width="14">&#160;</td><td valign="top" width="14">&#160;</td><td valign="top" width="15">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">9</td><td valign="top" width="21">8</td><td valign="top" width="21">2 & 7</td><td valign="top" width="21">6</td><td valign="top" width="21">5</td><td valign="top" width="21">4</td><td valign="top" width="21">3</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="21">&#160;</td><td valign="top" width="10">&#160;</td></tr></tbody></table><p>It first looks at the 7th character and finds an 'e' instead of the '/' that it wanted. The skip table tells it that 'e' isn't in any possible match, so it jumps ahead 7 more characters where it finds a 't'. The skip table <a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L318">tells it</a> to jump ahead 4 more characters where it <em>finally</em> finds the '/' it wanted. It then <a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L326">verifies</a> that this is the last character of our &quot;http://&quot; prefix. With a valid prefix found, we <a href="http://www.koders.com/csharp/fidABFA3D15F7A596443DCE29D6AE984F1192048031.aspx#L187">prepare for a match</a> in case we're lucky and the rest of the regex matches. </p><p>The bulk of the interpreter is in its &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L403">Go</a>&quot; method which is a 700 line switch statement that interprets the RegexCode we created earlier. The only interesting part is that the interpreter keeps two stacks to keep its state in case it needs to backtrack and abandon a path it took. The &quot;run <b>s</b>tack&quot; records where in the search string an operation begins while the &quot;run <b>t</b>rack&quot; records the RegexCode instruction that could potentially backtrack. Any time there is a chance that the interpreter could go down a wrong path, it pushes its state onto these stacks so that it can potentially try something else later.</p><p>On our string, the following instructions execute:</p><ol><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L430">Lazybranch</a> - This is a branch that is &quot;lazy.&quot; It will only occur if we fail and have to backtrack to this instruction. In case there are problems, we push 11 (the string offset to the start of &quot;http://&quot;) onto the &quot;run <b>s</b>tack&quot; and 0 (the RegexCode offset for this instruction) onto the &quot;run <b>t</b>rack.&quot; The branch is to code offset 21 which is the &quot;Stop&quot; instruction. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L441">Setmark</a> - We save our position in case we have to backtrack. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L824">Multi</a> - A multi-character match. The string to match is at offset 0 in the string table (which is &quot;http://&quot;). </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L441">Setmark</a> - Another position save in case of a backtrack. Since the Multi code succeeded, we push our &quot;run <b>s</b>tack&quot; offset of 18 (the start of &quot;www.&quot;) and our &quot;run <b>t</b>rack<b>&quot; </b>code position of 5 </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L883">Setrep</a> - Loads the &quot;\x1\x2\x1\x2F\x30\x64&quot; set representation at offset 1 in the string table that we calculated earlier. It reads an operand from the execution stack that we should verify that the set <b>rep</b>eats exactly once. It calls <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L815">CharInClassRecursive</a> that does the following: <ol><li>It sees that the first character, 'w', is not in the character range ['/', '0'). This check corresponds to the '/' in the &quot;[^\s/]&quot; part of the regex. </li><li>It next tries <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L874">CharInCategory</a> which notes that 'w' is part of the &quot;LowercaseLetter&quot; <a href="http://msdn.microsoft.com/en-us/library/system.globalization.unicodecategory.aspx">UnicodeCategory</a>. The magic number 0x64 in our set tells us to <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L890">do </a>a <a href="http://msdn.microsoft.com/en-us/library/t809ektx.aspx">Char.IsWhiteSpace</a> check on it. This too fails. </li><li>Although both checks fail, the interpreter sees that it needs to <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L828">flip the result</a> since it is a negated (^) set. This makes the character class match succeed. </li></ol></li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L948">Setloop</a> - A &quot;loop&quot; instruction is like a &quot;rep&quot; one except that it isn't forced to match anything. In our case, we see that we loop for a maximum of Int32.MaxValue times on the same set we saw in &quot;Setrep.&quot; Here you can see that the code generation phase turned the &quot;+&quot; in &quot;[^\s/]+&quot; of the regex into a Setrep of 1 followed by a Setloop. This is equivalent to &quot;[^\s/][^\s/]*&quot;. The loop keeps chomping characters until it finds the '/' which causes it to call <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L321">BackwardNext()</a> which sets the current position to just before the final '/'. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L470">CaptureMark</a> - Here we start capturing group 1 by popping the &quot;run <b>s</b>tack&quot; which gives us 18. Our current offset is 35. We <a href="http://www.koders.com/csharp/fidABFA3D15F7A596443DCE29D6AE984F1192048031.aspx#L354">capture</a> the string between these two positions, &quot;www.moserware.com&quot;, and <a href="http://www.koders.com/csharp/fidABFA3D15F7A596443DCE29D6AE984F1192048031.aspx#L330">keep it</a> for later use in case the entire regex succeeds. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L900">Oneloop</a> - Here we do a loop at most one time that will check for the '/' character. It succeeds. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L470">CaptureMark</a> - We capture into group 0 the value between the offset on the &quot;run <b>s</b>tack&quot;, which is 11 (the start of &quot;http://&quot;), and the last character of the string at offset 36. The string between these offsets is &quot;http://www.moserware.com/&quot;. </li><li><a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L414">Stop</a> - We're done executing RegexCode and can stop the interpreter. </li></ol><p>Since we stopped with successful captures, the Match is declared <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.group.success.aspx">a success</a>. Sure enough, if we look at our console window, we see:</p><blockquote><pre>Full uri = 'http://www.moserware.com/'<br />Host ='www.moserware.com'</pre></blockquote><p><b>Backtracking Down Unhappy Paths</b></p><p>I can hear the cursing shouts of ^#!@.*#!$ from the regex mob coming towards me. They're miffed that I used a toy regular expression with a pathetically easy search text that didn't do anything &quot;interesting.&quot;</p><p>The mob really shouldn't be that worried. We already have all the essential tools we need to understand how things work.</p><p>One common issue that you have to deal with in a &quot;real&quot; regular expression is backtracking. </p><p>Let's say you have a search text and pattern like this:</p><blockquote><pre><span style="color: rgb(0,0,255)">string</span> text = <span style="color: rgb(0,128,0)">&quot;This text has 1 digit in it&quot;</span>;<br /><span style="color: rgb(0,0,255)">string</span> pattern = <span style="color: rgb(0,128,0)">@&quot;.*\d&quot;</span>; <span style="color: rgb(43,145,175)">Regex</span>.Match(text, pattern);</pre></blockquote><p>You'd recognize the parse tree:</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SbwnM1rcCXI/AAAAAAAABLA/P6DqBD--AWk/s1600-h/RegexParseTreeDotStarDigit.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SbwnM1rcCXI/AAAAAAAABLA/P6DqBD--AWk/s400/RegexParseTreeDotStarDigit.png" /></a> </p><p>The only thing new about it is that the '.' pattern was translated into a &quot;Notone&quot; node that matches anything except one particular character (in our case, a line feed). We see that the set follows the obscure, but compact representation. The only thing new to report is that '\x09' is the magic number to represent all Unicode digits (which the <a href="http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html">Turkey Test</a> showed is more than just [0-9]).</p><p>It's painful to watch the regex interpreter work so hard for this match. The &quot;.*&quot; puts it <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L924">in a Notoneloop</a> that goes right to the end of the string since it doesn't find a line feed ('\n'). It then looks for <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L817">the Set</a> that represents &quot;\d&quot; and it fails. It has no choice but to backtrack by executing the &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L973">RegexCode.Notoneloop | RegexCode.Back</a>&quot; composite instruction which backtracks one character by resetting the &quot;run <strong>t</strong>rack&quot; to be the Set instruction again, but this time it will start one character earlier.</p><p>Even in our insanely simple search string, the interpreter has to backtrack by executing &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L973">RegexCode.Notoneloop | RegexCode.Back</a>&quot; and retesting <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L817">the Set</a> a total of <em>thirteen times</em>.</p><p>An almost identical process occurs if we had used a lazy match regular expression like &quot;.*?\d&quot;. The difference is that it does a &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L1004">Notonelazy</a>&quot; instruction and then gets caught up in a &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L1050">RegexCode.Notonelazy | RegexCode.Back</a>&quot; backtrack and <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L817">Set match</a> attempt that happens <em>fourteen times</em>. Each iteration of the loop causes the &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L1004">Notonelazy</a>&quot; instruction to add one more character instead of removing one like the &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L924">Notoneloop</a>&quot; instruction had to. This is typical:</p><blockquote><p>In situations where the decision is between &quot;make an attempt&quot; and &quot;skip an attempt,&quot; as with items governed by quantifiers, the engine always chooses to first <em>make</em> the attempt for <em>greedy</em> quantifiers, and to first <em>skip</em> the attempt for <em>lazy</em> (non-greedy) ones.&#160; <em><a href="http://www.amazon.com/gp/product/0596528124?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596528124">Mastering Regular Expressions</a></em>, p.159</p></blockquote><p>If we had a little more empathy for the regex interpreter, we would have written &quot;[^\d]*\d&quot; and avoided all the backtracking, but it wouldn't have shown this common error.</p><p>Alternations such as &quot;hello|world&quot; are handled with backtracking. Before each alternative is attempted, the current position is saved on the &quot;run <strong>t</strong>rack&quot; and &quot;run <strong>s</strong>tack.&quot; If the alternate fails, the regex engine resets the position to what it was before the alternate was tried and the next alternate is attempted.</p><p>Now, we can even understand how more advanced concepts like <a href="http://www.regular-expressions.info/atomic.html">atomic grouping</a> work. If we use a regex like:</p><blockquote><p>\w+:</p></blockquote><p>to match the names of email headers as in:</p><blockquote><p>Subject: Hello World!</p></blockquote><p>Things will work well. The problem will come when we try to match against</p><blockquote><p>Subject</p></blockquote><p>We already know that there is going to be a backtracking since &quot;\w+&quot; will match the whole string and then backtracking will occur as the interpreter desperately tries to match a ':'. If we used atomic grouping, as in:</p><blockquote><p>(?&gt;\w+):</p></blockquote><p>We would see that the generated RegexCode has two extra instructions of <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L701">Setjump</a> and <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L723">Forejump</a> in it. These instructions tell the interpreter to do unconditional jumps after matching the &quot;\w+&quot;. As <a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L723">the comment</a> for &quot;Forejump&quot; indicates, these unconditional jumps will &quot;zap backtracking state&quot; and be much more efficient for a failed match since backtracking won't occur.</p><p><b>Loose Ends</b></p><p>There are some minor details left. The first time you use any regex, a <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L102">lot</a> <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L260">of</a> <a href="http://www.koders.com/csharp/fid14AB8BA02EE8A6DBA830F1DCC147C2B17F0B3DE0.aspx#L358">work</a> goes on initializing all the <a href="http://msdn.microsoft.com/en-us/library/20bw873z.aspx">character classes</a> that are stored as static variables. If you just timed a single Regex, your numbers would be highly skewed by this process.</p><p>Another common issue is whether you should use the RegexOptions.Compiled flag. Compiling is handled by the <a href="http://www.koders.com/csharp/fid7CC2751EC539A3CCF3A96A3D82E38D6E6D7B79F3.aspx">RegexCompiler</a> class. The interesting aspects of the IL code generation is handled exactly like the interpreter, as indicated by <a href="http://www.koders.com/csharp/fid7CC2751EC539A3CCF3A96A3D82E38D6E6D7B79F3.aspx">this comment</a>: </p><blockquote><pre><span style="color: rgb(0,128,0)">/* <br /> * The main translation function. It translates the logic for a single opcode at <br /> * the current position. The structure of this function exactly mirrors <br /> * the structure of the inner loop of RegexInterpreter.Go(). <br /> * <br /> * The C# code from RegexInterpreter.Go() that corresponds to each case is <br /> * included as a comment. <br /> * <br /> * Note that since we're generating code, we can collapse many cases that are <br /> * dealt with one-at-a-time in RegexIntepreter. We can also unroll loops that <br /> * iterate over constant strings or sets. <br /> */</span></pre></blockquote><p>We can see that there <em>is</em> some optimization in the generated code. The down side is that we have to generate all the code regardless of if we use all of it or not. The interpreter only uses what it needs. Additionally, unless we use <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.compiletoassembly.aspx">Regex.CompileToAssembly</a> to save the compiled code to a DLL, we'll end up doing the entire process of creating the parse tree, RegexCode, and code generation at runtime.</p><p>Thus, for most cases, it seems that RegexOptions.Compiled isn't worth the effort. But it's good to keep in mind that there are exceptions when performance is critical and your regex can benefit from it (otherwise, why have the option at all?).</p><p>Another option is <a href="http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions.aspx">RegexOptions</a>.IgnoreCase that makes everything case insensitive. The vast majority of the process stays the same. The only difference is that all instructions that compare characters will convert each <a href="http://msdn.microsoft.com/en-us/library/system.char.aspx">System.Char</a> to lower case, mostly using the <a href="http://msdn.microsoft.com/en-us/library/xt041c19.aspx">Char.ToLower</a> method. This sounds reasonable, but it's not quite perfect. For example, in Koine Greek, the word for &quot;<a href="http://www.blueletterbible.org/lang/lexicon/lexicon.cfm?Strongs=G4597&amp;t=NKJV">moth</a>&quot; goes from uppercase to lowercase like this: </p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Sbwmu25wcUI/AAAAAAAABK4/Of_LjLHbejs/s1600-h/mothUpperAndLower.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/Sbwmu25wcUI/AAAAAAAABK4/Of_LjLHbejs/s400/mothUpperAndLower.png" /></a> </p><p>That is, in Greek, when a &quot;sigma&quot; (&#931;) appears in lowercase at the end of a word, it uses a <a href="http://blogs.msdn.com/michkap/archive/2005/05/26/421987.aspx">different letter</a> (&#962;) than if it appeared anywhere else (&#963;). RegexOptions.IgnoreCase can't handle cases that need more context than a single <a href="http://msdn.microsoft.com/en-us/library/system.char.aspx">System.Char</a> even though the string comparison functions can handle this. Consider this example:</p><blockquote><pre><span style="color: rgb(0,0,255)">string</span> mothLower = <span style="color: rgb(0,96,128)">&quot;&#963;&#8053;&#962;&quot;</span>; <br /><span style="color: rgb(0,0,255)">string</span> mothUpper = mothLower.ToUpper(); <span style="color: rgb(0,128,0)">// &quot;&#931;&#8139;&#931;&quot;</span><br /><span style="color: rgb(0,0,255)">bool</span> stringsAreEqualIgnoreCase = mothUpper.Equals(mothLower, <span style="color: rgb(43,145,175)">StringComparison</span>.CurrentCultureIgnoreCase);&#160; <span style="color: rgb(0,128,0)">// true</span> <br /><span style="color: rgb(0,0,255)">bool</span> stringsAreEqualRegex = <span style="color: rgb(43,145,175)">Regex</span>.IsMatch(mothLower, mothUpper, <span style="color: rgb(43,145,175)">RegexOptions</span>.IgnoreCase); <span style="color: rgb(0,128,0)">// false</span></pre></blockquote><p>This also means that .NET's Regex won't do well with characters outside the <a href="http://en.wikipedia.org/wiki/Basic_Multilingual_Plane">Basic Multilingual Plane</a> that need to be represented by more than one <a href="http://msdn.microsoft.com/en-us/library/system.char.aspx">System.Char</a> as a &quot;<a href="http://msdn.microsoft.com/en-us/library/8k5611at.aspx">surrogate pair</a>.&quot;</p><p>I bring all of these &quot;cases&quot; up because it obviously troubled one of the Regex programmers who wrote this <a href="http://www.koders.com/csharp/fidC88A6970F260F6826C679E703634322F3C553827.aspx#L1859">comment</a> <em><a href="http://www.koders.com/csharp/fidA16EF1E737BCF735FD1DE4D39E0E1AD9851FC2A7.aspx#L64">twice</a></em>:</p><blockquote><pre><span style="color: rgb(0,128,0)">// We do the ToLower character by character for consistency.&#160; With surrogate chars, doing <br />// a ToLower on the entire string could actually change the surrogate pair.&#160; This is more correct <br />// linguistically, but since Regex doesn't support surrogates, it's more important to be <br />// consistent.</span></pre></blockquote><p>You can tell the author was fully anticipating the <a href="http://code.logos.com/blog/2008/07/net_regular_expressions_and_unicode.html">bug reports</a> that eventually came as a result of this decision. Unfortunately, due to the way the code is structured, changing this behavior would take a hefty overhaul of the engine and would require a massive amount of regression testing. I'm guessing this is the reason why it won't be coming in a service pack anytime soon.</p><p>The last interesting option that affects most of the code is RegexOptions.RightToLeft. For the most part, this affects where the searching starts and how a &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L229">bump</a>&quot; is applied. When the engine wants to move forward or get the characters to the &quot;right&quot;, it checks this option to see if it should move +1 or -1 character from the current position. It's a simple idea, but its implementation is with many &quot;<a href="http://www.koders.com/csharp/fidE76CE858561A50AF7A1D9030DC8F2F4D6DEF839D.aspx#L247">if(!runrtl)</a>&quot; statements spread throughout the code.</p><p>Finally, you might be interested in how <a href="http://www.mono-project.com/Main_Page">Mono</a>'s regular expression compares with Microsoft's. The good news is that the code <a href="http://anonsvn.mono-project.com/viewvc/trunk/mcs/class/System/System.Text.RegularExpressions/">is also available</a> online as well. In general, Mono's implementation is very similar. Here are some of the (minor) differences:</p><ul><li>Mono's parse tree has a similar shape, but it uses more strongly typed classes. For example, sets such as [^\s/] are given their own class rather than encoded as a single string. </li><li>The Boyer-Moore prefix optimization is done in the <a href="http://anonsvn.mono-project.com/viewvc/trunk/mcs/class/System/System.Text.RegularExpressions/quicksearch.cs?view=log">QuickSearch</a> class. It is calculated at run-time and is only used if the search string is longer than 5 characters. </li><li>The regex machine doesn't have a separate string table for referencing strings like &quot;http://&quot;. Each character is passed in as an argument to the instruction. </li></ul><p><strong>Conclusion</strong></p><p>Weighing in around 14,000 lines of code, .NET's regular expression engine takes awhile to digest. After getting over the shock of its size, it was relatively straightforward to understand. Seeing the real source code, with its occasional funny comments, provided insight that Reflector simply couldn't offer. In the end, we see that a .NET regular expression pattern is simply a compact representation for its internal RegexCode machine language. </p><p>This whole process has allowed me to finally connect with regular expressions and give them a splash of empathy. Seeing the horror of backtracking first hand in the debugger was enough for me to want to do everything in my power to get rid of it. Following the translation process down to the RegexCode level clued me into how my regex pattern will actually execute. Feeling the wind fly by a regex using the Boyer-Moore prefix optimization has encouraged me to do whatever I can to put string literals at the front of a pattern. </p><p>It's all these little things that add up to a blazingly fast regular expression.</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2009%2f03%2fhow-net-regular-expressions-really-work.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2009%2f03%2fhow-net-regular-expressions-really-work.html" border="0" alt="kick it on DotNetKicks.com" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-8345470441664339492?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com19tag:blogger.com,1999:blog-6800934446457898793.post-89172364499499816952009-02-03T12:15:00.000-05:002009-02-03T12:15:10.083-05:00Rebooting Computing: Why?<p>Have you seen “<a title="See 01:25 of this video for a further explanation" href="http://www.youtube.com/watch?v=yOOJzQRJfIw">The Most Famous Chart in Computer Science Education</a>?” The exact numbers and data sources vary, but the curve always looks similar:<br /></p><p><a href="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SYGwFPoQRCI/AAAAAAAABJA/hUkKSJpFjb8/s1600-h/CollegeBoundSeniorEnrollmentsInComputingFromSAT.png"><img src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SYGwFPoQRCI/AAAAAAAABJA/hUkKSJpFjb8/s400/CollegeBoundSeniorEnrollmentsInComputingFromSAT.png" /></a> </p>I <a href="http://www.cra.org/CRN/issues/0801.pdf">used</a> <a href="http://professionals.collegeboard.com/profdownload/Total_Group_Report.pdf">data</a> from college bound seniors who indicated on their <a href="http://en.wikipedia.org/wiki/SAT">SAT</a> that they intended to major in “Computer and Information Sciences and Support Services.” The curve tends peak between 1999 and 2001 and then you see a huge decline that has just begun to bottom out to numbers less than <i>half</i> their peak value.<br /><p>Some people like to <a href="http://www.youtube.com/watch?v=yOOJzQRJfIw">explain away</a> this drop on another curve:</p><a title="Data from Yahoo! Finance on the NASDAQ index from 1997 - 2009" href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SYGwOsSAlII/AAAAAAAABJI/IWqVBQINmto/s1600-h/NASDAQ19972009.png"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SYGwOsSAlII/AAAAAAAABJI/IWqVBQINmto/s400/NASDAQ19972009.png" /></a><p> </p>Although there was a correlation of computer science enrollment and the stock market, you'll see that the curves diverge around 2003. A popular belief is that the bursting <a href="http://en.wikipedia.org/wiki/Dot-com_bubble">dot-com bubble</a> scared some potential students, but then by 2003 parents thought <a href="http://www.cato.org/pub_display.php?pub_id=2692">most software jobs were being offshored</a> and encouraged their kids to pick a different field.<br /><p>Some jobs <i>did</i> go to <a href="http://en.wikipedia.org/wiki/Bangalore">Bangalore</a>, but the total number of jobs <a href="http://www.acm.org/globalizationreport/">actually</a> <a href="http://www.bls.gov/news.release/ecopro.t06.htm">grew</a> in the US, even beyond their 1999 levels. There are still <a href="http://www.bls.gov/oco/ocos267.htm#outlook">excellent job</a> <a href="http://www.cra.org/govaffairs/sargent_adequacy_of_S-EW.ppt">prospects</a> for the long term. Even in hard times like the 1970's recession, companies like Apple and Microsoft <a href="http://www.paulgraham.com/badeconomy.html">were founded</a>. In 10 years, we'll know of a several great companies that got their start in the <a href="http://en.wikipedia.org/wiki/Global_financial_crisis_of_2008">current financial crisis</a>. It's unfortunate how students and their parents have been misled about the reality.<br /></p><p>We're faced with a pipeline problem. The fresh-outs you'll be looking to hire in 10 years are in middle school right now. Are you doing anything to woo them to a career in computing? What do you say to a bright young girl to at least <i>consider</i> looking at computer science?<br /></p><p>I could start with my story. As a kid, I was captivated by how I could think of an idea for a program and then have a computer execute it exactly. It was as if I could put part of my mind inside the computer. My parents and friends thought this was magic. It <i>was</i> magic, but it was a magic I could understand. There's always cool new things being computed. It was magical to see how <a href="http://en.wikipedia.org/wiki/IBM_Deep_Blue#Deep_Blue_versus_Kasparov">Deep Blue beat Kasparov</a> long before I began to understand the beauty of <a href="http://www.computerhistory.org/chess/main.php?sec=thm-42f15cec6680f">how it worked</a>. Every day I listen to <a href="http://en.wikipedia.org/wiki/MP3">MP3</a>s that were created by a compression algorithm that gets rid of sound that my ear can't hear. Companies like Walmart sift terabytes of data to predict market demand so they can send extra <a href="http://www.nytimes.com/2004/11/14/business/yourmoney/14wal.html">strawberry Pop-Tarts</a> when hurricanes are approaching. On a personal level, new algorithms predict with a high accuracy what types of <a href="http://en.wikipedia.org/wiki/Netflix_Prize">movies we'll like</a>. But that's just one tiny sliver of what's out there. Each person can have their own unique experience. There's a lot of great computing going on and the demand is only increasing.<br /></p><p>Sometimes you'll hear honest hesitations about a career in computing because of fears that they'll “sit in front of a computer all day.” The sad irony is that this thinking causes people to go into fields like accounting, graphic design, marketing, or hundreds of other fields where they spend just as much time in front of a computer. The difference is that they'll spend most of their time using applications like Outlook, Word, or Excel and often have less fun than the software developers that are creating these programs. Moreover, working in the computing fields will give someone a chance to create future interfaces that don't have everyone in front of giant screens all day.<br /></p><p>This isn't to say that there aren't boring software development jobs, but there are also plenty of great jobs. <a href="http://www.codinghorror.com/blog/archives/001202.html">It's a great career</a>. I sometime feel a little guilty that I can work in a field that I enjoy. As a field, we create software that powers <a href="http://www.inin.com/">business communications</a> and <a href="http://www.facebook.com/">connects you with friends</a>. Software will be a pivotal role in <a href="http://www.pacificbiosciences.com/index.php">gene sequencing and analyzing</a> that will usher in customized medical treatments and drugs. Software will drive many great innovations of the future.</p>It's sad that kids aren't even given a chance to see the breadth and excitement of our field. I don't blame them. On the whole, we're doing a terrible job broadcasting our image.<br /><p>Professors often teach computer science as if it is some sterile thing with nothing new in it. This is just not true; we're in our adolescence. Sure, we bumble around and do silly things at times, but it also means we're <i>growing</i>. We're in an incredible time. <a href="http://robotics.stanford.edu/%7Esahami/bio.html">Mehran Sahami</a> captured this well at the <a href="http://www.youtube.com/watch?v=nWRGPxSNnag">conclusion of his intro class at Stanford</a>:<br /> </p><blockquote><p>“Think about the time that you're living in. <a href="http://en.wikipedia.org/wiki/Donald_Knuth">Don Knuth</a>, who is considered the father of Computer Science is still alive and he's in this department. It's <i>sort of like you're geometers and you're living in the time of <a href="http://en.wikipedia.org/wiki/Euclid">Euclid</a></i>... It's all happening now. Don't think of this stuff as dead people who did this stuff and it just happened and now you're forced to do it. You're living in it.”<br /></p></blockquote><p>Mehran is one of the few teachers that do a great job of <a href="http://academicearth.org/lectures/life-after-programming-methodology">sharing</a> the new and exciting possibilities of computer science. Too often you see teachers that claim that computer science is some small box that is exactly what they're teaching.<br /></p><p>When I've had the honor of having conversations with computing pioneers <a href="http://www.codinghorror.com/blog/archives/001213.html">like Alan Kay</a>, I often hear how their teachers in the 60's would admit that they didn't understand the full possibilities of computing, and they wanted their students do better. The early <a href="http://en.wikipedia.org/wiki/Defense_Advanced_Research_Projects_Agency">ARPA</a> community with <a href="http://www.moserware.com/2008/05/who-is-this-licklider-guy.html">J.C.R. Licklider</a> at the helm is a great example of this style.<br /></p><p>Licklider encouraged <i>and funded</i> wild and imaginative ideas that caused a huge boom in computer science back in the 60's and early 70's. Unfortunately, this slowed down in the 1980s as funders became more conservative, took fewer risks, and as a result got more incremental improvements rather than something big. I think this is why Alan Kay has difficulty <a href="http://stackoverflow.com/questions/432922/significant-new-inventions-in-computing-since-1980">finding significant new inventions in computing since 1980</a>. Alan's statement sounds crazy until you see just how much of what we use was started before 1980. <a href="http://stackoverflow.com/questions/432922/significant-new-inventions-in-computing-since-1980#433063">Some</a> will point to the web and the browser as a huge new invention, but even <a href="http://en.wikipedia.org/wiki/Marc_Andreessen">Marc Andreessen</a>, <a title="Fastforward to 22:30, and you'll hear Judy quote this." href="http://www.npr.org/templates/story/story.php?storyId=96089391">speaking</a> on how he was able to create the first graphical web browser <a title="Fast forward to 22:30, and you'll hear Judy quote this." href="http://www.npr.org/templates/story/story.php?storyId=96089391">revealed</a>:<br /> </p><blockquote><p>“I was able to do it so quickly because it was the <i>icing on the cake that had been baking for 30 years</i>.”<br /></p></blockquote><p>Indeed he had. In the mid-60's, some of the baking started when Licklider funded <a href="http://en.wikipedia.org/wiki/Douglas_Engelbart">Doug Englebart'</a>s amazing <a href="http://en.wikipedia.org/wiki/On-Line_System">oN-Line System</a> that <a href="http://video.google.com/videoplay?docid=-8734787622017763097">amazingly</a> had hypertext links and was operated by a mouse. <a href="http://en.wikipedia.org/wiki/Leonard_Kleinrock">Len Kleinrock</a>'s Ph.D. proposal on packet theory in 1961 gave him a great start that ultimately led to his team sending the first message over ARPAnet in <a href="http://www.docstoc.com/docs/2187564/Microsoft-PowerPoint---Len-Kleinrocks-Brief-History-of-the">1969</a>. <a href="http://en.wikipedia.org/wiki/Vint_Cerf">Vint Cerf</a> and <a href="http://en.wikipedia.org/wiki/Bob_Kahn">Bob Kahn</a> had already <a href="http://www.cs.princeton.edu/courses/archive/fall06/cos561/papers/cerf74.pdf">published</a> a paper on <a href="http://en.wikipedia.org/wiki/Internet_protocol_suite">TCP/IP</a>, the bedrock of the Internet protocols, by 1974. All of these technologies were well refined and in production by the time <a href="http://en.wikipedia.org/wiki/Tim_Berners-Lee">Tim Berners-Lee</a> created HTTP in the early 90's to which Andreessen would add a graphical front end. </p>Are we willing to fund long-term “wild” and “crazy” ideas <i>today</i> to create Internet-sized future results? We've been too focused on short term results. It's not just academia; most companies focus on short-terms results that dismiss the fact that computing is a young field and miss what really matters:<br /> <blockquote><p>“Many HR departments haven't figured this out yet, but in reality, It's less important to know Java, Ruby, .NET, or the iPhone SDK. There's always going to be a new technology or a new version of an existing technology to be learned. <strong>The technology itself isn't as important; it's the constant learning that counts</strong>.” - <a href="http://www.amazon.com/gp/product/1934356050?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356050"><i>Pragmatic Thinking and Learning</i></a><i>, </i>p.145<br /></p></blockquote><p><b>Bummer, Now What?</b><br /></p><p>Last March, I was given the opportunity to be on <a href="http://rebootingcomputing.com/teams/about.html">a design team</a> to start tackling some of these <a href="http://rebootingcomputing.org/manifesto.html">problems</a>. We knew that we couldn't change the whole field and that some people would want to keep it the way it is. But we also knew that we had to do something; we didn't want to settle for the status quo.<br /></p><p>Our primary task was to plan a “summit” of the best people from academia, government, and industry and get them all in one room so that we could get a good sample of the entire field. We didn't want to let people have the chance to point fingers outside and say it was somebody else's problem. </p>After working on the basic concept for the summit, we needed to give it a name. I had enjoyed many side discussions of the great days of Licklider, <a href="http://en.wikipedia.org/wiki/Xerox_PARC">PARC</a>, and the early culture that accomplished great things. Sort of as a joke, I thought that we needed to “reboot” computer science to get rid of the cruft that had accumulated over time and get back to the excitement when the field was brand new. After some discussion, we decided to change “computer science” to a broader field of “computing” and use the “magic and beauty” of computer science to be the driver of the “rebooting.”<br /><p><a href="http://rebootingcomputing.org/"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SYe2XdcuhPI/AAAAAAAABJg/dzhu4eT26o4/s400/rebootingcomputinglogo.png" /></a> </p>Only later would I realize the rebooting metaphor could be stretched a bit further. We can “reboot” the field without throwing away the good parts just as an operating system can reboot and depend on its valuable <a href="http://en.wikipedia.org/wiki/Non-volatile_memory">non-volatile</a> memory being preserved. Rebooting doesn't mean that we'll go down the same crufty path (e.g. perhaps we have better “drivers” now). Most importantly, the <a href="http://rebootingcomputing.org/">domain name</a> was available so we ran with it.<br /><p>After nine months of planning and inviting over 220 people, we had our summit in January at the <a href="http://www.computerhistory.org/">Computer History Museum</a>. It was the first time that such a broad representation of the computing field came to work together in the same room.<br /></p><p>The summit was guided by the <a href="http://appreciativeinquiry.case.edu/">Appreciative Inquiry</a> process. It's a technique that has you work in small teams to discover a positive core of what's giving the field life and then uses that to start dreaming of a better future. As the three days unraveled, we made it to the “design” phase where we kicked off several projects that fell into three rough categories:<br /> </p><ul><li>Education<br /> <ul><li>K-8 Fundamentals (Creating engaging introductions of computing fundamentals at the elementary level)<br /> </li><li>Project/Problem Based Learning for Grades 7-14<br /> </li><li>CS in K-12: Essential Subject (Determining a path to get computing essentials introduced in the K-12 curriculum)<br /> </li><li>Recruiting CS Teachers (Significantly increase the number of computer science teachers)<br /> </li><li>National Curriculum for Multi-Disciplinary Collaboration<br /> </li><li>International Educational Repository (that would include classroom activities and ideas for the K-16 level)<br /> </li></ul></li><li>Outreach<br /> <ul><li><a href="http://www.labrats.org/">LabRats</a> (Build learning communities that include after school activities focused on areas like computer science)<br /> </li><li>Recruiting Women &amp; Minorities into CS<br /> </li><li><a href="http://www.imageofcomputing.com/">Image of Computing</a> (Sort of like a marketing campaign to show how computing is changing the world)<br /> </li><li>Tools for Fun and Beauty (Providing software tools for people sharing the fun and beauty of computing)<br /> </li><li>Relevant Computer Science Intersecting with Socially Relevant Projects (e.g. providing infrastructure in third world countries or disaster response scenarios)<br /> </li><li>Defining Future Computing Requirements for IT Service Verticals (e.g. Health Care, Financial, Government)<br /> </li></ul></li><li>Internal Growth<br /> </li><ul><li>Parallel Worlds Initiative (Leverage the boom in <a href="http://en.wikipedia.org/wiki/Multi-core">multi-core</a> to drive new areas of thinking in computing)<br /> </li><li>Open Artifacts (e.g. create hardware and software systems that can easily be inspected, understood, assembled, disassembled and reused in new ways to allow for exploration)<br /> </li><li>Rediscovering Computing “Gems” (Revisit ideas from the past that might have been previously abandoned because they were infeasible but now might be possible)<br /> </li><li>Computing Field Guide (Create a resource to show the breadth of computing to both novices and experts)<br /></li></ul></ul><p>I joined the Computing Field Guide team. I think it'll be fun to see if we can come up with a way to leverage many of the great existing resources out there and learn some of the breadth of the field as a result.<br /></p><p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SYGxSghf_wI/AAAAAAAABJY/zpQBVqxeeaE/s1600-h/RebootingGroup.jpg"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SYGxSghf_wI/AAAAAAAABJY/zpQBVqxeeaE/s400/RebootingGroup.jpg" /></a> </p>In the end, the three day summit was just the beginning of a long journey. It was a bit chaotic and some were disappointed we didn't fix everything right then or do more, but I think the summit gave a good context for the issues our field faces. My best memories include all of the great people that I met and being able to engage in some great conversations.<br /><p>Steve Jobs said “<a title="See 4:45" href="http://www.youtube.com/watch?v=D1R-jKKp3NA">you can't connect the dots looking forward; you can only connect them looking backwards</a>.” I think that holds true for this summit. There are still a lot of dots between here and <i>there</i>; wherever “there” might be. With a lot of hard work, I'm confident that the dots will connect somehow. There's an interesting road ahead and I want to be a part of it. We need to start baking cakes for future generations to ice.<br /></p><p><strong>Your Turn</strong></p>What do you think of the current state of computer science? What is your dream for the future? What are some things that we can start now to improve the current situation? Are you involved with any existing effort? Would you like to join ours?<br /><p>I'd love to hear your thoughts.</p>P.S. There are several blog posts by fellow “Rebooters” ([<a href="http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2009-01.html#e2009-01-17T15_09_23.htm">1</a>] [<a href="http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2009-01.html#e2009-01-19T09_53_10.htm">2</a>] [<a href="http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2009-01.html#e2009-01-20T16_27_09.htm">3</a>] [<a href="http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2009-01.html#e2009-01-21T07_55_01.htm">4</a>] [<a href="http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2009-01.html#e2009-01-22T16_05_19.htm">5</a>] [<a href="http://www.sdtimes.com/link/33201">6</a>] [<a href="http://www.sdtimes.com/ZEICHICK_S_TAKE_REBOOTING_COMPUTER_SCIENCE_PART_2/33214">7</a>] [<a href="http://geek-knitter.blogspot.com/2009/01/rebooting-computing.html">8</a>] [<a href="http://techher.blogspot.com/2009/01/reboot-computing-2009.html">9</a>]). There are some <a href="http://www.flickr.com/photos/cglusky/sets/72157612501297914/detail/">pictures on flickr</a> and a <a href="http://www.rebootingcomputing.org/community/">Rebooting Computing Community site</a> that's starting to have follow-on discussion and might eventually have videos of highlights from the summit. In addition, you might watch <a href="http://www.youtube.com/watch?v=5a_pO3NYJl0">this great talk</a> by Dr. Peter Denning who has been leading this effort for over five years.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-8917236449949981695?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com18tag:blogger.com,1999:blog-6800934446457898793.post-8283981899768697172009-01-02T12:15:00.001-05:002009-01-02T16:08:43.683-05:00Wetware Refactorings<p>Brain rot.<a href="http://en.wikipedia.org/wiki/File:NIA_human_brain_drawing.jpg"><img style="MARGIN: 0px 0px 10px 10px" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SVraXD0RkoI/AAAAAAAABGc/yNgs3KJzpzA/s200/NIA_human_brain_drawing.jpg" align="right" /></a> </p><p>While others were enjoying the final months of their college <a href="http://en.wikipedia.org/wiki/Senioritis">senioritis</a>, I was worried about brain rot. It hit me that in order to be bad or at best mediocre at something, all I had to do was... <em>nothing</em>. From a boring job to a bad marriage, it seemed that the secret to mediocrity was to coast along and not make any adjustments or actively work to make things better. Towards graduation, I knew that I had the option of going into the workplace and just let things happen, stop actively learning, and let my brain rot. It'd take awhile for people to realize that I'd stopped caring about learning. But by then, I'd be locked into a job where it didn't matter.</p><p>The alternative was to force myself to keep learning and accept the fact that <a href="http://www.moserware.com/2008/03/what-does-it-take-to-become-grandmaster.html">it would never be easy</a>. Fearful of brain rot, I decided to pick this second path. But I was on my own. Unlike school, there wouldn't be anyone forcing me to learn new things. Even with this decision, there was a slight feeling I was part of a losing game.</p><p>Throughout my school years, the consistent message about the brain was that you were given a limited number of brain cells at birth and you had to do your best to keep all the ones you could. At best, you could hope to somehow mature the ones that remained. Popular culture promoted this message and sometimes joked about it, such as <a href="http://en.wikipedia.org/wiki/Cliff_Clavin">Cliff</a>'s "Buffalo Theory" on <a href="http://en.wikipedia.org/wiki/Cheers">Cheers</a>:</p><blockquote><p>"Well you see, <a href="http://en.wikipedia.org/wiki/Norm_Peterson">Norm</a>, it's like this... A herd of buffalo can only move as fast as the slowest buffalo and when the herd is hunted, it is the slowest and weakest ones at the back that are killed first. This natural selection is good for the herd as a whole, because the general speed and health of the whole group keeps improving by the regular killing of the weakest members. In much the same way, the human brain can only operate as fast as the slowest brain cells. Now, as we know, excessive drinking of alcohol kills brain cells. But naturally, it attacks the slowest and weakest brain cells first. In this way, regular consumption of beer eliminates the weaker brain cells, making the brain a faster and more efficient machine. And that, Norm, is why you always feel smarter after a few beers."</p></blockquote><p>I kept this depressing view of brain cell scarcity until I learned about <a href="http://en.wikipedia.org/wiki/Neurogenesis">neurogenesis</a>:</p><blockquote><p>Fortunately, professor <a href="http://weblamp.princeton.edu/~psych/psychology/research/gould/index.php">Elizabeth Gould</a> thought otherwise. In a discovery that turned the field on its ear, she discovered neurogenesis -- the continued birth of new brain cells throughout adulthood. But here's the funny part. The reason researchers had never witnessed neurogenesis previously was because of the environment of their test subjects. </p><p>If you're a lab animal stuck in a cage, you will never grow new neurons.</p><p>If you're a programmer stuck in a drab cubicle, you will never grow new neurons.</p><p>On the other hand, in a rich environment with things to learn, observe, and interact with, you will grow plenty of new neurons and new connections between them.</p><p>For decades, scientists were misled because an artificial environment (sterile lab cages) created artificial data. Once again, context is key. Your working environment needs to be rich in sensory opportunities, or else it will literally cause brain damage. <em><a href="http://pragprog.com/titles/ahptl/">Pragmatic Thinking and Learning</a></em>, p.67</p></blockquote><p><strong>Neurobics</strong><br /><br /></p><p><strong><a href="http://www.amazon.com/gp/product/0761110526?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0761110526"><img style="MARGIN: 0px 10px 10px 0px" src="http://rcm-images.amazon.com/images/I/51CERxGBQDL._SL110_.jpg" align="left" /></a></strong>While listening to <a href="http://www.wnyc.org/shows/radiolab/episodes/2007/08/14/segments/80141">a segment on Radio Lab</a>, I finally realized that the brain doesn't have one central command structure that interprets the world. It's more likely that each sensory organ feeds in its own "note" to your mind and it's the combined musical "chord" that you perceive as a thought or memory. </p><p>In an attempt to take advantage of this discovery, I checked out the book "<a href="http://rcm.amazon.com/e/cm?t=moserware-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0761110526&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr">Keep Your Brain Alive: 83 neurobic exercises to help prevent memory loss and increase mental fitness</a>." It was a bit odd for me to read since the book is targeted at people twice my age, but it highlighted the interesting concept of "neurobics" which are like neural aerobics. The book explains how neurobics take advantage of the decentralized nature of your brain:</p><ol><ol><ol><li><strong>Involve one or more of your senses in a novel context.</strong> By blunting the sense you normally use, force yourself to rely on other senses to do an ordinary task. For instance: Get dressed for work with your eyes closed. </li><li><strong>Engage your attention </strong>To stand out from the background of everyday events and make your brain go into alert mode, an activity has to be unusual, fun, surprising, engage your emotions, or have meaning for you. (e.g. turn the pictures on your desk upside down)</li><li><strong>Break a routine activity in an unexpected, nontrivial way</strong>. Novelty just for its own sake is not highly neurobic. Routine breakers include taking a completely new route to work and shopping at a farmers market instead of a supermarket.<br />- <em><a href="http://rcm.amazon.com/e/cm?t=moserware-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0761110526&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr">Keep Your Brain Alive</a></em>, pp.33-34 </li></ol></ol></ol><p>Some of my favorite suggestions from the book include: <a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SVrYLNwwo0I/AAAAAAAABGM/obF7EWCe6fY/s1600-h/Office+Chess+Board.JPG"><img style="MARGIN: 0px 0px 0px 10px" alt="My desk with the chessboard" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SVrYLNwwo0I/AAAAAAAABGM/obF7EWCe6fY/s320/Office+Chess+Board.JPG" align="right" /></a></p><ul><li>Shower with your eyes closed. (p.43) </li><li>Brushing roulette: brush your teeth with your nondominant hand. (p.44) This also works for other routine activities like using your mouse.</li><li>The sightless start: enter and get ready to start your car with your eyes closed. (p.55)</li><li>Take brain breaks: a walk or social lunch break can help invigorate the mind. (p.81)</li><li>Have an ongoing chess game.</li><br /></ul><p>The last was the most interesting, and had me involve coworkers:</p><blockquote><p>We know of one office where a chessboard was left out near the water cooler. Any employee could come to the board (preferably during a break), assess the situation, and make a move. It was an ongoing game, with no known players, and no winners or losers. </p><p>Even a novice chess player will weigh dozens of possible moves, attempt to visualize the consequences of each one, then select the move that offers some strategic advantage. This type of "Random-player" chess game doesn't allow anyone to develop a long-term strategy. But it does require visual-spatial thinking that is different from what most of us do at work. The brief gear switching provides a break from verbal, left-brain activities and lets the "working brain" take a breather. - <em><a href="http://rcm.amazon.com/e/cm?t=moserware-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0761110526&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr">Keep Your Brain Alive</a>,</em> p.83</p></blockquote><p>In my case, the chess game didn't work out <em>exactly</em> like the book described, but it has been fun. I set up a small magnetic chess board on my desk and encouraged anyone to come and make a move. I thought it'd be interesting to have clear winner and loser. This posed a challenge of how to keep track of the game that had no time limit or fixed set of players. I used a business card to track of whose turn it is. When the side with the printing on it is turned up, it means that it's black's turn; otherwise it's white's turn. This "protocol" has worked out well and has allowed several coworkers to play throughout the day. As a side benefit, it's caused me to <a title="After debating between getting Fritz and Chessmaster, I went with Chessmaster since it has such a good training component to it." href="http://www.amazon.com/gp/product/B001EYUR0Y?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001EYUR0Y">actively work at</a> getting better at chess. </p><p><strong>Refactoring Your Wetware</strong><br /></p><p><a href="http://www.amazon.com/gp/product/1934356050?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356050"><img style="MARGIN: 0px 10px 10px 0px" src="http://rcm-images.amazon.com/images/I/51xArZnegaL._SL110_.jpg" align="left" /></a> Last week, I read through Andy Hunt's excellent "<a href="http://www.amazon.com/gp/product/1934356050?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356050">Pragmatic Thinking &amp; Learning: Refactor Your Wetware</a>" that has many more pragmatic brain tips that are written from a programmer perspective. The book is centered around the <a href="http://blog.bruceabernethy.com/post/The-Dreyfus-Model-of-Skills-Acquisition.aspx">Dreyfus Model</a> of skill acquisition where learning starts at a beginner stage where you need a lot of rules to function and then transitions all the way up to an expert level where you rely heavily on intuition. Here are just a few of the many ideas presented in the book:</p><ul><ul><li><p>Add sensory experience to engage more of your brain: continuing on the neurobics theme, Andy Hunt has some interesting ideas (pp.74-75): </p></li><ul><li>Instead of UML diagrams, try toy blocks or Lego bricks. </li><li>Use physical <a href="http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card">CRC cards</a> to engage your touch and spatial senses.</li><li>Draw a picture ("not UML or an official diagram; just a <em>picture</em>")</li><li>Describe your design verbally. </li><li>Act out your software design with coworkers.<br /></li></ul><li>Create a "Pragmatic Investment Plan" where you treat your skills and what you want to learn with at least as much care as you take with your finances and apply similar skills (e.g. diversify, have short and long term goals). Make sure your goals are Specific, Measurable, Achievable, Relevant, and Time-Boxed (<a href="http://en.wikipedia.org/wiki/SMART_(project_management)">SMART</a>) (pp.154-156)</li><li>Consider starting a reading group with people in the office to help learn a skill from a book. (p.164) </li><li>Make sure you have freedom to explore ideas by having a "starter kit" infrastructure of version control, unit testing, and build automation. This gives you the safety to fail, which is often needed when learning. (p.192) </li><li>Unscaffolding: artificially make things harder than they need to be so that when you have to do it for real, it seems a lot easier (e.g. train for running by tying weights to your ankles). I like how the author claims that this is why Ruby programmers should at least spend some time working in C++ (p.206) </li><li>Develop Your Exocortex: Have a place outside your brain where you can store and organize thoughts. The author recommends a personal wiki. I personally prefer to use <a href="http://www.google.com/notebook/">Google Notebook</a>. (p.221) </li></ul></ul><p><strong>Be the Query</strong></p><p>I enjoyed the discussion in the book on changing your perspective, especially when it comes to feeling like you're inside the system you're creating:</p><blockquote><p>Imagine yourself as an integral component of the problem you're working on: suppose you <em>are</em> the database query or the packet on the network. When you get tired of waiting in line, what will you do? Who would you tell? - (p.107)</p></blockquote><p>I think that this approach can help lead to a richer <a href="http://www.amazon.com/gp/product/0735619654?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0735619654">Object Thinking</a> in software designs. For example, if you can picture yourself as a database query, I think you'll have much more empathy for what's going on. This thinking might influence your design to avoid painful <a href="http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/rzajq/dsscan.htm">table scans</a> and favor indexes. </p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SVrp5eSUgZI/AAAAAAAABGs/3nnK-vYwlqY/s1600-h/Oblique+Strategies+and+Cube.JPG"><img alt="My oblique strategies coffee cup and my Rubik's cube that I like to play with." src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SVrp5eSUgZI/AAAAAAAABGs/3nnK-vYwlqY/s200/Oblique+Strategies+and+Cube.JPG" align="right" /></a></p><p>Another way to change your perspective is to use <a href="http://www.rtqe.net/ObliqueStrategies/">oblique strategies</a>:</p><blockquote><p>These questions and statements force you to draw analogies and to think more deeply about the problem. They are a great resource to draw on when you' get stuck. - (p.108)</p></blockquote><p>Some example strategies include:</p><ul><li>Use fewer notes</li><li>Don't be afraid of things because they're easy to do.</li><li>What wouldn't you do?</li></ul><p>I printed <a href="http://www.stretta.com/~matthew/resources/oblique/index.html">a bunch of cards</a> with each strategy on them and keep them by my desk in a coffee mug. It's a new addition, so I don't have long term results, but it is fun to take one out and think of how it might relate to a problem I'm working on when I get stuck.</p><p><strong>Keep Your Brain Cache Warm</strong></p><p>Many brain changing ideas require you to focus. This is hard to do when our jobs often require us to multitask or our culture encourages us to check email frequently in order to respond quickly and look good among our peers. There are dangers to this:</p><blockquote><p>Scientists agree that trying to focus on several things at once means you'll do poorly at each of them.</p><p>And if that wasn't bad enough, a controversial study done in the United Kingdom noted that if you constantly interrupt your task to check email or respond to an IM text message, your effective IQ drops ten points.</p><p>By comparison, smoking a marijuana joint drops your IQ a mere four points. - <em><em><a href="http://www.amazon.com/gp/product/1934356050?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356050">Pragmatic Thinking and Learning</a></em>, </em>p.228</p></blockquote><p>This is really hard to overcome. Since reading this, I've tried to avoid checking Outlook more than once an hour. After each check, I shut it down to prevent the distraction. I've found that it's helpful to actually shut it down; otherwise it's too tempting to ALT+TAB to it or get lured in by a notification message.</p><p>If you replace "phone" with "email", you can see that <em><a href="http://www.amazon.com/gp/product/0932633439?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0932633439">Peopleware</a></em> described over two decades ago why most people are working far below their potential of being in a state of "flow" where you actually get stuff done:</p><blockquote><p>If the average incoming [email] takes five minutes and your reimmersion period is fifteen minutes, the total cost of that [email] in flow time (work time) lost is twenty minutes. A dozen [emails] use up half a day. A dozen other interruptions and the rest of the work day is gone. This is what guarantees, "You never get anything done around here between 9 and 5." - <a href="http://www.amazon.com/gp/product/0932633439?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0932633439"><em>Peopleware 2nd edition</em></a>, p.63</p></blockquote><p>Therefore, for the sake of your sanity and focus, be careful before flushing your brain cache by doing a context switch. The time saved can be used for more creative thinking and getting things done. </p><p><strong>Is this All a Bunch of Hooey?</strong></p><p>I admit that some of these ideas sound silly. I haven't yet worked up the courage to bring Legos to a design meeting yet, but I can see how it would help use a different neural pathway and activate more gray matter. Surely that couldn't hurt, right? It'd probably bring a new perspective and overcome a road block. This is probably why some of the most creative companies <a href="http://www.ted.com/index.php/talks/tim_brown_on_creativity_and_play.html">encourage playful behavior at work</a>. This might be seen as a horrible waste of time to traditional management (and shareholders for that matter), but it's much more likely to use more of your brain which in turn might create better solutions.</p><p><a title="Sheep Dip plunge copyright 1951 C. Goodwin under GFDL." href="http://en.wikipedia.org/wiki/File:Sheep_dipping.jpg"><img style="MARGIN: 0px 10px 10px 0px" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SV49YupsUfI/AAAAAAAABG0/de20b3yrOS8/s200/Sheep_dipping.jpg" align="left" /></a> One alternative to all of this is to just coast along and not take thinking and learning into your own hands. Left on their own, your company is likely to put you through a <em><a href="http://en.wikipedia.org/wiki/Sheep_dip">sheep dip</a> </em>using a "training course" in an artificial environment that will easily wear off just like a farmer might dunk his sheep into a chemical bath to get rid of parasites which will also wear off and need to be repeated. </p><p>While sometimes uncomfortable at first, I've enjoyed incorporating some "wetware refactoring" into my daily life as a way to overcome brain rot and aid learning and thinking. It sure beats a sheep dip.</p><p>What do you do? Do you have specific wetware refactorings that you do? I'd love to hear them; the "crazier" they are the more likely they'll probably activate different neural pathways and probably lead to a better result. Let me know in the comments.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-828398189976869717?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com25tag:blogger.com,1999:blog-6800934446457898793.post-12145095851106469502008-12-02T08:00:00.001-05:002008-12-02T08:08:13.329-05:00The Private Life of a Public API<p>In college, I'd add "<span style="color:#0000ff;">public</span>" in front of my classes and methods without giving it much thought. Sure, I knew about "<span style="color:#0000ff;">protected</span>" and "<span style="color:#0000ff;">private</span>" and would use them where it made sense, but I had no <em>pragmatic</em> experience of designing my "<span style="color:#0000ff;">public</span>" code so that other people could easily use it.</p><p>Even a few years after graduation, I still didn't have to worry much about creating a public Application Programmer Interface (API). As it turned out, I was often the only "Programmer" that my code had to "Interface" with. </p><p>But I had a dream.</p><p>I knew that if I really wanted to get better as a programmer, I would have to write code that others could easily reuse. About two years ago, I started using <a href="http://www.red-gate.com/products/reflector/">Reflector</a> to make some serious study of the internals of the .NET Framework. It was great to be able to do deep "reflectorings" on a real framework that is used by millions of people and see its good parts and its mistakes.</p><p><a href="http://www.amazon.com/gp/product/0321545613?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321545613"><img style="MARGIN: 5px 10px 5px 0px" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/STNkI8hRRzI/AAAAAAAABFc/velw7gQsaCY/s200/FDG2+Cropped.jpg" align="left" /></a>My next big step was following the recommendations of several blogs and reviews by buying a copy of <a href="http://www.amazon.com/gp/product/0321545613?ie=UTF8&amp;tag=moserware-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321545613">Framework Design Guidelines</a> by <a href="http://blogs.msdn.com/kcwalina/">Krzysztof Cwalina</a> and <a href="http://blogs.msdn.com/brada/">Brad Abrams</a>. It's full of practical advice that explicitly points out how the .NET framework itself was <em>intentionally</em> designed. I found the book to be helpful enough that I really wanted to be a reviewer of the second edition. I didn't make the cut, but the publisher was kind and sent me a copy of it. I spent the past few days reading the new edition searching for updates. In the process, I also reflected on the older, but still relevant, guidelines from the first edition. </p><p>One of my favorite parts of the book is that it is full of annotations from the people in the trenches that actually designed the framework. For example:</p><blockquote><p>"If you say what your library does and ask a developer to write a program against what he or she expects such a library to look like (without actually looking at your library), does the developer come up with something substantially similar to what you've produced? Do this with a few developers. If the majority of them write similar things without matching what you've produced, <em><strong>they're right, you're wrong, and your library should be updated appropriately</strong></em>." - <a href="http://www.sellsbrothers.com/">Chris Sells</a>, p.3</p></blockquote><p>The book continues with many details of the work that goes into creating a public API and it helps shed some light an API beyond its short <a href="http://en.wikipedia.org/wiki/IntelliSense">IntellSense</a> description.</p><p><strong>It's FileName, not Filename. Ok?</strong></p><p>The design guidelines don't hide their goal:</p><blockquote><p>"Consistency is the key characteristic of a well-designed framework... Consistency is probably the main theme of this book. Almost every single guideline is partially motivated by consistency..." - p.6</p></blockquote><p><img style="MARGIN: 10px 0px 10px 10px" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/STMhoIX7TzI/AAAAAAAABFE/f6FMeCV3NRc/s320/opendialog.png" align="right" /> The problem with consistency is dealing with all the micro decisions that we have to make when we're programming. When writing a file open dialog class, how do you get the name of the file the user selects? You have at least 3 choices:</p><ol><li>dialog.getFilename() </li><li>dialog.get_file_name() </li><li>dialog.FileName </li><br /></ol><p>There's nothing wrong with <em>any</em> of these names or styles from a general perspective. If you write Java code, option #1 is a good choice. Option #2 is reasonable for people writing C++ code that uses the STL. But on .NET, there is no choice: you need to go with #3.</p><p>Names in .NET libraries must follow <a href="http://msdn.microsoft.com/en-us/library/x2dbyw72(VS.71).aspx">a few simple rules</a>. Almost all names in .NET are "PascalCased" except for method arguments which are "<a href="http://en.wikipedia.org/wiki/CamelCase">camelCased</a>." Acronyms over two letters are treated as words (e.g. System.IO and System.Xml). There are also a few rules about compound words that I had to burn into my memory after I broke the rules too many times: </p><div align="center"><table cellspacing="0" cellpadding="2" width="400" align="center" border="1"><tbody><tr><td valign="top" width="133"><strong>Pascal</strong></td><td valign="top" width="133"><strong>Camel</strong></td><td valign="top" width="133"><strong>Not</strong></td></tr><tr><td valign="top" width="133">Canceled</td><td valign="top" width="133">canceled</td><td valign="top" width="133">Cancelled</td></tr><tr><td valign="top" width="133">FileName</td><td valign="top" width="133">fileName</td><td valign="top" width="133">Filename</td></tr><tr><td valign="top" width="133">Hashtable</td><td valign="top" width="133">hashtable</td><td valign="top" width="133">HashTable</td></tr><tr><td valign="top" width="133">Id</td><td valign="top" width="133">id</td><td valign="top" width="133">ID</td></tr><tr><td valign="top" width="133">Ok</td><td valign="top" width="133">ok</td><td valign="top" width="133">OK</td></tr><tr><td valign="top" width="133">UserName</td><td valign="top" width="133">userName</td><td valign="top" width="133">Username</td></tr></tbody></table></div><br /><div align="center">(Subset of table from p.43)</div><p>The book hints at the naming process:</p><blockquote><p>"In the initial design of the Framework, we had hundreds of hours of debate about the naming style. To facilitate these debates we coined a number of terms. With Anders Hejlsberg, the original designer of Turbo Pascal, and key member of the design team, it is no wonder that we chose the term PascalCasing for the casing style popularized by the Pascal programming language." - Brad Abrams, p.38</p></blockquote><p>Ultimately, it doesn't matter how the name styles were chosen. The decision has been made. I once thought it didn't matter about these tiny details, but it really adds up over thousands of methods. Name things however you want on <a href="http://www.softiesonrails.com/2007/10/18/ruby-101-naming-conventions">other</a> <a href="http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html">platforms</a>: use underscores, SCREAMING_CAPS, whatever, just not in .NET.</p><p><strong>Hurling Programmers into a Pit of Success</strong></p><p>It's sometimes humbling when you see people use an API that you worked hard on. Imagine that you've spent a week creating a class that hides all the database goo involved in getting employee information and puts it into an array. Then, to your horror, you see someone write this:</p><pre><span style="COLOR: rgb(43,145,175)">Company</span> company = GetCompany(companyName);<br /><span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = 0; i &lt; company.Employees.Length; i++)<br />{<br /> <span style="COLOR: rgb(43,145,175)">Paycheck</span> paycheck = CreatePaycheck(company.Employees[i]);<br /> SendPaycheck(paycheck);<br />}</pre><p>Since you decided to expose things as a mutable array, you have to make a copy before returning it. The poor guy writing this simple code is going to have terrible performance because your code made it look like getting the employees array was "cheap." His code is doomed to 2n copies of the employee array because of your decision. The guidelines give guidance on how to avoid this problem: return a read-only collection or rename the property to a "GetEmployees" method so that programmers know the task isn't "cheap."</p><p>In addition to thinking about performance, you also have to keep in mind the context in which your code will be called. I've seen too many modern APIs that were designed by people who either didn't think about or care about their users. Methods that have boolean parameters are usually suspect. Methods with multiple boolean parameters are downright terrible. </p><p>Compare:</p><pre><span style="COLOR: rgb(43,145,175)">Stream</span> stream = <span style="COLOR: rgb(43,145,175)">File</span>.Open(<span class="str">"file.txt"</span>, <span style="color:#0000ff;">true</span>, <span style="color:#0000ff;">false</span>);</pre><p>with</p><pre><span style="COLOR: rgb(43,145,175)">Stream</span> stream = <span style="COLOR: rgb(43,145,175)">File</span>.Open(<span class="str">"file.txt"</span>, <span style="COLOR: rgb(43,145,175)">FileMode</span>.Open, <span style="COLOR: rgb(43,145,175)">FileAccess</span>.Read);</pre><p>Can you tell what the first one does? What about the second? </p><p>When I first read the "Member Design" chapter two years ago, I vowed I would never subject users to out-of-context boolean parameters again. A benefit of this has been that I'm able to read my old code months or years later and still understand what it does when I otherwise would have long forgotten the boolean parameters of a function. </p><p>There are many other, sometimes subtle things you can do to help make users successful with your code:</p><ul><li>If you override <a href="http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx">.Equals</a> on your class, you really should override <a href="http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx">.GetHashCode</a> or your objects might do bad things when put in hashtables/dictionaries. (p.270) </li><li>If you need a specific time of day (e.g. when to unlock a door each day), use a <a href="http://msdn.microsoft.com/en-us/library/system.timespan.aspx">TimeSpan</a> rather than a <a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx">DateTime</a> with some random date or some arbitrary number. (p.263) </li><li>If you have an asynchronous method that invokes an event handler, make sure you do it on the proper thread (p.306). If you don't, you might scar a novice programmer for life with threading pains. </li><li>Don't forget that end-users need to unit-test their code that is built using your library (p.7). This might involve making key methods virtual or factoring them out to an interface that can be swapped out with a "<a href="http://en.wikipedia.org/wiki/Mock_Object">mock</a>" implementation. </li></ul><p><strong>Nobody's Perfect</strong></p><p>Even when you have the best intentions, you'll make mistakes. For example, <a href="http://msdn.microsoft.com/en-us/library/system.io.path.invalidpathchars.aspx">Path.InvalidPathChars</a> is a mistake. It's a read-only field that is an array of characters that are invalid in filenames. Although the array <em>reference</em> is read-only, the array <em>contents</em> are not. This can lead to potential security issues if users depend on this array for safety and malicious code modifies the array contents.</p><p>Microsoft <a href="http://msdn.microsoft.com/en-us/library/ms172409.aspx">now recommends</a> people use Path.<a href="http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars.aspx">GetInvalidPathChars</a>() instead which returns a <em>copy</em> of the array instead. This is sort of ironic because it violates another type member guideline:</p><blockquote><p>"DO NOT have properties that match the name of 'Get' methods" - p.69</p></blockquote><p>This isn't <em>too</em> bad since Microsoft has marked the old method as <a href="http://msdn.microsoft.com/en-us/library/system.obsoleteattribute.aspx">obsolete</a>, which gives them a chance to remove it in, <em>ten years</em> or so. In the meantime, novice users might continue to be confused as to why there are two ways for getting invalid path characters.</p><p><strong>Public APIs: 21st Century Sewer Systems</strong></p><p><a title="Photo by Eddie S on Flickr" href="http://www.flickr.com/photos/pointshoot/2223236675/"><img style="MARGIN: 0px 0px 0px 10px" src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/STPlV5lTrQI/AAAAAAAABFk/WjhvtbfbD28/s400/sewercover.jpg" align="right" /></a>I often think that public APIs are like sewer systems. They're the low-level "plumbing" that no one really cares about or notices when they're working well. In fact, being boring is a "feature:"</p><blockquote><p>"Please don't innovate in library design. Make the API to your library as boring as possible. You want the functionality to be interesting, not the API." - Chris Sells, p.5</p></blockquote><p>It's easy to look at guidance like the Framework Design Guidelines and think they're a bunch of minute details that don't really matter and that following them will turn you into a mindless drone. Maybe I'm brainwashed, but I've found that having a de-facto standard on details helps me concentrate on the bigger picture: designing the functionality that users care about.</p><p>In addition to the book, there are other good resources online:</p><ul><li>The <a href="http://blogs.msdn.com/kcwalina/archive/2008/04/09/FDGDigest.aspx">Framework Design Guidelines Digest</a></li><li><a href="http://channel9.msdn.com/pdc2008/PC58/">Framework Design Guidelines session from PDC 2008</a> </li><li><a href="http://blogs.msdn.com/fxcop/archive/2008/08/19/fxcop-1-36-released.aspx">FxCop</a> is a tool that will automatically check your code for guideline "violations." It was especially helpful in helping me fix <a href="http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html">Turkey Test</a> violations. </li></ul><p>.NET is just one framework out there. There are great lessons from other platforms as well. Google's Chief Java Architect, <a href="http://en.wikipedia.org/wiki/Joshua_Bloch">Josh Bloch</a>, has some <a href="http://www.infoq.com/presentations/effective-api-design">great</a> <a href="http://www.infoq.com/articles/API-Design-Joshua-Bloch">advice</a> on developing good APIs, very little of it is specific to Java.</p><p><strong>In The End...</strong></p><p>Although it takes a lot of work to create a public API, it can be incredibly rewarding. It's exciting to hear about people you've never met before successfully using an API you've written. </p><p>Have fun, develop great code, and go <span style="color:#0000ff;">public</span> with care.</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f12%2fprivate-life-of-public-api.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f12%2fprivate-life-of-public-api.html" border="0" alt="kick it on DotNetKicks.com" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-1214509585110646950?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com5tag:blogger.com,1999:blog-6800934446457898793.post-36975542726145827242008-10-31T08:40:00.003-04:002008-10-31T13:51:35.700-04:00Boy Scout Check-ins<p>I missed the <a href="http://www.scouting.org/">Boy Scouts</a> callout when I was kid. Perhaps that's why it took me 20 years to figure out <a href="http://www.fieggen.com/shoelace/secureknot.htm">a knot</a> that keeps my shoes tied all day. My recent attempt at starting a campfire required a <a href="http://en.wikipedia.org/wiki/Propane">propane</a> torch. Despite my shortcomings, I felt a connection to the Scouts while reading this:</p><blockquote><p><a href="http://www.flickr.com/photos/greenacre8/369218941/" alt="Brightlingsea Essex Boy Scouts 1958 by greenacres8 on Flickr"><img style="border-width: 0px; margin: 0px 0px 0px 10px;" src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SQr6gJw7UeI/AAAAAAAABDc/as07uQa7vYk/s320/boyscouts.jpg" alt="boyscouts" width="244" align="right" border="0" height="156" /></a>It's not enough to write the code well. The code has to be <em>kept clean</em> over time. We've all seen code rot and degrade as time passes. So we must take an active role in preventing this degradation. </p><p>The <a href="http://en.wikipedia.org/wiki/Boy_Scouts_of_America">Boy Scouts of America</a> have a simple rule that we can apply to our profession. </p><p><em></em><a href="http://www.scouting.org/cubscouts/aboutcubscouts/history.aspx">Leave the campground cleaner than you found it.</a></p><p>If we all checked-in our code a little cleaner than when we checked it out, the code simply could not rot. The cleanup doesn't have to be something big. Change one variable name for the better, break up one function that's a little too large, eliminate one small bit of duplication, clean up one composite 'if' statement.</p><p>Can you imagine working on a project where the code <em>simply got better</em> as time passed? Do you believe that any other option is professional? Indeed, isn't continuous improvement an intrinsic part of professionalism? [<a href="http://www.amazon.com/gp/product/0132350882?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=0132350882">Clean Code</a>, p14]</p></blockquote><p>While reading this, I was reminded of another gem:</p><blockquote><p>Well-designed code <em>looks</em> obvious, but it probably took an awful lot of thought (and a lot of refactoring) to make it that simple. [<a href="http://www.amazon.com/gp/product/1593271190?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=1593271190">Code Craft</a>, p247]</p></blockquote><p>Both sound great, but they have a sort of "Don't forget to <a href="http://en.wikipedia.org/wiki/Dental_floss">floss</a>" ring to them. </p><p>We've heard for years that <a href="http://www.refactoring.com/">refactoring</a> helps improve code, but actually doing it can sometimes feel <em>too</em> daunting. It's just a fact that a lot of the code we deal with on a daily basis doesn't have enough test coverage, if there are any tests at all, to have us feel fully confident with many changes that we make to our code.</p><p>But a Scout wouldn't let the sad state of some parts of the code get him down. A Scout would always have his nose out for <a href="http://www.codinghorror.com/blog/archives/000589.html">stinky</a> <a href="http://c2.com/xp/CodeSmell.html">code</a> to clean up so that he could get a teeny bit of satisfaction knowing that he checked-in code that was better than when he checked it out.</p><p>This <a href="http://www.derickbailey.com/2008/03/11/MicroRefactoringLeaveTheCampsiteCleanerThanYouFoundIt.aspx">isn't a new idea</a>; it's just a matter of realizing how easy it is.</p><p><strong>Examples</strong></p><p>There's a lot of low-hanging fruit in a typical code base. Over months of development, the top of a C# file might look like this:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">using</span> System.Linq;<br /><span style="color: rgb(0, 0, 255);">using</span> System;<br /><span style="color: rgb(0, 0, 255);">using</span> System.Collections.Generic;<br /><span style="color: rgb(0, 0, 255);">using</span> Moserware.IO;<br /><span style="color: rgb(0, 0, 255);">using</span> System.Diagnostics;<br /><span style="color: rgb(0, 0, 255);">using</span> System.Text.RegularExpressions;<br /><span style="color: rgb(0, 0, 255);">using</span> System.Text;<span style="color: rgb(0, 0, 255);">using</span> System.Threading;</pre></blockquote><p>This is a messy way to introduce your code. With <a href="http://richardbushnell.net/index.php/2008/03/03/remove-and-sort-those-ugly-using-statements/">just a simple click</a> in Visual Studio, you can have it automatically remove clutter and sort things to get something nicer:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">using</span> System.Text.RegularExpressions;<br /><span style="color: rgb(0, 0, 255);">using</span> System.Threading;<br /><span style="color: rgb(0, 0, 255);">using</span> Moserware.IO;</pre></blockquote><p>For a three second time investment, you'll leave the file slightly better than you found it. With a <a href="http://code.msdn.microsoft.com/PowerCommands">free add-in</a>, you can do this for your <em>entire project</em> in about the same amount of time.</p><p>Different team members can often work in the same class and you'll end up with member variable declarations that identify each person's style:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> <span style="color: rgb(43, 145, 175);">CircularBuffer</span>&lt;T&gt;<br />{<br /> T[] m_array;<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">object</span> syncRoot = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(0, 0, 255);">object</span>();<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">int</span> _HeadIndex;<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">int</span> m_TailIndex;<br />...</pre></blockquote><p>This can easily be <a href="http://msdn.microsoft.com/en-us/library/ms379618.aspx#vs05_refac_topic8">made consistent in few seconds</a>:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> <span style="color: rgb(43, 145, 175);">CircularBuffer</span>&lt;T&gt;<br />{<br /> <span style="color: rgb(0, 0, 255);">private</span> T[] _Array;<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">int</span> _HeadIndex;<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">int</span> _TailIndex;<br /> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">object</span> _SyncRoot = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(0, 0, 255);">object</span>();<br />...</pre></blockquote><p>Changing a line like this:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">if</span>((i &gt;= minAmount) &amp;&amp; (i &lt;= maxAmount))</pre></blockquote><p>to use <a href="http://safari.oreilly.com/0735619670/ch19lev1sec1">number-line order</a>:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">if</span>((minAmount &lt;= i) &amp;&amp; (i &lt;= maxAmount))</pre></blockquote><p>makes the code slightly more visual and easier to read.</p><p><a href="http://www.refactoring.com/catalog/introduceExplainingVariable.html">Introducing an explaining variable</a> can turn:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(43, 145, 175);">DateTime</span> GetElectionDay(<span style="color: rgb(0, 0, 255);">int</span> year)<br />{<br /> <span style="color: rgb(43, 145, 175);">DateTime</span> startDate = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(43, 145, 175);">DateTime</span>(year, 11, 1);<br /> <span style="color: rgb(0, 128, 0);">// Get the first Tuesday following the first Monday</span><br /> <span style="color: rgb(0, 0, 255);">if</span> (startDate.DayOfWeek &lt;= DayOfWeek.Monday)<br /> {<br /> <span style="color: rgb(0, 128, 0);">// Current day of the week is before Tuesday</span><br /> <span style="color: rgb(0, 0, 255);">return</span> startDate.AddDays(DayOfWeek.Tuesday - startDate.DayOfWeek);<br /> }<br /> <span style="color: rgb(0, 0, 255);">else</span><br /> {<br /> <span style="color: rgb(0, 128, 0);">// Current day of the week is Tuesday or after</span><br /> <span style="color: rgb(0, 0, 255);">return</span> startDate.AddDays(7 - (startDate.DayOfWeek - DayOfWeek.Tuesday));<br /> }<br />}</pre></blockquote><p>into a slightly more maintainable version that doesn't need comments: </p><blockquote><pre><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(43, 145, 175);">DateTime</span> GetElectionDay(<span style="color: rgb(0, 0, 255);">int</span> year)<br />{<br /> <span style="color: rgb(43, 145, 175);">DateTime</span> nov1 = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(43, 145, 175);">DateTime</span>(year, 11, 1);<br /><br /> <span style="color: rgb(0, 0, 255);">int</span> daysUntilMonday;<br /> <span style="color: rgb(0, 0, 255);">if</span> (nov1.DayOfWeek &lt; <span><span style="color: rgb(43, 145, 175);">DayOfWeek</span></span>.Tuesday)<br /> {<br /> daysUntilMonday = <span><span style="color: rgb(43, 145, 175);">DayOfWeek</span></span>.Monday - nov1.DayOfWeek;<br /> }<br /> <span style="color: rgb(0, 0, 255);">else</span><br /> { <br /> daysUntilMonday = 6 - (nov1.DayOfWeek - <span><span style="color: rgb(43, 145, 175);">DayOfWeek</span></span>.Tuesday); <br /> }<br /><br /> <span style="color: rgb(43, 145, 175);">DateTime</span> firstMonday = nov1.AddDays(daysUntilMonday);<br /> <span style="color: rgb(0, 0, 255);">return</span> firstMonday.AddDays(1);<br />}</pre></blockquote><p>Along these lines, I tend to agree with <a href="http://steve-yegge.blogspot.com/">Steve Yegge</a>'s <a href="http://www.oreillynet.com/ruby/blog/2006/03/transformation.html">observation</a>:</p><blockquote><p>The [<a href="http://www.amazon.com/gp/product/0201485672?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=0201485672">Refactoring</a>] book next tells me: don’t comment my code. Insanity again! But once again, his explanation makes sense. I resolve to stop writing one-line comments, and to start making more descriptive function and parameter names.</p></blockquote><p>By themselves, each of these refactorings almost seems <em>too simple</em>. But each leaves your code in a slightly better place than you found it thereby qualify as a "Boy Scout Check-In."</p><p><strong>Be Careful</strong></p><p>We've probably all heard horror stories of some poor programmer who changed just "<a href="http://en.wikipedia.org/wiki/Off-by-one_error">one little character</a>" of code and caused rockets to explode or billion dollar security <a href="http://www.wired.com/software/coolapps/news/2005/11/69355?currentPage=all">bugs</a>. My advice is to not let that be you. Write more tests and use <a href="http://en.wikipedia.org/wiki/Code_review">code reviews</a> if that helps. Just don't let it be an excuse to not do <em>something</em>.</p><p>Boy Scout Check-ins should be short and measured in minutes for how long they take. Get in and out with slightly better code that fixed one small thing. Try hard not to fix a bug or add a feature while doing these small check-ins or you might face the wrath of your coworkers as Raymond Chen <a href="http://blogs.msdn.com/oldnewthing/archive/2008/10/30/9023340.aspx">points out</a>:</p><blockquote><p>Whatever your changes are, go nuts. All I ask is that you restrict them to "layout-only" check-ins. In other words, if you want to do some source code reformatting <i>and</i> change some code, please split it up into two check-ins, one that does the reformatting and the other that changes the code. </p><p>Otherwise, I end up staring at a diff of 1500 changed lines of source code, <a href="http://blogs.msdn.com/oldnewthing/archive/2008/03/27/8338530.aspx">1498 of which are just reformatting</a>, and 2 of which actually changed something. Finding those two lines is not fun. </p></blockquote><p><strong>Avoid Cycles</strong></p><p>One subtle thing to realize is that you don't want to get lost in an infinite loop with a coworker of mutually exclusive changes. This is easy since good people can disagree. For instance, compare:</p><blockquote><p><em>Use '</em>final'<strong> </strong><em>or<strong> '</strong></em>const' <em>when possible</em> By declaring a variable to be <em>final</em> in Java or <em>const</em> in C++, you can prevent the variable from being assigned a value after it's initialized. The <em>final</em> and <em>const</em> keywords are useful for defining class constants, input-only parameters, and any local variables whose values are intended to remain unchanged after initialization. [<a href="http://www.amazon.com/gp/product/0735619670?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=0735619670">Code Complete 2</a>, p243]</p></blockquote><p>and</p><blockquote><p>I also deleted all the 'final' keywords in arguments and variable declarations. As far as I could tell, they added no real value but did add to the clutter. Eliminating 'final' flies in the face of some conventional wisdom. For example, Robert Simmons strongly recommends us to "... <a href="http://books.google.com/books?id=awnmD1w4_T8C&amp;pg=PA72&amp;lpg=PA72&amp;dq=robert+simmons+%22spread+final+all+over+your+code%22&amp;source=web&amp;ots=ZuLGos4Q5j&amp;sig=MvXAFM0YMhmct2HEs895umrVy4g&amp;hl=en&amp;sa=X&amp;oi=book_result&amp;resnum=1&amp;ct=result">spread final all over your code</a>." Clearly I disagree. I think there are a few good uses for 'final', such as the occasional 'final' constant, but otherwise the keyword adds little value and creates a lot of clutter. [<a href="http://www.amazon.com/gp/product/0132350882?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=0132350882">Clean Code</a>, p276]</p></blockquote><p>Don't get bogged down with someone else on adding and removing 'final' or 'readonly'. Just be consistent.</p><p>I'm embarrassed to admit that in my earlier days, I might have "cleaned" code like this:</p><blockquote><pre><span style="color: rgb(0, 0, 255);">string</span> headerHtml = <span style="color: rgb(0, 96, 128);">"&lt;h1&gt;"</span> + headerText + <span style="color: rgb(0, 96, 128);">"&lt;/h1&gt;"</span>;</pre></blockquote><p>into </p><blockquote><pre><span style="color: rgb(0, 0, 255);">string</span> headerHtml = <span style="color: rgb(43, 145, 175);">String</span>.Concat(<span style="color: rgb(0, 96, 128);">"&lt;h1&gt;"</span>, headerText, <span style="color: rgb(0, 96, 128);">"&lt;/h1&gt;"</span>);</pre></blockquote><p>or even worse:</p><blockquote><pre><span style="color: rgb(43, 145, 175);">StringBuilder</span> sb = <span style="color: rgb(0, 0, 255);">new</span> <span style="color: rgb(43, 145, 175);">StringBuilder</span>();<br />sb.Append(<span style="color: rgb(0, 96, 128);">"&lt;h1&gt;"</span>);<br />sb.Append(headerText);<br />sb.Append(<span style="color: rgb(0, 96, 128);">"&lt;/h1&gt;"</span>);<br /><span style="color: rgb(0, 0, 255);">string</span> headerHtml = sb.ToString();</pre></blockquote><p>In this first case, I thought I was brilliant because I knew about the <a href="http://msdn.microsoft.com/en-us/library/a6d350wd.aspx">Concat</a> method and thought it'd give me faster code. This is not true because the C# compiler special cases string concatenation to automatically do this. The second example is painful because it's <a href="http://www.yoda.arachsys.com/csharp/stringbuilder.html">uglier and slower</a> and it isn't building a string in a loop where <a href="http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx">StringBuilder</a>s make a lot of sense.</p><p>After many dumb mistakes like this, I've finally decided that if I ever have a doubt on which option to use, I'll pick the more readable one:</p><blockquote><p>Write your code to be read. By humans. Easily. The compiler will be able to cope. [<a href="http://www.amazon.com/gp/product/1593271190?ie=UTF8&amp;tag=moserware-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=1593271190">Code Craft</a>, p59]</p></blockquote><p><strong>Coda</strong><br /></p><p><strong><a href="http://en.wikipedia.org/wiki/Image:Smokey3.jpg"><img style="border-width: 0px; margin: 0px 10px 0px 0px;" alt="Smokey3" src="http://4.bp.blogspot.com/_Zfbv3mHcYrc/SQr7XrO9luI/AAAAAAAABDk/snKOYgebJkA/s320/Smokey3.jpg" width="171" align="left" border="0" height="244" /></a></strong>Boy Scout check-ins are <a href="http://www.joelonsoftware.com/items/2007/06/07.html">small steps</a> that help fix the <a href="http://en.wikipedia.org/wiki/Fixing_Broken_Windows">broken windows</a> that we all have in our code. When you look at your code, try to find at least <em>one</em> thing you can do to leave it better. Eventually it becomes a game where everyone benefits. These check-ins can often be a small reward for checking-in a large feature or fixing a nasty bug.</p><p>If you're pressed for time and can't make the change now or you want to save it for when you can make the change across all your code, make a note to yourself. I create empty change-lists in <a href="http://en.wikipedia.org/wiki/Perforce">my version control system</a> for this purpose. This is also helpful if you find a bug and want to later <a href="http://www.fastcompany.com/magazine/06/writestuff.html?page=0%2C4">complained</a> that <a href="http://www.mayoclinic.com/health/hand-washing/HQ00407">hand-washing</a> took too long and "wasted" their precious time. We all have our own pressures that might cause us to think that we can neglect basic code hygiene. Over time, this snowballs into a mess that we've all had to deal with. </p><p>Only you can <a href="http://www.cedu.niu.edu/%7Efulmer/starfish.htm">make a difference</a> in <em>your</em> code campground.</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f10%2fboy-scout-check-ins.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f10%2fboy-scout-check-ins.html" border="0" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-3697554272614582724?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com9tag:blogger.com,1999:blog-6800934446457898793.post-32572922453988288562008-09-29T08:26:00.007-04:002008-10-03T22:36:09.338-04:00How Do Locks Lock?<p>When I was 9 or so, I was convinced I could write my own operating system in <a href="http://en.wikipedia.org/wiki/GW-BASIC">GW-BASIC</a>. After all, I <em>had</em> written programs that played <a href="http://en.wikipedia.org/wiki/Mary_Had_a_Little_Lamb">Mary Had a Little Lamb</a> on the <a href="http://en.wikipedia.org/wiki/PC_speaker">PC speaker</a> while displaying <a href="http://en.wikipedia.org/wiki/Color_Graphics_Adapter">CGA graphics</a>. How much harder could an operating system be?</p><p>One thing had me stumped. How would I get my OS to <a href="http://en.wikipedia.org/wiki/Computer_multitasking">multitask</a>? </p><p>After giving it some thought, the best idea I could come up with was to write the programs for my "OS" in such a way that they would occasionally perform a <a href="http://en.wikipedia.org/wiki/GOSUB">GOSUB</a> or <a href="http://en.wikipedia.org/wiki/GOTO">GOTO</a> to parts of other programs. By using a lot of mental <a href="http://en.wikipedia.org/wiki/Handwaving">handwaving</a> to myself, I was convinced I could <em>somehow</em> make it work. </p><p>But the details came back to bite me. I never pulled it off. I put it aside and worked on other things. I just assumed that something magical happened under the covers. My bedtime reading of magazines like <a href="http://en.wikipedia.org/wiki/PC/Computing">PC/Computing</a> convinced me that the magical solution to the problem included buzzwords like "<a href="http://en.wikipedia.org/wiki/Preemptive_multitasking">preemptive multitasking</a>" and "<a href="http://en.wikipedia.org/wiki/Thread_%28computer_science%29">multithreading</a>." Both of these ideas were in the upcoming <a href="http://en.wikipedia.org/wiki/Windows_NT">Windows NT</a> 3.1 design. I didn't really understand what these buzzwords meant, but at least they sounded impressive. </p><p>Even though I've learned a bit more about writing programs that can do more than one thing at a time since those early days, I still have points where I don't understand exactly what is going on. Recently, I decided that I wanted to stop my handwaving about locks and do whatever it took to find out how they, well... <em>lock</em>.</p><p><strong>A View from the Top</strong></p><p>Locks let you express your belief that something bad might happen if two threads go through a section of code at the same time. Locks are present in many languages. Here's an example of one in C#:</p><pre><span style="COLOR: rgb(0,0,255)">object</span> syncRoot = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(0,0,255)">object</span>();<br /><br /><span style="COLOR: rgb(0,0,255)">private</span> <span style="COLOR: rgb(0,0,255)">void</span> MyFunction()<br />{<br /><span style="COLOR: rgb(0,0,255)"> lock</span> (syncRoot)<br /> {<br /> <span style="COLOR: rgb(0,128,0)">// only one thread can enter this locked gate at a time.</span><br /> }<br />}</pre><p>The above lock creates a "gate" that only allows one thread at a time regardless of what that thread is doing. This is often too pessimistic and inefficient. In a lot of cases, it doesn't matter if multiple threads are reading a piece of data at the same time. However, we want to make sure that there is only one writer at a time. Furthermore, we want to make sure that the readers don't see corrupted garbage. </p><p>A lock that is optimized for allowing multiple readers at a time while still being consistent in the face of writers is called a reader/writer lock. Here's an example of some typical code you might see in an application that has to <a href="http://en.wikipedia.org/wiki/Cache">cache</a> objects that take a long time to create:</p><pre><span style="COLOR: rgb(0,0,255)">private readonly</span> Dictionary&lt;<span style="COLOR: rgb(0,0,255)">string</span>, ReallyExpensiveObject&gt; expensiveObjectCache<br /> = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">Dictionary</span>&lt;<span style="COLOR: rgb(0,0,255)">string</span>, <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span>&gt;();<br /><br /><span style="COLOR: rgb(0,0,255)">private readonly</span> <span style="COLOR: rgb(43,145,175)">ReaderWriterLock</span> rwl = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">ReaderWriterLock</span>();<br /><br /><span style="COLOR: rgb(0,0,255)">public</span> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span> GetExpensiveObject(<span style="COLOR: rgb(0,0,255)">string</span> key)<br />{ <br /> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span> expensiveObject;<br /><br /> rwl.AcquireReaderLock(<span style="COLOR: rgb(43,145,175)">Timeout</span>.Infinite);<br /><br /> <span style="COLOR: rgb(0,0,255)">try</span><br /> {<br /> <span style="COLOR: rgb(0,0,255)">if</span> (<span style="COLOR: rgb(0,0,255)">this</span>.expensiveObjectCache.TryGetValue(key, <span style="COLOR: rgb(0,0,255)">out</span> expensiveObject))<br /> {<br /> <span style="COLOR: rgb(0,128,0)">// Cache hit</span><br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObject;<br /> }<br /><br /> <span style="COLOR: rgb(0,128,0)">// Cache miss</span><br /> <span style="COLOR: rgb(43,145,175)">LockCookie</span> cookie;<br /><br /> cookie = rwl.UpgradeToWriterLock(<span style="COLOR: rgb(43,145,175)">Timeout</span>.Infinite);<br /> <span style="COLOR: rgb(0,0,255)">try</span><br /> {<br /> expensiveObject = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span>();<br /> expensiveObjectCache[key] = expensiveObject;<br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObject;<br /> }<br /><br /> <span style="COLOR: rgb(0,0,255)">finally</span><br /> {<br /> rwl.DowngradeFromWriterLock(<span style="COLOR: rgb(0,0,255)">ref</span> cookie);<br /> }<br /> }<br /> <span style="COLOR: rgb(0,0,255)">finally</span><br /> {<br /> rwl.ReleaseReaderLock();<br /> }<br />} </pre><p>This code will allow more than one reader at a time and will handle the case of upgrading the read lock to a write lock if it needs to insert an item into the cache. The code is a bit long and tedious to write. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn1">1</a>] Even worse, it has a very subtle bug in it that we'll look at later. </p><p>We first need to understand what is going on inside a lock. Since reader/writer locks are usually more interesting than a normal lock, we'll focus on the details of a reader/writer lock implementation. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn2">2</a>]</p><p><strong>Entering an Internal Lock</strong></p><p>Locks themselves have internal data that they must protect from corruption by competing threads. This internal data includes the number of active readers and how many threads are waiting to write data. In order to provide this protection, locks must enter an internal lock.</p><p>For simplicity, locks usually have a single variable that indicates if a thread has acquired the internal lock. I'll illustrate this and other concepts by posting snippets from <a href="http://blogs.msdn.com/vancem/default.aspx">Vance Morrison</a>'s excellent <a href="http://blogs.msdn.com/vancem/archive/2006/03/28/563180.aspx">reader-writer lock sample</a>: [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn3">3</a>]</p><pre> <span style="COLOR: rgb(0,0,255)">private</span> <span style="COLOR: rgb(0,0,255)">void</span> EnterMyLock() {<br /> <span style="COLOR: rgb(0,0,255)">if</span> (<span style="COLOR: rgb(43,145,175)">Interlocked</span>.CompareExchange(<span style="COLOR: rgb(0,0,255)">ref</span> myLock, 1, 0) != 0)<br /> EnterMyLockSpin();<br />}</pre><p>In Vance's code, a member variable named "myLock" is set to 1 if the lock is held, otherwise it is 0. The <a href="http://msdn.microsoft.com/en-us/library/system.threading.interlocked.compareexchange.aspx">Interlocked.CompareExchange</a> function is interesting because it does two things. If "myLock" is 0, then it is set to 1. If "myLock" doesn't equal 0, then we know that someone else has the internal lock. The documentation says that "the compare and exchange operations are performed as an atomic operation." I was curious how this actually worked, so I looked at .NET's source code and eventually hit this wall:</p><pre>[<span style="COLOR: rgb(43,145,175)">MethodImplAttribute</span>(<span style="COLOR: rgb(43,145,175)">MethodImplOptions</span>.InternalCall)]<br />[<span style="COLOR: rgb(43,145,175)">ReliabilityContract</span>(<span style="COLOR: rgb(43,145,175)">Consistency</span>.WillNotCorruptState, <span style="COLOR: rgb(43,145,175)">Cer</span>.Success)]<br /><span style="COLOR: rgb(0,0,255)">public</span> <span style="COLOR: rgb(0,0,255)">static</span> <span style="COLOR: rgb(0,0,255)">extern</span> <span style="COLOR: rgb(0,0,255)">int</span> Exchange(<span style="COLOR: rgb(0,0,255)">ref</span> <span style="COLOR: rgb(0,0,255)">int</span> location1, <span style="COLOR: rgb(0,0,255)">int</span> <span style="COLOR: rgb(0,0,255)">value</span>);</pre><p>In my earlier .NET days, I would have given up at this point. The "<a href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx">InternalCall</a>" attribute indicates that the CLR handles the call internally. It seemed like I would never quite know what happened inside this mysterious internal call.</p><p>And then I <a href="http://callvirt.net/blog/entry.aspx?entryid=b9a94d0c-761a-4d6b-bc2f-d6a5f8c1a4a7">met</a> <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=8c09fd61-3f26-4555-ae17-3121b4f51d4d&amp;displaylang=en">Rotor</a>. </p><p><strong>Inside an InternalCall</strong></p><p>Rotor lets you look at the CLR's internals that are mostly written in C++ with a small amount of assembly code. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn4">4</a>] If you navigate through several layers of function calls, you'll see that Interlocked.CompareExchange ultimately reaches this function in <a href="http://www.koders.com/assembler/fid77ECC209CEF9678F4ECEBD55A9AC0D10301EB8B0.aspx?s=CompareExchangeUP">clr/src/vm/i386/asmhelpers.asm</a> that is written in x86 assembly: [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn5">5</a>]</p><pre>FASTCALL_FUNC CompareExchangeMP,12<br /> _ASSERT_ALIGNED_4_X86 ecx<br /> mov eax, [esp+4] ; Comparand<br /> cmpxchg [ecx], edx<br /> retn 4 ; result in EAX<br />FASTCALL_ENDFUNC CompareExchangeMP</pre><p><a href="http://en.wikipedia.org/wiki/Image:Intel_80486DX2_top.jpg" target="_blank"><img style="MARGIN: 0px 10px 10px 0px" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SODCDVVXYgI/AAAAAAAABC8/1tAMBEgTdcA/s200/Intel_80486DX2_top.jpg" align="left" /></a>By far, the most interesting aspect of this is the "lock cmpxchg" line. Besides giving gamers power to play <a href="http://en.wikipedia.org/wiki/Doom_%28video_game%29">DOOM</a>, the <a href="http://en.wikipedia.org/wiki/Intel_80486">486</a> chip introduced a "cmpxchg" instruction that will both compare a value and exchange it with a new value if the comparison succeeds. It does this in a single CPU instruction. This is how the documentation can claim that it is an "atomic" operation. We'll see why it's very important to do this in a single instruction a bit later. The "lock" prefix is used to tell the CPU to assert a physical signal so that no other core can access memory at the same time. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn6">6</a>] This hardware locking is how the "myLock" variable can remain safe from simultaneous access by other cores.</p><p>But now what happens if another thread already had the internal lock? </p><p><strong>Spinlocks</strong></p><p>When locks need to wait on the internal lock, they typically use a <a href="http://en.wikipedia.org/wiki/Spinlock">spinlock</a>. This tells the processor to essentially spin around in circles in order to waste a little bit of time so that the thread that has the internal lock can possibly finish what it is doing and exit the lock.</p><p>Here's an example from Vance's code of how a spinlock is performed:</p><pre><span style="COLOR: rgb(0,0,255)">private</span> <span style="COLOR: rgb(0,0,255)">void</span> EnterMyLockSpin()<br />{<br /> <span style="COLOR: rgb(0,0,255)">for</span> (<span style="COLOR: rgb(0,0,255)">int</span> i = 0; ;i++)<br /> {<br /> <span style="COLOR: rgb(0,0,255)">if</span> (i &lt; 3 &amp;&amp; <span style="COLOR: rgb(43,145,175)">Environment</span>.ProcessorCount &gt; 1)<br /> <span style="COLOR: rgb(43,145,175)">Thread</span>.SpinWait(20); <span style="COLOR: rgb(0,128,0)">// Wait a few dozen instructions to let another processor release the lock. </span><br /> <span style="COLOR: rgb(0,0,255)">else</span><br /> <span style="COLOR: rgb(43,145,175)">Thread</span>.Sleep(0); <span style="COLOR: rgb(0,128,0)">// Give up my quantum.<br /></span><br /> <span style="COLOR: rgb(0,0,255)">if</span> (<span style="COLOR: rgb(43,145,175)">Interlocked</span>.CompareExchange(<span style="COLOR: rgb(0,0,255)">ref</span> myLock, 1, 0) == 0)<br /> <span style="COLOR: rgb(0,0,255)">return</span>;<br /> }<br />}</pre><p>It's a basic <a href="http://www.moserware.com/2008/02/for-loops-using-i-i-enumerators-or-none.html">for loop</a> that has a few interesting bits. The first thing to notice is that this loop will keep going until the CompareExchange succeeds. That is, until we acquire the internal lock.</p><p>On a multiprocessor system, it will try a <a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.spinwait.aspx">Thread.SpinWait</a> for 3 times. The documentation for SpinWait is a bit confusing about what it does with the "20" argument:</p><blockquote>SpinWait essentially puts the processor into a very tight loop, with the loop count specified by the iterations parameter. The duration of the wait therefore depends on the speed of the processor. </blockquote><p>What exactly is it doing? Looking at Rotor's <a href="http://www.koders.com/cpp/fid8D17314FA5D75768B578F75C68097CFFC58657FF.aspx#L1915">clr/src/vm/comsynchronizable.cpp</a> gives us the reality:</p><pre>FCIMPL1(void, ThreadNative::SpinWait, int iterations)<br />{<br /> WRAPPER_CONTRACT;<br /> STATIC_CONTRACT_SO_TOLERANT;<br /><br /> for(int i = 0; i &lt; iterations; i++)<br /> YieldProcessor();<br />}<br />FCIMPLEND</pre><p>Further diving shows that "<a href="http://msdn.microsoft.com/en-us/library/ms687419%28VS.85%29.aspx">YieldProcessor</a>" is this macro:</p><p>#define YieldProcessor() __asm { rep nop } </p><p>This is a "repeat no-op" assembly instruction. It's also known in the <a href="http://download.intel.com/design/processor/manuals/253667.pdf">Intel instruction set manual</a> as "PAUSE - Spin Loop Hint." [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn7">7</a>] This means that the CPU knows about the spin waiting that we're wanting to accomplish. </p><p>As the documentation hinted, the time spent waiting is dependant upon the clock rate of the machine. In my case, I have an EE6600 <a href="http://en.wikipedia.org/wiki/Intel_Core_2">Core 2 Duo</a> where each core runs at 2.4 GHz, and it's about 3.4 nanoseconds for each "YieldProcessor" call. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn8">8</a>] This means it takes approximately 70 nanoseconds for 20 iterations. Three unsuccessful passes through this loop will cost about 210 nanoseconds.</p><p>I'm sure that if reader/writer locks had <a href="http://en.wikipedia.org/wiki/Cheerleading">cheerleaders</a> inside of them, they would be shouting in hope that the spin wait used enough time so that the thread that had the internal lock that is protected by the "cmpxchg" will have released it. </p><p>Why does the lock try so hard to get by with only a spin wait? In a word: speed. </p><p>By not being able to satisfy the request with a spin wait, the thread gives up and goes to sleep. This requires intervention by the OS to potentially swap it out and run a different thread that that has been waiting. By letting another thread run, there is a chance that the CPU will have to toss out its <a href="http://en.wikipedia.org/wiki/CPU_cache">onboard cache</a> only to fetch it back when the thread gets swapped back in. All of this could potentially add up to hundreds of thousands of CPU cycles that aren't being used to get "real" work done. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn9">9</a>]</p><p><strong>How Does a Thread Sleep? How Does it Know When to Wake Up?</strong></p><p>Windows keeps track of the <a href="http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/core/fned_ana_sqrr.mspx?mfr=true">state of each thread</a> in your system. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn10">10</a>] Here's a simplified thread state chart from the excellent <a title="Specifically, this was derived from Figure 3-25" href="http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174">Windows Internals</a> book:</p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SODBN6vfQfI/AAAAAAAABCs/6p0cQFzrp8I/s1600-h/ThreadState.png"><img id="BLOGGER_PHOTO_ID_5251409610364895730" alt="" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SODBN6vfQfI/AAAAAAAABCs/6p0cQFzrp8I/s320/ThreadState.png" border="0" /></a><br /><br /><p>When your thread is "Running" and is interrupted because its time-slice ran out or it voluntarily gave up its time slice by using a Sleep(0) request, the OS will save the state of what it is doing by performing a <a href="http://en.wikipedia.org/wiki/Context_switch">context switch</a>. The fact that this switch can occur at any time is why it was critical that the CompareExchange code execute in a single CPU instruction that cannot be interrupted. If it didn't, it would be possible to put the lock in an inconsistent state between the compare and the exchange. </p><p>When the Sleep(0) call is made, the thread is put in a "Ready" queue meaning that it's "ready" to run and not waiting on anything. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn11">11</a>] </p><p>While we're at this chart, it's important to note that one of the possible thread states is "waiting." Windows will keep track of the <a href="http://msdn.microsoft.com/en-us/library/ms682396%28VS.85%29.aspx">events</a> that a thread is waiting on. </p><p>Events are useful for signaling between threads. For example, a reader/writer lock can "signal" other threads by informing the OS that an event has been "set." What happens next inside of the thread scheduler/dispatcher depends on the type of event that was set: [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn12">12</a>]</p><ul><li><a href="http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx">AutoResetEvent</a>: In this case, only a single thread that is waiting for the event will be put into the "ready" queue. Anyone else that is waiting for the event stays in the waiting queue. This is useful for releasing exactly one writer. </li><li><a href="http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx">ManualResetEvent</a>: When signaled, Windows will update all of the threads that are waiting on the event to be moved into the ready queue. Effectively, it releases them all. This is useful for releasing all waiting readers. </li><br /></ul><p>What's important to realize is that we have the cooperation of the thread dispatcher in the OS to obey the thread states. By simply being in the waiting queue, the threads aren't even considered to be scheduled to run and thus consume no real CPU time.</p><p><strong>Putting It All Together</strong></p><p>It's been a <em>long</em> journey, but we now have all the background information we need in order to understand how a reader/writer lock actually locks:</p><ul><li>Acquiring a Read Lock: </li><ul><li>Enter the internal lock (spin wait or sleep as necessary) </li><li>Look to see If there is anyone writing </li><ul><li>If no one is writing and no writers are waiting, just increase the number of readers. This is the <a href="http://en.wikipedia.org/wiki/Happy_path">happy path</a>. </li><li>If a writer is writing, tell the OS that we want to wait until the "ready for readers" event is set. </li></ul><li>Exit the internal lock. </li></ul><li>Exiting a read lock: </li><ul><li>Enter the internal lock </li><li>Decrement the total number of readers. </li><li>Check the total number of readers remaining </li><ul><li>If there are still readers remaining, then make sure that all waiting readers have been released so they can run. </li><li>If there are no readers left and there is at least one writer waiting, signal the appropriate event so that exactly one of the waiting writers wakes up and will get the lock. </li></ul><li>Exit the internal lock. </li></ul><li>Acquiring a write lock: </li><ul><li>Enter the internal lock </li><li>Check the number of readers or if there is an active writer in progress. In addition, check to see if there are any in line waiting to do either. </li><ul><li>If there are no readers or writers, record that we're writing. This is the happy path. </li><li>Otherwise wait for our turn in line on the write queue by waiting on the "ready for writing" event. </li></ul><li>Exit the internal lock </li></ul><li>Exiting a write lock: </li><ul><li>Enter the internal lock </li><li>Check how many readers or writers are waiting </li><ul><li>If there are no waiting writers, immediately signal all readers at once. </li><li>Alternatively, release one writer that has been waiting. </li></ul><li>Exit the internal lock. </li></ul></ul><p>As it turned out, the locks themselves are fairly simple. They just had a few pieces that came together in interesting ways.</p><p><strong>The Problem of the Upgrades</strong></p><p>There's a subtle problem with reader/writer locks: Imagine that two threads are both in a read lock and then they both decide that they need to upgrade to a write lock. Because a writer must wait for all readers to finish before acquiring a write lock, there seems to be a <a href="http://en.wikipedia.org/wiki/Deadlock">deadlock</a> scenario since neither one wants to give up its read lock. </p><p>The secret trick is that they indeed must give up their read lock if there are any other active readers. This forces a correct implementation to do something like this when performing an upgrade:</p><pre><span style="COLOR: rgb(0,128,0)">// Cache miss</span><br /><span style="COLOR: rgb(43,145,175)">LockCookie</span> cookie;<br /><br /><span style="COLOR: rgb(0,0,255)">int</span> writerSeqNum = rwl.WriterSeqNum;<br /><br />cookie = rwl.UpgradeToWriterLock(<span style="COLOR: rgb(43,145,175)">Timeout</span>.Infinite);<br /><br /><span style="COLOR: rgb(0,0,255)">try</span><br />{<br /><span style="COLOR: rgb(0,0,255)"> if</span> (rwl.AnyWritersSince(writerSeqNum))<br /> {<br /> <span style="COLOR: rgb(0,128,0)">// Since another writer snuck in, we might no longer need</span><br /> <span style="COLOR: rgb(0,128,0)">// to create a new object. Let's check again to see if we</span><br /> <span style="COLOR: rgb(0,128,0)">// need to do this.</span><br /><br /> <span style="COLOR: rgb(0,0,255)">if</span> (<span style="COLOR: rgb(0,0,255)">this</span>.expensiveObjectCache.TryGetValue(key, <span style="COLOR: rgb(0,0,255)">out</span> expensiveObjectCache))<br /> {<br /> <span style="COLOR: rgb(0,128,0)">// The other writer(s) must have created it</span><br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObjectCache;<br /> }<br /> }<br /><br /> <span style="COLOR: rgb(0,128,0)">// Other writers didn't sneak in, so we know we need to create</span><br /> <span style="COLOR: rgb(0,128,0)">// the object.</span><br /><br /> expensiveObject = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span>();<br /><br /> expensiveObjectCache[key] = expensiveObject;<br /><br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObject;<br /><br />}<br /><span style="COLOR: rgb(0,0,255)">finally</span><br />{<br /> rwl.DowngradeFromWriterLock(<span style="COLOR: rgb(0,0,255)">ref</span> cookie);<br />}</pre><p>Each time a writer lock is acquired, the WriterSeqNum is incremented. The "AnyWritersSince" function will check to see if any writers have occurred since the moment just before we upgraded. If this is true, then it means that another writer might have come in and thus we need to recheck our assumptions.</p><p>This is just one way to handle the upgrade problem. [<a href="http://www.moserware.com/2008/09/how-do-locks-lock.html#lockfn13">13</a>]</p><p>As <a href="http://www.bluebytesoftware.com/blog/Default.aspx">Joe Duffy</a> <a href="http://www.bluebytesoftware.com/blog/PermaLink,guid,c4ea3d6d-190a-48f8-a677-44a438d8386b.aspx">explained on his blog</a>, the new ReaderWriterLockSlim gets around the upgrade problem by introducing an "UpgradeableRead." When a thread enters an upgradeable read, the lock will force all subsequent readers to wait until the thread decides if it wants to upgrade. In the mean time, existing readers are allowed to finish. If an upgrade is requested, the lock will wait until no more readers are present. This preserves the integrity of the data.</p><p>Here's a full example:</p><pre><span style="COLOR: rgb(0,0,255)">private</span> <span style="COLOR: rgb(43,145,175)">ReaderWriterLockSlim</span> slimLock = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">ReaderWriterLockSlim</span>();<br /><br /><span style="COLOR: rgb(0,0,255)">public</span> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span> GetExpensiveObjectSlim(<span style="COLOR: rgb(0,0,255)">string</span> key)<br />{<br /><span style="COLOR: rgb(43,145,175)"> ReallyExpensiveObject</span> expensiveObject;<br /><br /> <span style="COLOR: rgb(0,0,255)">bool</span> upgraded = <span style="COLOR: rgb(0,0,255)">true</span>;<br /><br /> <span style="COLOR: rgb(0,0,255)">this</span>.slimLock.EnterUpgradeableReadLock();<br /><br /> <span style="COLOR: rgb(0,0,255)">try</span><br /> {<br /> <span style="COLOR: rgb(0,0,255)">if</span> (<span style="COLOR: rgb(0,0,255)">this</span>.expensiveObjectCache.TryGetValue(key, <span style="COLOR: rgb(0,0,255)">out</span> expensiveObject))<br /> {<br /> <span style="COLOR: rgb(0,128,0)">// Cache hit</span><br /> upgraded = <span style="COLOR: rgb(0,0,255)">false</span>;<br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObject;<br /> }<br /><br /> <span style="COLOR: rgb(0,128,0)">// Cache miss</span><br /> <span style="COLOR: rgb(0,0,255)">this</span>.slimLock.EnterWriteLock();<br /><br /> <span style="COLOR: rgb(0,0,255)">try</span><br /> {<br /> expensiveObject = <span style="COLOR: rgb(0,0,255)">new</span> <span style="COLOR: rgb(43,145,175)">ReallyExpensiveObject</span>();<br /> expensiveObjectCache[key] = expensiveObject;<br /> <span style="COLOR: rgb(0,0,255)">return</span> expensiveObject;<br /> }<br /> <span style="COLOR: rgb(0,0,255)">finally</span><br /> {<br /> <span style="COLOR: rgb(0,0,255)">this</span>.slimLock.ExitWriteLock(); <br /> }<br /> }<br /> <span style="COLOR: rgb(0,0,255)">finally</span><br /> {<br /> slimLock.ExitUpgradeableReadLock();<br /> }<br />}</pre><p>While showing the full syntax needed, it's a bad example of using a ReaderWriterLockSlim since it doesn't allow for multiple readers. The code might perform better by just entering a read lock if reads occur much more frequently than writes. If the a write is actually needed, then a subsequent write lock can be acquired and a double check can occur to see if a write is still needed. Alternatively, a classic <a href="http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx">Monitor</a> style lock can be used. </p><p><strong>Conclusion: Why Should I Care About the Details?</strong></p><p>Our journey has taken us from the high level of using a reader/writer lock to the low level of a single signal on the processor bus. Knowing this low level "goo" is helpful for a few reasons:</p><ol><li>Ideally, lock sections should be kept small so that no lock contention occurs in the first place so that we don't need to "spin wait" at all (to acquire the <span style="FONT-STYLE: italic">internal</span> lock). </li><li>Since readers are released all at once via an event, it shows how a reader/writer lock gets its performance benefit over a normal Monitor lock that would force waiting readers to wait in a line to get released one-by-one. </li><li>We now can see that locks aren't magic at all. They just have a few moving parts. </li><br /></ol><p>With a better understanding of locks, I'll focus my handwaving on other concepts... like building a <a href="http://www.bluebytesoftware.com/blog/2008/09/17/BuildingACustomThreadPoolSeriesPart3IncorporatingWorkStealingQueues.aspx">work-stealing thread pool</a>.</p><p><span style="FONT-WEIGHT: bold">UPDATE 30 Sep 2008:<span style="FONT-WEIGHT: bold"><span style="FONT-WEIGHT: bold"></span></span></span> I fixed the footnote links and updated conclusion #1 based off comments. </p><p><strong>UPDATE 3 Oct 2008:</strong> I updated the paragraph discussing why spin waits can be helpful based off some good discussion in the comments. </p><p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f09%2fhow-do-locks-lock.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f09%2fhow-do-locks-lock.html" border="0" /></a> <hr /><br /><p></p><p><em>Notes</em></p><p>(This article had a few places where I made some claims. I'm sure I probably got some things wrong or might have misunderstood something in my explorations. I'm putting notes here to give background of what I was thinking when I wrote the post. Please feel free to correct me and keep me honest via comments for the benefit of others)</p><p>[<a name="lockfn1">1</a>] If performance isn't insanely critical, you can create your own lock and have helper methods like "EnterScopedRead" that return an <a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx">IDisposable</a> object that will automatically release the lock when it's disposed. Then, you can use a C# <a href="http://msdn.microsoft.com/en-us/library/yh598w02%28VS.80%29.aspx">"using" statement</a> with it to reduce some of the code clutter.</p><p>[<a name="lockfn2">2</a>] I still think that reader/writer locks are more interesting than normal <a href="http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx">Monitor</a> type locks. However, if you have a relatively balanced number of readers and writers (e.g. no clear readers majority), then Monitors make more sense since they're slightly faster. However, the code that Monitors uses a lot more assembly code for performance reasons and thus is often harder to understand.</p><p>[<a name="lockfn3">3</a>] Even a cursory look at the source code of .NET 3.5's new <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx">ReaderWriterLockSlim</a> in <a href="http://www.red-gate.com/products/reflector/index.htm">Reflector</a> shows that Vance's lock code was the basis for it. ReaderWriterLockSlim is slightly more complex to handle cases like a recursive lock (e.g. acquiring a read lock when you have a write lock), but the core ideas remain the same.</p><p>[<a name="lockfn4">4</a>] To be technically correct, Rotor isn't <em>exactly</em> what the commercial CLR is. Some of the aspects like the garbage collector and the Just In Time (JIT) compiler are different due to trade secrets. However, I don't think the parts I'll be mentioning here are different between the reference implementation and the actual commercial implementation. For more details on Rotor, I recommend reading Joel Pobar and Ted Neward's <a href="http://callvirt.net/blog/entry.aspx?entryid=b9a94d0c-761a-4d6b-bc2f-d6a5f8c1a4a7">new book</a> on Rotor 2.0.</p><p>[<a name="lockfn5">5</a>] Things aren't <em>quite</em> that simple. The first thing to realize is that the CLR has a Platform Adaptation Layer (PAL) that handles all architecture specific code. Thus, there can be equivalent assembly code for other chips like the PowerPC which is located in clr/src/vm/ppc. Furthermore, the actual x86 code can be one of these two functions:</p><pre>FASTCALL_FUNC CompareExchangeUP,12<br /> _ASSERT_ALIGNED_4_X86 ecx<br /> mov eax, [esp+4] ; Comparand<br /> cmpxchg [ecx], edx<br /> retn 4 ; result in EAX<br />FASTCALL_ENDFUNC CompareExchangeUP</pre><p>or</p><pre>FASTCALL_FUNC CompareExchangeMP,12<br /> _ASSERT_ALIGNED_4_X86 ecx<br /> mov eax, [esp+4] ; Comparand<br />lock cmpxchg [ecx], edx<br /> retn 4 ; result in EAX<br />FASTCALL_ENDFUNC CompareExchangeMP</pre><p>If you look at <a href="http://www.koders.com/cpp/fid5D107FB771CB95D813D0E369FE8EE1ADD5564AF3.aspx?s=CmpXchgOps">cgenx86.cpp</a>, you'll see that CompareExchangeUP is the default and the CompareExchangeMP is used if your system has more than one processor:</p><p>CmpXchgOps FastInterlockCompareExchange = (CmpXchgOps)CompareExchangeUP;</p><p>// Adjust the generic interlocked operations for any platform specific ones we<br />// might have.<br /><br />void <a href="http://www.koders.com/">InitFastInterlockOps</a>()<br />{<br />...</p><pre> if (g_SystemInfo.dwNumberOfProcessors != 1)<br /> {<br /> ...<br /><br /> FastInterlockCompareExchange = (CmpXchgOps)CompareExchangeMP;<br /><br /> ...<br /> }<br /><br />...</pre><pre>}</pre><p>From this, I was able to determine that "CompareExchangeUP" is for <a href="http://en.wikipedia.org/wiki/Uniprocessor">uniprocessor</a> machines and "CompareExchangeMP" is for multiprocessor machines. If you look at the code carefully, you'll notice that the only difference is that the uniprocessor version doesn't bother locking the processor bus. This is safe because there is no chance of simultaneous memory access.</p><p>[<a name="lockfn6">6</a>] The truth is a little bit more complicated, but more interesting. The <a href="http://download.intel.com/design/processor/manuals/253668.pdf">Intel 64 and IA-32 Architectures Software Developer's Manual - Volume 3A: System Programming Guide, Part 1</a> tells us:</p><blockquote><p>7.1.4 Effects of a LOCK Operation on Internal Processor Caches. </p><p>For the Intel486 and Pentium processors, the LOCK# signal is always asserted on the bus during a LOCK operation, even if the area of memory being locked is cached in the processor. </p><p>For the P6 and more recent processor families, <em>if the area of memory being locked during a LOCK operation is cached in the processor that is performing the LOCK operation as write-back memory and is completely contained in a cache line, the processor may not assert the LOCK# signal on the bus.</em> Instead, it will modify the memory location internally and allow [its] cache coherency mechanism to insure that the operation is carried out atomically. This operation is called "cache locking." The cache coherency mechanism automatically prevents two or more processors that have the same area of memory from simultaneously modifying data in that area. (emphasis added)</p></blockquote><p>Here we learn that the <a href="http://en.wikipedia.org/wiki/Intel_P6">P6</a> and newer chips are smart enough to determine if they really have to block off the bus or can just rely on intelligent caching. I think this is a neat optimization.</p><p>[<a name="lockfn7">7</a>] I think the "PAUSE" instruction is an interesting example of how Intel allows for backwards compatibility. Its opcode of "F3 90" makes it identical to "REP NOP" which will cause older processors to still do nothing, however newer chips use this odd opcode as a clear hint to do more efficient things.</p><p>[<a name="lockfn8">8</a>] If you're curious about where I came up with the numbers, look at <a href="http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/980325.aspx">this discussion</a> on the Intel forums. It's a bit hard to measure since context switches might skew the results. My lowest run yielded numbers that indicate a nop took 0.34 clocks per instruction and that "PAUSE" took 8.21 clocks per instruction. I did (2,400,000,000 clocks / second) * (1 PAUSE / 8.21 clocks) to get 292,326,431 PAUSEs / second or 3.42 ns / PAUSE.</p><p>[<a name="lockfn9">9</a>] <strong>UPDATE:</strong> The original statement made a statement that this was 100,000 times slower. After some good discussion in the comments, I'm not going to claim specifics since it depends a lot on the machine's workload and a thread's working set.</p><p>It's interesting to note that Vance's original code gives up after only three tries of around 70ns each. The <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx">ReaderWriterLockSlim</a> that was ultimately derived from it keeps up the fight a little longer. It does something like "Thread.SpinWait(20 * (i + 1))" which leads to a geometric back-off over time for a total of up to 10 iterations which yields the equivalent of 1100 "YieldProcessor" calls or approximately 3.76 microseconds. This means it stays in the fight 1100 / 210 or 5.2 times longer.</p><p>(See the comments for more discussion on this)</p><p>[<a name="lockfn10">10</a>] It's important to realize that processes don't run on Windows, but threads do. Although processes provide isolation boundaries, they require a thread to execute code. </p><p>[<a name="lockfn11">11</a>] The Thread.Sleep(0) call ultimately reaches the <a href="http://msdn.microsoft.com/en-us/library/ms686307%28VS.85%29.aspx">SleepEx</a> API that has this documentation:</p><blockquote><p>A[n argument value of] zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.</p></blockquote><p>It's interesting that ReaderWriterLockSlim does a Sleep(0) for 5 times before finally doing Sleep(1) until it reaches success. I'm assuming it does the Sleep(1) in order to protect users from themselves in the event that the thread that has the lock and then goes into a state where it's waiting on something (e.g. I/O) to occur. Lock sensitive code should <em>not</em> be doing this, but it doesn't hurt to provide this forced 1 ms minimum delay. If they didn't do this, the thread that had the lock would remain on the waiting queue while waiting for I/O and this would potentially have the thread that needs the lock to immediately be put back on the run queue without burning much CPU time. </p><p>Finally, I'm assuming that SleepEx(0) performs a software <a href="http://en.wikipedia.org/wiki/Interrupt">interrupt</a>. This is like a GOTO that jumps to a <a href="http://en.wikipedia.org/wiki/Interrupt_descriptor_table">well known address</a> that that handles the scheduling/dispatching of threads in the kernel.</p><p>[<a name="lockfn12">12</a>] I'm simplifying things a bit here. Threads can wait on multiple events at one time. Therefore, setting one event might still mean that a thread is waiting on other events. </p><p>As an aside, it was only while researching this post that I realized why the <a href="http://msdn.microsoft.com/en-us/library/ms687025.aspx">WaitForMultipleObjects</a> API is so useful. By using it, you can eliminate a very costly process of putting your thread back on the ready queue and getting scheduled only to find out that it still needs to wait and thus go back on a the wait queue.</p><p>[<a name="lockfn13">13</a>] While the ReaderWriterLockSlim handles things properly, the early version that Vance posted will throw an error on a simultaneous upgrade. This is technically another way to handle the upgrade problem :-).</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-3257292245398828856?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com23tag:blogger.com,1999:blog-6800934446457898793.post-89554313798705540012008-08-25T06:58:00.007-04:002008-09-01T17:07:22.361-04:00Meta-FizzBuzz<p>By itself, solving the "<a href="http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/" target="_blank">FizzBuzz</a>" problem won't get you a <a href="http://www.hanselman.com/blog/YouCantTeachHeightMeasuringProgrammerCompetenceViaFizzBuzz.aspx" target="_blank">new job</a>. If it does, you probably wouldn't want that job. It's a <a href="http://www.answers.com/weed+out&amp;r=67" target="_blank">weed out</a> type of question that <a href="http://www.codinghorror.com/blog/archives/000804.html" target="_blank">doesn't say much about your skill</a> if you get it right, but it <a href="http://www.codinghorror.com/blog/archives/000781.html" target="_blank">hurts your credibility as a programmer</a> if you can't do it. It asks: </p><blockquote><p>Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.</p></blockquote><p>By rearranging the words in the problem statement and adding a few programmer keywords, you can create this simple <a title="Inspired by deuseldorf's solution on the beta StackOverflow site" href="http://beta.stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem#856" target="_blank">pseudocode solution</a>:</p><pre style="font-family:consolas, courier new, courier, monospace;"><span style="color:#0000ff;">for every</span> number <span style="color:#0000ff;">from</span> 1 <span style="color:#0000ff;">to</span> 100 <br /> <span style="color:#0000ff;">if</span> the number <span style="color:#0000ff;">is</span> a multiple of 3 <span style="color:#0000ff;">and</span> it <span style="color:#0000ff;">is</span> a multiple of 5 <span style="color:#0000ff;">then</span><br /> <span style="color:#0000ff;">print</span> <span style="color:#006080;">"FizzBuzz"</span><br /> <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> it <span style="color:#0000ff;">is</span> a multiple of 3 <span style="color:#0000ff;">then</span><br /> <span style="color:#0000ff;">print</span> <span style="color:#006080;">"Fizz"</span><br /> <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> it <span style="color:#0000ff;">is</span> a multiple of 5 <span style="color:#0000ff;">then</span><br /> <span style="color:#0000ff;">print</span> <span style="color:#006080;">"Buzz"</span><br /> <span style="color:#0000ff;">else</span><br /> <span style="color:#0000ff;">print</span> the number</pre><p>See? Simple and boring.</p><p>But what if the bar were raised in the future to be this "Meta-FizzBuzz" problem: </p><blockquote><p>Create a <em>language implementation</em> and write a solution to the FizzBuzz problem using it.</p></blockquote><p>It sounds crazy at first, but if you take it seriously, it is way more interesting than the original FizzBuzz problem. It forces you to have a deeper understanding of languages rather than just getting by with the basics. It also shows that languages are full of many design choices that often have several alternatives.</p><p>I decided to create a language implementation that would execute the above "<a href="http://en.wikipedia.org/wiki/Pseudocode" target="_blank">pseudocode</a>" solution. While working on the implementation, I discovered that needed to handle cases that I hadn't seen in "real" languages:</p><ul><li>Variables can be prefixed by "the" to make the code more readable. </li><li>Instead of having a <a href="http://en.wikipedia.org/wiki/Modulo_operation" target="_blank">modulo operator</a> (e.g. %), I picked the phrase "is a multiple of". </li><li>This language supports the special "it" variable that always refers to the last variable that was explicitly referenced. </li><br /></ul><p>These were just arbitrary decisions that I made to make the actual FizzBuzz program easy to read. Even though I'm still in the early stages of the development of <a href="http://www.moserware.com/2008/07/building-object-oriented-parasitic.html" target="_blank">OMeta#</a>, it wasn't too difficult to write a complete "Meta-FizzBuzz" implementation in about 100 lines of code with generous use of comments and whitespace:</p><pre style="font-family:consolas, courier new, courier, monospace;"><span style="color:#0000ff;">ometa</span> <span style="color:#2b91af;">MetaFizzBuzz</span> : <span style="color:#2b91af;">Parser</span> {<br /> <span style="color:#008000;">// Basic literals come first:</span><br /><br /> <span style="color:#008000;">// We override the Parser's version of "Number" which returns a string</span><br /> <span style="color:#008000;">// to instead return the integer value of the string.</span><br /> Number ^= Spaces (<span style="color:#006080;">'+'</span> <span style="color:#006080;">'-'</span> Empty):prefix<br /> Digit+:ds -&gt; { <span style="color:#0000ff;">int</span>.Parse(((prefix.Count &gt; 0) ? prefix.As&lt;<span style="color:#0000ff;">string</span>&gt;() : <span style="color:#006080;">""</span>) + ds.As&lt;<span style="color:#0000ff;">string</span>&gt;()) },<br /><br /> <span style="color:#008000;">// Allow literal strings surrounded by quotes (e.g. "FizzBuzz")</span><br /> QuotedString = Spaces <span style="color:#006080;">'"'</span> (~<span style="color:#006080;">'"'</span> :c)*:inner <span style="color:#006080;">'"'</span> -&gt; { inner.Count == 0 ? <span style="color:#006080;">""</span> : inner.As&lt;<span style="color:#0000ff;">string</span>&gt;() },<br /><br /> <span style="color:#008000;">// For more natural sounding code, we allow "the" in front of a variable name.</span><br /> <span style="color:#008000;">// In addition, we keep track of the last variable name used so that we can refer to</span><br /> <span style="color:#008000;">// it as "it" later on.</span><br /> VariableName = ("the" Empty) Spaces<br /> FirstAndRest("Letter", "LetterOrDigit"):n<br /> !{ Set("_it", n.As&lt;<span style="color:#0000ff;">string</span>&gt;()) } -&gt; { n },<br /><br /> <span style="color:#008000;">// Expressions are functions that evaluate to some object.</span><br /> <span style="color:#008000;">// We don't return the value directly since expressions can depend on</span><br /> <span style="color:#008000;">// global variables that could be change while executing.</span><br /> Exp = AndExp<br /> BinExp<br /> NumExp <br /> QuotedString:qs -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;) (() =&gt; qs.As&lt;<span style="color:#0000ff;">string</span>&gt;()) },<br /><br /> <span style="color:#008000;">// An "and" expression is the highest level of a function that returns</span><br /> <span style="color:#008000;">// a boolean value. This left-recursive definition allows for an arbitrary</span><br /> <span style="color:#008000;">// number of boolean expressions to be and-ed together.</span><br /> AndExp = AndExp:l "and" BoolExp:r -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;)(<br /> () =&gt; (<br /> (<span style="color:#0000ff;">bool</span>)l.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()()<br /> &amp;&amp;<br /> (<span style="color:#0000ff;">bool</span>)r.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()()<br /> ))<br /> }<br /> BoolExp,<br /><br /> <span style="color:#008000;">// This rule looks at what the expression returns and then tries to</span><br /> <span style="color:#008000;">// convert non-boolean values by declaring that non-zero values and</span><br /> <span style="color:#008000;">// non-empty strings are true and everything else is false.</span><br /> BoolExp = Exp:e -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;)(<br /> () =&gt; {<br /> <span style="color:#0000ff;">object</span> o = e.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()();<br /> <span style="color:#0000ff;">return</span> o <span style="color:#0000ff;">is</span> <span style="color:#0000ff;">bool</span> ? (<span style="color:#0000ff;">bool</span>)o<br /> : o <span style="color:#0000ff;">is</span> <span style="color:#0000ff;">int</span> ? ((<span style="color:#0000ff;">int</span>)o) != 0<br /> : !<span style="color:#0000ff;">string</span>.IsNullOrEmpty(o as <span style="color:#0000ff;">string</span>) &amp;&amp; (o != <span style="color:#2b91af;">OMetaList</span>&lt;<span style="color:#2b91af;">HostExpression</span>&gt;.Nil);<br /> }) <br /> }, <br /><br /> <span style="color:#008000;">// Binary expressions take two arguments (left and right).</span><br /> <span style="color:#008000;">// Here we just have the one that is relevant to FizzBuzz</span><br /> BinExp = NumExp:left<br /> <span style="color:#006080;">"is" </span><span style="color:#006080;">"a"</span> <span style="color:#006080;">"multiple"</span> <span style="color:#006080;">"of"</span><br /> NumExp:right -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;)(<br /> () =&gt; {<br /> <span style="color:#0000ff;">var</span> l = (<span style="color:#0000ff;">int</span>)left.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()();<br /> <span style="color:#0000ff;">var</span> r = (<span style="color:#0000ff;">int</span>)right.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()();<br /> <span style="color:#0000ff;">return</span> (l%r) == 0;<br /> })<br /> }, <br /><br /> <span style="color:#008000;">// Number expressions are functions that just return an integer.</span><br /> <span style="color:#008000;">// Note that "it" resolves to the *value* of the variable that was last referenced by name.</span><br /> NumExp = Number:n -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;) (() =&gt; n.As&lt;<span style="color:#0000ff;">int</span>&gt;()) } <br /> <span style="color:#006080;">"it"</span> -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;) (() =&gt; Get&lt;<span style="color:#0000ff;">int</span>&gt;(Get&lt;<span style="color:#0000ff;">string</span>&gt;("_it"))) }<br /> VariableName:vn -&gt; { (<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;) (() =&gt; Get&lt;<span style="color:#0000ff;">int</span>&gt;(vn.As&lt;<span style="color:#0000ff;">string</span>&gt;())) },<br /> <br /> <span style="color:#008000;">// Statements are the things that actually do work in this language.</span><br /> Stmt = <span style="color:#006080;">"print"</span> Exp:e -&gt; { (<span style="color:#2b91af;">Action</span>) (() =&gt; { <span style="color:#2b91af;">Console</span>.WriteLine(e.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()()); }) } <br /> <span style="color:#006080;">"if"</span> AndExp:b <span style="color:#006080;">"then"</span> Stmt:t<br /> (<span style="color:#006080;">"else"</span> Stmt Empty):f -&gt; { (<span style="color:#2b91af;">Action</span>) (<br /> () =&gt; {<br /> <span style="color:#0000ff;">if</span>((<span style="color:#0000ff;">bool</span>)b.As&lt;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#0000ff;">object</span>&gt;&gt;()())<br /> t.As&lt;<span style="color:#2b91af;">Action</span>&gt;()();<br /> <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span>(f.Count &gt; 0)<br /> f.As&lt;<span style="color:#2b91af;">Action</span>&gt;()();<br /> })<br /> }<br /> <span style="color:#006080;">"for"</span> <span style="color:#006080;">"every"</span> VariableName:n <span style="color:#006080;">"from"</span><br /> Number:low <span style="color:#006080;">"to"</span> Number:high<br /> Stmt:s -&gt; { (<span style="color:#2b91af;">Action</span>) (<br /> () =&gt; {<br /> <span style="color:#0000ff;">int</span> lowerBound = low.As&lt;<span style="color:#0000ff;">int</span>&gt;();<br /> <span style="color:#0000ff;">int</span> upperBound = high.As&lt;<span style="color:#0000ff;">int</span>&gt;(); <br /> <span style="color:#0000ff;">string</span> iterationVar = n.As&lt;<span style="color:#0000ff;">string</span>&gt;();<br /> <span style="color:#2b91af;">Action</span> iterationStmt = s.As&lt;<span style="color:#2b91af;">Action</span>&gt;();<br /> <span style="color:#0000ff;">for</span>(<span style="color:#0000ff;">int</span> i = lowerBound; i &lt;= upperBound; i++)<br /> {<br /> Set(iterationVar, i);<br /> iterationStmt(); <br /> }<br /> })<br /> },<br /><br /> <span style="color:#008000;">// A "block" is zero or more statements.</span><br /> Block = Stmt*:s -&gt; { (<span style="color:#2b91af;">Action</span>) (<br /> () =&gt; {<br /> <span style="color:#0000ff;">foreach</span>(<span style="color:#0000ff;">var</span> currentStatement <span style="color:#0000ff;">in</span> s)<br /> {<br /> currentStatement.As&lt;<span style="color:#2b91af;">Action</span>&gt;()();<br /> }<br /> })<br /> },<br /> <br /> <span style="color:#008000;">// And finally, a "program" is just a series of statements, which is a "block"</span><br /> Program = Block<br />}</pre><p><strong>Full disclosure</strong>: It took some debugging to get this implementation to work right. </p><p>If I had been beamed into the future and had to write this solution on a whiteboard, I would have been a bit nervous that I wouldn't have gotten it right and would have taken noticeably more time than I now take to write a FizzBuzz solution.</p><p>In order to keep the code size down, I directly execute <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=348120&amp;changeSetId=16572" target="_blank">the "pseudocode"</a> rather than convert it to an <a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank">intermediate tree</a>. I also simplified things by making all variables in this language global. The <a href="http://www.codeplex.com/ometasharp/SourceControl/DirectoryView.aspx?SourcePath=%24%2fometasharp%2ftrunk&amp;changeSetId=16572" target="_blank">latest version of the source code</a> has a slightly <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=347832&amp;changeSetId=16572" target="_blank">more elaborate version of Meta-FizzBuzz</a> that also allows <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=348135&amp;changeSetId=16572" target="_blank">an alternative pseudocode implementation</a>. </p><p>The current implementation of <a href="http://www.codeplex.com/ometasharp" target="_blank">OMeta#</a> uses C# 3.0 as the <a href="http://www.moserware.com/2008/07/building-object-oriented-parasitic.html" target="_blank">host language</a>. This makes everything inside of the { }'s two to three times uglier and larger than it might have been if I had used a more dynamic host language like <a href="http://blogs.msdn.com/deepak/archive/2007/05/02/managed-jscript-is-availaible.aspx" target="_blank">JavaScript</a>, <a href="http://www.codeplex.com/IronPython" target="_blank">Python</a>, <a href="http://en.wikipedia.org/wiki/IronRuby" target="_blank">Ruby</a>, or possibly <a href="http://blogs.msdn.com/charlie/archive/2008/01/25/future-focus.aspx" target="_blank">C# 4.0</a>. As I mentioned in my <a href="http://www.moserware.com/2008/07/building-object-oriented-parasitic.html" target="_blank">last post</a>, my hope is that eventually I'll be able to use clever techniques to make the host code appear more dynamic even though it might need to be strongly typed.</p><p>In the end, the Meta-FizzBuzz problem is just a thought experiment to guess what the low bar might look like in the future. That is, a future where it's so easy to create a language that perfectly fits your problem that people actually do. As an industry, we're not there yet, but it's fun to dream of the <a href="http://www.vpri.org/pdf/steps_TR-2007-008.pdf" target="_blank">STEPS</a> needed to get there.</p><p><strong>Feedback:</strong> What do you think the low bar will be in an upcoming era of <a href="http://www.moserware.com/2008/04/towards-moores-law-software-part-3-of-3.html" target="_blank">Moore's Law Software</a>? What do you think of the Meta-FizzBuzz problem? Feel free to post your own solution (or outline of a path that you'd take towards a solution) in the comments. Comments are also encouraged about OMeta#'s current syntax in general.</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f08%2fmeta-fizzbuzz.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f08%2fmeta-fizzbuzz.html" border="0" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-8955431379870554001?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com14tag:blogger.com,1999:blog-6800934446457898793.post-62374091054829691352008-07-31T07:34:00.001-04:002008-12-11T00:09:54.072-05:00Building an Object-Oriented Parasitic Metalanguage<p>It's all about pattern matching. The rest is just details. </p><p>My <a href="http://www.moserware.com/2008/06/ometa-who-what-when-where-why.html" target="_blank">last post on OMeta#</a> focused on what it is and the vision I have for its future. Briefly, <a href="http://www.cs.ucla.edu/~awarth/ometa/" target="_blank">OMeta</a> is a new language that makes it easier to design programming languages in an <a href="http://en.wikipedia.org/wiki/Object_oriented" target="_blank">object-oriented</a> fashion using very few lines of quite readable code. <a href="http://www.codeplex.com/ometasharp" target="_blank">OMeta#</a> is my attempt to support OMeta on the <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">.NET runtime</a>. My main strategy has been to base its design off of <a href="http://www.cs.ucla.edu/~awarth/" target="_blank">Alessandro Warth</a>'s JavaScript implementation of <a href="http://jarrett.cs.ucla.edu/ometa-js/" target="_blank">OMeta/JS</a>. This post gets into the specifics of how I've done this so far, but my hope is that you might see some places where the design could use improvement and that you might be encouraged to leave a comment so that it could get better.</p><p><strong>High Level Design</strong></p><p>At its core, OMeta has a very simple design. The highest level of abstraction is a grammar. Here is a calculator grammar in the current implementation of OMeta#:</p><pre style="font-family:consolas, courier new, courier, monospace;"><span style="color:#0000ff;">ometa</span> <span style="color:#2b91af;">Calculator</span> <: <span style="color:#2b91af;">Parser</span> {<br /> Digit = Super((Digit)):d -> { d.ToDigit() },<br /> Number = Number:n Digit:d -> { n.As&lt;<span style="color:#0000ff;">int</span>&gt;() * 10 + d.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> Digit,<br /> AddExpr = AddExpr:x '+' MulExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() + y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> AddExpr:x '-' MulExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() - y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> MulExpr,<br /> MulExpr = MulExpr:x '*' PrimExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() * y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> MulExpr:x '/' PrimExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() / y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> PrimExpr,<br /> PrimExpr = '(' Expr:x ')' -&gt; { x }<br /> Number,<br /> Expr = AddExpr<br />} </pre><p>A grammar is composed of rules (which are sometimes referred to as "productions"). Both the grammar itself and the rules have the same form:</p><p><a href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SIkraxIzsvI/AAAAAAAAA0k/5GqUY3WfhEk/s1600-h/ruleapplication.png" target="_blank"><img src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SIkraxIzsvI/AAAAAAAAA0k/5GqUY3WfhEk/s400/ruleapplication.png" /></a> </p><p>Going into the rule is a list of things of the <em>input</em> type (here they're represented by red circles) and coming out on the right is a list of things of the <em>destination</em> type (represented by purple triangles). As you can see from the diagram, the output list can have lists inside of it. In the calculator grammar, the circles are individual characters and the output is a single integer. </p><p><strong>My "<a href="http://en.wikipedia.org/wiki/Greenspun" target="_blank">Ad Hoc, Informally-Specified, Bug-Ridden, Slow Implementation of Half of Common Lisp</a>"</strong></p><p>As an implementer of OMeta, you have to make several design choices. One of the first is how to represent grammars. Since OMeta is object-oriented, I decided that it made sense to represent grammars as a .NET class (a.k.a. "<a href="http://msdn.microsoft.com/en-us/library/system.type.aspx" target="_blank">Type</a>"). Grammars contain rules; the obvious choice for implementing rules is to use a <a href="http://msdn.microsoft.com/en-us/library/ms173114.aspx" target="_blank">method</a>. This especially makes sense because rules can refer to rules in their base grammar. For example, the above calculator grammar has a rule called "Digit" which captures a single <em>numeric</em> digit. The "Digit" rule applies the "Digit" rule in its base grammar (Parser) that simply captures a digit <em>character</em>. It does this by applying the special "Super" rule which will use the base grammar to apply the rule that is specified by an argument. Since rules are implemented as methods and rules can "override" their definition from their base grammar, it made sense to make rule methods "<a href="http://msdn.microsoft.com/en-us/library/aa645767(VS.90).aspx" target="_blank">virtual</a>."</p><p>Another important decision is how to represent data going into and out of a rule application. An easy choice is to represent the data in a <a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx" target="_blank">List&lt;T&gt;</a>. This works out well except for the small detail that lists can contain other lists. This nested list idea has been around for at least 50 years in <a href="http://en.wikipedia.org/wiki/Lisp_(programming_language)" target="_blank">LISP</a> and languages derived from it (like <a href="http://en.wikipedia.org/wiki/Scheme_(programming_language)" target="_blank">Scheme</a>). Since it has worked out fairly well in those languages, I <a href="http://www.youtube.com/watch?v=J0UjU0rtavE" target="_blank">stole</a> the idea of a LISP-like list in my <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264656&amp;changeSetId=15493" target="_blank">OMetaList&lt;TInput&gt;</a> class which is a list of other lists with a special case that makes lists of length 1 equivalent to the element itself.</p><p>These decisions get us started, but a problem comes up if you try to implement the <a href="http://en.wikipedia.org/wiki/Factorial" target="_blank">factorial</a> function using recursion in an OMeta grammar:</p><pre><span style="color:#0000ff;">ometa</span> <span style="color:#2b91af;">Factorial</span> {<br /> Fact 0 -&gt; { 1 },<br /> Fact :n ?(n.As&lt;<span style="color:#0000ff;">int</span>&gt;() &gt; 0) Fact((n.As&lt;<span style="color:#0000ff;">int</span>&gt;() - 1)):m -&gt; { n.As&lt;<span style="color:#0000ff;">int</span>&gt;() * m.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br />} </pre><p>If you look carefully at this grammar, you'll see that it only says two things:</p><ol><li>If the next element of input matches a 0, return 1 </li><li>If the next element of input is something greater than zero, store its value to "n" and then apply the "Fact" rule supplying it with the value of "n - 1" and capture that result to "m". Finally, return "n * m". </li><br /></ol><p>What might not be obvious at first is that any time you store something to a variable using an expression like ":n", the value stored must be of the destination type (e.g. a triangle in the diagram). This makes us need to update our mental model for how OMeta works. We need a place to store rule "arguments" which are already in the destination type. </p><p>One way of doing this is to create an argument stack that is separate from the rest of the input. Additionally, we'll need a place to store grammar-local variables as well as a place to remember previous results of rule applications for performance reasons. This gives us a much more complete picture of what really occurs:</p><p><a href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SIsm-B67IgI/AAAAAAAAA1g/Ody7RBndMGg/s1600-h/rullapplicationfromstack.png" target="_blank"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SIsm-B67IgI/AAAAAAAAA1g/Ody7RBndMGg/s400/rullapplicationfromstack.png" /></a> </p><p>When a rule needs to consume input, it will first attempt to grab pop an item from the argument stack. If the stack is empty, then next element from the input list can be read. </p><p>I decided to store all of these details into a single class which I call an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264658&amp;changeSetId=15493" target="_blank">OMetaStream&lt;TInput&gt;</a> which internally uses an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264656&amp;changeSetId=15493" target="_blank">OMetaList&lt;TInput&gt;</a> for input data and an OMetaList&lt;<a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=316963&amp;changeSetId=15493" target="_blank">HostExpression</a>&gt; for storing the argument stack. The arguments are actually stored in an <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=314607&amp;changeSetId=15493" target="_blank">OMetaProxyStream&lt;TInput&gt;</a> which inherits from <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264658&amp;changeSetId=15493" target="_blank">OMetaStream&lt;TInput&gt;</a>, but this is just an implementation detail.</p><p>With the major data structures out of the way, one important choice remaining is how to handle going down the wrong path. If you look at the calculator grammar, you'll see that the "AddExpr" rule can be of the form "x + y", <strong>or</strong> "x - y", <strong>or</strong> a "MulExpr".</p><p>How does OMeta know which one to take? It makes a <em>prioritized choice</em> by trying each of the alternatives in the order specified. If it discovers that it has gone down the wrong path (e.g. the next item from the input is a "-" instead of a "+"), it needs to backtrack and reset itself to the condition it was in before the bad choice and then try the next option. </p><p>There are two obvious ways of doing this. The first approach is to leverage runtime support by using exceptions. This is exactly what OMeta/JS does. Using exceptions has an advantage of making the generated code simpler because there is no explicit code to "unwind the stack" in case you go down a bad path. </p><p>Although it makes the code easier to read, I decided against using exceptions and instead chose to use methods that return a boolean value to indicate if they succeeded. I did this for two important reasons:</p><ol><li>.NET does a bit of extra work when an exception is thrown (e.g. getting a stack trace). Therefore, throwing an exception has a non-trivial performance penalty. </li><li>Rules have prioritized choice. This means that failing a single choice doesn't imply that the whole rule fails. Failing can be a very common occurrence (it's not <em>exceptional</em>) and this makes it very performance sensitive. </li></ol><p>Here's a small glimpse of what the generated code looks like for attempting to apply the "AddExpr" rule:</p><pre><span style="color:#2b91af;">OMetaList</span>&lt;<span style="color:#2b91af;">HostExpression</span>&gt; x;<br /><span style="color:#2b91af;">OMetaStream</span>&lt;<span style="color:#0000ff;">char</span>&gt; addExprOut;<br /><br /><span style="color:#0000ff;">if</span>(!MetaRules.Apply(AddExpr, inputStream2, <span style="color:#0000ff;">out</span> x, <span style="color:#0000ff;">out</span> addExprOut))<br />{<br /> <span style="color:#0000ff;">return</span> MetaRules.Fail(<span style="color:#0000ff;">out</span> result2, <span style="color:#0000ff;">out</span> modifiedStream2);<br />}</pre><p>In this case, AddExpr is the name of the rule which is implemented as a method. Data is read from the "inputStream2" which is an OMetaStream (where the red circles are characters). The resulting list is saved to the "x" variable and the modified stream is stored in "addExprOut". In order to make back-tracking easier, OMetaStreams are mostly <a href="http://en.wikipedia.org/wiki/Immutable_object" target="_blank">immutable</a>, which means that they can't change. Instead of updating the stream itself, you get a fresh copy of the stream that contains what the result would be. If you need to back track, you can simply ignore the rule application output. As a side benefit, it makes it slightly easier to debug since you don't have to worry about the <a href="http://www.moserware.com/2007/11/attack-of-mutations-or-why-we-do-we.html" target="_blank">mutations that could otherwise occur</a>.</p><p><strong>Parasitic?</strong></p><p><a href="http://en.wikipedia.org/wiki/Image:Female_Catolaccus_grandis_wasp.jpg" target="_blank"><img src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SIqMacuDOXI/AAAAAAAAA1M/Gq_7xwTI9Rs/s200/Female_Catolaccus_grandis_wasp.jpg" align="right" /></a>OMeta's <a href="http://www.cs.ucla.edu/~awarth/" target="_blank">creator</a> <a href="http://vpri.org/pipermail/ometa/2008-July/000051.html" target="_blank">likes to refer to OMeta as a "parasitic language"</a> because it doesn't exist on its own. It always lives on top of a "host language." This makes an implementation usually defined in terms of its host language. That's why there is "OMeta/<strong>JS</strong>" which uses JavaScript as a host language. Although my ultimate goal for OMeta# is to have the host language be any .NET language, I decided to use C# as my first host language. </p><p>One of the first issues that came up was trying to recognize what exactly is C# code. As you can see from examples in my <a href="http://www.moserware.com/2008/06/ometa-who-what-when-where-why.html" target="_blank">last post</a>, my first attempt was to pick a really ugly pattern that wouldn't occur in normal use. I picked two consecutive @ signs as in:</p><p>@@/*This is C#*/@@</p><p>It worked out well, but it had the downside that it was, well... <em>incredibly ugly</em>. I have since written <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328653&amp;changeSetId=15493" target="_blank">a rudimentary C# recognizer</a> written in OMeta# itself that is aware of strings and comments. The upside is that the syntax looks a little nicer:</p><p>{ /*This is C#*/ }</p><p>Using C# as the host language had several implications. The most challenging was working with C#'s static type system. This was both a blessing and a curse. On the one hand, I had to constantly think about where the data came from and where it was going. This forced me to actually understand the overall design better. On the other hand, I had to spend <em>so much time</em> thinking about it. Late-bound systems with dynamic typing such as Smalltalk and JavaScript remove the need for people to spend so much time doing this. </p><p>I'm optimistic that over time a lot of the stronger annoyances will go away. For example, the current syntax forces type identification as in:</p><pre>-&gt; { n.As&lt;<span style="color:#0000ff;">int</span>&gt;() * 10 + d.As&lt;<span style="color:#0000ff;">int</span>&gt;() }</pre><p>Where, OMeta/JS can just say:</p><pre>-&gt; { n * 10 + d }</pre><p>I'm not exactly sure how to do this yet. My initial guess is that I might be able to write some sort of <a href="http://herbsutter.wordpress.com/2008/06/20/type-inference-vs-staticdynamic-typing/" target="_blank">type inference</a> algorithm (preferably written in OMeta#) that could do a reasonable job. My current ideas are tied too closely with the specific host language and would require a bit of work to port them to other host languages like Visual Basic. Another approach is to implement one or more helper classes that could enable <a href="http://en.wikipedia.org/wiki/Duck_typing" target="_blank">duck typing</a> (e.g. if it looks like a certain type, walks like that type, and quacks like the type, it's <em>probably</em> that type).</p><p>Being able to have strong static typing internally while having a very clean syntax would be ideal (e.g. sort of like the C# 3.0 "<a href="http://msdn.microsoft.com/en-us/library/bb383973.aspx" target="_blank">var</a>" keyword). Static typing is usually harder to achieve, but if you can do it well, you get many benefits. C# designer <a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg" target="_blank">Anders Hejlsberg</a> said it well in a <a href="http://www.se-radio.net/podcast/2008-05/episode-97-interview-anders-hejlsberg" target="_blank">recent interview</a>:</p><blockquote><p>"I don't see a lot of downsides to static typing other than the fact that it may not be practical to put in place, <em>and it is harder to put in place</em> and therefore takes longer for us to get there with static typing, but once you <em>do</em> have static typing. I mean, gosh, you know, like hey -- the compiler is going to report the errors <em>before</em> the space shuttle flies instead of whilst it's flying, that's a good thing!" </p></blockquote><p>Another issue that came up was properly handling inheritance. It makes sense to use "virtual" methods for rules, but this also requires you to emit the "<a href="http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx" target="_blank">override</a>" directive to <a href="http://msdn.microsoft.com/en-us/library/04xcc4t1.aspx" target="_blank">avoid warnings</a>. <a href="http://msdn.microsoft.com/en-us/library/ms228459.aspx" target="_blank">Another warning</a> cropped up from my use of the "<a href="http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx" target="_blank">base</a>" keyword in the many delegates that makes it convenient from a code emission perspective, but frustrating from a verifiable security perspective. Both of these warning are being left for a latter phase.</p><p>Compiler issues were only one factor. The other significant piece was aesthetics. A notable number of rules yield specific lists as their result. C# doesn't <a href="http://msdn.microsoft.com/en-us/library/bb384062.aspx" target="_blank">quite</a> have a good, clean way of expressing an OMetaList (that is, a list of lists). In order to get around this, I created the "<a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328644&amp;changeSetId=15493" target="_blank">Sugar</a>" helper class which makes it slightly easier to write these lists. It's still far from perfect. Instead of having a nice way for expressing lists like that OMeta/JS:</p><pre>-&gt; ['add', x, y]</pre><p>You have to do this instead:</p><pre>-&gt; { <span style="color:#2b91af;">Sugar</span>.Cons("add", x, y) }</pre><p>This annoyance can probably be fixed by tricking the C# recognizer to act as if C# had a nice implicit way of expressing an OMetaList and then re-writing the expression to use the Sugar class.</p><p>Beyond C#, there is the "meta" "host language" which is the .NET <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">common language runtime</a> itself. For code to play nice on it, it should abide by the .NET <a href="http://blogs.msdn.com/kcwalina/archive/2008/04/09/FDGDigest.aspx" target="_blank">framework design guidelines</a> which dictate naming conventions and general practices. This had a parasitic effect in that it led me to name my rules after the naming guidelines for methods (e.g. they must be <a href="http://c2.com/cgi/wiki?PascalCase" target="_blank">PascalCased</a>). Thus, in OMeta# there is the "<strong>D</strong>igit" rule instead of the "<strong>d</strong>igit" rule. OMeta/JS opts to prefix metarule method names with an underscore to make them not collide with other rules. I also wanted to hide metarules so that people would have to try harder to do the wrong thing; the best I could come up with to convey this idea was to implement them using an <a href="http://msdn.microsoft.com/en-us/library/ms173157.aspx" target="_blank">explicit interface</a> exposed via a property (e.g. instead of "_apply", I have "MetaRules.Apply").</p><p><strong>Being a Contextual Packrat</strong></p><p>The last intriguing thing about OMeta is exactly how it implements parsing. It uses a technique called a <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar" target="_blank">Parsing Expression Grammar</a> (PEG) that <a href="http://www.bford.info/" target="_blank">Bryan Ford</a> <a href="http://www.bford.info/pub/lang/peg.pdf" target="_blank">introduced</a> in 2004. It's just a fancy way to say you support the following features: (The table comes from the OMeta <a href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf" target="_blank">paper</a>. I've also included how OMeta# implements them to prove its legitimacy):</p><table cellspacing="0" cellpadding="2" border="1"><tbody><tr><td valign="top"><strong>expression</strong></td><td valign="top"><strong>meaning</strong></td><td valign="top"><strong>OMeta# Function</strong></td></tr><tr><td valign="top"><em>e</em><sub>1</sub> <em>e</em><sub>2</sub></td><td valign="top">sequencing</td><td valign="top">Seq</td><br /></tr><tr><td valign="top"><em>e</em><sub>1</sub> <em>e</em><sub>2</sub></td><td valign="top"><em>prioritized</em> choice</td><td valign="top">MetaRules.Or</td><br /></tr><tr><td valign="top"><em>e</em><sup>*</sup></td><td valign="top">zero or more repetitions</td><td valign="top">MetaRules.Many</td></tr><tr><td align="top"><em>e</em><sup>+</sup></td><td valign="top">one or more repetitions (not essential)</td><td valign="top">MetaRules.Many1</td></tr><tr><td valign="top">~<em>e</em></td><td valign="top">negation</td><td valign="top">MetaRules.Not</td></tr><tr><br /><td valign="top">&lt;<em>p</em>&gt;</td><td valign="top">production application</td><br /><td valign="top">MetaRules.Apply</td></tr><tr><td valign="top">'x'</td><td valign="top">matches the character x</td><td valign="top">Exactly</td></tr><br /></tbody></table><br /><p>The most interesting aspect to me is the prioritized choice. This is in contrast to "<a href="http://en.wikipedia.org/wiki/Context-free_grammar" target="_blank">Context-Free Grammar</a>s" (CFGs) which are the traditional way of defining parsers. To highlight the difference, consider parsing this line of C/C++ code:</p><pre><span style="color:#0000ff;">if</span> (condition1) <span style="color:#0000ff;">if</span> (condition2) Statement1(); <span style="color:#0000ff;">else</span> Statement2();</pre><p>Is it the same as:</p><pre><span style="color:#0000ff;">if</span> (condition1)<br />{<br /> <span style="color:#0000ff;">if</span> (condition2)<br /> {<br /> Statement1();<br /> }<br /> <span style="color:#0000ff;">else</span><br /> {<br /> Statement2();<br /> }<br />}</pre><p>... or is it:</p><pre><span style="color:#0000ff;">if</span> (condition1)<br />{<br /> <span style="color:#0000ff;">if</span> (condition2)<br /> {<br /> Statement1();<br /> } <br />}<br /><span style="color:#0000ff;">else</span><br />{<br /> Statement2();<br />}</pre><p>This is the classic "<a href="http://en.wikipedia.org/wiki/Dangling_else" target="_blank">dangling else</a>" problem. Context Free Grammars usually have this problem because they are free of any context when they are parsing (surprise!). In these situations, you often have to rely on something besides the grammar itself to resolve these ambiguities. Parsing Expression Grammars don't have this type of problem because you specify explicitly which one to try first. The prioritized choice therefore avoids ambiguity. </p><p>In order to make the performance relatively in line with the size of the input, a technique of "<a href="http://en.wikipedia.org/wiki/Memoization" target="_blank">memoization</a>" is used. This means the parser remembers what it has done previously; it does this as a <a href="http://en.wikipedia.org/wiki/Space-time_tradeoff" target="_blank">space-time tradeoff</a>. Keeping all those previous values have given them the reputation of being a "<a href="http://pdos.csail.mit.edu/~baford/packrat/">packrat</a>" parser.</p><p>Let's say you have</p><pre> AddExpr = AddExpr:x '+' MulExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() + y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> AddExpr:x '-' MulExpr:y -&gt; { x.As&lt;<span style="color:#0000ff;">int</span>&gt;() - y.As&lt;<span style="color:#0000ff;">int</span>&gt;() }<br /> MulExpr</pre>and you try the first choice (AddExpr:x '+' MulExpr:y), but you get to where you're expecting a "+" and it isn't there. You'll notice that the second choice (AddExpr:x <strong>'-'</strong> MulExpr:y) repeats the first part (namely AddExpr:x). Instead of re-evaluating it, you can just retrieve the stored value that you remembered, or rather<em> memoized</em>.<br /><br /><p>Well, it's almost that simple. Note that the definition of an add expression (AddExpr) is <a href="http://en.wikipedia.org/wiki/Left_recursion" target="_blank">left-recursive</a>. This means that the left side is defined in terms of itself. A naïve implementation of the parser would try to evaluate "AddExpr" by applying the first choice which started with a AddExpr which would then cause it to try to apply AddExpr again and eventually cause a <a href="http://en.wikipedia.org/wiki/Stack_overflow" target="_blank">stack overflow</a>.</p><p>It's not a trivial problem to fix. In fact, the paper that introduced Parsing Expression Grammars said that left-recursion should be avoided since you can rewrite the rule to avoid left-recursion. This is unfortunate guidance because the rewritten rule sometimes loses the clarity that the left-recursive version of the rule had.</p><p>At the start of this year, a <a href="http://www.vpri.org/pdf/packrat_TR-2007-002.pdf" target="_blank">paper</a> came out showing a very clever trick that makes left recursion possible.</p><p>Say that we're parsing the expression "1+2+3" using the "AddExpr." At the start of the expression we look at our memoization table to see if we have a precomputed value for "AddExpr". Since it is our first time, we won't find anything. The first part of the trick is to immediately store the result of "Fail" as the memoized result for AddExpr when starting at offset 0. We do this <em>before</em> we attempt to apply the rule.</p><p>When the parser uses recursion and finds itself again asking for the value of "AddExpr" at position 0, it <em>will</em> find a result of "fail" and thus fail that choice. It will then continue down to "MulExpr" where it will eventually match "1". The second part of the trick is to treat this value of "1" for "AddExpr" at position 0 as a "seed parse." The parser will then attempt to "grow the seed<em>"</em> by starting over at the beginning of the input stream, but this time it will remember its previous successful match. This will cause it to match "1+2" for AddExpr and then start over again by growing the seed to finally match "1+2+3." </p><p>In hindsight, it's a very simple idea. However, I say that only after some serious debugging time where I kept finding problems in my poor implementation. Alas, the entire algorithm is implemented in only a few lines of code in the "MetaRules.Apply" function in <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264639&amp;changeSetId=15493" target="_blank">OMetaBase.cs</a>.</p><p>So there you have it, you now know all of the interesting ideas in OMeta#. </p><p><strong>Where is This Going?</strong></p><p>OMeta# is a hobby project that's been a labor of love for me. You might have already guessed that if you noticed that <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">most check-ins</a> occur late at night or on the weekends. It's been slow, but it's coming together. Probably the most exciting highlight in the development came when I got enough of OMeta# working that I could rewrite parts of itself in OMeta#. This has the benefit of being cool from a meta self-reproducing level, but it's also a bonus because the code becomes much more readable and introspective. For example, compare the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=315537&amp;changeSetId=15493" target="_blank">C# recognizer that I wrote by hand</a> to the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=328653&amp;changeSetId=15493" target="_blank">OMeta# grammar version</a> that implements the same idea. </p><p>This approach of writing more of OMeta# <em>in</em> OMeta# will continue. It's my hope that as much as possible will be written in itself. A significant next step would be to rewrite the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264619&amp;changeSetId=15493" target="_blank">code generator</a> as an OMeta# grammar. This isn't a new design idea. Each subsequent version of Smalltalk has been <a href="http://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29" target="_blank">bootstrapped</a> by its previous version. </p><p>I'll be the first to point out that there are a lot of rough edges to my current implementation. If you look around the <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">source code</a>, you'll see several comments labeled "// HACK" where I admit a hacked version of an idea. One of the most glaring problems is that debugging is annoyingly difficult. I haven't yet implemented an optimizer for the generated code which causes a lot of unnecessary metarule applications. The second annoyance is that just stepping into so many methods that fail often takes a long time. Over time, I hope to add better hints to get more traditional error messages that you get from good compilers so that you don't have to step through the generated code to debug a grammar. </p><p>As mentioned earlier, the language recognizer could use some work to make the syntax cleaner as well inferring types so that grammar writers don't have to explicitly declare them. I have confidence that the work that would go into a good C# host language implementation would directly port to other languages such as Visual Basic.</p><p>There's also a great need cross pollination with other projects such as the <a href="http://en.wikipedia.org/wiki/Dynamic_Language_Runtime" target="_blank">Dynamic Language Runtime</a> (DLR) which has already tackled some of the issues that OMeta# will face. Additionally, languages such as <a href="http://en.wikipedia.org/wiki/F_Sharp_programming_language" target="_blank">F#</a> have similar data structures already built-in that OMeta uses. <a href="http://en.wikipedia.org/wiki/Boo_(programming_language)" target="_blank">Boo</a> and <a href="http://en.wikipedia.org/wiki/Nemerle" target="_blank">Nemerle</a> have interesting extensibility points which could provide some good ideas. The problem for me is that there is so many different places to look. It'd be great if you know these languages (or others) and could tell me via a comment or better yet, by sending code of how they could help OMeta#. </p><p>As of right now, I plan on keeping the core functionality in C# rather than rewriting everything in another language or by using the DLR. The main reason is that C# is wide-spread in availability, both on .NET as well as on <a href="http://en.wikipedia.org/wiki/Mono_(software)" target="_blank">Mono</a>. A second reason is that I would like to keep the outside dependencies on OMeta# as small as possible.</p><p>OMeta is a beautiful in the same sense that mathematics can have a simple beauty. LISP has been referred to by some as "<a href="http://bc.tech.coop/blog/060224.html" target="_blank">The Most Important Idea in Computer Science</a>" largely because its core ideas could be expressed on a half page of the <a href="http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf" target="_blank">LISP 1.5 manual</a> (page 13 to be exact). This elegance is similar to mathematics of <a href="http://en.wikipedia.org/wiki/Maxwell" target="_blank">Maxwell's Equations</a> describing electromagnetism. </p><p>It's my hope that I won't mess up the implementation to the point where this elegant beauty is lost. Currently it's way too ugly. I see some of the rough edges, but I'm sure you can help me discover others along with how to fix them. If this post sounds too complicated, it's not you, it's me. Let me know if something doesn't make sense and I'll try to provide clarification. </p><p>If you're interested in OMeta#, I highly encourage you to <a href="http://www.codeplex.com/ometasharp/SourceControl/ListDownloadableCommits.aspx" target="_blank">download the latest version of the source code</a> <a href="http://www.codeplex.com/ometasharp/" target="_blank">from CodePlex</a> and step through the <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=309791&amp;changeSetId=15493" target="_blank">unit test runner</a> to see things get built up. </p><p>If you can, keep notes of all the places where you see me doing something and let me know about them either through comments or via email. In addition, I also highly recommend experimenting Alessandro Warth's great <a href="http://jarrett.cs.ucla.edu/ometa-js/" target="_blank">OMeta/JS</a> implementation via your web browser.</p><p>Happy OMeta-ing!</p><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f07%2fbuilding-object-oriented-parasitic.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f07%2fbuilding-object-oriented-parasitic.html" border="0" alt="kick it on DotNetKicks.com" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-6237409105482969135?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com16tag:blogger.com,1999:blog-6800934446457898793.post-22911912401008727452008-06-24T00:36:00.003-04:002008-12-11T00:09:57.340-05:00OMeta#: Who? What? When? Where? Why?<p id="vyfd">What if programming language <i id="vyfd0">implementations</i> were <a id="vyfd1" href="http://en.wikipedia.org/wiki/Object_oriented">object-oriented</a>? What if you wanted to change one <i id="vyfd2"><a id="vyfd3" href="http://www.answers.com/itty-bitty&amp;r=67">itty-bitty</a></i> part of your favorite language? Say you wanted to add an <a href="http://en.wikipedia.org/wiki/Exponentiation" target="_blank">exponentiation operator</a> (^^). How hard would it be? </p><p id="vyfd4">Wouldn't it be nice if you could "subclass" a language like C# and then add 5 lines of code to make it work and then use it? What if you could add Ruby-like <a id="vyfd5" href="http://www.thirdbit.net/articles/2007/08/01/10-things-you-should-know-about-method_missing/">method_missing</a> support in 20 lines?</p><p id="vyfd6">What if you could conceive of a new language and start experimenting with it in production code in an hour? What if it leveraged your knowledge of existing frameworks like .NET?</p><p>Let's imagine that it were possible. Let's say someone else created a basic calculator-like "language":</p><p id="vyfd8"><a id="vyfd9" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF6vVA8OTdI/AAAAAAAAAd8/01EO7B9Wwa4/s1600-h/OMetaBasicCalc.png"><img id="vyfd10" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF6vVA8OTdI/AAAAAAAAAd8/01EO7B9Wwa4/s400/OMetaBasicCalc.png" /></a> </p><p id="vyfd11">Even without knowing the syntax, you can probably figure out how it works since it's written very close to the <a id="vyfd12" href="http://en.wikipedia.org/wiki/Backus-Naur_form">standard way</a> of describing a language. If you give this language "3*4", it will respond with 12. If you give it "2^(3*4)", it'd respond with a nice syntax error message like "I don't know how to deal with the '^' symbol. Sorry!"</p><p id="vyfd13">But you could make it work by writing this object-oriented-like "subclass" of the language:</p><p id="vyfd14"><a id="vyfd15" href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SF6vy_-ii9I/AAAAAAAAAeE/FmgnCNZG-b8/s1600-h/OMetaExponentCalc.png"><img id="vyfd16" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SF6vy_-ii9I/AAAAAAAAAeE/FmgnCNZG-b8/s400/OMetaExponentCalc.png" /></a> </p><p id="vyfd17">Now, giving this language "2^(3*4)" happily gives you 4096.</p><p id="vyfd18">This worked using simple inheritance. What if you wanted to compose your language from several other languages? That is, something like "<a id="vyfd19" href="http://en.wikipedia.org/wiki/Multiple_inheritance">multiple inheritance</a>" but without <a href="http://en.wikipedia.org/wiki/Multiple_inheritance#Criticisms" target="_blank">its problems</a>? What if we took a simpler approach and allowed a language to attempt to match elements of any other language?</p><p id="vyfd20">Let's say we want to build a scientific calculator that leverages some of the work we've already done. Instead of inheriting from it, we'll call out to it:</p><p id="vyfd21"><a id="vyfd22" href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SF6xI_7m1oI/AAAAAAAAAeM/IxwyBfXGdYU/s1600-h/OMetaScientificCalc.png"><img id="vyfd23" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SF6xI_7m1oI/AAAAAAAAAeM/IxwyBfXGdYU/s400/OMetaScientificCalc.png" /></a> </p><p id="vyfd24">Now you can calculate expressions like "sqrt (1+2^3)!"</p><p id="vyfd25">What if such a <i id="vyfd26">meta</i> language (e.g. a language for describing other languages) existed? What would you do with it? How might it help you <a id="vyfd27" href="http://www.joelonsoftware.com/articles/GuerrillaInterviewing3.html">get things</a> <a id="vyfd28" href="http://steve-yegge.blogspot.com/2008/06/done-and-gets-things-smart.html">done</a> while producing extremely small, but very <i id="vyfd29">readable</i> code? What if creating a new language that <i id="vyfd30">perfectly fit</i> a problem your software was trying to solve was as easy as writing a simple <a id="vyfd31" href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a>? </p><p id="vyfd32">What if you could get all the whiz-bang, gotta-have tool support like <a id="vyfd33" href="http://en.wikipedia.org/wiki/Syntax_highlighting">syntax highlighting</a>, <a id="vyfd34" href="http://en.wikipedia.org/wiki/Debugging">interactive debugging</a>, and a <a id="vyfd35" href="http://en.wikipedia.org/wiki/Compiler">compiler</a> for it came at almost no extra cost? What if the barrier to entry for a new language was so low, that almost anyone could do it quickly?</p><p>This is what I've been thinking about for the past month or so. </p><p id="vyfd37"><b id="vyfd38">Who? &amp; What?</b></p><p id="vyfd39">When I was doing some research for my "<a id="vyfd40" href="http://www.moserware.com/2008/04/towards-moores-law-software-part-3-of-3.html">Towards Moore's Law Software</a>" series, I came across a very interesting language called <a id="vyfd41" href="http://www.cs.ucla.edu/~awarth/ometa/">OMeta</a> which was created by <a id="vyfd42" href="http://www.cs.ucla.edu/~awarth/">Alessandro Warth</a> and <a id="vyfd43" href="http://piumarta.com/cv/bio.html">Ian Piumarta</a> with some inspiration from <a id="vyfd44" href="http://en.wikipedia.org/wiki/Alan_Kay">Alan Kay</a>. In their <a id="vyfd45" href="http://www.oopsla.org/oopsla2007/index.php?page=lds">2007 Dynamic Languages Symposium</a> <a id="vyfd46" href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf">paper</a>, the authors described OMeta as</p><blockquote id="vyfd47"><p id="vyfd48">".. a new object-oriented language for pattern matching. OMeta is based on a variant of <a id="vyfd49" href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">Parsing Expression Grammars</a> (PEGs) —a recognition based foundation for describing syntax—which we have extended to handle arbitrary kinds of data. We show that OMeta’s general-purpose pattern matching provides a natural and convenient way for programmers to implement tokenizers, parsers, visitors, and tree transformers, all of which can be extended in interesting ways using familiar object-oriented mechanisms. This makes OMeta particularly well-suited as a medium for experimenting with new designs for programming languages and extensions to existing languages."</p></blockquote><p id="vyfd52">To be honest, I didn't really understand the paper when I first read it. It sounded cool, but it used a few new terms I hadn't heard of before. However, I couldn't help but be fascinated by OMeta's <em>readable</em> syntax. OMeta doesn't try to solve every problem involved with writing a complete program. It makes no claims about being a good general purpose programming language. But it <a id="vyfd53" href="http://en.wikipedia.org/wiki/Positioning_(marketing)">positions</a> itself by doing just one thing really well:</p><p id="vyfd54">Pattern matching. </p><p id="vyfd55">If you look at modern programming languages that are good for developing <em>other</em> languages, you'll notice that they usually have good pattern matching capabilities. For example, in <a id="vyfd56" href="http://en.wikipedia.org/wiki/ML_programming_language">ML</a> (which stands for meta-language), you can specify functions in terms of patterns. Here's how you can reverse a list:</p><p id="vyfd57"><a id="vyfd58" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF7a73YbceI/AAAAAAAAAeU/WHRZnc3Wwno/s1600-h/MLReverse.png"><img id="vyfd59" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF7a73YbceI/AAAAAAAAAeU/WHRZnc3Wwno/s400/MLReverse.png" /></a> </p><p id="vyfd60">This defines the <b id="vyfd61">fun</b>ction named "reverse." When it sees the "pattern" where the function is called with an empty list (nil), it just returns nil. However, when the function is passed in a list whose first element is "x" and the rest of the list is "xs", it will return the reverse of the rest of the list and then append the head of the list to the end. </p><p>If you think about it for a second, it's a really compact way of expressing how to reverse a list.</p><p id="vyfd62"><b id="vyfd63">Streams of <i id="vyfd64">Anything</i></b></p><p id="vyfd65">What I find interesting about OMeta is <i id="vyfd66">how</i> it matches patterns. OMeta can operate on a stream of <i id="vyfd67">anything</i>. This is useful because modern language implementations have several phases that work on different types of "things." Here's a simplified view of what a <a id="vyfd68" href="http://en.wikipedia.org/wiki/Compiler">compiler</a> does:</p><p id="vyfd69"><a id="vyfd70" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF7jgB5evZI/AAAAAAAAAec/wfMLpzDyejg/s1600-h/CompilerPhases.png"><img id="vyfd71" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF7jgB5evZI/AAAAAAAAAec/wfMLpzDyejg/s400/CompilerPhases.png" /></a> </p><p id="vyfd72">At the start of the process, you're working with individual characters from source code. The list of characters is converted to tokens by use of a scanner. This is how the characters 'i', 'n', and 't' become the "INT" token. The next phase combines tokens together to form a higher level view of the program, typically using a <a id="vyfd73" href="http://en.wikipedia.org/wiki/Tree_data_structure">tree data structure</a>. From that phase, several intermediate steps occur on the program (almost always in tree form), until it's finally pulled apart to make an executable program.</p><p id="vyfd74">Often, you have to use different tools at each phase. You might use <a id="vyfd75" href="http://en.wikipedia.org/wiki/Lex_programming_tool">lex</a> for the scanner (aka "<strong>lex</strong>er"), <a id="vyfd76" href="http://en.wikipedia.org/wiki/Yacc">Yacc</a> for the parser, and some sort of <a id="vyfd77" href="http://en.wikipedia.org/wiki/Visitor_pattern">visitor pattern</a> in your implementation language (e.g. C#) for many of the intermediate phases. With all of these different tools to learn, it's no wonder why most people don't even bother trying to create their own language. </p><p id="vyfd78">OMeta is different in that lets you use the same syntax for all phases. The only thing that is different is <i id="vyfd79">what</i> the input stream contains. At the start, the input stream is characters. In subsequent phases, it tokens, then trees, and then finally you produce your intended result. At each pass, your OMeta code has similar syntax.</p><p id="vyfd80"><b id="vyfd81">Passing the Match Around</b></p><p id="vyfd82">Another interesting bit about OMeta is how it goes about <em>finding </em>rules. Rules are defined in grammars which behave like classes in an object-oriented language. A grammar can "inherit" from another grammar. An added twist is that a grammar can call out to a "foreign" grammar. This makes it easier to build a language from many different reusable parts and allows for trivial "mashups" of several languages. </p><p>Additionally, if a rule has multiple "choices," then OMeta always tries to match the first choice, then the second, and so on until it achieves success. Although this seems obvious in hindsight, most parsers <a id="vyfd84" href="http://en.wikipedia.org/wiki/Context-free_grammar">don't have prioritized choices</a> and thus they make it easy to define ambiguous rules. For example, is "1-2-3" equal to "(1-2)-3" = -4 or "1-(2-3)" = 2? With prioritized choice, you make this explicit. If it successfully parses, then it has exactly one choice and therefore no ambiguities.</p><p id="vyfd85">The last really interesting aspect of OMeta's design is what it does when it matches a pattern. A pattern might consist of several sub-components. Each of these components (e.g. rules) can be captured into a variable. OMeta then feeds these variables into a "host" language. </p><p id="vyfd86"><a id="vyfd87" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF77O9LL3_I/AAAAAAAAAek/cs7N1F0qIlM/s1600-h/OMetaRuleDecomposition.png"><img id="vyfd88" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF77O9LL3_I/AAAAAAAAAek/cs7N1F0qIlM/s400/OMetaRuleDecomposition.png" /></a> </p><p id="vyfd89">OMeta <i id="vyfd90">doesn't care</i> what the host language is. It can be just about any language (e.g. JavaScript, LISP, C++, etc.). Typically, the host language is what the OMeta implementation itself was written in. The host language is free to do whatever it likes with the variables. OMeta is only responsible for getting them there. The <a id="vyfd91" href="http://www.cs.ucla.edu/~awarth/papers/dls07.pdf">OMeta paper</a> describes an implementation where the host language is <a id="vyfd92" href="http://piumarta.com/software/cola/">cola</a>. Other early versions were written in <a id="vyfd93" href="http://en.wikipedia.org/wiki/Squeak">Squeak</a> and use that as the host language. </p><p id="vyfd94">Alessandro has recently created a <a href="http://jarrett.cs.ucla.edu/ometa-js/#OMeta_Tutorial" target="_blank">JavaScript version</a> where you experiment with OMeta/JS (e.g. <b id="vyfd95">J</b>ava<b id="vyfd96">S</b>cript is the host language) in your browser. It's a very interesting playground. Some of the demonstrations range from the basic calculator language, to a type checker, to LISP, to even the OMeta compiler and code generator <i id="vyfd98">itself</i> and all of them are written in OMeta/JS. The playground website is neat to use because it shows the translated (generated) JavaScript code for the grammar (although the generated code needs to be put through a <a id="vyfd99" href="http://www.prettyprinter.de/">pretty printer</a> to make any sense of it).</p><p id="vyfd100"><b id="vyfd101">Why t</b><b id="vyfd102">he "#" in OMeta#?</b></p><p id="hdj2">After understanding the basics of OMeta/JS, I thought it would be interesting to have the host language be <i id="vyfd106">any</i> .NET language. I started to sketch out what this might look like by using my limited JavaScript ability and translating Alessandro's code to an equivalent functionality in C#. The result was the start of a project that needed a name. "OMeta#" seemed to fit the bill. </p><p id="hdj20">Besides, it just sounded better than other .NET-ism alternatives like "NOMeta", "OMeta.net", or "IronOMeta."</p><p id="z4y-">Some might ask, "Why .NET?" A subtle reason is that OMeta is useful for code generation. Code generation is a normal part of the .NET ecosystem even if people don't realize it. When people use the graphical designer in <a id="y4jg" title="Windows Forms" href="http://en.wikipedia.org/wiki/Windows_Forms">Windows Forms</a>, there is a code generator working behind the scenes writing code for their host language (typically C# or Visual Basic). When people write <a href="http://en.wikipedia.org/wiki/ASP.NET" target="_blank">ASP.NET</a> ".aspx" files, there is a hidden process that takes that HTML-like "language" and <a id="hdj21" href="http://msdn.microsoft.com/en-us/library/ms366723.aspx">compiles it</a> to a real DLL.</p><p id="l6wj">For example, ASP.NET transforms this:</p><p id="hdj22"><a id="hdj23" href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SGB9x23PQnI/AAAAAAAAAgM/c1Sb6qTEAoU/s1600-h/AspNetHelloWorldAspx.png"><img id="hdj24" style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" alt="AspNetHelloWorldAspx" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SGB9x23PQnI/AAAAAAAAAgM/c1Sb6qTEAoU/s400/AspNetHelloWorldAspx.png" /></a> </p><p id="hdj25">Into this generated code:</p><p id="hdj26"><a id="hdj27" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF-nnXKgxQI/AAAAAAAAAfE/E2sbgLZYr6M/s1600-h/AspNetHelloWorldGenerated.png"><img id="hdj28" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF-nnXKgxQI/AAAAAAAAAfE/E2sbgLZYr6M/s400/AspNetHelloWorldGenerated.png" /></a> </p><p id="hdj29">I wanted to bring a similar "it just works" illusion to the .NET world with OMeta#.<a id="vyfd104" title="'Footsteps @ Porthleven' by Darren Copley" href="http://www.flickr.com/photos/97607362@N00/1102203511/" target="_blank"><img id="vyfd105" style="MARGIN: 5px 0px 5px 10px" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SF8On2eKQpI/AAAAAAAAAes/bndJjsBOEhg/s400/Footsteps.jpg" align="right" /></a></p><p id="vyfd107">With the encouragement of <a id="hdj210" href="http://www.cs.ucla.edu/~awarth/">Alessandro</a>, I started working on some of the supporting "goo" that would be required to get OMeta working on the .NET's <a href="http://en.wikipedia.org/wiki/Common_Language_Runtime" target="_blank">Common Language Runtime</a> (CLR). This isn't trivial because the CLR has stricter type system than languages like JavaScript. Also, since I chose C# as the implementation language, I had to make sure that the code passed all of the static type checking it performs at compile time. It's been a slow start, but I have been able to make a few steps towards making it work.</p><p id="vyfd111">One pragmatic question is why even bother adding another language, or rather, meta-language to the .NET world? Why not just get proficient at another toolset that is decent at creating language like <a id="vyfd112" href="http://www.antlr.org/" target="_blank">ANTLR</a>, <a id="vyfd113" href="http://www.codeplex.com/irony" target="_blank">Irony</a>, <a id="vyfd114" href="http://jparsec.codehaus.org/NParsec+Tutorial" target="_blank">NParsec</a>, or <a id="vyfd115" href="http://en.wikipedia.org/wiki/IronRuby" target="_blank">IronRuby</a>? What about using <a id="vyfd116" href="http://langnetsymposium.com/talks/3-03%20-%20Parsing%20Expression%20Grammars%20in%20FSharp%20-%20Harry%20Pierson.html" target="_blank">Parsing Expression Grammars in F#</a> or <a id="vyfd117" href="http://www.manning.com/rahien/" target="_blank">writing Domain Specific Languages in Boo</a> with its extensible compiler pipeline?</p><p>Ultimately, all of those tools are pretty good, but none of them did exactly what I was looking for. Some came close, but none of them seem capable of matching OMeta's power and simplicity.</p><p>Another reason was that I knew that writing an implementation of OMeta from the ground up would really help me "<a id="vyfd120" href="http://compsci.ca/blog/you-dont-know-that-programming-language/">know</a>" how it works. </p><p>More importantly, I thought it would be <em>fun</em> to work on. I'm not a language expert. I'll never reach the level of someone like <a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg" target="_blank">Anders</a>, but I was one of those odd kids that actually liked my compilers and programming languages classes. I also enjoyed <a id="vyfd121" href="http://www.langnetsymposium.com/talks.asp" target="_blank">the talks</a> from this year's <a id="vyfd122" href="http://www.langnetsymposium.com/" target="_blank">Lang.NET symposium</a> (even if I didn't understand a lot of things).</p><p id="vyfd126"><b id="vyfd127">The Grand OMeta# Vision</b></p><p id="vyfd128">The grand vision for OMeta# is to make it <i id="hdj211"><b id="hdj212">really simple</b></i> to create languages that "just work." It probably won't have the world's best performance, but it should be decent enough for almost all practical applications. It would be neat to have OMeta# (or something like it) be used to do the following:</p><ol id="vyfd130"><li id="vyfd132"><strong>Serve as a common, unified way for developing languages on the .NET platform</strong> — There are many helpful, yet often different "tools" out there for various stages of language design. I mentioned a few earlier, but some of the more advanced ones include the new <a href="http://en.wikipedia.org/wiki/Dynamic_Language_Runtime" target="_blank">Dynamic Language Runtime</a> (DLR) and <a href="http://en.wikipedia.org/wiki/Phoenix_(compiler_framework)" target="_blank">Phoenix compiler framework</a>. It would be neat to have a language that abstracted away some of these tools into a clean syntax like OMeta. That way, you'd get the benefit of these tools without having to constantly learn different ways of manipulating the concepts that can be expressed simply. </li><br /><li><strong>Factor out the "goo" of language development</strong> — For a language to be taken seriously, it has to have things like syntax highlighting, interactive debugging, and a decent compiler. Each of these takes time to implement and often involves a high learning curve. It would be great if you could just make some minor annotations to your OMeta grammar and then these features would "just work." </li><br /><li id="vyfd134"><strong>Useful for teaching</strong> — One of my favorite textbooks in college was "Programming Languages: An Interpreter-Based Approach" by <a href="http://www.eecs.harvard.edu/~nr/" target="_blank">Ramsey</a> (et. al.). Our class used a "draft" version of it (and it still hasn't been published yet). It took a very interesting approach towards teaching programming languages. In order to understand a language like <a href="http://en.wikipedia.org/wiki/Scheme_(programming_language)" target="_blank">Scheme</a>, you had to implement an interpreter for it in C or ML. I really liked this approach because getting your hands dirty with implementing the language typically leads to a better understanding of it. I would love to have the ability to implement this type of approach in something like OMeta. You could understand the essence of a language by only having to understand a page or two of code. It would also let you learn by experimenting with adding small features to existing languages. </li><br /><li id="vyfd135"><strong>Practical for production use</strong> — For anything to really succeed at moving <a href="http://www.moserware.com/2008/04/towards-moores-law-software-part-1-of-3.html" target="_blank">towards a Moore's Law increase in expressiveness</a>, it has to have reasonable quality. I can imagine OMeta# being introduced into real production projects by first integrating a small amount of OMeta's "generated" a project and then over time implementing more and more parts of the application in this highly specific language. For this to occur, it has to be reliable and simple to use. </li><br /></ol><p id="vyfd136"><b id="vyfd137">When? Where? </b></p><p id="vyfd138">All of the parts of the vision are still in the future. To make them a reality will require more than just a single person or even a couple of people. I'm <strike>naïve</strike> crazy enough to think that it's actually possible. In an effort not to "<a id="vyfd140" href="http://www.codinghorror.com/blog/archives/001134.html" target="_blank">go dark</a>," I've decided to be fairly open about the design and implementation of OMeta#. The current state of the code isn't even alpha quality yet. Despite all of these shortcomings, I've <a href="http://www.codeplex.com/ometasharp">posted what I have so far on CodePlex</a> and will continue to make updates to it. </p><p>Keeping in the tradition of other OMeta implementations, I've licensed it under the <a href="http://en.wikipedia.org/wiki/MIT_License" target="_blank">MIT License</a> so that you can use, experiment, play, and modify it without any licensing concerns.</p><p id="vyfd141">The first interesting result is that I've been able to get a complete end to end demo working for an extremely simple grammar that matches numbers. I fed this input grammar written in OMeta/C#:</p><p><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SGBI_NbgBMI/AAAAAAAAAf8/v1D6MAm1G_8/s1600-h/OMetaCSBootstrappedNumberParser.png" target="_blank"><img src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SGBI_NbgBMI/AAAAAAAAAf8/v1D6MAm1G_8/s400/OMetaCSBootstrappedNumberParser.png" /></a> </p><p>into my OMeta compiler/translator and successfully had it generate <a href="http://www.codeplex.com/ometasharp/SourceControl/FileView.aspx?itemId=264623&amp;changeSetId=12094" target="_blank">this output C# file</a>.</p><p id="vyfd143">There is still a ton of work left. It's quite possible that some of the design decisions I've made so far need to be challenged and redesigned. I'd love to get feedback from anyone that's interested.</p><p>What do you think? Do you think OMeta fills a unique niche? Do you think it would be useful to have as a tool in .NET? Would you want to help out making "The Grand OMeta# Vision" happen? If so, what parts can you help out with?</p><p id="vyfd144">I'm curious to hear your thoughts. In my next post, I hope to cover some of the technical details for how my current implementation works "under the covers."</p><p>P.S. Many thanks to Alessandro Warth for creating this beautiful language and helping me get started!</p><br /><br /><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f06%2fometa-who-what-when-where-why.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f06%2fometa-who-what-when-where-why.html" border="0" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-2291191240100872745?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com25tag:blogger.com,1999:blog-6800934446457898793.post-2517160165828837802008-05-21T22:00:00.002-04:002009-06-18T09:45:03.002-04:00Who Is This "Licklider" Guy?<center id="gw771"><a id="gw772" href="http://en.wikipedia.org/wiki/J._C._R._Licklider"><img id="gw773" style="margin: 0px 10px 10px 0px;" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SC7TdNj-vLI/AAAAAAAAAcM/bG1E5KuW-9k/s400/J__C__R__Licklider.jpg" /></a></center><p id="gw775"><i id="pn7n0">Who are they talking about? </i><i id="pn7n1">Why haven't I ever heard of him?</i></p><p id="gw777">I was at <a id="gw778" href="http://www.sri.com/">SRI</a>, a research institute by the <a id="gw779" href="http://www.stanford.edu/">Stanford</a> campus. Around me was a lively group of some of the best minds in Computer Science, some of them have had their PhDs in the field for 40 <i>years</i>. I had the honor of being the <i id="pn7n2">least</i> credentialed person in the room. As I listened to some of the discussions, I noticed that they seemed to keep bringing up the name "<a id="gw7712" href="http://en.wikipedia.org/wiki/J._C._R._Licklider">Licklider</a>." Sometimes they'd just call him "Lick." Other times they'd mention projects along with his name that I hadn't heard about before like "<a id="gw7713" href="http://en.wikipedia.org/wiki/Project_MAC">Project MAC</a>." Since the guys talked so much about him, I knew I had to find out more about who this "Lick" guy was. One of them suggested that I read the book <a id="gw7714" href="http://www.amazon.com/Dream-Machine-Licklider-Revolution-Computing/dp/0670899763/ref=ed_oe_h">"The Dream Machine: J.C.R. Licklider and the Revolution That Made Computing Personal</a>" by <a id="gw7715" href="http://mmwaldrop.com/">M. Mitchell Waldrop</a>. <a id="gw7716" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SC8yu9j-vMI/AAAAAAAAAcU/kCOiBRWJ_lw/s1600-h/EyesOverTheDreamMachine.JPG"><img id="gw7717" style="margin: 5px 0px 10px 5px;" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SC8yu9j-vMI/AAAAAAAAAcU/kCOiBRWJ_lw/s320/EyesOverTheDreamMachine.JPG" align="right" /></a></p><p id="gw7718">My local library had the book. I was a bit worried when I saw that it hadn't been checked out for three years. "Hmm... maybe it's not that good?" I thought. </p><p id="gw7719">I was pleasantly surprised.</p><p id="gw7720">At about 500 pages, it's not a small book. Fortunately, I was able to finish it just before the library forced me to return it since I hit the maximum amount of renewals on it. </p><p id="gw7721">The book put me on a journey that filled in a lot of details about computing history that I didn't even know I was clueless about while weaving a story about a man from Missouri. Although his full name was Joseph Carl Robnett Licklider, just about everyone called him "Lick," a name he acquired in his fraternity days. </p><p id="gw7723">Lick's story is bigger than just one guy. It's a story that goes back to the dawn of computing right up to the personal computer. While reading the book, I had a lot of "Aha!" moments that helped fill me into the colorful history of computing. For example, I had heard a lot about <a id="gw7724" href="http://en.wikipedia.org/wiki/Digital_Equipment_Corporation">DEC</a>'s <a id="gw7725" href="http://en.wikipedia.org/wiki/Programmed_Data_Processor">PDP</a> system, but it was interesting to know that they were specifically called "Programmed Data Processors" instead of "computers" because congress was pressured not to spend any more money on computers at the time. By itself, facts like these seem to be obscure trivia, but when you read about the politics of funding at the time, you can really understand that DEC had few alternatives.</p><p id="gw7726">I can't recall ever hearing Licklider's name before that meeting at SRI, but that's probably because I didn't try too hard. As a kid interested in computers growing up in the 1990's, I really focused my attention on learning about one person - <a id="gw7727" href="http://en.wikipedia.org/wiki/Bill_Gates">Bill Gates</a>. I read <a id="gw7728" href="http://www.amazon.com/Hard-Drive-Making-Microsoft-Empire/dp/0887306292">several</a> <a id="gw7729" href="http://www.amazon.com/Road-Ahead-Bill-Gates/dp/0140257276">books</a> about him and had a reasonably good idea of his background and the history of <a id="gw7730" href="http://en.wikipedia.org/wiki/Traf-O-Data">Traf-O-Data</a>, <a id="gw7731" href="http://en.wikipedia.org/wiki/Microsoft">Microsoft</a> and some of its products like <a id="gw7732" href="http://en.wikipedia.org/wiki/Microsoft_BASIC">BASIC</a>, <a id="gw7733" href="http://en.wikipedia.org/wiki/MS-DOS">DOS</a>, <a id="gw7734" href="http://en.wikipedia.org/wiki/OS/2">OS/2</a>, <a id="gw7735" href="http://en.wikipedia.org/wiki/Microsoft_Windows">Windows</a>, and <a id="gw7736" href="http://en.wikipedia.org/wiki/Windows_nt">NT</a>. Perhaps in the back of my mind I thought that learning about him would me emulate his success and make me <strike id="pn7n3">millions</strike>billions. Too bad that didn't work out.</p><p id="gw7737">In addition to the books, my other major source of information was when I watched <a id="gw7738" href="http://en.wikipedia.org/wiki/Robert_X._Cringely">Bob Cringely</a>'s <a id="gw7739" href="http://www.pbs.org/nerds/">Triumph of the Nerds</a> on PBS in the summer before I started high school. In hindsight, after reading this book I really wish I would have watched the 1998 follow-on to the series called "<a id="gw7740" href="http://www.pbs.org/opb/nerds2.0.1/">Nerds 2.01: A Brief History of the Internet</a>." I would have at least heard about Licklider and the computing days before Microsoft and Apple and not been so clueless back at that room in SRI.</p><p id="gw7741">What a story it is! It's not really just about Lick; it's about how he helped build a community that fostered the explosive computing growth in the 1960's right through the 70's and 80's.</p><p id="gw7742">Since I <a id="gw7743" href="http://www.moserware.com/2008/03/what-does-it-take-to-become-grandmaster.html">like to ask others</a> what stuck out in books that they've read, I thought I'd share some things I found interesting:</p><p><b id="gw7745">22 Days of Beeps Can Change a Nation</b><img id="gw7747" style="margin: 0px 5px 5px 0px;" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/SC9dYdj-vNI/AAAAAAAAAcc/6rN5vGcd-RQ/s200/Sputnik_asm.jpg" align="left" /></p><p>Chapter 6 opens on a rocket launch pad in the early morning of October 1957 at a top secret Soviet Union location. When the rocket took off and deployed its payload, the world came to know <a id="gw7749" href="http://en.wikipedia.org/wiki/Sputnik_1">Sputnik</a> by its incessant <i id="gw7750">beep beep beep</i> transmissions.</p><p id="gw7751">Waldrop quotes this account:</p><blockquote id="pn7n4"><p id="pn7n5">"[<i id="gw7752">Sputnik</i>'s] two transmitters would fail twenty-three days after launch - but their arrogant beeping would continue to sound in the American memory for years to come... Gone forever in this country was the myth of American superiority in all things technical and scientific." (p. 197)</p></blockquote><p id="gw7753">Although the U.S. had rockets under development that were more sophisticated than the Soviet ones, <a id="gw7754" href="http://www.pbs.org/wgbh/nova/sputnik/program.html">it was a huge blow to American pride</a> and there was a large public outcry. Everyone made the connection: if the Soviets could launch a satellite into space, they could probably launch a missile into any major U.S. city. </p><p id="pn7n6">One famous result of this perceived threat was <a id="gw7755" href="http://en.wikipedia.org/wiki/Dwight_D._Eisenhower">President Eisenhower</a>'s endorsement of "a plan to consolidate all the Pentagon's space research under a new civilian agency reporting directly to the secretary of defense. It would be called the <a id="gw7756" href="http://en.wikipedia.org/wiki/Defense_Advanced_Research_Projects_Agency#History">Advanced Research Projects Agency</a>, or ARPA." </p><p>Well it didn't <i id="gw7757">quite</i> work out exactly as planned. </p><p>Before ARPA opened for business, it had already been split up. The <a id="gw7758" href="http://en.wikipedia.org/wiki/NASA">National Aeronautics and Space Administration</a> (<a id="gw7759" href="http://www.nasa.gov/">NASA</a>) would handle all the non-military space projects and the services would get a large amount their funding back to handle most of their development projects. This left ARPA with "the kind of beyond-the-cutting-edge stuff that the services were willing to do without." (p. 198)</p><p id="gw7760">ARPA wasn't initially interested in computers. To them, they were really only helpful for things like accounting and payroll. This changed when ARPA was tasked to research new command and control ideas that would require a lot of data processing. This seemed like an ideal fit for computers. Licklider was asked to come over to ARPA and lead the new project.</p><p id="gw7761">He didn't want to take the job at first. He was already doing interesting things with computers and was so busy working on fleshing out his ideas of computer assisted "libraries of the future" to even think about burying himself in "the bureaucratic limbo of Washington." (p. 201)</p><p id="gw7762">Once he warmed up to the idea of going to ARPA, he began thinking that the command and control concept was ultimately a man-machine symbiosis, something he had been thinking about for years.</p><p id="gw7763"><a id="gw7764" href="http://en.wikipedia.org/wiki/Fig_wasp"><img id="gw7765" style="margin: 5px 5px 5px 0px;" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SC-ON9j-vRI/AAAAAAAAAc8/XjwAVNDbW-E/s200/Blastophaga_psenes.jpg" align="left" /></a>In March of 1960, he published his famous "<a id="gw7766" href="http://www.columbia.edu/%7Ejrh29/licklider/man-computer_symbiosis.html">Man-Computer Symbiosis</a>" which began: </p><blockquote id="gw7767"><p id="gw7768">"The fig tree is pollinated only by the insect Blastophaga grossorun. The larva of the insect lives in the ovary of the fig tree, and there it gets its food. The tree and the insect are thus heavily interdependent: the tree cannot reproduce without the insect; the insect cannot eat without the tree; together, they constitute not only a viable but a productive and thriving partnership. This cooperative 'living together in intimate association, or even close union, of two dissimilar organisms' is called symbiosis.</p><p id="gw7769">'Man-computer symbiosis' is a subclass of man-machine systems. There are many man-machine systems. At present, however, there are no man-computer symbioses. The purposes of this paper are to present the concept and, hopefully, to foster the development of man-computer symbiosis by analyzing some problems of interaction between men and computing machines, calling attention to applicable principles of man-machine engineering, and pointing out a few questions to which research answers are needed. The hope is that, in not too many years, human brains and computing machines will be coupled together very tightly, and that the resulting partnership will think as no human brain has ever thought and process data in a way not approached by the information-handling machines we know today."</p></blockquote><p id="gw7770">This might not seem radical in 2008, but it was revolutionary back in the 1960's when most people could only think of computers as batch processing machines. Lick saw computers in a symbiosis where humans could do the thinking and the machines would do the "algorithmic chores they were so good at" (p.148). In order to find out how much of a benefit they'd be, he did an experiment on himself and found to his horror that he spent 85% of his time just "getting into a position to think, to make a decision, to learn something I needed to know." The rest of the time was just clerical or mechanical. Computers would be a perfect fit to handle all the dreary stuff that got in the way of <i id="pn7n7">real</i> thinking.</p><p id="gw7771">Lick knew that he could start making the man-computer symbiosis concept real and get the government to pay for it through his association with ARPA. Lick's view was "that the problems of command and control were essentially problems of man-computer interaction. I thought it was just ridiculous having command-and-control systems based on batch processing. Who can direct a battle when he's got to write a program in the middle of a battle?" (p. 202)</p><p id="gw7772">On the next page we see:</p><blockquote id="gw7773"><p id="gw7774">"Improbably, miraculously, through some once-in-a-lifetime alignment of all the right planets, ARPA was offering him a chance to turn his vision into a reality. He could reinvent the whole field of computing. He could transform those giant calculating machines into full-fledged partners in a human creativity. He could create 'information utilities' that spanned the continent. He could democratize information by opening up vast libraries of material to instant access by anyone. And he could do it all with the Pentagon's money." (p. 203)</p></blockquote><p id="gw7775">And boy did he ever: </p><blockquote id="gw7776"><p id="gw7777">"[The professional bureaucrats] had a history of giving grants to individual people in twenty-thousand-dollar chunks. But Lick was talking about millions of dollars and whole teams of people. It was as though these folks had encountered this alien creature: friendly, but strange." (p. 206)</p></blockquote><p id="gw7778">In addition to funding research organizations like <a id="gw7779" href="http://en.wikipedia.org/wiki/System_Development_Corporation">SDC</a>, <a id="gw7780" href="http://en.wikipedia.org/wiki/RAND">RAND</a>, and <a id="gw7781" href="http://en.wikipedia.org/wiki/SRI_International">SRI</a>, Lick is remembered for helping fund the new computer science departments at <a id="gw7782" href="http://www.cs.berkeley.edu/">Berkeley</a>, <a id="gw7783" href="http://www-cs.stanford.edu/">Stanford</a>, <a id="gw7784" href="http://www.cs.cmu.edu/">Carnegie Mellon</a>, and perhaps most famously, <a id="gw7785" href="http://www.eecs.mit.edu/">MIT</a>. Lick's funding at MIT went towards a system that would put together several foundational ideas needed for his man-computer symbiosis. The goal was "Machine-Aided-Cognition," but since computer time was hard to come by and they had to invent a lot of the concepts for <a id="gw7786" href="http://en.wikipedia.org/wiki/Time-sharing">time-sharing</a> to allow multiple people to access a computer at once, the project also went by the name "Multiple Access Computer." Regardless of which one you chose, the acronym was the same. </p><p id="gw7787">"<i id="gw7788">So that's the Project MAC </i><i id="gw7789">the folks in the room were talking about,</i>" I thought as I read about it.</p><p id="gw7790">Project MAC would lay a lot of the foundations for modern operating systems. Examples include technologies like <a id="pn7n8" href="http://en.wikipedia.org/wiki/Computer_multitasking">multitasking</a> and <a id="pn7n9" href="http://en.wikipedia.org/wiki/File_system">file systems</a> to policies such as regular backups to protect themselves from their mistakes. They had to introduce passwords to stop some people from stealing computer time as well as ideas from unpublished academic papers. Unix and the C language it was written in was an offshoot of this project as an attempt to write a <i id="pn7n10">simpler</i> version than what the Project MAC team was trying to accomplish. </p><p id="pn7n11">And yet, Project MAC was just <i id="pn7n12">one</i> of the many projects that Lick was funding and tracking. To the outside observer, all of the projects seemed like an ad hoc mess rather than a carefully crafted plan. Lick knew that his man-computer symbiosis dream would need to be maintained by more than just him. Waldrop writes:</p><p id="gw7793">"Lick realized, if this vision was ever going to outlast his tenure at ARPA, he would somehow have to forge all these groups into a self-reinforcing, self-sustaining community." (p. 225)</p><p id="pn7n13">One such example of how he did this was his famous 1963 <a id="gw7795" href="http://www.kurzweilai.net/articles/art0366.html?printable=1">memo</a> which began: "[to the] Members and Affiliates of the Intergalactic Computer Network." In his mind, Lick was referring to a <i id="pn7n15">human</i> network. He continued: "It is evident that we have among us a collection of individual (personal and/or organizational) aspirations, efforts, activities, and projects." The challenge now was to exploit "the possibilities for mutual advantage". He went on to describe a connected system that would keep all the research projects together, a network focused on human thoughts but connected by wires. In essence, the early signs of the Internet.</p><p id="gw7796">But it took some time to materialize and didn't happen during Lick's ARPA tenure.</p><p id="gw7797">He did make progress. Due to the computing focus that Lick had caused, his ARPA division was given the title "Information Processing Techniques Office" (IPTO). After his two year tenure at ARPA, Lick handed the reins over to a young <a id="gw7798" href="http://en.wikipedia.org/wiki/Ivan_Sutherland">Ivan Sutherland</a> (creator of <a id="gw7799" href="http://en.wikipedia.org/wiki/Sketchpad">Sketchpad</a>, which launched the field computer graphics and computer aided design). When Sutherland finished his tenure, <a id="gw77100" href="http://en.wikipedia.org/wiki/Robert_Taylor_%28computer_scientist%29">Bob Taylor</a> would take over and proceed to actually make Lick's "Intergalactic Network" of people a real physical thing by linking ARPA people together into <a id="gw77101" href="http://en.wikipedia.org/wiki/ARPANET">ARPANET</a>, <i id="gw77102">the</i> direct predecessor of the Internet. </p><p id="gw77103">The <a id="gw77104" href="http://en.wikipedia.org/wiki/ARPANET#Initial_ARPA_deployment">first message went across it</a> at 10:30 PM on October 29, 1969. </p><p id="gw77105">Two interesting things from the book stand out right around this period of time. The first was that the height of the <a id="gw77106" href="http://en.wikipedia.org/wiki/Vietnam_War">Vietnam War</a> was taking a huge toll on the nation, both in terms of people and dollars. In a reported attempt to limit spending on the war, Montana senator <a id="pn7n16" href="http://en.wikipedia.org/wiki/Mansfield_Amendment">Mike Mansfield</a> proposed an amendment that would prevent the Defense Department from "[carrying] out any research project or study unless such project or study has a direct and apparent relationship to a specific military function." </p><p id="pn7n17">The practical effect of the "<a id="ceea" title="Mansfield Amendmant" href="http://nsf.gov/nsb/documents/2000/nsb00215/nsb50/1970/mansfield.html">Mansfield Amendment</a>" was that it diverted a large percentage of people's time into writing how their project had a "direct and apparent" relevancy. It's also one of the largest reasons why ARPA is now known as <a id="pn7n18" href="http://en.wikipedia.org/wiki/DARPA">DARPA</a>:</p><blockquote id="pn7n19"><p id="pn7n20">"In retrospect, moreover, [the Mansfield Amendment] came to be seen as the symbolic watershed for ARPA, the point at which it started its downhill slide from being a cutting-edge agency that was blessedly free to take risks to being an ordinary agency that was cautious and risk-averse." (p. 395)</p></blockquote><p id="gw77108">The second big thing was that in May of 1969, Xerox was making a <i id="gw77109">lot</i> of money selling copiers. But their management knew they had to be more than a one product company. In an attempt to branch out and "go digital," they purchased <a id="gw77110" href="http://en.wikipedia.org/wiki/Scientific_Data_Systems">Scientific Data Systems</a> (SDS). However, they had a problem: the company was largely computer illiterate. They needed to go out and recruit the best computer people the world had. One of their first hires was none other than former ARPA IPTO director Bob Taylor. Taylor would go on to attract many from Lick's "Intergalactic Network" ARPA community who had been distressed by the Mansfield Amendment and its research cutting implications.</p><p id="gw77111">The resulting <a id="pn7n21" href="http://en.wikipedia.org/wiki/Xerox_Parc">Xerox Palo Alto Research Center</a> (PARC) was <i id="gw77112">the</i> place to be in the 1970's. It fostered freedom to explore ideas just like the early ARPA days since its backers were willing to invest in long-term innovation. Its <a id="pn7n22" href="http://www.wheels.org/spacewar/stone/rolling_stone.html">anti-corporate culture</a> included meetings filled with beanbag chairs which prevented people from leaping out of their chair to argue with someone. This 'helped' you hear them out. PARC would go on to create the foundations of personal computing as we know it with their <a id="gw77113" href="http://en.wikipedia.org/wiki/Xerox_Alto">Alto</a> personal computer which was named after the city they were in. The Alto had new ideas like bitmapped displays, windows, an Ethernet network, WYSIWYG word processing, laser printing, and roots of modern object oriented programming. Unfortunately, Xerox's management didn't quite understand the business value of what their PARC guys were creating. Additionally, the guys inside PARC had a hard time creating a clear path and business model for getting their ideas to market. There was one notable exception. Waldrop writes:</p><blockquote id="gw77114">"If [<a id="gw77116" href="http://en.wikipedia.org/wiki/Jack_Goldman">Jack Goldman</a>] hadn't thrown a tantrum [in order to get the business guys to listen], they might just have rejected the laser printer itself - the <i id="pn7n23">one</i> PARC-bred product that would eventually earn billions for Xerox and repay its investment in PARC many times over." (p. 392)</blockquote><p id="gw77117"><a id="pn7n24" href="http://en.wikipedia.org/wiki/Steve_jobs">Steve Jobs</a>, along with some other engineers, would visit PARC in December of 1979 for a demonstration of the Alto system. Jobs was so enamored by the graphical interface that he saw that he didn't even explore the object oriented programming and networking ideas. During the visit, Jobs reportedly exclaimed "Why hasn't this company brought this to market?" (p. 443) He didn't wait around for Xerox. Apple's first graphical computer, "<a id="pn7n25" href="http://en.wikipedia.org/wiki/Apple_Lisa">Lisa</a>," 'borrowed' several ideas from the Alto. When the Lisa and <a id="pn7n26" href="http://en.wikipedia.org/wiki/IBM_PC">IBM PC</a> hit the market in the early 80's, the guys inside PARC realized that <a id="pn7n27" href="http://www.amazon.com/Fumbling-Future-Invented-Personal-Computer/dp/1583482660">Xerox had blown a huge opportunity</a>. Many jumped ship. One example was <a id="pn7n28" href="http://en.wikipedia.org/wiki/Charles_Simonyi">Charles Simonyi</a>, who took his ideas <a id="pn7n29" href="http://en.wikipedia.org/wiki/Bravo_%28software%29">Bravo</a> word processing ideas north to a relatively new company in Washington named Microsoft. It was a huge difference in culture. Simonyi's commented on the contrast:</p><blockquote id="pn7n30">"It was like going into the graveyard or retirement home before going into the maternity ward. You could see that Microsoft could do things one hundred times faster, literally, I'm not kidding. Six years from that point, we overtook Xerox in market valuation." (p. 449)</blockquote><p id="gw77118">And that brought me full circle back to the pop culture history I was more familiar with. Throughout the years Lick would stay involved in some part with the research community, sometimes getting bogged down with management tasks which he despised. He would teach at MIT through the 80s with students that would only later realize all that he had done. Failing health caused him to pass away at the age of 75 on June 26, 1990: just before the world at large would come to use the "Intergalactic Network." </p><p id="gw77119">Lick was known for being quite modest about his contributions, often minimizing his role. When asked about what he did, he said:</p><blockquote id="pn7n32">"I think that I found a lot of bright people and got them working in this area. I got it moving. [And it was] a fantastic community. I guess that's the word. It was more than just a collection of bright people. It was a thing that organized itself into a community, so that there was some competition and some cooperation, and it resulted in the emergence of a field." (p. 258)</blockquote><p id="pn7n34">So <i id="gw77123">that's</i> why they kept talking about him. Now I get it. </p><p id="pn7n35">Lick organized a community that would change the computing world. He realized that it's ultimately the people that matter. I think that our industry puts too much emphasis on technology and tends to marginalize people. I think that one of the first steps to reverse this trend is to understand the contributions of its founders like Lick. </p><p id="pn7n36">"The Dream Machine" was a good book. I recommend it to anyone who might be curious about what happened in computing before the Microsoft, Apple, and especially Google days. From the early days of <a id="pn7n37" href="http://en.wikipedia.org/wiki/Von_Neumann">Von Neumann</a> and <a id="pn7n38" href="http://en.wikipedia.org/wiki/Alan_Turing">Turing</a>, right up to the 90's, Waldrop's detailed research helped <a id="pn7n39" href="http://www.technologyreview.com/Infotech/12040/page1/">the story</a> come alive. The book appears to be out of print, but it is well worth a visit to your library or getting a <a id="pn7n40" href="http://product.half.ebay.com/The-Dream-Machine_W0QQprZ1845304QQtgZinfo">used</a> copy. </p><p id="gw77127">If you made it this far, I'd really love to hear your comments on a few related questions:</p><ul id="pn7n41"><li id="pn7n42">Had you heard of Licklider before? If so, where? What sticks out in your mind about Lick? </li><li id="pn7n43">What do you think about Lick's funding and management strategy in the early days of ARPA's IPTO? </li><li>What do you think of Lick's comparison of the Fig Wasp and Fig Tree to a man-computer relationship? Do you think we've obtained the man-computer symbiosis he was referring to? </li><li id="pn7n44">What about PARC? It could still be considered success since the laser printer paid for Xerox's investment in it. However, as Steve Jobs points out, they could have been the IBM of the 90's but blew their chance. What do you think? </li><li id="pn7n45">What do you think about the Mansfield Amendment of the 1970 fiscal year? It's easy to criticize things in hindsight. If it was 1969 and you didn't know the future, which side would you have honestly taken? How would you have defended your position? </li><li>If you read this book or similar books, what is most memorable to you about the period from the 1930's through the late 80's that you think most people don't know about? </li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-251716016582883780?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com13tag:blogger.com,1999:blog-6800934446457898793.post-59503513089857421302008-04-26T21:09:00.011-04:002009-02-16T19:06:12.147-05:00My "Better Know a Framework" Talk at IndyCodeCamp<p>The podcast "<a href="http://www.dotnetrocks.com/">.NET Rocks</a>!" has a segment called "Better Know A Framework" at the start of every show. The point of the short segment is to simply raise awareness of perhaps lesser known areas of the .net framework. I've found that it's a great way to learn about some things that I simply haven't looked at before.</p><p>When <a href="http://www.aaronlerch.com/blog/">Aaron Lerch</a> asked for session proposals for the <a href="http://www.indycodecamp.com/">IndyCodeCamp</a> that he and some others were organizing, I thought it'd be fun to have a "Better Know a Framework" session that had much of the same feel as the segment on the show.</p><p>In order to prepare for <a href="http://www.indycodecamp.com/Sessions/tabid/438/Default.aspx#framework">the talk</a>, I went back through every segment and made a few notes on what parts of the framework was covered as well as documentation links for more information. In case that work might helpful to anyone else, I'm including it as an "appendix" to this post.</p><br /><a href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SBPnJJcdt3I/AAAAAAAAAbs/hPVJdB1QqFE/s1600-h/bkafwideshot.JPG"><img id="BLOGGER_PHOTO_ID_5193748939628459890" style="margin: 0px 10px 10px 0px;" alt="Thanks to Mike Hall for the photo" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/SBPnJJcdt3I/AAAAAAAAAbs/hPVJdB1QqFE/s320/bkafwideshot.JPG" border="0" /></a> <p>The actual talk went pretty well. There were around 30 people at the session (my session was concurrent with 3 other sessions). One of the highlights was the introduction where the hosts of .NET Rocks introduced me (via <a href="http://cid-8509553b6d92361d.skydrive.live.com/self.aspx/Moserware/bkaf_intro.wma">a recording</a>). Another highlight was being able to throw out flip-flops with <a href="http://www.inin.com/">my company's</a> logo on them to people in the audience that were first to answer some of the questions I asked.</p><p>In trying keep with the <a href="http://blogs.msdn.com/trobbins/archive/2004/12/12/280181.aspx">code camp manifesto</a>, I intentionally had no slides. The presentation was basically me stepping through <a href="http://cid-8509553b6d92361d.skydrive.live.com/self.aspx/Moserware/BetterKnowAFrameworkTalk.zip">this C# solution</a>.<br /></p><p>I created it to show how to use some lesser known classes and namespaces. I also briefly mentioned the "<a href="http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html">Turkey Test</a>" and its implications on code.</p><p>Feel free to download the solution and run through it. If you couldn't make it to the talk, feel free to ask questions via the comments. If you were able to attend the event in person, please fill out the <a href="http://www.codecampevals.com/">evaluation form online</a> or leave comments here as well. </p><p>Thanks to Aaron Lerch and many others who helped organize Indianapolis's first code camp! It was a privilege to get the chance to speak there.</p><p><b id="apz9">Appendix</b></p><p id="xj12">Here's a very brief recap of every "Better Know a Framework" segment since it started. If you'd like more information about it, I included a link to the show where you can listen to it. I also linked to the MSDN documentation for what was covered. I put an asterisk (*) by the show number if I covered that topic in my demo source file. </p><ul id="r_6-"><li id="naow"><a id="wb2h" title="243" href="http://www.dotnetrocks.com/default.aspx?showNum=243">243</a>* - <a id="nx8e" href="http://msdn2.microsoft.com/en-us/library/system.bitconverter.aspx">System.BitConverter</a>: Coverts value types like an int to bytes and back. Also determines endianness of the machine. </li><li id="r:1o"><a id="w216" title="244" href="http://www.dotnetrocks.com/default.aspx?showNum=244">244</a>* - <a id="oukr" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator.aspx">System.Security.Cryptography.RandomNumberGenerator</a>: Much better than System.Random at generating cryptographically strong random numbers. </li><li id="wbfu"><a id="m-rr" title="245" href="http://www.dotnetrocks.com/default.aspx?showNum=245">245</a> - <a id="euey" title="System.Net.NetworkInformation.Ping" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.ping.aspx">System.Net.NetworkInformation.Ping</a>: which returns a <a id="ul3y" title="System.Net.NetworkInformation.PingReply" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.pingreply.aspx">System.Net.NetworkInformation.PingReply</a> that has a <a id="nr5h" title="System.Net.NetworkInformation.IPStatus" href="http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.ipstatus.aspx">System.Net.NetworkInformation.IPStatus</a> which is useful in determining if a remote machine is available (assuming they respond to ping that is). </li><li id="ri:s"><a id="qoij" title="246" href="http://www.dotnetrocks.com/default.aspx?showNum=246">246</a> - <a id="kvv4" title="System.Diagnostics.FileVersionInfo" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.aspx">System.Diagnostics.FileVersionInfo</a>: Useful for getting detailed information EXEs and DLLs (such as the company that produced the file). </li><li id="c24f"><a id="yeun" href="http://www.dotnetrocks.com/default.aspx?showNum=247">247</a>* - <a id="lyrh" title="System.Diagnostics.Process" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.aspx">System.Diagnostics.Process</a>: Information about a process on the system such as how much memory it's using, its process ID, main window name, etc. Also includes methods to do things like kill the process. </li><li id="a8g8"><a id="ktob" href="http://www.dotnetrocks.com/default.aspx?showNum=248">248</a> - <a id="aase" title="System.Net.Dns" href="http://msdn2.microsoft.com/en-us/library/system.net.dns.aspx">System.Net.Dns</a> Useful for determining the IP address(es) for a given host name. </li><li id="dcad"><a id="lvor" href="http://www.dotnetrocks.com/default.aspx?showNum=249">249</a>* - <a id="rhib" title="System.Text.StringBuilder" href="http://msdn2.microsoft.com/en-us/library/system.text.stringbuilder.aspx">System.Text.StringBuilder</a>: Much faster at building a string than concatenating a string. Discussed in depth on show #<a id="t4dw" title="87" href="http://www.dotnetrocks.com/default.aspx?showNum=87">87</a> </li><li id="taus"><a id="k_nu" href="http://www.dotnetrocks.com/default.aspx?showNum=250">250</a>* - <a id="nyes" title="System.Threading" href="http://msdn2.microsoft.com/en-us/library/system.threading.aspx">System.Threading</a> namespace: Classes useful in synchronization of threads: </li><ul id="g4l9"><li id="xq9n">CPU: <a id="nl_p" title="Interlocked" href="http://msdn2.microsoft.com/en-us/library/system.threading.interlocked.aspx">Interlocked</a> - Operations performed atomically by the processor (e.g. <a id="jptr" title="Interlocked.Increment" href="http://msdn2.microsoft.com/en-us/library/dd78zt0c.aspx"><br />Interlocked.Increment</a>) </li><li id="xqvn">CLR: <a id="t.3z" title="System.Threading.Monitor" href="http://msdn2.microsoft.com/en-us/library/system.threading.monitor.aspx">Monitor</a> and <a id="zcl1" title="ReaderWriterLock" href="http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx">ReaderWriterLock</a> </li><li id="xg7.">Kernel: <a id="qr:y" title="Semaphore" href="http://msdn2.microsoft.com/en-us/library/system.threading.aspx"><br />Semaphore</a>, <a id="chd4" title="AutoResetEvent" href="http://msdn2.microsoft.com/en-us/library/system.threading.autoresetevent.aspx"><br />AutoResetEvent</a>, <a id="bwpc" title="ManualResetEvent" href="http://msdn2.microsoft.com/en-us/library/system.threading.manualresetevent.aspx"><br />ManualResetEvent</a>, <a id="wegv" title="WaitHandle" href="http://msdn2.microsoft.com/en-us/library/system.threading.waithandle.aspx"><br />WaitHandle</a> (e.g. <a id="wbpk" title="WaitHandle.WaitAll" href="http://msdn2.microsoft.com/en-us/library/system.threading.waithandle.waitall.aspx"><br />WaitHandle.WaitAll</a>) </li></ul><li id="zbfv"><a id="a5-3" href="http://www.dotnetrocks.com/default.aspx?showNum=251">251</a>* -<a id="g:0b" title="System.IO.FileSystemWatcher" href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx"> System.IO.FileSystemWatcher</a>: Useful for getting notifications when something on the file system changes. </li><li id="cejc"><a id="j97o" href="http://www.dotnetrocks.com/default.aspx?showNum=252">252</a>* - <a id="vrqk" title="System.IO.Compression" href="http://msdn2.microsoft.com/en-us/library/system.io.compression.aspx">System.IO.Compression</a> namespace: Classes involved in compressing and decompressing files/streams. </li><li id="b-5v"><a id="m:.i" href="http://www.dotnetrocks.com/default.aspx?showNum=253">253</a>* - <a id="j9tx" title="System.Collections.Stack" href="http://msdn2.microsoft.com/en-us/library/system.collections.stack.aspx">System.Collections.Stack</a> for LIFO (last-in-first-out) and <a id="xx4z" title="System.Collections.Queue" href="http://msdn2.microsoft.com/en-us/library/system.collections.queue.aspx"><br />System.Collections.Queue</a> for FIFO (first-in-first-out). Also available are generic <a id="c345" title="Stack" href="http://msdn2.microsoft.com/en-us/library/3278tedw.aspx"><br />Stack<t></t></a> and <a id="dxcf" title="Queue" href="http://msdn2.microsoft.com/en-us/library/7977ey2c.aspx">Queue<t></t></a>. </li><li id="xx6i"><a id="ptyy" href="http://www.dotnetrocks.com/default.aspx?showNum=254">254</a> - <a id="or3m" title="System.ComponentModel.BooleanConverter" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.booleanconverter.aspx">System.ComponentModel.BooleanConverter</a>: Type converter to and from booleans. </li><li id="gzl9"><a id="i9c4" href="http://www.dotnetrocks.com/default.aspx?showNum=255">255</a> - Calendars in <a id="mzc7" title="System.Globalization" href="http://msdn2.microsoft.com/en-us/library/system.globalization.taiwancalendar.aspx">System.Globalization</a>: Many utilities for manipulating dates in various calendar schemes: </li><ul id="p4fn"><li id="szr6"><a id="s92." title="System.Globalization.GregorianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.gregoriancalendar.aspx">GregorianCalendar</a> - (most popular) </li><li id="bs2:"><a id="q9q9" title="System.Globalization.HebrewCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.hebrewcalendar.aspx">HebrewCalendar </a></li><li id="j9q7"><a id="cg5c" href="http://msdn2.microsoftssystem.globalization.hijricalendar.aspx/">HijriCalendar</a> </li><li id="hc7u"><a id="xpnq" title="System.Globalization.JapaneseCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.japanesecalendar.aspx">JapaneseCalendar</a> </li><li id="ly0g"><a id="oegu" title="System.Globalization.JapaneseLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.japaneselunisolarcalendar.aspx">JapaneseLunisolarCalendar</a> </li><li id="q-pk"><a id="ssuy" title="System.Globalization.JulianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.juliancalendar.aspx">JulianCalendar</a> </li><li id="zmge"><a id="cskg" title="System.Globalization.KoreanCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.koreancalendar%28VS.71%29.aspx">KoreanCalendar</a> </li><li id="gbz0"><a id="nqfj" title="System.Globalization.PersianCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.persiancalendar.aspx">PersianCalendar</a> </li><li id="fxo2"><a id="zr43" title="TaiwanCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.taiwancalendar.aspx">TaiwanCalendar</a> </li><li id="tmz1"><a id="egn2" title="ThaiBuddhistCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.thaibuddhistcalendar.aspx">ThaiBuddhistCalendar</a> </li><li id="pwep"><a id="ldin" title="UmAlQuraCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.umalquracalendar.aspx">UmAlQuraCalendar</a> </li><li id="dqqk"><a id="i3lh" title="EastAsianLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.eastasianlunisolarcalendar.aspx">EastAsianLunisolarCalendar</a> </li><li id="g:qu"><a id="dlzh" title="ChineseLunisolarCalendar" href="http://msdn2.microsoft.com/en-us/library/system.globalization.chineselunisolarcalendar.aspx">ChineseLunisolarCalendar</a> </li></ul><br /><li id="zsyx"><a id="wv.u" href="http://www.dotnetrocks.com/default.aspx?showNum=256">256</a> - <a id="bmlf" title="System.Web.Mail" href="http://msdn2.microsoft.com/en-us/library/system.web.mail.aspx">System.Web.Mail</a>: Old (deprecated) way of sending an email. </li><li id="p-.6"><a id="zajk" href="http://www.dotnetrocks.com/default.aspx?showNum=257">257</a> - <a id="mx6k" title="System.Net.Mail" href="http://msdn2.microsoft.com/en-us/library/system.net.mail.aspx">System.Net.Mail</a>: .net 2.0+ way of sending emails </li><li id="dg7w"><a id="lqzs" href="http://www.dotnetrocks.com/default.aspx?showNum=258">258</a>* - <a id="j7bh" title="System.ComponentModel.BackgroundWorker" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx">System.ComponentModel.BackgroundWorker</a>: Simplifies use of background worker threads that need to update a UI via use of the <a id="gx5e" title="RunWorkAsync" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkerasync.aspx">RunWorkAsync</a> method and <a id="rggc" title="DoWork" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx">DoWork</a> event. </li><li id="oz5x"><a id="p2sg" href="http://www.dotnetrocks.com/default.aspx?showNum=259">259</a> - <a id="pixh" title="System.ComponentModel.BrowseableAttribute" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.browsableattribute.aspx">System.ComponentModel.BrowseableAttribute<br /></a>: Can be used to disable a property's visibility in the properties window (e.g. windows forms control). </li><li id="q2ed"><a id="jv0u" href="http://www.dotnetrocks.com/default.aspx?showNum=260">260</a>* - <a id="u9ut" title="System.Collections.Generic.Dictionary" href="http://msdn2.microsoft.com/en-us/library/xfhwa508.aspx">System.Collections.Generic.Dictionary<tkey,></tkey,></a>: Maps keys to values </li><li id="u_si"><a id="nsjs" href="http://www.dotnetrocks.com/default.aspx?showNum=261">261</a> - <a id="jx1h" title="System.Windows.Input" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.aspx">System.Windows.Input</a> namespace: WPF classes used for input (e.g. <a id="ob0b" title="InputManager" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.notifyinputeventargs.inputmanager.aspx"><br />InputManager</a>, <a id="bw4b" title="KeyboardNavigation" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.keyboardnavigation.aspx">KeyboardNavigation</a>, <a id="uyyj" title="Mouse" href="http://msdn2.microsoft.com/en-us/library/system.windows.input.keyboardnavigation.aspx">Mouse</a>) </li><li id="avuw"><a id="of:0" href="http://www.dotnetrocks.com/default.aspx?showNum=262">262</a> - <a id="zpir" title="System.Reflection.Assembly" href="http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.aspx">System.Reflection.Assembly</a>: Useful for finding information about .net assemblies such as classes, interfaces, methods, properties, events, etc. </li><li id="su3."><a id="wv6n" href="http://www.dotnetrocks.com/default.aspx?showNum=263">263</a>* - <a id="cxzt" title="System.Threading.Timer" href="http://msdn2.microsoft.com/en-us/library/system.threading.timer.aspx">System.Threading.Timer</a>: Simple and lightweight timer. See <a id="nqyu" title="this link" href="http://shrinkster.com/rv3">comparison</a> of timers. </li><li id="kd4t"><a id="lyyn" href="http://www.dotnetrocks.com/default.aspx?showNum=264">264</a> - <a id="z-qj" title="System.SerializableAttribute" href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx">System.SerializableAttribute</a>: Marks an object as serializable (able to create a persisted represention of it). A binary formatter/serializer is at <a id="rd.0" title="System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" href="http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx"><br />System.Runtime.Serialization.Formatters.Binary.BinaryFormatter</a> </li><li id="auuo"><a id="u439" href="http://www.dotnetrocks.com/default.aspx?showNum=265">265</a> - <a id="kcs8" title="System.Xml.XPath.XPathDocument" href="http://msdn2.microsoft.com/en-us/library/system.xml.xpath.xpathdocument.aspx">System.Xml.XPath.XPathDocument</a>: Provides a fast read-only in-memory representation of an XML document using the XPath data model. See also <a id="p-ni" title="System.Xml.XmlReader" href="http://msdn2.microsoft.com/en-us/library/system.xml.xpath.xpathdocument.aspx"><br />System.Xml.XmlReader</a> for read-only XML reading. </li><li id="g.:7"><a id="n8gx" href="http://www.dotnetrocks.com/default.aspx?showNum=266">266</a> - <a id="l1pp" title="System.ApplicationException" href="http://msdn2.microsoft.com/en-us/library/system.applicationexception.aspx">System.ApplicationException</a>: Intended for use of application specific exceptions, but if you read <a id="ueug" title="Best Practices for Handling Exceptions" href="http://msdn2.microsoft.com/en-us/library/seyhszts.aspx">Best Practices for Handling Exceptions</a>, you'll see that you shouldn't use it anymore. </li><li id="omf."><a id="eid9" href="http://www.dotnetrocks.com/default.aspx?showNum=267">267</a>* - <a id="jla0" title="Global Assembly Cache" href="http://msdn2.microsoft.com/en-us/library/yf1d93sz.aspx">Global Assembly Cache</a>: Otherwise known as the GAC. Provides a system-wide storage facility for assemblies. To put an assembly in the GAC, you need to use the <a id="bmoh" title="strong name tool" href="http://msdn2.microsoft.com/en-us/library/k5b5tt23.aspx"><br />strong name tool</a> (SN) to get it ready, and then use <a id="vu1b" title="GACUTIL" href="http://msdn2.microsoft.com/en-us/library/ex0ss12c.aspx"><br />GACUTIL</a> on it. </li><li id="a5yl"><a id="oz8-" href="http://www.dotnetrocks.com/default.aspx?showNum=268">268</a>* - <a id="at:k" title="System.Console" href="http://msdn2.microsoft.com/en-us/library/system.console.aspx">System.Console</a>: Besides the obvious methods like <a id="b07s" title="WriteLine" href="http://msdn2.microsoft.com/en-us/library/system.console.writeline.aspx">WriteLine</a>, there are many lesser-known ones: </li><ul id="lub3"><li id="mufs"><a id="n1i6" title="CapsLock" href="http://msdn2.microsoft.com/en-us/library/system.console.capslock.aspx">CapsLock</a> </li><li id="x0z-"><a id="orpi" title="NumberLock" href="http://msdn2.microsoft.com/en-us/library/system.console.numberlock.aspx">NumberLock</a> </li><li id="nz3m"><a id="bzh_" title="ForegroundColor" href="http://msdn2.microsoft.com/en-us/library/system.console.numberlock.aspx">ForegroundColor</a> </li><li id="ihot"><a id="oqnd" title="WindowHeight" href="http://msdn2.microsoft.com/en-us/library/system.console.windowheight.aspx">WindowHeight</a> </li><li id="wak4"><a id="d0.h" title="WindowTop" href="http://msdn2.microsoft.com/en-us/library/system.console.windowtop.aspx">WindowTop</a> </li><li id="s4wp"><a id="ezbq" title="WindowLeft" href="http://msdn2.microsoft.com/en-us/library/system.console.windowleft.aspx">WindowLeft</a> </li><li id="if:3"><a id="j_:o" title="WindowWidth" href="http://msdn2.microsoft.com/en-us/library/system.console.windowwidth.aspx">WindowWidth</a> </li><li id="yiih"><a id="fmu_" title="Title" href="http://msdn2.microsoft.com/en-us/library/system.console.title.aspx">Title</a> (sets what to display in the title bar) </li><li id="g7ns"><a id="r_w:" title="CursorVisible" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorvisible.aspx">CursorVisible</a> </li><li id="gr.w"><a id="l.iq" title="In" href="http://msdn2.microsoft.com/en-us/library/system.console.in.aspx">In</a> (Stdin) </li><li id="b:sr"><a id="zq1q" title="Error" href="http://msdn2.microsoft.com/en-us/library/system.console.error.aspx">Error</a> (Stderr) </li><li id="dck8"><a id="cgss" title="Out" href="http://msdn2.microsoft.com/en-us/library/system.console.out.aspx">Out</a> (Stdout) </li><li id="xh:n"><a id="s_vy" title="CursorSize" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorsize.aspx">CursorSize</a> </li><li id="l7ni"><a id="vlmf" title="CursorLeft" href="http://msdn2.microsoft.com/en-us/library/system.console.cursorleft.aspx">CursorLeft</a> </li><li id="j187"><a id="sn3x" title="CursorTop" href="http://msdn2.microsoft.com/en-us/library/system.console.cursortop.aspx">CursorTop</a> </li><li id="po1j"><a id="tiu8" title="BackgroundColor" href="http://msdn2.microsoft.com/en-us/library/system.console.backgroundcolor.aspx">BackgroundColor</a><br /></li></ul><li id="jxtb"><a id="w45:" href="http://www.dotnetrocks.com/default.aspx?showNum=269">269</a>* - <a id="a33f" title="System.Environment" href="http://msdn2.microsoft.com/en-us/library/system.environment.aspx">System.Environment</a>: Contains many assorted details about your application's environment: </li><ul id="v2g:"><li id="lfzl"><a id="qvh0" title="UserName" href="http://msdn2.microsoft.com/en-us/library/system.environment.username.aspx">UserName</a>: User name of the person currently logged in. </li><li id="wmhs"><a id="graf" title="WorkingSet" href="http://msdn2.microsoft.com/en-us/library/system.environment.workingset.aspx">WorkingSet</a>: Physical memory mapped to the process </li><li id="fyfr"><a id="xfpd" title="GetFolderPath" href="http://msdn2.microsoft.com/en-us/library/system.environment.getfolderpath.aspx">GetFolderPath</a>: Useful for finding file paths to things like the Program Files folder (which can be different depending on if you're running 64 bit Windows) </li></ul><br /><li id="woys"><a id="hg4t" href="http://www.dotnetrocks.com/default.aspx?showNum=270">270</a> - <a id="rg1a" title="System.Net.HttpWebRequest" href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebrequest.aspx">System.Net.HttpWebRequest </a>, <a id="hipr" title="HttpWebResponse" href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebresponse.aspx">HttpWebResponse </a>, <a id="nrfk" title="WebRequest" href="http://msdn2.microsoft.com/en-us/library/system.net.webrequest.aspx">WebRequest </a>classes: Lower level classes used to perform an HTTP request. See notes on show #<a id="hea5" title="275" href="http://www.dotnetrocks.com/default.aspx?showNum=275">275</a> for the much simpler WebClient class. </li><li id="zs_2"><a id="w8ed" href="http://www.dotnetrocks.com/default.aspx?showNum=271">271</a>* - <a id="g6o0" title="System.IO.StreamWriter" href="http://msdn2.microsoft.com/en-us/library/system.io.streamwriter.aspx">System.IO.StreamWriter</a> and <a id="r8al" title="StreamReader" href="http://msdn2.microsoft.com/en-us/library/system.io.streamreader.aspx">StreamReader</a>: Helper classes for dealing with text files/streams (contains methods like <a id="nens" title="ReadToEnd" href="http://msdn2.microsoft.com/en-us/library/system.io.streamreader.readtoend.aspx">ReadToEnd</a>() for returning a string of whatever is left in the stream) </li><li id="bnmw"><a id="zthf" href="http://www.dotnetrocks.com/default.aspx?showNum=272">272</a> - <a id="fn65" title="System.Windows.Forms.Splitter" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.splitter.aspx">System.Windows.Forms.Splitter</a>: Control that allows you to split parts of a UI in a way that allows the user to expand or shrink an area. This class can be hard to use, see show #<a id="i-nf" title="273" href="http://www.dotnetrocks.com/default.aspx?showNum=273">273</a>. </li><li id="c_lc"><a id="w4ix" href="http://www.dotnetrocks.com/default.aspx?showNum=273">273</a> - <a id="aryk" title="System.Windows.Forms.SplitContainer" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.splitcontainer.aspx">System.Windows.Forms.SplitContainer</a>: Much simpler way to provide a split UI. </li><li id="pazx"><a id="e7sn" href="http://www.dotnetrocks.com/default.aspx?showNum=274">274</a> - <a id="azq1" title="System.Windows.Forms.ToolTip" href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx">System.Windows.Forms.ToolTip</a>: An <a id="nk8g" title="extender provider" href="http://msdn2.microsoft.com/en-us/library/ms171836.aspx"><br />extender provider</a> that allows you to add Tooltips to all items in a container's scope. It implements <a id="s.10" title="System.ComponentModel.IExtenderProvider" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.iextenderprovider.aspx">System.ComponentModel.IExtenderProvider</a>. Similiar to how <a id="g:ci" title="System.Windows.Forms.ErrorProvider" href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.iextenderprovider.aspx"><br />System.Windows.Forms.ErrorProvider</a> works. </li><li id="etbx"><a id="tm2x" href="http://www.dotnetrocks.com/default.aspx?showNum=275">275</a>* - <a id="mkns" title="System.Net.WebClient class" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.aspx">System.Net.WebClient</a>: Provides a very easy way to perform common HTTP operations in 1 line of code (e.g. <a id="etog" title="DownloadFile" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.downloadfile.aspx">DownloadFile</a>, <a id="la-s" title="DownloadData" href="http://msdn2.microsoft.com/en-us/library/system.net.webclient.downloaddata.aspx">DownloadData</a>) </li><li id="i2h9"><a id="yxwn" href="http://www.dotnetrocks.com/default.aspx?showNum=276">276</a> - <a id="ka9q" title="System.Web.UI.Page" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.aspx">System.Web.UI.Page</a>: <a id="td5y" title="SavePageStateToPersistenceMedium" href="http://savepagestatetopersistencemedium/">SavePageStateToPersistenceMedium</a> and <a id="ctl00_rs1_mainContentContainer_ctl367" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.loadpagestatefrompersistencemedium.aspx"><br />LoadPageStateFromPersistenceMedium</a> allows you to store viewstate in a different place besides sending it down to the browser each time. This can be useful as viewstate can account for a large (67%+) part of your page's size. </li><li id="mue4"><a id="m33b" href="http://www.dotnetrocks.com/default.aspx?showNum=277">277</a> - <a id="a8wa" title="System.Web.Management" href="http://msdn2.microsoft.com/en-us/library/system.web.management.aspx">System.Web.Management</a> namespace: Classes that do all sorts of management of web servers and web farms. For example, <a id="ctl00_rs1_mainContentContainer_ctl65" href="http://msdn2.microsoft.com/en-us/library/system.web.management.webauditevent.aspx">WebAuditEvent</a> allows you to audit web events. </li><li id="dy6."><a id="az_7" href="http://www.dotnetrocks.com/default.aspx?showNum=278">278</a> - <a id="mzr5" title="System.IO.IsolatedStorage" href="http://msdn2.microsoft.com/en-us/library/system.io.isolatedstorage.aspx">System.IO.IsolatedStorage</a>: (In this show Carl thought that IsolatedStorage was used for storing things in a secret way. See show #<a id="os_:" title="278" href="http://www.dotnetrocks.com/default.aspx?showNum=278">278</a> ) </li><li id="kckd"><a id="d2_9" href="http://www.dotnetrocks.com/default.aspx?showNum=279">279</a>* - Christopher Loaf from Sweden pointed out that <a id="mzr5" title="System.IO.IsolatedStorage" href="http://msdn2.microsoft.com/en-us/library/system.io.isolatedstorage.aspx">System.IO.IsolatedStorage</a> is primarily used for storing and retrieving data in a partial trust environment (e.g. a web browser). </li><li id="p1vp"><a id="gyqs" href="http://www.dotnetrocks.com/default.aspx?showNum=280">280</a>* - <a id="vyof" title="System.Convert" href="http://msdn2.microsoft.com/en-us/library/system.convert.aspx">System.Convert</a>: Methods for converting items from one type to another (e.g <a id="kfuk" title="ToBoolean" href="http://msdn2.microsoft.com/en-us/library/system.convert.toboolean.aspx"><br />ToBoolean</a>, <a id="fxps" title="ToChar" href="http://msdn2.microsoft.com/en-us/library/system.convert.tochar.aspx">ToChar</a>, <a id="zhs7" title="ToBase64String" href="http://msdn2.microsoft.com/en-us/library/system.convert.tobase64string.aspx">ToBase64String</a>, <a id="vbt8" title="FromBase64String" href="http://msdn2.microsoft.com/en-us/library/system.convert.frombase64string.aspx">FromBase64String</a>). In addition, has <a id="k2th" title="IsDBNull" href="http://msdn2.microsoft.com/en-us/library/system.convert.isdbnull.aspx">IsDBNull</a> to determine if an object is a database null value. </li><li id="tlnm"><a id="yn1s" href="http://www.dotnetrocks.com/default.aspx?showNum=281">281</a>* <a id="x.f2" title="System.Globalization.CultureInfo" href="http://msdn2.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx">System.Globalization.CultureInfo</a>: Used for ensuring that you retrieve, store, and process information according to a specific culture. For example, if you do DateTime.Now.ToString("D"), you'll get the date formatted in a culturally specific way as outlined by this class.<br /><a id="mn41" href="http://www.dotnetrocks.com/default.aspx?showNum=282">282</a> - <a id="xkre" title="System.Guid" href="http://msdn2.microsoft.com/en-us/library/system.guid.aspx">System.Guid</a>: Class used for handling global unique identifiers. </li><li id="ty5v"><a id="vf5g" href="http://www.dotnetrocks.com/default.aspx?showNum=283">283</a> - <a id="hksj" title="System.IO.Packaging" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.aspx">System.IO.Packaging</a>: Provides classes that support storage of multiple data objects in a single container. (Most notable example is Office 2007+ documents, see show #<a id="fx85" title="285" href="http://www.dotnetrocks.com/default.aspx?showNum=285">285</a> ) </li><ul id="k38v"><li id="j3lr"><a id="hxrc" title="Package" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.package.aspx">Package</a> </li><li id="j905"><a id="ziqu" title="ZipPackage" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.zippackage.aspx">ZipPackage</a> </li><li id="oz8d"><a id="t3hf" title="PackageRelationship" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.packagerelationship.aspx">PackageRelationship</a> </li><li id="ye-c"><a id="u._g" title="PackagePart" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.packagepart.aspx">PackagePart</a> </li><li id="sf4b"><a id="aruu" title="PackageDigitalSignature" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.packagedigitalsignature.aspx">PackageDigitalSignature</a> </li><li id="vxjm"><a id="dq06" title="System.Windows.Xps.Packaging.XpsDocument" href="http://msdn2.microsoft.com/en-us/library/system.windows.xps.packaging.xpsdocument.aspx">System.Windows.Xps.Packaging.XpsDocument</a><br /></li></ul><li id="tky1"><a id="dg3k" href="http://www.dotnetrocks.com/default.aspx?showNum=284">284</a> - <a id="wmpb" title="System.Security.Cryptography.SHA1" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.sha1.aspx">System.Security.Cryptography.SHA1</a>: Hash algorithm that has been <a id="j_ku" title="academically broken" href="http://news.zdnet.com/2100-1009_22-5598536.html"><br />academically broken </a>and therefore shouldn't be used anymore for safety reasons. The framework also has unbroken ones such as <a id="a4lt" title="SHA512" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.sha512.aspx">SHA512</a> which uses 512 bits instead of 160 bits, but is much more secure. </li><li id="ptag"><a id="d8:a" href="http://www.dotnetrocks.com/default.aspx?showNum=285">285</a> - Comments about the Guid class and how <a id="hksj" title="System.IO.Packaging" href="http://msdn2.microsoft.com/en-us/library/system.io.packaging.aspx">System.IO.Packaging</a> is really useful for reading Office 2007 documents such as Word files) </li><li id="t7ku"><a id="tvz1" href="http://www.dotnetrocks.com/default.aspx?showNum=286">286</a> - <a id="d84q" title="Microsoft.Windows.Themes" href="http://msdn2.microsoft.com/en-us/library/microsoft.windows.themes.aspx">Microsoft.Windows.Themes</a>: Classes used by WPF to provide visual appearance that is similiar to Vista, XP, and Window 2000 and lower (Luna, Aero, Royale, and Classic). </li><li id="lzl10"><a id="xmx3" href="http://www.dotnetrocks.com/default.aspx?showNum=287">287</a>* - <a id="ykp-" title="System.IDisposable" href="http://msdn2.microsoft.com/en-us/library/system.idisposable.aspx">System.IDisposable</a>: Useful for controlling exactly when resources get released. An <a id="ddbn" title="talks about it" href="http://www.dotnetrocks.com/default.aspx?showNum=10">early Dotnetrocks</a> show with <a id="oei6" title="Chris Sells" href="http://www.sellsbrothers.com/">Chris Sells</a> talks about it in depth. </li><li id="my_3"><a id="thln" href="http://www.dotnetrocks.com/default.aspx?showNum=288">288</a> - No Better Know a Framework segment. </li><li id="rkn_"><a id="rcs3" href="http://www.dotnetrocks.com/default.aspx?showNum=289">289</a> - <a id="oy3y" title="System.ICloneable" href="http://msdn2.microsoft.com/en-us/library/system.icloneable.aspx">System.ICloneable</a>: Originally designed to provide a way of determining how to create a clone (copy) of an object. However, Brad Abrams recommends <a id="flkh" title="not to implement it" href="http://blogs.msdn.com/brada/archive/2004/05/03/125427.aspx">not to implement it</a> in public APIs since its semantics are confusing. </li><li id="yg1c"><a id="jqse" href="http://www.dotnetrocks.com/default.aspx?showNum=290">290</a> - <a id="cx6s" title="System.Security.Principal.WindowsPrincipal" href="http://msdn2.microsoft.com/en-us/library/system.security.principal.windowsprincipal.aspx">System.Security.Principal.WindowsPrincipal</a>: Contains methods for determining information about the current user's Windows account information (e.g. use <a id="dwpr" title="IsInRole" href="http://msdn2.microsoft.com/en-us/library/system.security.principal.windowsprincipal.isinrole.aspx"><br />IsInRole</a> to determine if the user is an administrator) </li><li id="hbz1"><a id="ad-q" title="291" href="http://www.dotnetrocks.com/default.aspx?showNum=291">291</a>* - <a id="anjv" title="System.GC" href="http://msdn2.microsoft.com/en-us/library/system.gc.aspx">System.GC</a>: Methods and properties pertaining to the built-in Garbage collector (see show #<a id="sals" title="287" href="http://www.dotnetrocks.com/default.aspx?showNum=287">287</a> notes as to how this relates to <a id="ykp-" title="System.IDisposable" href="http://msdn2.microsoft.com/en-us/library/system.idisposable.aspx">System.IDisposable</a>) </li><li id="no60"><a id="bu9d" href="http://www.dotnetrocks.com/default.aspx?showNum=292">292</a> - <a id="qxya" title="System.CodeDom" href="http://msdn2.microsoft.com/en-us/library/system.codedom.aspx">System.CodeDom</a> and <a id="y3_g" title="System.CodeDom.Compiler" href="http://msdn2.microsoft.com/en-us/library/system.codedom.compiler.aspx">System.CodeDom.Compiler</a> namespaces: Classes for manipulating source code and their compiled forms. </li><li id="hore"><a id="t.tp" href="http://www.dotnetrocks.com/default.aspx?showNum=293">293</a>* - <a id="mtw4" title="System.Math" href="http://msdn2.microsoft.com/en-us/library/system.math.aspx">System.Math</a>: Class containing many common math operations </li><ul id="tqa1"><li id="mhm6"><a id="j:6o" title="Max" href="http://msdn2.microsoft.com/en-us/library/system.math.max.aspx">Max</a> </li><li id="qkag"><a id="xevm" title="Min" href="http://msdn2.microsoft.com/en-us/library/system.math.min.aspx">Min</a> </li><li id="brc6"><a id="bfow" title="Abs" href="http://msdn2.microsoft.com/en-us/library/system.math.abs.aspx">Abs</a>olute Value </li><li id="c4vc"><a id="k8rx" title="Tan" href="http://msdn2.microsoft.com/en-us/library/system.math.tan.aspx">Tan</a>gent </li><li id="hflw"><a id="o..w" title="Floor" href="http://msdn2.microsoft.com/en-us/library/system.math.floor.aspx">Floor</a> </li><li id="chih"><a id="geiw" title="Sqrt" href="http://msdn2.microsoft.com/en-us/library/system.math.sqrt.aspx">Sqrt</a> </li><li id="kl76"><a id="dnxv" title="Sin" href="http://msdn2.microsoft.com/en-us/library/system.math.sin.aspx">Sin</a>e </li><li id="e_o6"><a id="yq33" title="Sinh" href="http://msdn2.microsoft.com/en-us/library/system.math.sinh.aspx">Sinh</a> </li><li id="o:sk"><a id="g2pc" title="IEEERemainder" href="http://msdn2.microsoft.com/en-us/library/system.math.ieeeremainder.aspx">IEEERemainder</a> </li><li id="l4mw"><a id="a5wi" title="BigMul" href="http://msdn2.microsoft.com/en-us/library/system.math.bigmul.aspx">BigMul</a>: returns full product of two 32 bit numbers (64 bit result) </li></ul><br /><li id="kne2"><a id="d:p_" href="http://www.dotnetrocks.com/default.aspx?showNum=294">294</a>* - <a id="kl4q" title="System.TimeSpan" href="http://msdn2.microsoft.com/en-us/library/system.timespan.aspx">System.TimeSpan</a>: Many methods and properties that are useful in working with a span of time (e.g. 30 minutes) </li><li id="jmo7"><a id="kcaa" href="http://www.dotnetrocks.com/default.aspx?showNum=295">295</a>* - <a id="abz3" title="System.WeakReference" href="http://msdn2.microsoft.com/en-us/library/system.weakreference.aspx">System.WeakReference</a>: Class that holds onto an object reference but gives clues to the garbage collector that the reference can be let go of if memory pressure arises. </li><li id="df.2"><a id="sqw." href="http://www.dotnetrocks.com/default.aspx?showNum=296">296</a> - <a id="svkz" title="System.DataMisalignedException" href="http://msdn2.microsoft.com/en-us/library/system.datamisalignedexception.aspx">System.DataMisalignedException</a>: Obscure exception that can be thrown if data is read from or written to memory that isn't aligned according to what the processor expected. </li><li id="d9pd"><a id="uwmz" href="http://www.dotnetrocks.com/default.aspx?showNum=297">297</a>* - <a id="p-1p" title="System.Text.RegularExpressions.Match" href="http://msdn2.microsoft.com/en-us/library/system.text.regularexpressions.match.aspx">System.Text.RegularExpressions.Match</a>: Regular expressions are very useful for parsing and manipulating text. See <a id="gixj" title="have reference" href="http://www.ilovejackdaniels.com/cheat-sheets/regular-expressions-cheat-sheet/">this reference</a> for a sampling of what types of patterns you can use. </li><li id="cz-b"><a id="vicg" href="http://www.dotnetrocks.com/default.aspx?showNum=298">298</a> - <a id="pxhn" title="System.Resources.IResourceReader" href="http://msdn2.microsoft.com/en-us/library/system.resources.iresourcereader.aspx">System.Resources.IResourceReader</a> interface: You can use a <a id="lst9" title="ResourceReader" href="http://msdn2.microsoft.com/en-us/library/system.resources.resourcereader.aspx">ResourceReader</a> or <a id="xrfs" title="ResourceWriter" href="http://msdn2.microsoft.com/en-us/library/system.resources.resourcewriter.aspx"><br />ResourceWriter</a> for using resources that can be stored elsewhere besides inside the assembly. </li><li id="fp.j"><a id="lt71" href="http://www.dotnetrocks.com/default.aspx?showNum=299">299</a> - <a id="b_:2" title="System.Web.HttpResponse.TransmitFile" href="http://msdn2.microsoft.com/en-us/library/12s31dhy.aspx">System.Web.HttpResponse.TransmitFile</a>: Provides a simple way to write a file to a stream. </li><li id="sf45"><a id="t_5j" href="http://www.dotnetrocks.com/default.aspx?showNum=300">300</a> - No Better Know a Framework segment </li><li id="nvlg"><a id="y6uw" href="http://www.dotnetrocks.com/default.aspx?showNum=301">301</a>* - <a id="j998" title="IEnumerator" href="http://msdn2.microsoft.com/en-us/library/system.collections.ienumerator.aspx">System.Collections.IEnumerator</a> and <a id="mgdi" title="" href="http://msdn2.microsoft.com/en-us/library/78dfe2yb.aspx">System.Collections.Generic.IEnumerator<t></t></a>: Interfaces used for specifying how to enumerate (go one by one) through a collection. </li><li id="wk6x"><a id="n9wg" href="http://www.dotnetrocks.com/default.aspx?showNum=302">302</a> - <a id="xfze" title="System.Speech.Synthesis" href="http://msdn2.microsoft.com/en-us/library/system.speech.synthesis.aspx">System.Speech.Synthesis</a> namespace: Classes for creating speech from text </li><li id="bp7i"><a id="lplo" href="http://www.dotnetrocks.com/default.aspx?showNum=303">303</a> - <a id="bfu7" title="Microsoft.VisualBasic.Compatibility.VB6" href="http://msdn2.microsoft.com/en-us/library/microsoft.visualbasic.compatibility.vb6.aspx">Microsoft.VisualBasic.Compatibility.VB6</a> namespace: Classes for handling compatibility with VB6 semantics in .net. </li><li id="rb:q"><a id="zt2e" href="http://www.dotnetrocks.com/default.aspx?showNum=304">304</a> - <a id="afi9" title="System.Drawing.Printing.PrintDocument" href="http://msdn2.microsoft.com/en-us/library/system.drawing.printing.printdocument_members.aspx">System.Drawing.Printing.PrintDocument</a>: Class that has methods and events (e.g. <a id="svcq" title="PrintPage" href="http://msdn2.microsoft.com/en-us/library/system.drawing.printing.printdocument.printpage.aspx"><br />PrintPage</a>) for easy use with printing. </li><li id="brfo"><a id="f4zy" href="http://www.dotnetrocks.com/default.aspx?showNum=305">305</a>*- <a id="r5.q" title="System.IComparable" href="http://msdn2.microsoft.com/en-us/library/system.icomparable.aspx">System.IComparable</a> and <a href="http://msdn2.microsoft.com/en-us/library/4d7sx9hd.aspx">System.IComparable<t></t></a>: Has a <a id="wevf" title="CompareTo" href="http://msdn2.microsoft.com/en-us/library/system.icomparable.compareto.aspx"><br />CompareTo</a> method to determine how two objects relate to each other (Carl focused on equals, but you can also do greater than and less than). </li><li id="h01d"><a id="wu2n" href="http://www.dotnetrocks.com/default.aspx?showNum=306">306</a> - <a id="gb6d" title="System.IO.Ports" href="http://msdn2.microsoft.com/en-us/library/system.io.ports.aspx">System.IO.Ports</a>: Classes like <a id="w9bv" title="SerialPort" href="http://msdn2.microsoft.com/en-us/library/system.io.ports.serialport.aspx">SerialPort</a> which are used for serial communications. </li><li id="jfiw"><a id="yo-i" href="http://www.dotnetrocks.com/default.aspx?showNum=307">307</a>* - Email from Thomas Betz about show #305 on <a id="r5.q" title="System.IComparable" href="http://msdn2.microsoft.com/en-us/library/system.icomparable.aspx">System.IComparable</a> discussing how it's most commonly used for sorting. The <a id="pmwm" title="System.Object.Equals" href="http://msdn2.microsoft.com/en-us/library/bsc2ak47.aspx">System.Object.Equals</a> and <a id="nbn7" title="System.IEquatable" href="http://msdn2.microsoft.com/en-us/library/ms131187.aspx">System.IEquatable</a> are better suited for determining equality. </li><li id="z0l2"><a id="u7vp" href="http://www.dotnetrocks.com/default.aspx?showNum=308">308</a> - HTTP Handlers implementing <a id="y7wg" title="System.Web.IHttpHandler" href="http://msdn2.microsoft.com/en-us/library/system.web.ihttphandler.aspx">System.Web.IHttpHandler</a>: For example, you can register your code to be called when IIS processes a certain file extension. </li><li id="c8nb"><a id="wbel" href="http://www.dotnetrocks.com/default.aspx?showNum=309">309</a>* - Discussion of C#'s <a id="e1m1" title="yield keyword" href="http://msdn2.microsoft.com/en-us/library/9k7k7cf0.aspx">yield keyword</a> and how it can be used. </li><li id="a1fd"><a id="a7iy" href="http://www.dotnetrocks.com/default.aspx?showNum=310">310</a>* - Discussion of the new <a id="gvpr" title="Type inference" href="http://en.wikipedia.org/wiki/Type_inference">type inference</a> feature in <a id="gr90" title="C#" href="http://www.danielmoth.com/Blog/2007/02/local-variable-type-inference-in-c-30.html">C# 3</a> and <a id="ea7." title="VB" href="http://blogs.msdn.com/timng/archive/2007/02/11/type-inference-in-visual-basic-part-1.aspx">VB 9</a> so that you don't have to bother defining an object's type. </li><li id="d_76"><a id="uyta" href="http://www.dotnetrocks.com/default.aspx?showNum=311">311</a> - <a id="qs0i" title="System.Web.IHttpModule" href="http://msdn2.microsoft.com/en-us/library/system.web.ihttpmodule.aspx">System.Web.IHttpModule</a>: Can be used to handle processing in the HTTP life cycle such as authentication, logging, and redirects. See <a id="bohf" title="Creating and Registering a Custom HTTP Module" href="http://msdn2.microsoft.com/en-us/library/ms227673.aspx">Creating and Registering a Custom HTTP Module</a> for more information. </li><li id="i1jr"><a id="brhe" href="http://www.dotnetrocks.com/default.aspx?showNum=312">312</a> - Discussion of the new <a id="ot2y" title="Anonymous Types" href="http://weblogs.asp.net/scottgu/archive/2007/05/15/new-orcas-language-feature-anonymous-types.aspx?CommentPosted=true">anonymous types</a> feature in C# 3 and VB 9. </li><li id="jv6x"><a id="xmfe" href="http://www.dotnetrocks.com/default.aspx?showNum=313">313</a> - S<a id="m6zo" title="" href="http://msdn2.microsoft.com/en-us/library/ms668604.aspx">ystem.Collections.ObjectModel.ObservableCollection<t></t></a>: Collection that has events for notification of when the collection has been modified. </li><li id="npyl"><a id="rvnw" href="http://www.dotnetrocks.com/default.aspx?showNum=314">314</a> - <a id="d8l9" title="System.Windows.Converters" href="http://msdn2.microsoft.com/en-us/library/system.windows.converters.aspx">System.Windows.Converters</a>: Classes like <a id="m6tb" title="Int32RectValueSerializer" href="http://msdn2.microsoft.com/en-us/library/system.windows.converters.int32rectvalueserializer.aspx">Int32RectValueSerializer</a> which are used by WPF to persist objects to a string. </li><li id="d7ln"><a id="bbb-" href="http://www.dotnetrocks.com/default.aspx?showNum=315">315</a>* - <a id="sbll" title="System.IFormattable" href="http://msdn2.microsoft.com/en-us/library/system.iformattable.aspx">System.IFormattable</a>: Allows you to specify special string formatting options in <a id="a-1g" title="String.Format" href="http://msdn2.microsoft.com/en-us/library/system.string.format.aspx"><br />String.Format</a> and <a id="s0gp" title="ToString" href="http://msdn2.microsoft.com/en-us/library/system.iformattable.tostring.aspx">ToString</a>. </li><li id="n4ma"><a id="gr_5" href="http://www.dotnetrocks.com/default.aspx?showNum=316">316</a> - S<a id="gmzs" title="" href="http://msdn2.microsoft.com/en-us/library/b3h38hb0.aspx">ystem.Nullable<t></t></a>: Generic wrapper for value types that allow for the possibility of a null. </li><li id="zm.q"><a id="ptgk" href="http://www.dotnetrocks.com/default.aspx?showNum=317">317</a> - <a id="efqf" title="System.Net.PeerToPeer" href="http://msdn2.microsoft.com/en-us/library/system.net.peertopeer.aspx">System.Net.PeerToPeer</a> namespace: Classes providing access to peer network functionality such as how peers discover each other using the Windows peer to peer infrastructure (e.g. PNRP - peer name resolution protocol) </li><li id="juq9"><a id="c_q4" href="http://www.dotnetrocks.com/default.aspx?showNum=318">318</a> - <a id="wfls" title="System.Net.PeerToPeer.Collaboration" href="http://msdn2.microsoft.com/en-us/library/system.net.peertopeer.collaboration.aspx">System.Net.PeerToPeer.Collaboration</a> namespace: Enhances the peer-to-peer networking functionality and provides capabilities for serverless, managed collaboration sessions. </li><li id="u:rk"><a id="qf2y" href="http://www.dotnetrocks.com/default.aspx?showNum=319">319</a>* - <a id="ang7" title="System.Linq.IQueryable" href="http://msdn2.microsoft.com/en-us/library/system.linq.iqueryable.aspx">System.Linq.IQueryable</a>: Used by LINQ to evaluate queries. <a id="yzyo" title="IQueryProvider" href="http://msdn2.microsoft.com/en-us/library/system.linq.iqueryprovider.aspx"><br />IQueryProvider</a> creates and executes these. </li><li id="b3mw"><a id="vae_" href="http://www.dotnetrocks.com/default.aspx?showNum=320">320</a> - <a id="woo7" title="System.IO.Pipes" href="http://msdn2.microsoft.com/en-us/library/system.io.pipes.aspx">System.IO.Pipes</a> namespace: Classes for working with interprocess communications using pipes. </li><li id="vyjn"><a id="q80g" href="http://www.dotnetrocks.com/default.aspx?showNum=321">321</a>* - <a id="ui9j" title="System.AppDomain" href="http://msdn2.microsoft.com/en-us/library/system.appdomain.aspx">System.AppDomain</a>: Encapsulates working with an application domain (a lighter weight than an process, but used by the CLR to provide isolation). See <a id="ipx9" title="show 8" href="http://www.dotnetrocks.com/default.aspx?showNum=8">show 8</a> with Rocky Lhotka for a discussion on them. </li><li id="c70p"><a id="dau." href="http://www.dotnetrocks.com/default.aspx?showNum=322">322</a> - <a id="i6xr" title="System.AppDomain.AssemblyResolve" href="http://msdn2.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx">System.AppDomain.AssemblyResolve</a> event: This method is raised if code in an AppDomain tries to find an Assembly and is not able to. See <a id="n-qs" title="on it" href="http://support.microsoft.com/kb/837908">this</a> knowledge base article for how to use it. </li><li id="qwqr"><a id="rj0e" href="http://www.dotnetrocks.com/default.aspx?showNum=323">323</a> - <a id="wsqf" title="System.AppDomain.DoCallBack" href="http://msdn2.microsoft.com/en-us/library/system.appdomain.docallback.aspx">System.AppDomain.DoCallBack</a> method: Useful for executing a callback in another AppDomain. </li><li id="un4:"><a id="v6:8" href="http://www.dotnetrocks.com/default.aspx?showNum=324">324</a> - <a id="k2gz" title="System.Web.Mobile" href="http://msdn2.microsoft.com/en-us/library/system.web.mobile.aspx">System.Web.Mobile</a> namespace: Classes for use with mobile web devices. <a id="lq_h" title="MobileCapabilities" href="http://msdn2.microsoft.com/en-us/library/system.web.mobile.mobilecapabilities.aspx"><br />MobileCapabilities</a> class can be used to determine things like a client's screen size. </li><li id="z8y3"><a id="es9i" href="http://www.dotnetrocks.com/default.aspx?showNum=325">325</a> - <a id="i37j" title="System.Delegates" href="http://msdn2.microsoft.com/en-us/library/system.delegate.aspx">System.Delegate</a>: Class encapsulating a single method; sort of like a function pointer but better. </li><li id="tn-8"><a id="s1.u" href="http://www.dotnetrocks.com/default.aspx?showNum=326">326</a> - More on <a id="i37j" title="System.Delegates" href="http://msdn2.microsoft.com/en-us/library/system.delegate.aspx">delegates</a> and how they are a combination of a code pointer plus the metadata including an invoke method. </li><li id="cftk"><a id="c6tj" href="http://www.dotnetrocks.com/default.aspx?showNum=327">327</a> - <a id="gluc" title="System.Configuration.IPersistComponentSettings" href="http://msdn2.microsoft.com/en-us/library/system.configuration.ipersistcomponentsettings.aspx">System.Configuration.IPersistComponentSettings</a>: Defines standard functionality for controls or libraries that store and retrieve application settings. </li><li id="exyr"><a id="k96y" href="http://www.dotnetrocks.com/default.aspx?showNum=328">328</a> - <a id="f:ez" title="System.Windows.Xps" href="http://msdn2.microsoft.com/en-us/library/system.windows.xps.aspx">System.Windows.Xps</a> namespace: Classes like <a id="xfhf" title="XpsDocumentWriter" href="http://msdn2.microsoft.com/en-us/library/system.windows.xps.xpsdocumentwriter.aspx"><br />XpsDocumentWriter</a> for saving XAML objects to a PDF like format. </li><li id="nprc"><a id="su80" href="http://www.dotnetrocks.com/default.aspx?showNum=329">329</a> - <a id="c7ih" title="System.Data.IDbDataAdapater" href="http://msdn2.microsoft.com/en-us/library/system.data.idbdataadapter.aspx">System.Data.IDbDataAdapater</a>: Interface used by <a id="li6t" title="System.Data.Common.DbDataAdapter" href="http://msdn2.microsoft.com/en-us/library/system.data.common.dbdataadapter.aspx"><br />System.Data.Common.DbDataAdapter</a> and others built from it to fill a <a id="lpap" title="DataSet" href="http://msdn2.microsoft.com/en-us/library/system.data.dataset.aspx"><br />DataSet</a> </li><li id="k.kv"><a id="oots" href="http://www.dotnetrocks.com/default.aspx?showNum=330">330</a> - <a id="wb5l" title="System.Net.Sockets" href="http://msdn2.microsoft.com/en-us/library/system.net.sockets.aspx">System.Net.Sockets</a> namespace: Classes for use with low-level socket communication. See DNR TV show (part <a id="v4ip" title="DNR tv show" href="http://www.dnrtv.com/default.aspx?showNum=46">part 1</a> and <a id="wfz5" title="2" href="http://www.dnrtv.com/default.aspx?showNum=47">2</a>) </li><li id="b9ld"><a id="sums" href="http://www.dotnetrocks.com/default.aspx?showNum=331">331</a> - No Better Know a Framework segment. </li><li id="kn6f"><a id="d0qp" href="http://www.dotnetrocks.com/default.aspx?showNum=332">332</a>* - <a id="pmnp" title="System.String" href="http://msdn2.microsoft.com/en-us/library/system.string.aspx">System.String</a><a id="dwm1" title="Compare" href="http://msdn2.microsoft.com/en-us/library/system.string.compare.aspx"> Compare</a> method: Useful for performing a culturally sensitive string comparison. See <a id="vxkd" title="System.Globalization.CompareOptions" href="http://msdn2.microsoft.com/en-us/library/system.globalization.compareoptions.aspx">System.Globalization.CompareOptions</a>. </li><li id="z2ji"><a id="snz3" href="http://www.dotnetrocks.com/default.aspx?showNum=333">333</a>* - <a id="c.i6" title="System.Diagnostics.Trace" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.aspx">System.Diagnostics.Trace</a>: Class used to trace (record) what paths are executed in your code. If you've ever used <a id="gkyd" title="Console.WriteLine" href="http://msdn2.microsoft.com/en-us/library/system.console.writeline.aspx">Console.WriteLine</a>, you'll find <a id="unky" title="Trace.Write" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.write.aspx">Trace.Write</a> and <a id="gnww" title="Trace.WriteLine" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.writeline.aspx">Trace.WriteLine</a> similar. They write to a listener. </li><li id="ties"><a id="e8ls" href="http://www.dotnetrocks.com/default.aspx?showNum=334">334</a>* - <a id="s_bf" title="System.Diagnostics.TraceListener" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.tracelistener.aspx">System.Diagnostics.TraceListener</a>: Base class used to implement trace listeners (destinations/outputs for <a id="unky" title="Trace.Write" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.write.aspx">Trace.Write</a>). For example <a id="cadq" title="TextWriterTraceListener" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.textwritertracelistener.aspx">TextWriterTraceListener</a> writes to text files. You can use a config file to add/modify the listener without modifying code. In addition, you can do it dynamically in code via the <a id="e5.f" title="Trace.Listeners" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.listeners.aspx">Trace.Listeners</a>.Add method. </li><li id="v82c"><a id="lzm_" href="http://www.dotnetrocks.com/default.aspx?showNum=335">335</a>* - <a id="oh87" title="System.IO.FileInfo" href="http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.aspx">System.IO.FileInfo</a>: Provides many details about a file: </li><ul id="fszt"><li id="bv6q"><a id="wgpr" title="length" href="http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.length.aspx">Length</a>/size </li><li id="xx9p"><a id="bzbu" title="CreationTimeUtc" href="http://msdn2.microsoft.com/en-us/library/system.io.filesysteminfo.creationtimeutc.aspx">CreationTimeUtc</a> </li><li id="wh46"><a id="pmzy" title="Directory" href="http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.directory.aspx">Directory</a> </li><li id="gnfp"><a id="yesr" title="DirectoryName" href="http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.directoryname.aspx">DirectoryName</a> </li><li id="jhxf"><a id="zwif" title="Exists" href="http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.exists.aspx">Exists</a> </li><li id="j9hb"><a id="e92h" title="LastAccessTime" href="http://msdn2.microsoft.com/en-us/library/system.io.filesysteminfo.lastaccesstime.aspx">LastAccessTime</a></li></ul><li id="u_m7"><a id="li:o" href="http://www.dotnetrocks.com/default.aspx?showNum=336">336</a>*: <a id="d15b" title="System.IO.MemoryStream" href="http://msdn2.microsoft.com/en-us/library/system.io.memorystream.aspx">System.IO.MemoryStream</a>: Provides an in-memory version of a <a id="zcxp" title="Stream" href="http://msdn2.microsoft.com/en-us/library/system.io.stream.aspx"><br />Stream</a>. Much easier to work with than a byte array.<br /></li></ul><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.moserware.com%2f2008%2f04%2fmy-better-know-framework-talk-at.html"><img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.moserware.com%2f2008%2f04%2fmy-better-know-framework-talk-at.html" border="0" /></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6800934446457898793-5950351308985742130?l=www.moserware.com'/></div>Jeff Moserhttp://www.blogger.com/profile/16074905903060665396noreply@blogger.com8tag:blogger.com,1999:blog-6800934446457898793.post-87536919286861360102008-04-16T07:12:00.002-04:002008-12-11T00:10:00.205-05:00Towards Moore's Law Software: Part 3 of 3<p>(<strong>Note:</strong> This is the third and final part of a series. <a href="http://www.moserware.com/2008/04/towards-moores-law-software-part-1-of-3.html">Part one</a> appeared Monday and <a href="http://www.moserware.com/2008/04/towards-moores-law-software-part-2-of-3.html">part two</a> appeared yesterday.)</p><p id="j7y2"><b id="ujck">First "STEPS"</b></p><p id="j7y2">Let's say we want to build the <a href="http://en.wikipedia.org/wiki/TCP/IP">TCP/IP</a> stack of an operating system. A <a id="c2a-" href="http://lxr.linux.no/linux/net/ipv4/tcp_ipv4.c">traditional implementation</a> might take 10,000 lines of code. What if you rethought the design from the ground up? What if you could make the IP packet handling code look almost identical to the <a id="ofzy" title="See " href="http://tools.ietf.org/html/rfc791">RFC 791 diagram</a> which defines IP? That's exactly what the <a href="http://www.vpri.org/html/people/team.htm">Viewpoints team</a> did. This is <i id="bxq8">real code</i> in their system:</p><p id="a1w6"><a id="qg-8" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_fYeN-Jc8I/AAAAAAAAAac/MqNzuL14I-o/s1600-h/ipheader.png"><img id="x915" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_fYeN-Jc8I/AAAAAAAAAac/MqNzuL14I-o/s400/ipheader.png" /></a></p><p id="y3h-">and the TCP stack is similar to the <a id="figl" title="See " href="http://tools.ietf.org/html/rfc793">RFC 793 diagram</a>:</p><p id="ajp_"><a id="oav_" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_fZlN-Jc9I/AAAAAAAAAak/_dJMMq3JO1E/s1600-h/tcpheader.png"><img id="tiu1" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_fZlN-Jc9I/AAAAAAAAAak/_dJMMq3JO1E/s400/tcpheader.png" /></a></p><p id="f78x">That's right; the <a href="http://en.wikipedia.org/wiki/ASCII_art">ASCII art</a> diagram <em>is</em> the code. How did they do it? Well, when you have a powerful "<a title="See page 10" href="http://www.vpri.org/pdf/steps_TR-2007-008.pdf">meta-meta language-language</a>" like their IS, you can define languages in a form that reads like a traditional <a id="nxox" href="http://en.wikipedia.org/wiki/Backus-Naur_form">Backus-Naur Form</a> (BNF) grammar representation:</p><br /><a id="pt6f" title="This is all it takes to define a languge" href="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_cAAN-Jc2I/AAAAAAAAAZs/eM3bX3tzrag/s1600-h/diagramcode.png"><img id="fma4" src="http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_cAAN-Jc2I/AAAAAAAAAZs/eM3bX3tzrag/s400/diagramcode.png" /></a><br /><br /><p id="tppk">With packet parsing out of the way, the implementation of their TCP algorithm is a little dense, but readable piece of code that handles the <a id="iidb" href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">SYN, ACK, and other responses</a>:</p><p id="huhh"><a id="abur" href="http://2.bp.blogspot.com/_Zfbv3mHcYrc/R_fZ29-Jc-I/AAAAAAAAAas/AjPoHl55uec/s1600-h/tcpipcode.png"><img id="v:-x" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/R_fZ29-Jc-I/AAAAAAAAAas/AjPoHl55uec/s400/tcpipcode.png" /></a> </p><p id="owni">With this as our basis, writing a service like the <a id="v-:k" href="http://en.wikipedia.org/wiki/DAYTIME">Daytime Service</a> is quite simple:</p><p id="qp03"><a id="jm:3" href="http://1.bp.blogspot.com/_Zfbv3mHcYrc/R_faRt-JdAI/AAAAAAAAAa8/NKjLQLskCts/s1600-h/daytimeservice.png"><img id="kym:" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/R_faRt-JdAI/AAAAAAAAAa8/NKjLQLskCts/s400/daytimeservice.png" /></a></p><p id="qp03">All told, the entire stack is comfortably under 200 lines of code without using any tricks like code generation wizards. The graphics subsystem is similarly clever. It basically defines everything as a polygon (including fonts, windows, etc). It's well under 500 lines of code. They have to be this compact in order to meet their goal of an entire system in under 20,000 lines.</p><p id="qp03">Another interesting metaphor in the project is the use of "massively parallel objects" or what <a href="http://www.vpri.org/pdf/NSF_prop_RN-2006-002.pdf">they refer</a> to as "particle fields," as <a title="Forward to 50:30" href="http://irbseminars.intel-research.net/AlanKay.wmv">a fundamental part</a> of the system:</p><blockquote id="zvm7"><p id="tsjf">"Even less in the mainstream, the “particle/field” idea [PF] has been found more in specialty areas (such as <a href="http://en.wikipedia.org/wiki/Finite_state_machine">finite-automata</a> and <a href="http://en.wikipedia.org/wiki/Finite_element_method">FEM</a>, <a href="http://en.wikipedia.org/wiki/Swarm_intelligence">swarm programming</a> in biology, etc.), than as a general system building tool (although it is the center of systems such as <a href="http://en.wikipedia.org/wiki/Sketchpad">Sketchpad</a> and <a href="http://en.wikipedia.org/wiki/TeX">TEX</a>, and is even found in an operating system such as <a href="http://portal.acm.org/citation.cfm?doid=122120.122122">MUSE</a>). <strong>Traditional object-oriented design has tended to overbalance its attention on the objects and to give too rudimentary attention to message-passing</strong>. If the center of attention were to be shifted to messaging of all kinds, then the notion of “fields” immediately suggests itself as a more general way to think about inter-object relationships (the previous example of “ants distributing and sensing pheromones” is a good metaphor of this style)."</p></blockquote><p id="sdup">For example, this idea can be applied to text formatting where you essentially treat <em>every letter </em>as its own object. Programming the solution then becomes much easier. You can have simple rules where you just look out for your immediate neighboring letters and then use an extremely efficient message passing system to make your simple code work in a very efficient manner. Here's a sample demonstration from their <a title="See page 9" href="http://www.vpri.org/pdf/NSF_prop_RN-2006-002.pdf">NSF proposal</a>:</p><p><a id="euut" title="See page 8" href="http://www.vpri.org/pdf/NSF_prop_RN-2006-002.pdf"><img id="bt.y" src="http://1.bp.blogspot.com/_Zfbv3mHcYrc/R_jFkd-JdBI/AAAAAAAAAbE/VPkWsZQds6c/s400/particlefieldletters.png" /></a> </p><p id="brti"><a title="" href="http://www.flickr.com/photos/antmoose/91813052/" two="two" flocks="flocks" joining="joining" each="each" by="by" on="on" anthony="Anthony"><img style="MARGIN: 10px 0px 10px 10px" src="http://2.bp.blogspot.com/_Zfbv3mHcYrc/SAFpDpGUpzI/AAAAAAAAAbM/8VXXY-1YAFg/s320/twoflocksjoining.jpg" align="right" /></a> This reminds me of ideas from "<a href="http://www.wnyc.org/shows/radiolab/episodes/2005/02/18">emergence</a>" which is a theory that explains how a <a href="http://en.wikipedia.org/wiki/Flocking_%28behavior%29">flock of birds</a> or an <a href="http://en.wikipedia.org/wiki/Swarm_intelligence">ant colony</a> can do complex things even though each individual in the system thinks simple thoughts. An individual bird is only thinking in terms of simple rules like "try to follow the guy in front of you" and "get out of the way if something dangerous is nearby." Just these two rules alone can lead to the fantastically complicated formations that we see in the sky.</p><p id="nmp2">The massively parallel objects with efficient messaging metaphor leads to algorithms that are simpler in concept because you can focus on the behavior of one little object rather than have to worry about how the whole system works.</p><p id="ybqu"><b id="baeh">"I want it <a href="http://www.youtube.com/watch?v=Z9obgyYB1IU&amp;feature=related">now</a>!" </b></p><p id="z58z">With the Viewpoints team only in their second year of a five year project, we can get a feel for where the future of software development is going, but we can't realistically put it into production quite <em>yet</em>. What are our options then? </p><p><a id="jm5t" href="http://blogs.tedneward.com/">Ted Neward</a> likes <a id="emfh" href="http://www.oopsla.org/podcasts/Episode13_Aggressive_Learning.mp3">to</a> <a id="qj:f" href="http://channel9.msdn.com/Showpost.aspx?postid=394826">talk</a> <a href="http://www.dotnetrocks.com/default.aspx?showNum=332">about</a> how the next five years will be about programming languages attempting to bridge the "huge disconnect between the practitioners, the guys who get stuff done, and the academics, who think about how we get things done." He says this disconnect exists because "the academics and the practitioners don't talk to each other." I really think that the next five years we'll see significant strides towards improving the situation. If you want to jump ahead of the curve, I think it's worthwhile start imagining a dream language that would help you cut along the "natural joints" of a problem you work on. Can you think of an expressive language like the ASCII art for parsing TCP/IP headers that is targeted for <em>your</em> specific problem? </p><p>Another interesting observation Ted made was that:</p><blockquote><p>"... programming languages, much like human languages, are expressions not just of concepts within them, but also the environment in which they were born."</p></blockquote><p>That is, no language is perfect. Each language has a culture that gave birth to it which was usually focused on a particular type of problem. I often find that I put myself in too much of a language box and unfortunately <a href="http://www.bartleby.com/59/3/ignoranceisb.html">am happy</a> in that box. This led to me asking Alan Kay about the best way to cope with a design problem I had. The power to think in a highly tailored, but not necessarily general, programming language might end up being the best solution to problems we face.</p><p>If you go down this path, there are <a id="szec" href="http://www.antlr.org/">many</a> <a id="y116" href="http://jparsec.codehaus.org/NParsec+Tutorial">tools</a> and some <a id="f2-g" href="http://msdn2.microsoft.com/en-us/magazine/cc136756.aspx">good articles</a> available now to help you get started writing your own custom language. If you want to be a bit more conservative, you <a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html">can write an internal domain specific language</a> inside of host languages like Ruby or C#. However, if you go down the custom route, you'll benefit of doing it now rather than if you had done it 20 years ago because there are huge frameworks at your disposal like Microsoft's <a id="mb:e" href="htt