<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-13967713</id><updated>2011-12-29T16:30:14.585+01:00</updated><category term='AOP'/><category term='tools'/><category term='engineering'/><category term='process'/><category term='HCI'/><category term='quote'/><category term='multithreading'/><category term='UML'/><category term='multicore'/><category term='oop'/><category term='COM'/><category term='poll'/><category term='announce'/><category term='cloud'/><category term='algorithms'/><category term='concurrency'/><category term='profession'/><category term='form'/><category term='ASP.NET'/><category term='GUI'/><category term='C#'/><category term='C++'/><category term='article reference'/><category term='agile'/><category term='NOSD'/><category term='metrics'/><category term='analysis'/><category term='generics'/><category term='free time'/><category term='coding'/><category term='pattern'/><category term='real options'/><category term='windows'/><category term='link'/><category term='design'/><category term='quality'/><category term='modeling'/><category term='book reference'/><category term='project management'/><category term='requirements'/><category term='architecture'/><category term='teaching'/><category term='estimation'/><category term='database'/><category term='.NET'/><category term='thinking'/><category term='language design'/><title type='text'>Carlo Pescio - blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.carlopescio.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default?start-index=101&amp;max-results=100'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>303</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-13967713.post-5463363919044562014</id><published>2011-10-17T18:56:00.000+02:00</published><updated>2011-10-17T18:56:32.000+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='requirements'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><title type='text'>You're solving the wrong problem</title><content type='html'>&lt;img src="http://www.eptacom.net/blog/wrong.jpg" align="left" style="margin-right:16px;"&gt; It had to happen. After my post on &lt;a href="http://www.carlopescio.com/2011/06/cut-red-wire.html"  target="_blank"&gt;Yahtzee&lt;/a&gt;, my agile friend (Marco) has come back with more code katas, adding to the pile we already discussed. His latest shot was &lt;a href="http://codekata.pragprog.com/2007/01/kata_nine_back_.html"  target="_blank"&gt;Kata Nine&lt;/a&gt;, a.k.a. "Back to the CheckOut".&lt;br /&gt;His code was fine, really. Nothing fancy, basically a straightforward application of the Strategy pattern. You can find many similar implementations on the net (one of which prompted my tweet about ruby on training wheels, but it was more about the development style than the final result). Of course, my friend would have been disappointed if I had just said "yeah, well done!", so I had to be honest (where is the point of being friends if you can't be honest) and say "yeah, but you're solving the wrong problem".&lt;br /&gt;&lt;br /&gt;A short conversation followed, centered on the need to question requirements (as articulated by users and customers) and come up with the real, hidden requirements, the value of domain knowledge and the skills one would need to develop to become an effective analyst or "requirement engineer" (not that I suggest you do :-), with the usual drift into agility and such.&lt;br /&gt;&lt;br /&gt;I'll recommend that you read the problem statement for kata nine. It's not really necessary that you solve the problem, but it wouldn't hurt to think about it a little. I'm not going to present any code this time.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Kata Nine through the eye of a requirements engineer&lt;/b&gt;&lt;br /&gt;The naive analyst would just take a requirement statement from the user/customer, clean it up a little, and pass it downstream. That's pretty much useless. The skilled analyst will form a coherent [mental] model of the world, and move toward a deeper understanding of the problem. The quintessential tool to get there is simple, and we all learn to use it around age 4: it's called &lt;b&gt;questions&lt;/b&gt; :-). Of course, it’s all about the quality of the questions, and the quality of the mental model we're building . In the end, it has a lot to do with the way we look at the world, as explained by the concept of &lt;a href="http://en.wikipedia.org/wiki/Framing_(social_sciences)"  target="_blank"&gt;framing&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The problem presented in kata nine can be framed as a set of billing rules. Rules, as formulated, are based on product type (SKU), product price (per SKU) and a discount concept based on grouping a fixed quantity of items (quantity depending on SKU) and assigning a fixed price to that group (3 items 'A' for $1.30). It might be tempting for an analyst to draw a class diagram here, and for a designer to introduce an interface over the concept of rule, so that the applicability and the effects of a rule become just an implementation detail (you wish :-).&lt;br /&gt;&lt;br /&gt;Note how quickly we're moving from the real-world issues of products, prices, discounts into the computing world, made of classes, interfaces, information hiding. However, the skilled analyst will recognize some underlying assumptions and ask for more details. Here are a few questions he may want to ask, and some of the reasoning that may follow. Some are trivial, some are not. Sometimes, two trivial questions conjure to uncover a nontrivial interplay.&lt;br /&gt;&lt;br /&gt;- rules may intersect on a single SKU (3 items 'A' for $1.30, 6 for $2.50). Is that the case? Is there a simplified/simplifying assumption that  grouping by larger quantities will always lead to a more convenient price per unit? &lt;br /&gt;&lt;br /&gt;- without discounts, billing is a so-called &lt;i&gt;online process&lt;/i&gt;, that is, you scan one item, and you immediately get to know the total (so far). You just add the SKU price, and never have to re-process the previous items. &lt;br /&gt;If you have &lt;b&gt;at most&lt;/b&gt; one grouping-based discount rule per SKU, you still have a &lt;i&gt;linear process&lt;/i&gt;. You add one item, and you either form a new group, or add to the spare items. Forming a new group may require to recalculate the billing (just for the spares).&lt;br /&gt;If you allow more than one rule for the same SKU, well, it depends. Under the assumption above about convenience for larger groups, you basically have a &lt;i&gt;prioritized list of rules&lt;/i&gt;.  You add one item, and you have to reprocess the entire set of items with the same SKU. You apply the largest possible quantity rule, get a spare set, apply the larger quantity rule to that spare set, and so on, until only the default "quantity 1" rule applies. This is a linear, deterministic process, repeated every time you add a new item.&lt;br /&gt;In practice, however, you may have a rule for 3, 4, 5 items of the same SKU. A group of 8 items could then be partitioned in 4+4 or 5+3. Maybe 5+3 (which would be chosen by a priority list) is more convenient. Maybe not. Legislation tends to favor the buyer, so you should look for the most favorable partitioning. This is no longer a linear process, and the corresponding code will increase in complexity, testing will be more difficult, etc. &lt;br /&gt;Perhaps we should exclude these cases. Perhaps we just discovered a new requirement for another part of the systems, where rules are interactively created (we don't expect to add rules by writing code, do we :-). We need to dig deeper.&lt;br /&gt;Note: understanding when a requirement is moving the problem to an entirely new level of complexity is one of the most important moments in requirement analysis. As I said before, I often use the term "nonlinear decision" here,  implying that there is a choice: to include that requirement or not, to renegotiate the requirement somehow, to learn more about the problem and maybe discover that it's our lucky day and that the real problem is not what we thought. This happens quite often, especially when requirements are gathered from legacy systems. I discussed this in an old (but still relevant) paper: &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/probsol.pdf" target="_blank"&gt;When Past Solutions Cause Future Problems&lt;/a&gt;, IEEE Software, 1997.&lt;br /&gt;&lt;br /&gt;- grouping by SKU is still a relatively simple policy. At worst, you recalculate the partitioning for all the items of the same SKU that you're scanning, and deal with a localized combinatorial problem. Is that the only kind of rule we need? What about the popular "buy 3 items, get the cheapest for $1", that is not based on SKU? What about larger categories, like "buy 3 items in the clothing department, get the cheapest for $1"? A naive analyst may ignore the issue, and a naive designer may think that dropping an interface on top of a rule will make this a simple extension. That's not the case.&lt;br /&gt;Once you move beyond grouping by SKU, you have to recalculate the entire partitioning for &lt;b&gt;all&lt;/b&gt; scanned products every time a new product is scanned. You add a product B priced as $5. Which combination of products and rules results in the most favorable price? Grouping with the other 3 items with the same SKU, or with other 2 in the clothing department? Finding the most favorable partitioning is now a rule-based combinatorial process. New rules can be introduced at any time, so it's hard to come up with an optimization scheme. Beware the large family with two full carts :-). &lt;br /&gt;Your code is now two orders of magnitude harder than initially expected. Perhaps we should really renegotiate requirements, or plan a staged development within a larger timeframe than expected. What, you didn't investigate requirements, promised a working system in a week, and are now swamped? Well, you can always join the recurrent twitter riot against estimates :-).&lt;br /&gt;&lt;br /&gt;- Oh, of course you also have fidelity cards, don't you. Some rules apply only if you have a card. In practice, people may hand their card over only after a few items have been scanned. So you need to go back anyway, but that wouldn't be a combinatorial process per se, just a need to start over.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It gets much worse...&lt;/b&gt;&lt;br /&gt;There is an underlying, barely visible concept of time in the problem statement: &lt;i&gt;"this week we have a special offer"&lt;/i&gt;. So, rules apply only during a time interval.&lt;br /&gt;&lt;br /&gt;Time-dependent rules are tricky. The skilled analyst knows that it's quite simple to verify if a specific &lt;i&gt;instant&lt;/i&gt; (event) falls within an interval, and then apply the rules that happen to be effective at that instant. However, he also understands that a checkout is not an instantaneous process. It takes time, perhaps a few seconds, perhaps a few minutes. What if the two intervals overlap, that is, a rule is effective when checkout starts, but not when it ends (or vice versa)? The notion of "correctness", here, is relatively hard to define, and the store manager must be involved in this kind of decision. The interplay with the need to recalculate everything whenever a new item is scanned should be obvious: if you don't do anything about it, the implementation is going to choose for you.&lt;br /&gt;Note: traditionally, many businesses have tried to sidestep this sort of problem by applying changes to business rules "after hours". Banks, for instance, still rely a lot on nightly jobs, but even more so on the &lt;i&gt;concept&lt;/i&gt; of night. This safe harbor, however, is being constantly challenged by a 24/7 world. Your online promotion may end at midnight in your state, but that could be morning in your customer's state.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;... before it gets better :-)&lt;/b&gt;&lt;br /&gt;Of course, it's not just about finding more and more issues. The skilled analyst will quickly see that a fixed price discount policy (3 x $1.30) could easily be changed into a proportional discount ("20% off"). He may want to look into that at some point, but that's a secondary detail, because it's not going to alter the nature of the problem in any relevant way. Happy day :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Are we supposed to ask those questions?&lt;/b&gt;&lt;br /&gt;Shouldn't we just start coding? It's agile 2011, man. Implement the first user story, get feedback, improve, etc. It's about individual and interactions, tacit knowledge, breaking new ground, going into the unknown, fail fast, pivot, respond to change. Well, at least, it's just like that on Hacker News, so it must be true, right?  &lt;br /&gt;I'm not going to argue with that, if not by pointing out an old post of mine on &lt;a href="http://www.carlopescio.com/2006/07/self-fulfilling-expectations.html" target="_blank"&gt;self-fulfilling expectations&lt;/a&gt; (quite a few people thought it was just about UML vs. coding; it's the old "look at the moon, not at the finger" thing). How much of the rework (change) is actually due to changing business needs, and how much is due to lack of understanding of the &lt;b&gt;current&lt;/b&gt; business needs? We need to learn balance. Analysis paralysis means wasting time and opportunities. So does the opposite approach of rushing into coding.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;We tried having an analyst, but it didn't work&lt;/b&gt;&lt;br /&gt;My pre-canned, context-free :-) answer to this is: "no, your obsolete coder is not a skilled analyst". Here are some common traits of the &lt;b&gt;unskilled&lt;/b&gt; analyst:&lt;br /&gt;- ex coder, left himself become obsolete but knows something about the problem domain and the legacy system, so the company is trying to squeeze a little more value out of him.&lt;br /&gt;- writes lengthy papers called "functional specifications" that nobody wants to read.&lt;br /&gt;- got a whole :-) 3 days training on use cases, but never got the difference with a functional spec.&lt;br /&gt;- kinda knows entity-relationship, and can sort-of read a class diagram. However, he would rather fill 10 pages of unfathomable prose than draw the simplest diagram.&lt;br /&gt;- talks about web applications using CICS terminology.&lt;br /&gt;- the only Michael Jackson he ever heard about was a singer.&lt;br /&gt;- after becoming agile :-), he writes user stories like "as a customer, I want to pay my bill" (yeah, sure, whatever).&lt;br /&gt;- actually believes he can use a set of examples (or test cases) as a specification (good luck with combinatorial problems).&lt;br /&gt;&lt;br /&gt;More recurrent ineffective analysts: the marketer who couldn't market, the salesman who couldn't sale, the customer care who didn't care. Analysis is though. Just because Moron Joe couldn't do it, however, it doesn't mean it can't be done.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How to become a skilled analyst&lt;/b&gt;&lt;br /&gt;The answer is surprisingly simple:&lt;br /&gt;- you can't. It's too late. The discipline has been killed and history has been erased.&lt;br /&gt;- you shouldn't. Nobody is looking for a skilled analyst anyway. Go learn a fashionable language or technology instead.&lt;br /&gt;&lt;br /&gt;More seriously (well, &lt;i&gt;slightly&lt;/i&gt; more seriously), the times of functional specifications are gone for good, and nobody is mourning. Use cases stifled innovation for a long while, then faded into background because writing effective use cases was hard, writing crappy use cases was simple, and people usually went for simple. Users stories are a joke, but who cares. &lt;br /&gt;&lt;br /&gt;What if you want to learn the way of the analyst, anyway? Remember, a skilled analyst is &lt;b&gt;not&lt;/b&gt; an expert in a &lt;b&gt;specific&lt;/b&gt; domain (although he tends to grow into an expert in several domains). He's not the person you pay to get answers. He's the person you pay to get &lt;b&gt;better questions&lt;/b&gt; (and so, indirectly, better answers). &lt;br /&gt;The skilled analyst will ask different questions, explore different avenues, and find out different facts. So the essential skills would be observation, knowledge of large class of problems, classification, and description.  Description. Michael Jackson vehemently advocated the need for a discipline of description (see "Defining a Discipline of Description," IEEE Software, Sep./Oct. 1998; it's behind pay walls, but I managed to find a free copy &lt;a href="http://mcs.open.ac.uk/mj665/Missing6.pdf" target="_blank"&gt;here&lt;/a&gt;, until it lasts; please go read it). He noted, however, that we lacked suck a discipline; that was 1998, and no, we ain't got one meanwhile.&lt;br /&gt;&lt;br /&gt;Now, consider the patterns of thought I just used above to investigate potential issues: &lt;br /&gt;Rules -&gt; overlapping rules. &lt;br /&gt;Incremental problem -&gt; Priority list -&gt; Selective combinatorial problem -&gt; Global combinatorial problem. &lt;br /&gt;Time interval -&gt; overlapping intervals -&gt; effective rules.  &lt;br /&gt;The problem is, that kind of knowledge is nowhere to be learnt. You get it from the field, when it dawns on you. Or maybe you don't. Maybe you get exposed to it, but never manage to give it enough structure, so you can't really form a proto-pattern and reuse that knowledge elsewhere. Then you won't have 20 years of experience, but 1 year of experience 20 times over.&lt;br /&gt;&lt;br /&gt;Contrast this with more mature fields. Any half-decent mechanical engineer would immediately recognize cyclic stress and point out a potential &lt;a href=" http://en.wikipedia.org/wiki/Fatigue_(material)" target="_blank"&gt;fatigue&lt;/a&gt; issue. It's part of the basic training. It's not (yet) about solving the problem. It's about recognizing large families of recurrent issues.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C'mon, we got Analysis Patterns!&lt;/b&gt;&lt;br /&gt;Sort of. I often recommend Fowler's book, and even more so the lesser known volumes from David Hay (Data Model Patterns) and a few more, similar works. But honestly, those are not analysis patterns. They are "just" models. Some better and more refined than others. But still, they are just models. A pattern is a different beast altogether, and I'm not even sure we can have analysis patterns (since a pattern includes a solution resolving forces, and analysis is not about finding a solution). &lt;br /&gt;&lt;br /&gt;A few years ago &lt;a href="http://www.carlopescio.com/2007/12/problem-frames.html" target="_blank"&gt;I argued&lt;/a&gt; that &lt;i&gt;problem frame patterns&lt;/i&gt; were closer to the spirit of patterns than the more widely known work from Fowler, and &lt;a href="http://www.carlopescio.com/2008/02/problem-frames-and-dnc.html" target="_blank"&gt;later&lt;/a&gt; used them to investigate the applicability of Coad's Domain Neutral Component (which is another useful weapon in the analyst arsenal).&lt;br /&gt;&lt;br /&gt;However, in a maturing discipline of requirements engineering, we would need to go at a much finer granularity, and build a true catalog of recurring real-world problems, complete with questions to ask, angles to investigate, subtleties to work out. No solutions. It's not about design. It's not about process reengineering. It's about learning the problem.&lt;br /&gt;&lt;br /&gt;Again, I don't think we will, but here is a simplified attempt at documenting the Rules/Timing stuff, in a format somewhat inspired by patterns, but still new (and therefore, tentative).&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Name&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;Time-dependent Rules and Transactions&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Context&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;We have a set of Rules that must be checked during a Transaction. Rules are effective from time T1 to time T2. Time can be expressed in absolute terms (e.g. December 25, 2011, 12:00 AM), recurring terms (every Friday, 12:00 to 17:00), etc. A Transaction is a set of actions, taking place over time, with a non-negligible duration (that is, a transaction is not an instantaneous event). Rules may have to be checked several times during the lifetime of a single Transaction.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;The interval during which any given Rule is effective may overlap with the time interval required to carry over a transaction, that is, a rule may be effective when the transactions starts, but not when it ends, or vice versa, or may be valid for an interval beginning and ending inside the transaction time span (for long-lived transactions). Still, we need to guarantee some form of coherence in the observed behavior.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;[... the checkout problem would be a perfect fit here...]&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Issues and Questions&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;- Is there any kind of regulation dictating the system behavior?&lt;br /&gt;- Would the effect of simply applying rules effective at different times be noticeable?&lt;br /&gt;- Can the transaction be simplified into an instantaneous event?&lt;br /&gt;- Can we just "freeze" the rule set when the transaction starts? (there are two facets here: the real-world implications of doing so, and the machine-side implications of doing so).&lt;br /&gt;- Can we replay the entire transaction every time a new event is processed (e.g. a new item is added to the cart), basically moving everything forward in time?&lt;br /&gt;- etc.&lt;br /&gt;&lt;br /&gt;I don't know about you, but I would love to have a place where this kind of knowledge could be stored, cleaned up, structured, and curated. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;It would be easy to blame it all on agility. After all, a lot of people have taken agility as an excuse for "if it's hard, don't do it". Design has been trivialized to SOLID and Beck's 4 principles. Analysis is just gone. Still, I'm not going to. I've seen companies stuck in waterfall. It ain't pretty. But it's more and more obvious that we're stuck in just another tar pit, where a bunch of gurus keep repeating the same mantras, and the discipline is not moving forward. &lt;br /&gt;&lt;br /&gt;Coding is fascinating. A passionate programmer will stay up late to work on some interesting problem and &lt;i&gt;watch his code work&lt;/i&gt;. I did, many times, and I'm sure I'll still do for a long while. Creating models and descriptions does not seem to be on a par with that. There is some intellectual satisfaction in there too, but not near as much as seeing something actually &lt;i&gt;run&lt;/i&gt;. In the end, this might be the simplest, most honest explanation of why, in the end, we always come back to code.&lt;br /&gt;&lt;br /&gt;Still, we need a place, a format, a curating community for long-term, widely useful knowledge that transcends nitty-gritty coding issues (see also my concept of  &lt;a href="http://www.carlopescio.com/2010/03/where-is-your-knowledge.html" target="_blank"&gt;Half-Life of a Knowledge Repository&lt;/a&gt;). Perhaps we just need to make it fun. I like the way the guys at &lt;a href="http://thefuntheory.com/" target="_blank"&gt;The Fun Theory&lt;/a&gt; can turn everything into something fun (take a look at the piano stairs). Perhaps we should give requirements engineering another shot :-).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you read so far, you should &lt;a href="https://twitter.com/#!/CarloPescio" target="_blank"&gt;follow me&lt;/a&gt; on twitter.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Acknowledgement&lt;/b&gt;&lt;br /&gt;The image on top is a copy of &lt;a href="http://www.flickr.com/photos/johnnyjet/3290272880/" target="_blank"&gt;this picture&lt;/a&gt; from Johnny Jet, released under a creative common license with permission to share for commercial use, with attribution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-5463363919044562014?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/5463363919044562014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=5463363919044562014' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/5463363919044562014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/5463363919044562014'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/10/youre-solving-wrong-problem.html' title='You&apos;re solving the wrong problem'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8200746350171647910</id><published>2011-10-07T15:49:00.000+02:00</published><updated>2011-10-07T15:49:07.830+02:00</updated><title type='text'> Ricerca Programmatore WCF / HTML5 / ecc</title><content type='html'>Un mio cliente (centro di ricerca in zona La Spezia) cerca uno sviluppatore freelance per un progetto di 3-5 mesi.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;Conoscenze richieste:&lt;br /&gt;- silverlight, html5, css, javascript&lt;br /&gt;- C#, WCF, Service Oriented Architecture&lt;br /&gt;- programmazione ad oggetti&lt;br /&gt;&lt;br /&gt;Desiderabili:&lt;br /&gt;- ASP.NET&lt;br /&gt;- SQL Server&lt;br /&gt;- Sistemi GIS&lt;br /&gt;- Inglese ragionevole&lt;br /&gt;&lt;br /&gt;&amp;nbsp;Il lavoro sara' da svolgere in sede. E' ovviamente previsto un affiancamento, ma e' richiesta una buona autonomia nell'affrontare e risolvere i problemi. Il trattamento economico e' interessante. Mandatemi un CV all'indirizzo jobs@eptacom.net, faro' una prima scrematura e poi vi mettero' in contatto diretto con il team di sviluppo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8200746350171647910?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8200746350171647910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8200746350171647910' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8200746350171647910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8200746350171647910'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/10/ricerca-programmatore-wcf-html5-ecc.html' title='&lt;img src=&quot;http://www.eptacom.net/flagIta.gif&quot;/&gt; Ricerca Programmatore WCF / HTML5 / ecc'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-2070094895947897718</id><published>2011-09-02T16:52:00.001+02:00</published><updated>2011-09-02T16:58:48.974+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>Notes on Software Design, Chapter 15: Run-Time Entanglement</title><content type='html'>So, here I am, back to my unpopular :-) series on the Physics of Software. It's time to explore the run-time side of entanglement, or more exactly, begin to explore, as I'm trying to write shorter posts, hoping to increase frequency as well. &lt;br /&gt;A lot of time has gone by, so here is a recap from &lt;a href="http://www.carlopescio.com/2010/11/notes-on-software-design-chapter-12.html" target="blank"&gt;Chapter 12&lt;/a&gt;: &lt;i&gt;Two clusters of information are entangled when performing a change on one immediately requires a change on the other&lt;/i&gt; (to maintain overall consistency). If you're new to this, reading chapter 12, 13 and 14 (dealing with the artifact-side of entanglement) won't hurt.&lt;br /&gt;&lt;br /&gt;Moving to the run-time side, some forms of entanglement are obvious (like redundant data). Some are not. Some are rather narrow in scope. Some are far-reaching. I'll cover quite a few cases in this post, although I'm sure it's not an exhaustive list (yet).&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Redundancy&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;This is the most obvious form of run-time entanglement: duplicated information. &lt;br /&gt;Redundancy occurs even without your intervention: swap-file vs. RAM contents, 3rd-2nd-1st level cache vs. RAM and vs. caches in other cores/processors, etc; at this level, entanglement satisfaction is usually called &lt;b&gt;coherence&lt;/b&gt;. &lt;br /&gt;In other cases, redundancy is an explicit design decision: database replicas, mem-cached contents, etc. At a smaller scale, we also have redundancy whenever we store the same value in two distinct variables. Redundancy means our system is always on the verge of violating the underlying information entanglement. That's why caches are notoriously hard to "get right" in heavily concurrent environments without massive locking (which is a form of &lt;a href="http://www.carlopescio.com/2010/09/notes-on-software-design-chapter-10-run.html" target="blank"&gt;friction&lt;/a&gt;). This is strictly related with the &lt;a href="http://www.carlopescio.com/2011/05/cap-theorem-memristor-and-physics-of.html" target="blank"&gt;CAP Theorem&lt;/a&gt;, which I have discussed months ago, but I'll come back to it in the future.&lt;br /&gt;Just like we often try (through hard-won experience) to minimize redundancy in artifacts (the &lt;a href="http://media.pragprog.com/articles/may_04_oo1.pdf" target="blank"&gt;Keep it dry&lt;/a&gt; principle), we learnt to minimize redundancy in data as well (through normalization, see below), but also to somehow control redundancy through design patterns like the observer. I'll get back to patterns in the context of entanglement in a future post.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Referential Integrity&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;This is perhaps less obvious, but easy to understand. &lt;a href="http://en.wikipedia.org/wiki/Referential_integrity " target="blank"&gt;Referential integrity&lt;/a&gt;, as known within the relational database culture, requires (quoting Wikipedia) that &lt;i&gt;any field in a table that is declared a foreign key can contain only values from a parent table's primary key or a candidate key.&lt;/i&gt; That means you cannot remove some records unless you update others, or that you cannot create some records unless some other is in place. That's a form of entanglement, and now we can start to grasp another concept: the idea of transaction is born out of the need to have intermediate micro-states that do not respect the entanglement constraint, yet make those micro-states invisible. As far as the external observer is concerned, time is quantized, and transactions are the ticks.&lt;br /&gt;Interestingly, &lt;a href="http://en.wikipedia.org/wiki/Database_normalization" target="blank"&gt;database normalization&lt;/a&gt; is all (just? :-) about imposing a &lt;b&gt;specific form&lt;/b&gt; on data entanglement. Consider a database that is not in &lt;a href="http://en.wikipedia.org/wiki/Second_normal_form" target="blank"&gt;second normal form&lt;/a&gt;; I'll use the same example of the Wikipedia page for simplicity. Several records contain the same information (work location). If we change the work location for Jones, we have to update three records. This is entanglement through redundancy, of course. Normalization &lt;b&gt;does not&lt;/b&gt; remove entanglement. What it does is to impose a particular form on it: through foreign keys. That makes it easier to deal with entanglement within the relational paradigm, but it is not without consequences for modularity (which would require an entire post to explore). In a sense, this "standardization" of entanglement form could be seen as a form of dampening. Views, too, are a practical dampening tool (on capable hands). More on this in a future post.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Class Invariant&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;This, I must confess, was not obvious at all to recognize at first, which is weird in insight. A &lt;a href="http://en.wikipedia.org/wiki/Class_invariant" target="blank"&gt;class invariant&lt;/a&gt; is a constraint on the internal state (data) of any object of that class. That means, of course, that those data &lt;b&gt;cannot&lt;/b&gt; change independently. Therefore, they are entangled by definition. More precisely, a class invariant can often be stated as a set of predicates, and each predicate is revealing some form of entanglement between two or more data members.&lt;br /&gt;Curiously enough (or perhaps not :-), invariant must hold at the beginning/end of externally observable methods, though it can be broken during the actual execution of those methods. That is to say, public methods play the role of transactions, making time quantized once again.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Object Lifetime&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;Although this can be seen as a special case of class invariant (just like a cascade delete is ascribed to referential integrity) I'd like to make this explicit, for reasons we'll understand better in a future post. Some objects cannot outlive others. Some objects cannot be created without others. Reusing the terminology of &lt;a href="http://www.carlopescio.com/2011/01/notes-on-software-design-chapter-13-on.html" target="blank"&gt;chapter 13&lt;/a&gt;, this is a D-D or C-C form of entanglement. The same form of entanglement can be found underneath several DB normalization concepts, and thanks to the RT/Artifact dualism, will turn out to be a useful concept in the artifact world as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Toward a concept of tangling through procedural knowledge&lt;/b&gt;&lt;br /&gt;All the above, I guess, it's pretty obvious in hindsight. It borrows heavily on the existing literature, which always considered data as something that can be subject to constraints. The risk here is to fall into the "information as data" tar pit. Information is not data. Information includes procedural knowledge (see also my old posts &lt;a href="http://www.carlopescio.com/2008/09/lost.html" target="blank"&gt;Lost&lt;/a&gt; &lt;a href="http://www.carlopescio.com/2008/09/and-found.html" target="blank"&gt;... and Found?&lt;/a&gt; for more on the concept of Information and Alexandrian centers). Is there a concept of entanglement for procedural knowledge?&lt;br /&gt;&lt;br /&gt;Consider this simple spreadsheet:&lt;br /&gt;&lt;br /&gt;&lt;table border="1" cellspacing="0" cellpadding="4"&gt;&lt;tr style="background-color:#a0a0a0;"&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#a0a0a0;"&gt;1&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#a0a0a0;"&gt;2&lt;/td&gt;&lt;td&gt;200&lt;/td&gt;&lt;td&gt;240&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;That may look like plain data, but behind the curtain we have two formulas (procedural knowledge):&lt;br /&gt;&lt;br /&gt;A2=A1*B1&lt;br /&gt;B2=A2*1.2&lt;br /&gt;&lt;br /&gt;In the picture above, the system is stable, balanced, or as I will call it, in a &lt;b&gt;steady state&lt;/b&gt;. Change a value in A1 or B1, however, and procedural knowledge will kick in. After a short interval (during which the system is unbalanced, or as I'll call it, in a &lt;b&gt;transient state&lt;/b&gt;), balance will be restored, and &lt;b&gt;all data entangled through procedural knowledge&lt;/b&gt; will be updated.&lt;br /&gt;A spreadsheet, of course, is the quintessential &lt;a href="http://en.wikipedia.org/wiki/Dataflow" target="_blank" &gt;Dataflow&lt;/a&gt; system, so it's also the natural &lt;i&gt;trait d'union&lt;/i&gt; between knowledge-as-data and procedural knowledge. It should be rather obvious, however, that a similar reasoning can be applied to any kind of event-driven or reactive system. That kind of system is sitting idle (steady state) until something happens (new information entering the system and moving it to a transient state). That unleashes a chain of reactions, until balance has been restored.&lt;br /&gt;&lt;br /&gt;Baby steps: now, what was the old-school view of objects (before the watering down took place)? Objects were like tiny little machines, communicating through messages. Right. So invoking a method on an object is not really different than sending the object a message. We're still upsetting its steady state, and the procedural knowledge inside the method is restoring balance (preserving the invariant, etc.)&lt;br /&gt;&lt;br /&gt;So, what about the traditional, top-down, imperative batch system? It's actually quite straightforward now: invoking a function (even the infamous main function) means pushing some information inside the system. The system reacts by moving information around, creating new information, etc, until the output is ready (the new steady state). The glue between all that information is the procedural knowledge stored inside the system. Procedural knowledge is basically encoding the entanglement path for dynamic information.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Say that again?&lt;/b&gt;&lt;br /&gt;This is beginning to look too much like philosophy, so let's move to code once again. In any C-like languages, given this code:&lt;br /&gt;&lt;pre&gt;int a2 = a1 * b1;&lt;br /&gt;int b2 = a2 * 1.2;&lt;br /&gt;int a3 = a1 + b1;&lt;/pre&gt;we're expecting the so-called control-flow to move forward, initializing a2, then b2, then a3. In practice, the compiler could reorder the statements and calculate a3 first, or in between, and even the processor could execute the two instructions "out of order" (see the concept of "observable behavior" in the C and C++ standard). What we are actually saying is that a2 can be calculated given a1 and b1, and how; that b2 can be calculated given a2, and how; and that a3 can be calculated given a1 and b1, and how. The "can be calculated given ..." is an abstract interpretation of the code. That abstract interpretation provides the entanglement graph for run-time entities. The "how" part, as it happens, is more germane to the function than to the form, and in this context, is somehow irrelevant. &lt;br /&gt;&lt;br /&gt;What about the control-flow primitives, like iteration, choice, call, etc? Iteration and choice are nothing special: at run-time, a specific branch will be taken, for a specific number of times, resulting in a specific run-time entanglement between run-time entities. Call (procedure call, function call) is somewhat different, because it reveals the fractal nature of software: whatever happens inside the function is hidden (except via side effects) from the caller. The function will carry out its job, that is, will restore the fine-grained input-output balance upon invocation.&lt;br /&gt;&lt;br /&gt;This is the general idea of procedural knowledge: given an input, control-flow goes on, until the program reaches a steady state, where output has been produced. As noted above, due to the fractal nature of information, this process takes place at different levels. A component instance may still be in a transient state while some object contained in that instance is already back to a steady state.&lt;br /&gt;&lt;br /&gt;In this sense, a procedure (as an artifact) is how we teach a machine to calculate an output given an input, through the stepwise creation and destruction of entangled run-time information. Phew :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next steps&lt;/b&gt;&lt;br /&gt;The beauty of the Run-Time/Artifact dualism is that whatever we learn on one side, we can often apply on the other side (with the added benefit that many things are easier to "get" on one side or another). &lt;br /&gt;Here, for instance, I've introduced the concept of steady and transient state for run-time information. The same reasoning can be applied to the artifact side. Whenever you create, update or delete an artifact A1, if there is any other artifact that is entangled with A1, the system goes into an unbalanced, transient state. You have to apply work (energy) to bring it back to the steady state, where all the entangled information is properly updated (balanced). A nice quote from Leonardo da Vinci could apply here: "Motion is created by the destruction of balance" (unfortunately, I can't find an authoritative source for the quote :-). Motion in the information space is created by unsettling the system (moving to a transient state) until entanglement is finally satisfied again, and a steady state is reached. This is as true in the artifact space as in the run-time space.&lt;br /&gt;Overall, this has been more like a trampoline chapter, where a few notions are introduced for the benefits of forthcoming chapters. Here is a short list of topics that I'll try to explore at some point in the future:&lt;br /&gt;&lt;br /&gt;- The truth about multiplicity, frequency, and attraction/rejection in the run-time world.&lt;br /&gt;- As above, in the artifact world.&lt;br /&gt;- Moving entanglement between run-time and artifacts (we do this a lot while we design).&lt;br /&gt;- The Entanglement Diagram.&lt;br /&gt;- A few examples from well-known Design Patterns.&lt;br /&gt;- Cross-cutting concerns and Delocalized plans: relationships with entanglement.&lt;br /&gt;- More on distance, entanglement, probability of failure, and the CAP theorem.&lt;br /&gt;- Dampening (isolation). This will open a new macro-chapter in the Physics of Software series.&lt;br /&gt;&lt;br /&gt;If you read so far, you should &lt;a href="https://twitter.com/#!/CarloPescio" target="_blank"&gt;follow me&lt;/a&gt; on twitter, or perhaps even share this post (I dare you :-)&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-2070094895947897718?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/2070094895947897718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=2070094895947897718' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2070094895947897718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2070094895947897718'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/09/notes-on-software-design-chapter-15-run.html' title='Notes on Software Design, Chapter 15: Run-Time Entanglement'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-5459660748856496234</id><published>2011-06-29T17:18:00.008+02:00</published><updated>2011-06-30T00:02:02.051+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Cut the red wire!</title><content type='html'>&lt;img src="http://www.eptacom.net/blog/redWire.jpg" align="left" style="margin-right:16px;"&gt;We're all familiar with this scene: the good guys trying to save the day (or the world) by defusing a bomb. Quickly running out of time, they have to cut a wire. Failure is not an option. The red bar won't turn into a green bar.&lt;br /&gt;&lt;br /&gt;What if you had to write code that works &lt;b&gt;the very first time&lt;/b&gt;? What if you had &lt;b&gt;no chance to test&lt;/b&gt; your code, let alone fixing bugs? You got only one chance to run your code and save the world. Would that change the way you write? The way you think? How? What can you learn from that?&lt;br /&gt;&lt;br /&gt;Lest you think I'm kinda crazy: I'm not actually suggesting that you shouldn't test your code. I'm not actually suggesting that you stop doing your test-driven thing (if you do) or that you forget your test plan (if you have one), etc etc. &lt;br /&gt;Consider this like a stretching exercise. We may learn something useful just by going outside our comfort zone. Give it a try.&lt;br /&gt;&lt;p style="clear:both;"&gt;&lt;/p&gt;&lt;br /&gt;&lt;b&gt;Yahtzee&lt;/b&gt;&lt;br /&gt;[sorry guys, gotta go into Dr. Mallard mode for a while; you can breeze through this section, if you're the TL;DR type]&lt;br /&gt;&lt;br /&gt;I came to write this post, and to choose Yahtzee as the underlying problem, mostly because I like coincidences :-). &lt;br /&gt;&lt;br /&gt;A friend of mine, a relatively young programmer in love with everything agile, every once in a while shows me some "code kata" that he has completed. Not long ago, he came up with the &lt;a href="http://codingdojo.org/cgi-bin/wiki.pl?KataYahtzee" target="_blank"&gt;KataYahtzee&lt;/a&gt;. His code was, to use his words "completely covered by tests". After all, that's what today's gurus are &lt;b&gt;constantly&lt;/b&gt; talking about. Tests, tests, more tests (yawn). However, the code emerging from all those tests was in my opinion rather crappy (one of the benefits of friendship is that you can say this sort of things in a benign way and have them interpreted in a benign way :-). I muttered something about a better alternative, promised I would send him my code, then got caught in other stuff and never actually implemented a thing.&lt;br /&gt;&lt;br /&gt;Still, shortly after, I was visiting the blog of an acquaintance of mine (xpmatteo), and after leaving a &lt;a href="http://matteo.vaccari.name/blog/archives/602" target="_blank"&gt;comment&lt;/a&gt;, I read a few more things including a post about Yahtzee and the removal of conditionals and loops.&lt;br /&gt;&lt;br /&gt;That was yet another coincidence: I joked with my agile friend before, telling him that sooner or later, they would have raised the bar from anti-if to anti-while, anti-for, anti-pattern-matching, anti-list-comprehension, anti-recursion, etc :-). But I also truly liked the idea that by changing the underlying data structure you could make some rules extremely simple to check (I'm a big fan of the "smart data – stupid procedures" approach). Anyway, that reminded me of my promise, so I fired up my editor and then I closed it :-), because I'd better read the actual rules first (some would call me anti-agile for that, but I don't see why I can't leverage existing knowledge, when available).&lt;br /&gt;&lt;br /&gt;Having never played  Yahtzee before, I quickly discovered that the &lt;a href="http://en.wikipedia.org/wiki/Yahtzee" target="_blank"&gt;standard rules&lt;/a&gt; didn't match the rules in the kata page. However, you'll find them under "scoring variations". Reading wikipedia sorted out some of my doubts (is "13333" a double pair? No), so I was ready to actually write some code. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Before you get any further&lt;/b&gt;&lt;br /&gt;This is where I should ask you to try it on your own. You probably won't, but if you do, remember: you want your code to run the very first time. You can write a set of test cases, but if one fails, the game is over (unless the test case is wrong).&lt;br /&gt;&lt;br /&gt;Just to add a little juice: the modern twist on the opening scene is that shortly after the heroes manage to defuse the bomb, the countdown is restarted. So, here is your  second little bomb coming: if it actually works the first time, change the rules from the "kata version" to the traditional Yahtzee rules, quickly :-), and run a new set of test cases. We're counting on you.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Picking my tools&lt;/b&gt;&lt;br /&gt;My &lt;i&gt;alma mater&lt;/i&gt; was completely sold on formal methods, and I used to like them too. In practice, over a number of years now, I had very few chances (and then reasons) to apply formal methods in the real world. Therefore, I &lt;b&gt;won't suggest&lt;/b&gt; that you develop a formal proof of correctness for your code before you run it. &lt;br /&gt;&lt;br /&gt;The problem with a formal proof is that (in many cases) the proof is at least as complex as the code, sometimes more. I won't trust my only chance on a proof that is potentially more obscure than my code. After all, Donald Knuth &lt;a href="http://www-cs-faculty.stanford.edu/~knuth/faq.html" target="_blank"&gt;notoriously said&lt;/a&gt; &lt;i&gt;"Beware of bugs in the above code; I have only proved it correct, not tried it"&lt;/i&gt;. Sure, I may try to check my proof :-) with the help a theorem prover, but that would be cheating: in a sense, the prover would be &lt;i&gt;testing&lt;/i&gt; my proof. &lt;br /&gt;&lt;br /&gt;Another well-known technique to develop mission-critical code is the use of inspections and reviews. But then again, this is sort of cheating, because I would be using people to test my code (in their heads). That's a no-no. &lt;br /&gt;&lt;br /&gt;So, having ruled out old-school stuff like &lt;a href="http://en.wikipedia.org/wiki/Cleanroom_Software_Engineering" target="_blank"&gt;Cleanroom Software Engineering&lt;/a&gt;, and having removed TDD from the table at very beginning, let's move on. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Is that even possible?&lt;/b&gt;&lt;br /&gt;Of course, before we even start trying, it makes sense to ask if there is actually any hope to get a program working the very first time. Well, for simple problems, it's certainly possible. For instance, if you ask me to calculate the area of a circle with (say) 5 digits accuracy given the radius, I may just write something like:&lt;br /&gt;&lt;pre&gt;double Area( double radius )&lt;br /&gt;  {&lt;br /&gt;  return radius * radius * 3.1415926 ;&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;I would probably use a statically checked language (which is a bit like cheating, but not too much :-), just to catch any typo. After that, I would feel rather confident.&lt;br /&gt;&lt;br /&gt;Ok, that was easy. Indeed, it would have been even simpler/safer if my language had a PI constant. The language would have been closer to the problem I was trying to solve. Which is exactly what we need: a language where our problem can be explained in a simple, straightforward way. Here, I think, is the key to my approach to writing code that runs the first time (I actually do that in real life, just not every time – more on this later on). I could say it shortly like this: &lt;b&gt;Everything is simple when it has a direct mapping to your language&lt;/b&gt;. &lt;br /&gt;Quoting Ward Cunningham (from "Clean Code" by Bob Martin), "You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem". I won't trust my only chance on nothing less than beautiful code :-).&lt;br /&gt;&lt;br /&gt;Now, we can read this as the frequently preached "look for the best language for the problem at hand", and in a sense it's true, but truth is, once you get past a few obvious cases, you ain't gonna find a language that was made exactly for your problem. The alternative approach, of course, is to create a language that is made exactly for your problem. No, I'm not suggesting that you design a language and write a compiler first: remember, you can only run your code once. That includes your brand-new compiler. Do it if you want, but don't blame me if you manage to annihilate our civilization.&lt;br /&gt;&lt;br /&gt;Looking back at the trivial Area function, you can easily see that my language had a useful abstraction (a "double", meaning IEEE 754 floating-point math) together with a few basic operations. Say that I trust those abstractions and the underlying hardware. I also trust my Area function, simple and small as it is. Area, therefore, could be thought of as a &lt;b&gt;language extension&lt;/b&gt;, a new trusted abstraction.&lt;br /&gt;&lt;br /&gt;I could simply call this &lt;b&gt;"Compositional Correctness"&lt;/b&gt;: get your low-level abstractions right. Then build more abstractions on top of those, each so small and simple that it is trivially correct. Of course, you can do it the other way too (top-down), or you can mix the strategies. In a sense, it's just an application of C. A. R. Hoare's principle: &lt;i&gt;"there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult"&lt;/i&gt;. Well, sometimes, it doesn't have to be difficult.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listen to Your Problem&lt;/b&gt;&lt;br /&gt;I can almost hear the word "DSL" in the background, and indeed, a &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_language" target="_blank"&gt;Domain Specific Language&lt;/a&gt; may turn a complex problem into a trivial one. For instance, HTML is a pretty good DSL to create formatted, hyperlinked documents. &lt;br /&gt;DSLs are often associated with humongous graphical / modeling tools (and I'm not gonna trust my only chance with one of those) or with flexible languages like Ruby. Still, remember the old Bell Labs motto: "library design is language design". You don't really need to write your language: you can extend your language just by writing a library (like with Area). &lt;br /&gt;Of course, you need a programming language with some built-in flexibility (which is why I dislike overly restrictive languages), but you don't need to get too fancy. To prove my point, I'll use (modern) C# in what follows. I could have used good ol' C++ as well. Java would make a few things a little more cumbersome than I'd like to, but it could still be a viable option. Dynamic languages would do just fine. As usual, design decisions are way more important than little language-specific details.&lt;br /&gt;&lt;br /&gt;A DSL should speak the language of your problem. Therefore, the first step toward the creation of a DSL should be to carefully listen to your problem and understand the inner nature, the basic concepts upon which the problem structure is built. In a better world, this would be a widely researched, frequently applied process, but in this world, it's not (although you can find a few noteworthy works on DLSs). In practice, I first try to understand whether the problem "fits" with some of the categories I'm familiar with, like:&lt;br /&gt;&lt;br /&gt;- is it a unification / pattern matching problem? For instance, I could model a double pair like (x,x,y,y,z), and leave it as an implicit convention of the language that different letters will necessarily match different faces. This looks promising, until you look at some rules (like Large straight) that don't really fit that model. Sure, you can stretch the language a little, and allow literals: by the way, this is the approach taken by the original &lt;a href="http://rubyquiz.com/quiz19.html" target="_blank"&gt;Ruby Quiz&lt;/a&gt; solution, which inspired the kata, which inspired this post. However, if you look at the original Yahtzee rules for a Large straight, they won't fit with literals either (it's just five sequential dice). Pattern matching is not the real Yahtzee language. As an aside, having read the Ruby code, it just doesn't like like the kind of code I would trust to run flawlessly the first time :-).&lt;br /&gt;&lt;br /&gt;- is it an incremental counting problem? What I really loved in Matteo's post was the idea that you could simply keep a count of faces, and that would easily provide a score for several rules. However, he already showed that such technique won't cover all rules.&lt;br /&gt;&lt;br /&gt;- is it a map/reduce kind of problem? It doesn't really look like that, because the "map" is supposed to take a (k1,v1) pair and return a list of (k2,v2) pairs, to be grouped and reduced. I could shoehorn Yahtzee into this, but it doesn't look like a natural fit for its rules.&lt;br /&gt;&lt;br /&gt;- is it a filter and projection problem (a-la SQL)? This may actually work. Conditions can be expressed as filters. I can start with a sequence and, through a series of trivial filters, end up with an empty sequence (if there is no match for the rule) or with the surviving dice. At that point, it's basically a matter of taking the sum. Hmm, perhaps this could work. Time to dig a little deeper.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Why not SQL, then?&lt;/b&gt;&lt;br /&gt;At this point, it might be tempting to simply use SQL as a language. Alternatively, if you're familiar with .NET, you may want to try LINQ, which is basically a SQL-like syntax to play with collections. Well, why not. Here is a Pair scoring expressed as a LINQ statement:&lt;br /&gt;&lt;pre&gt;2 * &lt;br /&gt;(from d in dice group d by d into g &lt;br /&gt; where g.Count() &amp;gt;= 2 orderby g.Key&lt;br /&gt; descending select g.Key).FirstOrDefault();&lt;/pre&gt;&lt;br /&gt;Part of the trick here is that the select expression returns a collection of integers, and that FirstOrDefault will return the first element (the highest face with a pair in the original sequence) or 0, which is the default value for int. It works with any kind of sequence (IEnumerable). In my tests (yes, I tested this :-), I just used an array of integers to represent dice.&lt;br /&gt;&lt;br /&gt;The problem is, however, that this code has to be carefully read. I have seen production code full of statements like that, and to put it gently, it sucks. &lt;br /&gt;On the upside, it's control-flow free, so it should please a few people out there :-). More seriously, the absence of control flow should probably by a byproduct of the "right" Yahtzee language. Control flow makes code harder to read in one pass. If I have to trust the code, I'd like to read it and "get it" in one pass. Note, however, that absence of control flow is not a guarantee of readability (or testability, or whatever else). Standard SQL, for instance, is control-flow free, but I can hardly say that a lengthy query mixing inner and outer joins can be easily read and trusted. The LINQ query above has no control flow, but I wouldn't like my code to read like that. Part of the problem lies with the LINQ syntax, but another part of the problem is that we're relying on standard data structures (collections) and standard SQL-like instructions, and they don't speak the &lt;b&gt;problem language&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt; Sketching the Yahtzee language&lt;/b&gt;&lt;br /&gt;Language design is difficult and requires that we pay attention to many details and facets. We want the "procedural" part to become trivial: this is the point of the entire exercise. Sketching the language requires that we focus on a few rules, while keeping the others (or at least some of them) in the back of our mind, because the "right" language must be a good fit for most of them (ideally, all of them). However, picking two similar rules to begin with allows us to focus slightly better, without being too narrow. I'll pick the Pair and Double Pair rules.&lt;br /&gt;&lt;br /&gt;We also have to choose a language style. The "language style" inside Area was the familiar "infix operations" borrowed from math. Personally, I can't see that as a good fit for the Yahtzee rules. I'm pretty sure, however, that I'd like my rules to become one-liners, something you can understand by reading it once. I think a &lt;a href="http://en.wikipedia.org/wiki/Fluent_interface" target="_blank"&gt;Fluent Interface&lt;/a&gt; style will fit that role better.&lt;br /&gt;&lt;br /&gt;At this stage, I would not focus too much on [domain] classes. Sure, some classes are there just for the picking, as Bertrand Meyer said. Dice, Face, Roll, Rule, Score, etc. However, when you design a small DSL, starting with classes is not necessarily the right approach. More often than not, classes will emerge as the (Alexandrian) &lt;b&gt;centers&lt;/b&gt; of the conversations we're building. Still, we have to start somewhere, so I'll have an imaginary "roll" object (of unknown class) representing the roll we want to score against a rule.&lt;br /&gt;&lt;br /&gt;Let's give it a try. A trivial pair of one-liners for our rules could be:&lt;br /&gt;&lt;pre&gt;roll.GetHighestPair().Score();&lt;br /&gt;roll.GetTwoHighestPairs().Score();&lt;/pre&gt;&lt;br /&gt;however, this is &lt;b&gt;wrong&lt;/b&gt;. Sure, it looks like good old stepwise refinement, but in fact I'm just pushing the burden of Yahtzee rules on roll's shoulders. Rules can grow and change, roll should be a stable abstraction. &lt;br /&gt;Even this little step in the wrong direction, however, can teach us something: what if there is no pair? I surely don't want my rules to be choke-full of conditionals, as that would wreck my "read it once and see it's right" principle. So, we can already give some structure to our language:&lt;br /&gt;&lt;br /&gt;we are manipulating a collection of die (roll)&lt;br /&gt;the collection may go through several "stages" (the "filters" or "selections")&lt;br /&gt;at every stage, the collection may get empty, but never a null reference (that will avoid conditionals)&lt;br /&gt;the score of an empty collection is zero (which is consistent with Yahtzee)&lt;br /&gt;&lt;br /&gt;Ok, let's give it another try:&lt;br /&gt;&lt;pre&gt;roll.GetPairs().GetHighest().Score();&lt;br /&gt;roll.GetPairs().GetTwoHighest().Score();&lt;/pre&gt;&lt;br /&gt;this is marginally better, because we formed a few smaller concepts. We can ask a roll for pairs; we can ask a pairs collection for the highest (by face: that should be made more explicit in our language), or the two highest. However, it's still very tailored, and it does not support any other rule. As we progress, the other rules have to get slightly more in the foreground to help us shaping our language (yeah, it's really a &lt;a href="http://en.wikipedia.org/wiki/Gestalt_psychology" target="_blank"&gt;Gestalt&lt;/a&gt; process, but don't get me started on this :-). &lt;br /&gt;&lt;br /&gt;The problem with the concept of pair is that it's not general enough to appear in our language. We need something more general. In the end, Yahtzee as a selection language is mostly about filtering by face or by occurrences of dice, grouped by faces. Perhaps a class would help here, a group of dice with the same face:&lt;br /&gt;&lt;pre&gt;class DiceGroup&lt;br /&gt;  {&lt;br /&gt;    public DiceGroup(int f, int c)&lt;br /&gt;    {&lt;br /&gt;      Face = f;&lt;br /&gt;      Count = c;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int Face&lt;br /&gt;    {&lt;br /&gt;      get;&lt;br /&gt;      private set;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int Count&lt;br /&gt;    {&lt;br /&gt;      get;&lt;br /&gt;      private set;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int Score()&lt;br /&gt;    {&lt;br /&gt;      return Face * Count;&lt;br /&gt;    }&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;Now, I know some of you have been brainwashed :-) to the point that you feel the need to write a load of test cases for this class, but let's face it: it's basically as complex as Area, actually even less. I made it more complex than strictly needed, by using properties instead of plain public data, but that's giving me something back: immutability. A DiceGroup cannot be changed after construction. Not having to reason about mutable objects helps a lot in writing safe code, and Yahtzee is not a performance-critical problem, so I can afford it. DiceGroup is also a stable abstraction. Either you use it as-is, or you scrap it and use something else. There is no point in tweaking DiceGroup. Hence, a &lt;b&gt;real&lt;/b&gt; economic theory for software design (as opposed to babbling about the need to refactor every single line you ever wrote) would tell us that there is little value in drowning &lt;b&gt;this specific class&lt;/b&gt; in trivial test cases. &lt;br /&gt;Provocation: what if the best way to minimize the cost of change was to find a number of useful, small abstractions that &lt;b&gt;do not change&lt;/b&gt; at all, or rarely do, because they're in frictionless contact with the nature of the problem?&lt;br /&gt;&lt;br /&gt;Now that I have a DiceGroup, what is a Roll? Well, a Roll might be just a sequence of DiceGroup. I can take my 5 dice, organize them in 1 to 5 DiceGroup objects (depending on the actual faces) and call that sequence a Roll. I'll ignore the details of how to do that for now, and get back to it later. Let's say that a Roll will be immutable too, so whenever we filter a Roll, we get a new Roll.&lt;br /&gt;&lt;br /&gt;So, say that I roll my dice and I get 4, 4, 1, 4, 3. I'll organize them into three DiceGroup objects: {4,3}, {1,1}, {3,1} (read them as {Face,Count}). To score them as Pair, I would have to remove the two DiceGroup with Count &amp;lt; 2, but that's not enough: {4,3} must also be turned into {4,2}, because the idea of Pair is that you max out at 2 occurrences. Hmm. That's just like trimming. I could write Pairs just like:&lt;br /&gt;&lt;pre&gt;roll.TrimCountTo(2).TopFace().Score();&lt;/pre&gt;&lt;br /&gt;where both TrimCountTo and TopFace return a new Roll, filtered and changed as needed. The rule is pretty readable, and given the language conventions above about returning an empty sequence if there is no match for the filter, I'll just get 0 when there are no pairs.&lt;br /&gt;&lt;br /&gt;TwoPairs would require a little extension to the language, because TopFace is again a bit too tailored to the Pair rule. The language itself is also telling us that (if we listen closely) because a TopFace method should return a DiceGroup, not a Roll. That makes the language asymmetric, so operations are harder to combine, and I don't want that. Lucky enough, this is easy to fix: why not having a TopByFace(n) method returning a roll with the n best DiceGroup (by face)? Now I can write Pair and TwoPairs like:&lt;br /&gt;&lt;pre&gt;roll.TrimCountTo(2).TopByFace(1).Score();&lt;br /&gt;roll.TrimCountTo(2).TopByFace(2).Score();&lt;/pre&gt;&lt;br /&gt;[Un]surprisingly enough, those two little functions will get us many other rules for free:&lt;br /&gt;ThreeOfAKind: roll.TrimCountTo(3).Score();&lt;br /&gt;FourOfAKind: roll.TrimCountTo(4).Score();&lt;br /&gt;Yahtzee: r.TrimCountTo(5).Score();&lt;br /&gt;Chance: roll.Score();&lt;br /&gt;&lt;br /&gt;Yo, I like this. Rules are trivially correct. They can be created by combining a few operators. This looks like the right DSL, or part of it. You can't express all the Yahtzee rules with just two operators (TrimCountTo and TopByFace). Ones, Twos, ..., Sixes are out. Well, they can be easily brought in by mirroring TrimCountTo with TrimFaceTo. So, I will have:&lt;br /&gt;&lt;br /&gt;Ones: roll.TrimFaceTo(1).Score();&lt;br /&gt;etc...&lt;br /&gt;&lt;br /&gt;This is almost &lt;b&gt;too&lt;/b&gt; simple, isn't it? Well, when it gets &lt;b&gt;that&lt;/b&gt; easy, it's because the language "was made for the problem", to quote Ward again, or because our solution is in frictionless contact with the forcefield, to bring in Alexander once more.&lt;br /&gt;&lt;br /&gt;As usual, the thinking process is more important than code here. I &lt;b&gt;am&lt;/b&gt; getting feedback. Backtalk, actually. I'm just not getting it the way most people are used / taught to (by executing code). I'm getting feedback through a &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/ListenToYourToolsAndMaterials.pdf" target="_blank"&gt;reflective conversation with my material&lt;/a&gt;. I know, this is not what everyone is telling you. And please understand I'm not implying that you should stop testing your code. I'm just taking the path less traveled by to see what happens.&lt;br /&gt;&lt;br /&gt;What's left? Small straight (1,2,3,4,5), Large straight (2,3,4,5,6), Full house (two of a kind + three of a kind, exactly: as per instructions, (4,4,4,4,4) is not a Full house). These rules cannot be expressed yet. You may see a pattern here, however. The straights are basically trimming by face, but with multiple faces. Full house is trimming by count, but with multiple counts. This may suggest an improvement to our language: turn TrimCountTo into TrimCountsTo, and TrimeFaceTo into TrimFacesTo. Care must be taken, however, not to break the simplicity of the language by creating too powerful instructions. Perhaps an orthogonal operator should be brought in. This is already a very long post, and I still have a lot of code to show, so I'll leave this extension out. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Structure of the Yahtzee Language&lt;/b&gt;&lt;br /&gt;DiceGroup was trivial. I basically did that bottom-up. Roll might not be just as trivial, and so far we only know that we need a TrimCountTo, a TrimFaceTo, and a Score method. Now we have two forces to balance:&lt;br /&gt;We want Roll to be as trivial as possible. It has to work the first time! Honestly, this is the keystone now. DiceGroup was so trivial to be obviously correct. Rules are now so obvious that we can happily trust them. We need Roll to be so simple that we can trust it too.&lt;br /&gt;We want our DSL to be extendible. We're missing a few rules, and the "standard" Yahtzee rules were different as well. I don't want to tweak Roll to change or extend the rules: remember what I said about finding &lt;b&gt;stable&lt;/b&gt; abstractions.&lt;br /&gt;&lt;br /&gt;I've been talking about [programming] language design in the past, and how "good" languages should be largely extendible. A few built-in core concepts supporting most of the language itself, which would then largely be in a library. It's time to apply the same principle to the Yahtzee Language.&lt;br /&gt;&lt;br /&gt;Here is where our actual implementation language can help or hinder. C# is almost helpful here. A dynamic language, or a language with structural conformance for interfaces, would make the following code much shorter and easier to read. Anyway, the key concept here is that of an &lt;b&gt;open class&lt;/b&gt;, something that we can extend without breaking the basic abstraction and without creating subtypes (while still not breaking encapsulation). What we need is a "simple" Roll class with the core methods and a set of Extension Methods (in C# parlance) which implements the "upper layer" of our language. Score() will end up in Roll, while TrimCountTo, TrimFaceTo, and TopByFace will land in a RollLanguage class. Therefore, adding support for more rules won't require any change to existing classes. Just implement new extension methods. Of course, that in turn requires Roll to be flexible enough to support basically all the desirable extension methods.&lt;br /&gt;&lt;br /&gt;In practice, it's not that hard. Let's start with RollLanguage. Ideally, it would be something like this:&lt;br /&gt;&lt;pre&gt;static class RollLanguage&lt;br /&gt;  {&lt;br /&gt;    public static Roll TopByFace(this Roll groups, int minCount)&lt;br /&gt;    {&lt;br /&gt;    //trivial code here&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static Roll TrimCountTo(this Roll groups, int minCount)&lt;br /&gt;    {&lt;br /&gt;    //trivial code here&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static Roll TrimFaceTo(this Roll groups, int face)&lt;br /&gt;    {&lt;br /&gt;    //trivial code here&lt;br /&gt;    }&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;Let's go ahead and implement TrimFaceTo. This would be my first shot:&lt;br /&gt;&lt;pre&gt;public static Roll TrimFaceTo(this Roll groups, int face)&lt;br /&gt;{&lt;br /&gt;  return groups.Where(g =&amp;gt; g.Face == face);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;note that I'm using LINQ (not exactly, I'm using the Linq extension method Where, not the LINQ syntax). However, this is a very simple expression. Sure, you have to know C# and .NET, but that's basically returning a sequence with all the DiceGroup which have the specified face. Unfortunately that won't compile :-), for two simple reasons:&lt;br /&gt;&lt;br /&gt;1) Roll must be an IEnumerable&amp;lt;DiceGroup&amp;gt;, because that's what Where expects.&lt;br /&gt;2) Where will then return an IEnumerable&amp;lt;DiceGroup&amp;gt;, not a Roll.&lt;br /&gt;&lt;br /&gt;(1) Is relatively trivial to fix, and while doing so, we'll sketch Roll as well:&lt;br /&gt;&lt;pre&gt;class Roll : IEnumerable&amp;lt;DiceGroup&amp;gt;&lt;br /&gt;{&lt;br /&gt;  public IEnumerator&amp;lt;DiceGroup&amp;gt; GetEnumerator()&lt;br /&gt;  {&lt;br /&gt;    return diceByFace.GetEnumerator();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()&lt;br /&gt;  {&lt;br /&gt;    return diceByFace.GetEnumerator();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private IEnumerable&amp;lt;DiceGroup&amp;gt; diceByFace;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This is a boilerplate code (partially generated by Visual Studio), that I wouldn't need with dynamic languages (or with structural conformance). It's pretty trivial though: Roll has-a and is-a IEnumerable&amp;lt;DiceGroup&amp;gt;. It implements the interface by forwarding to the data member. I'm rather confident that it's correct.&lt;br /&gt;&lt;br /&gt;(2) Requires that we tweak our code a little (again, this wouldn't be necessary in a more flexible programming language). Code speaks better than words here:&lt;br /&gt;&lt;pre&gt;public static Roll TrimFaceTo(this Roll groups, int face)&lt;br /&gt;{&lt;br /&gt;  return groups.Where(g =&amp;gt; g.Face == face).AsRoll();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static Roll AsRoll(this IEnumerable&amp;lt;DiceGroup&amp;gt; r)&lt;br /&gt;{&lt;br /&gt;  return new Roll(r);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;All methods in RollLanguage can be implemented over Linq, but have to end with AsRoll() to convert the IEnumerable into an actual Roll. Yeah, it sucks, but the alternative (getting rid of DiceGroup and Roll altogether) is even worse (I'll touch on this later on). An implicit conversion operator would be ok, but C# does not allow implicit conversion from interfaces.&lt;br /&gt;&lt;br /&gt;So, here is TrimToCount:&lt;br /&gt;&lt;pre&gt;public static Roll TrimCountTo(this Roll groups, int minCount)&lt;br /&gt;{&lt;br /&gt;  return groups.Where(g =&amp;gt; g.Count &amp;gt;= minCount).Select(&lt;br /&gt;    g =&amp;gt; new DiceGroup(g.Face, minCount)).AsRoll();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Honestly, this is a borderline function. You need to be somewhat confident with Linq to get it the first time through. Basically, I'm filtering by count (that's the easy part) and then I'm capping the count by creating a new DiceGroup with the same face and minCount as the actual count. I can trust this, but if you don't, I'll understand :-). Simpler code is welcome!&lt;br /&gt;&lt;br /&gt;So far I managed to avoid any kind of conditional. I didn't want any IF in my rules, and I didn't need any in RollLanguage thus far. However, my most readable TopByFace implementation is if-based:&lt;br /&gt;&lt;pre&gt;public static Roll TopByFace(this Roll groups, int minCount)&lt;br /&gt;{&lt;br /&gt;  if( groups.Count() &lt; minCount )&lt;br /&gt;    return Roll.Empty();&lt;br /&gt;  else&lt;br /&gt;    return groups.OrderByDescending(g =&amp;gt; g.Face).Take(minCount).AsRoll();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The idea is simple: if I don't have at least minCount groups, the filter fails and an empty roll must be returned. Otherwise, I can simply use Linq again, sort my groups by face (descending) and take the first minCount groups. Again, this might be borderline for someone uncomfortable with Linq. Looks pretty trivial to me, but simpler code would be welcome; actually, if you are an anti-if devotee, feel &lt;b&gt;morally obliged&lt;/b&gt; to show me how to improve that code &lt;b&gt;and&lt;/b&gt; get rid of the if (using a ternary operator is not a real alternative, of course). Pushing the IF in a custom version of Take is possible, but that would be just moving it around (with an interesting trade/off in efficiency Vs. reusability).&lt;br /&gt;&lt;br /&gt;By writing this code, we already got a set of requirements for Roll. Must be (and have) an IEnumerable&amp;lt;DiceGroup&amp;gt;; must have a Score() method; must have an Empty() static method returning an empty sequence; must be constructable from a IEnumerable&amp;lt;DiceGroup&amp;gt; (trivial); we also need the "real" constructor, taking a sequence (or array) of integers (the 5 dice) and doing the actual grouping. We have already seen part of the code above, so I'll add the trivial parts here and leave the "hard" constructor last:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Roll : IEnumerable&amp;lt;DiceGroup&amp;gt;&lt;br /&gt;{&lt;br /&gt;  public Roll(IEnumerable&amp;lt;DiceGroup&amp;gt; dice)&lt;br /&gt;  {&lt;br /&gt;    diceByFace = dice;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public int Score()&lt;br /&gt;  {&lt;br /&gt;    return diceByFace.Sum(g =&amp;gt; g.Score());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public static Roll Empty()&lt;br /&gt;  {&lt;br /&gt;    return empty;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private IEnumerable&amp;lt;DiceGroup&amp;gt; diceByFace;&lt;br /&gt;  private static int[] emptyArray = new int[0];&lt;br /&gt;  private static Roll empty = new Roll(emptyArray);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OK. Once again, this is so trivial that I can trust it. Now let's get over with the grouping; lucky me, I can simply use Linq once again:&lt;br /&gt;&lt;pre&gt;public Roll(int[] dice)&lt;br /&gt;{&lt;br /&gt;  diceByFace = dice.GroupBy(x =&amp;gt; x).Select(&lt;br /&gt;    g =&amp;gt; new DiceGroup(g.First(), g.Count()));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Once again, this is borderline if you aren't familiar with Linq. I'm grouping by faces, and for each group I'm building a DiceGroup object with face and count. I'd like a simpler syntax (g.First() is not exactly obvious) but this is what Linq provides me with. Usually, I'd also add an assertion that dice has 5 elements. I left that out to keep my code shorter.&lt;br /&gt;&lt;br /&gt;Interestingly, although I ignored performance, concurrency, etc so far, it would be rather simple to translate all this code in high-performance C++, using mutable stack-based objects, because in Yahtzee we're always dealing with (at most) 5 dice, so everything could be pre-allocated at fixed size. I would have to re-create some of the Linq extension methods, but C++11 has got lambda, so the overall style could stay the same.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wrap it up (and extend it)&lt;/b&gt;&lt;br /&gt;We're basically through. At this point, everything else is cosmetic. How do I group rules? Do I need a Rule interface? Well, in C#, I could just use a delegate for that. Can I just use member functions in a Yahtzee class and get over with it? Sure, unless we're concerned about a hierarchy of Yahtzee games (standard, non-standard, etc). Also, organizing rules into an array or dictionary might be the simplest way to glue them to the UI (which I'm not going to write). Since this is all basically irrelevant to our quest, I just wrote a set of one-line member functions.&lt;br /&gt;&lt;br /&gt;Part 2 of the problem was to change rules to the original Yahtzee scoring. For instance, adopting the original rules a Three-Of-A-Kind will get you the sum of all dice (not just the 3 of a kind). The simplest way, perhaps a bit too technical, would be to do it like this:&lt;br /&gt;&lt;pre&gt;Math.Sign( ScoreThreeOfAKind( roll ) ) * roll.Score()&lt;/pre&gt;&lt;br /&gt;Alternatively, you can create new filters, returning the original roll (if the filter is passed) or an empty roll. It's basically trivial now. &lt;br /&gt;&lt;br /&gt;In the end, I didn't create classes like Dice or Face. They would add some value (by forcing constraints) but I don't want to get too serious with this code :-). &lt;br /&gt;&lt;br /&gt;The entire code is &lt;a href="http://www.eptacom.net/blog/Yahtzee.cs" target="_blank"&gt;here&lt;/a&gt;. For simplicity, I used a single file. I added a few tests in the end, so that I could either succeed or fail when I finally ran the code (it worked!). In the end, I sort of like it. It's not perfect, but is pretty good. Feel free to improve it, in which case, I'd like to know!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Winding down&lt;/b&gt;&lt;br /&gt;Even though I've written so much, there would be much more to say. I'll give you the short version:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bad abstraction vs. Good abstraction&lt;/b&gt;&lt;br /&gt;strictly speaking, I wouldn't need any "base" abstraction like DiceGroup and Roll in my Yahtzee language. I could write every single function as an extension method of standard library classes. Why should I use concrete, non-reusable terms like Roll and DiceGroup when I could just  use &lt;b&gt;IEnumerable&amp;lt;IGrouping&amp;lt;int, int&amp;gt;&amp;gt;&lt;/b&gt;? Arguably, my code would be "more abstract", "more mathematic", and therefore "better" by sticking to abstract, domain-independent interfaces. Here, I think, my programming style differs from some. I used to like the idea of abstracting the domain &lt;i&gt;away&lt;/i&gt; from my code, perhaps 20 years ago or so. I guess it was some sort of academic imprinting. However, over time I moved into a different coding style, where abstractions are taken from the problem domain, not from abstract math. This allows me to focus on the real-world, concrete problem I want to solve; to speak the language of the problem, with people and with my code; and to leave behind me code that can be more easily understood by people who know about the problem domain, and perhaps a little less about computer science. I hinted at this issue in the past, as in my &lt;a href=" http://www.carlopescio.com/2008/10/microblogging-is-not-my-thing.html" target="_blank"&gt;mind map&lt;/a&gt; about habitable software, and even before, without ever taking time to do it justice. Perhaps this post will fill part of that gap.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Code quality&lt;/b&gt;&lt;br /&gt;As I discussed my code with my friend, he sort of liked it. He couldn't fully admit it, because hey, I had no tests in place, but he obviously felt it was much easier to read &lt;b&gt;and&lt;/b&gt; to evolve. Of course, popular authors would say that it's bad code anyway: "Code without tests is bad code. It doesn't matter how well written it is; it doesn't matter how pretty or object-oriented or well-encapsulated it is" (Michael C. Feathers, "Working Effectively with Legacy Code"). This is pretty harsh, because if I had to choose between the code above (with this blog post as the dreaded "comprehensive documentation") and some crappy code entirely covered by tests, I would have a hard time choosing the latter. &lt;br /&gt;Curiously enough, for a very long time testability has been like the stepchild of -ilities. In the past few years, the pendulum swung too far on the other side, and now it's all about tests. &lt;br /&gt;Since it's way too easy to babble and pontificate, I'd like someone to write much better code than mine (and yeah, &lt;b&gt;completely different&lt;/b&gt;, thank you) using TDD, and show me the process through which tests are driving him toward that code. If you ain't got code, please don't bother leaving a comment about the greatness of TDD and how dumb I am for even trying to write code without using tests. OTOH, if you got code to back up your claims, you're more than welcome. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Limits and confessions&lt;/b&gt;&lt;br /&gt;I'm making a habit to conclude with a few confessions, so here I come. I don't always write code this way. I tend to: I like my code to work the first time. However, it took me more than the allotted time of 1h to complete my mission. Writing the code was easy. Thinking about the language, trying out a few different styles, rejecting options, etc, was not, and almost never is. &lt;br /&gt;The "little DSL" approach requires a clarity of thought that we can't always afford, and it does not necessarily pay off. Yahtzee is also quite simple, and requirements were well-known. Again, that's a luxury we don't face so often (although I don't buy the idea that we never know what we're doing; deep inside uncertainty there is often a core of stable concepts, if you take the time to dig it out).&lt;br /&gt;There are also limits to the applicability of these techniques. Not every single problem lends itself well to the DSL approach. As usual, we have to be flexible, understand the nature of the problem, and choose the best design &lt;b&gt;strategy&lt;/b&gt;. A DSL was just particularly well-suited for Yahtzee.&lt;br /&gt;Indeed, a few years ago I spent some time doing a [little] upfront design, followed by implementation, for the &lt;a href="http://www.carlopescio.com/2007/07/get-ball-rolling-part-1-of-4-i-guess.html" target="_blank"&gt;bowling problem&lt;/a&gt;. Back then, my aim was to show that you don't have to give up on OOP and OOD so easily, and that by sticking to OOD you won't end up with a LOC monster as it was suggested elsewhere. I didn't use a DSL back then, but of course, it's quite possible to combine a little upfront OOD with a little DSL-like library with a little emergent design. This is very close to what I usually do when I have to code something on my own. Group dynamics are different, and I tend to adapt my techniques to the context.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What can we learn from this stuff?&lt;/b&gt;&lt;br /&gt;A lot, I hope :-). Software development is about acquiring and encoding knowledge into an executable format (my usual quote from Phillip Armour). Our code can be extremely simplified through a careful selection of the language we use to encode that knowledge: when the language is aligned with the problem domain, many layers of complexity simply fall down. Your programming language is usually &lt;b&gt;not&lt;/b&gt; aligned with your problem. It's your job to make it so, by introducing the right abstractions.&lt;br /&gt;So, next time you're facing some complex issue, ask yourself: what if this code had to run the very first time?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Acknowledgement&lt;/b&gt;&lt;br /&gt;The image on top is adapted from &lt;a href="http://www.flickr.com/photos/wstryder/5643458755/" target="_blank"&gt;this picture&lt;/a&gt; from Lauri Rantala, released under a creative common license with permission to modify the picture and for commercial use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-5459660748856496234?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/5459660748856496234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=5459660748856496234' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/5459660748856496234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/5459660748856496234'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/06/cut-red-wire.html' title='Cut the red wire!'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7294108346540570869</id><published>2011-05-21T11:58:00.002+02:00</published><updated>2011-05-21T12:23:51.872+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>The CAP Theorem, the Memristor, and the Physics of Software</title><content type='html'>Where I present seemingly unrelated facts that are, in fact, not unrelated at all :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The CAP Theorem&lt;/b&gt;&lt;br /&gt;If you keep current on technology, you're probably familiar with the proliferation of &lt;a href="http://en.wikipedia.org/wiki/NoSQL " target="_blank" &gt;NoSQL&lt;/a&gt; , a large family of non-relational data stores. Most NoSQL stores have been designed for internet-scale applications, where large data stores are preferably deployed using an array of loosely connected low-cost servers. That brings a set of well-known issues to the table:&lt;br /&gt;&lt;br /&gt;- we'd like data to be consistent (that is, to respect all the underlying constraints at any time, especially replication constraints). We call this property &lt;b&gt;C&lt;/b&gt;onsistency.&lt;br /&gt;&lt;br /&gt;- we'd like fast response time, even when some server is down or under heavy load. We call this property &lt;b&gt;A&lt;/b&gt;vailability.&lt;br /&gt;&lt;br /&gt;- we'd like to keep working even if the system gets partitioned (a connection between servers fails). We call this property &lt;b&gt;P&lt;/b&gt;artition tolerance.&lt;br /&gt;&lt;br /&gt;The CAP Theorem (formerly the Brewer's Conjecture) says that we can only choose two properties out of three.&lt;br /&gt;&lt;br /&gt;There is a lot of literature on the CAP Theorem, so I don't need to go in further details here: if you want a very readable paper covering the basics, you can go for &lt;a href="http://www.julianbrowne.com/article/viewer/brewers-cap-theorem" target="_blank" &gt;Brewer's CAP Theorem&lt;/a&gt; by Julian Browne, while if you're more interested in a formal paper, you can refer to &lt;a href="http://lpd.epfl.ch/sgilbert/pubs/BrewersConjecture-SigAct.pdf " target="_blank" &gt;Brewer’s Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services&lt;/a&gt; by Seth Gilbert and Nancy Lynch.&lt;br /&gt;&lt;br /&gt;There is, however, a relatively subtle point that is often brought up and seldom clarified, so I'll give it a shot. Most people realize that there is some kind of "connection" between the concept of availability and the concept of partition. If a server is partitioned away, it is by definition not available. In that sense, it may seem like there is some kind of overlapping between the two concepts, and overlapped concepts are bad (orthogonal concepts should be preferred). However, it is not so:&lt;br /&gt;&lt;br /&gt;- Availability is an &lt;b&gt;external&lt;/b&gt; property, something the clients of the data store can see. They either can get data when they need it, or they can't.&lt;br /&gt;&lt;br /&gt;- Partitioning is an &lt;b&gt;internal&lt;/b&gt; property, something clients are totally unaware of. The data store has to deal with that on the inside.&lt;br /&gt;&lt;br /&gt;Of course, given the fractal nature of software, in a system of systems we may see lack of availability at one level, because of the lack of partition tolerance at a lower level (or vice-versa, as an unavailable node may not be distinguishable from a partitioned node).&lt;br /&gt;&lt;br /&gt;To sum up, while the RDBMS world has usually approached the problem by choosing Consistency and Availability over Partition tolerance, the NoSQL world has often chosen Availability and Partition tolerance, leading to the now famous Eventually Consistent model.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Memristor, or the Value of a Theory&lt;/b&gt;&lt;br /&gt;As a kid, I spent quite a bit of time hacking electronic stuff. I used to scavenge old TV sets and the like, and recover resistors, capacitors, and inductors to use on very simple projects. Little I knew that, theoretically, there was a missing passive element: the &lt;a href="http://en.wikipedia.org/wiki/Memristor" target="_blank" &gt;memristor&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Leon Chua developed &lt;a href="http://www.cpmt.org/scv/meetings/chua.pdf" target="_blank" &gt;the theory&lt;/a&gt; in 1971. It took until 2008 before someone could finally create a working memristor, using nanoscale techniques that would have looked like science fiction in 1971. Still, the theory was there, long before, pointing toward the future.  At the bottom of the theory was the realization that the three known passive elements could be defined by a relationship between four concepts (current, voltage, charge, and flux-linkage). By investigating all possible relationships, he found a missing element, one that was theoretically possible, but yet undiscovered. He used the term &lt;i&gt;completeness&lt;/i&gt; to indicate this line of reasoning, although we often call this kind of property &lt;i&gt;symmetry&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Software Entanglement&lt;/b&gt;&lt;br /&gt;In &lt;a href="http://www.carlopescio.com/2010/11/notes-on-software-design-chapter-12.html" target="_blank" &gt;Chapter 12&lt;/a&gt; of my ongoing series on the nature of software, I introduced the concept of Entanglement, further discusses in &lt;a href="http://www.carlopescio.com/2011/01/notes-on-software-design-chapter-13-on.html" target="_blank" &gt;Chapter 13&lt;/a&gt; and &lt;a href="http://www.carlopescio.com/2011/02/notes-on-software-design-chapter-14.html" target="_blank" &gt;Chapter 14&lt;/a&gt; (for the artifact world).&lt;br /&gt;&lt;br /&gt;Here, I'll reuse my early definition from Chapter 12: &lt;b&gt;Two clusters of information are entangled when performing a change on one immediately requires a change on the other.&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Entanglement is constantly at work in the artifact world: change a class name, and you'll have to fix the name everywhere; add a member to an enumeration, and you'll have to update any switch/case statement over the enumeration; etc. It's also constantly at work in the &lt;b&gt;run-time&lt;/b&gt; world. &lt;br /&gt;&lt;br /&gt;Although I haven't formally introduced entanglement for the run-time world (that would/will be the subject of the forthcoming Chapter 15), you can easily see that maintaining a database replica creates a run-time entanglement between data: update one, and the other must be immediately (atomically, as we use to say) updated. Perhaps slightly more subtle is the fact that referential integrity is strongly related to run-time entanglement as well. Consistency in the CAP theorem, therefore, is basically Entanglement satisfaction.&lt;br /&gt;&lt;br /&gt;Once we understand that, it's perhaps easier to see that the CAP theorem applies well beyond our traditional definition of distributed system. Consider a multi-core CPU with independent L1 caches. Cache contents become entangled whenever they map to the same address. CPU designers usually go with CA, forgetting P. That makes a lot of sense, of course, because we're talking about in-chip connections.&lt;br /&gt;&lt;br /&gt;That's sort of obvious, though. Things get more interesting when we start to consider the run-time/artifact symmetry. That's part of the value of a [good] theory.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A CAP Theorem for Artifacts&lt;/b&gt;&lt;br /&gt;My perspective on the &lt;a href="http://www.PhysicsOfSoftware.com" target="_blank" &gt;Physics of Software&lt;/a&gt; is strongly based on the run-time/artifact dualism. Most forces apply in both worlds, so it is just natural to bring ideas from one world to another, once we know how to translate concepts. Just like symmetry allowed Chua to conceive the memristor, symmetry may allow us to extend concepts from the run-time world to the artifact world (and vice-versa). Let's give the CAP theorem a shot, by moving each run-time concept to the corresponding notion in the artifact world:&lt;br /&gt;&lt;br /&gt;Consistency: just like in the run-time world, it's about satisfying Entanglement. While change in the run-time world is a C/U/D action on data, here is a C/U/D action on artifacts. If you add a member to an enumerated type, your artifacts are consistent when you have updated every portion of code that was enumerating over the extension of that type, etc.&lt;br /&gt;&lt;br /&gt;Availability: just like in the run-time world, is the ability to access a working, up-to-date system. If you can't deploy your new artifacts, your system is not available (as far as the artifact world is concerned). The old system may be up and running, but your new system is not available to the user.&lt;br /&gt;&lt;br /&gt;Partition tolerance: just like in the run-time world, it means you want your system to be usable even if some changes can't be propagated. That is, some artifacts have been partitioned away, and cannot be reached. Therefore, some sort of partial deployment will take place.&lt;br /&gt;&lt;br /&gt;Well, indeed, &lt;b&gt;you can only have two&lt;/b&gt; :-). Consider the artifacts involved in the usual distributed system:&lt;br /&gt;&lt;br /&gt;- one or more servers&lt;br /&gt;- one or more clients&lt;br /&gt;- a contract in between&lt;br /&gt;&lt;br /&gt;The clients and the server (as artifacts – think source code not processes) are U/D entangled over the contract: change a method signature (in RPC speak), or the WSDL, or whatever represents your contract, and you have to change both to maintain consistency.&lt;br /&gt;&lt;br /&gt;What happens if you update [the source code of] a server (say, to fix a serious bug), and by doing so you need to update the contract, but cannot update [the source code of] a client [timely]? This is just like a partition. Think of a distributed development team: the team working on the client, for a reason or another, has been partitioned away.&lt;br /&gt;&lt;br /&gt;You only have two choices:&lt;br /&gt;&lt;br /&gt;- let go of Availability: you won't deploy your new server until you can update the client. This is the artifact side of not having your database available until all the replicas are connected (in the run-time world).&lt;br /&gt;&lt;br /&gt;- let go of Consistency: you'll have to live with an inconsistent client, using a different contract.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Consequences&lt;/b&gt;&lt;br /&gt;Chances are that you:&lt;br /&gt;- Shiver at the idea of letting go of Consistency.&lt;br /&gt;- Think versioning may solve the problem.&lt;br /&gt;&lt;br /&gt;Of course, versioning is a coping strategy, not a solution. In fact, versioning is usually proposed in the run-time world of data stores as well. However, versioning your contract is like pretending that the server has never been updated. It may or may not work (what if your previous contract had major security flaws that cannot be plugged unless you change the contract? What if you changed your server in a way that makes the old contract impossible to keep? etc). It also puts a significant burden on the development team (maintaining more source code than strictly needed) and may significantly slow down development, which is another way to say it's impacting availability (of artifacts).&lt;br /&gt;&lt;br /&gt;It is important, however, that we thoroughly understand &lt;b&gt;context&lt;/b&gt;. After all, any given function call is a contract, and we surely want to maintain consistency as much as we can. So, when does the CAP Theorem apply to Artifacts? Partition tolerance and Availability must be part of the equation. That requires one of the following conditions to apply:&lt;br /&gt;&lt;br /&gt;- Independent development teams. The Facebook ecosystem, for instance, is definitely prone to the artifact side of the CAP Theorem, just like any other system offering a public API to the world at large. You just can't control the clients.&lt;br /&gt;&lt;br /&gt;- A large system that cannot be updated in every single part (unless you accept to slow down deployment/forgo availability). A proliferation of clients (web based, rich, mobile, etc) may also bring you into partitioning problems.&lt;br /&gt;&lt;br /&gt;If you work on a relatively small system, and you have control of all clients, you're basically  on a safe field – you can go with Consistency and Availability, because you just don't have significant partitions. Your development team is more like a multi-core CPU than a large distributed system.&lt;br /&gt;&lt;br /&gt;Once we understand that versioning is basically a way to pretend changes never happened on the server side, is there something similar to &lt;a href="http://en.wikipedia.org/wiki/Eventual_consistency" target="_blank" &gt;Eventual Consistency&lt;/a&gt;  for the artifact side? &lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/bliki/TolerantReader.html" target="_blank" &gt;TolerantReader&lt;/a&gt; may help. If you put extra effort into your clients, you can actually have a working system that will eventually be consistent (when source code for clients will be finally updated) but still be functional during transition times, without delaying the release of server updated. Of course, everything that requires discipline on the client side is rather useless in a Facebook-like ecosystem, but might be an excellent strategy for a large system where you control the clients.&lt;br /&gt;&lt;br /&gt;Interestingly, Fowler talks about the virtues of TolerantReader as if it was always warranted for a distributed system. I tend to disagree: it makes sense only when some form of development-side partitioning can be expected. In many other cases, an enforced contract through XSD and code generation is exactly what we need to guarantee Consistency and Availability (because code generation helps to quickly align the syntactical bits – you still have to work on the semantic parts on both sides). Actually, the extra time required to create a TolerantReader will impact Availability on the short term (the server is ready, the client is not). Context, context, context. This is one more reason why I think we need a Physics of Software: without a clear understanding of forces and materials, it's too easy to slip into the fallacy that just because something worked very well for me [in some cases], it should work very well for you as well. &lt;br /&gt;&lt;br /&gt;In fact, once you recognize the real forces, it's easy to understand that the problem is not limited to service-oriented software, XML contracts, and the like. You have the same problem between a database schema and a number of different clients. Whenever you have artifact entanglement &lt;b&gt;and&lt;/b&gt; the potential for development partitioning (see  above) you have to deal with the artifact-side CAP Theorem.&lt;br /&gt;&lt;br /&gt;Moving beyond TolerantReader (which is not helping much when your client is &lt;b&gt;sending&lt;/b&gt; the wrong data anyway :-), when development partitioning is expected, you need to think about a flexible contract from the very beginning. Facebook, for instance, allows clients to specify which fields they want to receive, but is still pretty rigid in the fields they have to send.&lt;br /&gt;&lt;br /&gt;This is one more interesting R&amp;D challenge that is not easily solved with today's technology. Curiously enough, in the physical world we have long understood the need to use soft materials at the interface level to compensate for imperfections and unexpected variations of contact surfaces. Look at any recent, thermally insulated window, and most likely you're gonna find a seal between the sash and the frame. Why are seals still needed in a world of high-precision manufacturing? ;-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;Time for a confession: when I first thought about all the above, I had already read quite a bit on the CAP Theorem, but not the &lt;a href="http://www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf" target="_blank" &gt;original presentation&lt;/a&gt; from Eric Brewer where the conjecture (it wasn't a theorem back then) was first introduced. The presentation is about a larger topic: challenges in the development of large-scale distributed systems.&lt;br /&gt;&lt;br /&gt;As I started to write this post, I decided to do my homework and go through Brewer's slides. He identified three issues: state distribution,  consistency vs. availability, and boundaries. The first two are about the run-time world, and ultimately lead to the CAP theorem. While talking about Borders, however, Brewers begins with run-time issues (independent failure) and then moves into the artifact world, talking (guess what!) about contracts, boundary evolution, XML, etc. Interestingly, nothing in the presentation suggests any relationship between the problems. Here, I think, is the value of a good theory: as for the memristor, it provides us with leverage, moving what we know to a higher level.&lt;br /&gt;&lt;br /&gt;In fact, another pillar of the Physics of Software is the Decision Space. I'm pretty sure the CAP theorem can be applied in the decision space as well, but that will have to wait.&lt;br /&gt;&lt;br /&gt;Well, if you liked this, stay tuned for Chapter 15 of my  &lt;a href="http://www.carlopescio.com/search/label/NOSD" target="_blank" &gt;NOSD&lt;/a&gt; series, share this post, &lt;a href="https://twitter.com/#!/CarloPescio" target="_blank" &gt;follow me&lt;/a&gt; on twitter, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7294108346540570869?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7294108346540570869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7294108346540570869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7294108346540570869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7294108346540570869'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/05/cap-theorem-memristor-and-physics-of.html' title='The CAP Theorem, the Memristor, and the Physics of Software'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4967524377527429317</id><published>2011-04-20T15:06:00.008+02:00</published><updated>2011-09-28T21:48:00.455+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Your coding conventions are hurting you</title><content type='html'>If you take a walk in my hometown, and head for the center, you may stumble into a building like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/names2.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;from a distance, it's a relatively pompous edifice, but as you get closer, you realize that the columns, the ornaments, everything is fake, carefully painted to look like the real thing. Even shadows have been painted to deceive the eye. Here is another picture from the same neighbor: from this angle, it's easier to see that everything has just been painted on a flat surface:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/names1.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Curiously enough, as I wander through the architecture and code of many systems and libraries, I sometimes get the same feeling. From a distance, everything is object oriented, extra-cool, modern-flexible-etc, but as you get closer, you realize it's just a thin veneer over procedural thinking (and don't even get me started about being "modern").&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Objects, as they were meant to be&lt;/b&gt;&lt;br /&gt;Unlike other disciplines, software development shows little interest for classics. Most people are more attracted by recent works. Who cares about some 20 years old paper when you can play with Node.js? Still, if you never took the time to read &lt;a href="http://www.smalltalk.org/downloads/papers/SmalltalkHistoryHOPL.pdf" target="_blank"&gt;The Early History of Smalltalk&lt;/a&gt;, I'd urge you to. Besides the chronicles of some of the most interesting times in hw/sw design ever, you'll get little gems like this: &lt;i&gt;"The basic principal of recursive design is to make the parts have the same power as the whole." For the first time I thought of the whole as the entire computer and wondered why anyone would want to divide it up into weaker things called data structures and procedures. Why not divide it up into little computers, as time sharing was starting to? But not in dozens. Why not thousands of them, each simulating a useful structure? &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;That's brilliant. It's a vision of objects like little virtual machines, offering specialized services. Objects were meant to be smart. Hide data, expose behavior. It's more than that: Alan is very explicit about the idea of methods as &lt;b&gt;goals&lt;/b&gt;, something you want to happen, unconcerned about how it is going to happen.&lt;br /&gt;&lt;br /&gt;Now, I'd be very tempted to write: "unfortunately, most so-called object-oriented code is not written that way", but I don't have to :-), because I can just quote Alan, from the same paper: &lt;i&gt;The last thing you wanted any programmer to do is mess with internal state even if presented figuratively. Instead, the objects should be presented as &lt;i&gt;sites of higher level behaviors more appropriate for use as dynamic components&lt;/i&gt;. [...]It is unfortunate that much of what is called “object-oriented programming” today is simply old style programming with fancier constructs. Many programs are loaded with “assignment-style” operations now done by more expensive attached procedures. &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;That was 1993. Things haven't changed much since then, if not for the worse :-). Lot of programmers have learnt the &lt;i&gt;mechanics&lt;/i&gt; of objects, and forgot (or ignored) the underlying &lt;i&gt;concepts&lt;/i&gt;. As you get closer to their code, you'll see procedural thinking oozing out. In many cases, you can see that just by looking at class names.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Names are a thinking device&lt;/b&gt;&lt;br /&gt;Software development is about discovering and encoding knowledge. Now, humans have relatively few ways to encode knowledge: a fundamental strategy is to &lt;b&gt;name&lt;/b&gt; things and concepts. Coming up with a good name is hard, yet programming requires us to devise names for:&lt;br /&gt;- components&lt;br /&gt;- namespaces / packages&lt;br /&gt;- classes&lt;br /&gt;- members (data and functions)&lt;br /&gt;- parameters&lt;br /&gt;- local variables&lt;br /&gt;- etc&lt;br /&gt;People are basically lazy, and in the end the compiler/interpreter doesn't care about our beautiful names, so why bother? Because finding good names is a journey of discovery. The names we choose shape the dictionary we use to talk and think about our software. If we can't find a good name, we obviously don't know enough about either the problem domain or the solution domain. Our code (or our model) is telling us something is wrong. Perhaps the metaphor we choose is not properly aligned with the problem we're trying to solve. Perhaps there are just a few misleading abstractions, leading us astray. Still, we better &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/ListenToYourToolsAndMaterials.pdf" target="_blank"&gt;listen&lt;/a&gt;, because we are doing it wrong.&lt;br /&gt;&lt;br /&gt;As usual, balance is key, and focus is a necessity, because clock is ticking as we're thinking. I would suggest that you focus on class/interface names first. If you can't find a proper name for the class, try naming functions. Look at those functions. What is keeping them together? You can apply them to... that's the class name :-). Can't find it? Are you sure those functions belong together? Are you thinking in concepts or just slapping an implementation together? What is that code &lt;b&gt;really&lt;/b&gt; doing? Think method-as-a-goal, class-as-a-virtual-machine. Sometimes, I've found useful to think about the opposite concept, and move from there.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fake OO names and harmful conventions&lt;/b&gt;&lt;br /&gt;That's rather bread-and-butter, yet it's way more difficult than it seems, so people often tend to give up, think procedurally, and use procedural names as well. Unfortunately, procedural names have been institutionalized in patterns, libraries and coding conventions, therefore turning them into a major issue. &lt;br /&gt;&lt;br /&gt;In practice, a few widely used conventions can seriously stifle object thinking:&lt;br /&gt;- the -er suffix&lt;br /&gt;- the -able suffix&lt;br /&gt;- the -Object suffix&lt;br /&gt;- the I- prefix&lt;br /&gt;&lt;br /&gt;of these, the I- prefix could be the most harmless in theory, except that in practice, it's not :-). Tons of ink has been wasted on the -er suffix, so I'll cover that part quickly, and move to the rest, with a few examples from widely used libraries.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Manager, Helper, Handler...&lt;/b&gt;&lt;br /&gt;Good ol' Peter Coad used to say: &lt;i&gt;Challenge any class name that ends in "-er" (e.g. Manager or Controller). If it has no parts, change the name of the class to what each object is managing. If it has parts, put as much work in the parts that the parts know enough to do themselves&lt;/i&gt; (that was the "er-er Principle"). That's central to object thinking, because when you need a Manager, it's often a sign that the Managed are just plain old data structures, and that the Manager is the smart procedure doing the real work.&lt;br /&gt;&lt;br /&gt;When Peter wrote that (1993), the idea of an Helper class was mostly unheard of. But as more people  got into the OOP bandwagon, they started creating larger and larger, uncohesive classes. The proper OO thing to do, of course, is to find the right cooperating, cohesive concepts. The lazy, fake OO thing to do is to take a bunch of methods, move them outside the overblown class X, and group them in XHelper. While doing so, you often have to weaken encapsulation in some way, because XHelper needs a privileged access to X. Ouch. That's just painting an OO picture of classes over old-style coding. Sadly enough, in a wikipedia article that I won't honor with a link, you'll read that "Helper Class is one of the basic programming techniques in object-oriented programming". My hope for humanity is only restored by the fact that the article is an orphan :-).&lt;br /&gt;&lt;br /&gt;I'm not going to say much  about Controller, because it's so popular today (MVC rulez :-) that it would take forever to clean this mess. Sad sad sad.&lt;br /&gt;&lt;br /&gt;Handler, again, is an obvious resurrection of procedural thinking. What is an handler if not a damn procedure? Why do something need to be "handled" in the first place? Oh, I know, you're thinking of events, but even in that case, EventTarget, or even plain Target, is a much better abstraction than EventHandler.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Something-able&lt;/b&gt;&lt;br /&gt;Set your time machine to 1995, and witness the (imaginary) conversation between naïve OO Developer #1, who for some reason has been assigned to design the library of the new wonderful-language-to-be, and naïve OO Developer #2, who's pairing with him along the way.&lt;br /&gt;N1: So, I've got this Thread class, and it has a run() function that it's being executed into that thread... you just have to override run()...&lt;br /&gt;N2: So to execute a function in a new thread you have to extend Thread? That's bad design! Remember we can only extend one class!&lt;br /&gt;N1: Right, so I'll use the Strategy Pattern here... move the run() to the strategy, and execute the strategy in the new thread.&lt;br /&gt;N2: That's cool... how do you wanna call the strategy interface?&lt;br /&gt;N1: Let's see... there is only one method... run()... hmmm&lt;br /&gt;N2: Let's call it Runnable then!&lt;br /&gt;N1: Yes! Runnable it is!&lt;br /&gt;&lt;br /&gt;And so it began (no, I'm not serious; I don't know how it all began with the -able suffix; I'm making this up). Still, at some point people thought it was fine to look at an interface (or at a class), see if there was some kind of "main method" or "main responsibility" (which is kinda obvious if you only have one) and name the class after that. Which is a very simple way to avoid thinking, but it's hardly a good idea. It's like calling a nail "Hammerable", because you known, that's what you do with a nail, you hammer it. It encourages procedural thinking, and leads to ineffective abstractions.&lt;br /&gt;&lt;br /&gt;Let's pair our naïve OO Developer #1 with an Object Thinker and replay the conversation:&lt;br /&gt;&lt;br /&gt;N1: So, I've got this Thread class, and it has a run() function that it's being executed into that thread... you just have to override run()...&lt;br /&gt;OT: So to execute a function in a new thread you have to extend Thread? That's bad design! Remember we can only extend one class!&lt;br /&gt;N1: Right, so I'll use the Strategy Pattern here... move the run() to the strategy, and execute the strategy in the new thread.&lt;br /&gt;OT: OK, so what is the real abstraction behind the strategy? Don't just think about the mechanics of the pattern, think of what it really represents...&lt;br /&gt;N1: Hmm, it's something that can be run...&lt;br /&gt;OT: Or executed, or performed independently...&lt;br /&gt;N1: Yes&lt;br /&gt;OT: Like an Activity, with an Execute method, what do you think? [was our OT aware of the UML 0.8 draft? I still have a paper version :-)]&lt;br /&gt;N1: But I don't see the relationship with a thread...&lt;br /&gt;OT: And rightly so! Thread depends on Activity, but Activity is independent of Thread. It just represents something that can be executed. I may even have an ActivitySequence and it would just execute them all, sequentially. We could even add concepts like entering/exiting the Activity... &lt;br /&gt;(rest of the conversation elided – it would point toward a better timeline :-)&lt;br /&gt;&lt;br /&gt;Admittedly, some interfaces are hard to name. That's usually a sign that we don't really know what we're doing, and we're just coding our way out of a problem. Still, some others (like Runnable) are improperly named just because of bad habits and conventions. Watch out.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Something-Object&lt;/b&gt;&lt;br /&gt;This is similar to the above: when you don't know how to name something, pick some dominant trait and add Object to the end. Again, the problem is that the "dominant trait" is moving us away from the concept of an object as a virtual machine, and toward the object as a procedure. In other cases, Object is dropped in just to avoid more careful thinking about the underlying concept. &lt;br /&gt;&lt;br /&gt;Just like the -able suffix, sometimes it's easy to fix, sometimes is not. Let's try something not trivial, where the real concept gets obscured by adopting a bad naming convention. There are quite a few cases in the .NET framework, so I'll pick &lt;b&gt;MarshalByRefObject&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;If you don't use .NET, here is what the documentation has to say:&lt;br /&gt;&lt;i&gt;Enables access to objects across application domain boundaries in applications that support remoting&lt;/i&gt;&lt;br /&gt;What?? Well, if you go down to the Remarks section, you get a better explanation:&lt;br /&gt;&lt;i&gt;Objects that do not inherit from MarshalByRefObject are implicitly marshal by value. […] The first time [...] a remote application domain accesses a MarshalByRefObject, a proxy is passed to the remote application&lt;/i&gt;&lt;br /&gt;Whoa, that's a little better, except that it's "are marshaled by value", not "are marshal by value" but then, again, the name should be MarshaledByRefObject, not MarshalByRefObject. Well, &lt;i&gt;all your base are belong to us&lt;/i&gt; :-)&lt;br /&gt;&lt;br /&gt;Now, we could just drop the Object part, fix the grammar, and call it MarshaledByReference, which is readable enough. A reasonable alternative could be MarshaledByProxy (Vs. MarshaledByCopy, which would be the default).&lt;br /&gt;Still, we're talking more about implementation than about concepts. It's not that I want my object marshaled by proxy; actually, I don't care about marshaling at all. What I want is to keep a single object identity across appdomains, whereas with copy I would end up with distinct objects. So, a proper one-sentence definition could be:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Preserve object identity when passed between appdomains [by being proxied instead of copied]&lt;/i&gt;&lt;br /&gt;or&lt;br /&gt;&lt;i&gt;Guarantees that methods invoked in remote appdomains are served in the original appdomain&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Because if you pass such an instance across appdomains, any method call would be served by the original object, in the original appdomain. Hmm, guess what, we already have similar concepts. For instance, we have objects that, after being created in a thread, must have their methods executed only inside that thread. A process can be set to run only on one CPU/core. We can configure a load balancer so that if you land on a specific server first, you'll stay on that server for the rest of your session. We call that concept &lt;b&gt;affinity&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;So, a MarshalByRefObject is something with an &lt;b&gt;appdomain affinity&lt;/b&gt;. The marshaling thing is just an implementation detail that makes that happen. &lt;b&gt;AppDomainAffine&lt;/b&gt;, therefore, would be a more appropriate name. Unusual perhaps, but that's because of the common drift toward the &lt;i&gt;mechanics&lt;/i&gt; of things and away from &lt;i&gt;concepts&lt;/i&gt; (because the mechanics are usually much easier to get for techies). And yes, it takes more clarity of thoughts to come up with the notion of appdomain affinity than just slapping an Object at the end of an implementation detail. However, clarity of thoughts is exactly what I would expect from framework designers. While we are at it, I could also add that AppDomainAffine should be an attribute, not a concrete class without methods and fields (!) like MarshalByRefObject. Perhaps I'm asking too much from those guys.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ISomething&lt;/b&gt;&lt;br /&gt;I think this convention was somewhat concocted during the early COM days, when Hungarian was widely adopted inside Microsoft, and having ugly names was therefore the norm. Somehow, it was the only convention that survived the general clean up from COM to .NET. Pity :-).&lt;br /&gt;&lt;br /&gt;Now, the problem is not that you have to type an I in front of things. It's not even that it makes names harder to read. And yes, I'll even concede that after a while, you'll find it useful, because it's easy to spot an interface just by looking at its name (which, of course, is a relevant information when your platform doesn't allow multiple inheritance). The problem is that it's too easy to fall into the trap, and just take a concrete class name, put an I in front of it, and lo and behold!, you got an interface name. Sort of calling a concept IDollar instead of Currency.&lt;br /&gt;&lt;br /&gt;Case in point: say that you are looking for an abstraction of a container. It's not just a container, it's a special container. What makes it special is that you can access items by index (a more limited container would only allow sequential access). Well, here is the (imaginary :-) conversation between naïve OO Developer #1, who for unknown reasons has been assigned to the design of the base library for the newfangled language of the largest software vendor on the planet, and himself, because even naïve OO Developer #2 would have made things better:&lt;br /&gt;&lt;br /&gt;N1: So I have this class, it's called List... it's pretty cool, because I just made it a generic, it's List&amp;lt;T&amp;gt; now!&lt;br /&gt;N1: Hmm, the other container classes all derive from an interface... with wonderful names like IEnumerable (back to that in a moment). I need an interface for my list too! How do I call it?&lt;br /&gt;N1: IListable is too long (thanks, really :-)))). What about IList? That's cool!&lt;br /&gt;N1: Let me add an XML comment so that we can generate the help file...&lt;br /&gt;&lt;i&gt;&lt;br /&gt;IList&amp;lt;T&amp;gt; Interface&lt;br /&gt;Represents a collection of objects that can be individually accessed by index.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;So, say that you have another class, let's call it Array. Perhaps a SparseArray too. They both can be accessed by index. So Array IS-A IList, right? C'mon.&lt;br /&gt;&lt;br /&gt;Replay the conversation, drop in our Object Thinker:&lt;br /&gt;&lt;br /&gt;N1: So I have this class, it's called List... it's pretty cool, because I just made it a generic, it's List&amp;lt;T&amp;gt; now!&lt;br /&gt;N1: Hmm, the other container classes all derive from an interface... with wonderful names like IEnumerable. I need an interface for my list too! How do I call it?&lt;br /&gt;OT: What's special about List? What does it really add to the concept of enumeration? (I'll keep the illusion that "enumeration" is the right name so that N1's mind won't blow away)&lt;br /&gt;N1: Well, the fundamental idea is that you can access items by index... or ask about the index of an element... or remove the element at a given index...&lt;br /&gt;OT: so instead of &lt;i&gt;sequential access&lt;/i&gt; you now have &lt;i&gt;random access&lt;/i&gt;, as it's usually called in computer science?&lt;br /&gt;N1: Yes...&lt;br /&gt;OT: How about we call it RandomAccessContainer? It reads pretty well, like: a List IS-A RandomAccessContainer, an Array IS-A RandomAccessContainer, etc.&lt;br /&gt;N1: Cool... except... can we put an I in front of it?&lt;br /&gt;OT: Over my dead body.... hmm I mean, OK, but you know, in computer science, a List is usually thought of as a sequential access container, not a random access container. So I'll settle for the I prefix if you change List to something else.&lt;br /&gt;N1: yeah, it used to be called ArrayList in the non-generic version...&lt;br /&gt;OT: kiddo, do you think there was a reason for that?&lt;br /&gt;N1: Oh... (spark of light)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Yes, give me the worst of both worlds!&lt;/b&gt;&lt;br /&gt;Of course, given enough time, people will combine those two brilliant ideas, turn off their brain entirely, and create wonderful names like IEnumerable. Most .NET collections implement IEnumerable, or its generic descendant IEnumerable&amp;lt;T&amp;gt;: when a class implements IEnumerable, its instances can be used inside a foreach statement. &lt;br /&gt;&lt;br /&gt;Indeed, IEnumerable is a perfect example of how bad naming habits thwart object thinking, and more in general, abstraction. Here is what the official documentation says about IEnumerable&amp;lt;T&amp;gt;:&lt;br /&gt;&lt;i&gt;Exposes the enumerator, which supports a simple iteration over a collection of a specified type.&lt;/i&gt;&lt;br /&gt;So, if you subscribe to the idea that the main responsibility gives the -able part, and that the I prefix is mandatory, it's pretty obvious that IEnumerable is the name to choose. &lt;br /&gt;&lt;br /&gt;Except that's just wrong. The right abstraction, the one that is completely hidden under the IEnumerable/IEnumerator pair, is the sequential access collection, or even better, a Sequence (a Sequence is more abstract than a Collection, as a Sequence can be calculated and not stored, see yield, continuations, etc). Think about what makes more sense when you read it out loud:&lt;br /&gt;&lt;br /&gt;A List is an IEnumerable (what??)&lt;br /&gt;A List is a Sequence (well, all right!)&lt;br /&gt;&lt;br /&gt;Now, a Sequence (IEnumerable) in .NET is traversed ("enumerated") through an iterator-like class called an IEnumerator ("iterator" like in the iterator pattern, not like that thing they called iterator in .NET). Simple exercise: what is a better name than IEnumerator for something that can only move forward over a Sequence?. &lt;br /&gt;&lt;br /&gt;&lt;b&gt; Is that all you got?&lt;/b&gt;&lt;br /&gt;No, that's not enough! Given a little more time, someone is bound to come up with the worst of &lt;b&gt;all&lt;/b&gt; worlds! What about an interface with: &lt;br /&gt;an I prefix&lt;br /&gt;an -able suffix&lt;br /&gt;an Object somewhere in between&lt;br /&gt;&lt;br /&gt;That's a challenging task, and strictly speaking, they failed it. They had to put -able in between, and Object at the end. But it's a pretty amazing name, fresh from the .NET Framework 4.0: IValidatableObject (I wouldn't be surprised to discover, inside their code, an IValidatableObjectManager to, you know, &lt;i&gt;manage&lt;/i&gt; :-&amp;gt; those damn stupid validatable objects; that would really close the circle :-). &lt;br /&gt;&lt;br /&gt;We can read the documentation for some hilarious time: &lt;br /&gt;&lt;i&gt;IValidatableObject Interface - Provides a way for an object to be invalidated.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Yes! That's what my objects really want! To be &lt;b&gt;invalidated&lt;/b&gt;! C'mon :-)). I'll spare you the imaginary conversation and go straight to the point. Objects don't want to be invalidated. That's procedural thinking: "validation". Objects may be subject to &lt;b&gt;constraints&lt;/b&gt;. Yahoo! &lt;b&gt;Constraints&lt;/b&gt;. What about a Constraint class (to replace the Validation/Validator stuff, which is so damn &lt;b&gt;procedural&lt;/b&gt;). What about a Constrained (or, if you can't help it, IConstrained) interface, to replace IValidatableObject? &lt;br /&gt;&lt;br /&gt;Microsoft (and everyone else, for that matter): what about having a few more Object Thinkers in your class library teams? Oh, while we are at it, why don't you guys consider that we may want to check constraints in any given place, not just in the front end? Why not moving all the constraint checking away from UI or Service layers and make the whole stuff available &lt;i&gt;everywhere&lt;/i&gt;? It's pretty simple, trust me :-).&lt;br /&gt;&lt;br /&gt;Bonus exercise: once you have Constraint and IConstrained, you need to check all those constraints when some event happens (like you receive a message on your service layer). Come up with a better name than ConstraintChecker, that is, something that is not ending in -er. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;And miles to go...&lt;/b&gt;&lt;br /&gt;There would be so much more to say about programming practices that hinder object thinking. Properties, for instance, are usually misused to expose internal state ("expressed figuratively" or not), instead of being just zero-th methods (henceforth, goals!). Maybe I'll cover that in another post.&lt;br /&gt;&lt;br /&gt;An interesting question, for which I don't really have a good answer, is: could some coding convention &lt;b&gt;promote&lt;/b&gt; object thinking? Saying "don't use the -er suffix" is not quite the same as saying "do this and that". Are your conventions moving you toward object thinking?&lt;br /&gt;&lt;br /&gt;If you read so far, you should &lt;a href="https://twitter.com/#!/CarloPescio" target="_blank"&gt;follow me on twitter&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4967524377527429317?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4967524377527429317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4967524377527429317' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4967524377527429317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4967524377527429317'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/04/your-coding-conventions-are-hurting-you.html' title='Your coding conventions are hurting you'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-1883777476419270124</id><published>2011-03-06T12:11:00.002+01:00</published><updated>2011-03-06T12:15:02.505+01:00</updated><title type='text'>Cloud</title><content type='html'>Recent words cloud for my blog, courtesy of &lt;a href="http://www.wordle.net/create" target="_blank"&gt;wordle&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/Cloud20110306.png"/&gt;&lt;br /&gt;&lt;br /&gt;A cloud taken on June 20, 2010 is &lt;a href="http://www.carlopescio.com/2010/06/cloud.html"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-1883777476419270124?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/1883777476419270124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=1883777476419270124' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1883777476419270124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1883777476419270124'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/03/cloud.html' title='Cloud'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-3922534467794094490</id><published>2011-02-27T10:53:00.003+01:00</published><updated>2011-02-27T20:04:07.437+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>Notes on Software Design, Chapter 14: the Enumeration Law</title><content type='html'>In my &lt;a href="http://www.carlopescio.com/2011/01/notes-on-software-design-chapter-13-on.html"&gt;previous post&lt;/a&gt; on this series, I used the well-known Shape problem to explain polymorphism from the entanglement perspective. We've seen that moving from a C-like approach (with a ShapeType enum and a union of structures) to an OO approach (with a Shape interface implemented by concrete shape classes) creates new centers, altering the entanglement between previous centers. &lt;br /&gt;This time, I'll explore the landscape of entanglement a little more, using simple, well-known problems. My aim is to provide an intuitive grasp of the entanglement concept before moving to a more formal definition. In the end, I'll come up with a simple Software Law (one of many). This chapter borrows extensively from the previous one, so if you didn't read chapter 13, it's probably better to do so before reading further.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Shapes, again&lt;/b&gt;&lt;br /&gt;Forget about the Shape interface for a while. We now have two concrete classes: Triangle and Circle. They represent geometric shapes, this time without graphical responsibilities. A triangle is defined by 3 points, a Circle by center and radius. Given a Triangle and a Circle, we want to know the area of their intersection. &lt;br /&gt;As usual, we have two problems to solve: the actual mathematical problem and the software design problem. If you're a mathematician, you may rightly think that solving the first (the function!) is important, and the latter is sort of secondary, if not irrelevant. As a software designer, however, I'll allow myself the luxury of ignoring the gory mathematical details, and tinker with form instead.&lt;br /&gt;&lt;br /&gt;If you're working in a language (like C++) where functions exist [also] outside classes, a very reasonable form would be this:&lt;br /&gt;&lt;pre&gt;double Intersection( const Triangle&amp; t, const Circle&amp; c )&lt;br /&gt;  {&lt;br /&gt;  // something here&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Note that I'm not trying to solve a more general problem. First, I said "forget the Shape interface"; second, I may not know how to solve the general problem of shapes intersection. I just want to deal with a circle and a triangle, so this signature is simple and effective.&lt;br /&gt;&lt;br /&gt;If you're working in a class-only language, you have several choices.&lt;br /&gt;&lt;br /&gt;1) Make that an instance method, possibly changing an existing class.&lt;br /&gt;&lt;br /&gt;2) Make that a static method, possibly changing an existing class.&lt;br /&gt;&lt;br /&gt;3) If your language has open classes, or extension methods, etc, you can add that method to an existing class without changing it (as an artifact).&lt;br /&gt;&lt;br /&gt;So, let's sort this out first. I hope you can feel the ugliness of placing that function inside Triangle or Circle, either as an instance or static method (that feeling could be made more formal by appealing to coupling, to the open/closed principle, or to entanglement itself). &lt;br /&gt;So, let's say that we introduce a new class, and go for a static method. At that point is kinda hard to find nice names for class and method (if you're thinking about ShapeHelper or TriangleHelper, you've been living far too long in ClassNameWasteLand, sorry :-). Having asked this question a few times in real life (while teaching basic OO thinking), I'll show you a relatively decent proposal:&lt;br /&gt;&lt;pre&gt;class Intersection&lt;br /&gt;  {&lt;br /&gt;  public static double Area( Triangle t, Circle c )&lt;br /&gt;    {&lt;br /&gt;    // something here&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;It's quite readable on the calling site:&lt;br /&gt;&lt;pre&gt;double a = Intersection.Area( t, c ) ;&lt;br /&gt;&lt;/pre&gt;Also, the class name is ok: a proper noun, not something ending with -er / -or that would make Peter Coad (and me :-) shiver. An arguably better alternative would be to pass parameters in a constructor and have a parameterless Area() function, but let's keep it like this for now.&lt;br /&gt;&lt;br /&gt;Whatever you do, you end up with a method/function body that is deeply coupled with both Triangle and Circle. You need to get all their data to calculate the area of the intersection. Still, this doesn't feel wrong, does it? That's the method purpose. It's ok to manipulate center, radius, and vertexes. Weird, coupling is supposed to be bad, but it doesn't feel bad here.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Interlude&lt;/b&gt;&lt;br /&gt;Let me change problem setting for a short while, before I come back to our beloved shapes. You're now working on yet another payroll system. You got (guess what :-) a Person class:&lt;br /&gt;&lt;pre&gt;class Person&lt;br /&gt;  {&lt;br /&gt;  Place address;&lt;br /&gt;  String firstName;&lt;br /&gt;  String lastName;&lt;br /&gt;  TelephoneNumber homePhone;&lt;br /&gt;  // …&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;(yeah, I know, some would have written "Address address" :-)&lt;br /&gt;&lt;br /&gt;You also have a Validate() member function (I'll simplify the problem to returning a bool, not an error message or set of error messages).&lt;br /&gt;&lt;pre&gt;bool Validate()&lt;br /&gt;  {&lt;br /&gt;  return &lt;br /&gt;    address.IsValid() &amp;&amp; &lt;br /&gt;    ValidateName( firstName ) &amp;&amp; &lt;br /&gt;    ValidateName( lastName ) &amp;&amp; &lt;br /&gt;    homePhone.IsValid() ;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Yikes! That code sucks! It sucks because it's asymmetric (due to the two String-typed members) but also because it's fragile. If I get in there and add "Email personalEmail ;" as a field, I'll have to update Validate as well (and more member functions too, and possibly a few callers). Hmmm. That's because I'm using my data members. Well, I'm using Triangle and Circle data member as well in the function above, which is supposed to be worse; here I'm using &lt;i&gt;my own&lt;/i&gt; data members. Why was that right, while Validate "feels" wrong? Don't use hand-waving explanations :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Back to Shapes&lt;/b&gt;&lt;br /&gt;A very reasonable request would be to calculate the intersection of two triangles or two circles as well, so why don't we add those functions too:&lt;br /&gt;&lt;pre&gt;class Intersection&lt;br /&gt;  {&lt;br /&gt;  public static double Area( Triangle t, Circle c )&lt;br /&gt;    {     // something here    }&lt;br /&gt;  public static double Area( Triangle t1, Triangle t2 )&lt;br /&gt;    {     // something here    }&lt;br /&gt;  public static double Area( Circle c1, Circle c2 )&lt;br /&gt;    {     // something here    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;We need 3 distinct algorithms anyway, so anything more abstract than that may look suspicious. It makes sense to keep the three functions in the same class: the first function is already coupled with Triangle and Circle. Adding the other two doesn't make it any worse from the coupling perspective. Yet, this is &lt;b&gt;wrong&lt;/b&gt;. It's a step toward the abyss. Add a Rectangle class, and you'll have to add 4 member functions to Intersection.&lt;br /&gt;&lt;br /&gt;Interestingly, we came to this point without introducing a single switch/case, actually without even a single "if" in our code. Even more interestingly, our former Intersection.Area was structurally similar to Person.Validate, yet relatively good. Our latter Intersection is not structurally similar to Person, yet it's facing a similar problem of instability.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Let's stop and think :-)&lt;/b&gt;&lt;br /&gt;A few possible reactions to the above:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;- I'm too demanding. You can do that and nothing terrible will happen.&lt;/i&gt;&lt;br /&gt;Probably true, a small scale software mess rarely kills. The same kind of problem, however, is often at the core of a large-scale mess.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;- I'm throwing you a curve.&lt;/i&gt;&lt;br /&gt;True, sort of. The intersection problem is a well-known double-dispatch issue that is not easily solved in most languages, but that's only part of the problem. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;- It's just a matter of Open/Closed Principle.&lt;/i&gt;&lt;br /&gt;Yeah, well, again, sort of. The O/C is more concerned with extension. In practice, you won't create a new Person class to add email. You'll change the existing one.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;- I know a pattern / solution for that!&lt;/i&gt;&lt;br /&gt;Me too :-). Sure, some acyclic variant of Visitor (or perhaps more sophisticated solutions) may help with shape intersection. A reflection+attribute-based approach to validation may help with Person. As usual, we should look at the moon, not at the finger. It's not the problem per se; it's not about finding an ad-hoc solution. It's more about understanding the common cause of a large set of problems.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;- Ok, I want to know what is really going on here :-)&lt;/i&gt;&lt;br /&gt;Great! Keep reading :-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C/D-U-U Entanglement&lt;/b&gt;&lt;br /&gt;Everything that felt wrong here, including the problem from Chapter 13, that is:&lt;br /&gt;&lt;br /&gt;- the ShapeType-based Draw function with a switch/case inside&lt;br /&gt;&lt;br /&gt;- Person.Validate&lt;br /&gt;&lt;br /&gt;- the latter Intersection class, dealing with more than one case&lt;br /&gt;&lt;br /&gt;was indeed suffering from the &lt;b&gt;same&lt;/b&gt; problem, namely an entanglement chain: C/D-U-U. In plain English: Creation or Deletion of something, leading to an Update of something else, leading to an Update of something else. I think that understanding the full chain, and not simply the U-U part, makes it easier to recognize the problem. Interestingly, the former Intersection class, with just one responsibility, was immune from C/D-U-U entanglement.&lt;br /&gt;&lt;br /&gt;The chain is easier to follow on the Draw function in Chapter 13, so I'll start from there. ShapeType makes it easy to understand (and talk about) the problem, because it's both &lt;a href="http://en.wikipedia.org/wiki/Nominative_type_system" target="_blank"&gt;Nominative&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Extensional_definition" target="_blank"&gt;Extensional&lt;/a&gt;. Every concept is named: individual shape types and the set of those shape types (ShapeType itself). The set is also providing through its full extension, that is, by enumerating its values (that's actually why it's called an enumerated type). Also, every concrete shape is given a name (a struct where concrete shape data are stored).&lt;br /&gt;&lt;br /&gt;So, for the old C-like solutions, entanglement works (unsurprisingly) like this:&lt;br /&gt;&lt;br /&gt;- There is a C/D-C/D entanglement between members of ShapeType and a corresponding struct. Creation or deletion of a new ShapeType member requires a corresponding action on a struct.&lt;br /&gt;&lt;br /&gt;- There is a C/D-U entanglement between members of ShapeType and ShapeType (this is obvious: any enumeration is C/D-U entangled with its constituents).&lt;br /&gt;&lt;br /&gt;- There is U-U entanglement between ShapeType and Draw, or every other function that is &lt;b&gt;enumerating over ShapeType&lt;/b&gt; (a switch/case being just a particular case of enumerating over names).&lt;br /&gt;&lt;br /&gt;Consider now the first Intersection.Area. That function is enumerating over two sets: the set of Circle data, and the set of Triangle data. There is no switch/case involved: we're just using those data, one after another. That amounts to enumeration of names. The function is C/D-U-U entangled with any circle and triangle data. We don't consider that to be a problem because we assume (quite reasonably) that those sets won't change. If I change my mind and represent a Circle using 3 points (I could) I'll have to change Area. It's just that I do not consider that change any likely.&lt;br /&gt;&lt;br /&gt;Consider now Person.Validate. Validate is enumerating over the set of Person data, using their names. It's not using a switch/case. It doesn't have to. Just using a name after another amounts to enumeration. Also, enumeration is not broken by a direct function call: moving portions of Validate into sub-functions wouldn't make any difference, which is why layering is ineffective here. &lt;br /&gt;Here, Validate is U-U entangled with the (unnamed) set of Person data, or C/D-U-U entangled with any of its present or future data members. Unlike Circle or Triangle, we have all reasons to suspect the Person data to be unstable, that is, for C and/or D to occur. Therefore, Validate is unstable.&lt;br /&gt;&lt;br /&gt;Finally, consider the latter Intersection class. While the individual Area functions are ok, the Intersection class is not. Once we bring in more than one intersection algorithm, we entangle the class with the &lt;i&gt;set of shape types&lt;/i&gt;. Now, while in the trivial C-like design we had a visible, named entity representing the set of shapes (ShapeTypes), in the intersection problem I didn't provide such an artifact (on purpose). The fact that we're not naming it, however, does not make it any less real. It's more like we're dealing with an &lt;a href="http://en.wikipedia.org/wiki/Intensional_definition" target="_blank"&gt;Intensional&lt;/a&gt; definition of the set itself (this would be a long story; I wrote an entire post about it, then decided to scrap it).  Intersection is C/D-U-U entangled with individual shape types, and that makes it unstable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Software Law&lt;/b&gt;&lt;br /&gt;One of the slides in my &lt;a href="http://www.physicsofsoftware.com" target="_blank"&gt;Physics of Software&lt;/a&gt; reads "software has a nature" (yeah, I need to update those slides with tons of new material). In natural sciences, we have the concept of &lt;a href="http://en.wikipedia.org/wiki/Physical_law" target="_blank"&gt;Physical law&lt;/a&gt;, which despite the name doesn't have to be about physics :-). In physics, we do have quite a few interesting laws, not necessarily expressed through complex formulas. The &lt;a href="http://en.wikipedia.org/wiki/Laws_of_thermodynamics" target="_blank"&gt;Laws of thermodynamics&lt;/a&gt; , for instance, can be stated in plain English. &lt;br /&gt;&lt;br /&gt;When it comes to software, you can find several "laws of software" around. However, most of them are about process (like Conway's law, Brooks' law, etc), and just a few (like Amdhal's law) are really about software. Some are just principles (like the Law of Demeter) and not true laws. Here, however, we have an opportunity to formulate a meaningful law (one of many yet to be discovered and/or documented):&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- The Enumeration Law&lt;/b&gt;&lt;br /&gt;&lt;i&gt;every artifact (a function, a class, whatever) that is enumerating over the members of set &lt;b&gt;by name&lt;/b&gt; is U-U entangled with that set, or said otherwise, C/D-U-U entangled with any member of the set.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This is not a design principle. It is not something you must aim for. It's a law. It's always true. If you don't like the consequences, you have to change the shape of your software so that the law no longer applies, or that entanglement is harmless because the set is stable.&lt;br /&gt;&lt;br /&gt;This law is not earth-shattering. Well, the laws of thermodynamics don't look earth-shattering either, but that doesn't make them any less important :-). Honestly, I don't know about you, but I wish someone taught me software design this way. This is basically what is keeping me going :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Consequences&lt;/b&gt;&lt;br /&gt;In &lt;a href="http://www.carlopescio.com/2010/11/notes-on-software-design-chapter-12.html"&gt;Chapter 12&lt;/a&gt;, I warned against the natural temptation to classify entanglement in a good/bad scale, as it has been done for coupling and even for connascence. For instance, "connascence of name" is considered the best, or least dangerous, form. Yet we have just seen that entanglement with a set of names is at the root of many problems (or not, depending on the stability of that name set).&lt;br /&gt;&lt;br /&gt;Forces are not good or evil. They're just there. We must be able to recognize them, understand how they're influencing our material, and deal with them accordingly. For instance, there are well-known approaches to mitigate dependency on names: indirection (through function pointers, polymorphism, etc) may help in some cases; double indirection (like in double-dispatch) is required in other cases; reflection would help in others (like Validate). All those techniques share a common effect, that we'll discuss in a future post.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;Speaking of future: recently, I've been exploring different ways to represent entanglement, as I wasn't satisfied with my forcefield diagram. I'll probably introduce an "entanglement diagram" in my next post.&lt;br /&gt;&lt;br /&gt;A final note: visit counters, sharing counters and general feedback tell me that this stuff is not really popular. My previous rant on design literature had way more visitors than any of my posts on the Physics of Software, and was far easier to write :-). If you're not one of the usual suspects (the handful of good guys who are already sharing this stuff around), consider spreading the word a little. You don't have to be a hero and tell a thousand people. Telling the guy in front of you is good enough :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-3922534467794094490?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/3922534467794094490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=3922534467794094490' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3922534467794094490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3922534467794094490'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/02/notes-on-software-design-chapter-14.html' title='Notes on Software Design, Chapter 14: the Enumeration Law'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8597939822614492856</id><published>2011-02-03T17:28:00.004+01:00</published><updated>2011-02-26T21:35:26.981+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='book reference'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Is Software Design Literature Dead?</title><content type='html'>Sometimes, my clients ask me what to read about software design. Most often than not, they don't want a list of books – many already have the classics covered. They would like to read papers, perhaps recent works, to further advance their understanding of software design, or perhaps something inspirational, to get new ideas and concepts. I have to confess I'm often at loss for suggestions.&lt;br /&gt;&lt;br /&gt;The sense of discomfort gets even worse when they ask me what happened to the kind of publications they used to read in the late '90s. Stuff like the C++ Report, the Journal of Object Oriented Programming, Java Report, Object Expert, etc. Most don't even know about the &lt;a href="http://www.jot.fm/" target="_blank"&gt;Journal of Object Technology&lt;/a&gt;, but honestly, the JOT has taken a strong academic slant lately, and I'm not sure they would find it all that interesting. I usually suggest they keep current on design patterns: for instance, the complete &lt;a href=" http://sunsite.informatik.rwth-aachen.de/Publications/CEUR-WS/Vol-566/" target="_blank"&gt;EuroPLoP 2009 proceedings&lt;/a&gt; are available online, for free. However, mentioning patterns sometimes furthers just another question: &lt;i&gt;what happened to the pattern movement&lt;/i&gt;? Keep that conversation going for a while, and you get the final question: &lt;i&gt;so, is software design literature dead&lt;/i&gt;?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Is it?&lt;/b&gt;&lt;br /&gt;Note that the question is not about software design - it's about software design &lt;b&gt;literature&lt;/b&gt;. Interestingly, Martin Fowler wrote about the other side of the story (&lt;a href="http://www.martinfowler.com/articles/designDead.html" target="_blank"&gt;Is Design Dead?&lt;/a&gt;) back in 2004. He argued that design wasn't dead, but its nature had changed (I could argue that if you change the &lt;i&gt;nature&lt;/i&gt; of something, then it's perhaps inappropriate to keep using the same name :-), but ok). So perhaps software design literature isn't dead either, and has just changed nature: after all, looking for "software design" on Google yields 3,240,000 results. &lt;br /&gt;Trying to classify what I usually find under the "software design" chapter, I came up with this list:&lt;br /&gt;&lt;br /&gt;- Literature on software design philosophy, hopefully with some practical applications. Early works on Information Hiding were as much about a philosophy of software design as about practical ways to structure our software. There were a lot of philosophical papers on OOP and AOP as well. Usually, you get this kind of literature when some new idea is being proposed (like my &lt;a href="http://www.PhysicsOfSoftware.com" target="_blank"&gt;Physics of Software&lt;/a&gt; :-). It's natural to see less and less philosophy in a maturing discipline, so perhaps a dearth of philosophical literature is not a bad sign.&lt;br /&gt;&lt;br /&gt;- Literature on notations, like UML or SysML. This is not really software design literature, unless the rationale for the notation is discussed.&lt;br /&gt;&lt;br /&gt;- Academic literature on metrics and the like. This would be interesting if those metrics addressed real design questions, but in practice, everything is always observed through the rather narrow perspective of correlation with defects or cost or something appealing for manager$. In most cases, this literature is not really about software design, and is definitely not coming from people with a strong software design background (of course, they would disagree on that :-)&lt;br /&gt;&lt;br /&gt;- Literature on software design principles and heuristics, or refactoring techniques. We still see some of this, but is mostly a rehashing of the same old stuff from the late '90s. The SOLID principles, the Law of Demeter, etc. In most cases, papers say nothing new, are based on toy problems, and are here just because many programmers won't read something that has been published more than a few months ago. If this is what's keeping software design literature alive, let's pull the plug.&lt;br /&gt;&lt;br /&gt;- Literature on methods, like Design by Contract, TDD, Domain-Driven Design, etc. Here you find the occasional must-read work (usually a book from those who actually invented the approach), but just like philosophy, you see less and less of this literature in a maturing discipline. Then you find tons of  &lt;i&gt;advocacy&lt;/i&gt; on methods (or against methods), which would be more interesting if they involved &lt;b&gt;real&lt;/b&gt; experiments (like the ones performed by Simula labs) and not just another toy projects in the capable hands of graduate students. Besides, experiments on design methods should be evaluated [mostly] by cost of change in the next few months/years, not exclusively by design principles. Advocacy may seem to keep literature alive, but it's just noise.&lt;br /&gt;&lt;br /&gt;- Literature on platform-specific architectures. There is no dearth of that. From early EJB treatises to JBoss tutorials, you can find tons of papers on "enterprise architecture". Even Microsoft has some architectural literature on application blocks and stuff like that. Honestly, in most cases it looks more like Markitecture (marketing architecture as defined by Hohmann), promoting canned solutions and proposing that you adapt your problem to the architecture, which is sort of the opposite of real software design. The best works usually fall under the "design patterns" chapter (see below).&lt;br /&gt;&lt;br /&gt;- Literature for &lt;a href="http://www.joelonsoftware.com/articles/fog0000000018.html" target="_blank"&gt;architecture astronauts&lt;/a&gt;. This is a nice venue for both academics and vendors. You usually see heavily layered architectures using any possible standards and still proposing a few more, with all the right (and wrong) acronyms inside, and after a while you learn to turn quickly to the next page. It's not unusual to find papers appealing to money-saving managers who don't "get" software, proposing yet another combination of blueprint architectures and MDA tools so that you can "generate all your code" with a mouse click. Yeah, sure, whatever.&lt;br /&gt;&lt;br /&gt;- Literature on design patterns. Most likely, this is what's keeping software design literature alive. A well-written pattern is about a real problem, the forces shaping the context, an effective solution, its consequences, etc. This is what software design is about, &lt;b&gt;in practice&lt;/b&gt;. On the other hand, a couple of conferences every year can't keep design literature in perfect health.&lt;br /&gt;&lt;br /&gt;- Literature on design in the context of agility (mostly about TDD). There is a lot of this on the net. Unfortunately, it's mostly about trivial problems, and even more unfortunately, there is rarely any discussion about the quality of the design itself (as if having tests was enough to declare the design "good"). The largest issue here is that it's basically impossible to talk about the design of anything non-trivial strictly from a code-based perspective. Note: I'm &lt;b&gt;not&lt;/b&gt; saying that you can't design using only code as your material. I'm saying that when the problem scales slightly beyond the toy level, the amount of code that you would have to write &lt;b&gt;and&lt;/b&gt; show to talk about design and &lt;b&gt;design alternatives&lt;/b&gt; grows beyond the manageable. So, while code-centric practices are &lt;b&gt;not&lt;/b&gt; killing design, they are nailing the coffin on design &lt;b&gt;literature&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Geez, I am usually an optimist :-)), but this picture is bleak. I could almost paraphrase Richard Gabriel (of "Objects have failed" fame) and say that evidently, software design has failed to speak the truth, and therefore, software design narrative (literature) is dying. But that would not be me. I'm more like the opportunity guy. Perhaps we just need a different kind of literature on software design.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Something's missing&lt;/b&gt;&lt;br /&gt;If you walk through the aisles of a large bookstore, and go to the "design &amp; architecture" shelves, you'll all the literary kinds above, not about software, but about real-world stuff (from chairs to buildings). except  on the design of physical objects too. Interestingly,  you can also find a few &lt;b&gt;more&lt;/b&gt;like:&lt;br /&gt;&lt;br /&gt;- Anthologies (presenting the work of several designers) and monographs on the work of famous designers. We are at loss here, because software design is not immediately visible, is not interesting for the general public, is often kept as a trade secret, etc. &lt;br /&gt;I know only one attempt to come up with something similar for software: "Beautiful Architecture" by Diomidis Spinellis. It's a nice book, but it suffers from a lack of depth. I enjoyed reading it, but didn't come back with a new perspective on something, which is what I would be looking for in this kind of literature. &lt;br /&gt;It would be interesting, for instance, to read more about the architecture of successful open-source projects, not from a fanboy perspective but through the eyes of experienced software designers. Any takers?&lt;br /&gt;&lt;br /&gt;- Idea books. These may look like anthologies, but the focus is different. While an anthology is often associated with a discussion or critics of the designer's style, an idea book presents several different objects, often out of context, as a sort of creative stimulus. I don't know of anything similar for software design, though I've seen many similar book for "web design" (basically fancy web pages). In a sense, some literature on patterns comes close to being inspirational; at least, good domain-specific patterns sometimes do. But an idea book (or idea paper) would look different.&lt;br /&gt;&lt;br /&gt;I guess anthologies and monographs are at odd with the software culture at large, with its focus on the whizz-bang technology of the day, little interest for the past, and often bordering on religious fervor about some products. But idea books (or most likely idea papers) could work, somehow.&lt;br /&gt;&lt;br /&gt;Indeed, I would like to see more software design literature organized as follows:&lt;br /&gt;&lt;br /&gt;- A real-world, or at least realistic problem is presented.&lt;br /&gt;&lt;br /&gt;- Forces are discussed. Ideally, real-world forces.&lt;br /&gt;&lt;br /&gt;- Possibly, a subset of the whole problem is selected. Real-world problems are too big to be dissected in a paper (or two, or three). You can't discuss the detailed design of a business system in a paper (lest you appeal only to architecture astronauts). You could, however, discuss a selected, challenging portion. Ideally, the problem (or the subset) or perhaps just the approach / solution, should be of some interest even outside the specific domain. Just because your problem arose in a deeply embedded environment doesn't mean I can't learn something useful for an enterprise web application (assuming I'm open minded, of course :-). Idea books / papers should trigger some lateral thinking on the reader, therefore unusual, provocative solutions would be great (unlike literature on patterns, where you are expected to report on well-known, sort of "traditional" solutions).&lt;br /&gt;&lt;br /&gt;- Practical solutions are presented and scrutinized. I don't really care if you use code, UML, words, gestures, whatever. Still, I want some depth of scrutiny. I want to see more than one option discussed. I don't need working code. I'm probably working on a different language or platform, a different domain, with different constraints. I want fresh design ideas and new perspectives.&lt;br /&gt;&lt;br /&gt;- In practice, a good design aims at keeping the cost of change low. This is why a real-world problem is preferable. Talking about the most likely changes and how they could be addressed in different scenarios beats babbling about tests and SOLID and the like. However, "most likely changes" is meaningless if the problem is not real.&lt;br /&gt;&lt;br /&gt;Funny enough, there would be no natural place to publish something like that, except your own personal page. Sure, maybe JOT, maybe not. Maybe IEEE Software, maybe not. Maybe some conference, maybe not. But we don't have a software design journal with a large readers pool. This is part of the problem, of course, but also a consequence. Wrong feedback loop :-).&lt;br /&gt;&lt;br /&gt;Interestingly, I proposed something similar years ago, when I was part of the editorial board of a software magazine. It never made a dent. I remember that a well-known author argued against the idea, on the basis that people were not interested in all this talking about ins-and-outs, design alternatives and stuff. They would rather have a single, comprehensive design presented that they could immediately use, preferably with some source code. Well, that's entirely possible; indeed, I don't really know how many software practitioners would be interested in this kind of literature. Sure, I can bet a few of you guys would be, but overall, perhaps just a small minority is looking for inspiration, and most are just looking for canned solutions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Or maybe something else...&lt;/b&gt;&lt;br /&gt;On the other hand, perhaps this style is just too stuck in the '90s to be appealing in 2011. It's unidirectional (author to readers), it's not "social", it's not fun. Maybe a design challenge would be more appealing. Or perhaps the media are obsolete, and we should move away from text and graphics and toward (e.g.) videos. I actually tried to watch some code kata videos, but the guys thought they were &lt;a href="http://www.youtube.com/watch?v=aMHTC4IqK3A" target="_blank"&gt;like this&lt;/a&gt;, but to an experienced designer they looked more &lt;a href="http://www.youtube.com/watch?v=Wnjb8Hx76u8" target="_blank"&gt;like this&lt;/a&gt;.  (and not even &lt;b&gt;that&lt;/b&gt; funny). Maybe the next generation of software designers will come up with a better narrative style or media.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Do something!&lt;/b&gt;&lt;br /&gt;I'm usually the "let's do something" kind of guy, and I've entertained the idea of starting a Software Design Gallery, or a Software Design Idea Book, or something, but honestly, it's a damn lot of work, and I'm a bit skeptical about the market size (even for a free book/paper/website/whatever). As usual, any feedback is welcome, and any action on your part even more :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8597939822614492856?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8597939822614492856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8597939822614492856' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8597939822614492856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8597939822614492856'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/02/is-software-design-literature-dead.html' title='Is Software Design Literature Dead?'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4611140671750103125</id><published>2011-01-19T22:38:00.002+01:00</published><updated>2011-01-19T23:09:24.897+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Can we really control the quality/cost trade-off?</title><content type='html'>An old rule in software project management (also known as the  &lt;a href="http://en.wikipedia.org/wiki/Project_triangle" target="_blank"&gt; Project triangle&lt;/a&gt; is that you can have a system that:&lt;br /&gt;- has low development cost (Cheap)&lt;br /&gt;- has short development time (Fast)&lt;br /&gt;- has good quality (Good)&lt;br /&gt;except you can only choose two :-). That seem to suggest that if you want to go fast, and don't want to spend more, you can only compromise on quality. Actually, you can also compromise on feature set, but in many real-world cases, that happens only after cost, time and quality have already been compromised.&lt;br /&gt;&lt;br /&gt;So, say that you want to compromise on quality. Ok, I know, most engineers don't want to compromise on quality; it's almost like compromising on ethics. Still, we actually &lt;b&gt;do&lt;/b&gt;, more often that we'd like to, so let's face the monster. We can:&lt;br /&gt;&lt;br /&gt;- Compromise on external quality, or quality as perceived by the user. &lt;br /&gt;Ideally, this would be simply defined as MTBF (Mean Time Between Failures), although for many users, the perceived "quality" is more akin to the "user experience". In practice, it's quite hard to predict MTBF and say "ok, we won't do error checking here because that will save us X development days, and only decrease MTBF by Y". Most companies don't even measure MTBF. Those who do, use it just as a post-facto quality goal, that is, they fix bugs until they reach the target MTBF. We just don't know enough, in the software engineering community, to actually &lt;b&gt;plan&lt;/b&gt; the MTBF of our product.&lt;br /&gt;&lt;br /&gt;- Compromise on internal quality, or quality as perceived by developers. &lt;br /&gt;Say goodbye to clarity of names, separation of concerns, little or no duplication of logic, extendibility in the right places, low coupling, etc. In some cases, poor internal quality may resurface as poor external quality (say, there is no error handling in place, so the code just crashes on unexpected input), but in many cases, the code can be rather crappy but appear to work fine.&lt;br /&gt;&lt;br /&gt;- Compromise on process, or quality as perceived by the Software Engineering Institute Police :-).&lt;br /&gt;What usually happens is that people start bypassing any activity that may seem to slow them down, like committing changes into a version control system :-) or being thorough about testing. Again, some issues may resurface as external quality problems (we don't test, so the user gets the thrill of discovering our bugs), but users won't notice if you cut corners in many process areas (well, they won't notice short-term, at least).&lt;br /&gt;&lt;br /&gt;Of course, a "no compromises" mindset is dangerous anyway, as it may lead to an excess of ancillary activities not directly related to providing value (to the project and to users). So, ideally, we would choose to work at the best point in the quality/time and/or quality/cost continuum (the "best point" would depend on a number of factors: more on this later). Assuming, however, that there is indeed a continuum. Experience taught me the opposite: we can only move in discrete steps, and those are few and rather far apart.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Quality and Cost&lt;/b&gt;&lt;br /&gt;Suppose I'm buying a large quantity of forks, wholesale. Choices are almost limitless, but overall the &lt;b&gt;real&lt;/b&gt; choice is between:&lt;br /&gt;&lt;br /&gt;- the plastic kind (throwaway)&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/plasticFork.jpg"&gt;&lt;br /&gt;it works, sort of, but you can't use it for all kinds of food, you can't use it while cooking, and so on.&lt;br /&gt;&lt;br /&gt;- the "cheap steel" kind. &lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/cheapFork.jpg"&gt;&lt;br /&gt;it's surely more resistant than plastic: you can actually &lt;b&gt;use&lt;/b&gt; it. Still, the tines are irregular and feel uncomfortable in your mouth. Weight isn't properly balanced. And I wouldn't bet on that steel actually being stainless.&lt;br /&gt;&lt;br /&gt;- the good stainless steel kind. &lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/stainlessFork.jpg"&gt;&lt;br /&gt;Properly shaped, properly balanced, good tasting :-), truly stainless, easy to clean up. You may or may not have decorations like that: price doesn't change so much (more on this below).&lt;br /&gt;&lt;br /&gt;- the gold-plated kind. &lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/goldFork.jpg"&gt;&lt;br /&gt;it shows that you got money, or bad taste, or both :-). Is not really better than the good stainless fork, and must be handled more carefully. It's a real example of "worse is better".&lt;br /&gt;&lt;br /&gt;Of course, there are other kind of forks, like those with resin or wood handles (which ain't really cheaper than the equivalent steel kind, and much worse on maintenance), or the sturdy plastic kind for babies (which leverage parental anxiety and charge a premium). So, the quality/cost landscape does not get much richer than that. Which brings us to prices. I did a little research (not really exhaustive – it would take forever :-), but overall it seems like, normalizing on the price of the plastic kind, we have this price scale:&lt;br /&gt;&lt;br /&gt;Plastic: 1&lt;br /&gt;Cheap steel: 10&lt;br /&gt;Stainless steel: 20&lt;br /&gt;Gold-plated: 80&lt;br /&gt;&lt;br /&gt;The range is huge (1-80). Still, we have a big jump from throwaway to cheap (10x), a relatively small jump from cheap to good (2x), and another significant jump between good and gold-plated (4x). I think software is not really different. Except that a 2x jump is usually considered huge :-).&lt;br /&gt;&lt;br /&gt;Note that I'm focusing on &lt;b&gt;building&lt;/b&gt; cost, which is the significant factor on market price for a commodity like forks. Once you consider operating costs, the stainless steel is the obvious winner.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Quality/Cost landscape for Software&lt;/b&gt;&lt;br /&gt;Again, I'll consider only building costs here, and leave maintenance and operation costs aside for a moment.&lt;br /&gt;&lt;br /&gt;If you build throwaway software, you can get really cheap. You don't care about error handling (which is a huge time sink). You copy&amp;paste code all over. You proceed by trial and error, and sometimes patch code without understanding what is broken, until it seems to work. You keep no track of what you're doing. You use function names like foo and bar. Etc. After all, you just want to run that code once, and throw it away (well, that's the theory, anyway :-).&lt;br /&gt;We may think that there is no place at all for that kind of code, but actually, end-user programming often falls into that case. I've also seen system administration scripts, lot of scientific code, and quite a bit of legacy business code that would easily fall into this category. They were written as throwaways, or by someone who only had experience writing throwaways, and somehow they didn't get thrown away.&lt;br /&gt;&lt;br /&gt;The next step is very far apart: if you want your code to be &lt;b&gt;any&lt;/b&gt; good, you have to spend much more. It's like the plastic/"cheap steel" jump. Just put decent error handling in place, and you'll spend way more. Do a reasonable amount of systematic testing (automated or not) and you're gonna spend more. Aim for your code to be reasonably readable, and you'll have to think more, go back and refactor as you learn more, etc. At this stage, internal quality is still rather low; code is not really stainless. External quality is acceptable. It doesn't feel good, but it gets [some] work done. A lot of "industrial" code is actually at this level. Again, maintenance may not be cheap, but I'm only considering building costs here; a 5x to 10x jump compared to throwaway code is quite reasonable.&lt;br /&gt;&lt;br /&gt;The next step is when you invest more in -ilities, as well as in external quality through more systematic and deeper testing. You're building something that you and your users like. It's truly stainless. It feels good. However, it's hard to be "just a little stainless". It's hard to be "somehow modular" or "sort of thread-safe". Either you're on one side, or you're on the other. If you want to be on the right side, you're gonna spend more. Note that just like with fork, long-term cost is lower for good, stainless code, but as far as building cost is concerned, a 2X increase compared to "cheap steel" code is not surprising.&lt;br /&gt;&lt;br /&gt;Gold-plating is obvious: grandiose design that serves no purpose (and that would appear as gratuitous complexity to a good designer), coding standards that add no value (like requiring a comment on each and every parameter of every function), etc. I've seen systems spending a lot of energy trying to be as scalable as Amazon, even though they only had to serve a few hundred concurrent clients. Goldplated systems spend more on building, and may also incur higher maintenance costs afterward (be careful not to scratch the gold :-). Of course, it takes experience to recognize goldplating. To someone that has never designed a system for testability, interfaces for mocking may seem like a waste. To an experienced designer, they tell a different story.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But software is... soft!&lt;/b&gt;&lt;br /&gt;As usual, a metaphor can be stretched only so far. Software quality can be easily altered over time. Plastic can't be transformed into gold (if you can, give me a call :-), but we can release a bug-ridden version and fix issues later. We may incur intentional technical debt and pay it back in the next release. This could be the right strategy in the right market at the right time, but that's not always the case.&lt;br /&gt;&lt;br /&gt;Indeed, although start-ups, customer discovery, innovative products, etc seem to get all the attention lately, if you happen to work in a mature market you may want to focus on early-on quality. Some customers are known to be forgiving about quality issues, in exchange for early access to innovative products. It's simply not the general case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Modular Quality?&lt;/b&gt;&lt;br /&gt;Theoretically, we could invest more in some "critical" components and less in others. After all, we don't need the same quality (external and internal) in every single portion. We can accept quirks here and there. Due to the fractal nature of software, this can be extended to the entire hierarchy of artifacts. It's surely possible. However, it takes a lot of maturity to develop on the edge of quality. Having to constantly reason about the quality/cost trade off can easily cost you more than you're saving: I'd rather spend that reasoning to create quality code. &lt;br /&gt;&lt;br /&gt;Once again, however, we may have a plan to start with plastic and grow into stainless steel over time. We must be aware that it is easier said than done. I've seen it many times over my long career. Improving software quality is just another case of moving our software in the decision space. We decided to make software out of plastic early on, and now we want to move it to another place, say the cheap steel spot. Some work is required. Work is proportional to the distance (which is large – see above), but also to the opposing force. Whatever form that force takes, a significant factor is always the mass to be moved, and here lies the key. It's hard to move a monolithic mass of code into another place (in the decision space). It's easier if you can move it a module at time. &lt;br /&gt;&lt;br /&gt;Within a small modular unit, you can easily improve local quality. Change a switch/case into polymorphism. Add an interface to decouple two concrete classes. It's easy and it's cheap, because mass is small. Say, however, that you got your modular structure wrong: an important concept has not been identified, and is now scattered all around. You have to tweak a lot of code. While doing so, you'll find that you're not just fighting the mass you have to move: you have to fight the gravitational attraction of the surrounding code. That may reveal more scattered concepts. It's a damn lot of work, possibly more than it's worth. Software is not necessarily soft.&lt;br /&gt;&lt;br /&gt;So, can we really move software around? Yes, in the small. Yes, if you got the modular structure right, and you're only cleaning up within that modular structure. Once again, the fractal nature of software can be our best friend or our worst enemy. Get the right partitioning between applications / services, and you only have to work inside. Get the right partitioning between components, and you only have to work inside. And so on. It's fine to have a plastic component, inasmuch as the interface is right. Get the modular structure wrong, and sooner or later you'll need to make wide-range changes, or accept a "cheap steel" quality. If we got it wrong at a small scale, it's no big deal. At a large scale, it can be a massacre.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;Once again, modularity is the key. Not just "any" modularity, but a modularity aligned with the underlying forcefield. If you get that right, you can build plastic components and evolve them to stainless steel quality over time. Been there, done that. Get your modular structure wrong, and you'll lack locality of action. In other words: if you plan on cutting corners inside a module, you have to invest at the interface level. That's simpler if you design top-down than if you're in the "emergent design" camp, because the module will be underengineered inside, and we can't expect a clean interface to emerge from underengineered code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4611140671750103125?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4611140671750103125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4611140671750103125' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4611140671750103125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4611140671750103125'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/01/can-we-really-control-qualitycost-trade.html' title='Can we really control the quality/cost trade-off?'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-3649106339338291223</id><published>2011-01-02T21:40:00.002+01:00</published><updated>2011-01-02T22:35:05.394+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Notes on Software Design, Chapter 13: On Change</title><content type='html'>We have a long history of manipulating physical materials. Cavemen built primitive tools out of rocks and sticks. I would speculate :-) that they didn't know much about physics, yet through observation, serendipity and good old trial and error they managed to survive pretty well, or we wouldn't be here today talking about software.&lt;br /&gt;&lt;br /&gt;For centuries, we only had empirical observations and haphazard theories about the real nature of the physical world. The &lt;a href="http://en.wikipedia.org/wiki/Classical_element" target="_blank"&gt;Greek Classical Element&lt;/a&gt; were Earth, Water, Air, Fire, and Aether, which is not exactly the way we look at materials today. Yet the Greeks managed to build large and incredibly beautiful temples.&lt;br /&gt;&lt;br /&gt;Of course, today we know a quite a bit more. Take any kind of physical material, like a copper wire. In the real world,  you can:&lt;br /&gt;&lt;br /&gt;- apply thermal stress to the material, e.g. by warming it. Different materials react differently.&lt;br /&gt;&lt;br /&gt;- apply mechanical stress to the material, e.g. by pulling it on both ends. Different materials react differently.&lt;br /&gt;&lt;br /&gt;- apply electromagnetic forces, e.g. by moving the wire inside a magnetic field. Different materials react differently.&lt;br /&gt;&lt;br /&gt;- etc.&lt;br /&gt;&lt;br /&gt;To get just a little more into specifics, if we restrict ourselves to mechanical stress, and focus on the so-called &lt;i&gt;static loading&lt;/i&gt;, we end up with just a few kind of stress: tension, compression, bending, torsion, and shear (see &lt;a href="http://books.google.com/books?id=qbdnVEd5nukC&amp;lpg=PT41&amp;ots=l_YyA4IsJM&amp;dq=tension%2C%20compression%2C%20bending%2C%20shear%2C%20torsion&amp;pg=PT41" target="_blank"&gt;here&lt;/a&gt; and also &lt;a href="http://www.allstar.fiu.edu/aero/flight11.htm" target="_blank"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Although people have built large, beautiful structures without any formal knowledge of material science, it is hard to deny the huge progress made possible by a deeper understanding of what is actually going on with materials. Knowledge of forces and reactions allows us to choose the best material, the best shape, and even to create new, better materials.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The software world&lt;/b&gt;&lt;br /&gt;Although we can build large, even beautiful systems, it is hard to deny that we are still in the dark ages. We have vague principles that usually can't be formally defined. We have different materials, like statically typed and dynamically typed languages, yet we don't have a sound theory of forces, so we end up with the usual evangelist trying to convert the world to its material of choice. It's kinda funny, because it's just as sensible as having a Brick Evangelist trying to convince you to use bricks instead of glass for your windows ("it's more robust!"), and a Glass Evangelist trying to convince you to build your entire house out of glass ("you'll get more light!"). &lt;br /&gt;&lt;br /&gt;Indeed, a key realization in my exploration on the nature of software was that we completely lack the notion of &lt;i&gt;force&lt;/i&gt;. Sure, we use a bunch of terms like "flexibility", "heavy load", "fast", "fragile", etc., and they all seem to be somehow inspired by physics, but in the end it's just vernacular usage without any kind of theory behind.&lt;br /&gt;&lt;br /&gt;As I realized that, I began looking for a small, general yet useful set of  "software forces". Nothing too fancy. Tension, compression, bending, torsion, and shear are not fancy, but are incredibly useful for physical materials (no, I wasn't looking for similar concepts in software, but for something just as useful). &lt;br /&gt;&lt;br /&gt;Initially, I focused my attention on artifacts, because design is very much about form, and form is made visible through artifacts. I got many ideas and explored several avenues, but most seemed more like  ad hoc concepts or turned out to be dead ends. Eventually, I realized we already knew the fundamental forces, though we never used the term "force" to characterize them. &lt;br /&gt;&lt;br /&gt;Interestingly, those forces are better known in the run-time world, and are usually restricted to &lt;i&gt;data&lt;/i&gt;. Upon closer scrutiny, it turned out they also apply to procedural knowledge, and to the artifact world as well. Also, it turned out that those forces were intimately connected with the concept of entanglement, and could actually shed some light on entanglement itself. More than that, they could be used to find entangled information, in practice, no more philosophy, thank you :-).&lt;br /&gt;&lt;br /&gt;So, let's take the easy road and see what we can do with run-time knowledge expressed through &lt;b&gt;data&lt;/b&gt;, and build from there.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It's almost too simple&lt;/b&gt;&lt;br /&gt;Think about a simple data-oriented application, like a book library. What can you do with a Book record? It's rather obvious: create, read, update, delete. That's it. CRUD. (I'm still thinking about the need for an identity-preserving Move outside the database realm, but let's focus on CRUD right now). CRUD for run-time data is trivial, and is a well-known concept. &lt;br /&gt;&lt;br /&gt;CRUD in the artifact world is also relatively simple and intuitive:&lt;br /&gt;&lt;br /&gt;Create: we create a new artifact, being it a component, a class, a function.&lt;br /&gt;&lt;br /&gt;Read: this got me thinking for a while. In the end, my best shot is also the simplest: we (the contingent intepreter) read the function, as an act of understanding. More on the idea of contingent/essential interpreter in a rather whimsical :-) &lt;a href="http://www.dreamsongs.com/Files/Form&amp;Function.pdf" target="_blank"&gt;presentation&lt;/a&gt; by Richard Gabriel, that I already suggested a few years ago.&lt;br /&gt;&lt;br /&gt;Update: we change an artifact; for instance, we change the source code of  some function.&lt;br /&gt;&lt;br /&gt;Delete: we remove an artifact; for instance, we remove a member function from a class.&lt;br /&gt;&lt;br /&gt;Note that given the fractal nature of software, some operations are recursively identical (by deleting a component we delete all the sub-artifacts), while others change nature as we move into the fractal hierarchy (by creating a new class inside a component we're also updating the component). This is true in the run-time world of data as well.&lt;br /&gt;&lt;br /&gt;Extending CRUD to run-time procedural knowledge is not necessarily trivial. Can we talk about CRUD for functions (as run-time, not compile-time, concepts)? We usually don't, but that's because the most common material and tools (programming languages) we're using are largely based on the idea that procedural knowledge is created once (through artifacts), then compiled and executed.&lt;br /&gt;&lt;br /&gt;However, interpreted languages always had the possibility of creating, updating and deleting functions at run-time. Some compiled languages allow dynamic function creation (like C#, through Reflection.Emit) but not update/delete. The ability to update a function through reflection would be an important step toward AOP-like possibilities, but most languages have no support for that. This is fine, though: liquids can't be compressed, but that didn't prevent us from defining the concept of compression. I'm looking for concepts that apply in both worlds (artifacts and run-time) but not necessarily to all materials (languages, etc.). So, to summarize:&lt;br /&gt;&lt;br /&gt;- Create, Update, Delete retain the usual meaning also for the run-time concept of functions. It means we're literally creating, updating and deleting a function at run-time. The same applies to the (run-time) concept of class (not object). We can Create, Update, Delete classes at run-time as well (given the appropriate language/material).&lt;br /&gt;&lt;br /&gt;- Read, in the artifact world, is the human act of reading, or better, is the contingent interpreter (us) giving meaning to (interpreting) the function. At run-time, the equivalent notion is execution, with the essential interpreter (the machine) giving meaning to the function. Therefore, reading a function in the run-time world simply means executing the function. Executing a function may also update some data, but this is fine: the function is read, data are updated; there is no contradiction.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Where do we go from here?&lt;/b&gt;&lt;br /&gt;I'm trying to keep this post short, so I'll necessarily leave a lot of stuff for next time. However, I really want to anticipate something. In my previous post I said:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Two clusters of information are entangled when performing a change on one immediately requires a change on the other. &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I can now state that better as:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Two clusters of information are entangled when a C/R/U/D on one immediately requires a C/R/U/D on the other. &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Yes, the two definitions are not equivalent, as Read is not a Change. The second definition, however, is better, for reasons we'll explore in the next few posts. One reason is that it provides guidance on the kind of "change" you need to consider. Just restrict yourself to CRUD, and you'll be fine. As we'll see next, we can usually group CD and RU, and in fact I've defined two concepts representing those groupings.&lt;br /&gt;&lt;br /&gt;Entanglement through CD and/or RU is not necessarily a bad thing. It means that the entangled clusters are attracting each other, and, inasmuch as that specific force is concerned, rejecting others. In other words, they want to form a single cluster, possibly a composite cluster in the next hierarchical level (like two functions attracting themselves and creating a class). Of course, it might also be the case that the two clusters should be merged into a single cluster.&lt;br /&gt;&lt;br /&gt;We'll see more about different form of CRUD-induced entanglement in the next few posts. We'll also see how many concepts (from references to database normalization) are actually just ways to deal with the many forms of entanglement, or to move entanglement from the artifact space to the run-time space. Right now, I'll use my remaining time to explain polymorphism through the entanglement perspective. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Polymorphism explained&lt;/b&gt;&lt;br /&gt;Consider the usual idea of multiple shapes (circle, triangle, rectangle, etc.) that can be drawn on a screen. In the pre-object era (say, in ANSI C) we could have defined a ShapeType enum, a Shape struct with a ShapeType field and possibly a ShapeData field, where ShapeData would have probably been a union (with all fields for all different shapes). Draw would have been implemented as a switch/case over the ShapeType field.&lt;br /&gt;&lt;br /&gt;We have U/U entanglement between ShapeType and ShapeData, and between ShapeType and Draw. U/U means that whenever we update ShapeType we need to update ShapeData as well. I add the Spiral type, so I need to add the relevant fields in the ShapeData union, and add logic to Draw. We also have U/U entanglement between ShapeData and Draw: if we change the way we store shape data, we have to change the Draw function as it depends on those data. We could live with that, but is not pretty.&lt;br /&gt;&lt;br /&gt;What if we have another function that depends on ShapeType, like Area? Well, we need another switch-case, and Area will have the same kind of U/U entanglement with ShapeType and ShapeData as Draw. It is that entanglement that is bringing all those concepts together. ShapeType, ShapeData, Draw and Area want to form a cluster.&lt;br /&gt;&lt;br /&gt;Note that without polymorphism (language-supported or simulated through function pointers) the code mass is organized into a potentially degenerative form: every function (Draw, Area, etc) is U/U-entangled with ShapeType, and is therefore attracting new procedural knowledge related to each and every ShapeType value. The forcefield will make those functions bigger and bigger, unless of course ShapeType is no longer extended.&lt;br /&gt;&lt;br /&gt;Object-oriented polymorphism "works" because it changes the gravitational centers. Each concrete  class (Circle, Triangle, etc) becomes a gravitational center for procedural and structural knowledge entangled with a single (ex)ShapeType value. In fact, ShapeType no longer needs to exist at all. There is still U/U-entanglement between the (ex)ShapeData portion related to Circle and the procedural knowledge in Circle.Draw and Circle.Surface (in a Java/C#ish syntax). But this is fine, because they have now been brought together into a new cluster (the Circle class) that then rejected the other artifacts (the rest of the ShapeData fields, the other functions). As I said in my previous post, entanglement between distant element is bad.&lt;br /&gt;&lt;br /&gt;Note that we don't really change the mass of code. We just organize it differently, around different gravitational centers. If you draw functions as tall boxes in the switch-case form, you can see that classes are just "wide" boxes cutting through functions. The area of the boxes (the amount of code) does not change.&lt;br /&gt;&lt;br /&gt;Object-oriented polymorphism in a statically-typed language also requires [interface] inheritance. This brings in a new form of U/U-entanglement, this time between the interface and each and every concrete class. Whenever we change the interface, we have to change all the concrete classes.&lt;br /&gt;&lt;br /&gt;Interestingly, some of those functions might be entangled in the run-time world: they tend to be called together (R/R-entanglement in the run-time space). That would suggest yet another clustering (in the artifact space), like separating all the drawing operations from the geometrical operations in different interfaces.&lt;br /&gt;&lt;br /&gt;Note that the polymorphic solution is not necessarily better: it's just a matter of probability. If the set of functions is unstable, plain polymorphism is not really a good answer. We may want to explore a more complex solution based on the Visitor pattern, or some other clustering of artifacts. Understanding entanglement for Visitor is indeed an interesting exercise. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Coming soon (I hope :-)&lt;/b&gt;&lt;br /&gt;CD and RU-entanglement (with their real names :-), paving our way to the concept of isolation, or shielding, or whatever I'm gonna settle for. Oh guys, by the way: happy new year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-3649106339338291223?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/3649106339338291223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=3649106339338291223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3649106339338291223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3649106339338291223'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2011/01/notes-on-software-design-chapter-13-on.html' title='Notes on Software Design, Chapter 13: On Change'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4507504197254939450</id><published>2010-12-19T19:56:00.002+01:00</published><updated>2010-12-19T19:59:53.888+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: finito!</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; La versione &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; e' ormai completa, giusto in tempo per Natale :-).&lt;br /&gt;&lt;br /&gt;Per ora dedichero' un po' di energie al blog ed alla Physics of Software. In ogni caso, il gruppo Facebook del libro resta attivo per suggerimenti, idee ecc in merito ad una prossima versione 2.x del libro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4507504197254939450?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4507504197254939450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4507504197254939450' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4507504197254939450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4507504197254939450'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/12/c-manuale-di-stile-finito.html' title='C++ Manuale di Stile: finito!'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-6101176145597245622</id><published>2010-11-19T17:44:00.002+01:00</published><updated>2010-11-19T17:48:05.601+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Notes on Software Design, Chapter 12: Entanglement</title><content type='html'>Mechanical devices require maintenance, some more than others. Maintenance is intended to keep them working, because mechanical parts tend to wear out. Maintenance is required so that they can still work "as new", that is, do the same thing they were built to do.&lt;br /&gt;&lt;br /&gt;Software programs require maintenance, some more than others. Maintenance is intended to keep them useful, because software parts don't wear out, but they get obsolete. They solve yesterday's problems, not today's problems. Or perhaps they didn't even solve yesterday's problems right (bugs). Maintenance is required so that software can so something &lt;i&gt;different&lt;/i&gt; from what it was built to do.&lt;br /&gt;&lt;br /&gt;Looking from a slightly different perspective, software is encoded knowledge, and the value of knowledge is constantly decaying (see the concept of &lt;a href="http://www.carlopescio.com/2010/03/where-is-your-knowledge.html"&gt;half-life of knowledge&lt;/a&gt;). Maintenance is required to restore value. Energy (human work) must be supplied to keep encoded knowledge current, that is, valuable.&lt;br /&gt;&lt;br /&gt;Either way, software developers spend a large amount of their time &lt;i&gt;changing&lt;/i&gt; stuff.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Change&lt;/b&gt;&lt;br /&gt;Ideally, changes would be purely &lt;i&gt;additional&lt;/i&gt;. We would write a new software entity (e.g. a class) inside a new artifact (a source file). We would transform that artifact into something executable (if needed; interpreted languages don't need this step). We would deploy just the new executable artifact. The system would automagically discover the new artifact and start using it.&lt;br /&gt;&lt;br /&gt;Although it's possible to create systems like that (I've done it many times through plug-in architectures), programs are not written this way from the ground up. Plug-ins, assuming they exist at all, usually appears at a relatively coarse granularity. Below that level, maintenance is rarely additional. Besides, additional maintenance is only possible when the change request is aligned with the underlying architecture.&lt;br /&gt;&lt;br /&gt;So, the truth is, most often we can't simply add new knowledge to the system. We also have to change and remove existing parts. A single change request then results in a &lt;b&gt;wave&lt;/b&gt; of changes, propagating through the system. Depending on some factors (that I'll discuss later on) the wave could be dampened pretty soon, or even amplified. In that case, we'll have to change more and more parts as the wave propagates through the system. If we change a &lt;a href="http://www.carlopescio.com/2010/11/design-structure-and-decisions.html"&gt;modularized decisions&lt;/a&gt;,  the change wave is dampened at module boundary.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The nature of change&lt;/b&gt;&lt;br /&gt;Consider a system with two hardware nodes. The nodes are based on completely different hardware architectures: for instance, node 1 is a regular PC, node 2 is a DSP+ASIC embedded device. They are connected through standard transport protocols. Above transport, they don't share a single line of code, because they don't calculate the same function. &lt;br /&gt;Yet, if you change the code deployed in node 1, you have to change some (different) code in node 2 as well, or the system won't work. Yikes! Aren't those two systems &lt;b&gt;loosely coupled&lt;/b&gt; according to the traditional coupling theory? Sure. But still, changes need to happen on both sides.&lt;br /&gt;&lt;br /&gt;The example above may seem paradoxical, or academic, but is not. Most likely, you own one of those devices. It's a decoder, like those for DVB-T, sat TV, or inside DivX players. The decoder is not computing the same function as the encoder (in a sense, it's computing the inverse function). The decoder may not share any code at all with the encoder. Still, they must be constantly aligned, or you won't see squat.&lt;br /&gt;&lt;br /&gt;This is the real nature of change in software: you change something, and a number of things must be changed at the same time to preserve correctness. In a sense, change is affecting very distant, even physically disconnected components, and must be simultaneous: change X, and Y, Z, K must all change, at once. &lt;br /&gt;&lt;br /&gt;At this point, we may think that all the physical analogies are breaking down, because this is not how the physical world behaves. Except it does :-). You just have to look at the right scale, and move from the familiar Newtonian physics to the slightly less comfortable (for me, at least) quantum physics.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Quantum Entanglement&lt;/b&gt;&lt;br /&gt;Note: if you really, really, really hate physics, you can skip this part. Still, if you never came across the concept of Quantum Entanglement, you may find it interesting. Well, when I first heard of it, I thought it was amazing (though I didn't see the connection with software back then).&lt;br /&gt;&lt;br /&gt;You probably know about the &lt;a href="http://en.wikipedia.org/wiki/Uncertainty_principle" target="_blank"&gt;Heisenberg Uncertainty Principle&lt;/a&gt;. Briefly, it says that when you go down to particles like photons, you can't measure (e.g.) both position and wavelength at arbitrarily high precision. It's not a problem of measurement techniques. It's the nature of things. &lt;br /&gt;&lt;br /&gt;Turns out, however, that we can create &lt;b&gt;entangled particles&lt;/b&gt;. For instance, we can create two particles A and B that share the same exact wavelenght. Therefore, we can try to circumvent the uncertainty principle by measuring particle A wavelength, and particle B position. Now, and this is absolutely mind-blowing :-), &lt;b&gt;it does not work&lt;/b&gt;. As soon as you try to measure particle B position, particle A reacts, by collapsing its wave function, immediately, even at an arbitrary distance. You cannot observe A without changing B. &lt;br /&gt;&lt;br /&gt;Quoting &lt;a href="http://en.wikipedia.org/wiki/Quantum_entanglement" target="_blank"&gt;wikipedia&lt;/a&gt;: &lt;i&gt;Quantum entanglement [..] is a property of certain states of a quantum system containing two or more distinct objects, in which the information describing the objects is inextricably linked such that performing a measurement on one immediately alters properties of the other, even when separated at arbitrary distances.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Replace measurement with change, and that's exactly like software :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Software Entanglement&lt;/b&gt;&lt;br /&gt;The parallel between entangled particles and entangled information is relatively simple. What is even more interesting, it works both in the artifact world and in the run-time world, at every level in the corresponding hierarchy (the run-time/artifact distinction is becoming more and more central, and was sorely missing in most previous works on related concepts). On the other hand, the concept of entanglement has far-reaching consequences, and is also a trampoline to new concepts. This post, therefore, is more like a broad introduction than an in-depth scrutiny.&lt;br /&gt;&lt;br /&gt;Borrowing from quantum physics, we can define software entanglement as follows:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Two clusters of information are entangled when performing a change on one immediately requires a change on the other.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;A simple example in the artifact space is renaming a function. All (by-name) callers must be changed, immediately. Callers are entangled with the callee. A simple example in the run-time space is caching. Caching requires cache coherence mechanisms, exactly because of entanglement.&lt;br /&gt;&lt;br /&gt;Note 1: I said "by name", because callers by reference are not affected. This is strongly related with the idea of dampening, and we'll explore it in a future post.&lt;br /&gt;&lt;br /&gt;Note 2: for a while, I've been leaning on using "tangling" instead of "entanglement", as it is a more familiar word. So, in some previous posts, you'll find mentions to "tangling". In the end, I decided to go with "entanglement" because "tangling" has already being used (with different meaning) in AOP literature, and also because entanglement, although perhaps less familiar, is simply more precise.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Not your granpa coupling&lt;/b&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Coupling_(computer_science)" target="_blank"&gt;Coupling&lt;/a&gt; is a time-honored concept, born in the 70s and survived to this day. Originally, coupling was mostly concerned with &lt;i&gt;data&lt;/i&gt;. Content coupling took place when a module was tweaking another module's internal data; common coupling was about sharing a global variable; etc. Some forms of coupling were considered stronger than others.&lt;br /&gt;&lt;br /&gt;Most of those concepts can be applied to OO software as well, although most metrics for OO coupling takes a more simplified approach and mostly consider &lt;i&gt;dependencies&lt;/i&gt; as coupling. Still, some forms of dependency are considered stronger than others. Inheritance is considered stronger than composition; dependency on a concrete class is considered stronger than dependency on an interface; etc. Therefore, the mere presence of an interface between two classes is assumed to reduce coupling. If class A doesn't talk to class B, and doesn't even know about class B existence, they are considered uncoupled.&lt;br /&gt;&lt;br /&gt;Of course, lack of coupling in the traditional sense does not imply lack of entanglement. This is why so many attempts to decouple systems through layers are so ineffective. As I said many times, all those layers in business systems can't usually dampen the wave of changes coming from the (seemingly) innocent need to add a field to a database table. In every layer, we usually have some information node that is tangled with that table. Data access; business logic; user interface; they all need to change, instantly, so that this new field will be put to use. That's entanglement, and it's not going away by layering. &lt;br /&gt;&lt;br /&gt;So, isn't entanglement just coupling? No, not really. Many systems that would be defined as "loosely coupled" are indeed "heavily entangled" (the example above with the encoder/decoder is the poster child of a loosely coupled / heavily entangled system). &lt;br /&gt;&lt;br /&gt;To give honor to whom honor is due, the closest thing I've encountered in my research is the concept of &lt;i&gt;connascence&lt;/i&gt;, introduced by Meilir Page-Jones in a little known book from mid-90s ("What Every Programmer Should Know About Object-Oriented Design"). Curiously enough, I came to know connascence after I conceived entanglement, while looking for previous literature on the subject. Stille, there are some notable differences between connascence and entanglement, that I'll explore in the forthcoming posts (for instance, Page-Jones didn't consider the RT/artifact separation). &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Implications&lt;/b&gt;&lt;br /&gt;I'll explore the implications of entanglement in future posts, where I'll also try to delve deeper into the nature of change, as we can't fully understand entanglement until we fully understand change.&lt;br /&gt;&lt;br /&gt;Right now, I'd like to highlight something obvious :-), that is, having distant yet entangled information is dangerous, and having too much tangled information is either maintenance hell or performance hell (artifact vs run-time).&lt;br /&gt;&lt;br /&gt;Indeed, it's easy to classify entanglement as an attractive force. This is an oversimplification, however, so I'll leave the real meat for my next posts.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Beyond Good and Evil&lt;/b&gt;&lt;br /&gt;There is a strong urge inside the human being to classify things as "good" and "bad". Within each category, we further classify things by degree of goodness or badness. Unsurprisingly, we bring this habit into computer science.&lt;br /&gt;&lt;br /&gt;Coupling has long been sub-classified by "strength", with content coupling being stronger than stamp coupling, in turn stronger than data coupling. Even connascence has been classified by strength, with e.g. connascence of position being stronger than connascence of name. The general consensus is that we should aim for the weakest possible form of coupling / connascence.&lt;br /&gt;&lt;br /&gt;I'm going to say something &lt;b&gt;huge&lt;/b&gt; now, so be prepared :-). This is &lt;b&gt;all wrong&lt;/b&gt;. When two information nodes are entangled, changes will propagate, period. The safest entanglement is the one with the minimum likelihood of occurrence. Of course, that must be weighted with the number of entangled nodes. It's very similar to &lt;b&gt;risk exposure&lt;/b&gt; (believe or not, I couldn't find a decent link explaining the concept to the uninitiated :-).&lt;br /&gt;&lt;br /&gt;There is more. We can dampen the effects of some forms of entanglement. That requires human work, that is, energy. It's usually upfront work (sorry guys :-), although that's not always the case. Therefore, even if I came up with some classification of good/bad entanglement, it would be rather pointless, because dampening is totally context-dependent.&lt;br /&gt;&lt;br /&gt;I'll explore dampening in future posts, of course. But just to avoid excessive vagueness, think about polymorphism: it's about dampening the effect of a change (which change? Which other similar change is not dampened at all by polymorphism?). Think about the concept of reference. It's about dampening the effect of a change (in the run-time space). Etc.&lt;br /&gt;&lt;br /&gt;Your system is not really aligned with the underlying forcefield unless you have  strategies in place to dampen the effect of entanglement with high risk exposure. Conversely, a deep understanding of entanglement may highlight different solutions, where entangled information is kept together, as to minimize the cost of change. Examples will follow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What's next?&lt;/b&gt;&lt;br /&gt;Before we can talk about dampening, we really need to understand the nature of change better. As we do that, we'll learn more about entanglement as well, and how many programming and design concepts have been devised to deal with entanglement, while some concepts are still missing (but theoretically possible). It's a rather long trip, but the sky is clear :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-6101176145597245622?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/6101176145597245622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=6101176145597245622' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6101176145597245622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6101176145597245622'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/11/notes-on-software-design-chapter-12.html' title='Notes on Software Design, Chapter 12: Entanglement'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-884851823372176731</id><published>2010-11-01T15:42:00.002+01:00</published><updated>2010-11-01T15:46:11.996+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Design, Structure, and Decisions</title><content type='html'>Joe is a junior programmer in the IT department of SomeLargeCompany, Inc. His company is not in the business of software; however, they have a lot of custom programs that are constantly developed, adapted, tweaked to follow the ever-changing landscape of products, sales, regulations, etc.&lt;br /&gt;&lt;br /&gt;Joe is largely self-taught. He doesn't know much about software engineering, but in the end, he gets things done.&lt;br /&gt;&lt;br /&gt;Right now, Joe is writing some code dealing with money. He's using lots of floating points variables ("double" in his language) to store money.&lt;br /&gt;Joe does not know about the inherent rounding error of decimal-to-binary conversion (and back). He doesn't know about a decimal floating point type. He doesn't know, and didn't look for, a Money class that could also store the currency. He's just coding his way out of his problem. He didn't &lt;b&gt;choose&lt;/b&gt; to use a double after pondering on the alternatives, or based on previous experiences. It wasn't a choice at all. He just didn't know any better.&lt;br /&gt;&lt;br /&gt;Joe is actually in the middle of a rather long function, doing some database lookup, some calculations, some reporting. He learned, the hard way, that is better to check for errors. He will handle any error in the simplest possible way: by opening an error box in the middle of the function, where the error can be diagnosed.&lt;br /&gt;Joe doesn't know about design principles. He doesn't know that it's usually better to keep business logic decoupled from the user interface. He didn't &lt;b&gt;choose&lt;/b&gt; to put some GUI code inside the business logic after thinking about alternatives. He just did it. He didn't know any better.&lt;br /&gt;&lt;br /&gt;That function is so long because at some point Joe realized he had to handle several different cases. He did that the usual way: with a switch/case. He never really "got" objects and couldn't even think about using polymorphism there. He uses classes, somehow, but not at that fine granularity. So, again, he didn't &lt;b&gt;choose&lt;/b&gt; the switch/case over something else. He just didn't know any better.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Structure vs. Design&lt;/b&gt;&lt;br /&gt;Joe is a good guy, really; and his code kinda works, most of the times. But this story is not about Joe. It's about code, structure, design, and decisions: because in the end, Joe will write some serious amount of code. Code has an inner &lt;b&gt;structure&lt;/b&gt;: in this case, structure will reveal heavy reliance on primitive types (double), will reveal that business logic is tangled with database access and with user interface concerns, and will also reveal that no extension mechanism is in place. Code never lies. &lt;br /&gt;&lt;br /&gt;Now, the modern (dare I say post-agile?) way of thinking is that in the end, &lt;i&gt;the code is the design&lt;/i&gt;. That is, if you want to know the &lt;i&gt;real&lt;/i&gt; design, you have to look at the code. You'll find a lot of literature (not to mention blog posts), some from well-known authors, promoting or just holding on this idea. At some point, just about everybody gave in and accepted this as a truism. As you might guess, I didn't.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A process or a thing?&lt;/b&gt;&lt;br /&gt;Software development is a young discipline, yet extremely dynamic. It's hardly surprising to find confusion and disagreement even on the fundamentals. That includes, of course, having several hundred different definitions of "software design". For some, it's a process. For some, it's the result of that process. We then have endless debates, like "is coding a form of design?", which again are often confusing "design" with "modeling" and wasting lot of ink about nothing.&lt;br /&gt;&lt;br /&gt;It doesn't have to be that hard. Let's start with the high-level question: design as a process vs. design as a thing. It's a rather simple choice; we may even benefit from the digital version of some old, dusty &lt;a href="http://www.etymonline.com/index.php?term=design" target="_blank"&gt;etymology dictionary&lt;/a&gt;, where design is commonly defined as "mark out, devise, choose, designate, appoint". Design is an act, and therefore a process. Please don't read "process" as "a series of mechanical acts"; just consider a process as something you carry out over a period of time.&lt;br /&gt;More exactly, design is &lt;b&gt;decision&lt;/b&gt; process. We choose between alternatives, balancing forces as we go. We make decisions through a &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/ListenToYourToolsAndMaterials.pdf" target="_blank"&gt;reflective conversation&lt;/a&gt; with our materials, taking place all the time, from early requirements to bug fixing.&lt;br /&gt;&lt;br /&gt;Design, however, is &lt;b&gt;not&lt;/b&gt; the code. It is &lt;b&gt;not&lt;/b&gt; the diagram. It is &lt;b&gt;not&lt;/b&gt; an artifact. If we really want to transform design into "a thing", then it is best defined as &lt;i&gt;the set of choices that brought us to the artifact&lt;/i&gt;; assuming, of course, that we actually made any choice at all.&lt;br /&gt;&lt;br /&gt;Side note: not every decision is a design decision. Design is concerned with form, that is, with the shape of our material. Including or excluding a feature from a product, for instance, is not a design decision; it is best characterized as a marketing decision. In practice, a product often results from the interplay of marketing and design decisions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Design as a decision process&lt;/b&gt;&lt;br /&gt;Back in &lt;a href="http://www.carlopescio.com/2006/12/infrastructure-and-superstructure.html"&gt;2006&lt;/a&gt; I suggested that we shouldn't use terms like "accidental architecture" because architecture (which is just another form of design) is always intentional: it's a set of choices we &lt;b&gt;make&lt;/b&gt;. I suggested using "structure" instead.&lt;br /&gt;&lt;br /&gt;Artifacts &lt;b&gt;always&lt;/b&gt; have structure. Every artifact we use in software development is made of things (depending on our paradigm) that are somehow related (again, depending on our paradigm). That's the structure. Look at a diagram, and you'll see structure. Look at the code, and you'll see structure. Look at the executable, and if you can make sense of it, you'll see structure.&lt;br /&gt;&lt;br /&gt;There is a fundamental difference between &lt;b&gt;structure&lt;/b&gt; and &lt;b&gt;design&lt;/b&gt;. Structure can be the result of an intentional process (design) or the result of an accidental process (coding your way out of something). Design is always intentional; if it's not intentional, it's not design. &lt;br /&gt;&lt;br /&gt;So, if you want to know the real &lt;b&gt;structure&lt;/b&gt; (and yes, usually you want to), you have to look at the code. You may also look at diagrams (I would). But diagrams will show an abstract, idealized, and yes, possibly obsolete high-level structure. The "real" structure is the code structure. It would be naive, however, to confuse structure with design.&lt;br /&gt;&lt;br /&gt;Consider Joe's code. We can see some structure in that code. That structure, however, is not design. There is no rationale behind that structure, except "I didn't know any better". Joe did not &lt;i&gt;design&lt;/i&gt; his code. He just wrote it. He didn't make a single &lt;i&gt;decision&lt;/i&gt;. He did the only thing he knew. That's not design. Sorry.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is design, again?&lt;/b&gt;&lt;br /&gt;Once we agree that design is a decision process, we can see different design approaches for what they are: different ways to come to a decision.&lt;br /&gt;&lt;br /&gt;The upfront school claims that some decisions can be made before writing code, perhaps by drawing models. Taken to the extreme (which is always naive), it would require that we make all design decisions before writing code. &lt;br /&gt;&lt;br /&gt;The emergent design school claims that system-level decisions should emerge from the self-organization of lower-level decision, mostly taken by writing code according to "good practices" like Don't Repeat Yourself. Taken to the extreme (which is always naive), it would require that we make no system-level choices at all, and wait for code to jell into a well-formed structure.&lt;br /&gt;&lt;br /&gt;The pattern school claims that we can recognize forces and adopt pre-packaged decisions, embodied into a pattern.&lt;br /&gt;&lt;br /&gt;Systematic techniques like my good old SysOOD claim that we can systematically recognize some problems and choose from a set of sound transformations.&lt;br /&gt;&lt;br /&gt;The MDA school claims that we can organize decisions along two axes: decisions that we store in models, and decisions that we store in transformation tools. This would be a long story in itself.&lt;br /&gt;&lt;br /&gt;Etc.&lt;br /&gt;&lt;br /&gt;If you have a favorite design approach (say, TDD or Design by Contract) you may consider spending a little time pondering on which kind of decisions are better supported by that approach. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;There is no choice&lt;/b&gt;&lt;br /&gt;If there is no choice to be made, or if you can't see that there is a choice to be made, you are not doing design. This is so &lt;b&gt;big&lt;/b&gt; that I'll have to say it again. &lt;b&gt;If there is no choice to be made, you're not doing design&lt;/b&gt;. You might be drawing some fancy diagram, but it's not design anyway. I can draw a detailed diagram of the I/O virtualization layer for an embedded device in 10 minutes. I've done that many times. I'm not choosing anything, just replicating something. That's not design. It's "just" modeling.&lt;br /&gt;&lt;br /&gt;On the other end of the spectrum, I've been writing quite a bit of code lately, based on various Facebook APIs (the graph api, the javascript sdk, fbml, whatever). Like many other APIs, things never really work as documented (or lacking documentation, as it would be reasonable to assume). Here and there, in my code, I had to do things not the way I wanted, but the only way that actually worked. In light of the above, I can honestly say that I did &lt;b&gt;not&lt;/b&gt; design those portions. I often couldn't make a choice, although I wish I could (in this sense, it would be terrible to have someone look at that code and think that it represents "my design").&lt;br /&gt;&lt;br /&gt;Of course, that's not my first web application ever. Over time, I've written many, and I've created a lot of small reusable components. I know them well, I trust them, I have the source code, and I'm familiar with it. When I see a problem that I can easily solve by reusing one, I tend to do it on the spot.  &lt;br /&gt;Now, this is a borderline case, as I'm not really making a choice. The component is just there, crying to be reused. I'm just going with the flow. It's perhaps 5% design (recognizing the component as a good candidate and choosing to use it) and 95% habits. &lt;br /&gt;Reusing standard library classes is probably 1% design, 99% habits. We used to write our own containers and even string classes back in the early 90s. Today, I must have a very compelling case to do so (the 1% design is recognizing I don't have a very compelling case :-).&lt;br /&gt;&lt;br /&gt;Trying to generalize a little, we may like to think that we're making decisions all the time, but this is far from true. In many cases, we don't, because:&lt;br /&gt;&lt;br /&gt;- Like Joe, we don't know any better. &lt;br /&gt;&lt;br /&gt;- Like above, we're working with an unstable, poorly documented, rather crappy third party library. It's basically trial and error, with a little clean-up in the end (so, let's say 2-5% design). The library is making the choices (95-98%).&lt;br /&gt;&lt;br /&gt;- We've done this several times in the past, and we're just repeating ourselves again. It's a habit. Perhaps we should question our habit, but we don't. Perhaps we should see that we're writing the same code over and over and &lt;b&gt;design&lt;/b&gt; a reusable component, but we don't.&lt;br /&gt;&lt;br /&gt;- We (the company, the team, the community) have a standard way to do this.&lt;br /&gt;&lt;br /&gt;- The library/framework/language we're using has already made that choice.&lt;br /&gt;&lt;br /&gt;- We took a high-level decision before, and the rest follows naturally. &lt;br /&gt;&lt;br /&gt;After pondering on this for a while, I came to the conclusion that in the past I've been mixing two aspects of the decision making process. The &lt;b&gt;need&lt;/b&gt; to make a decision, and the &lt;b&gt;freedom&lt;/b&gt; to make a decision. You can plot this as a quadrant, if you want.&lt;br /&gt;&lt;br /&gt;Sometimes, there is just no need to make a choice. This can actually be a good thing. It could be a highly productive state where you just have to write down your logic. There might be short "design moments" where we make low-scale decisions (the fractal nature of software makes the decision process fractal as well), but overall we just go with the flow. As usual, the issue is &lt;b&gt;context&lt;/b&gt;. Not making a decision because there is a natural solution is quite different from not making a decision because we can't even see the possibilities, or the need. &lt;br /&gt;&lt;br /&gt;Sometimes, we need to make a choice. At that point, we need the freedom to do so. If the code is so brittle that you have to find your way by trial and error, if company standards are overly restrictive, if our language is too limited, if the architecture is too constraining, we lack freedom. That leads to sub-optimal local and global choices. Here is the challenge of architecture: make the right decisions, so that you offer a reasonable structure for growth, yet leave enough freedom for local choices, and a feedback loop from local to global.&lt;br /&gt;&lt;br /&gt;Design, as a decision process, is better experienced in bursts. You make a set of choices, and then you let the natural consequences unravel themselves. You may unravel some consequences using models, if you like it. In some cases, it's very effective. Some consequences are best unraveled by writing code. Be smart, not religious.&lt;br /&gt;&lt;br /&gt;Be aware when you have to make too many choices, too often. It's fine in the beginning, as the decision space is huge. But as you progress, the need for new choices should naturally decrease, in frequency and in scale. Think of coding as a conversation with your artifacts. Just like any conversation, it can turn into an argument and then into a fight. Your code just does not want to be shaped that way; it was never meant to be shaped that way; it is resisting your change. You change something here, just to find out that you really need to patch that other part, and so on. You have to think, think, think. Lot of effort, little progress. On a deeper level, you're &lt;a href="http://www.carlopescio.com/2009/04/bad-luck-or-fighting-forcefield.html"&gt;fighting the forcefield&lt;/a&gt;. The design is not aligned with the forcefield. There is friction (in the decision space!) and friction energy is wasted energy.&lt;br /&gt;&lt;br /&gt;Finally, if you draw a quadrant, you'll see an interesting spot where there is no need to make choices, but there is freedom to. I like that spot: it's where I know how to do it, because I've done it before, but it's not the only way to do it, and I might try something new this time. Some people don't take the opportunity, and always take the safe, known way. Depending on the project, I don't mind taking a risk if I see the potential for a sizeable reward.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What about &lt;i&gt;good&lt;/i&gt; design?&lt;/b&gt;&lt;br /&gt;Back in 1972, David Parnas wrote one of the most influential papers ever ("On the criteria to be used in decomposing systems into modules"), where two alternative modular structures were proposed for the same system. The first used the familiar functional decomposition. The second was based on the concept of Information Hiding. Later on, that paper has been heavily quoted in the OOP literature as an inspiration for encapsulation. Indeed, Parnas suggests hiding data structure details inside modules, but that was just an example. The real message was that modules should encapsulate &lt;b&gt;decisions&lt;/b&gt;: &lt;i&gt;every module [...] is characterized by its knowledge of a design decision which it hides from all others"&lt;/i&gt;; again: &lt;i&gt;"we propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others"&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Think about it, and it makes lot of sense. Design is a decision-making process. Decisions may turn out to be wrong, or may become obsolete as business and technology change. Some decisions are also meant to be temporary from the very beginning. In all cases, we would like to modularize those decisions, so that we can change them without global impact. &lt;br /&gt;&lt;br /&gt;Unfortunately, this is not how most people design software. Most decisions are not modularized at all. Worse yet, most decisions are not made &lt;b&gt;explicit&lt;/b&gt;, either in code, diagrams, sketchy notes, whatever. And worst of all, a lot of code is written without taking any decision at all, just like good ol' Joe does. "Seat of your pants" is not a design strategy.&lt;br /&gt;&lt;br /&gt;Note: given current programming technology and tools, modularizing decisions is easier said than done. For instance, I decided to use AJAX in the web application I mentioned above. I would love to modularize that decision away. But it would be damn hard. Too hard to be worth it. So I let this decision influence the overall structure. There are many cases like this. Quite often, during a joint design session, I would say something like - guys, here we're making a pervasive, non-linear choice. This is like a magic door. Once we choose, we enter into a different world.&lt;br /&gt;&lt;br /&gt;So, we're doing a good design job when we make modular decisions, that we can change later without global impact. I think this may shed a different light on delaying decisions (design decisions, not (e.g.) marketing decision). &lt;br /&gt;&lt;br /&gt;The folklore is that if you wait, you can make a more informed decision. Of course, if you wait too much, you reach a state of paralysis where you can't progress anymore, and you may also miss some opportunity along the road.&lt;br /&gt;&lt;br /&gt;From the decision modularization perspective, things are slightly more precise:&lt;br /&gt;&lt;br /&gt;- If, given our current knowledge, the decision can't be modularized, it's better to wait, because we might find a way to make it modular, or get a better picture of our problem, and hopefully make the "right" nonmodular decision. Note that when a decision is not modular, undoing/changing it will incur a substantial cost: the mass to move in the decision space will be high, and that's our measure of work.&lt;br /&gt;&lt;br /&gt;- If the decision can be modularized, but you think that given more knowledge you could modularize it better, it makes sense to wait. Otherwise, there is little or no value in waiting. Note that postponing a decision and postponing implementation are two different things (unless your only way to make a decision is by writing code). There is a strong connection with my concept of &lt;a href="http://www.carlopescio.com/2010/01/delaying-decisions.html"&gt;invariant decision&lt;/a&gt;, but I'll leave it up to you to dig around.&lt;br /&gt;&lt;br /&gt;As an aside, I'm under the impression that most people expect to just "learn the right answer" by waiting. And by "right" they mean that there is no need to modularize the decision anymore (because it's right :-). This is quite simplistic, as there is no guarantee whatsoever that a delayed decision will be particularly stable. &lt;br /&gt;So, again, the value of delaying should be in learning new ways to modularize away the decision. Learning more about the risk/opportunity trade-off of &lt;b&gt;not&lt;/b&gt; modularizing away the decision is second best.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;In a sense, software development is all about decisions. Yet, the concept is completely absent from programming and modeling languages, and not particularly explicit in most design methods as well.&lt;br /&gt;In the Physics of Software I'm trying to give Decisions a central role. Decisions are gateways to different forcefields. Conversely, we shape the forcefield by making decisions. Decisions live in the Decision Space, and software evolution is basically a process of moving our software to another position in the Decision Space. Decisions are also a key ingredient to link software design and software economics. I have many interesting ideas here, mostly based on real option theories, but that's another story.&lt;br /&gt;&lt;br /&gt;Next time: tangling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-884851823372176731?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/884851823372176731/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=884851823372176731' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/884851823372176731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/884851823372176731'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/11/design-structure-and-decisions.html' title='Design, Structure, and Decisions'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8888112205228197585</id><published>2010-10-11T17:27:00.001+02:00</published><updated>2010-10-11T17:30:01.214+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: nuovi capitoli</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; Finalmente ho trovato il tempo di integrare i capitoli 12-14 nella versione &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; del testo.&lt;br /&gt;&lt;br /&gt;Mancano meno di 20 pagine (i capitoli 1 e 2) al completamento del lavoro :-). A quel punto vorrei aggiungere una breve introduzione, che rispecchi la mia visione "moderna" di un manuale di stile, e poi verra' il momento di pensare alle versioni future.&lt;br /&gt;&lt;br /&gt;Chi vuole collaborare trova tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt; del mio sito, incluse le informazioni per unirsi al gruppo di lavoro.&lt;br /&gt;&lt;br /&gt;Per ora ringrazio come sempre tutti i volontari. I capitoli 1 e 2 non sono ancora in assegnazione - e' un periodo un po' intenso ed il tempo scarseggia. Conto di metterli online nel prossimo week-end o poco oltre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8888112205228197585?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8888112205228197585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8888112205228197585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8888112205228197585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8888112205228197585'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/10/c-manuale-di-stile-nuovi-capitoli.html' title='C++ Manuale di Stile: nuovi capitoli'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-447151406139320702</id><published>2010-10-04T15:34:00.003+02:00</published><updated>2010-10-04T15:45:14.096+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Notes on Software Design, Chapter 11: Friction in the Artifacts world</title><content type='html'>When I first "got" the concept of run-time friction, I thought it made sense only in the run-time world. I was thinking of friction as "everything that gets in the way as we process the Function", and since there is no Function in the artifact world, there can be no friction as well. That disturbed me a little, because every other concept was present in both worlds.&lt;br /&gt;&lt;br /&gt;Later on, I realized I could extend that notion to the artifact side in two distinct ways. One didn't survive scrutiny. It was too informal, although somehow I'd like to bring back some of the underlying reasoning, probably as part of a different property. The other proved more solid. Since a few people asked me (in real life) how do I get these ideas, I think it might be interesting to tell the story behind the concept; after all, a blog ought to be a... log :-). The story is not really linear, but then, very few things in life are linear.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1&lt;/b&gt;&lt;br /&gt;It was an early morning back in July. I was running. At some point (within the first few kilometers) I had a flash that perhaps the notion of &lt;a href="http://www.carlopescio.com/2008/12/notes-on-software-design-chapter-2-mass.html"&gt;mass&lt;/a&gt; was not a primitive concept. Perhaps there was a concept of volume (and LOC would give volume, not mass) and a concept of density (after all, lines can be quite different). I spent a few minutes thinking about density (the simplest idea being that perhaps something like cyclomatic complexity could explain density), then thinking that I didn't like volume because it reminded me of Halstead's Software Science, and I didn't want my work to be so disconnected from practice. Then I started to think about a concept of surface; maybe there was an ideal volume / surface ratio too? Then the zen effect of running took over and I blissfully stopped thinking :-)). [most of those ideas were good, and at some point I'll have to reconsider a few things].&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 2&lt;/b&gt;&lt;br /&gt;Days later, I was thinking about giving a name to this stuff I'm writing. I came up with a few ideas, and also run a trademark / domain name search, because you never know. Looking for "Physics of Software", I found a remotely related entry in the C2 wiki: &lt;a href="http://c2.com/cgi/wiki?PhysicalCuesInSoftwareDevelopment" target="_blank"&gt;Physical Cues In Software Development&lt;/a&gt;. &lt;br /&gt;Now, that stuff seems more concerned with the geometry/topology of code than with the physics of software, but while reading that page I was slightly tantalized by this sentence: "Too dense to refactor easily". Interesting. I did some literature research on density vs. refactoring, but nothing substantial came up.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 3&lt;/b&gt;&lt;br /&gt;Days later again. I was writing some code (yeah, I write real world code too :-). I tend to write short methods: I practice what I preach. Still, I was in the middle of a rather long function (by my standards, that is, about 100 lines). I was looking at it, trying to understand how it got to be that big. I could see the gravitational effect of having used a massive third party component; that was consistent with my current understanding of the scale-free nature of software (more on this another time).&lt;br /&gt;I could also see a few small, simple improvements, but in the end it was not trivial to refactor that method into a few shorter functions. Sure, it could be done, just not by selecting a few lines and choosing "extract method" from the refactoring menu. I had to create new classes, shuffle responsibilities around. Overall, it was a large effort (given the relatively small mass). I contemplated the idea of leaving that function alone :-). Too dense to refactor easily? Hmm.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 4&lt;/b&gt;&lt;br /&gt;Perhaps a couple of weeks later. This thing kept bouncing in my head. I always assumed I could refactor every single method into a set of smaller methods, perhaps introducing new classes. Sure, run-time friction could grow as a result, but that's just something to be balanced. But was that actually true? Could I write a function that was basically impossible to refactor, that is, where extracting a few lines required either a huge effort or, even better, where to move N symbols outside, you basically have to add N symbols inside (to call the extracted method)? Having too much to do, I left the question unanswered.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 5&lt;/b&gt;&lt;br /&gt;Just a few days later. Late evening, but unwilling to call it a day :-), I sat down trying to write a gordian function :-), a simple sequence of lines that couldn't easily be refactored. This is what I end up with:&lt;pre&gt;&lt;br /&gt;void f( int a, int b )&lt;br /&gt;  {&lt;br /&gt;  int c = a + b;&lt;br /&gt;  int d = a + c;&lt;br /&gt;  int e = b + c;&lt;br /&gt;  int f = a + d;&lt;br /&gt;  int g = b + d;&lt;br /&gt;  int h = c + d;&lt;br /&gt;  int i = c + e;&lt;br /&gt;  int j = b + e;&lt;br /&gt;  int k = a + e;&lt;br /&gt;  // ... use f, g, h, i, j, k as above&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It may be easier to visualize the pattern through a graphical view:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/gordian.jpg"/&gt;&lt;br /&gt;&lt;br /&gt;the idea is pretty simple: at every level, I'm using nearby concepts and distant concepts; I'm also creating nodes for subsequent use in lower levels.  Now, this function is trivial. Cyclomatic complexity is just 1. Yet is hard to refactor. It is hard to move things (lines, symbols, concepts) around. So I thought perhaps this was "density".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 6&lt;/b&gt;&lt;br /&gt;Out of nowhere, a few days later I realize that density was not the right name. When you have troubles moving things around, we call it viscosity, not density. That triggered an internal alert: viscosity has already been used in some computing literature, and I hate to redefine existing terms, so let's check literature again.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 7&lt;/b&gt;&lt;br /&gt;To my knowledge, "viscosity" has been used in:&lt;br /&gt;- The &lt;a href="http://www.cl.cam.ac.uk/~afb21/publications/CT2001.pdf" target="_blank"&gt;Cognitive Dimensions of Notations&lt;/a&gt; literature, where it is defined as "the difficulty of making small changes to the information structure" or "resistance to change", both of which are rather similar to what I'm thinking. Note that although the papers above are about the notation, not the code, I discussed extending those concepts from tools to materials almost &lt;a href="http://www.carlopescio.com/2008/02/cognitive-dimensions-of-notations.html"&gt;three years ago&lt;/a&gt;.&lt;br /&gt;- The well known &lt;a href="http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf" target="_blank"&gt;Design Principles and Design Patterns&lt;/a&gt; paper from Robert Martin, where it is defined as "When the design preserving methods are harder to employ than the hacks, then the viscosity of the design is high". This is completely unrelated, and honestly I'm not sure that "viscosity" is the right term. Indeed, Martin is using several physics-lookalike properties (immobility, fragility, rigidity), but it seems like they've been adopted on the basis of some vernacular usage of terms, not on the basis of strong correlation between the software world and the physical world (there is certainly no notion of "preserving a design vs. hacks" in viscosity as defined in physics).&lt;br /&gt;&lt;br /&gt;In the end, I considered viscosity as a good choice for the difficulty of moving knowledge around in the artifact world.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 8&lt;/b&gt;&lt;br /&gt;Guess what. &lt;a href="http://en.wikipedia.org/wiki/Viscosity" target="_blank"&gt;Viscosity&lt;/a&gt; is basically &lt;b&gt;friction&lt;/b&gt; (in fluids). Ok, I got it :-). &lt;br /&gt;Just like run-time friction kicks in when you try to move run-time knowledge around, artifact-side friction kicks in when you try to move artifact-side knowledge around. Code is one way of representing artifact-side knowledge. Diagrams are another way. They both manifest some resistance to change.&lt;br /&gt;Once you get the concept (almost) right, it's time to clean things up, come up with a more precise definition, see if it's useful and what you can learn from it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Defining viscosity&lt;/b&gt;&lt;br /&gt;Why is the artifact in step 5 viscous, that is, what makes it difficult to move knowledge around? The main issue is that we can't find sub-centers, because every line has local interactions (with nearby knowledge) and non-local interaction (with distant knowledge). So although every single line is using just a few symbols, you can't simply find a subset of lines that is relatively isolated from the rest. Every line is also very simple on its own, and unworthy to be moved outside alone.&lt;br /&gt;&lt;br /&gt;So, I could define a viscous artifact A like this:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;A is viscous when given any subset B of A, the mass of knowledge inside B is not significantly higher than the amount of knowledge exchanged between B and A-B&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I crafted this definition rather carefully :-). In fact, the problem with the function above is not just that every line depends on nearby and distant knowledge. It's also that it's doing very little. Otherwise, we could move a significant portion of code (doing "lot" of stuff) outside the function, of course by passing parameters. But then, the mass of knowledge inside the subset B would be higher than the mass of knowledge exchanged (the parameters). That is not the case in function f.&lt;br /&gt;&lt;br /&gt;Viscous artifacts resist shear/tensile stress, that is, they resist extraction of knowledge. As we try to move the knowledge in B outside A, the knowledge exchanged with A-B is opposing the movement. The effort we have to spend to reorganize viscous artifacts is the equivalent of friction energy in the run-time world. Only, this time, it's human work, not CPU work.&lt;br /&gt;&lt;br /&gt;Note: I could come up with some kind of formula for a viscosity coefficient. I did not because I feel I'm not yet at that stage. Still, the minimum ratio between exchanged and internal knowledge (quantified over the subsets B, not over A) seems like a good candidate.&lt;br /&gt;&lt;br /&gt;It is important to understand that viscosity is an &lt;i&gt;internal&lt;/i&gt; property of an artifact. It has nothing to do with the artifact interface. It's about the artifact internals. Of course, given the hierarchy of artifacts, an artifact may have low [internal] viscosity, yet be part of a viscous higher-level artifact. For instance, a low-viscosity function can be part of an high-viscosity class. In that case, it would be easy to move some portions of code outside the function, but not outside the class.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Consequences&lt;/b&gt;&lt;br /&gt;Once again, we have to resist the temptation to define some property as "bad". In the physical world, viscosity is not "bad". It can be useful, or it can be a problem: it's a matter of context.&lt;br /&gt;&lt;br /&gt;Besides, when you look at the definition above, you may see some relationship with a vague notion of cohesion: a viscous artifact is "more cohesive". Cohesion is usually considered a good property. What's wrong here?&lt;br /&gt;&lt;br /&gt;My current understanding is that it's fine to be viscous when the mass is small. Actually, it's good to be viscous when the mass is small. A small viscous chunk of knowledge is a good center: it stands on its own, and can't be easily broken. However, &lt;b&gt;viscosity should decrease as mass increases&lt;/b&gt;. That gives an opportunity for extraction of knowledge, thereby forming new centers. Note that by saying so, I'm implicitly accepting the existence of high-mass artifacts. Still:&lt;br /&gt;&lt;br /&gt;- high-mass, low-viscosity artifacts can be considered as rather innocent underengineering, a form of technical debt that can be easily repaid (see also the latest comments to &lt;a href="http://www.carlopescio.com/2010/04/notes-on-software-design-chapter-0-what.html"&gt;Chapter 0&lt;/a&gt;). The high gravity of the artifact will bring in more stuff: that would be the ideal time to refactor the code, which will be easy, since viscosity is low.&lt;br /&gt;&lt;br /&gt;- high-mass, high-viscosity artifacts are a serious design weakness that should be dealt with as soon as you notice, possibly while you're still creating the artifact. Gravity will bring in more stuff, and things can only get worse.&lt;br /&gt;&lt;br /&gt;Note: a trivial refactoring of a viscous artifact will significantly increase run-time friction, as we'll have to pass a lot of parameters around. In most cases, we'll have to rethink the artifact and perhaps a significant portion of the surroundings, as we may have chosen the wrong centers.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;It's sort of revealing that I started with a notion of density but ended up with a notion of viscosity, and had to reject an existing definition of viscosity in the process. Labeling software phenomena after physical phenomena is simple. Doing so in a meaningful way is not so trivial. &lt;br /&gt;&lt;br /&gt;I think that keeping the duality run-time / artifact in mind is helping me a lot in this journey. Things are much easier once you can clearly see that you're dealing with two different worlds. A &lt;a href="http://blogs.msdn.com/b/ricom/archive/2010/09/27/less-loosely-coupled-than-meets-the-eye.aspx" target="_blank"&gt;recent post&lt;/a&gt; by Rico Mariani, for instance, raises an interesting point, which is trivially explained within my frame of reasoning, but seems unnecessarily obscure when you simply talk about "coupling" and ignore the artifact/run-time duality.&lt;br /&gt;&lt;br /&gt;As I progress in cleaning up some ideas on the decision space, I hope to bring in even more clarity. Which reminds me that I have something really important to say about design and decisions. It's short, and I'll let it preempt :-) the next chapter on tangling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-447151406139320702?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/447151406139320702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=447151406139320702' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/447151406139320702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/447151406139320702'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/10/notes-on-software-design-chapter-11.html' title='Notes on Software Design, Chapter 11: Friction in the Artifacts world'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-2290505128185289058</id><published>2010-09-12T18:40:00.002+02:00</published><updated>2010-09-12T20:13:22.356+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Notes on Software Design, Chapter 10: Run-Time Friction</title><content type='html'>So, here is the story. I keep a lot of notes. Some are text files with relevant links and organized ideas. Most are rather embarrassing scribbles on just about any piece of paper that is lying around when I need it. From time to time, I move some notes from paper to files, discard concepts that didn't prove themselves, and rearrange paragraphs to fake some kind of logical, sequential reasoning over a process that was, in fact, rather chaotic.  Not surprisingly (since software is just another way to encode knowledge), David Parnas suggested long ago that we could do the same while documenting software design (see &lt;a href="http://web.cs.wpi.edu/~gpollice/cs3733-b05/Readings/FAKE-IT.pdf" target="_blank"&gt;"A rational design process: How and why to fake it"&lt;/a&gt;). &lt;br /&gt;Well, it's not always easy. Sometimes, I try to approach the storytelling from an angle, see that it doesn't work out so well, and look for another. Sometimes I succeed, sometimes I don't (although, of course, the reader is the ultimate judge). This time, I have to confess, I feel like I couldn't find the right angle, the right way to start, to unfold a concept in a way that makes it look simple and natural. So I'll trust you to be smart enough to make sense of what follows :-). It's a very long post, and you may want to digest it in more than one session.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The physical world&lt;/b&gt;&lt;br /&gt;I guess you all had to push some furniture around at one time or another. You have probably felt a stronger resistance in the beginning, followed by a milder form of resistance as soon as you got some movement. &lt;br /&gt;The mild resistance is due to kinetic friction, while the initial, stronger resistance is usually due to static friction, that you have to overcome before moving the object (if you're not familiar with kinetic and static friction, &lt;a href="http://en.wikipedia.org/wiki/Friction" target="_blank"&gt;wikipedia&lt;/a&gt;will tell you more than you want to know :-).&lt;br /&gt;&lt;br /&gt;As you move your stuff around, friction makes you &lt;b&gt;waste some energy&lt;/b&gt;, in a way that is basically proportional to the normal force, the distance, and the coefficient of kinetic friction (see the page above for the actual equation). I'll get back to this later, but if you move a constant mass on a flat surface, the energy you waste is proportional to the mass you move, the distance you go, and the magic coefficient of friction.&lt;br /&gt;&lt;br /&gt;The beauty of all this is that it's simple and rather unambiguous. Friction is always present in mechanical engineering, but it's a well understood concept (as far as engineering is concerned; it's still blurry at the quantum level, at least for the uninitiated like myself), and there is usually no wishy-washy talking about friction. It's not a broad concept, that is, you won't be able to design the next-generation jet engine if all you have in your conceptual toolbox is friction, yet you won't be able to design an engine at all without an appreciation of friction.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The software world&lt;/b&gt;&lt;br /&gt;I'm first and foremost a software design practitioner: I design software, almost every day. Sometimes by myself, most often with other people; therefore, I do a lot of "design talk". In many cases, at one point or another, someone is going to bring in "performance" or "efficiency" to support (or reject) a design decision. &lt;br /&gt;We use those words a lot, with different meaning depending on who's saying it and why he's saying it. It seems like I'm never tired of linking wikipedia, so here is a page on  &lt;a href="http://en.wikipedia.org/wiki/Computer_performance" target="_blank"&gt;computer performance&lt;/a &gt;. Just look at the initial list of different, context-dependent meanings. It's not surprising, then, to find out some people have very peculiar views of performance. "I use arrays because they're more efficient". Sure, except that then you do a linear search because you need multiple indexes; say "efficient" again :-)? &lt;br /&gt;&lt;br /&gt;One might expect Computer Science (with capital letters :-) to come to the rescue and define terms more precisely, and hopefully with some relevance for practice. However, computer science is more concerned with &lt;a href="http://en.wikipedia.org/wiki/Algorithmic_complexity" target="_blank"&gt;computational complexity theory&lt;/a&gt; than with the nitty-gritty details of being "fast".&lt;br /&gt;Now, don't get me wrong. You won't get too far as a programmer (and definitely not as a software designer) if you don't get the concept of complexity classes, if you can't see that an algorithm is O( n^2 ) and another is O( n log n ), or if you don't even know what the &lt;a href="http://en.wikipedia.org/wiki/Big_Oh_notation" target="_blank"&gt;Big Oh notation&lt;/a&gt; is all about. You &lt;b&gt;have&lt;/b&gt; to know this stuff, period. In a sense, complexity theory is part of the &lt;i&gt;math of software&lt;/i&gt;, and there is little point in investigating a &lt;a href="http://www.physicsofsoftware.com" target="_blank"&gt;physics of software&lt;/a&gt;  if you don't get the math first. But math alone won't cut it. However, once we get past the complexity class we get very little assistance from computer science (and I'm purposely ignoring the fact that just because an algorithm is in the O( n log n ) class in the average case doesn't mean I can't beat it with an O( n^2 ) algorithm in my &lt;i&gt;practical&lt;/i&gt; cases). &lt;br /&gt;&lt;br /&gt;On the "software engineering" side, the usual advice is to build the program and then use a profiler. Yeah, well, sure, beats banging your head against the wall :-), but it's not exactly like knowing what you're doing all along. Still, we make a lot of low-level design decisions while coding, and many of them will ultimately impact "performance". Lacking the basic terminology to think (and talk) about this kind of stuff is rather depressing, so why don't we try to move just a tiny step forward?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wasting energy in software&lt;/b&gt;&lt;br /&gt;So, here I have this piece of software (executable knowledge). For most practical applications, what I need is to get some data (interactively, from a DB, through some kind of device, whatever), transform it in a meaningful way (which could be a complex process encoded in thousands of lines), and spit out some results (which is still data, anyway). The transformation is the &lt;i&gt;Function&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;On the artifact side, our software may be using global variables all around, or be based on a nice polymorphic structure, yet the Function doesn't care. The structure we provide on the artifact side is the domain of Form (by now, you're probably familiar with all this stuff). &lt;br /&gt;&lt;br /&gt;Now, transformation is a process, and no real-world process is 100% efficient; it's always going to waste something. Perhaps we should look better at that "waste" part. Something I learnt a long time ago, while pondering on &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/sysdes.pdf" target="_blank"&gt;principles and patterns&lt;/a&gt;, is that overly general concepts (like "performance") must give way to more specialized notions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Some code, please :-)&lt;/b&gt;&lt;br /&gt;Consider this short portion of C code. I'm using C because it's a low-level language, where the implications of any given choice are relatively easy to understand.&lt;br /&gt;&lt;pre&gt;double max( double x, double y )&lt;br /&gt;  {&lt;br /&gt;  if( x &gt; y )&lt;br /&gt;    return x;&lt;br /&gt;  else&lt;br /&gt;    return y;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;double max3( double x, double y, double z )&lt;br /&gt;  {&lt;br /&gt;  double d = max( x, y );&lt;br /&gt;  d = max( d, z );&lt;br /&gt;  return d;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;The code is pretty obvious. In a common, stack-based CPU architecture, max3 will copy x and y on the stack and call max; then it will copy d and z and call max again. The return value might be stored in a CPU register or in RAM, depending on the compiler. &lt;br /&gt;&lt;br /&gt;Copying those values is a waste of energy, of course. I could manually inline max inside max3 and get rid of that waste. I would sacrifice reusability and perhaps clarity for "higher performance" or "higher efficiency" or "reduced waste". Alternatively, the compiler could inline the function on my behalf (see &lt;a href="http://www.carlopescio.com/2010/06/notes-on-software-design-chapter-6.html"&gt;Chapter 6&lt;/a&gt; for the role of languages on balancing the two worlds).&lt;br /&gt;&lt;br /&gt;What if I'm working on some large data structure? The Fortran guy down the corner will suggest that by keeping your structures in the common area / global memory, you won't even have to pass parameters around: every function knows exactly where to get input and where to store output! Again, we'll sacrifice reusability, and perhaps duplicate large portions of code, for sake of efficiency. As you go through most literature on High Performance Computing (see, for instance, &lt;a href="http://queue.acm.org/detail.cfm?id=1820518" target="_blank"&gt;The Ideal HPC Programming Language&lt;/a&gt;, recently reprinted in Communications of ACM), you'll see that the HPC community is constantly facing the problem of wasted cycles, and is wasting a lot of LOC to prevent that.&lt;br /&gt;&lt;br /&gt;Moving data around is not the only way to waste energy. Consider this portion of real-world code, written by a (supposedly) performance-conscious "little meritocracy":&lt;br /&gt;&lt;pre&gt;static int is_rfc2822_header(char *line)&lt;br /&gt;{&lt;br /&gt;int ch;&lt;br /&gt;char *cp = line; &lt;br /&gt;if (!memcmp(line, "From ", 5) || !memcmp(line, "&gt;From ", 6))&lt;br /&gt;  return 1;&lt;br /&gt;while ((ch = *cp++)) { &lt;br /&gt;  if (ch == ':')&lt;br /&gt;    return cp != line;&lt;br /&gt;  if ((33 &lt;= ch &amp;&amp; ch &lt;= 57) ||&lt;br /&gt;     (59 &lt;= ch &amp;&amp; ch &lt;= 126))&lt;br /&gt;    continue;&lt;br /&gt;  break;&lt;br /&gt;  }&lt;br /&gt;return 0;&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;yeah, it's ugly as hell, but it's also wasteful (which is funny, for reasons that are too long to explain here). If you read it carefully, you'll find a way to optimize the "while" body quite a bit, and while you're at it, you can easily make it more readable. Also, the two memcmp in the beginning are wasting cycles (going through the first 5 characters twice), but just like the coefficient of friction must be measured in practice, at this level any alternative should really be measured on a real-world CPU.&lt;br /&gt;&lt;br /&gt;Note: as we optimize code, we have to assume that is correct. We don't change Form unless we know that the Function is right. Before posting this, I checked for any update to the codebase (I got that code a few years ago, and it never looked right to me). The code is still the same, but now there is also a comment explaining what the function is intended to do. Unfortunately, it's not what it's doing, which is even more ironic, for the same unspoken reasons above. Anyway, we could easily fix the bug &lt;b&gt;and&lt;/b&gt; still optimize the code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Run-time Friction&lt;/b&gt;&lt;br /&gt;Just like in the physical world we move object around, in the run-time world of software we move knowledge around. More exactly, we move data around (we call it data flow) and we move the execution point around (we call it control flow). We move that stuff around to calculate some Function. In the process of calculating the Function, we usually waste some cycles. We waste cycles because we have to copy data on the stack, or from one data structure to another. We waste cycles because we do unnecessary comparison, computations, jumps. We waste cycles because we process the same data more than once. Most often, we waste those cycles because we get something in exchange in the Form (artifact) domain. Sometimes, we waste cycles just because of bad coding.&lt;br /&gt;&lt;br /&gt;The energy waste is not a constant: copying an integer is different from copying an array of integers (that's weight, of course). Also, if your array has been swapped out to the paging file, the copy is going to cost you more: that's the contribution of distance, and I'll get back to this later. Right now, remember that wasted energy is a consequence of friction, but &lt;b&gt;is not&lt;/b&gt; friction. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Causes and types of software friction&lt;/b&gt;&lt;br /&gt;We have already seen a few cases of software friction: when you copy data, you waste cycles. Max3 didn't strictly need to copy data: the Function didn't care about reusing max, only Form did. Before we try do define friction more precisely, it's interesting to see how deep the analogy with real-world friction really is. Indeed, we even have static software friction, and kinetic software friction!&lt;br /&gt;&lt;br /&gt;Consider a Java (or .NET) virtual machine. When you hit a function for the first time, the code is compiled just in time. This has nothing to do with Function. It is a byproduct of a technological choice. It will cost you some cycles: that's friction. Also, it happens only once, to "put things in motion": that's &lt;i&gt;static friction&lt;/i&gt;. In general, &lt;b&gt;static friction will increase latency&lt;/b&gt;, while &lt;b&gt;kinetic friction will reduce throughput&lt;/b&gt;. Good: we just sorted out the two main components of "performance".&lt;br /&gt;&lt;br /&gt;Consider a web service. Before you can call the server, you go through a relatively lengthy process, from high-level stuff (marshaling your data) to low level stuff (establishing a network connection). This is all friction: the Function is happening on the other side, inside the service code. Here we see both static and kinetic friction at play: establishing a connection adds latency, exchanging data over the network reduces throughput. &lt;br /&gt;&lt;br /&gt;Consider stored procedures. The ideal stored procedure takes little data in input, does significant CRUD inside, and returns little. This way, we have minimal waste due to kinetic friction, as we exchange little data with the database. Of course, this is not the only way to minimize energy waste: another approach would be to reduce distance, by bringing the database itself in-process. Interestingly, most real-time databases use the second approach.&lt;br /&gt;&lt;br /&gt;So, what is causing friction in software?  Friction is caused by:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A copy of data from one place to another (e.g. parameter passing, temporary variables, etc), as this adds no meaning to data, and therefore is useless as far as Function is concerned.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Syntactical transformation of data (e.g. marshaling) which adds no semantics (as above: this processing is not part of the Function). This includes any form of data transformation needed to talk over a non-native protocol.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Unnecessary statements (like those that could be removed in the C function above). &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Redundant access / processing (some will be removed by the compiler, but some won't)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Bookkeeping (allocation, deallocation, reference counting, heap defragmentation, garbage collection, paging, etc). All this adds no semantics, and it's irrelevant for the Function: indeed, a well-written garbage collected program should behave properly under the so-called &lt;a href="http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx" target="blank"&gt;null garbage collector&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Unnecessary indirection. This is a long story and I'll leave for another time, as I've yet to talk about indirection in the physics of software.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In general, &lt;b&gt;everything that is not strictly necessary to calculate the Function&lt;/b&gt;, but has been added because of Form, or because of the programmer's inability to streamline the code to the mere Function, is a source of friction and will waste run-time energy.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Defining friction&lt;/b&gt;&lt;br /&gt;At this stage in my understanding of the physics of software, it's still hard to come up with numbers, coefficients, sometimes even formulas. Actually, I'm usually happy when I get some concept right. Still, let's look at a simplified formula for the energy wasted through friction (in the real world):&lt;br /&gt;&lt;br /&gt;Normal Force * Coefficient of Friction * Distance.&lt;br /&gt;&lt;br /&gt;That would hold pretty well in the software world as well, both at the qualitative (easier) and probably quantitative (not there yet) level. At the qualitative level, it tells us what we can control and perhaps leverage. I'll explore this in the next paragraph. At the quantitative level, it could help to evaluate low-level choices. First, however, we have to define Normal Force, Coefficient of Friction, and Distance.&lt;br /&gt;&lt;br /&gt;I've defined distance in the run-time world in &lt;a href="http://www.carlopescio.com/2010/08/notes-on-software-design-chapter-9.html"&gt;Chapter 9&lt;/a&gt;. Unfortunately, it's an ordinal scale, so we can't do math with distance. This sort of rules out any chance to have a quantitative definition of friction, but we can also look at it from the other side: a better understanding of friction energy (like: wasted cycles) could shed light on the right measurement scale for distance!&lt;br /&gt;&lt;br /&gt;Assuming a flat world (I have no reason to think otherwise) the Normal Force is just weight. Weight could be easily defined as the number of bytes involved. For instance, the cost of a copy is linear with the number of bytes you copy.&lt;br /&gt;&lt;br /&gt;The coefficient of friction is a dimensionless parameter. Interestingly, if we decide to measure energy in cycles (which makes some sense, although we usually think of cycles as time, not energy) that would imply that unit of measurement for Distance is cycles/byte. I'll have to think more about this.&lt;br /&gt;&lt;br /&gt;Although the coefficient of friction, in the real world, cannot be predicted but only measured, we have some intuitive grasp of it being related to the materials. As the aforementioned wikipedia page explains, it's a relatively complex "system property", depending on many factors. The same applies in the software world. The cost to move a bunch of bytes from one position to another dependes on a bunch of factors. If we want to raise the abstraction level and think in terms of objects, and not bytes, things become more complex. The exact copy semantics (reference, shallow, deep) kicks in. That's fine: a software material with shallow copy semantics would have a different coefficient of friction than one with reference copy semantics. &lt;br /&gt;&lt;br /&gt;Overall, I think we have little control over the coefficient of friction (I might be wrong), so for any practical purpose, distance and weight are the most interesting parameters.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Is it useful, anyway?&lt;/b&gt;&lt;br /&gt;A good theory, and a good concept, must have a good explanatory power, that is, we should be able to use them to explain known phenomena, explain why something works, rationalize widespread practice or beliefs, etc.&lt;br /&gt;&lt;br /&gt;As I've already discussed, the evolution of programming languages can be largely seen as an attempt to balance the world of artifact / form with the run-time / function world. In this sense, we can look for instance at the &lt;a href="http://thbecker.net/articles/rvalue_references/section_07.html" target="blank"&gt;perfect forwarding&lt;/a&gt; problem, solved by right value references in the next C++ standard, as a further attempt to remove some energy waste, by avoiding unnecessary copy of data. C++ provides many ways to control friction energy, mostly in the area of generic programming and also template metaprogramming. The &lt;a href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" target="blank"&gt;Curiously Recurring Template Pattern&lt;/a&gt;, for instance, provides a form of static polymorphism exactly to avoid some friction due to unnecessary indirection (virtual dispatch).&lt;br /&gt;&lt;br /&gt;More generally, the simple equation for energy waste provides a clue on what we can actually control: weight, distance, coefficient of friction. This is it. As we shape software, this is what we can actually change if we want to reduce friction energy.&lt;br /&gt;&lt;br /&gt;Consider &lt;a href="http://en.wikipedia.org/wiki/HTTP_compression" target="blank"&gt;HTTP compression&lt;/a&gt;: distance couldn't be changed, so we had to change weight.&lt;br /&gt;&lt;br /&gt;Also, understanding the difference between static and kinetic friction explains a lot of existing practices. Think of the &lt;a href="http://en.wikipedia.org/wiki/Nagle's_algorith" target="blank"&gt;Nagle's algorithm&lt;/a&gt;. It works by increasing static friction (therefore latency) in exchange for lower kinetic friction (therefore throughput). Once you get your concepts right, so many things unfold so easily :-).&lt;br /&gt;&lt;br /&gt;Finally, the analogy holds to the extremes: just like excessive friction in mechanical systems can lead to jam, excessive friction due to paging can jam a software system. This is commonly known as &lt;a href="http://en.wikipedia.org/wiki/Thrashing_(computer_science)" target="blank"&gt; Trashing&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I think a caveat is in order: friction in the physical world is not necessarily evil. Wasn't it for friction, we couldn't even walk. Mechanical devices have to deal with friction all the time, but they also &lt;i&gt;exploit&lt;/i&gt; friction all the time. It's harder to exploit friction in software (although the Nagle's algorithm does). Most often, we must see friction as a trade/off with other properties, mostly in the artifact side. Still, an understanding of the different types of friction, and of the constituents of friction energy, can help evaluate alternatives and even generate new, better ideas in a more systematic and (dare I say it :-) scientific way.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A different angle&lt;/b&gt;&lt;br /&gt;I choose friction as a physical analogy because it's a simple, familiar concept. Intuition and everyday experience can easily compensate any lack of engineering knowledge. Still, I've been tempted to use different analogies, like hydraulic or electrical analogies. Indeed, there are several analogies between electrical, mechanical, hydraulic and even acoustic and optical systems (see &lt;a href="http://en.wikipedia.org/wiki/Hydraulic_analogy" target="_blank"&gt;here&lt;/a&gt; for a start), so it's always possible to choose a different reference system.&lt;br /&gt;&lt;br /&gt;Anyway, my alternative would have been to model everything after resistance and current. Current would be  the equivalent of throughput, or "performance", and resistance would cause thermal dissipation. In the end, I didn't go this way for a number of reasons; for instance, one-shot stuff like JIT would require something like a thermistor (think of a PTC in CRT degaussing), but I would lose a few readers that way :-). &lt;br /&gt;&lt;br /&gt;Still, if you followed so far, there is an interesting result I'd like to share. Consider a trivial circuit where we apply 1V to a 1 ohm resistor, resulting in 1A current. Now, I'll replace the resistor with a series of 2, with resistance (1-P) and P ohms. Nothing changes, same current. Resistors represent processes.&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/amdahl.png"/&gt;&lt;br /&gt;Now say that we have this concept of parallel execution, so the process carried out by P can be  parallelized. By way of the analogy, to increase throughput (current) I can simply add up to N resistors in parallel. Now the circulating current is obviously 1 / (1-P + P/N) A. Guess what, I just rediscovered &lt;a href="http://en.wikipedia.org/wiki/Amdahl's_law" target="_blank"&gt;Amdahl's Law&lt;/a&gt; using Ohm's Law. That's cute :-).&lt;br /&gt;&lt;br /&gt;Ok guys, next time I'll have a much shorter post on the artifact-side notion of friction. If we survive that, we'll be ready for tangling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-2290505128185289058?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/2290505128185289058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=2290505128185289058' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2290505128185289058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2290505128185289058'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/09/notes-on-software-design-chapter-10-run.html' title='Notes on Software Design, Chapter 10: Run-Time Friction'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-6270357921309855169</id><published>2010-09-06T14:05:00.002+02:00</published><updated>2010-10-11T17:27:08.141+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: nuovi capitoli</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; La versione &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; fa un altro passo avanti: ho integrato i capitoli 10 e 11. Siamo arrivati all'80% circa del testo (l'elenco delle raccomandazioni e' "generabile" e quindi non richiedera' revisione).&lt;br /&gt;&lt;br /&gt;Per chi vuole collaborare: e' iniziata la revisione dei capitoli 12-13-14. Tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt; del mio sito, incluse le informazioni per unirsi al gruppo di lavoro. Al solito, vi invito a diffondere l'iniziativa, siamo quasi al traguardo :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-6270357921309855169?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/6270357921309855169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=6270357921309855169' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6270357921309855169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6270357921309855169'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/09/c-manuale-di-stile-nuovi-capitoli.html' title='C++ Manuale di Stile: nuovi capitoli'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-1355984474331843307</id><published>2010-08-19T14:56:00.003+02:00</published><updated>2010-08-19T18:06:53.621+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Notes on Software Design, Chapter 9. A simple property: Distance (part 2)</title><content type='html'>What is Distance in the run-time world? As I began pondering on this, it turned out I could define  distance in several meaningful ways. Some were redundant with other notions I have yet to present. Some were useless for a theory of software design. In the end, I picked up a very simple definition, with some interesting ramifications.&lt;br /&gt;&lt;br /&gt;Just like the  notion of distance in the artifact world is based on the hierarchy of artifacts, the notion of distance in the run-time world is based on a hierarchy of locations. These are the locations where executable knowledge is located at any given time. So, given two pieces of executable knowledge P1 and P2, we can define an ordinal scale:&lt;br /&gt;&lt;br /&gt;P1 and P2 are inside the CPU registers or the CPU execution pipeline - that's minimum distance.&lt;br /&gt;P1 and P2 are inside the same L1 cache line&lt;br /&gt;P1 and P2 are inside the L1 cache&lt;br /&gt;… etc&lt;br /&gt;&lt;br /&gt;for the full scale, see the (updated) &lt;a href="http://www.PhysicsOfSoftware.com/Summary.pdf"&gt;Summary&lt;/a&gt; at the &lt;a href="http://www.PhysicsOfSoftware.com/"&gt;Physics of Software&lt;/a&gt; website. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dude, I don't care about cache lines!&lt;/b&gt;&lt;br /&gt;Yeah, well, but the processor does, and I'm looking for a good model of the real-world, not for an abstract model of computing disconnected from reality (which would be more like the math of software, not the physics). &lt;br /&gt;You may be writing your code in Java or C#, or even in C++, and be blissfully unaware of what is going on under the hood. But the caches are there, and their effect is absolutely visible. For a simple, experimental, and well-written summary, see Igor Ostrovsky's &lt;a href="http://igoro.com/archive/gallery-of-processor-cache-effects/" target="_blank"&gt;Gallery of Processor Cache Effects&lt;/a&gt; (the source code is in C#,  but results wouldn't be different in Java or C++).&lt;br /&gt;Interestingly enough, most algorithms and data structures are &lt;b&gt;not&lt;/b&gt; optimized for modern processors with N levels of cache. Still, there is an active area of research on &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.44.5650" target="_blank"&gt;cache-oblivious algorithms&lt;/a&gt; which, despite the name, are supposed to perform well with any cache line size across any number of cache levels (you can find a few links to specialized algorithms &lt;a href="http://blogs.msdn.com/b/devdev/archive/2007/06/12/cache-oblivious-data-structures.aspx" target="_blank"&gt;here&lt;/a&gt; but you'll have to work around broken links).&lt;br /&gt;&lt;br /&gt;What about virtual memory? Again, we can ignore the magic most of the times, but when we're looking for high-performance solutions, we have to deal with it. Unconvinced? Take a look at &lt;a href="http://queue.acm.org/detail.cfm?id=1814327" target="_blank"&gt;You're Doing It Wrong&lt;/a&gt;, where Poul-Henning Kamp explains (perhaps with a bit too much "I know it all and you don't" attitude :-)) why textbooks are not really talking about real-world computers [anymore].&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Consequences&lt;/b&gt;&lt;br /&gt;What happens when run-time distance grows? We're bound to see a staircase-like behavior, as in the second picture in the gallery above, just with more risers/treads. When you move outside your process, you have context switching. When you move outside your computer, you have network latency. When you move outside your LAN, you also have name lookup and &lt;a href="http://compnetworking.about.com/od/networkdesign/l/bldef_hop.htm" target="_blank"&gt;packet hops&lt;/a&gt;. We'll understand all this stuff much better as we get to the concept of friction.&lt;br /&gt;&lt;br /&gt;There is more. When talking about artifact distance, I said that coupling (between artifacts) should decrease as distance increases. In the run-time world, coupling &lt;b&gt;to the underlying platform&lt;/b&gt; should decrease as distance increases. This must be partially reflected in the artifacts themselves, but it is also a language / platform / transformation concern.&lt;br /&gt;Knowledge at short distance can be tightly coupled to a specific hw / sw platform. For instance, all code inside one component can be tightly bound to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An internal object model, say the C++ object model of a specific compiler version, or the C# or Java object model for a specific version of the virtual machine.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A specific operating system, if not virtualized (native code).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A specific hardware, if not virtualized.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is fine at some level. I can even accept the idea that all the components inside a single application have to share some underlying assumptions. Sure, it would be better if components were relatively immune from binary issues (a plague in the C++ world). But overall (depending on the size of the application) I can "control" things and make sure everything is aligned.&lt;br /&gt;But when I'm talking to another service / application over the network, my degree of control is much smaller. If everything is platform-dependent (with a broad definition of platform, mind you: Java is a platform), we're in for major deployment / maintenance issues. Even worse, it would represent a huge platform lock-in (I can't use a different technology for a new service). Things get just worse on a global network scale. This is why XML took the world by storm, why web services have been rather successful in the real world, and so on. This is also why I like technologies / languages that take integration with other technologies / languages seriously, and not &lt;a href="http://www.carlopescio.com/2005/07/pure-something-considered-harmful.html "&gt;religiously&lt;/a&gt;.&lt;br /&gt;As usual, the statement above is bi-directional. That is, it makes very little sense to pursue strong decoupling from the underlying platforms at micro-level. Having a class talking to itself in XML is not a brilliant strategy. Again, design is about balance: in this case, balance between efficiency and convenience on one side, and flexibility and evolvability on the other. Balance is obtained when you can depend on your platform locally, and be increasingly independent as you move farther. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Run-time Distance is not a constant&lt;/b&gt;&lt;br /&gt;Not necessarily, anyway; it depends on small-scale technical choices. In C++, for instance, once you get two objects in the same cache line, they will stay there for their entire life, because identity in C++ is address-based. In a garbage collected environment, this is not true anymore: objects can move freely during collection. &lt;br /&gt;Moreover, once we move from the cache line to the entire cache, things come and go, they become near and distant along time. This contributes to complex performance patterns, and indeed, modern hardware makes accurate performance prediction almost impossible. I'm pretty sure there are some interesting phenomena to be studied here - a concept of oscillating distance, perhaps  the equivalent of  a performance &lt;a href="http://en.wikipedia.org/wiki/Beat_(acoustics)" target="_blank"&gt;beat&lt;/a&gt; when two concurrent threads have slightly different oscillating frequency, and so on, but I'm not currently investigating any of this - it's just too early.&lt;br /&gt;At some point, distance becomes more and more "constant". Sure, a local service may migrate to LAN and then to WAN, but usually it does so because of human intervention (decisions!), and may require changes on the artifact side as well. Short-range distance is a fluid notion, changing as executable knowledge is, well, executed :-).&lt;br /&gt;&lt;br /&gt;By the way: distance in the artifact world is not a constant, either. It is constant when the code is frozen. As soon as we change it, we change some distance relationships. In other words, when the computer is processing executable knowledge, run-time distance changes. When &lt;b&gt;we&lt;/b&gt; process encoded knowledge (artifacts), artifact distance changes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Distance-preserving transformations&lt;/b&gt;&lt;br /&gt;Knowledge encoded in artifacts can be transformed several times before becoming executable knowledge. Most of those transformations are distance-preserving, that is, they map nearby knowledge to nearby knowledge (although with some jumps here and there).&lt;br /&gt;&lt;br /&gt;For instance, pure sequences of statements (without choices, iterations, calls) are "naturally" converted into sequential machine-level instructions that not only will likely sit in the same cache line, but won't break the prefetch pipeline either. Therefore, code that is near in the artifact world will end up near in the run-time world as well.&lt;br /&gt;In the C/C++ family, data that is sequentially declared in a structure (POD) is sequential in memory as well. Therefore, there is a good chance of sharing the same cache line if you keep your structures small.&lt;br /&gt;Conversely, data and code in different components are normally mapped to different pages (in virtual memory systems). They won't share the same cache line (they may &lt;i&gt;compete&lt;/i&gt; for the same cache line, but won't be present in the same line at once). So distant things will be distant.&lt;br /&gt;&lt;br /&gt;Even "recent" advances in processor architecture are increasing the similarity between the artifact and run-time class of distance. Consider &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.154.7435" target="_blank"&gt;predicated execution&lt;/a&gt;: it's commonly used to remove branches at machine-level for short sequence of statements in if/else conditionals (see Fig. 1 in the linked paper). In terms of distance, it allows nearby code in the artifact space to stay close in the run-time space, by eliminating branches and therefore maximizing proximity in the execution pipeline.&lt;br /&gt;&lt;br /&gt;Some transformations, however, are not distance-preserving. Inlining of code (think of C++ inline functions, for instance) will &lt;i&gt;shrink&lt;/i&gt; distance while moving from the artifact world to the run-time world. &lt;br /&gt;Aspect Oriented Programming is particularly interesting from the point of view of distance. On the artifact side, aspects allow to isolate cross-cutting concerns. Therefore, they allow to increase distance between the advice, that is factored out, and the join points. A non-distance-preserving transformation (weaving) brings the two concepts back together as we move toward execution. &lt;br /&gt;&lt;br /&gt;Curiously enough, some non-preserving transformations work in the opposite way: they allow things to be near in the artifact space, yet be distant in the run-time world. Consider the numerous technologies (dating back to remote procedure calls) that allow you to code as if you were invoking a local function, or a method of a local object, while in fact you are executing a remote function, or a method of a remote object (through some kind of local proxy). This is creating an illusion of short distance (in the artifact world) while in fact maintaining high distance in the run-time world. As usual, whenever we create software over a thin layer of illusion, there is a potential for problems. When you look at &lt;a href="http://www.rgoarchitects.com/Files/fallacies.pdf" target="_blank"&gt;The 8 fallacies of distributed computing &lt;/a&gt;, you can immediately recognize that dealing with remote objects as if they were local objects can be rather dangerous. Said otherwise, the illusion of short distance is a &lt;a href="http://www.carlopescio.com/2007/01/leaky-abstractions-and-tacit.html "&gt;leaky abstraction&lt;/a&gt;. More on distributed computing when I'll get to the concept of friction.&lt;br /&gt;&lt;br /&gt;A closing remark: in my previous post, I said that gravity (in the artifact world) tends to increase performance (a run-time property). We can now understand that better, and say that it is largely (not entirely) because:&lt;br /&gt;- the most common transformations are distance-preserving.&lt;br /&gt;- performance increases as the run-time distance decreases.&lt;br /&gt;Again, &lt;i&gt;friction&lt;/i&gt; is also at play here, but I have yet to introduce the concept.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Addenda on the artifact side&lt;/b&gt;&lt;br /&gt;Some concepts on the artifact side are meant to give the illusion of a shorter distance, while maintaining separation. Consider &lt;a href="http://msdn.microsoft.com/en-us/library/bb308966.aspx#csharp3.0overview_topic3" target="_blank"&gt;extension methods&lt;/a&gt; in .NET or the more powerful concept of &lt;a href="http://en.wikibooks.org/wiki/Objective-C_Programming/in_depth#Categories" target="_blank"&gt;category&lt;/a&gt; in objective C. They both give the illusion of being very close to a class (when you use them) while in fact they are just as distant as any other class. (By the way: I've been playing with extension methods [in C#] as a way to get something like partial specialization in C++; it kinda works, but not inside generics, which is exactly were I would need it).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Distance in the Decision Space&lt;/b&gt;&lt;br /&gt;While thinking about distance in the artifact and in the run-time world, I realized that the &lt;a href="http://www.carlopescio.com/2009/01/notes-on-software-design-chapter-3-mass.html "&gt;very first&lt;/a&gt; notion of distance I introduced  was in the decision space. Still, I haven't defined that notion at the detail level (or lack thereof :-) at which I've defined distance in the artifact and run-time world. I have a few ideas, of course, the simplest definition being "the number of decision that must be undone + the number of [irreversible?] decisions that must be taken to move your artifacts". Those decisions would involve some mass of code. Moving that mass for that "space" would give a notion of necessary work. Anyway, it's probably too early to say more, as I have to understand the decision space better. &lt;br /&gt;&lt;br /&gt;Coming soon, I hope, the notion of friction.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-1355984474331843307?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/1355984474331843307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=1355984474331843307' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1355984474331843307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1355984474331843307'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/08/notes-on-software-design-chapter-9.html' title='Notes on Software Design, Chapter 9. A simple property: Distance (part 2)'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-9021914818708117742</id><published>2010-08-05T17:26:00.005+02:00</published><updated>2010-08-05T18:00:30.327+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='book reference'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>Notes on Software Design, Chapter 8. A simple property: Distance (part 1)</title><content type='html'>You're writing a function in your preferred language. At some point, you look at your code and you see that a portion just does not belong there. You move it outside, creating another function. Asked why, you may answer that by doing so you made it reusable; that you want to respect the Single Responsibility Principle; that you want to increase cohesion; that code just looks "cleaner" and "easier to read" that way; and so on. I guess it sounds rather familiar. &lt;br /&gt;&lt;br /&gt;By moving the code outside the function, you also increased its &lt;b&gt;distance&lt;/b&gt; with the code that is left &lt;b&gt;inside&lt;/b&gt;. This is probably not so familiar: distance is not a textbook property of software. However, the notion of distance is extremely important. Fortunately, distance is a very simple concept. It has an immediate intuitive meaning, and although it's still rather informal, we can already use it to articulate some non-trivial reasoning.&lt;br /&gt;&lt;br /&gt;I'm trying to keep this post reasonably short, so I'll cover only the artifact side of the story here. I'll talk about the run-time world next time.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Concept of Distance&lt;/b&gt;&lt;br /&gt;Consider this simple function (it's C#, but that's obviously irrelevant)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int sum( int[] a )&lt;br /&gt;  {&lt;br /&gt;  int s = 0;&lt;br /&gt;&lt;br /&gt;  foreach( int v in a )&lt;br /&gt;    s += v ;&lt;br /&gt;  &lt;br /&gt;  return s;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I used two blank lines to split the function in three smaller portions: initialization - computation - return. I didn't use comments - the code is quite readable as it is, and you know the adage: if you see a comment, make a function. It would be unnatural (and with dubious benefits) to split that function into sub-functions. Still, I wanted to highlight the three tiny yet distinct procedural portions (centers) within that function, so I used empty lines. I guess most of you have done the same at one point or another, perhaps on a larger scale.&lt;br /&gt;&lt;br /&gt;Said otherwise, I wanted to show that some statements were conceptually closer than others. They don't have to be procedural statements. I have seen people "grouping" variable declarations in the same way, to show that some variables sort of "lump together" without creating a structure or a class. I did that by increasing their physical distance in the artifact space.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Measure of Distance&lt;/b&gt;&lt;br /&gt;Given two pieces of information P1, P2, encoded in some artifacts A1, A2, we can define their distance D( P1, P2 ) using an &lt;a href="http://en.wikipedia.org/wiki/Level_of_measurement"  target="_blank"&gt;ordinal scale&lt;/a&gt;, that is, a totally ordered set:&lt;br /&gt;&lt;br /&gt;P1 and P2 appear in the same statement - that's minimum distance&lt;br /&gt;P1 and P2 appear in the same group of consecutive statements &lt;br /&gt;P1 and P2 appear in the same function&lt;br /&gt;… etc&lt;br /&gt;&lt;br /&gt;for the full scale, including the data counterpart, see my &lt;a href="http://www.PhysicsOfSoftware.com/Summary.pdf"&gt;Summary&lt;/a&gt; at the &lt;a href="http://www.PhysicsOfSoftware.com/"&gt;Physics of Software&lt;/a&gt; website.&lt;br /&gt;&lt;br /&gt;Note that Distance is a &lt;b&gt;relative property&lt;/b&gt;. You cannot take a particular piece of information and identify its distance (as you could do, for instance, with mass). You need two. &lt;br /&gt;Also, the ordinal scale is rather limiting: you can do no math with it. It would be nice to turn it into a meaningful interval or ratio scale, but I'm not there yet.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Is Distance useful?&lt;/b&gt;&lt;br /&gt;As in most theories, individual concepts may seem rather moot, but once you have enough concepts you can solve interesting problems or gain better understanding of complex phenomena. Right now, I haven't introduced the concept of tangling yet, so Distance may seem rather moot on itself. Still, we can temporarily use a vague notion of coupling to explore the value of distance. It will get better in the [near] future, trust me :-).&lt;br /&gt;&lt;br /&gt;Consider a few consecutive statements inside a function. It's ok if they share intimate knowledge. The three segments in &lt;i&gt;sum&lt;/i&gt; are rather strongly coupled, to the point that it's ineffective to split them in subfunctions, but that doesn't bother me much. It's fine to be tightly coupled at small distance. As we'll see, it's more than fine: it's expected.&lt;br /&gt;&lt;br /&gt;Functions within a class are still close together, but farther apart. Again, it's ok if they share some knowledge. Ideally, that knowledge is embodied in the class invariant, but private functions are commonly tied with calling functions in a rather strong way. They often assume to be called in specific states (that could be captured in elaborated preconditions), and the caller is responsible to guarantee such preconditions. Sequence of calls are also expected to happen in specific orders, so that preconditions are met. Again, that doesn't bother me much. That's why the class exists in the first place: to provide a place where I can group together "closely related" functions and data.&lt;br /&gt;&lt;br /&gt;Distinct classes are even more distant. Ideally, they won't share much. In practice, classes inside the same component often end up having some acquaintance with each other. For instance, widgets inside a widget library may work well together, but may not work at all with widgets inside a different library. Still, they're distant enough to be used individually.&lt;br /&gt;&lt;br /&gt;We expect components / services to be lightly coupled. They can share some high-level contract, but that should be all.&lt;br /&gt;&lt;br /&gt;Applications shouldn't be coupled at all – any coupling should appear at a lower level (components).&lt;br /&gt;&lt;br /&gt;The logical consequence here is that &lt;b&gt;coupling must decrease as distance increases&lt;/b&gt;. There is more to this statement than is immediately obvious. The real meaning is:&lt;br /&gt;a) large distance requires low coupling&lt;br /&gt;b) small distance requires high coupling&lt;br /&gt;&lt;br /&gt;When I explain the concept, most people immediately think of (a) and ignore (b). Yet (b) is very important, because it says: &lt;br /&gt;1) &lt;i&gt;if coupling with the surroundings is not strong enough, you should move that portion elsewhere&lt;/i&gt;. &lt;br /&gt;2) &lt;i&gt;the code should go where the coupling is stronger&lt;/i&gt; (that is, if code is attracted elsewhere, consider moving it elsewhere :-)). That's basically why &lt;a href='http://books.google.com/books?id=1MsETFPD3I0C&amp;pg=PA80&amp;lpg=PA80&amp;dq="feature+envy"' target="_blank"&gt;feature envy&lt;/a&gt; is considered a bad smell – the code is in the wrong place.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cohesion as an emergent property&lt;/b&gt;&lt;br /&gt;Cohesion has always been a more elusive concept than coupling. Looking at literature, you'll find dozens of different definitions and metrics for cohesion (early works like Myers' Composite/Structured Design used to call it "strength"). I've struggled with the concept for a while, because it didn't fit too well with other parts of my theory, but then I realized that cohesion is not a property &lt;i&gt;per se&lt;/i&gt;. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cohesion is a byproduct of attraction and distance&lt;/b&gt;: an artifact is cohesive if its constituents are at the right distance, considering the forces of attraction and rejection acting upon that artifact. If the resulting attraction is too strong or too weak, parts of that artifact want to move either down or up in the distance hierarchy, or into another site at the same level. &lt;br /&gt;&lt;br /&gt;Attraction is too weak: the forces keeping that code together are not strong enough to warrant the short distance at which we placed the code. For instance, a long function with well-identified segments sharing little data. We can take that sequence of statements and move it up in the hierarchy - forming a new function.&lt;br /&gt;&lt;br /&gt;Attraction is too strong: for instance, we put code in different classes, but those classes are intimately connected. The easier thing is to demote one class to a set of functions (down in the hierarchy) and merge those functions with the other class. But perhaps the entire shape is wrong, at odd with the forcefield. Perhaps new abstractions (centers) must be found, and functions, or even statements, moved into new places.&lt;br /&gt;&lt;br /&gt;This is closing the circle, so to speak. &lt;b&gt;Good software is in a state of equilibrium: attraction and rejection are balanced with proper distance between elements&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Note: I'm talking about attraction and rejection, but I have yet to present most attractive / repulsive forces. Still, somehow I hope most of you can grasp the concepts anyway. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;An Alexandrian look on the notion of distance&lt;/b&gt;&lt;br /&gt;I've quoted Christopher Alexander several time in an early discussion on the concept of form. Now, you may know that Alexander's most recent theory is explained in 4 tomes (which I haven't deeply read yet) collectively known as "The Nature of Order". A few people have tried to relate some of his concepts with the software world, but so far the results have been rather unimpressive (I'm probably biased in my judgment :-).&lt;br /&gt;&lt;br /&gt;On my side, I see a very strong connection between the concept of equilibrium as an interplay between distance and the artifact hierarchy and the Alexandrian concept of levels of scale: “A balanced range of sizes is pleasing and beautiful”. &lt;br /&gt;Which is not to say that you should have long functions, average functions, small functions :-). I would translate that notion in the software world as: &lt;i&gt;a balanced use of the artifact hierarchy is pleasing and beautiful&lt;/i&gt;. That is:&lt;br /&gt;Don't use long function: use multiple functions in a class instead.&lt;br /&gt;Don't use long classes: use multiple classes in a component instead.&lt;br /&gt;Don't create huge components: use multiple components inside an [application/service/program] instead&lt;br /&gt;&lt;br /&gt;This is routinely ignored (which, I think, contributes to the freescale nature of most source code) but it's also the very first reason why those concepts have been introduced in the first place!  Actually, we are probably still missing a few levels in the hierarchy, as required for instance to describe systems of systems. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gravity, efficiency, and the run-time distance&lt;/b&gt;&lt;br /&gt;Remember &lt;a href="http://www.carlopescio.com/2009/01/notes-on-software-design-chapter-3-mass.html"&gt;gravity&lt;/a&gt;? Gravity (in the artifact world) provides a path of least resistance for the programmer: just add stuff where there is other vaguely related related stuff. &lt;b&gt;Gravity works to minimize distance&lt;/b&gt;, but in a kind of piecemeal, &lt;a href="http://en.wikipedia.org/wiki/Maxima_and_minima" target="_blank"&gt;local minimum&lt;/a&gt; way. It's easy to get trapped into local minimum. The minimum is local when we add code that is not tightly connected with the surroundings, so that other forces at play (not yet discussed) will reject it.&lt;br /&gt;&lt;br /&gt;When you point out incoherent, long functions, quite a few programmers bring in "efficiency" as an excuse (the other most common excuse being that it's easier to follow your code when you can just read it sequentially, which is another way to say "I don't understand abstraction" :-).&lt;br /&gt;Now, efficiency is a run-time concept, and I haven't explained the corresponding concept in my theory yet. Still, using again the informal notion of efficiency we all have, we can already see that efficiency [in the run-time world] tends to decrease as distance [in the artifact world] increases. For instance, moving lines into another function requires passing parameters around. This is a first-cut, rough explanation of the well-known trade-off between run-time efficiency and artifact quality (maintainability, readability, reusability). &lt;br /&gt;&lt;br /&gt;Coming soon:&lt;br /&gt;the concept of distance in the run-time world, and distance-preserving transformations&lt;br /&gt;efficiency in the physics of software&lt;br /&gt;tangling&lt;br /&gt;not sure yet : ), but probably isolation and density&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-9021914818708117742?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/9021914818708117742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=9021914818708117742' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/9021914818708117742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/9021914818708117742'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/08/notes-on-software-design-chapter-8.html' title='Notes on Software Design, Chapter 8. A simple property: Distance (part 1)'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4762831823730979137</id><published>2010-07-27T09:50:00.003+02:00</published><updated>2010-07-27T14:39:17.440+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>On Kent Beck's Responsive Design</title><content type='html'>I try to keep an eye on software design literature. I subscribe to relevant publications from IEEE and ACM; I get a copy of conference proceedings; I read blogs and, just like everybody else, I follow links and suggestions. Being aware of the potential risk of filtering out information that is not aligned with the way I think, I'm also following a few blogs that are definitely not aligned with my belief system, just to make sure I don't miss too much. I'm bound to miss something, anyway, but I can live with that :-).&lt;br /&gt;&lt;br /&gt;A few weeks ago I realized that I wasn't following &lt;a href="http://www.threeriversinstitute.org/blog/" target="_blank"&gt;Kent Beck's blog&lt;/a&gt;. I don't know why: I'm not a fan of XP, but I'm rather fond of Kent. He's an experienced designer with many good ideas. So, I took a tour of his posts and discovered that I had completely missed the concept of Responsive Design. That's weird, because I'm reading/scanning quite a few agile-oriented blogs, and I've never seen any mention of it. Oh, well; time to catch up.&lt;br /&gt;&lt;br /&gt;I did my homework and spent some time reading all posts in the &lt;a href="http://www.threeriversinstitute.org/blog/?cat=6" target="_blank"&gt;Responsive Design category&lt;/a&gt; and watching Kent's interesting &lt;a href="http://www.infoq.com/presentations/responsive-design" target="_blank"&gt;QCon presentation&lt;/a&gt;. Looking at blog dates, it seems like activity peaked in April 2009, but rapidly declined during 2009 to almost nothing in 2010. So, apparently, Responsive Design hasn't taken the world by storm yet. Well, design wasn't so popular in the pre-agile era, and it's not going to be popular in the post-agile era either :-).&lt;br /&gt;&lt;br /&gt;Anyway, the presentation inspired me with a stream of reflections that I'd like to share with you guys. I would recommend that you watch the presentation first (I know, it takes about 1 hour, but I think it's worth it). What follows is not intended to be a critic. I'm mostly trying to relate Kent's perspective on "what software design is about" with mine. It's a rather long post, so I split it in three paragraphs. The first two are about concepts in the presentation itself. The third is about an interesting difference in perspective, and how it affects our thinking.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Reflections on the introductory part&lt;/b&gt;&lt;br /&gt;The idea of taking notes as we design, to uncover our own strategies and tactics, sounded &lt;b&gt;so&lt;/b&gt; &lt;a href="http://www.carlopescio.com/2008/11/tale-of-two-methods.html"&gt;familiar&lt;/a&gt;. I guess at some point some of us feel an urge to understand what we're &lt;b&gt;really&lt;/b&gt; doing. Although I'm looking for something different from Kent, I share some of his worries: trivial or extremely complicated insights might be just around the corner :-)&lt;br /&gt;&lt;br /&gt;The talk about the meaning of "responsive" around 0:13 is resonating very well with the concepts of forcefield, design as "shaping a material", and backtalk. From my perspective, Kent is mostly saying: am I going to look at the forcefield, and design accordingly, or am I going to force a preconceived set of design decisions upon the problem? (see also my &lt;a href="http://www.carlopescio.com/2009/07/when-in-doubt-do-right.html"&gt;empty cup&lt;/a&gt; post). &lt;br /&gt;&lt;br /&gt;Steady flow of features. We all love that, of course, and in a sense it's the most agile, XP-ish concept in the entire talk. The part about "the right time to design" seems rather connected with the Least Responsible Moment, so I can't really spare you a link to my own little idea of &lt;a href="http://www.carlopescio.com/2010/01/delaying-decisions.html"&gt;Invariant Decisions&lt;/a&gt;.&lt;br /&gt;Again, I have a feeling that there is never enough context when talking about timing. I've certainly designed systems with a large separation (in time) between design and implementation. In many cases, it worked out quite well (of course, we always considered design as something fluid, not cast in stone). I guess it has a lot to do with how much domain knowledge you can leverage. Not every project is about doing something nobody has done before. Many are "just" about doing something  in a much better way. Context, context, context...&lt;br /&gt;&lt;br /&gt;Starting with values: it's something I have to improve in my &lt;a href="http://www.physicsofsoftware.com"&gt;Physics of Software&lt;/a&gt; work. Although I've said several times that all new methods should start with a declaration of values and beliefs, so far I haven't been thorough on this side. For instance, I value honest, unbiased, free, creative communication and thinking about software design issues, where the best ideas, and not the best talkers, get to win (just because I'm a good talker doesn't mean I want to win that way :-)). That's why I'm trying to come up with a less ambiguous, wishy-washy way to think and talk about design.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Most of the decisions I make while designing have nothing to do with the problem domain [… but ...] are shaped by the fact that I'm instructing a computer&lt;/i&gt;. Weird. This is not my experience. I surely reuse solutions across domains, but the problem domain is heavily shaping the forcefield. When you go down to small-scale decisions, yeah, it gets more domain-independent, but high-level design is heavily problem-dependent. For instance, while you can usually (but not always) implement a chosen data structure in a rather domain-independent way, choosing the right data structure is usually a domain-dependent choice. &lt;br /&gt;Don't get me wrong: I know I can safely ignore some portions of the problem domain when I design - I do that all the time. My view is that I can ignore the (possibly very complex) functional issues that have little impact on the forcefield, and therefore on the form. This is a complex subject that would require an in-depth study.&lt;br /&gt;&lt;br /&gt;Principles. I don't quite like the term "principle" because is so wide in meaning that you can use it for just about everything. So, while the "don't repeat yourself" is a commonly accepted design principle, Kent's examples of principles from the insurance world or from Dynamo looks much more like &lt;b&gt;pre-made [meta] decisions&lt;/b&gt; to me. &lt;br /&gt;&lt;i&gt;"You should never to lose a write"&lt;/i&gt;. Fine. It's a decision, you can basically consider that a requirement. &lt;br /&gt;&lt;i&gt;"We're there to aid human decision making"&lt;/i&gt;. Fine. It's a meta-decision, meaning, it's not just a design decision: it will influence everything, from your value proposition down to functional requirements and so on. It's not really a design principle, not even a project-specific design principle: it's more akin to a metaphor or to a goal.&lt;br /&gt;Aside from that distinction, I agree that sometimes constraints, whatever form they take, are actually &lt;i&gt;helpful&lt;/i&gt; during design, because they prune out a lot of the decision space (again, see my post above on the empty cup). Of course, the wrong constraints can prevent you from finding the sweet spot, so timing is an issue here as well - some constraints should be considered fluid early on, because you may learn that they're not the right constraints for your project.&lt;br /&gt;&lt;br /&gt;The short part about patterns and principles reminded me of my early work on SysOOD, some of which got published in IEEE Software exactly as &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/sysdes.html"&gt;Principles Vs. Patterns&lt;/a&gt;. So, while Kent wants to understand principles better, I've always been trying to eliminate principles altogether (universal principles, that is). Still, I'd like to see the "non-universal" or "project-specific" principles recast under some other name and further explored, because I agree that having a shared set of values / goals / constraints can help &lt;i&gt;tremendously&lt;/i&gt; in any significant project. Oh, I still have the Byte smalltalk balloon issue somewhere : ).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Reflection on the 4 strategies&lt;/b&gt;&lt;br /&gt;I see the "meat" of the talk as being about [meta] strategies to &lt;b&gt;move in the decision space&lt;/b&gt;. Your software is at some point A in the multi-dimensional decision space; for instance, you decided early on that you would use filenames and not streams. Now you want to move your software to another point B in the decision space (where, for instance, streams are used instead of filenames). How do you go from A to B? &lt;br /&gt;That's an interesting issue, where experienced designers/programmers routinely adopt different approaches compared to novices (see the empty cup post again), so it's both interesting and promising to see Kent articulate his reasoning. In a sense, it's completely orthogonal to both patterns/antipatterns (which may point you to B / away from A) and to my work (which is more concerned with understanding and articulating why B is a more desirable point than A, or to find B in the first place). &lt;br /&gt;Actually, strictly speaking I'm not even sure this stuff is really about "design". In my view, design is more about finding B. The execution/implementation of design, however, is about moving to B. Therefore, Kent's strategies looks more like "design execution strategies" than "design strategies".&lt;br /&gt;&lt;br /&gt;That said, there is a subtle, yet striking difference between Kent's perspective and mine. Kent is talking about / looking to software design in a "first-person perspective", while I'm looking through the "I'm shaping a material" metaphor. He says things like: "I'm here; how do I get there?", and he's literally mimicking small steps. I'm saying things like: "my software is here; how do I move it there?"; it may seem like a small, irrelevant distinction, but I think it's shaping our thoughts rather deeply. It surely shapes the names we use: I would have never used "stepping stone", because I'm not thinking of myself going anywhere : ). More on this on the third paragraph below.&lt;br /&gt;&lt;br /&gt;Although this is probably the most “practical” part of the talk, concepts are a little fuzzy. Leap can be seen as a strategy, actually the simplest strategy of all: you just move there. Safe Steps is more like a meta-strategy to move inside the decision space (indeed, around 42:00 Kent talks about Safe/Small Steps as a "principle"). Once you choose Safe Steps, you have many options left, Parallel, Stepping Stones and Simplifications being 3 of them. Still, the granularity of those strategies is so coarse that it's rather surprising Kent found only 3 of them. &lt;br /&gt;&lt;br /&gt;For instance, I probably wouldn't have used Parallel to deal with the filenames/streams issues. I can't really say without looking at the code, but assuming I wanted to take small steps, I could have created a new class, which IS-A stream and HAS-A filename, moved the existing code to use that class (a very simple and safe change, because both the stream and the filename are there), gradually moved all the filename-dependent code inside that class, removed the filename from the interface (as it's no longer used), moved the filename-dependent code in a factory (so that I could make a choice on the stream type). At that point I could have killed the temporary class, using a plain stream again. This strategy (I could call it wrap/extract/unwrap) is quite simple and effective when dealing with legacy code, and doesn't really fit in any of the strategies Kent is proposing. &lt;br /&gt;&lt;br /&gt;Stepping Stone. While Leap and Parallel are more like strategies to &lt;b&gt;implement&lt;/b&gt; a decision you have already taken, it seems to me that Stepping Stone is different. Although this might be my biased understanding of it, it's also the only interpretation I can give that makes Stepping Stone different from good old top-down decomposition (which Kent makes clear is different, at about 50:30).&lt;br /&gt;I would say that Stepping Stone is about making progress where you can, and while doing so, shed some light on the surroundings as well. This is not very clear in the beginning, but as Kent moves forward, it's more and more obvious that he's thinking about novel situations, where you don't know exactly what you want to build.&lt;br /&gt;Indeed, sometimes the forcefield is just too blurry. Still, we often can see a portion of it rather clearly, and we may have a sensible idea about the form we want to shape &lt;b&gt;locally&lt;/b&gt;. Stepping Stone is a good strategy here: build (or design) what you understand, get feedback (or backtalk), get progress, etc. I usually keep exploring the dark areas while I'm building stepping stones. I'm also rather careful not to overcommit on stepping stones, as they may turn out not to fit perfectly with what's coming next. That's fine, inasmuch as we understand that design is a process, not a phase with a beginning and an end. &lt;br /&gt;I can also build "stepping stones" when I know where I'm going to, but as I said, at that point it's hard to tell the difference between building stepping stones and executing top-down design. Oh, by the way, for the agile guys who hated me so much for saying that TDD is a limited design strategy: move around 50:20. Play. Rewind. Play again. Repeat till necessary :-). But back to Stepping Stones: I think the key phrase here is around 55:40, when Kent says that by standing on a stepping stone he can see where to go next, which I read like: a previously blurry portion of the forcefield is now visible and clear, and I can move further.&lt;br /&gt;&lt;br /&gt;Simplification. This is more akin to a design strategy, not to an execution strategy. I could see Simplification as a way to create small steps (perhaps even stepping stones). Indeed, the difference between Stepping Stones and Simplification is not really obvious (around 1:02:00 a participant asks about the similarity and doesn't seem like Kent can explain the difference so well either). I guess simplification is about to solve one single problem by solving a simpler version of the same problem first, whereas Stepping Stones are about solving a complex problem by solving &lt;b&gt;another&lt;/b&gt; problem first (one that, however, brings us closer to solving the initial problem). In this sense, Simplification can be used where you can see where you wanna go (but it's too big / risky / ambitious) but also where you can't see exactly where you want to go, but you can clearly see a smaller version of it. Or, from my "I'm shaping a material" perspective, you can't really see the form of the real thing, but you can see the form of a smaller version of it. As I said, this stuff is interesting but rather fuzzy, and honestly, I'm not really sold on those 4 strategies.&lt;br /&gt;&lt;br /&gt;Overall, I'd like to see Responsive Design further developed. It would probably benefit from a better distinction between design, design execution, principles, values, goals, and so on, but it's interesting stuff in the almost flat landscape of contemporary software design literature.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Perspective Matters&lt;/b&gt;&lt;br /&gt;As I said, Kent is looking at the decision space in first-person perspective, while I see myself moving other things around. There is an interesting implication: when you think about moving yourself, you mostly consider distance. You are who you are. You want to go elsewhere. Distance, and therefore Leaps, Small Steps, Stepping Stones, it's all that matters.&lt;br /&gt;&lt;br /&gt;When you think about moving something else, you have to consider two more factors. That, in my opinion, allows better reasoning.&lt;br /&gt;&lt;br /&gt;Sure, distance is an important factor. But, as I explained in my post about &lt;a href="http://www.carlopescio.com/2009/01/notes-on-software-design-chapter-3-mass.html"&gt;Inertia&lt;/a&gt;, another important factor is Mass. You cannot ignore mass, but it's unnatural to consider a varying mass from a first-person perspective.&lt;br /&gt;&lt;br /&gt;A simple example: I use Visual Studio (yeah yeah I know, some of you don't like it : ). Sometimes, as I'm creating a new project, I click in the wrong place (yeah yeah I'm kinda dumb :-) and I get the wrong project type. I want a C# project and I get a VB.NET project (yikes!! :-)). That's quite a distance in the decision space. Yet there is a very simple, safe step (Leap): delete the project and start from scratch. The distance is not a problem, because mass is basically null. I can use Leap not because the distance is small, but because the mass is small. I wouldn't do that with an existing, large project (I may consider going through an IL -&gt; C# transformation though :-).&lt;br /&gt;&lt;br /&gt;There is more: when I discussed Inertia, I talked about software being in a state of rest or &lt;b&gt;motion&lt;/b&gt; in the decision space. This is the third factor, and again, it's hard to think about it in first-person perspective. You want to go somewhere, but you're already going elsewhere. It's not truly natural. Deflecting a moving object, however, is quite ordinary (most real-life games involving a ball, for instance, involve deflecting a moving object).&lt;br /&gt;&lt;br /&gt;Consider a large project. Maybe a team is busy moving a subsystem S1 to another place in the decision space. Now you want to move subsystem S2 from A to B. It's not enough to consider distance and mass. You have to consider whether or not S2 is already moving, perhaps by attraction from S1. So S2 may be small (in mass) and the distance A-B may be small too, but if S2 is already moving into a different direction your job is harder, more risky, and in need of a careful execution strategy.&lt;br /&gt;&lt;br /&gt;A real-world example: you have a legacy C++/MFC application. Currently, the UI is talking with the application through a small, homebrew messaging component (MC), of which you are in charge. You just found a better messaging component (BMC) on the internet, say something that is more efficient, portable, and actively developed by a community. You want to move your subsystem to another place in the decision space, from MC to BMC. Part of BMC being "portable" is based on the reasonable assumption that messages are strictly C++ objects. &lt;br /&gt;&lt;br /&gt;Meanwhile, another team is moving the UI toward .NET (that's a big mass - big distance issue, but it's their problem, not yours :-). Now, there is an attraction between your messaging component and the UI. A .NET UI may have some issues dealing with native C++ messages. So, like it or not, there is another force at play, trying to move your component to a different place (say, NMC). Now, the mass of the messaging component might be small. The distance between MC and BMC may be small too - perhaps something you can deal with by using an adapter. But probably BMC is in a very different direction than NMC, where the UI team is pushing your component to move. So it's not just a matter of distance. It's not even enough to consider mass. You need to consider distance + full-blown Inertia. Or, to cut it short, &lt;a href="http://en.wikipedia.org/wiki/Work_(physics)" target="_blank"&gt;work&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Of course, depending on your project, some factor may dominate over the others, and a simpler model might be enough, but usually, distance alone won't cut it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;There is more...&lt;/b&gt;&lt;br /&gt;At the end of the presentation, Kent mentions power law distribution. This is something that has got me interested too in the past few months (I mentioned that in Facebook), but it's too early to say something about it, and I want to check a few ideas with the author of an interesting paper first, anyway.&lt;br /&gt;&lt;br /&gt;See you guys soon with a post on Distance (not in the decision space, but in the artifact space!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4762831823730979137?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4762831823730979137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4762831823730979137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4762831823730979137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4762831823730979137'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/07/on-kent-becks-responsive-design.html' title='On Kent Beck&apos;s Responsive Design'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4876028338778496741</id><published>2010-07-22T18:02:00.002+02:00</published><updated>2010-07-22T18:12:30.965+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: nuovi capitoli</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; Il lavoro procede: ho integrato nella versione &lt;a href="http://sites.google.com/site/cppstile/home/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; del libro (in PDF) il capitolo 9 e la bibliografia (a cui ho aggiunto un paio di voci). Siamo quasi al 70% del testo (oltre, se consideriamo la bibliografia, che non ho sottoposto a revisione in quanto non modificata dall'editore).&lt;br /&gt;Gli aggiornamenti bibliografici sono il risultato di alcune integrazioni / correzioni al testo, che sta ricominciando a "vivere" :-).&lt;br /&gt;&lt;br /&gt;Per chi vuole collaborare: e' iniziata la revisione del capitolo 10. Tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt; del mio sito, incluse le informazioni per unirsi al gruppo di lavoro. Al solito, vi invito a diffondere l'iniziativa via blog, tweet, facebook, forum e quant'altro...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4876028338778496741?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4876028338778496741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4876028338778496741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4876028338778496741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4876028338778496741'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/07/c-manuale-di-stile-nuovi-capitoli.html' title='C++ Manuale di Stile: nuovi capitoli'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-6081602336835022764</id><published>2010-07-19T15:53:00.003+02:00</published><updated>2010-07-19T16:12:49.951+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>A Physics of Software</title><content type='html'>I wanted a catchy name :-) for all the stuff I'm writing on software design and the nature of software, so I came up with the idea of "A Physics of Software". Lo and behold! I registered &lt;a href="http://www.PhysicsOfSoftware.com"&gt;www.PhysicsOfSoftware.com&lt;/a&gt; (right now, it will just redirect to a page hosted in my eptacom.net website).&lt;br /&gt;&lt;br /&gt;That wouldn't be really interesting, except that I took some time to create a short presentation-style summary of the main (stable) concepts, together with a few hyperlinks to blog posts and papers. I'll keep the summary updated as I present new concepts and I see them grow into a "mature" state.&lt;br /&gt;&lt;br /&gt;The summary / page is also a more structured place to consolidate ideas. For instance, I'll soon be talking about the concept of Distance here, but I've already consolidated my current understanding of the Artifact/Run-Time space hierarchies in the summary paper. So I see the blog posts and the PhysicsOfSoftware web page as mutually supporting each other. Therefore, even if you're already familiar with my work, it may be worth a look.&lt;br /&gt;&lt;br /&gt;I've spent quite some time recently pondering on this stuff, so my post on Distance is almost ready. However, I also have a half-baked post on Responsive Design, and I don't know yet which is gonna be first.&lt;br /&gt;&lt;br /&gt;Anyway, see you soon guys :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-6081602336835022764?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/6081602336835022764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=6081602336835022764' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6081602336835022764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6081602336835022764'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/07/physics-of-software.html' title='A Physics of Software'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-6329629193893771163</id><published>2010-06-29T11:56:00.002+02:00</published><updated>2010-06-29T12:14:14.154+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: nuovi capitoli</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; Finalmente, arrivate le revisioni e completato un merge un po' faticoso :-), ho potuto integrare i capitoli dal 3 al 6 nella versione &lt;a href="http://sites.google.com/site/cppstile/home/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; del libro (in PDF). Siamo a buon punto, i capitoli in PDF vanno dal 3 all'8, abbiamo superato la meta' del guado. Ho anche apportato alcune modifiche ed integrazioni al testo, un primo piccolo passo verso la revisione dei contenuti.&lt;br /&gt;&lt;br /&gt;Per chi vuole collaborare: stiamo lavorando alla revisione del capitolo 9. Tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt; del mio sito, incluse le informazioni per unirsi al gruppo di lavoro. Al solito, vi invito a diffondere l'iniziativa via blog, tweet, facebook, forum e quant'altro...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-6329629193893771163?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/6329629193893771163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=6329629193893771163' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6329629193893771163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6329629193893771163'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/c-manuale-di-stile-nuovi-capitoli.html' title='C++ Manuale di Stile: nuovi capitoli'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8855081168363759813</id><published>2010-06-24T15:17:00.003+02:00</published><updated>2010-06-24T16:11:55.689+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Notes on Software Design, Chapter 7: a better Forcefield Diagram</title><content type='html'>In my previous post in the NOSD series, I mentioned how an improved &lt;a href="http://www.carlopescio.com/2009/10/forcefield-diagram.html"&gt;forcefield diagram&lt;/a&gt; was needed to model the kind of reasoning I'm trying to bring in software design. I also discussed the artifact-run/time dualism, and how many concepts in language design were born out of the fundamental need to balance conflicting forces between these two worlds. I also mentioned the role of some patterns in resolving the same kind of conflict.&lt;br /&gt;&lt;br /&gt;Here I'll show you a practical example, introducing the improved forcefield notation as we go. It's quite simple, and as usual, the reasoning is more important than the drawing. I'll use new colors and shapes, but it's all very informal, the notation is not cast in stone, and it will probably evolve and change over time.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A common problem&lt;/b&gt;&lt;br /&gt;You have two classes (Class1, Class2); as we learnt in Chapter 6, that usually means you have two &lt;b&gt;artifacts&lt;/b&gt;, and right now I feel like blue is a good color for artifacts, so I'll color them in blue. &lt;br /&gt;&lt;br /&gt;Now, those classes have some commonality in behavior; for instance, they both represent a geometrical object, and can provide you with a bounding box.&lt;br /&gt;Behavior is a &lt;b&gt;run-time&lt;/b&gt; concept, and I'll color that information in pink.&lt;br /&gt;&lt;br /&gt;Commonality in behavior is an attractive force; I haven't talked about this yet, but trust me : ), or just rely on your intuition that "things that do similar things are close to each other".&lt;br /&gt;&lt;br /&gt;Commonality in behavior also attracts a natural desire in the artifact space: polymorphic/uniform access to such behavior. While writing calling code, I'd like to ask for a bounding box in the same way, perhaps polymorphically through a base class / interface. That would make my client (partially) unaware of the specific classes.&lt;br /&gt;&lt;br /&gt;Unfortunately, Class1 and Class2 have been written with different conventions. They don't share a base class; they don't use the same naming for functions; they may not even use the same types for parameters. Different conventions are an artifact issue, so I'll color this in blue again. Of course, different conventions are keeping Class1 and Class2 apart, and actively rejecting polymorphic / uniform access. So here is the forcefield, representing our problem:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/bff1.png" alt=""/&gt;&lt;br /&gt;&lt;br /&gt;Note that there is nothing here about a solution. At this stage, the forcefield is a representation of the problem. Still, we have a conflict between forces, and somehow we have to deal with it. What if we don't? I'll keep that as last.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Enter decisions&lt;/b&gt;&lt;br /&gt;A missing concept in my previous attempts at modeling the forcefield was the very important notion of decision. Although I'm trying to keep concepts to a bare minimum, the Decision Space is an important piece of the puzzle, and there can't be a Decision Space without Decisions. I'm using a yellow hexagon to represent a decision.&lt;br /&gt;&lt;br /&gt;So, how can we deal with those conflicting forces? A simple, technically sound decision is to refactor Class1 and Class2 to a common base class (or interface, or a hierarchy of both). That decision has a strong impact on "Different Conventions", effectively removing it from the forcefield, including the rejection lines. I think the diagram speaks for itself:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/bff2.png" alt=""/&gt;&lt;br /&gt;&lt;br /&gt;So, decisions can &lt;i&gt;alter&lt;/i&gt; the forcefield, for better or worse. Still, we may choose to keep the artifacts unchanged. Perhaps Class1 and Class2 come from third-party libraries, or perhaps they're shared with a lot of existing code, and refactoring may impact that code as well (remember &lt;a href="http://www.carlopescio.com/2009/01/notes-on-software-design-chapter-3-mass.html"&gt;Mass and Inertia&lt;/a&gt;). Again, it's useful to represent this decision explicitly, although it's just an intermediate step. I colored "Different Conventions" in green to say that we deliberately decided to keep it inside the forcefield.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/bff3.png" alt=""/&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Patterns&lt;/b&gt;&lt;br /&gt;Design patterns are now mainstream, with dozens of books and hundreds, if not thousands, of papers describing the problem / context / solution triad.&lt;br /&gt;Now, the solution is usually represented using a UML diagram and/or some source code. Problem and context are described using text, or an &lt;i&gt;example&lt;/i&gt; in UML/code. That's because we don't (didn't :-) have any proper way to describe a problem (forcefield) and context (mostly, pre-made decisions).&lt;br /&gt;Still, look at the picture above once again: that's (of course :-) the problem/context setting for a well-known pattern: &lt;a href="http://en.wikipedia.org/wiki/Adapter_pattern" target="_blank"&gt;adapter&lt;/a&gt;. So let's look at the adapter in action, or how using adapter will impact the forcefield:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/bff4.png" alt=""/&gt;&lt;br /&gt;&lt;br /&gt;Adapter "simply" breaks the rejection between Different Conventions and Polymorphic / Uniform Access, therefore allowing client code to ignore the specific interface of Class1 and Class2. It is very interesting to observe what the forcefield is telling us: we didn't completely remove conflict. There is still an attraction/rejection between Class1 and Class2. In this sense, Adapter is less effective than refactoring (which, however, requires us to change the artifacts).&lt;br /&gt;That conflict will emerge over time; for instance, adding common functionality will take more time, possibly some duplication of code, etc. This kind of "consequence" is not very well documented in the GoF book.&lt;br /&gt;&lt;br /&gt;Note: there is no redundancy with code here: we're talking about the problem space and the decision space. Contrast this with the usual redundancy between a UML diagram and code (with pros and cons, as usual). Also, isn't this diagram much better at communicating design problems, decisions, and impact than the largely ignored &lt;a href="http://www.carlopescio.com/2009/06/design-rationale.html"&gt;design rationale&lt;/a&gt; tools and notations?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What else?&lt;/b&gt;&lt;br /&gt;There is also a different decision we can make; it's a particularly bad decision, therefore it's also very popular :-) wherever code quality is easily ignored. We can just forgo uniform access, and have clients deal with a non-uniform interface (through if, switch/case, whatever). This is what I meant by "not dealing with conflict" earlier. I called that decision "Tangled Clients" for reasons that will become clear in a future post.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/bff5.png" alt=""/&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Time out&lt;/b&gt;&lt;br /&gt;Last time I said I would provide some examples of conflicting forces in the non-software world. I'll have to cut this post short, because the forcefield diagram I've come up with would take too much to explain. But I'll offer a few pointers for those of you with some time to spare:&lt;br /&gt;&lt;br /&gt;- Very simple: the adapter is extremely frequent in the real world as well, as the well-known socket adapter. The forcefield is remarkably similar, but finding the exact translation of every concept is not necessarily trivial. Try this out :-).&lt;br /&gt;&lt;br /&gt;- Harder, some engineering knowledge is required. Rotating pumps may leak (why? hint: some empty space is needed if you want something to rotate freely :-). Old pumps just used a seal, which wasn't really good at preventing leaks. At some point (I think around 1940) the &lt;a href="http://en.wikipedia.org/wiki/End_face_mechanical_seal" target="_blank"&gt;end face mechanical seal&lt;/a&gt; has been adopted as a better seal for rotating pumps. However, the fluid can still leak, which ain't that good in a number of cases. An interesting solution here is the magnetic drive pump (look it up, guys :-). Draw the forcefield for the problem, and represent how using a magnetic field to transmit movement can compensate otherwise conflicting forces. By the way, this is the example I was thinking about when I wrote my previous post.&lt;br /&gt;&lt;br /&gt;- Manufacturing is actually full of great examples of conflicting forces and different approaches to compensate or overcome conflict. Think about thermal grease, just to give a starting point. The list is endless. Trying to model some forcefield in detail is a fascinating exercise.&lt;br /&gt;&lt;br /&gt;- If you want to stay on the software side, here is an interesting one. Take some programming language feature (for instance, if you use .NET, you may consider partial classes or attributes; if you use Java, annotations) and identify which tension between the run-time world and the artifact world they're meant to solve. Partial classes are a simple, but interesting exercise: most criticism I've heard about them is stemming from a very partial :-) understanding of the surrounding forcefield, just like the common abuse I've seen (split a large class in two files :-)).&lt;br /&gt;&lt;br /&gt;As usual, there is much more to say about compensating forces, the artifact/run-time dual nature of software, and so on, including an unexpected intuition on economy of scale that I got just yesterday while running. See you soon, and drop me a line if you try this stuff out :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8855081168363759813?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8855081168363759813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8855081168363759813' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8855081168363759813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8855081168363759813'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/notes-on-software-design-chapter-7.html' title='Notes on Software Design, Chapter 7: a better Forcefield Diagram'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7820558269999751210</id><published>2010-06-22T16:57:00.003+02:00</published><updated>2010-06-22T17:40:33.103+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='requirements'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>"New" version of SmartFP paper online</title><content type='html'>While tidying up a few notes, I realized I've had a newer version of the SmartFP paper (&lt;a href="http://www.eptacom.net/smartfp/SmartFP.pdf"&gt;SmartFP: Function Points as a Decision Tree&lt;/a&gt;) sitting on my hard disk for a couple of years :-).&lt;br /&gt;It's just a small change from previous version: I added a short case study, inspired from a widely used book on function points. Still, if you're interested in FP/FPA, it may be worth reading.&lt;br /&gt;I also have a funny story about this paper not getting published, but I'll save it for another time (got too much still to do today...)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7820558269999751210?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7820558269999751210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7820558269999751210' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7820558269999751210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7820558269999751210'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/new-version-of-smartfp-paper-online.html' title='&quot;New&quot; version of SmartFP paper online'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7219928404955305240</id><published>2010-06-22T15:20:00.002+02:00</published><updated>2010-06-22T15:22:56.229+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: nuovo capitolo in PDF</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; Il progetto di ricostruzione del testo originale prosegue. La versione &lt;a href="http://sites.google.com/site/cppstile/home/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; del testo (in PDF) ora include i capitoli 7 e 8. A breve spero di poter integrare i capitoli 3-6.&lt;br /&gt;&lt;br /&gt;Da oggi e' disponibile per chi vuole collaborare alla revisione il capitolo 9. Tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt; del mio sito, incluse le informazioni per unirsi al gruppo di lavoro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7219928404955305240?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7219928404955305240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7219928404955305240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7219928404955305240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7219928404955305240'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/c-manuale-di-stile-nuovo-capitolo-in.html' title='C++ Manuale di Stile: nuovo capitolo in PDF'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7341446115307471693</id><published>2010-06-20T10:20:00.003+02:00</published><updated>2010-06-20T10:23:11.042+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><title type='text'>Cloud</title><content type='html'>&lt;img src="http://www.eptacom.net/blog/Cloud20100620.png" alt=""&gt;&lt;br /&gt;&lt;br /&gt;A word cloud of the current atom feed, courtesy of &lt;a href="http://www.wordle.net/" target="_blank"&gt;Wordle&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7341446115307471693?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7341446115307471693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7341446115307471693' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7341446115307471693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7341446115307471693'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/cloud.html' title='Cloud'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-245393190403662474</id><published>2010-06-19T21:44:00.000+02:00</published><updated>2010-06-19T21:45:16.793+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quote'/><title type='text'>Quote of the Day</title><content type='html'>&lt;i&gt;the universe begins to look more like a giant thought than a great machine&lt;/i&gt;&lt;br /&gt;Sir James Jeans&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-245393190403662474?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/245393190403662474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=245393190403662474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/245393190403662474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/245393190403662474'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/quote-of-day.html' title='Quote of the Day'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-9197573983327123978</id><published>2010-06-16T16:03:00.002+02:00</published><updated>2010-06-16T16:08:12.045+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: primo capitolo in PDF</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt; Il progetto di ricostruzione del testo originale avanza, anche se un po' a rilento. La versione &lt;a href="http://sites.google.com/site/cppstile/home/CppManualeDiStile_Reloaded.pdf" target="_blank"&gt;Reloaded&lt;/a&gt; del testo, attualmente con il solo capitolo 7, e' ora disponibile in PDF.&lt;br /&gt;&lt;br /&gt;Tutti i dettagli sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile" target="_blank"&gt;pagina dedicata&lt;/a&gt;, incluse le informazioni per unirsi al gruppo di lavoro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-9197573983327123978?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/9197573983327123978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=9197573983327123978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/9197573983327123978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/9197573983327123978'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/c-manuale-di-stile-primo-capitolo-in.html' title='C++ Manuale di Stile: primo capitolo in PDF'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8568037375587037725</id><published>2010-06-06T21:39:00.003+02:00</published><updated>2010-06-06T21:58:50.978+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>Notes on Software Design, Chapter 6: Balancing two Worlds</title><content type='html'>Back in my time, computer science students were introduced to the distinction between syntax and semantics from day one. That distinction is central in understanding programming languages from the algebraic perspective.&lt;br /&gt;&lt;br /&gt;When you are looking for a theory of software forces, however, you'll find another distinction more useful. &lt;b&gt;We have artifacts, and we have run-time instances of artifacts&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Software is encoded knowledge, and as software developers we shape that knowledge. However, we can't act on knowledge itself: we must go through a representation. Source files are a representation, UML diagrams are a representation, and so on. &lt;br /&gt;Source files represent information using a language-specific &lt;i&gt;syntax&lt;/i&gt;; for instance, if you use Java or C#, you encode some procedural and structural knowledge about a class inside a text file. The text file is an artifact; it's not a run-time thing. Along the same lines, you can use UML and draw a class diagram, encoding structural knowledge about several classes. That's another artifact. Often, when we say "class C" or "function foo" what we mean is actually its representation inside an artifact (a sequence of LOCs in a source file, where we encode some knowledge in a specific language). &lt;br /&gt;Artifacts can be transformed into other artifacts: without mentioning MDA, you can just compile a bunch of source files and get an executable file. The executable file is just another artifact.&lt;br /&gt;&lt;br /&gt;At that point, however, you can actually &lt;b&gt;run&lt;/b&gt; the artifact. Let's say that you get a new process: the process is a run-time instance of the executable file artifact. Of course, you may start several run-time instances of the same artifact.&lt;br /&gt;&lt;br /&gt;Once the process is started, a wonderful thing happens :-). Your structural and procedural knowledge, formerly represented through LOCs inside artifacts, is now executable as well. Functions can be called. Classes can be instantiated. A function call is a run-time instance of a function. An object is a run-time instance of a class.&lt;br /&gt;&lt;br /&gt;We never shape the run-time instances directly. We shape artifacts (like a class described through textual Java or C++) so as to influence the run-time shape of the instances. Sometimes we shape an artifact so that its run-time instances can shape other run-time instances (meta-object protocols, dynamically generated code, etc).&lt;br /&gt;&lt;br /&gt;Interestingly, &lt;b&gt;some forces apply at the artifact level, while other forces apply at the instance level&lt;/b&gt;. If we don't get this straight, we end up with the usual confusion and useless debates.&lt;br /&gt;&lt;br /&gt;A few examples are probably needed. As I haven't introduced enough software forces so far, I'll base most of my examples on -ilities, because the same reasoning applies.&lt;br /&gt;&lt;br /&gt;Consider reusability: when we say that we want to reuse "a class" what we usually mean is that we want to reuse an &lt;b&gt;artifact&lt;/b&gt; (a component, a source file). Reusing a run-time instance is a form of object caching, which might be useful, but is not what is meant by reusability.&lt;br /&gt;&lt;br /&gt;Consider efficiency: when we say "this function is more efficient" what we usually mean is that its run-time instances are faster than other comparable implementations. &lt;br /&gt;&lt;br /&gt;Consider &lt;a href="http://www.carlopescio.com/2008/12/notes-on-software-design-chapter-2-mass.html"&gt;mass and gravity&lt;/a&gt; (the only software property/force I've introduced so far). Both are about the artifacts.&lt;br /&gt;&lt;br /&gt;I guess it's all bread-and-butter so far, so why is this distinction important? In &lt;a href="http://www.carlopescio.com/2008/11/notes-on-software-design-chapter-1.html"&gt;Chapter 1&lt;/a&gt;, I wrote: &lt;i&gt;a Center is (in software) a locus of highly cohesive information. in order to create highly cohesive units, we must be able to separate things. so this is what software [design] is about: keeping some things near, some things distant.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Now here is something interesting: in many cases, &lt;b&gt;we want to keep the artifacts apart, but have the run-time instances connected&lt;/b&gt;. This need to balance  asymmetrical forces in two worlds has been one of the dominant forces in the evolution of programming languages and paradigms, although nobody (as far as I know) has properly recognized its role. &lt;br /&gt;&lt;br /&gt;Jump on my time machine, and get back to the 70s. Now consider a sequence of lines, in some programming language, encoding some procedural knowledge. We want to reuse that procedural knowledge, so we extract the lines into a "reusable" function. Reusability of procedural knowledge &lt;b&gt;requires&lt;/b&gt; physical separation between a caller and a (reusable) callee (that's basically why subroutines/procedures/functions had to be invented). So, we can informally think of reusability as a force in the artifact world, keeping things apart.&lt;br /&gt;Now consider the specular world of run-time instances. Calling a function entails a cost: we have to save the instruction pointer, pass parameters, change the IP, execute the function's body, restore the IP and probably do some cleanup (details depend on language and CPU). Reusability on the artifact side just compromised efficiency on the run-time side. In most cases, we can ignore the side-effect in the run-time world. Sometimes, we can't, so we have two conflicting forces.&lt;br /&gt;Enter the brave language designer: his job is to invent something to bring balance between these two forces, in two different worlds. His first invention is &lt;i&gt;macro expansion&lt;/i&gt; through pre-processing (as in C or macro assemblers). C-style macros may solve the problem, but they bring in others. So the language designer gets a better idea: &lt;i&gt;inline expansion&lt;/i&gt; of function calls. That works better. However is done, &lt;b&gt;inlining&lt;/b&gt; is a way to keep things apart in the artifact world, and strictly together in the run-time world.&lt;br /&gt;&lt;br /&gt;Move along time, and consider concepts like function pointers, functions as first-class objects, or polymorphism: again, they're all about keeping artifacts apart, but instances connected. I don't want the artifact defining function/class f to know about function/class g, but I definitely want this instance of f to call g. Indeed (as we'll explore later on) the entire concept of indirection is born out of this basic need: &lt;b&gt;keep artifacts apart and instances connected&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Consider AOP-like techniques: once again, they are about separating artifacts, while having the run-time behavior composed.&lt;br /&gt;&lt;br /&gt;Once you understand this simple need, you can look at several programming concepts and clearly see their role in balancing forces between the two worlds. Where languages didn't help, patterns did. More on this next time.&lt;br /&gt;&lt;br /&gt;At this point, however, we can draw another conclusion: that a better &lt;a href="http://www.carlopescio.com/2009/10/forcefield-diagram.html"&gt;forcefield diagram&lt;/a&gt; would allow us to model forces (in the two worlds) and how we intend to balance those forces (which is how we intend to shape our software), and keep these two aspects apart. After all, we may have different strategies to balance forces out. More on this another time (soon enough, I hope). &lt;br /&gt;&lt;br /&gt;Interestingly, software is not alone in this need to balance forces of attraction and rejection. I'll explore this in my next post, together with a few more examples from the software world. I also have to investigate the relationship between the act of balancing forces and the decision space I've mentioned while talking about &lt;a href="http://www.carlopescio.com/2009/01/notes-on-software-design-chapter-3-mass.html"&gt;inertia&lt;/a&gt;. This is something I haven't had time to explore so far, so it's gonna take a little more time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8568037375587037725?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8568037375587037725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8568037375587037725' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8568037375587037725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8568037375587037725'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/06/notes-on-software-design-chapter-6.html' title='Notes on Software Design, Chapter 6: Balancing two Worlds'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-2312218387055016773</id><published>2010-05-06T13:55:00.003+02:00</published><updated>2010-05-08T10:15:05.705+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>C++ Manuale di Stile: Free</title><content type='html'>&lt;img src="http://www.eptacom.net/flagIta.gif"/&gt;Ho reso disponibile gratuitamente una versione digitalizzata del mio "C++ Manuale di Stile" (un po' vecchio ma ancora utile :-) &lt;br /&gt;&lt;br /&gt;Sulla &lt;a href="http://www.eptacom.net/pubblicazioni/cpp_stile"&gt;pagina dedicata&lt;/a&gt; trovate tutti i dettagli e qualche idea su un progetto futuro che spero possa prendere forma.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-2312218387055016773?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/2312218387055016773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=2312218387055016773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2312218387055016773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2312218387055016773'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/05/c-manuale-di-stile-free.html' title='C++ Manuale di Stile: Free'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8068255040107823300</id><published>2010-04-29T16:35:00.004+02:00</published><updated>2010-04-29T17:06:19.644+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='NOSD'/><title type='text'>Notes on Software Design, Chapter 0: What?</title><content type='html'>As an author, I've learnt that the introduction is best written last, when text has unfolded, and you really know what your paper is about.&lt;br /&gt;I'm far from that stage with my Notes on Software Design, but I see things clearly enough now that I can write a reasonable introduction, hence the Chapter 0, coming after Chapter 5.&lt;br /&gt;&lt;br /&gt;It all starts with the realization that software is just a material, and software design (at any level) is an act meant to give shape (or form) to the material. Software, however, is not a physical material, so we can't borrow on traditional disciplines to seek guidance. Well, sort of.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What do we know about physical materials?&lt;/b&gt;&lt;br /&gt;I'm not trying to write an essay on &lt;a href="http://en.wikipedia.org/wiki/Materials_science" target="_new"&gt;Materials science&lt;/a&gt;, so I'll focus on a few central issues here.&lt;br /&gt;&lt;br /&gt;Materials have well defined &lt;a href="http://en.wikipedia.org/wiki/List_of_materials_properties" target="_new"&gt;properties&lt;/a&gt;. Examples of properties are Electrical conductivity, Coefficient of thermal expansion, Hygroscopy, and so on.&lt;br /&gt;&lt;br /&gt;Properties enrich our language and make reasoning more effective (Donald Norman would say that properties "make us smart"). Arguments based on well-defined properties are more robust and don't lead to endless debates. &lt;i&gt;"This material has high hygroscopy, so keep it away from moisture"&lt;/i&gt;. Period. No debate. &lt;br /&gt;&lt;br /&gt;Properties allow to focus: I need to sustain high compression. Therefore, I need high compressive strength. Etc.&lt;br /&gt;&lt;br /&gt;Properties allow to select the best materials. &lt;a href="http://en.wikipedia.org/wiki/Elasticity_(physics)" target="_new"&gt; Elasticity&lt;/a&gt; is required if you want your material to come back to its original shape after stress. Actually, if you know the stress, you can pick the best material, based on a set of criteria, defined by the target product. An important criterion, of course, would be cost. &lt;br /&gt;&lt;br /&gt;Properties provide guidance while shaping the material. In fact, we even have &lt;i&gt;manufacturing  properties&lt;/i&gt;, like castability (see the wikipedia page above on material properties).&lt;br /&gt;&lt;br /&gt;Now, properties are well-defined when they are based on replicable, experimental observations. Most often, they are based on both a quantitative measurement process and on a physical theory of matter.&lt;br /&gt;&lt;br /&gt;The quantitative side is often based on &lt;b&gt;forces&lt;/b&gt;. Compressibility is based on Pressure (and Volume). So we can link everything back to a few well-understood forces. &lt;br /&gt;&lt;br /&gt;The theoretical side is usually based on a model of matter. Physical materials are subjected to the well-know laws, like newtonian physics (at the right scale). The model of matter itself (e.g. the notion of &lt;a href="http://www.substech.com/dokuwiki/doku.php?id=metals_crystal_structure" target="_new"&gt;metals crystal structure&lt;/a&gt;) is helpful when we try to understand why materials behave in a certain way under some specific force.&lt;br /&gt;&lt;br /&gt;Moving up (as I said, I'm not trying to write a comprehensive essay on physical materials), we have construction principles and patterns. This is encoded knowledge, prescribing what we should or should not do, or describing how to do something. The bright side is that, in the modern world, we can trace back most principles and patterns to a set of well-defined forces and properties.&lt;br /&gt;&lt;br /&gt;Finally, we have tools. &lt;a href="http://en.wikipedia.org/wiki/Finite_element_method" target="_new"&gt;Finite-Element Analysis&lt;/a&gt;, for instance, can be used to investigate the mechanical, thermal, electromagnetic, [etc], properties of a large structure.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What do we know about software as a material?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Not much, I'm afraid. Our knowledge is basically articulated in:&lt;br /&gt;&lt;br /&gt;- Principles&lt;br /&gt;- Patterns and Blueprints&lt;br /&gt;- Methods&lt;br /&gt;- Metrics&lt;br /&gt;- Ilities&lt;br /&gt;&lt;br /&gt;There is no shortage of principles. This &lt;a href="http://rearchitect.wordpress.com/2006/02/12/software-design-principles-mined-from-books-and-papers/" target="_new"&gt;interesting page&lt;/a&gt;, for instance, lists quite a few. Many are ill-defined and redundant, but a working knowledge of most principles is considered necessary for any good programmer / designer.&lt;br /&gt;&lt;br /&gt;We have patterns - I know I don't have to say more about this. We also have reference architectures, which are not quite the same as patterns or pattern languages, but close enough.&lt;br /&gt;&lt;br /&gt;We have methods. Test Driven Design, for instance, is a method, not a principle.&lt;br /&gt;&lt;br /&gt;We have metrics. Metrics seem to be very close to properties. &lt;a href=" http://yunus.hacettepe.edu.tr/~sencer/complexity.html" target="_new"&gt;Halstead&lt;/a&gt; defined a concept of "volume" for software, based on information theory. The well-known &lt;a href="http://web.cs.wpi.edu/~gpollice/cs562-s05/Readings/CKMetrics.pdf" target="_new"&gt;Chidamber and Kemerer&lt;/a&gt; suite defined a number of property-like concepts like Depth of Inheritance Tree, Number of Children, and so on. Metrics have the nice property of being easy to measure (most of the times). They have the dubious property of being very remotely connected with design reasoning. In fact, most literature on metrics is about proving they're not meaningless, mostly by showing some correlation with bug density or change density or something more connected with software development.&lt;br /&gt;&lt;br /&gt;We have -ilities, like reliability, scalability, and so on. These are often ill-defined, hard to measure properties of the final product. More akin to defining a "safe car" than to defining the properties of an alloy.&lt;br /&gt;Some authors have contributed more ility-like properties. &lt;a href="http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf" target="_new"&gt;Robert Martin&lt;/a&gt;, for instance, talks about Rigidity, Fragility, Viscosity and so on, but they are mostly based on metaphorical reasoning, not an a solid theory. They're also partially overlapping, and not precisely defined.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What do we ignore about software as a material?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We don't have a theory of forces. Lacking forces, it's basically impossible to come up with meaningful properties. Compressibility can't be defined when you don't even know about compression (pressure).&lt;br /&gt;&lt;br /&gt;We don't have &lt;b&gt;true&lt;/b&gt; properties. Properties should extend from language design to library design to application design. Properties should encompass paradigms. Properties should be based on a sensible theory of what software design is about, not on the mere fact that we can measure something or come up with a nice formula. Properties must be perceived as useful by software designers.&lt;br /&gt;&lt;br /&gt;We don't have a way to model forces and properties, basically because we don't know jack about them.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Some perspective&lt;/b&gt;&lt;br /&gt;I live in an old building (and I like it :-). When you look at the walls, however, you can almost hear the architect thinking "every problem can be solved by making some wall thicker". Modern buildings are designed with completely different techniques. The next-generation green buildings will make the most out of our knowledge of construction materials.&lt;br /&gt;&lt;br /&gt;I also live in the software world. You probably know the adage "All problems in computer science can be solved by another level of indirection" (David Wheeler). Why is that? What is, exactly, a level of indirection? What is indirection, by the way? Why is it useful? What is the underlying theory, what is a reasonable measure? What is the real difference between indirection in data and in control flow? Pick your favorite book on software design, and look up the answer if you can find it :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So what?&lt;/b&gt;&lt;br /&gt;Well, in the end, this is what I'm aiming for. A theory of software forces. A set of useful properties of software &lt;i&gt;as a material&lt;/i&gt;. This is what all this stuff is about. I haven't worked out everything yet. Actually, I've changed my mind on several things I've written so far (hey, it's a blog, not a book :-). But it's slowly coming together.&lt;br /&gt;&lt;br /&gt;Oh, by the way. I know quite a few people that won't feel good about the above. They want software to be an art. They want software to be "about humans". &lt;br /&gt;Let me state this clearly: I'm not trying to pursue some sort of "deskilling", whereby any fool could put together great software by applying some sort of magic process. I don't believe in deskilling. Actually, I believe in upskilling. I also understand the idea of software development as a craft, and even as an art. I know the poetry of code, so to speak :-). I rely on intuition and tacit knowledge every single day. &lt;br /&gt;Still, no amount of craftsmanship will prevent a cold, thin glass from breaking when force is applied. I want to know why, and how to shape it anyway, and I want a better way to say that, to teach that, I want to reach a deeper understanding upon which better, more ambitious systems can be built.&lt;br /&gt;&lt;br /&gt;Too much? Most likely :-), but hey, what is life without a noble aspiration?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8068255040107823300?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8068255040107823300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8068255040107823300' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8068255040107823300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8068255040107823300'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/04/notes-on-software-design-chapter-0-what.html' title='Notes on Software Design, Chapter 0: What?'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7541165755846615831</id><published>2010-03-30T23:10:00.003+02:00</published><updated>2010-03-30T23:30:09.543+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><title type='text'>Migration Completed</title><content type='html'>Migration to www.carlopescio.com worked, with a few minor quirks. Some images and links in very old posts (but perhaps also in more recent ones) pointing to files on www.eptacom.net, using relative paths, are now broken. &lt;br /&gt;&lt;br /&gt;In theory, blogger supports a missing file redirection; in practice, it doesn't seem to work for my specific case. I guess I'll live with the broken links : ) and just fix them whenever I stumble into one or someone complains. &lt;br /&gt;&lt;br /&gt;Fixing everything takes time and is against the spirit of &lt;a href="http://www.carlopescio.com/2005/10/blogging-as-destructuring.html"&gt;blogging as destructuring&lt;/a&gt;. Still, if you have any trouble reading any particular post (old ones), just let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7541165755846615831?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7541165755846615831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7541165755846615831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7541165755846615831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7541165755846615831'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/migration-completed.html' title='Migration Completed'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4954433096666596404</id><published>2010-03-30T18:17:00.002+02:00</published><updated>2010-03-30T18:26:40.594+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='announce'/><title type='text'>Blog Maintenance</title><content type='html'>I'm using Blogger to manage my blog, and so far I've been publishing to my website using the FTP Publishing feature, that Google decided to remove.&lt;br /&gt;I don't want to switch to another blogging platform (yet), so I'll have to go with the flow, migrate my blog to a custom domain, and hope Google's FTP Migration Tool works :-).&lt;br /&gt;&lt;br /&gt;When all is said and done, you'll no longer be able to reach my blog at www.eptacom.net/blog. It will be moved to &lt;a href="http://www.carlopescio.com"&gt;www.carlopescio.com&lt;/a&gt;, where I have hosted a copy of the blog so far. If you subscribed to the atom feed, you'll have to re-subscribe after the blog is moved (sorry).&lt;br /&gt;&lt;br /&gt;A message from Google should appear here after migration. I guess it will take a few days, as some DNS stuff is involved. That will be the right time to update your favorites, or re-subscribe the feed, etc. &lt;br /&gt;&lt;br /&gt;See you on &lt;a href="http://www.carlopescio.com"&gt;www.carlopescio.com&lt;/a&gt; (yeah, I'm being optimistic :-))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4954433096666596404?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4954433096666596404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4954433096666596404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4954433096666596404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4954433096666596404'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/blog-maintenance.html' title='Blog Maintenance'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-894627018843068372</id><published>2010-03-21T19:48:00.002+01:00</published><updated>2010-03-21T19:50:28.060+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quote'/><title type='text'>Quote of the Day</title><content type='html'>&lt;i&gt;Problems worthy of attack prove their worth by hitting back&lt;/i&gt; (Piet Hein)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-894627018843068372?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/894627018843068372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=894627018843068372' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/894627018843068372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/894627018843068372'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/quote-of-day.html' title='Quote of the Day'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-39491107244471675</id><published>2010-03-12T18:01:00.011+01:00</published><updated>2010-03-12T21:14:04.627+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Where is your Knowledge?</title><content type='html'>Software development is a process of knowledge acquisition and knowledge encoding (see Phillip Armour, copiously quoted in this blog). Where, and how, do we &lt;i&gt;store&lt;/i&gt; that knowledge? In several places, in several ways:&lt;br /&gt;&lt;br /&gt;In source code: that's executable knowledge&lt;br /&gt;In models: that's formal knowledge&lt;br /&gt;In other kind of documents: that's written knowledge&lt;br /&gt;In our brain, consciously: that's explicit knowledge&lt;br /&gt;In our brain, unconsciously: that's tacit knowledge&lt;br /&gt;&lt;br /&gt;Knowledge stored in source code has the extremely useful property of being executable, but we can't store the entire development knowledge in executable statements. &lt;a href="http://www.eptacom.net/blog/2009/06/design-rationale.html"&gt;Design Rationale&lt;/a&gt;, for instance, is not present in code (and not even in most UML diagrams, for that matter), and is basically stored at the conscious/unconscious level. My &lt;a href="http://www.eptacom.net/blog/2009/10/forcefield-diagram.html"&gt;forcefield diagram&lt;/a&gt; is much better at formally capturing rationale.&lt;br /&gt;&lt;br /&gt;Explicit knowledge is often passed by as oral tradition, while tacit knowledge is often passed by as "a way of doing things", just by working together. Pair programming, reviews, joint design sessions (and so on) help distribute both explicit and tacit knowledge.&lt;br /&gt;&lt;br /&gt;Knowledge has value, but that value is not constant over time. In 1962, Fritz Machlup came up with the concept of &lt;a href="http://en.wikipedia.org/wiki/Half-life_of_knowledge" target="_new"&gt;Half-life of knowledge&lt;/a&gt;: &lt;i&gt;the amount of time that has to elapse before half of the knowledge in a particular area is superseded or shown to be untrue.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Moreover, the initial value of a particular piece of knowledge can be very high, like a new algorithm that took you years to get right, or very small, like a trivial validation rule.&lt;br /&gt;&lt;br /&gt;Recently, I began to think about the half-life of our knowledge repositories as well. With my usual boldness, I'll go ahead and define the &lt;b&gt;Half-Life of a Knowledge Repository&lt;/b&gt;:&lt;i&gt; the amount of time that has to elapse before half of the knowledge in a repository is unrecoverable or just too costly to recover.&lt;/i&gt; I could even define "too costly" as "higher than the discounted value of that knowledge when lookup is attempted".&lt;br /&gt;&lt;br /&gt;The concept of recoverable knowledge is slightly deeper than it may seem. Sure, it does cover the obvious problems of losing knowledge for lack of backup procedures, or because it's stored in a proprietary format no longer supported, and so on. But it covers also several interesting cases:&lt;br /&gt;&lt;br /&gt;- the knowledge is in the brain of an employee, who leaves the company&lt;br /&gt;- the knowledge is in source code, but it's in an obsolete language&lt;br /&gt;- the knowledge is in source code, but it's extremely hard to read&lt;br /&gt;- etc.&lt;br /&gt;&lt;br /&gt;I'll leave it up to you to define the half-life of source code, models, documents, brain (conscious and unconscious). Of course, more details are needed: niche languages, for instance, tend to have a shorter half-life.&lt;br /&gt;&lt;br /&gt;Now, here is the real boon :-). We can combine the concept of Knowledge Half-Life, Knowledge Value, and Knowledge Repository Half-Life to map the risk of storing a particular piece of knowledge in a particular repository (only). Here is my first-cut map:&lt;br /&gt;&lt;br /&gt;&lt;table border="0" cellpadding="8" cellspacing="0" style='border:1.0px solid black;text-align:center;'&gt;&lt;tr&gt;&lt;td&gt;Knowledge Half-Life&lt;/td&gt;  &lt;td&gt;Knowledge (initial) Value&lt;/td&gt;  &lt;td&gt;Repository Half-Life&lt;/td&gt;  &lt;td&gt;Result&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td style='color:DarkGreen;'&gt;OK&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td style='color:DarkRed;'&gt;Risk&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td style='color:DarkOrange;'&gt;Little Waste&lt;/td&gt; &lt;/tr&gt;  &lt;tr&gt;  &lt;td&gt;Long&lt;/td&gt; &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td style='color:DarkOrange;'&gt;Little Risk&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td style='color:DarkOrange;'&gt;Little Waste&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td style='color:DarkOrange;'&gt;Little Risk&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Long&lt;/td&gt;  &lt;td style='color:DarkRed;'&gt;Waste&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td&gt;Short&lt;/td&gt;  &lt;td style='color:DarkGreen;'&gt;OK&lt;/td&gt; &lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;It's interesting to review one of the values in the &lt;a href="http://agilemanifesto.org/" target="_new"&gt;Agile Manifesto&lt;/a&gt; (&lt;i&gt;Working software over comprehensive documentation&lt;/i&gt;) under this perspective.&lt;br /&gt;&lt;br /&gt;Let's say we have a piece of knowledge, and that knowledge can be indeed stored in code (as I said, you can't store everything in code).&lt;br /&gt;&lt;br /&gt;If the half-life of knowledge is short, storing it in code &lt;i&gt;only&lt;/i&gt; is probably the best economical choice. If the half-life of knowledge is long, we have to worry a little more. If we add &lt;b&gt;relevant&lt;/b&gt; unit tests to that piece of code, we increase the repository half-life, as they make it easier to recover knowledge from code. If we use a mainstream language, we can also increase the repository half-life. &lt;br /&gt;&lt;br /&gt;This may still not be enough. If you had to recover the entire knowledge stored in a non-trivial piece of code (say, an mp4 codec) having &lt;i&gt;only&lt;/i&gt; the source code, and no (comprehensive) documentation on what that piece of code is doing, why, and how, it would take you far too much. The half-life of code is shorter than the half-life of code + documents. &lt;br /&gt;Actually, depending on context, given the choice to have just the code and nothing else, or just comprehensive documentation and nothing else, we better be careful about what we choose (when knowledge half-life is long, of course).&lt;br /&gt;&lt;br /&gt;Of course, the opposite is also true: if you store knowledge with short half-life outside code, you seriously risk wasting your time.&lt;br /&gt;&lt;br /&gt;I've often been critic about teaching and applying principles and techniques without the necessary &lt;a href="http://www.eptacom.net/blog/2007/09/voyage-in-agile-memeplex.html"&gt;context&lt;/a&gt;. I hope that somehow, the table above and the underlying concepts can move our understanding of &lt;i&gt;when to use what&lt;/i&gt; a little further.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-39491107244471675?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/39491107244471675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=39491107244471675' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/39491107244471675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/39491107244471675'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/where-is-your-knowledge.html' title='Where is your Knowledge?'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-419482431244085733</id><published>2010-03-08T18:55:00.003+01:00</published><updated>2010-03-08T19:00:57.711+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><category scheme='http://www.blogger.com/atom/ns#' term='AOP'/><title type='text'>Why you should learn AOP</title><content type='html'>A few days ago, I've spent some time reading a critic of AOP (&lt;a href="http://onward-conference.org/2009/files/steimannessay.pdf " target="_new"&gt;The Paradoxical Success of Aspect-Oriented Programming&lt;/a&gt; by Friedrich Steimann). As often, I felt compelled to read some of the bibliographical references too, which took me a little more (week-end) time.&lt;br /&gt;&lt;br /&gt;Overall, in the last few years I've devoted quite some time to learn, think, and even &lt;a href="http://www.eptacom.net/blog/labels/AOP.html "&gt;write a little&lt;/a&gt; about AOP. I'm well aware of the problems Steimann describes, and I share some skepticism about the viability of the AOP paradigm as we know it. &lt;br /&gt;&lt;br /&gt;Too much literature, for instance, is focused on a small set of pervasive concerns like logging. I believe that as we move toward higher-level concerns, we must make a clear distinction between pervasive concerns and cross-cutting concerns. A concern can be cross-cutting without being pervasive, and in this sense, for instance, I don't really agree that AOP is not for singletons (see my old post &lt;a href="http://www.eptacom.net/blog/2006/09/some-notes-on-aop.html"&gt;Some notes on AOP&lt;/a&gt;).&lt;br /&gt;Also, I wouldn't dismiss the distinction between spectators and assistants so easily, especially because many pervasive concerns can be modeled as spectators. Overall, the paradigm seems indeed a little immature when you look at the long-term maintenance effects of aspects as they're known today.&lt;br /&gt;&lt;br /&gt;Still, I think the time I've spent pondering on AOP was truly well spent. Actually, I would suggest that you spend some time learning about AOP too, even if you're not planning to use AOP in the foreseeable future. &lt;br /&gt;&lt;br /&gt;I don't really mean learning a specific language - unless you want/need to try out a few things. I mean learning the concepts, the AOP perspective, the AOP terminology, the effects and side-effects of an Aspect Oriented solution.&lt;br /&gt;&lt;br /&gt;I'm suggesting that you learn all that despite the obvious (or perhaps not so obvious) deficiencies in the current approaches and languages, the excessive hype and the underdeveloped concepts. I'm suggesting that you learn all that because it will make you a better designer.&lt;br /&gt;&lt;br /&gt;Why? Because it will expand your mind. It will add a new, alternative perspective through which you can look at your problems. New questions to ask. New concepts. New &lt;b&gt;names&lt;/b&gt;. Sometimes, all we need is a name. A beacon in the brainstorm, and a steady hand.&lt;br /&gt;&lt;br /&gt;As I've said many times now, as designers we're shaping software. We can choose many shapes, and ideally, we will find a shape that is in frictionless contact with the forcefield. Any given paradigm will suggest a set of privileged shapes, at macro and micro-level. Including the aspect-oriented paradigm in your thinking will expand the set of shapes you can apply and conceive. &lt;br /&gt;&lt;br /&gt;Time for a short war story :-). In the past months I've been thinking a lot about some issues in a large CAD system. While shaping a solution, I'm constantly getting back to what I could call aspect-thinking. There are many cross-cutting concerns to be resolved. Not programming-level concerns (like the usual, boring logging stuff). Full-fledged application-domain concerns, that tend to cross-cut the principal decomposition. &lt;br /&gt;&lt;br /&gt;Now, you see, even thinking "principal decomposition" and "cross-cutting" is making your first step into aspect-thinking. Then you can think about ways to bring those concerns inside the principal decomposition (if appropriate and/or possible and/or convenient) or think about the best way to keep them outside without code-level tangling. Tangling. Another interesting name, another interesting concept.&lt;br /&gt;&lt;br /&gt;Sure, if you ain't using true AOP (for instance, we're using plain old C++), you'll have to give up some oblivousness (another name, another concept!), but it can be done, and it works fine (for a small scale example, see &lt;a href="http://www.eptacom.net/blog/2008/04/can-aop-inform-oop-toward-soa-too-part.html"&gt;part 1&lt;/a&gt; and &lt;a href="http://www.eptacom.net/blog/2008/04/can-aop-inform-oop-toward-soa-too-part_25.html"&gt;part 2&lt;/a&gt; of my "Can AOP inform OOP?")&lt;br /&gt;&lt;br /&gt;So far, the candidate shape is causing some discomfort. That's reasonable. It's not a "traditional" solution. Which is fine, because so far, tradition didn't work so well :-). Somehow, I hope the team will get out of this experience with a new mindset. Nobody used to talk about "principal decomposition" or "cross-cutting concern" in the company. And &lt;a href="http://www.eptacom.net/blog/2010/03/you-cant-control-what-you-cant.html"&gt;you can't control what you can't name&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I hope they will gradually internalize the new concepts, as well as the tactics we can use inside traditional languages. That would be a major accomplishment. Much more important than the design we're creating, or the tons of code we'll be writing. Well, we'll see...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-419482431244085733?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/419482431244085733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=419482431244085733' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/419482431244085733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/419482431244085733'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/why-you-should-learn-aop.html' title='Why you should learn AOP'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-681562208120567363</id><published>2010-03-07T22:13:00.003+01:00</published><updated>2010-03-08T13:33:31.068+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='thinking'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='book reference'/><title type='text'>You can't control what you can't …</title><content type='html'>… measure, Tom de Marco used to say ("Controlling Software Projects: Management, Measurement, and Estimation", 1982). Tom &lt;a href="http://www2.computer.org/cms/Computer.org/ComputingNow/homepage/2009/0709/rW_SO_Viewpoints.pdf " target="_new"&gt;recently confessed&lt;/a&gt; he no longer subscribes to that point of view. Now, I like Tom and I've learnt a lot from him, but I don't really agree about most of what he's saying in that paper. &lt;br /&gt;&lt;br /&gt;Sure, the overall message is interesting: earth-shaking projects have a ROI so big that you don't really care about spending a little more money. But money isn't the only thing you may need to control (what about time, and your window of opportunity?) and not each and every project can be a earth-shaking project. If you need to comply with some policy or regulation by a given date, it may well be a moot project, but you better control for time :-). More examples (tons, actually) on demand. Relinquishing control is a fascinating concept, and by all means, if you can redefine your projects so that control is no longer necessary, &lt;b&gt;just do it&lt;/b&gt;. But frankly, it's not always an option.&lt;br /&gt;&lt;br /&gt;Still, can we control what we can't measure? As usual, it depends. It depends on &lt;i&gt;what&lt;/i&gt; you want to control, and on your definition of &lt;i&gt;control&lt;/i&gt;. We can watch over some things informally, that is, using a rough, imprecise, perhaps intuitive measure ("feeling") and still keep inside reasonable boundaries. This might be enough to be "in control". As others have noted (see for instance &lt;a href="http://blog.castsoftware.com/managing-what-you-cant-measure/" target="_new"&gt;Managing What You Can’t Measure&lt;/a&gt;) sometimes all we need is a feeling that we're going off track, and a sensible set of tactics to get back on.&lt;br /&gt;&lt;br /&gt;All that said, I feel adventurous enough today :-) to offer my own version of Tom's (repudiated) law. I just hope I won't have to take it back in 30 years :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;You can't control what you can't name&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;I would have said "define", but a precise definition is almost like a measure. But if you can't even name the concept (which, yes, requires at least a very informal definition of the term), you're &lt;i&gt;consciously unaware&lt;/i&gt; of it. Without awareness, there is no control.&lt;br /&gt;&lt;br /&gt;I can say that better: you can't control it &lt;i&gt;intentionally&lt;/i&gt;. For a long time, people have controlled forces they didn't fully understand, and perhaps couldn't even name, for instance in building construction. They did that through what Alexander called the &lt;i&gt;unselfconscious process&lt;/i&gt;, by relying on tradition (which was largely based on trial and error). &lt;br /&gt;&lt;br /&gt;I see this very often in software projects too. People doing things because tradition taught them to do so. They don't really understand why - and would react vehemently if you dare to question their approach or suggest another way. They do so because tradition provides safety, and you're threatening their safety.&lt;br /&gt;&lt;br /&gt;The problem with the unselfconscious process is that it doesn't scale well. When the problem is new, when the rate of change in the problem domain increases, whenever the right answer can't be found in tradition, the unselfconscious process doesn't work anymore. We gotta move to the selfconscious process. You gotta learn concepts. Names. Forces. Nonlinear interactions. We gotta think before we do. We gotta ask questions. Question the unquestionable. Move outside our comfort area. Learn, learn, learn.&lt;br /&gt;&lt;br /&gt;Speaking of learning, I've got something to say, which is why I wrote this post in the first place, but I'll save that for tomorrow :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-681562208120567363?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/681562208120567363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=681562208120567363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/681562208120567363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/681562208120567363'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/03/you-cant-control-what-you-cant.html' title='You can&apos;t control what you can&apos;t …'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-3198325339611744984</id><published>2010-02-12T18:21:00.003+01:00</published><updated>2010-02-12T18:53:37.927+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><title type='text'>Form vs. Function: a Space Odyssey</title><content type='html'>I was teaching Object Oriented Design past week, and I mentioned the interplay between form and function (form follows function; function follows form). I'm rather cautious not to spend too much time on philosophy, although a little philosophy shouldn't hurt, and people who know me tend to expect a short philosophical digression every now and then.&lt;br /&gt;&lt;br /&gt;Function follows form: that is to say, the shape of an object will suggest possible uses. Form follows function: the intended usage of an object will constrain, and therefore guide, its physical shape. This is true for software objects as well. It's just a different material, something we can't immediately see and shape with our hands.&lt;br /&gt;&lt;br /&gt;Realizing that function follows form is a pivotal moment in the development of intelligence. You probably remember the opening of &lt;a href="http://en.wikipedia.org/wiki/2001_%28film%29" target="_new"&gt;2001: A Space Odyssey&lt;/a&gt;. The apes are touching the monolith and, shortly after, one of them is playing with a bone and bang! - it's not just a bone anymore: it's a tool. Function follows form. This chapter is known as "The Dawn of Man", and rightly so.&lt;br /&gt;&lt;br /&gt;Watch a little more, and you'll see a doughnut-shaped space station. That's a very good example of form following function (exercise for the reader :-)&lt;br /&gt;&lt;br /&gt;By the way, if you have never seen that apes stuff till now :-), &lt;a href="http://www.youtube.com/watch?v=GVMPlIQAz5E" target="_new"&gt;here it is&lt;/a&gt;, at least until it gets removed from YouTube...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-3198325339611744984?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/3198325339611744984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=3198325339611744984' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3198325339611744984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3198325339611744984'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/02/form-vs-function-space-odyssey.html' title='Form vs. Function: a Space Odyssey'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7306428421146377258</id><published>2010-01-25T17:03:00.001+01:00</published><updated>2010-01-25T17:06:08.628+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quote'/><title type='text'>[Long] Quote of the Day</title><content type='html'>"I learned this, at least, by my experiment: that if one advances confidently in the direction of his dreams, and endeavours to live the life which he has imagined, he will meet with a success unexpected in common hours. He will put some things behind, will pass an invisible boundary; new, universal, and more liberal laws will begin to establish themselves around and within him; or the old laws be expanded, and interpreted in his favour in a more liberal sense, and he will live with the license of a higher order of beings. In proportion as he simplifies his life, the laws of the universe will appear less complex, and solitude will not be solitude, nor poverty poverty, nor weakness weakness. If you have built castles in the air, your work need not be lost; that is where they should be. Now put the foundations under them."&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Henry David Thoreau&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7306428421146377258?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7306428421146377258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7306428421146377258' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7306428421146377258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7306428421146377258'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/01/long-quote-of-day.html' title='[Long] Quote of the Day'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-2122354707672817919</id><published>2010-01-10T22:41:00.003+01:00</published><updated>2010-03-08T12:41:53.748+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='real options'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Delaying Decisions</title><content type='html'>Since &lt;a href="http://www.eptacom.net/blog/2008/10/microblogging-is-not-my-thing.html"&gt;microblogging is not my thing&lt;/a&gt;, I decided to start 2010 by writing my longer post ever :-). It will start with a light review of a well-known principle and end up with a new design concept. Fasten your seatbelt :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Last Responsible Moment&lt;/b&gt;&lt;br /&gt;When we develop a software product, we make decisions. We decide about individual features, we make design decisions, we make coding decisions, we even decide which bugs we really want to fix before going public. Some decisions are taken on the fly; some, at least in the old school, are somewhat planned.&lt;br /&gt;&lt;br /&gt;A key principle of  &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development" target="_new"&gt; Lean Development&lt;/a&gt; is to delay decisions, so that:&lt;br /&gt;a) decisions can be based on (yet-to-discover) facts, not on speculation&lt;br /&gt;b) you exercise the wait option (more on this below) and avoid early commitment &lt;br /&gt;&lt;br /&gt;The principle is often spelled as "Delay decisions until the last responsible moment", but a quick look at &lt;a href="http://www.poppendieck.com/ " target="_new"&gt;Mary Poppendieck's website&lt;/a&gt; (Mary co-created the Lean Development approach) shows a more interesting nuance: "Schedule Irreversible Decisions at the Last Responsible Moment". &lt;br /&gt;&lt;br /&gt;Defining "Irreversible" and "Last Responsible" is not trivial. In a sense, there is nothing in software that is truly irreversible, because you can always start over. I haven't found a good definition for "irreversible decision" in literature, but I would define it as follows: &lt;i&gt;if you make an irreversible decision at time T, undoing the decision at a later time will entail a complete (or almost complete) waste of everything that has been created after time T.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;There are some documented definitions for "last responsible moment". A popular one is "The point when failing to decide eliminates an important option", which I found rather unsatisfactory. I've also seen some attempts to quantify that better, as in this &lt;a href="http://www.agilejournal.com/pdf/last-responsible-moment.pdf" target="_new"&gt;funny story&lt;/a&gt;, except that in the real world you never have a problem which is &lt;i&gt;that&lt;/i&gt; simple (very few ramifications in the decision graph) and &lt;i&gt;that&lt;/i&gt; detailed (you know the schedule beforehand). I would probably define the Last Responsible Moment as follows: &lt;i&gt;time T is the last responsible moment to make a decision D if, by postponing D, the probability of completing on schedule/budget (even when you factor-in the hypothetical learning effect of postponing) decreases below an acceptable threshold.&lt;/i&gt; That, of course, allows us to scrap everything and restart, if schedule and budget allows for it, and in this sense it's kinda coupled with the definition of irreversible.&lt;br /&gt;&lt;br /&gt;Now, irreversibility is bad. We don't want to make irreversible decisions. We certainly don't want to make them too soon. Is there anything we can do? I've got a few important things to say about modularity vs. irreversibility and passive vs. proactive option thinking, but  right now, it's useful to recap the major decision areas within a software project, so that we can clearly understand what we can &lt;b&gt;actually delay&lt;/b&gt;, and what is &lt;b&gt;usually suggested&lt;/b&gt; that we delay.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Major Decision Areas&lt;/b&gt;&lt;br /&gt;I'll skip on a few very-high-level, strategic decisions here (scope, strategy, business model, etc). It's not that they can't be postponed, but I need to give some focus to this post :-). So I'll get down to the more &lt;i&gt;ordinarily&lt;/i&gt; taken decisions.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;People&lt;/i&gt;&lt;br /&gt;Choosing the right people for the project is a well-known ingredient for success.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Approach/Process&lt;/i&gt;&lt;br /&gt;Are we going XP, Waterfall, something in between? :-).&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Feature Set&lt;/i&gt;&lt;br /&gt;Are we going to include this feature or not?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Design&lt;/i&gt;&lt;br /&gt;What is the internal shape (form) of our product?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Coding&lt;/i&gt;&lt;br /&gt;Much like design, at a finer granularity level.&lt;br /&gt;&lt;br /&gt;Now, "design" is an overly general concept. Too general to be useful. Therefore, I'll split it into a few major decisions.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Architectural Style&lt;/i&gt;&lt;br /&gt;Is this going to be an embedded application, a rich client, a web application? This is a rather irreversible decision.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Platform&lt;/i&gt;&lt;br /&gt;Goes somewhat in pair with Architectural Style. Are we going with an embedded application burnt into an FPGA? Do you want to target a PIC? Perhaps an embedded PC? Is the client a Windows machine, or you want to support Mac/Linux? A .NET server side, or maybe Java? It's all rather irreversible, although not completely irreversible.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;3rd-Party Libraries/Components/Etc&lt;/i&gt;&lt;br /&gt;Are we going to use some existing component (of various scale)? Unless you plan on wrapping everything (which may not even be possible), this often end up being an irreversible decision. For instance, once you commit yourself to using Hibernate for persistence, it's not trivial to move away.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Programming Language&lt;/i&gt;&lt;br /&gt;This is the quintessential irreversible decision, unless you want to play with language converters. Note that this is not a coding decisions: coding decisions are made after the language has been chosen.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Structure / Shape / Form&lt;/i&gt;&lt;br /&gt;This is what we usually call "design": the shape we want to impose to our material (or, if you live in the "emergent design" side, the shape that our material will take as the final result of several incremental decisions). &lt;br /&gt;&lt;br /&gt;So, what are we going to delay? We can't delay all decisions, or we'll be stuck. Sure, we can delay something in each and every area, but truth is, every popular method has been focusing on just a few of them. Of course, different methods tried to delay different choices.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Little Historical Perspective&lt;/b&gt;&lt;br /&gt;Experience brings perspective; at least, true experience does :-). Perspective allows to look at something and see more than it's usually seen. For instance, perspective allows to look at the old, outdated, obsolete waterfall approach and see that it (too) was meant to delay decisions, just different decisions.&lt;br /&gt;&lt;br /&gt;Waterfall was meant to delay people decisions, design decisions (which include platform, library, component decisions) and coding decisions. People decision was delayed by &lt;i&gt;specialization&lt;/i&gt;: you only have to pick the analyst first, everyone else can be chosen later, when you know what you gotta do (it even makes sense -)). Design decision was delayed because platform, including languages, OS, etc, were way more balkanized than today. Also, architectural styles and patterns were much less understood, and it made sense to look at a larger picture before committing to an overall architecture.&lt;br /&gt;Although this may seem rather ridiculous from the perspective of a 2010 programmer working on Java corporate web applications, most of this stuff is still relevant for (e.g.) mass-produced embedded systems, where choosing the right platform may radically change the total development and production cost, yet choosing the wrong platform may over-constrain the feature set.&lt;br /&gt;&lt;br /&gt;Indeed, &lt;a href="http://en.wikipedia.org/wiki/Open_system_(computing) " target="_new"&gt;open systems&lt;/a&gt; (another legacy term from late '80s - early '90s) were born exactly to lighten up that choice. Choose the *nix world, and forget about it. Of course, the decision was still irreversible, but granted you some latitude in choosing the &lt;i&gt;exact&lt;/i&gt; hw/sw. The entire multi-platform industry (from multi-OS libraries to Java) is basically built on the same foundations. Well, that's the bright side, of course :-).&lt;br /&gt;&lt;br /&gt;Looking beyond platform independence, the entire concept of "standard" allows to delay some decision. TCP/IP, for instance, allows me to choose &lt;i&gt;modularly&lt;/i&gt; (a concept I'll elaborate later). I can choose TCP/IP as the transport mechanism, and then delay the choice of (e.g.) the client side, and focus on the server side. Of course, a choice is still made (the client must have TCP/IP support), so let's say that &lt;i&gt;widely adopted&lt;/i&gt; standards allow for some modularity in the decision process, and therefore to delay some decision, mostly design decisions, but perhaps some other as well (like people).&lt;br /&gt;&lt;br /&gt;It's already going to be a long post, so I won't look at each and every method/principle/tool ever conceived, but if you do your homework, you'll find that a lot of what has been proposed in the last 40 years or so (from code generators to MDA, from spiral development to XP, from stepwise refinement to OOP) includes some magic ingredient that allows us to postpone some kind of decision.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It's 2010, guys&lt;/b&gt;&lt;br /&gt;So, if you ain't agile, you are clumsy :-)) and c'mon, you don't wanna be clumsy :-). So, seriously, which kind of decisions are usually delayed in (e.g.) XP?&lt;br /&gt;&lt;br /&gt;People? I must say I haven't seen much on this. Most literature on XP seems based on the concept that team members are mostly programmers with a wide set of skills, so there should be no particular reason to delay decision about who's gonna work on what. I may have missed some particularly relevant work, however.&lt;br /&gt;&lt;br /&gt;Feature Set? Sure. Every incremental approach allows us to delay decisions about features. This can be very advantageous if we can play the learning game, which includes rapid/frequent delivery, or we won't learn enough to actually &lt;i&gt;steer&lt;/i&gt; the feature set. &lt;br /&gt;Of course, delaying some decisions on feature set can make some design options viable now, and totally bogus later. Here is where you &lt;b&gt;really&lt;/b&gt; have to understand the concept of &lt;b&gt;irreversible&lt;/b&gt; and &lt;b&gt;last responsible moment&lt;/b&gt;. Of course, if you work on a settled platform, things get simpler, which is one more reason why people get religiously attached to a platform.&lt;br /&gt;&lt;br /&gt;Design? Sure, but let's take a deeper look. &lt;br /&gt;&lt;br /&gt;Architectural Style: not much. Quoting Booch, &lt;i&gt;"agile projects often start out assuming a given platform and environmental context together with a set of proven design patterns for that domain, all of which represent architectural decisions in a very real sense"&lt;/i&gt;. See my post &lt;a href="http://www.eptacom.net/blog/2007/11/architecture-as-tradition-in.html"&gt;Architecture as Tradition in the Unselfconscious Process&lt;/a&gt; for more.&lt;br /&gt;Seriously, nobody ever expected to start with a monolithic client and end up with a three-tier web application built around a MVC pattern just by coding and refactoring. The architectural style is pretty much a given in many contemporary projects.&lt;br /&gt;&lt;br /&gt;Platform: sorry guys, but if you want to start coding &lt;i&gt;now&lt;/i&gt;, you gotta choose your platform &lt;i&gt;now&lt;/i&gt;. Another irreversible decision made right at the beginning.&lt;br /&gt;&lt;br /&gt;3rd-Party Libraries/Components/Etc: some delay is possible for modularized decisions. If you wanna use hibernate, you gotta choose pretty soon. If you wanna use Seam, you gotta choose pretty soon. Pervasive libraries are so entangled with architectural styles that it's relatively hard to delay some decisions here. Modularized components (e.g. the choice of a PDF rendering library) are simple to delay, and can be proactively delayed (see later).&lt;br /&gt;&lt;br /&gt;Programming Language: no way guys, you have to choose right here, right now.&lt;br /&gt;&lt;br /&gt;Structure / Shape / Form: of course!!! Here we are. This is it :-). You can delay a lot of detailed design choices. Of course, we always postpone some design decision, even when we design before coding. But let's say that this is where I see a lot of suggestions to delay decisions in the agile literature, often using the dreaded Big Upfront Design as a straw man argument. Of course, the emergent design (or &lt;a href="http://www.eptacom.net/blog/2006/12/infrastructure-and-superstructure.html "&gt;accidental architecture&lt;/a&gt;) may or may not be good. If I had to compare the design and code coming out of the XP Episode with &lt;a href="http://www.eptacom.net/blog/2007/07/get-ball-rolling-part-1-of-4-i-guess.html"&gt;my own&lt;/a&gt;, I would say that a little upfront design can do wonders, but hey, you know me :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Practicing&lt;/b&gt;&lt;br /&gt;OK guys, what follows may sound a little odd, but in the end it will prove useful. Have faith :-).&lt;br /&gt;You can get better at everything by doing anything :-), so why not getting better at delaying decisions by playing Windows Solitaire? All you have to do is set the options in the hardest possible way:&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/sol3.png"/&gt;&lt;br /&gt;now, play a little, until you have to make some decision, like here:&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/sol1small.png"/&gt;&lt;br /&gt;I could move the 9 of spades or the 9 of clubs over the 10 of hearts. It's an irreversible decision (well, not if you use the undo, but that's lame :-). There are some ramifications for both choices.&lt;br /&gt;If I move the 9 of clubs, I can later move the king of clubs and uncover a new card. After that, it's all unknown, and no further speculation is possible. Here, learning requires an irreversible decision; this is very common in real-world projects, but seldom discussed in literature.&lt;br /&gt;If I move the 9 of spades, I uncover the 6 of clubs, which I can move over the 7 of aces. Then, it's kinda unknown, meaning: if you're a serious player (I'm not) you'll remember the previous cards, which would allow you to speculate a little better. Otherwise, it's just as above, you have to make an irreversible decision to learn the outcome.&lt;br /&gt;&lt;br /&gt;But wait: what about the last responsible moment? Maybe we can delay this decision! Now, if you delay the decision by clicking on the deck and moving further, you're not delaying the decision: you're wasting a chance. In order to delay this decision, there must be something else you can do. &lt;br /&gt;Well, indeed, there is something you can do. You can move the 8 of aces above the 9 of clubs. This will uncover a new card (learning) without wasting any present opportunity (it could still waste a future opportunity; life it tough). Maybe you'll get a 10 of aces under that 8, at which point there won't be any choice to be made about the 9. Or you might get a black 7, at which point you'll have a different way to move the king of clubs, so moving the 9 of spades would be a more attractive option. So, delay the 9 and move the 8 :-). Add some luck, and it works:&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/sol2small.png"/&gt;&lt;br /&gt;and you get some money too (total at decision time Vs. total at the end)&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/sol4.png"/&gt;&lt;br /&gt;&lt;br /&gt;Novice solitaire players are also known to make irreversible decision &lt;i&gt;without necessity&lt;/i&gt;. For instance, in similar cases:&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/sol5small.png"/&gt;&lt;br /&gt;I've seen people eagerly moving the 6 of aces (actually, whatever they got) over the 7 of spades, because "that will free up a slot". Which is true, but irrelevant. This is a decision you can easily delay. Actually, it's a decision you &lt;i&gt;must&lt;/i&gt; delay, because:&lt;br /&gt;- if you happen to uncover a king, you can always move the 6. It's not the last responsible moment yet: if you do nothing now, nothing bad will happen.&lt;br /&gt;- you may uncover a 6 of hearts before you uncover a king. And moving that 6 might be more advantageous than moving the 6 of aces. So, &lt;b&gt;don't do it&lt;/b&gt; :-). If you want to look good, quote Option Theory, call this a Deferral Option and write a paper about it :-).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Proactive Option Thinking&lt;/b&gt;&lt;br /&gt;I've recently read an interesting paper in IEEE TSE ("An Integrative Economic Optimization Approach to Systems Development Risk Management", by Michel Benaroch and James Goldstein). Although the real meat starts in chapter 4, chapters 1-3 are probably more interesting for the casual reader (including myself). &lt;br /&gt;There, authors recap some literature about Real Options in Software Engineering, including the popular argument that delaying decisions is akin to a deferral option. They also make important distinctions, like the one between &lt;i&gt;passive&lt;/i&gt; learning through deferral of decisions, and &lt;i&gt;proactive&lt;/i&gt; learning, but also between responsiveness to change (a central theme in agility literature) and manipulation of change (relatively less explored), and so on. There is a a lot of food for thought in those 3 chapters, so if you can get a copy, I suggest that you spend a little time pondering over it.&lt;br /&gt;Now, I'm a strong supporter of Proactive Option Thinking.  Waiting for opportunities (and then react quickly) is not enough. I believe that options should be "implanted" in our project, and that can be done by applying the right design techniques. How? Keep reading : ).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Invariant Decision&lt;/b&gt;&lt;br /&gt;If you look back at those pictures of Solitaire, you'll see that I wasn't really delaying irreversible decisions. All decisions in solitaire are irreversible (real men don't use CTRL-Z). Many decisions in software development are irreversible as well, especially when you are in a tight budget/schedule, so starting over is not an option. Therefore, irreversibility can't really be the key here. Indeed, I was trying to delay &lt;b&gt;Invariant Decisions&lt;/b&gt;. Decisions that I can take now, or I can take later, with little or no impact on the outcomes. The concept itself may seem like a minor change from "irreversible", but it allows me to do some magic:&lt;br /&gt;- I can get rid of the "last responsible moment" part, which is poorly defined anyway. I can just say: &lt;b&gt;delay invariant decisions&lt;/b&gt;. Period. You can delay them as much as you want, provided they are still invariant. No ambiguity here. That's much better.&lt;br /&gt;- I can proactively make some decisions invariant. This is so important I'll have to say it again, this time in bold: &lt;b&gt;I can proactively make some decisions invariant&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Invariance, Design, Modularity&lt;/b&gt;&lt;br /&gt;If you go back to the Historical Perspective paragraph, you can now read it under a different... perspective :-). Several tools, techniques, methods can be adopted not just to delay some decision, but to &lt;i&gt;create&lt;/i&gt; the option to delay the decision. How? Through careful design, of course!&lt;br /&gt;&lt;br /&gt;Consider the strong modularity you get from service-oriented architecture, and the platform independence that comes through (well-designed) web services. This is a powerful weapon to delay a lot of decisions on one side or another (client or server). &lt;br /&gt;&lt;br /&gt;Consider standard protocols: they are a way to make some decision invariant, and to modularize the impact of some choices.&lt;br /&gt;&lt;br /&gt;Consider encapsulation, abstraction and interfaces: they allow you to delay quite a few low-level decisions, and to &lt;i&gt;modularize the impact of change as well&lt;/i&gt;. If your choice turn out to be wrong, but it's highly localized (modularized) you may afford undoing your decision, therefore turning irreversible into reversible. A barebone example can be found in my old post (2005!) &lt;a href="http://www.eptacom.net/blog/2005/10/builder-pattern-as-option.html "&gt;Builder [pattern] as an option&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Consider a very old OOA/OOD principle, now somehow resurrected under the "ubiquitous language" umbrella. It states that you should try to reflect the real-world entities that you're dealing with in your design, and then in your code. That includes avoiding primitive types like integer, and create meaningful classes instead. Of course, you have to understand what you're doing (that is, you gotta be a &lt;b&gt;good designer&lt;/b&gt;) to avoid useless overengineering. See &lt;a href="http://www.eptacom.net/blog/2007/08/get-ball-rolling-part-4-of-4-told-ya.html "&gt;part 4&lt;/a&gt; of my digression on the XP Episode for a discussion about adding a seemingly useless Ball class (that is: implanting a low cost - high premium option).&lt;br /&gt;Names alter the forcefield. A named concept stands apart. My next post on the forcefield theme, by the way, will explore this issue in depth :-).&lt;br /&gt;&lt;br /&gt;And so on. I could go on forever, but the point is: you can make many (but not all, of course!) decisions invariant, if you apply the right design techniques. Most of those techniques will also modularize the cost of rework if you make the wrong decision. And sure, you can try to do this on the fly as you code. Or you may want to to some upfront design. You know what I'm thinking.&lt;br /&gt;&lt;br /&gt;OK guys, it took quite a while, but now we have a new concept to play with, so more on this will follow, randomly as usual. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-2122354707672817919?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/2122354707672817919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=2122354707672817919' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2122354707672817919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2122354707672817919'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/01/delaying-decisions.html' title='Delaying Decisions'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-7995976774023850060</id><published>2010-01-01T15:44:00.002+01:00</published><updated>2010-01-01T15:48:29.924+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Inspirational reading</title><content type='html'>&lt;a href="http://cogprints.org/266/0/selfctr.htm" target="_new"&gt;The Self as a Center of Narrative Gravity&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By the way guys, happy new year : )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-7995976774023850060?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/7995976774023850060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=7995976774023850060' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7995976774023850060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/7995976774023850060'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2010/01/inspirational-reading.html' title='Inspirational reading'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-8923924853999947066</id><published>2009-12-15T19:13:00.002+01:00</published><updated>2009-12-15T19:14:18.699+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>A little more on DSM and Gravity</title><content type='html'>In a recent paper ("The Golden Age of Software Architecture" Revisited, IEEE Software, July/August 2009), Paul Clements and Mary Shaw conclude by talking about Conformance Checking. Indeed, although many would say that the real design/architecture is represented by code, a few :-) of us still think that code should reflect design, and that conformance of code to design should be automatically checked when possible (not necessarily in any given project; not all projects are equal).&lt;br /&gt;Conformance checking is not always simple; quoting Clements and Shaw: &lt;i&gt;"Many architectural patterns, fundamental to the system’s design taken forward into code, are undetectable once programmed. Layers, for instance, usually compile right out of existence."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The good news is that layers can be easily encoded in a DSM. While doing so, I would use an extension of the traditional yes/no DSM, as I've anticipated in a comment to the previous post. While the traditional DSM is basically binary (yes/no), in many cases we are better off with a ternary DSM. That way, we can encode three different decisions:&lt;br /&gt;&lt;b&gt;Yes-now&lt;/b&gt;: there is a dependency, and it's here, right now.&lt;br /&gt;&lt;b&gt;Not-now&lt;/b&gt;: there is no dependency right now, but it wouldn't be wrong to have one.&lt;br /&gt;&lt;b&gt;Never&lt;/b&gt;: adding this dependency would violate a fundamental design rule.&lt;br /&gt;&lt;br /&gt;A strong layered system requires some kind of isolation between layers. Remember &lt;a href="http://www.eptacom.net/blog/2008/12/notes-on-software-design-chapter-2-mass.html"&gt;gravity&lt;/a&gt;: new things are naturally attracted to existing things. &lt;br /&gt;Attraction is stronger in the direction of simplicity and lack of effort: if no effort is required to violate architectural integrity, sooner or later it will be violated. Sure, conformance checking may help, but it would be better to &lt;a href="http://www.eptacom.net/blog/2009/02/notes-on-software-design-chapter-4.html"&gt;set up the gravitational field&lt;/a&gt; so that things are naturally attracted to the &lt;i&gt;right&lt;/i&gt; place.&lt;br /&gt;&lt;br /&gt;The real issue, therefore, is the &lt;i&gt;granularity&lt;/i&gt; of the DSM for a layered system. Given the fractal nature of software, a DSM can be applied at any granularity level: between functions, classes, "logical" components, "physical" components. Unless your system is quite small, you probably want to apply the DSM at the component level, which also means your layers should appear at the component level.&lt;br /&gt;&lt;br /&gt;Note the distinction between logical and physical component. If you're working in a modern language/environment (like .NET or Java), creating a physical component is just a snap. Older languages, like C++, never got the idea of component into the standard, for a number of reasons; in fact, today this is one of the most limiting factors when working on large C++ system. In that case, I've often seen designer/programmers creating "logical" components out of namespaces and discipline. I've done that myself too, and it kinda works.&lt;br /&gt;&lt;br /&gt;Here is the catch: binary separation between physical components is stronger than the logical separation granted from using different namespaces, which in turn is stronger than the separation between two classes in the same namespace, which is much stronger than the separation between two members of the same class. &lt;br /&gt;More exactly, as we'll see in a forthcoming post, a binary component may act as a better &lt;b&gt;shield&lt;/b&gt; and provide stronger &lt;b&gt;isolation&lt;/b&gt;.&lt;br /&gt; &lt;br /&gt;If a binary component A uses binary component B, and B uses binary component C, but does not reveal so in its interface (that is, public/protected members of public classes in B do not mention types defined in C) A knows precious nothing about C. &lt;br /&gt;Using C from A requires that you discover C existence, then the existence of some useful class inside C. Most likely, to do so, you have to look inside B. At that point, adding a new service inside B might just be more convenient. This is especially true if your environment does not provide you with free indirect references (that is, importing B does not inject a reference to C "for free"). &lt;br /&gt;Here is again the interplay between good software design and properly designed languages: a better understanding of software forces could eventually help to design better languages as well, where violating a design rule should be harder than following the rule.&lt;br /&gt;&lt;br /&gt;Now, if A and B are logical components (inside a larger, physical component D), then B won't usually act as a shield, mostly because the real (physical) dependency will be placed between D and C, not between B and D. Whatever B can access, A can access as well, without any additional effort. The gravitational field of B is weaker, and some code might be attracted to A, which is not what the designer wanted.&lt;br /&gt;&lt;br /&gt;Therefore, inasmuch as your language allows you to, a physical component is always the preferred way to truly isolate one system from another.&lt;br /&gt;&lt;br /&gt;OK, this was quite simple :-). Next time, I'll go back to the concept of frequency and then move to isolation!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-8923924853999947066?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/8923924853999947066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=8923924853999947066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8923924853999947066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/8923924853999947066'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/12/little-more-on-dsm-and-gravity.html' title='A little more on DSM and Gravity'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-1514002329050980185</id><published>2009-10-21T16:25:00.003+02:00</published><updated>2009-10-21T16:37:05.978+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>The Dependency Structure Matrix</title><content type='html'>Design is about making decisions; diagrams encode &lt;b&gt;some&lt;/b&gt; of those decisions. Consider this simple component diagram:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/dep-dms1.png"/&gt;&lt;br /&gt;&lt;br /&gt;We have 3 "physical" components (e.g. DLLs) X, C, D. X is further partitioned in 2 logical components: in this real-world case, the designer used namespaces to identify separate logical components inside a single physical component. The designers is also telling us that A and B depends on D, B depends on C, C depends on D. So far, so good.&lt;br /&gt;&lt;br /&gt;UML diagrams, however, cannot easily convey some part of the reasoning. In a sense, to fully grasp the designer's intention, we have to understand not only what &lt;b&gt;is&lt;/b&gt; in the diagram, but also what is &lt;b&gt;not&lt;/b&gt; in the diagram. This may seem unusual, but is easily explained. Consider the picture above again. There is no dependency between A and C. Now, maybe A doesn't &lt;b&gt;currently&lt;/b&gt; need to access C (and therefore there is no dependency) but if we need to access C from A tomorrow, it's just fine to add a dependency. Or maybe the designer's intent was to shield A from C, possibly using B as a man-in-the-middle. &lt;br /&gt;That's not obvious from the diagram, and there is no place in the diagram to say that (not with a formal, standard UML syntax). Of course, good names may help. Replacing B with something more meaningful, maybe mentioning a bridge or proxy pattern, may suggest that A is not supposed to interact with C.&lt;br /&gt;&lt;br /&gt;Is there a better way? Maybe something that can be actually checked against code? Checking code compliance with diagrams may seem so &lt;i&gt;passe' &lt;/i&gt; or even plain absurd, given the current trend of discarding diagrams and/or reverse-engineering diagrams from code. Still, here is a real-world story:&lt;br /&gt;The design above (which is, of course, largely simplified) was handed out from the original designers-implementers to a larger (offshore) team. They explained some of the design rationale (informally), and after a while, they left the company. Months later, the offshore team needed a new service from C inside A, so they did the simplest thing that can possibly work: they called C from A. After all, A and B are inside the same physical component. Whatever B can do, A can do too.&lt;br /&gt;Unfortunately, a cornerstone of the original design was that A should never talk to C. The dependency was not in the diagram, because it was not supposed to exist, &lt;b&gt;ever&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The team manager knew that, but given the size of the real X (about 500 KLOC) she couldn't possibly review all the changes from the offshore team. Of course, at least someone in the offshore team didn't fully grasp the designer's intent.&lt;br /&gt;&lt;br /&gt;So, back to the original question: is there a better way? I could say "a forcefield diagram" :-), but in this specific case, there is also a well-known engineering tool: the Dependency Structure Matrix (also known as the Design Structure Matrix). A DSM encodes dependencies between "things". Not just dependencies, but also forbidden dependencies. See the following picture:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/dep-dms2.png"/&gt;&lt;br /&gt;&lt;br /&gt;The 5 green "Y" cells correspond to the 5 existing dependencies; the "N" cells correspond to the "missing" dependencies, but they say something more: that those dependencies are &lt;b&gt;forbidden&lt;/b&gt;. Now, this is a useful piece of information, something that can be easily checked against code. That does not mean that we can't change the design: it simply means we don't want to change the design inadvertently, just by typing in some code that was not supposed to be there. Checking code against the abstract design should just prompt a review; the design could be wrong, in which case, it should be changed (along with the DSM).&lt;br /&gt;&lt;br /&gt;There is some interesting literature about DSM in software, most from Baldwin and Clark of "Design Rules" fame, but also from others (like one I mentioned &lt;a href="http://www.eptacom.net/blog/2005/09/real-options-and-software-design.html"&gt;back in 2005&lt;/a&gt;). There are also quite a few tools to reverse-engineer a DSM from code, which makes checking code against the designed DSM relatively trivial (the bad side is that some languages, like C++, are notably hard to reverse engineer, so tools are lacking; Java and C# have both free and commercial tools available). I'm not aware of any UML tool that can generate a DSM from the diagrams, but that's theoretically trivial, and could even be built as a plug-in for some CASE tools.&lt;br /&gt;&lt;br /&gt;As usual, there is more to say about the DSM, gravity, and the forcefield. I'll save that for my next post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-1514002329050980185?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/1514002329050980185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=1514002329050980185' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1514002329050980185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/1514002329050980185'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/10/dependency-structure-matrix.html' title='The Dependency Structure Matrix'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4243899231002611073</id><published>2009-10-05T12:35:00.002+02:00</published><updated>2009-10-05T13:18:31.943+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>A ForceField Diagram</title><content type='html'>The Design Rationale Diagram I discussed in my previous post is hardly complete, and it could be vastly improved by asking slightly different questions, leading to different decision paths. Still, it's a reasonable first-cut attempt to model the decision process. It can be used to communicate the reasoning behind a specific decision, in a specific context.&lt;br /&gt;&lt;br /&gt;That, however, is not the way I &lt;i&gt;really&lt;/i&gt; think. Sure, I can rationalize things that way, but it's not the way I store, recall, organize information inside my head. It's not the way I &lt;i&gt;see&lt;/i&gt; the &lt;a href="http://www.eptacom.net/blog/2009/01/notes-on-software-design-chapter-3-mass.html"&gt;decision space&lt;/a&gt;.&lt;br /&gt;In the end, software design is about things going together and things staying apart, at all the granularity levels (see also my post on &lt;a href="http://www.eptacom.net/blog/2008/11/notes-on-software-design-chapter-1.html"&gt;partitioning&lt;/a&gt;).&lt;br /&gt;As I progress in my understanding of forces, I tend to form clusters. Clusters are born out of attraction and rejection inside the decision space. I've found that thinking this way helps me reach a better understanding of my design instinct, and to communicate my thoughts more clearly.&lt;br /&gt;&lt;br /&gt;Now, although I've been thinking about this for long while (not full-time, lucky me :-), I can't say I have found the perfect representation. The decision space in inherently multi-dimensional, and I always end up needing more dimensions that I can fit either in 2D or 3D. Over time, I tried several notations, inventing things from scratch or borrowing from other domains. Most were dead ends. In the end, I've chosen (so far :-) a very simple representation, based on just 3 concepts (possibly 4 or 5).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- nodes&lt;/b&gt;&lt;br /&gt;Nodes represent information, which is our material. Information has fractal nature, and I don't bother if I'm mixing up levels. Therefore, a node may represent a business goal, or the adoption of a tool or library, or a nonfunctional requirement, or a specific component, class, function. While most methods are based on a strict separation of concepts, I find that very limiting.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- an attraction relationship&lt;/b&gt;&lt;br /&gt;Nodes can attract each other. For instance, a node labeled "reliable" may attract a node labeled "redundant" when reasoning about the large display problem. I just connect the two nodes using a thick line with little "hands" on the ends. I place attracted nodes close to each other.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;- a rejection relationship&lt;/b&gt;&lt;br /&gt;Nodes can reject each other. For instance, stateful most clearly reject stateless :-). Some technology might be at odd with another. A subsystem must not depend on another. And so on. Nodes that reject each other are placed at some distance.&lt;br /&gt;&lt;br /&gt;It's all very simple and unsophisticated. Here is an example based on the large display problem, inspired by the discussion on design rationale:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/FF1.png"/&gt;&lt;br /&gt;&lt;br /&gt;and here are two diagrams I've used in real-world projects recently, scaled down to protect the innocent:&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/ffs1c.png"/&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/ffs2c.png"/&gt;&lt;br /&gt;&lt;br /&gt;The relationship between a node, a cluster, and an Alexandrian &lt;i&gt;center&lt;/i&gt; is better left for another time. Still, a node in one diagram may represent an entire cluster, or an entire diagram. Right now I'm tempted to use a slightly different symbol (which would be the fourth) to represent "expandable" nodes, although I'm really trying to keep symbols to a bare minimum. I'm also using colors, but so far in a very informal way.&lt;br /&gt;&lt;br /&gt;As simple as it is, I've found this diagram to be very effective as a &lt;i&gt;reasoning device&lt;/i&gt;, while too many diagrams end up being mere &lt;i&gt;documentation devices&lt;/i&gt;. I can sit in front of my (large :-) screen, think and draw, and the drawing helps me focus. I can draw this on a whiteboard in a meeting, and everyone get up to speed very quickly on what I'm doing.&lt;br /&gt;&lt;br /&gt;This, however, is just half the story. We can surely work with informal concepts and diagrams, and that's fine, but what I'm trying to do is to add &lt;i&gt;precision&lt;/i&gt; to the diagram. Precision is often confused with details, like "a class diagram is more precise if you show all the parameters and types". I'm not looking for that kind of "precision". Actually, I don't want this diagram to be redundant with code at all; we already have many code-like diagrams, and they all get down the same roads (generate code from diagrams or generate diagrams from code). I want a reasoning device: when I want to code, I'm comfortable with code :-).&lt;br /&gt;&lt;br /&gt;I mostly want to add precision about relationships. Why, for instance, is there an attraction between Slow Client and Stateful? Informally, because if we have a stateful system, the slow client can poll on its own terms, or alternatively, because the client may use a sophisticated subscription based on the previous state. Those options, by the way, could be represented on the forcefield diagram itself (adding more nodes, or a nested diagram); but that's still the "informal" reasoning. Can we make it any more formal, precise, grounded on sound principles?&lt;br /&gt;&lt;br /&gt;This is where the ongoing work on concepts like gravity, frequency, and so on kicks in. Slow Client and Stateful are attracted because on a finer granularity (another, perhaps better, diagram) "Slow Client" means a publisher and a subscriber operating at different frequencies, and a stateful repository is a well-known strategy (a pattern!) to provide &lt;b&gt;Isolation&lt;/b&gt; between systems operating at different frequencies (together with synchronization or transactions).&lt;br /&gt;&lt;br /&gt;Now, I haven't introduced the concept of Isolation yet (though I mentioned something on my Facebook page :-), so this is sort of a spoiler :-)), but in the end I hope to come up with a simple reasoning system, where you can start with informal concepts and refine nodes and forces until you reach the "universal", fractal forces I'm discussing in the "Notes on Software Design" posts. That would give a solid ground to the entire diagram.&lt;br /&gt;&lt;br /&gt;A final note on the forcefield diagram: at this stage, I'm just using Visio, or more exactly, I'm abusing some stencils in the Visio library. I wanted something relatively organic, mindmap-like. Maybe one day I'll move back to some 3D ideas (molecular structures come to mind), but I've yet to see how this scales to newer concepts, larger problems, and so on. If you want to play with it, I can send you the VSS file with the stencils.&lt;br /&gt;&lt;br /&gt;Ok, I'll get back to Frequency (and Interference and Isolation and more :-) soon. Before that, however, I'd like to take a diversion on the Dependency Structure Matrix. See ya!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4243899231002611073?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4243899231002611073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4243899231002611073' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4243899231002611073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4243899231002611073'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/10/forcefield-diagram.html' title='A ForceField Diagram'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-3742134168743522721</id><published>2009-08-31T18:11:00.002+02:00</published><updated>2009-10-05T10:52:44.344+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Representing Design Rationale Inside Activity Diagrams</title><content type='html'>Design is about making choices. We often do so on the fly, leaning on experience and intuition, by talking about the problem with colleagues, or borrowing from literature (e.g. patterns). We also make some choice by &lt;i&gt;habit&lt;/i&gt;, which is a different form of experience, one that has higher risk of becoming disconnected with the real problem. &lt;br /&gt;Most of this process is tacit, and even when we discuss choices openly, it doesn't get recorded. Sometimes, a list of pros/cons is made when there is some disagreement about the best option.&lt;br /&gt;&lt;br /&gt;This all works well when the problem is simple, but sometimes even experienced designers feel like they're not grasping the &lt;i&gt;essential issues&lt;/i&gt;, that something has not yet been found, named, disentangled. This is when having yet one more tool can prove useful.&lt;br /&gt;Now, I don't usually go through the effort to model and transcribe the rationale behind each and every design choice I make. It could be interesting, also from a pedagogical point of view, but it would take a lot of time and would probably disrupt my thought processes. However, when the issues are particularly thorny/unclear,  or when there is a large disagreement on the best choice (or even on the goals and criteria), I've found that getting design rationale out of our individual heads and talk on a shared representation can move things a little forward.&lt;br /&gt;&lt;br /&gt;Over the years, I've tried out a number of tools, approaches, and so on; lately, I've tried using Activity Diagrams in a rather unorthodox way, to represent my reasoning about design, not design itself. The idea is &lt;b&gt;not&lt;/b&gt; to encode your decisions ex-post, but ex-ante, while you're thinking (that is, while they're still options, not decisions). Also, the diagram must be considered quite fluid, as it shows our current understanding, and we're building the diagram to improve our understanding.&lt;br /&gt;&lt;br /&gt;Enough talk, let's see a realistic example. I'll refer to the &lt;a href="http://www.eptacom.net/blog/2008/10/some-small-design-issues-part-1.html"&gt;Large Display&lt;/a&gt; problem I discussed a few months ago. Actually, I'll just cover the initial choice between using a real-time database or an IPC/messaging system. It's gonna be quite a mouthful anyway! &lt;br /&gt;&lt;br /&gt;To start, I'll have to draw a line between a messaging system and a RTDB, and that in itself is not easy. I'll go for a very simple distinction, because my goal here is not really to talk about RTDBs, but about design rationale (the usual "look at the moon, not at the finger" concept). &lt;br /&gt;So, consider a control system that reads some data from the field and then needs to publish those data for other processes. It could just send data through a messaging (publish/subscribe) system. Here I define a messaging system as &lt;i&gt;stateless&lt;/i&gt;, meaning it simply keeps track of subscriptions, and sends everything that is published to the subscribers (according to some criteria, like message type or tag). It does not keep an history, or a snapshot of what has been last sent. Therefore, it cannot apply some filters, like "notify me only if the difference between the previous value and the current value is above a threshold" because the previous value is just not stored. Also, when a subscriber is started, it cannot get the current snapshot of the system, because it is not there: it will have to wait for messages to come, incrementally. Shortly stated, a RTDB will keep a snapshot of the system, and well, you can figure out the difference. Of course, a RTDB is also more complex.&lt;br /&gt;&lt;br /&gt;So, how do we choose between a messaging system and a RTDB? We may write down a long list of pro/cons, but that's really unstructured, and that's not the way our brain works. To provide more structure, I use an Activity Diagram with orthogonal swimlanes (all the following pictures are taken from &lt;a href="http://staruml.sourceforge.net/" target="_new"&gt;Star UML&lt;/a&gt;, a free tool that is rather fast and unobtrusive). &lt;br /&gt;The vertical swimlanes are flexible: they represent the main concerns. The horizontal swimlanes are fixed: they provide structure.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/DRTemplate.png"&gt;&lt;br /&gt;For the Large Display problems, we could start with a few main concerns like performance, reliability, cost, and so on. We just drop the names on the vertical swimlanes. My template is then partitioned in 3 horizontal bands: the root question, the reasoning, the outcome. Everything inside is dynamic, and changes as we understand more: even the root questions may change, as we discover larger or smaller, independent problems. Sometimes, even the main concerns change, as we discover options or issues we didn't consider before.&lt;br /&gt;&lt;br /&gt;We can focus on just one concern right now, let's say performance (don't we all like performance? :-). A first-cut, interesting top-level question could be: is the published data rate high or low? If the rate is low and we have no persistent state, when you turn on the large display you see nothing: you have to wait till some data gets published. On the other hand, if the rate is high, it may even overwhelm the display system: there is little need to refresh a value a thousand times per second. That actually depends on the display: if it's a real-time plot, you may want a high refresh rate too.&lt;br /&gt;&lt;br /&gt;Ok, we could start modeling this part of our reasoning using the familiar activity diagram symbols. Actually, since most of the nodes here would be decision nodes, I just omit the diamond and use an activity node with multiple outgoing paths to show choices.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/DR1.png"&gt;&lt;br /&gt;Note: The empty boxes are just placeholders for some later reasoning. It's just laziness on my side :-) and they wouldn't appear in a real diagram.&lt;br /&gt;&lt;br /&gt;Now, this seems just like a decision tree, but it's slightly different. First, it's a decision &lt;b&gt;graph&lt;/b&gt;: common choices between paths are shared, and this is a precious information because it shows crucial choices (more on this later). Second, it's a multifaceted graph: every vertical swimlane shows a facet of a more complex reasoning; for instance, what is good for performance might not be good for reliability or cost.&lt;br /&gt;&lt;br /&gt;Let's try to move ahead a little. When the incoming data rate is higher than what [most] clients need, we have basically two choices:&lt;br /&gt;1) smarter subscriptions; they could still be rather dumb, like "no more than 3 times per second" or much smarter like "when relative change is higher than 5%, but no more than 5 times per second". Note that the latter is more suited to a RTDB than to a stateless messaging system.&lt;br /&gt;2) change paradigm and move to client-initiated polling. The clients will ask for data with their own timing. Of course, at this point we give up the possibility of not asking for data if the value has not changed. Anyway, this again requires some kind of &lt;i&gt;stateful&lt;/i&gt; middleware; a messaging system won't do.&lt;br /&gt;When data rate is low, but high startup time for clients is not an option, we can't wait for data to come: we have to poll, at least at startup. So, polling can solve two problems, of course at expense of bandwidth if it is the &lt;i&gt;only&lt;/i&gt; available option.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/DR2.png"&gt;&lt;br /&gt;&lt;br /&gt;While drawing this, we may come to the conclusion that we need to ask better questions: are we building a publisher-driven or a client-driven system? If it's client-driven, it cannot be stateless! What do we really know about clients? How many there will be? What about publishers? What is the typical data rate and configuration? What are we aiming for? Do we need to narrow the expectations? This might change the top question (client Vs. publisher driven) or even some concern. That's fine, it means the technique is working :-) and that it's helping us thinking.&lt;br /&gt;&lt;br /&gt;Now, it would take quite a lot of time to explore all the facets of even a simple system like this. Actually, most people won't even do it in real life: they will fall in love with one idea, spend most of their time preaching and rationalizing about the virtues of their idea, and never really take the time to go through this kind of process. Still, trying to work out the "Reliability" swimlane would prove interesting. For instance, a common technique to achieve reliability is redundancy. Redundancy is much easier for a stateless system. Redundancy is easier when clients don't have to subscribe at all, but can simply poll. And so on. If you have some spare time, you may want to give it a try.&lt;br /&gt;&lt;br /&gt;The notation I use is quite informal. I could improve that easily: UML is fairly flexible; so far I didn't, because people can grasp it anyway, even when I drop in the &lt; &lt; or &gt; &gt; to represent options or when I have just one arrow coming out, meaning that I've just decomposed a choice and a consequence. It's just a reasoning workflow, and I haven't felt the need to make it any more precise than that.&lt;br /&gt;&lt;br /&gt;Back to the forcefield: the rationale &lt;b&gt;is not&lt;/b&gt; the forcefield. The rationale, however, is talking about forces and centers. Outcomes (messaging and RTDB) are centers. Main choices, like "client driven" or "stateless", are again centers. Those centers are attracting or rejecting each other. This is the forcefield. This is closer to the way I think in the back of my mind, how I "see" the system, how I keep options open. Now, I just need a way to show this. That's for my next post :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-3742134168743522721?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/3742134168743522721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=3742134168743522721' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3742134168743522721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/3742134168743522721'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/08/representing-design-rationale-inside.html' title='Representing Design Rationale Inside Activity Diagrams'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-6876032002823951046</id><published>2009-07-08T09:43:00.005+02:00</published><updated>2009-10-05T10:49:16.058+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quote'/><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='link'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='book reference'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>When in doubt, do the right thing</title><content type='html'>The bright side of spending most of my professional time on real-world projects is that I have an endless stream of inspiration, and what is even more important, the possibility of trying out new ideas, concepts, and methods. The dark side is that the same source of inspiration is taking away the precious time I would need to encode, structure, articulate knowledge, that therefore remains largely implicit, tacit, intuitive. The pitch black side is that quite often I'd like to share some real-world story, but I can't, as the details are kinda classified or just to protect the innocent. Sometimes, however, the story can be told with just a little camouflage.&lt;br /&gt;&lt;br /&gt;Weeks ago, I was trying to figure out the overall architecture of a new system, intended to replace an obsolete framework. I could see a few major problems, two of which were truly hard to solve without placing a burden on everyone using the framework. Sure, we had other details to work out, but I could see no real showstoppers except for those two. The project manager, however, didn't want to face those problems. She wanted to start with the easy stuff, basically re-creating structures she was familiar with. I tried to insist about the need to figure out an overall strategy first, but to no avail. She wanted progress, right here, right now. That was a huge mistake.&lt;br /&gt;&lt;br /&gt;Now, do not misunderstand me: I'm not proposing to stop any kind of development before you work every tiny detail out. Also, in some cases, the only real way to understand a system is by building it. However, building the &lt;b&gt;wrong&lt;/b&gt; parts first (or in this case, building the easy parts first) is always a big mistake. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Expert designers know that in many cases, you have to face the most difficult parts early on&lt;/i&gt;. Why? Because if you do it too late, you won't have the same options anymore; previous decisions will act like constraints on late work.&lt;br /&gt;&lt;br /&gt;Diomidis Spinellis has recently written a very nice essay on this subject (IEEE Software, March/April 2009). Here is a relevant quote: &lt;i&gt;On a blank sheet of paper, the constraints we face are minimal, but each design decision imposes new restrictions. By starting with the most difficult task, we ensure that we’ll face the fewest possible constraints and therefore have the maximum freedom to tackle it. When we then work on the easier parts, the existing constraints are less restraining and can even give us helpful guidance.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I would add more: even if you take the agile stance against upfront design and toward emergent design, the same reasoning applies. If you start with the wrong part, the emergent design will work against you later. Sure, if you're going agile, you can always refactor the whole thing. But this reasoning is faulty, because in most cases, the existing design will also limit your creativity. It's hard to come up with new, wild ideas when those ideas conflict with what you have done up to that moment. It's just human. And yeah, agile is about humans, right? :-)&lt;br /&gt;&lt;br /&gt;Expert designer start with the hard parts, but beginners don't. I guess I can quote another nice work, this time from Luke Hohmann (Journey of the Software Professional - a Sociology of Software Development): &lt;i&gt;Expert developer's do tend to work on what is perceived to be the hard part of the problem first because their cognitive libraries are sufficiently well developed to know that solving the "hard part first" is critical to future success. Moreover, they have sufficient plans to help them identify what the hard part is. Novices, as noted often fail to work on the hard-part-first for two reasons. First, they may not know the effectiveness of the hard part first strategy. Second, even if they attempt to solve the hard part first, they are likely to miss it.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Indeed, an expert analyst, or designer, knows &lt;i&gt;how to look&lt;/i&gt; at problems, how to find the best &lt;i&gt;questions&lt;/i&gt; before looking for answers. To do this, however, we should relinquish preconceived choices. Sure, experts bring experience to the table, hopefully in several different fields, as that expands our library of mental plans. But (unlike many beginners) we don't approach the problem with pre-made choices. We first want to learn more about the forces at play. Any choice is a constraint, and we don't want artificial constraints. We want to approach the problem from a clean perspective, because freedom gives us the opportunity to choose the best &lt;i&gt;form&lt;/i&gt;, as a mirror of the forcefield. By the way, that's why zealots are often mediocre designers: they come with too many pre-made choices, or as a Zen master would say, with a &lt;a href="http://earthsgreatawakening.com/2009/05/30/zen-stories-the-full-cup/" target="_new"&gt;full cup&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Of course, humans being humans, it's better &lt;b&gt;not&lt;/b&gt; to focus exclusively on the hard stuff. For instance, in many of my design sessions with clients, I try to focus on a few simple things as we start, then dig into some hard stuff, switch back to something easy, and so on. That gives us a chance to take a mental break, reconsider things in the back of our mind, and still make some progress on simpler stuff. Ideally, but this should be kinda obvious by now, the easy stuff should be chosen to be as independent/decoupled as possible from the following hard stuff, or we would be back to square one :-).&lt;br /&gt;&lt;br /&gt;In a sense, this post is also about the same thing: writing about some easy stuff, to take a mental break from the more conceptual stuff on the forcefield. While, I hope, still making a little progress in sharing some useful design concept. See you soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-6876032002823951046?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/6876032002823951046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=6876032002823951046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6876032002823951046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/6876032002823951046'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/07/when-in-doubt-do-right.html' title='When in doubt, do the right thing'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4033404125447723993</id><published>2009-06-09T14:34:00.001+02:00</published><updated>2010-06-24T16:13:33.283+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Design Rationale</title><content type='html'>In the past few weeks I've taken a little time to write down more about the concept of frequency; while doing so, I realized I had to explore the concept of forcefield better, and while doing so (yeap :-)) I realized there was a rather large overlap between the notion of forcefield and the notion of &lt;i&gt;design rationale&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Design_Rationale" target="_new"&gt;Design rationale&lt;/a&gt; extends beyond software engineering, and aims to capture design decisions and the reasoning behind those decisions. Now, design decisions are (ideally) taken as trade-offs between several competing forces. Those forces creates the forcefield, hence the large overlap between the two subjects.&lt;br /&gt;&lt;br /&gt;The concept of design rationale has been around for quite a few years, but I haven't seen much progress either in tools or notations. Most often, tools fall into the “rationalize after the fact” family, while I'm more interested in &lt;i&gt;reasoning tools and notations&lt;/i&gt;, that would help me (as a designer) get a better picture about my own thoughts &lt;i&gt;while I'm thinking&lt;/i&gt;. That resonates with the concept of &lt;i&gt;reflection in action&lt;/i&gt; that I've discussed in &lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/ListenToYourToolsAndMaterials.pdf"&gt;Listen to Your Tools and Materials&lt;/a&gt; a few years ago.&lt;br /&gt;&lt;br /&gt;So, as I was reading a recent issue of IEEE Software (March/April 2009), I found a list of recent (and not so recent) tools dealing with design rationale in a paper by Philippe Kruchten, Rafael Capilla, Juan Carlos Dueñas (&lt;i&gt;The Decision View’s Role in Software Architecture Practice&lt;/i&gt;), and I decided to take a quick ride. Here is a very quick summary of what I've found.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.users.muohio.edu/burgeje/SEURAT" target="_new"&gt;Seurat&lt;/a&gt;&lt;br /&gt;Seurat (see also the PDF tutorial on the same website) is based on a very powerful language / model, but the tool (as implemented) is very limiting. It's based on a tree structure, which makes for a nice todo list, but makes visual reasoning almost impossible. Actually, in the past I've investigated on using the tree format myself (and while doing so, I discovered others have done the same: see for instance the &lt;a href="http://c2.com/cgi/wiki?ReasoningTree" target="_new"&gt;Reasoning Tree&lt;/a&gt; pattern), but restricting visualization to (hyperlinked) nodes in a tree just does not work when you're facing difficult problems.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sysiphus.informatik.tu-muenchen.de" target="_new"&gt;Sysiphus&lt;/a&gt;&lt;br /&gt;Sysiphus seems to have recently morphed into another tool (UniCase), but from the demo of UniCase it's hard to appreciate any special support for design rationale (so far).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ict.swin.edu.au/personal/atang/" target="_new"&gt;AREL&lt;/a&gt;&lt;br /&gt;(see also some papers from Antony Tang on the same page; Antony also had an excellent paper on AREL in the same issue of IEEE Software)&lt;br /&gt;AREL is integrated with Enterprise Architect. Integration with existing case tools (either commercial or free) seems quite a good idea to me. AREL uses a class diagram (through a UML profile) to model design rationale, so it's not limited to a tree format. Still, I've found the results rather hard to read. It seems more like a tool to give structure to design knowledge than a tool to reason about design. As I go through the examples, I have to &lt;i&gt;study&lt;/i&gt; the diagram; it doesn't just &lt;i&gt;talk back&lt;/i&gt; to me. I have to click around and look at other artifacts. The reasoning is not in the diagram, it's only accessible through the diagram. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://193.1.97.13:8080" target="_new"&gt;PAKME&lt;/a&gt;&lt;br /&gt;Honestly, PAKME seems more like an exercise in building a web-based collaboration tool for software development than a serious attempt at providing a useful / usable tool to record design rationale. It does little more than organize artifacts, and it requires so many clicks / page refresh to get anything done that I doubt a professional designer could ever use it (sorry guys).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://triana.escet.urjc.es/ADDSS" target="_new"&gt;ADDSS&lt;/a&gt;&lt;br /&gt;ADDSS is very much like PAKME, although it adds a useful Patterns section. It's so far from what I consider a useful design tool (see my paper above for more) that I can't really think of using it (sorry, again).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://search.cs.rug.nl/griffin" target="_new"&gt;Knowledge Architect&lt;/a&gt;&lt;br /&gt;Again, a tool with some good ideas (like Word integration) but far from what I'm looking for. It's fine to create a structured design document, but not to reason about difficult design problems.&lt;br /&gt;&lt;br /&gt;In the end, it seems like most of those tools suffer from the same problems:&lt;br /&gt;- The research is good; a nice metamodel is built, some of the problems faced by professional designers seem to be well understood.&lt;br /&gt;- The tool does little more than organize knowledge, would get in the way of the designer thinking about thorny issues, does not help through visualization, and is at best useful at the end of the design process, possibly to &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.8358&amp;rep=rep1&amp;type=pdf" target="_new"&gt;fake some rationality&lt;/a&gt;, a-la Parnas/Clements.&lt;br /&gt;&lt;br /&gt;That said, AREL is probably the most promising tool of the pack, but in the end I've being doing pretty much the same for years now, using (well, abusing :-) plain old use case diagrams to model goals and issues, with a few ideas taken from KAOS and the like. &lt;br /&gt;&lt;br /&gt;Recently, I began experimenting with another standard UML diagram (the activity diagram) to model some portion of design reasoning. I'll show an example in my next post, and then show how we can change our perspective and move from design reasoning to the forcefield.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4033404125447723993?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4033404125447723993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4033404125447723993' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4033404125447723993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4033404125447723993'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/06/design-rationale.html' title='Design Rationale'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4733483014195720005</id><published>2009-06-02T11:49:00.003+02:00</published><updated>2009-06-02T12:19:52.790+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Good Design</title><content type='html'>I rarely (if ever) blog about technology, mostly because once you cut the marketing cr@p, consumer technology is often &lt;i&gt;so moot&lt;/i&gt;. Still, a few days ago I read about &lt;a href="http://dsonline.computer.org/portal/cms_docs_computer/computer/homepage/Apr09/r4bri.pdf" target="_new"&gt;local dimming&lt;/a&gt; in the news section of IEEE Computer. A good designer should be quick to spot good (or intriguing) design, and that idea struck me as an excellent use of technology.&lt;br /&gt;&lt;br /&gt;It's also interesting to look at it from a forcefield perspective. CCFLs had several drawbacks as light sources for LCD displays. Some of those issues have been resolved using LED backligthing instead, but if we stop there, we're just using new technology to solve the &lt;i&gt;exact same problem&lt;/i&gt; we solved with yesterday's technology. That's usually the wrong approach, as the old technology was part of a larger design, a larger forcefield, and it managed to resolve only &lt;i&gt;some&lt;/i&gt; of those forces.&lt;br /&gt;&lt;br /&gt;Back to local dimming, the idea is amazingly simple from the forcefield perspective: instead of using lamps for ligthing and LCD for contrast, color, etc, split some of the work between the LEDs and the LCD. This can be done because once we introduce a LED matrix, the forcefield itself changes. This has long been known: when we introduce technology, we can even change &lt;i&gt;the problem itself&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Of course, we face similar issues in software all the time. I wrote something along the same lines in IEEE Software back in 1997 (&lt;a href="http://www.eptacom.net/pubblicazioni/pub_eng/probsol.pdf"&gt;When Past Solutions Cause Future Problems&lt;/a&gt;). I wasn't talking forcefield back then, but the "ask why" suggestion is very much forcefield friendly. More on this shortly, as I'm trying to catch up with many ideas I didn't have time to blog about, and write them down in small chunks...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4733483014195720005?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4733483014195720005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4733483014195720005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4733483014195720005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4733483014195720005'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/06/good-design.html' title='Good Design'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-2569981593837963606</id><published>2009-05-10T16:24:00.003+02:00</published><updated>2009-05-10T16:55:36.368+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='article reference'/><title type='text'>Interesting paper</title><content type='html'>While looking for something else, I stumbled on a paper with an intriguing title: &lt;a href="http://se.cs.toronto.edu/IWLU/papers/Ambiguity_Garcia.pdf" target="new"&gt;The Ambiguity Criterion in Software Design&lt;/a&gt; by Álvaro García and Nelson Medinilla.&lt;br /&gt;&lt;br /&gt;I encourage readers interested in the concepts of design and form to take a look. Although I don't really like the term "ambiguity" (it makes for a catchy title, but it's commonly used with quite a different semantics) I think the paper is dealing with an interesting, pervasive attribute of software.&lt;br /&gt;&lt;br /&gt;If you have read my previous posts on software design, you may recognize (although not spelled that way) the [almost] fractal nature of "ambiguity". Actually, as I spoke of "n-degrees of separation" in a &lt;a href="http://www.eptacom.net/blog/2009/03/notes-on-software-design-chapter-5.html"&gt;previous post&lt;/a&gt;, I had some overlapping concepts in mind. Curiously enough, subtyping is also mentioned in another article I've &lt;a href="http://www.eptacom.net/blog/2008/04/asymmetry.html" target="new"&gt;recommended time ago&lt;/a&gt; about symmetry and symmetry breaking.&lt;br /&gt;&lt;br /&gt;I think there is something even more primitive than that at play here, something more fractal in nature, something that has to do with names and identities or (as the authors note) abstractions and instances. I also mentioned a problem with compile-time names in the post above, so there is a lot of stuff pointing the same direction! &lt;br /&gt;&lt;br /&gt;I have to think more about that, but first I'll have to write down what's left about &lt;i&gt;frequency&lt;/i&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-2569981593837963606?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/2569981593837963606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=2569981593837963606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2569981593837963606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/2569981593837963606'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/05/interesting-paper.html' title='Interesting paper'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-4758968945930808518</id><published>2009-05-01T19:51:00.004+02:00</published><updated>2009-05-02T08:28:31.278+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='GUI'/><title type='text'>Einstellung</title><content type='html'>As I mentioned in previous posts, one of the projects I've been recently involved with is a complete rewriting of the GUI layer for a rather large system. We want to move from an MFC-based framework to .NET, mostly to improve productivity. &lt;br /&gt;Initially, we'll basically move the GUI as-is, without re-designing the human-computer interaction. Therefore, it would pay to recover as much information as possible from the existing system, and do it automatically.&lt;br /&gt;&lt;br /&gt;Among other things, we have about 250 dialog boxes to port, so I thought it would be a good idea to write a translator from the Win32 RC format to whatever new format we need. This way, we can recover layout (positioning and sizes) and also translate each control to their nearest equivalent.&lt;br /&gt;&lt;br /&gt;That means, of course, that we know the target, and today, the .NET game boils down to choosing between Windows Forms and WPF. The choice is rather hard, althogh I know many programmers would jump immediately on the WPF bandwagon. Anyway, as we discussed the translator above, the project manager observed that WinForms stores everything in code. If we ever have to do this kind of change again, she said, we will miss the simplicity of RC. XAML would make layout and controls easier to move to another technology, just as RC.&lt;br /&gt;&lt;br /&gt;That's true; I don't particularly like the idea of having to parse C# to recover layout information, control initialization parameters, and so on.&lt;br /&gt;&lt;br /&gt;Funny thing is, for a while I got trapped in this parsing concept. I guess it has to do with education. Any computer scientist will recognize this as a parsing and translation problem. It's a well known problem frame. And that calls for a parser, of course :-).&lt;br /&gt;&lt;br /&gt;It took me a while to realize I didn't have to write a parser at all: I could just use reflection! To test the idea, I wrote a simple C# program (about 60 lines of code) which takes a form and recursively dumps layout and initialization parameters in an XML format.&lt;br /&gt;&lt;br /&gt;For instance, given this form:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.eptacom.net/blog/WinFormsToXml.png"/&gt;&lt;br /&gt;&lt;br /&gt;where the blue rectangle is a panel, and the label and button are nested controls, I'll get &lt;a href="http://www.eptacom.net/blog/WinFormsToXml.xml" target="_new"&gt;this XML&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The idea is pretty simple: I dump every property without a Browsable(false) attribute, that is, everything that you can change at design-time. If the Controls collection is not empty, I'll recurse into it. The nice part is that it could be made to work also for dynamic controls, created at run-time and not a design-time. Just call the translator after all the controls have been created, and that's it.&lt;br /&gt;&lt;br /&gt;Things could be easily improved. Right now, I don't handle collections (see bindings), non-visual components, and I dump every single property. It would be useful, perhaps, to dump only values that have been changed. That's easy, just create a control of the same class on the fly, and check for differences. Piece of cake.&lt;br /&gt;&lt;br /&gt;Now, I wish I could say I thought of this through my understanding of the forcefield :-). But I can't. It just came to me. Dunno how. The problem, of course, is moving past the &lt;a href="http://www.eptacom.net/blog/2006/01/functional-fixedness-and-einstellung.html"&gt;Einstellung effect&lt;/a&gt; of education. What can I say? Keep your mind open, practice lateral thinking, never give up :-). And yeah, well, keep an eye on that forcefield, as that may help too...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13967713-4758968945930808518?l=www.carlopescio.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.carlopescio.com/feeds/4758968945930808518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13967713&amp;postID=4758968945930808518' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4758968945930808518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13967713/posts/default/4758968945930808518'/><link rel='alternate' type='text/html' href='http://www.carlopescio.com/2009/05/einstellung.html' title='Einstellung'/><author><name>Carlo.Pescio</name><uri>http://www.blogger.com/profile/12652284939993729858</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13967713.post-3433539828695199082</id><published>2009-04-26T20:08:00.002+02:00</published><updated>2009-04-26T20:13:16.574+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profession'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='book reference'/><title type='text'>Bad Luck, or "fighting the forcefield"</title><content type='html'>In my previous post, I used the expression "fighting the forcefield". This might be a somewhat uncommon terminology, but I used it to describe a very familiar situation: actually, I see people fighting the forcefield all the time. &lt;br /&gt;&lt;br /&gt;Look at any troubled project, and you'll see people who made some wrong decision early on, and then stood by it, digging and digging. Of course, any decision may turn out to be wrong. Software development is a knowledge acquisition process. We often take decisions without knowing all the details; if we didn't, we would never get anything done (see &lt;a href="http://en.wikipedia.org/wiki/Analysis_paralysis" target="_new"&gt;analysis paralysis&lt;/a&gt; for more). Experience should mitigate the number of wrong decisions, but there are going to be mistakes anyway; we should be able to recognize them quickly, backtrack, and take another way.&lt;br /&gt;&lt;br /&gt;Experience should also bring us in closer contact with the forcefield. Experienced designers don't need to go through each and every excruciating detail before they can take a decision. As I said earlier, we can almost &lt;i&gt;feel&lt;/i&gt;, or &lt;i&gt;see&lt;/i&gt; the forcefield, and take decisions based on a relatively small number of prevailing forces (yes, I dare to consider myself an experienced designer :-). &lt;br /&gt;This process is largely unconscious, and sometimes it's hard to rationalize all the internal reasoning; in many cases, people expect very argumentative explanations, while all we have to offer on the fly is &lt;b&gt;aesthetics&lt;/b&gt;. Indeed, I'm often very informal when I design; I tend to use colorful expressions like "oh, that sucks", or "that brin
