<?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-5654876</id><updated>2012-02-01T14:34:55.090+02:00</updated><category term='wcf'/><category term='socialism'/><category term='scientists'/><category term='logic'/><category term='programming'/><category term='information'/><category term='puzzle'/><category term='philosophy'/><category term='Java'/><category term='computers'/><category term='creationism'/><category term='c#'/><category term='copyright'/><category term='economics'/><category term='excel'/><category term='clean code'/><category term='probabilities'/><category term='reliability'/><category term='religion'/><category term='OOP'/><category term='hoax'/><category term='mathematics'/><category term='Christianity'/><category term='fanfiction'/><category term='tdd'/><category term='writing'/><category term='911'/><category term='rant'/><title type='text'>Marcel Popescu</title><subtitle type='html'>Stuff I care about</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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>82</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5654876.post-6187624067025980532</id><published>2012-02-01T14:34:00.000+02:00</published><updated>2012-02-01T14:34:55.098+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Taking a walk</title><content type='html'>[Inspired by &lt;a href="http://lifeistheteacher.wordpress.com/2012/01/07/my-only-experience-in-a-public-high-school-and-a-call-to-action/"&gt;http://lifeistheteacher.wordpress.com/2012/01/07/my-only-experience-in-a-public-high-school-and-a-call-to-action/&lt;/a&gt;]&lt;p&gt;Frank was walking around, window-shopping while waiting for the time to come to perform at the near middle school. He was a sixteen-year old guitarist who was visiting a friend and got an offer to perform on a Friday in the friend's class. Frank was homeschooled so classes bored him to tears; he preferred to discover what was interesting in this part of the town instead of listening to a teacher drone about a subject he had absolutely no interest in.&lt;p&gt;Unfortunately, close to the time he was actually preparing to go back to the school, he got stopped by two cops who started asking questions about who he was and what he was doing there. It was clear they believed him to be a truant student but even so, Frank thought, why was it their business?&lt;p&gt;"I'm a musician; I'm performing at the school here in about half an hour."&lt;p&gt;"Right, kid, pull the other one," one of the cops said.&lt;p&gt;Frank was surprised at the disrespect. "Why do you assume I'm lying? And why is it your business anyway?"&lt;p&gt;"Kid, if I want your opinion I'll give it to you. Where do you live?"&lt;p&gt;Frank narrowed his eyes. He was starting to get pissed off. "I don't like how you guys behave. Is this your understanding of ‘protect and serve'? I'm a citizen minding my own business; please mind your own." Frank was not going to start anything, but if they annoyed him too much he was going to defend himself.&lt;p&gt;"Kid," the second cop said, "I think you need some time in jail to cool down. Put your hands behind your head and turn around."&lt;p&gt;Frank ignored his order. "So you think that might makes right, huh? You can force me to do what you want and that makes it ok? If I could kill you, would that be ok too?"&lt;p&gt;Both cops put their hands on their guns. "Is that a threat?"&lt;p&gt;Frank blinked. "Wow, you're stupid even for a cop. Yes, it's a threat."&lt;p&gt;"That's it!" one of them barked, pulling out his gun. "Hands behind your head, now; you're under arrest."&lt;p&gt;Frank ignored him once again. "Last chance; cool down and leave or this is the last time you're bullying anyone." He could feel the energy gathering around him and knew that his eyes would soon start to glow. From the descriptions of those who really knew him and what he could do, he knew that would look awesome and scary at the same time.&lt;p&gt;One of the cops grabbed his shoulder and tried to turn him around. Frank turned his head to look at him and touched him back. Everything went nuts as the cop's arm burst into flames.&lt;p&gt;The other cop had not pulled his gun before; he did now and shot at Frank. Frank switched his attention from the first cop, who was now screaming his throat raw, and started moving towards the second. The cop kept shooting and backing off, throwing his gun at Frank when the slide locked back. "What are you?" he screamed.&lt;p&gt;"A kid, I think you called me," Frank replied calmly, still moving towards him. "I just hate bullies. Have you learnt your lesson? Are you going to stop annoying peaceful people? On second thought," he continued without waiting for a reply, "I don't think I trust you." He pointed his finger at the cop who started screaming in fear, expecting to share his colleague's fate. "Might does not make right," he thundered, "but I'm not against using one's opinions against him. Don't make me come after you."&lt;p&gt;With that, Frank disappeared. A few seconds later, the fire that had by now engulfed the first cop completely went out and his skin started to heal. He was back to normal in less than a minute.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6187624067025980532?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6187624067025980532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6187624067025980532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6187624067025980532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6187624067025980532'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2012/02/inspired-by-httplifeistheteacher.html' title='Taking a walk'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4018806552743639919</id><published>2012-01-10T13:53:00.000+02:00</published><updated>2012-01-11T01:08:56.271+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Conquest</title><content type='html'>&lt;p&gt;"Do not be afraid."&lt;p&gt;David jumped around, his body flush with adrenaline. He had been alone in the room, or at least that's what he thought. Fortunately, he had managed to put his pants on.&lt;p&gt;"Who are you?" he managed. Someone was there, in the room, on the other side of the bed from him. He couldn't understand how he got past the agents outside.&lt;p&gt;"My name is Ra'ken," the man said. "We need to talk."&lt;p&gt;"How did you get here?" David asked, trying to decide whether shouting would be a good idea.&lt;p&gt;"I will explain. Please finish dressing and then we can go outside so you can feel safer. I did not mean to scare you."David felt a bit ridiculous but he was old enough to know that just because someone tells you they don't want to harm you it doesn't mean it's true. He finished putting a shirt on. "Shall we?" he asked, turning his head back to the other man.&lt;p&gt;"After you," the man said.&lt;p&gt;David opened the door. The three agents stopped talking and turned their heads to him. "POTUS is up," one of them announced, letting everyone in the White House know that the day had started.&lt;p&gt;Five seconds later, all hell broke loose. David had made it to the middle of the room when Ra'ken followed him. As soon as one of the agents saw him he shouted "Stop! Identify yourself!" and pulled his gun. Ra'ken stopped and lifted his hands a bit.&lt;p&gt;"Wait," David said. He took his first good look at Ra'ken. The man, though he was starting to feel like that wasn't the case, was very tall - over seven feet. He had a long face and long, blond hair. "Are you an elf?" David asked before he could control himself.&lt;p&gt;"I have been called that, yes," Ra'ken answered. "I mean you no harm," he continued, looking at everyone in the room.&lt;p&gt;"Ok, first things first," David said. "How did you get here? In my room?"&lt;p&gt;"Magic," Ra'ken answered.&lt;p&gt;"Please be serious," David protested.&lt;p&gt;Ra'ken lifted his right hand with the palm up. A small globe of fire formed over it.David felt for the chair behind him and sat down. "What the hell?" he managed. The globe was still burning. "Are you seeing that too?" he asked the agents, who nodded back. He had to admire them, they seemed unmoved by the scene - all of them were still pointing their guns at the intruder.&lt;p&gt;Ra'ken closed his hand and the globe disappeared. "We need your help," he said.&lt;hr/&gt;&lt;p&gt;The tension in the room was palpable. The president had cancelled everything on the day's agenda for his top advisers and set up an emergency meeting for 2 pm. The rumors were flying around, though nobody took the idea of a war seriously - it wouldn't have made sense for the president to know about it before the CIA or the NSA. Still, Joe thought, something big must be at stake for David to cancel everything; he knew how important the meet-and-greet sessions were for a new cabinet.&lt;p&gt;"Joe," asked Carol, the National Security Adviser, "do you know what this is about?"&lt;p&gt;"I'm just as much in the dark as you are," Joe replied, "and let me tell you, I don't like it a bit." Joe was David's closest friend since college and as soon as David got elected he named Joe as the Director of the CIA. It wasn't just a matter of whom you knew, it was too important a position for David not to give it to someone he knew he could trust.&lt;p&gt;At exactly 2 pm, David entered the room. "Please be seated," he said as everyone had raised from their chairs. After taking his place at the head of the table and waiting for them to settle down, he began. "Gentlemen, I'd like you to meet my guest, Ra'ken."&lt;p&gt;The same door David had used opened up and Ra'ken entered. Joe felt his jaw drop and by the reaction of those around him, he wasn't the only one in shock.&lt;p&gt;"Hello," the new guest said. "My name is Ra'ken; my species is called Erzhi but I have been called an elf before. Feel free to use either name."&lt;p&gt;"How?" Joe managed to ask.&lt;p&gt;David made a face. "That is indeed a problem. Ra'ken came here using magic. Before you start," he raised a hand to stop the exclamations of unbelief, "he can prove it."&lt;p&gt;"Indeed," confirmed Ra'ken. "For now, however, that is not important."&lt;p&gt;"Please have a seat," David said, pointing out to one of the available chairs, "and tell us why you came."&lt;p&gt;Ra'ken sat down and took a deep breath. "We are at war," he began.&lt;hr/&gt;&lt;p&gt;"The race we are fighting is called the Moqqid. They are strong magic users and have a large empire - much larger than ours. They have at least twenty-seven planets that we know about."&lt;p&gt;Everyone around the table was stunned. Not one, but two alien races, one of them with a huge empire, and Earth found itself in the middle of a conflict.&lt;p&gt;Ra'ken continued. "We have fewer people and fewer resources than the Moqqid. We have been fighting for several decades and, even though we have won some battles, we are losing. The Moqqid have already captured three of our planets and we have no news about the fate of our people there. We are becoming desperate."&lt;p&gt;Joe started thinking - any conflicts the US was involved in would have to be cancelled right away. The contractors would not complain, given that the new war they were about to be involved in would be much larger in scale. If anything, they were going to be ecstatic. Just bringing back the troops from Asia would free over a hundred thousand people.&lt;p&gt;"We are going to need any technology you can give us," he interrupted. "Weapons would be best, but we can use anything - medical, logistics, anything. In exchange, we can probably supply ten thousand troops right away." Joe was looking forward to a heated negotiation.&lt;p&gt;Ra'ken turned his head to him. "I apologize for the misunderstanding," he said. "We have no technology. We also do not need your help to wage war. Humans are incapable of using magic; a single Moqqid warlock, even a low level one, would destroy all ten thousand human soldiers without being hurt."&lt;p&gt;David blinked. "What do you need from us, then?"&lt;p&gt;Ra'ken turned back. "Slaves," he answered.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4018806552743639919?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4018806552743639919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4018806552743639919' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4018806552743639919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4018806552743639919'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2012/01/conquest.html' title='Conquest'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7139866324849100149</id><published>2011-10-16T20:06:00.000+03:00</published><updated>2011-10-16T20:11:50.393+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><title type='text'>Don't expose class internals</title><content type='html'>&lt;p&gt;I'm going to disagree a bit with Robert Martin, the author of &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt;. In his G14 "Feature Envy" smell he uses the example of an method on an HourlyPayCalculator class that takes an HourlyEmployee argument and then uses its properties to do its job. That makes the method "envy" the HourlyEmployee class - the method "wishes it was inside the HourlyEmployee class".&lt;p&gt;So far, so good. Unfortunately, Robert continues with a counter-example to the feature envy smell; he uses the following example (Java code):&lt;pre&gt;&lt;br /&gt;  public class HourlyEmployeeReport {&lt;br /&gt;    private HourlyEmployee employee;&lt;br /&gt;&lt;br /&gt;    public HourlyEmployeeReport(HourlyEmployee e) {&lt;br /&gt;      this.employee = e;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;    String reportHours() {&lt;br /&gt;      return String.format("Name: %s\tHours: %d.%1d\n",&lt;br /&gt;      employee.getName(),&lt;br /&gt;      employee.getTenthsWorked()/10,&lt;br /&gt;      employee.getTenthsWorked()%10);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Robert says: &lt;i&gt;"Clearly, the reportHours method envies the HourlyEmployee class. On the other hand, we don't want HourlyEmployee to have to know about the format of the report. Moving that format string into the HourlyEmployee class would violate several principles of object oriented design."&lt;/i&gt;&lt;p&gt;I believe there's a way to solve both problems. The HourlyEmployee class has to know about the &lt;b&gt;concept&lt;/b&gt; of reporting; that's why we're exposing the getName() method. The only decision is whether we hide this concept or make it explicit. Here's a way we could make it explicit (I'll use C# because, while I can read Java, I'm not confident enough to write it):&lt;pre&gt;&lt;br /&gt;  public interface HourlyEmployeeReporting {&lt;br /&gt;    void Report(string name, double tenthsWorked);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public class HourlyEmployee {&lt;br /&gt;    private string name;&lt;br /&gt;    private double tenthsWorked;&lt;br /&gt;    //... other stuff, but keep the internals hidden&lt;br /&gt;&lt;br /&gt;    public void Report(HourlyEmployeeReporting reporter) {&lt;br /&gt;      reporter.Report(name, tenthsWorked);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public class HourlyEmployeeReporter: HourlyEmployeeReporting {&lt;br /&gt;    void Report(string name, double tenthsWorked) {&lt;br /&gt;      var report = string.format("Name: {0}\tHours: {1}.{2}\n",&lt;br /&gt;        name, tenthsWorked / 10, tenthsWorked % 10);&lt;br /&gt;      // do something with the report value, like writing it to a Logger&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This way we haven't sacrificed any of the object oriented principles: everything is encapsulated, we can still have reporting and, quite importantly, reporting is exposed as a concept instead of being hidden just because we can use the internals of the HourlyEmployee class to do it.&lt;p&gt;[Note: I am not saying that exposing getName() doesn't work. I am saying that the way I'm showing is more object oriented.]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7139866324849100149?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7139866324849100149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7139866324849100149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7139866324849100149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7139866324849100149'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/10/dont-expose-class-internals.html' title='Don&apos;t expose class internals'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3562939922436407997</id><published>2011-10-06T12:42:00.002+03:00</published><updated>2011-10-06T14:23:12.152+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>The Awakening</title><content type='html'>&lt;p&gt;The source of their Powers was never discovered; what nobody had doubted, however, was that there was a will behind it. Both the fact that there were exactly nine of them – one for each billion people – and the fact that each of them gained their powers on January 1st, 2050, at exactly midnight local time, made coincidence a too unlikely explanation.&lt;p&gt;Once it found out about their existence, the world called them superheroes; but amongst themselves they would use the name Champions.&lt;hr/&gt;&lt;p&gt;The people would not discover the existence of the Champions for more than a year, though, because at the same time they had gained their powers, the Universe had started responding to spells. Some would call them wishes, or prayers; whatever the name, people's intentions were starting to directly affect the real world. Like many religions had insisted, it would only happen if the person making the wish genuinely believed in it; unlike what those religions had taught, the effect of the wish appeared to be completely unrelated to its content. Someone would pray for a million dollars, truly believing in the power of prayer; a week-long drought would be the result.&lt;p&gt;Very soon, in a matter of days, people realized what happened and started experimenting. Whatever the reason for this change, it appeared to be almost mechanical in the way it interpreted the spells. They had to be voiced - mere thinking did not seem to have an effect - but the language would appear to have little relevance. Wishing for a million dollars in English, French or Chinese would all cause a week-long drought, with maybe minutes in difference; on the other hand, wishing for a million Euros or Yuan would change the length of the drought significantly and work was in progress to determine the exact relationship. Intonation, number of people making the same wish, number of repetitions - everything had an effect.&lt;p&gt;It didn't take long before the experiments were formalized; by next Fall, Universities throughout the world began adding to their curricula courses in the new science of Magic. The governments were even faster in regulating the new Spellcaster profession. The American DHS was the first to have a Magic Crimes Division, but other agencies and governments followed suit very quickly. Even the Vatican announced that they were going to convene a special council to analyze the new situation.&lt;hr/&gt;&lt;p&gt;Ideas for further development:&lt;ul&gt;  &lt;li&gt;The DHS asks for the power to record everything, including private residencies, to discover people who make unlicensed wishes. It is granted, as long as the search is never done manually, only through an AI that can check warrants. The recordings are also supposed to be erased after an year but, with cryptographically-secure storage being practically free, this is not something you can count on.  &lt;li&gt;A black market in spells develops very quickly.  &lt;li&gt;The copyright lawsuits in spells dwarf anything previously seen with movies, music or patents; the next richest guy on the planet is a spell writer.  &lt;li&gt;Religious fanaticism leads to armed confrontation against the government; even regular people are uneasy with the idea of the government regulating religious prayers.&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3562939922436407997?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3562939922436407997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3562939922436407997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3562939922436407997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3562939922436407997'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/10/awakening.html' title='The Awakening'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-1082869908666673486</id><published>2011-10-02T22:11:00.000+03:00</published><updated>2011-11-08T13:50:30.228+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>TDD by example - first book</title><content type='html'>&lt;p&gt;This is an alpha version of a TDD booklet I wrote. As I said &lt;a href="http://mdpopescu.blogspot.com/2011/09/tdd-by-example.html"&gt;earlier&lt;/a&gt;, I plan on writing several of these.&lt;p&gt;&lt;a href="http://renfieldsoftware.com/Files/TDD_by_example_Evaluating_an_expression.pdf"&gt;TDD by example - Evaluating an expression&lt;/a&gt; [pdf]&lt;p&gt;It's a hands-on book; if you don't plan to follow it by writing code, it might not be of any help. The intended target are people who have done no TDD at all, or who tried it and couldn't make it work. If you have experience doing TDD, this book will probably look childish.&lt;p&gt;Feedback will be strongly appreciated. Positive if at all possible, but even "it sucks" is better than nothing :)&lt;p&gt;The book is also available from Amazon &lt;a href="http://www.amazon.com/TDD-example-Evaluating-expression-ebook/dp/B005TEN130/ref=tmm_kin_title_0?ie=UTF8&amp;m=AG56TWVU5XWC2"&gt;for $4.99 for Kindle&lt;/a&gt; (if you're in the US or Canada; I know Amazon changes the price in other countries) or &lt;a href="http://www.amazon.com/TDD-example-Evaluating-Marcel-Popescu/dp/1466410930/ref=tmm_pap_title_0"&gt;$14.99 in paperback&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-1082869908666673486?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/1082869908666673486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=1082869908666673486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1082869908666673486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1082869908666673486'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/10/tdd-by-example-first-book.html' title='TDD by example - first book'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6632850404960255768</id><published>2011-09-29T00:44:00.002+03:00</published><updated>2011-10-01T21:30:18.538+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>Science vs dogma</title><content type='html'>&lt;p&gt;Two hypotheticals:&lt;p&gt;1. You (common, everyday man) observe something occurring in nature. Every time it happens, you figure out that a specific something causes it. You emit the hypothesis that "A causes B" and devise a number of experiments to disprove it. You fail, and as far as you know everyone else also fails to disprove your theory. You tentatively accept the theory.&lt;p&gt;2. You observe something occurring in nature. It violates accepted dogma. You note that there is no known case where the alleged cause is known to actually produce the observed effect and, in fact, there is no actual proof that the cause even exists. You are told that you lack the inner grace that allows the high priests to verify that the cause does indeed exist; that there are secret rituals you're not privy to that they have used to confirm the truth of the dogma, and you're better off just accepting it as fact.&lt;p&gt;The first paragraph describes, for example, the idea that complex information is overwhelmingly, if not exclusively, generated by intelligent causes. A lot of people consider it to be a religious belief.&lt;p&gt;The second paragraph describes stuff like dark matter, string theory, &lt;strike&gt;quantum physics&lt;/strike&gt;, black holes and pretty much everything physicists declare to be scientific truth. (I love that phrase... "scientific truth". It has a gnostic ring to it.)&lt;p&gt;&lt;p&gt;&lt;b&gt;Edit&lt;/b&gt;: To clarify, by "quantum physics" above I meant the more esoteric interpretations, like the multi-verse theory; stuff that is not even verifiable, let alone verified.&lt;p&gt;&lt;p&gt;&lt;b&gt;Edit 2&lt;/b&gt;: This is a great example of a scientist understanding the science / dogma problem : &lt;a href="http://www.wwheaton.com/waw/mad/mad19.html"&gt;The Van Allen Belts and Travel to the Moon&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6632850404960255768?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6632850404960255768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6632850404960255768' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6632850404960255768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6632850404960255768'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/science-vs-dogma.html' title='Science vs dogma'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5700560433740072265</id><published>2011-09-28T09:47:00.002+03:00</published><updated>2011-09-29T00:49:04.721+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Thou shalt not steal</title><content type='html'>&lt;p&gt;Jimmy was quite good at his craft, and that made him proud. His Pa, though – his Pa could never find out; he was a big stickler for that “honest work” bull, his Pa was. Jimmy was big for his fourteen years, so his Pa had started to bug him more often lately – “it’s time to start earning your keep, Jimmy”, “come work with me at the farm, Jimmy, we could use someone like you”. It was very annoying, even more so because Jimmy did want his Pa to be proud of him, but he wanted to get there his own way.&lt;p&gt;No, his choice of craft was not that of a farmer, or a carpenter, or anything like that. Jimmy was a pickpocket – a good one, if he said so himself. Minor stuff for now, but he had never been caught – the very thought of what his Pa would do to him if he found out about it gave him shivers – and he was hoping for a big score. Jimmy was sure that his big score was close – didn’t his Ma tell him that “good things come to those who wait”? So Jimmy waited, and practiced.&lt;p&gt;His Pa was also annoying Jimmy about his friends. He didn’t like them – he said they were a bad influence on him. That was not right – he had learnt his craft from them, and because of that extra money he could afford a few more trinkets. He was even less of a burden in the house expenses, so that had to be a good thing, no?&lt;p&gt;Still, that big score was the only thing that would solve their problems. His Pa worked at least ten hard hours a day, and barely got enough money to feed them all – Jimmy had a little sister that he loved, and he would bring her little gifts bought with his “earnings”. Sometimes even sweets, though that was really rare. If Jimmy could manage to score big, his Pa could work a bit less, his Ma could have enough money to buy something for herself, and his sister would have everything she wanted. They would all be so proud of him, and his Pa would have to admit he was wrong about Jimmy.&lt;p&gt;There was one problem that made that big hit unlikely, though, and Jimmy was aware of it: the economy was really bad. People were getting laid off left and right, some of them were even killing themselves when the banks got their homes. It looked like nobody had any money, so where could Jimmy find a sucker with lots of money? He thought about robbing a bank, but he didn’t know how to use a gun, and he wasn’t a bank robber anyway – he was a pickpocket, and he wanted to stick to what he knew.&lt;p&gt;Until one day… one of his friends found out that someone was going to carry a lot of cash on himself. Jimmy didn’t know how he knew that, and he didn’t care much. Since Jimmy was the best, he was recruited for the job. The sucker was old and careless – Jimmy could spot the big bundle under his jacket from a mile away. The guy was practically begging to be robbed, so what could Jimmy do but be a good fellow and help him out? It’s not like he was harming anyone – the guy surely had plenty more money where that came from, and anyone carrying a large bag of cash should hire some security to help, no? The guy must be a cheapskate on top of everything else.&lt;p&gt;The job was so easy a kid could have done it. Someone with even less experience than himself, Jimmy thought. The old guy was really bad at taking care of his stuff – Jimmy was definitely going to be a better master for the money than him. All it had taken was a few moments of carelessness, a well-timed distraction provided by one of Jimmy’s friends, and his dream was accomplished – the big hit, finally. Sure, the old guy was a little roughed up, but it wasn’t anything permanent – he was going to be fine. A rich guy like him was sure to have expensive doctors anyway.&lt;p&gt;Jimmy was ecstatic. Here was his chance to prove his parents wrong – especially his Pa. He was a man now, who would help his family. Of course, he had to take some time to celebrate the hit, and he had to split the loot with the rest of the gang. Jimmy kinda lost track of the celebration – he never had drunk so much ale before in his life, and that was a problem. Still, after the party ended, he still had enough to help his family for a good while, and Jimmy was nothing if not optimistic – more jobs like this would surely come.&lt;p&gt;So, two mornings after his hit, after trying to put back some order in his looks – it wouldn’t do to have his father start berating him as soon as he entered the house – Jimmy went back home with a smile on his face. His pockets were full of sweets for his sister Lexie, and he even had one good cigar for his Pa. He was going to give it to him and watch him smoke, and hear him tell that he was proud of Jimmy, and that he was indeed becoming a man.&lt;p&gt;As soon as he entered the house, Jimmy knew something was wrong. Both his Ma and Lexie were crying, and there were a few other people in the house. Some of the neighbors were there, and even Aunt Janet from Boston, who almost never came to visit.&lt;p&gt;“Ma?” asked Jimmy, “what happened? Sis?”&lt;p&gt;His Ma lifted her eyes and looked at him. “Oh, Jimmy,” she cried, “thank God you’re ok! I thought I had lost you too!”&lt;p&gt;“Ma? What do you mean? I’m ok, what happened? Where’s Pa? Lexie, don’t cry,” he continued, “here, I have some sweets for you, I know you like sweets.” He tried to give Lexie a handful of sweets, but she kept crying and didn’t even look at him.&lt;p&gt;“Oh, Jimmy, my poor boy. I... I…” his mother started crying again.&lt;p&gt;“Sit down, Jimmy,” said Aunt Janet. “Here, take a seat. Have some water to drink.” She pushed a glass of water to him.&lt;p&gt;“Auntie? What happened? Where’s Pa? Why is everyone crying?” Jimmy asked, really scared by now.&lt;p&gt;“Boy, I don’t know how to tell you this, so I’m just gonna say it,” said Aunt Janet. “Your father is dead. It seems that someone beat the farm administrator and stole the money he was taking to the bank to pay the mortgage, so the owner had to close the farm and sell everything. Your Pa couldn’t take the shame of having lost his job, so he hanged himself.”&lt;p&gt;“What?” Jimmy was sure this was a joke, a bad one. His vision was starting to darken, and he was making an effort to hear Aunt Janet, who kept talking.&lt;p&gt;“He left you a note,” Janet said. “He wanted you to know that he was always proud of you, and he knew you were going to become a great man. He said he was sorry for failing as a father, and he couldn’t bear to see the disappointment in your eyes. He said he was hoping you will do better than he did, and he asks that you forgive him, and that you take care of your mother and sister.”&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5700560433740072265?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5700560433740072265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5700560433740072265' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5700560433740072265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5700560433740072265'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/thou-shalt-not-steal.html' title='Thou shalt not steal'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3699490060015154244</id><published>2011-09-22T15:32:00.001+03:00</published><updated>2011-11-08T13:52:13.031+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>TDD by example</title><content type='html'>&lt;p&gt;I intend to start a series of short "booklets", for lack of a better term, on the same idea of &lt;a href="http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627"&gt;Growing Object-Oriented Software, Guided by Tests&lt;/a&gt; - show how a test-driven design process works for writing an application, from beginning to end. I realize I have hardly any readers, but is anybody interested in something like that? The articles will be free on my blog, of course, but I intend to also make them available for sale on Amazon.&lt;p&gt;I thought of stuff like writing an expression evaluator - 2 + 3 * 5 / (1 - 7) - and a postfix expression evaluator - 7 2 3 + * - but I tend to jump to math problems. On one hand, I need relatively simple problems, as I want to emphasize the TDD part; on the other hand, I don't want to write the next Stack implementation. Can anybody suggest topics?&lt;p&gt;Edited: follow-up at &lt;a href="http://mdpopescu.blogspot.com/2011/10/tdd-by-example-first-book.html"&gt;http://mdpopescu.blogspot.com/2011/10/tdd-by-example-first-book.html&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3699490060015154244?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3699490060015154244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3699490060015154244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3699490060015154244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3699490060015154244'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/tdd-by-example.html' title='TDD by example'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7045803069784127804</id><published>2011-09-21T17:20:00.000+03:00</published><updated>2011-09-29T00:48:20.762+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Flash fiction</title><content type='html'>&lt;p&gt;My house stands at the edge of the Earth.&lt;p&gt;It didn’t use to. Earth was a normal planet, a planet-sized planet as it were. Round. Not as big as Jupiter, of course, but not so small as to see its edges. I’ve been to cities that were bigger than what Earth looks like now.&lt;p&gt;There are only a few thousands of us left. We can’t say we’re alive, really – we’re almost zombies. Everybody that’s still here lost family and friends. We’re in the acceptance stage now… there was fighting, and incredulity, and mass suicides, but everybody seems to be resigned to whatever fate we have. Nobody has a clue what happened. It doesn’t even make any sense – no celestial body this small should have an atmosphere, and yet the air is perfectly breathable. A lot more breathable than it used to be, in fact – there’s no industry left on Earth, nothing to pollute. I think all the animals are gone too, except for a few pets. Oh, and lots of insects. The scientists were right; the cockroaches will inherit the Earth. Whatever will remain of it, if anything.&lt;p&gt;I don’t know what happened. Nobody does for sure. Maybe God was fed up with the humans again, and thought floods were passé? Maybe some evil wizard played with something that escaped his control? Whatever it was, it destroyed us all. The speed of the shrinkage has slowed down, but even if it were to stop completely there are too few people left now and too little space to live in. Some people have called this the Earth Spaceship; it finally became true.&lt;p&gt;Why am I even writing this? I have no idea. Maybe I’m an incorrigible optimist, even in the face of certain disaster. Maybe all the pessimists died out and I feel responsible for humanity. Maybe this is all a nightmare. Oh God, how I hope this is a nightmare! Somehow, though, I can’t seem to wake up from it.&lt;p&gt;At least we avoided global warming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7045803069784127804?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7045803069784127804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7045803069784127804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7045803069784127804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7045803069784127804'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/flash-fiction.html' title='Flash fiction'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4694796681138269433</id><published>2011-09-17T23:20:00.001+03:00</published><updated>2011-09-17T23:20:25.608+03:00</updated><title type='text'></title><content type='html'>&lt;i&gt;“The fact is that the average man’s love of liberty is nine-tenths imaginary, exactly like his love of sense, justice and truth. He is not actually happy when free; he is uncomfortable, a bit alarmed, and intolerably lonely. Liberty is not a thing for the great masses of men. It is the exclusive possession of a small and disreputable minority, like knowledge, courage and honor. It takes a special sort of man to understand and enjoy liberty–and he is usually an outlaw in democratic societies.”&lt;/i&gt;&lt;br/&gt;— H.L. Mencken, Baltimore Evening Sun, Feb. 12, 1923&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4694796681138269433?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4694796681138269433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4694796681138269433' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4694796681138269433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4694796681138269433'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/fact-is-that-average-mans-love-of.html' title=''/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2801171805092328743</id><published>2011-09-17T17:08:00.001+03:00</published><updated>2011-09-29T00:48:06.122+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>Johnny Got His Gun</title><content type='html'>&lt;p&gt;I don't believe in Hell. Several years ago I decided to fully accept the preterist theory (short version: everything in the Bible has already happened); this has led me to universalism - everyone goes to heaven. I've held this belief for quite a while now.&lt;p&gt;I just changed it - somewhat. I suddenly believe in Hell, a place of such misery and torture that people can't really imagine it. A horrifying place. I also believe &lt;b&gt;I'm in it right now&lt;/b&gt;, I just found a tiny bit which is somewhat less horrible. (I try not to make too many waves so I don't get moved to a more horrible part.)&lt;p&gt;This movie is why I think so - &lt;a href="http://www.imdb.com/title/tt0067277/"&gt;Johnny Got His Gun&lt;/a&gt;. It made me realize that politicians and soldiers are, if not &lt;i&gt;the&lt;/i&gt; Devil, then something very close to it. They do their best to make other people's lives and homes a Hell. Hiroshima and Nagasaki might have been the clearest example, but read this description of the &lt;a href="http://en.wikipedia.org/wiki/Carpet_bombing"&gt;carpet bombing&lt;/a&gt; of Tokyo from Wikipedia:&lt;p&gt;&lt;i&gt;On March 9 and 10 1945, B-29 Superfortresses were directed to bomb the most heavily populated civilian sectors of Tokyo. In just 2 days of bombing, over 100,000 of the population had burned to death from a heavy bombardment of incendiary bombs. Another 100,000 were left homeless.&lt;/i&gt;&lt;p&gt;We're in Hell. I now understand why some people commit suicide - they just discovered this, and can't handle it.&lt;p&gt;As for the rest of us - it's our job to make it better... though it's hard to be optimistic when I see how many people around me still worship the Devil.&lt;p&gt;Edit: For another horrible example, &lt;a href="http://www.dailymail.co.uk/news/article-2039542/Hell-earth-Detailed-satellite-photos-death-camps-North-Korea-deny-exist.html"&gt;North Korea's death camps&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2801171805092328743?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2801171805092328743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2801171805092328743' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2801171805092328743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2801171805092328743'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/johnny-got-his-gun.html' title='Johnny Got His Gun'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5654876.post-160435318339828283</id><published>2011-09-07T10:56:00.002+03:00</published><updated>2011-09-07T10:56:45.951+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scientists'/><title type='text'>On science, peer review and consensus</title><content type='html'>I find myself searching for these two articles a lot, so I thought I'd save them here. I can't recommend them enough.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theatlantic.com/magazine/archive/2010/11/lies-damned-lies-and-medical-science/8269/"&gt;http://www.theatlantic.com/magazine/archive/2010/11/lies-damned-lies-and-medical-science/8269/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://s8int.com/crichton.html"&gt;http://s8int.com/crichton.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-160435318339828283?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/160435318339828283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=160435318339828283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/160435318339828283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/160435318339828283'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/09/on-science-peer-review-and-consensus.html' title='On science, peer review and consensus'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-9011701106006456171</id><published>2011-08-20T15:18:00.011+03:00</published><updated>2011-09-29T00:50:44.312+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Random N out of M</title><content type='html'>Someone asked about randomly picking N elements out of an array of M, and I remembered reading about one way of doing that, so here it is: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static IEnumerable&amp;lt;int&amp;gt; Generate(Random rnd, int n, int m)&lt;br /&gt;    {&lt;br /&gt;      var i = 0;&lt;br /&gt;      while (n &amp;gt; 0)&lt;br /&gt;      {&lt;br /&gt;        var r = rnd.NextDouble();&lt;br /&gt;        if (r &amp;lt; (double) n / m)&lt;br /&gt;        {&lt;br /&gt;          yield return i;&lt;br /&gt;          n--;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        m--;&lt;br /&gt;        i++;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above C# method assumes 0 &amp;lt; N &amp;lt;= M and will return an IEnumerable&amp;lt;int&amp;gt; containing exactly N numbers in the 0 .. M - 1 interval. This method can even be used to pick items out of a stream without waiting for the whole stream to be produced first.&lt;br /&gt;&lt;br /&gt;A simpler method would be to just do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var i = 0; i &amp;lt; n; i++)&lt;br /&gt;    {&lt;br /&gt;      do {&lt;br /&gt;        var next = rnd.Next(m);&lt;br /&gt;      while (!alreadyGenerated(next));&lt;br /&gt;      yield return next;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;but this one requires 1) saving all numbers (to check if one was already generated) and 2) having the actual data in an array instead of a stream (since the indexes are not generated in ascending order).&lt;p&gt;&lt;b&gt;Edit&lt;/b&gt;: Per the observation from the first comment, the first fragment will never loop more than M times - an O(M) algorithm. The second fragment risks an O(M^2) if N is close to M.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-9011701106006456171?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/9011701106006456171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=9011701106006456171' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9011701106006456171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9011701106006456171'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/08/random-n-out-of-m.html' title='Random N out of M'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-9091058504567539945</id><published>2011-06-17T16:19:00.001+03:00</published><updated>2011-06-17T16:20:57.873+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Heinlein's rules of writing</title><content type='html'>(H/T to &lt;a href="http://www.deanwesleysmith.com/?p=4398"&gt;Dean Wesley Smith&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;1) You must write.&lt;br /&gt;2) You must finish what you write.&lt;br /&gt;3) You must not rewrite unless to editorial demand.&lt;br /&gt;4) You must mail your work to someone who can buy it.&lt;br /&gt;5) You must keep the work in the mail until someone buys it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-9091058504567539945?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/9091058504567539945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=9091058504567539945' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9091058504567539945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9091058504567539945'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/06/heinleins-rules-of-writing.html' title='Heinlein&apos;s rules of writing'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4721703029542203831</id><published>2011-06-12T21:32:00.004+03:00</published><updated>2011-09-29T00:47:33.803+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Story</title><content type='html'>I wrote this story a few days ago. I have no idea what to do with it now... so here's the first step: put it on the blog.&lt;br /&gt;&lt;br /&gt;If anybody gets here, by some amazing coincidence, please leave feedback even if it's only "it sucks" :)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The paradox maker&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Jack ripped the envelope. “Dear Mr. Harroway,” it began, “we are happy to inform you that your application for a study of the local effects of the 2030 Tehran terrorist attacks has been accepted.”&lt;br /&gt;&lt;p&gt;“Yes!” he shouted. “Yes, yes, yes!” His work at cultivating important officials had finally paid off. The bribes didn’t hurt either.&lt;br /&gt;&lt;p&gt;Jack was a brilliant physicist. Almost forty-five years old – his birthday just last month – he had everything a scientist could want: a great career, the admiration of his peers, even a great family. He did have one obsession though: he wanted to go back in time and kill himself.&lt;br /&gt;&lt;p&gt;Why? He probably couldn’t answer, at least not without a great deal of thought, but it was mostly because he had been fascinated by the idea the first time he encountered it, in some long-forgotten book on paradoxes. It was just a “thing” – some people collected stamps, some women, he wanted a clear-cut paradox. He didn’t trust the grandfather version, because there was always the risk that someone else was his real father; he wanted to be absolutely certain that he had a genuine paradox. A science-fiction story he had read long ago claimed that the Universe rejected paradoxes and would actively fight against them. Good. Jack was up to it. Man versus the Universe, what could possibly be more awesome?&lt;br /&gt;&lt;p&gt;Getting here had taken a lot of work. Time travel was a heavily regulated business, and time travel in the close past was almost never granted. The politicians were too afraid of someone changing the result of the last election. Jack soon realized that he couldn’t come up with any plausible excuse for his trip, so he focused on solving the problem through the most direct means: bribery and old-boys networking. Of course, that meant cultivating important city officials, but academia was good for that. There were fund-raising events, and alumni who had the necessary connections. As time passed, he had become more and more obsessed with the idea, sacrificing everything to it.&lt;br /&gt;&lt;p&gt;His wife was his unknowing accomplice. High society parties were her idea of heaven, and the young enthusiastic idealist who had married a poor scientist was long gone. She had grown more sophisticated – and, he would have to admit, more elegant – raising to the occasion as a graceful hostess. They didn’t have any children, something they were both happy about, so she would fully focus on their social advancement. It was a marriage made in heaven… well, it would have been, if not for his hidden goal.&lt;br /&gt;&lt;p&gt;Well, this was it. His had all the approvals he needed to go back in time 20 years. That was normally something historians would do, but he claimed he intended to write a book on the subject, and that coupled with a heavy bribe was a good enough excuse. He was absolutely forbidden from interfering or warning anyone, of course – and, in fact, had absolutely no intention of doing that. He was implanted with a full immersion recording device which was supposed to serve as evidence of his being a good boy and doing exactly what he was supposed to do – research only, no actions that would change the timeline. He was fine with that – in fact, a recording of his accomplishing a genuine paradox was a bonus.&lt;br /&gt;&lt;p&gt;Two minutes till the deadline. Jack went back over the plan once more. He would have been 15 at the time, living in the same city and already intrigued by the idea of time-travel paradoxes. Time-travel had started being practical not long before, in 2025, but it was still mostly used only by the US government. The foreign governments were making a lot of noise about it, at the same time sinking huge amounts in trying to reproduce – or steal – the invention; in fact, the Tehran attacks were supposed to be related to that. Time travel was in the news all over the world – and young Jack Harroway, 15 years old prodigy student, was completely fascinated by it. It had ultimately led to him becoming a physicist… and to this day.&lt;br /&gt;&lt;p&gt;Five more seconds… four… three… two… one… flash. There was no reason for any effects to occur when someone moved through time, but most people reported some sensation – flashes, blackouts, short-term dizziness. He was here, close to his old home – he chose that spot beforehand, with nobody questioning it. This was it. The high he was on was incredible – adrenalin was pumping through his body, giving him a sensation of invincibility. He was going to create a real paradox.&lt;br /&gt;&lt;p&gt;First things first: confirm arrival. No accident has ever been reported, but his experiment was too important to trust others. Trust, but verify, wasn’t there a president who said that? If something wrong did happen, he had an emergency return button he could use, but he was worried more about failing his attempt than about being stuck in the wrong time or place. In any case, that was quickly solved; he put a quarter in a nearby newspaper box and verified that this was indeed June 12, 2030. The attacks would occur at 9pm EST, and he was supposed to have arrived at 4pm. The Sun was still pretty high on the sky, so he assumed the time was accurate. Satisfied, he looked around and started walking to his destiny. That sounded so important – his destiny. He almost felt like shouting to the people on the street – the attacks are nothing, the economy is nothing: you’re witnessing destiny in the making! Eh, what did they know?&lt;br /&gt;&lt;p&gt;There – the house was just as he remembered it. His father would still be alive – he had died of cancer when Jack was 38 – and his younger version would probably be playing some online RPG. He was quite a fan in his youth; he didn’t much like the fantasy RPGs, but the sci-fi-themed ones was something else altogether. What could be cooler than having your own spaceship and travelling among the stars, fighting pirates and rescuing civilians? Wait – creating a genuine paradox and fighting the Universe would surely qualify.&lt;br /&gt;&lt;p&gt;He rang the bell. After a few seconds, his mother opened the door. “Yes?” she said.&lt;br /&gt;&lt;p&gt;“Hello, is Jack home? I’m his physics professor.”&lt;br /&gt;&lt;p&gt;“Oh,” she said, flustered. “Is there anything wrong? Has something happened?”&lt;br /&gt;&lt;p&gt;“No, no,” said Jack. “This is not school related. We’re both playing the same online game, we’re in the same clan actually, and I wanted to discuss something with him.”&lt;br /&gt;&lt;p&gt;“Oh,” she replied, a bit colder. He remembered that – his parents were never supportive of his infatuation with online games. He couldn’t object too much, really, since he now pretty much agreed with them that they were a waste of time, but back then it had been a problem.&lt;br /&gt;&lt;p&gt;“Please take a seat,” his mother said. “I’m Melanie, Jack’s mother; just a moment until I get him here. He’s probably playing right now.”&lt;br /&gt;&lt;p&gt;“Nice to meet you, Melanie; I’m Robert,” said Jack.&lt;br /&gt;&lt;p&gt;“Nice to meet you, Robert; it will only be a second.”&lt;br /&gt;&lt;p&gt;The young Jack appeared shortly. “Yes?” he asked, not recognizing the stranger.&lt;br /&gt;&lt;p&gt;“Hi, Jack, “ the future Jack said. “Sorry to bother you at home… there is a problem with the Paradox Engine and we need to solve it before the next clan fight.”&lt;br /&gt;Young Jack’s eyes became larger. “The Paradox Engine” was his idea of a password to recognize his older self; in fact, he only came up with it two days before. His breath quickened. He suddenly realized what this meant.&lt;br /&gt;&lt;p&gt;“Oh, yes, please come to my room to discuss it,” he said, turning back without waiting for a reply. “Mom, we’ll be in my room, please don’t disturb us,” he continued.&lt;br /&gt;&lt;p&gt;“Ok, honey. Professor Robert, would you like something to drink? A coffee?” she asked.&lt;br /&gt;&lt;p&gt;“No thanks, ma’am, I’m fine. I won’t be long, please don’t bother on my account,” Jack replied. He quickly followed his younger self to his room.&lt;br /&gt;&lt;p&gt;Once there, the young version closed the door carefully and then sat down. “So… we did it. Well, you did. You came back in time.”&lt;br /&gt;&lt;p&gt;“Yeah,” future Jack replied. “It took some doing, as you can see, but we’re finally here.”&lt;br /&gt;&lt;p&gt;“Oh, wow. I can’t believe it. I mean, I only came up with the password two days ago. In fact, I don’t think I read about paradoxes more than six months ago.”&lt;br /&gt;&lt;p&gt;“Yes, I know,” said future Jack. “That’s why I chose this day; I wanted to make sure everything is still fresh in your mind. So, are you ok with it?”&lt;br /&gt;&lt;p&gt;“Now?”&lt;br /&gt;&lt;p&gt;“I’d prefer it. I’m worried that something might happen to stop us. That story I read, about the Universe actively preventing paradoxes from happening, really did a number on me. The closer we get to it, the more worried I am.”&lt;br /&gt;&lt;p&gt;“I don’t think I remember that story,” said young Jack.&lt;br /&gt;&lt;p&gt;“Hmm… I don’t remember exactly when I read it, but I guess it was after your time.”&lt;br /&gt;&lt;p&gt;“Ok. Let’s do it. I’m as ready as I’ll ever be.”&lt;br /&gt;&lt;p&gt;“Do you want to close your eyes?”&lt;br /&gt;&lt;p&gt;“Ok. You’ll make it quick, right?” asked young Jack.&lt;br /&gt;&lt;p&gt;“Of course. You’re me, remember? I have no intention of causing myself any unnecessary pain.”&lt;br /&gt;&lt;p&gt;Taking a deep breath, future Jack removed a ceramic knife from his pocket. A metal one could have been detected by the time travel office and he didn’t want that to happen. Folding it open, Jack steeled himself and with a sudden move, plunged the knife into his younger version’s throat.&lt;br /&gt;&lt;p&gt;Young Jack’s eyes flew open and he tried to put his hands on his neck. He tried to say something, but old Jack pulled the knife out and hit a few more times, finally managing to hit the heart. Killing someone is difficult, he thought, even when they’re cooperating. He was quite nauseated – he was not a psychopath, at least he didn’t think so, and seeing a young man die, and blood everywhere, was having an effect. The smell wasn’t helping either; he felt very dizzy… the room started spinning… everything was splashed with red blood… or was it black?&lt;br /&gt;&lt;p&gt;Jack fainted.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;p&gt;When he came out of it, Jack was back in his home… just before he had left for the local branch of the Federal Bureau of Time Travel. He was worried that he dreamt the whole thing, but he could still smell the blood, and in fact his clothes and face were still dripping red. Puzzled, he went to take a shower and change his clothes, hoping that his wife wasn’t home. This doesn’t make any sense, he thought.&lt;br /&gt;&lt;p&gt;“Jack?” he heard his mother calling. “What?” he replied, before realizing that this was impossible. He didn’t live with his mother anymore – she was back in the old house. Looking around him and seeing nobody, he decided that he must have imagined the voice. It didn’t last long.&lt;br /&gt;&lt;p&gt;“Jack, dear, I’m going out to buy some food. If your father comes home before me, tell him I won’t be long.”&lt;br /&gt;&lt;p&gt;Suddenly, he was back in the old room. Looking down at his hands, he realized he was in his 15-years old body. What was going on here?!&lt;br /&gt;&lt;p&gt;Over the next few days, he switched back and forth between his old and new selves. He had no control over the change, and he was starting to worry about getting out of the house – if the switch caught him while crossing the street, he had no idea what might happen. Unfortunately, that was not really a problem – causality seemed to have lost its power as far as he was concerned. Impossible things started happening – he would pour water into a glass, only to find it still empty, strong winds would start inside his room, he would hear or see things that nobody else did… worse of all, he started getting seizures.&lt;br /&gt;&lt;p&gt;He tried asking for help, explaining what he did to other physicists. Nobody believed him, mainly because there was no record of him ever going back in time, but also because his frequent body switches made the whole explanation incoherent. Jack tried going to a psychiatrist, but the medication did nothing but make him even dizzier. His apparent mental health worsened at an incredible speed, so in a couple of weeks his wife had no choice but commit him to an asylum.&lt;br /&gt;&lt;p&gt;Jack is happy now. All the inmates know that he’s the sole paradox maker in the Universe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4721703029542203831?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4721703029542203831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4721703029542203831' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4721703029542203831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4721703029542203831'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/06/story.html' title='Story'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-1354533064221794914</id><published>2011-06-12T00:29:00.004+03:00</published><updated>2011-06-12T00:34:12.373+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='copyright'/><category scheme='http://www.blogger.com/atom/ns#' term='socialism'/><title type='text'>Communist USA</title><content type='html'>Here's something I never thought I'd see in the US (as bad as I believe it has become):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ideasmatter.com"&gt;Ideas Matter&lt;/a&gt;, a pro-IP propaganda site build by Microsoft and others, has the following on their About page:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;In the words of President Barack Obama: "Our single greatest asset is..."&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bear with me while I'm freaking out here. I grew up in communist Romania until I was 18. &lt;span style="font-weight:bold;"&gt;Any time&lt;/span&gt; you wanted to write something - including in school essays - we would have to quote the beloved president. Freaking programming books, few as they were, would have something that the president said in their introduction.&lt;br /&gt;&lt;br /&gt;What the hell???&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-1354533064221794914?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/1354533064221794914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=1354533064221794914' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1354533064221794914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1354533064221794914'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/06/communist-usa.html' title='Communist USA'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4086012078005475324</id><published>2011-01-13T14:40:00.001+02:00</published><updated>2011-01-13T14:41:36.493+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scientists'/><title type='text'>The pursuit of knowledge</title><content type='html'>From &lt;a href="http://freedomtwentyfive.wordpress.com/2011/01/09/why-im-leaving/"&gt;http://freedomtwentyfive.wordpress.com/2011/01/09/why-im-leaving/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;But, you ask, what about the glorious pursuit of knowledge? Won’t you be dedicating your life to advancing the state of human knowledge? If you’re asking that, I guess you’ve never actually been inside a Western University: They are cesspools of mediocrity and ideological cant. The contemporary university is quite possibly the worst place in the world to actually think freely and come up with new ideas.  As a career academic, you will frequently have to choose between honesty and your career. And remember, if you aren’t willing to make the “right” choice, there are a thousand others lined up behind you who will.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4086012078005475324?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4086012078005475324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4086012078005475324' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4086012078005475324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4086012078005475324'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/01/pursuit-of-knowledge.html' title='The pursuit of knowledge'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-279302524052631690</id><published>2011-01-06T14:27:00.003+02:00</published><updated>2011-01-06T14:33:22.822+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='excel'/><title type='text'>Excel gotcha</title><content type='html'>Just got bit by a... I can't call it "bug", but at least surprising behavior, in Excel 2007 (though I believe it is the same even in other versions).&lt;br /&gt;&lt;br /&gt;I had a column of text (file names) in a csv document which was opened in Excel and re-saved as a regular Excel files. The recipient of that document asked me while some of the file names were in scientific notation :) It puzzled me for a bit, until I realized that a lot of the file names had the form &lt;b&gt;12E12345&lt;/b&gt;. When the part after the "E" was small enough (I didn't bother searching for the limit, but I'd make a wild guess and say below 300), Excel would interpret that string as a number in scientific notation - so 01E00212 became 1E+212.&lt;br /&gt;&lt;br /&gt;The program I used to generate these csv documents knew to prefix strings made up of only digits and starting with zeroes with an apostrophe - like &lt;b&gt;'00123&lt;/b&gt;. This one, however, caught me unprepared :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-279302524052631690?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/279302524052631690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=279302524052631690' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/279302524052631690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/279302524052631690'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2011/01/excel-gotcha.html' title='Excel gotcha'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-8154535895158174307</id><published>2009-11-06T15:08:00.001+02:00</published><updated>2009-11-06T15:08:26.249+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><title type='text'>Complexity and chance</title><content type='html'>In one of the Miles Vorkosigan books, the main character has a device installed in his brain and a remote that can trigger a seizure - he needs that because otherwise he would get uncontrolled seizures, usually at moments of high stress (when that's the last thing he needs). One of his problems is having that remote triggered accidentally, so the doctors assure him they coded the connection - no random signal can trigger the seizure, only the remote.&lt;br /&gt;&lt;br /&gt;What are the possible dangers here?&lt;br /&gt;&lt;br /&gt;1) Accidental signals that would match the frequency of the brain device, thus generating a false positive.&lt;br /&gt;&lt;br /&gt;How does one defend against this possibility? A small code of some sort is usually required for triggering the functionality - like the 4-digit code I have to enter when my Nokia cellphone locks the keys (to prevent me from accidentally dialing out when I keep the phone in my pocket).&lt;br /&gt;&lt;br /&gt;2) Intentional signals from would-be hackers who want to trigger the device.&lt;br /&gt;&lt;br /&gt;In this case, one would need a much more complicated mechanism - possibly a challenge-response sequence where the remote must confirm that it knows a secret. (The book does not explicitly say this but, with Miles formerly in ImpSec and currently one of the several Imperial Auditors, we can assume something like this was actually employed.)&lt;br /&gt;&lt;br /&gt;Note the difference? Against randomness, a very simple (= of low complexity) code is sufficient. It is unlikely to the extreme that I would accidentally press my Nokia cellphone's 4-digit code while carrying it in my pocket. It is practically impossible that I would manage that with an 8-digit code. If that code is entered, the phone software can safely assume I *meant* for it to happen - chance simply cannot account for that complexity. (Again, that's a 4-digit code, which is around 14 bits of information - 2^13 = 8,192 &lt; 10,000 &lt; 2^14 = 16,384.)&lt;br /&gt;&lt;br /&gt;However, intelligence CAN overcome quite a hefty complexity barrier. Millions of man-years have been spent on creating ciphers that are supposed to last against other millions of man-years working to defeat them. This is VERY STRONG evidence that, given a complex system, we can safely eliminate chance as the cause. While chance can overcome complexity barriers of a few bits - even of dozens of bits, given enough time and the right circumstances - once we get in the realm of hundreds of bits (the CSI barrier) it is absolutely ridiculous to insist on claiming it is a reasonable possibility.&lt;br /&gt;&lt;br /&gt;So - what created life, again? :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-8154535895158174307?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/8154535895158174307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=8154535895158174307' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8154535895158174307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8154535895158174307'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/11/complexity-and-chance.html' title='Complexity and chance'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6404275873919230319</id><published>2009-08-01T15:14:00.002+03:00</published><updated>2009-08-01T15:35:51.436+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Maintainability</title><content type='html'>Lots of noise on this subject - as far as I know, it started with &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/07/21/nhibernate-2-1-changes-overview.aspx"&gt;this article&lt;/a&gt; by Patrick Smacchia that has apparently annoyed Ayende, who &lt;a href="http://ayende.com/Blog/archive/2009/07/21/answering-to-nhibernate-codebase-quality-criticism.aspx"&gt;replied&lt;/a&gt; to it (and followed &lt;a href="http://ayende.com/Blog/archive/2009/07/24/nhibernate-and-ndepend-ndash-skimming-the-surface.aspx"&gt;here&lt;/a&gt;). A few days later, Ayende &lt;a href="http://ayende.com/Blog/archive/2009/07/29/what-is-maintainable.aspx"&gt;replies to an article by Frans Bouma&lt;/a&gt; to explain what he means by maintainability - a definition that goes against what Patrick &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/07/29/maintainability-learnability-component-layering.aspx"&gt;believes&lt;/a&gt; to be true.&lt;br /&gt;&lt;br /&gt;Now that you're up to date, my opinion :)&lt;br /&gt;&lt;br /&gt;An analogy from C. S. Lewis helps here. To claim that using toothpaste is good, he said, does not mean that if you find someone with bad teeth, but who uses toothpaste all the time, and someone who never used it, but has great teeth, you have disproved the statement. What matters is: given the same person, is he going to be better off by using toothpaste or not?&lt;br /&gt;&lt;br /&gt;To apply the analogy: given the same person, whether an average developer from the street or Peter Norvig (or Ayende or Frans or Patrick), which application is he going to find more maintainable: one with - say - hundreds of cyclical references, or one layered as Patrick argues should be done?&lt;br /&gt;&lt;br /&gt;In my opinion, this helps to nullify the inherent subjectivity of the issue: an application is more maintainable than another if, on average, more programmers would find it so. (I remember reading about someone who wrote code that would take into account the time it took to execute a piece of code and then read the next value from the disk &amp;mdash; which was exactly what he needed at that point; he knew where the disk head would be given that precise timing. That was a maintainable application for him &amp;mdash; less so for anyone else.)&lt;br /&gt;&lt;br /&gt;Of course, my definition (if I can call it that) still depends on the idea that there are lots more competent programmers than &lt;a href="http://thedailywtf.com/"&gt;Daily WTF&lt;/a&gt; candidates; I do not know if this is in fact the case :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6404275873919230319?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6404275873919230319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6404275873919230319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6404275873919230319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6404275873919230319'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/08/maintainability.html' title='Maintainability'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-8793218079361338597</id><published>2009-07-11T11:22:00.002+03:00</published><updated>2009-07-11T11:24:35.380+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><title type='text'>Monkeysphere?</title><content type='html'>Interesting article at &lt;a href="http://www.cracked.com/article_14990_what-monkeysphere.html"&gt;http://www.cracked.com/article_14990_what-monkeysphere.html&lt;/a&gt;. They didn't elaborate on the subject of religion, but I think (as some commented) that this is why the so-called golden rule is emphasized: trying to love everyone as you love yourself is another way of saying "realize they're also people just like yourself".&lt;br /&gt;&lt;br /&gt;No big discovery, I realize :) but I liked the connection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-8793218079361338597?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/8793218079361338597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=8793218079361338597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8793218079361338597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8793218079361338597'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/07/monkeysphere.html' title='Monkeysphere?'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3967382394054553569</id><published>2009-07-10T18:33:00.003+03:00</published><updated>2009-07-10T18:36:18.898+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><title type='text'>More on biblical laws</title><content type='html'>Sort of a follow-up to &lt;a href="http://mdpopescu.blogspot.com/2008/11/biblical-laws-during-last-few-years-i.html"&gt;my previous article&lt;/a&gt; - I just read "&lt;a href="http://mindfulhack.blogspot.com/2009/06/religion-why-did-pig-become-so.html"&gt;Why did the pig become so unpopular?&lt;/a&gt;" which added a lot of economic reasons for forbidding pig eating to the one I considered before (the disease part - pig meat has to be cooked really well to be safe, otherwise you risk a bunch of problems, which in Israel 5000 years ago is serious).&lt;br /&gt;&lt;br /&gt;Interesting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3967382394054553569?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3967382394054553569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3967382394054553569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3967382394054553569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3967382394054553569'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/07/more-on-biblical-laws.html' title='More on biblical laws'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2587011437156270277</id><published>2009-06-23T09:49:00.002+03:00</published><updated>2009-06-23T10:10:52.442+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>More speculation...</title><content type='html'>... in the vein of &lt;a href="http://mdpopescu.blogspot.com/2008/11/biblical-laws-during-last-few-years-i.html"&gt;this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jesus says in &lt;a href="http://www.biblegateway.com/passage/?search=mark%2011:23&amp;version=73"&gt;Mark 11:23&lt;/a&gt; &lt;span style="font-style:italic;"&gt;I tell you the truth. Anyone may say to this hill, "Go and jump into the sea." He must not doubt in his heart, but he must believe that he will have the things he asks for and he will have them.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What if Jesus didn't mean "if you have faith, I will move the hill (mountain) for you", but "if you have faith, the hill will move because the Universe was built to respond to human volition"? We know that the human body responds to human will sometimes (placebo effect); there's a speculative part of physics (quantum physics) that has as a basic tenet that human observation can influence the outcome of physical processes.&lt;br /&gt;&lt;br /&gt;Why the need for "unwavering" faith, then? Well, the Universe is probably a simple mechanism, if you're not very sure of what you want it cannot respond to your will. Maybe there's a "faith threshold" that triggers the mechanism; or maybe there's a required ratio between the "amount" of faith and the desired effect (so less faith would be required for moving a pin than for moving a mountain).&lt;br /&gt;&lt;br /&gt;As I said - speculation; it's not something I actually believe, for now it's just an amusing idea.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2587011437156270277?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2587011437156270277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2587011437156270277' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2587011437156270277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2587011437156270277'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/06/more-speculation.html' title='More speculation...'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2116585106338857258</id><published>2009-06-04T13:19:00.004+03:00</published><updated>2009-06-04T13:35:52.574+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>On extending DBMSes</title><content type='html'>Problem: you have some data for your company. The data has to be accessed from multiple applications (think accounting, personnel, sales and so on). How do you make sure business rules are obeyed - because if there's a bug in even one application, it will ruin the data and thus every other application.&lt;br /&gt;&lt;br /&gt;I agree with pretty much everything &lt;a href="http://www.dbdebunk.com"&gt;Fabian Pascal&lt;/a&gt; has to say about relational databases. The RDB *is* the place where data should live, and ideally it should be the place for business logic too - because business logic is about data.&lt;br /&gt;&lt;br /&gt;However, there are a few problems with this - mainly because of a lack in implementation, not in the theory of the relational database:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;No existing DBMS (Database Management System) - the actual implementation of the relational database theory - can support thousands of concurrent users, let alone millions.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It is hard to do user management / authentication in the same database as your business data - in fact, it might be a good idea to have separate databases for users (think Active Directory) and the actual data you care about.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The SQL language sucks for general purpose programming. It is difficult to write complex business rules in, and even more difficult to port to another vendor.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For these reasons, one should write an application whose main purpose is to "guard" the (main) database and enforce the business rules; think of it as "extending" the DBMS. &lt;a href="#1"&gt;[1]&lt;/a&gt; All other applications should go through this "gatekeeper" application.&lt;br /&gt;&lt;br /&gt;I guess this is some sort of "pattern" - an architecture that can be used to solve a number of problems.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;a name="1"&gt;[1]&lt;/a&gt; Note: some DBMSes allow you to write "plugins" or "user functions" in a different language. The problem is, these are also not easily portable, so I would recommend against it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2116585106338857258?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2116585106338857258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2116585106338857258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2116585106338857258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2116585106338857258'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/06/on-extending-dbmses.html' title='On extending DBMSes'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2618910450014917324</id><published>2009-05-24T23:07:00.010+03:00</published><updated>2009-05-25T08:21:33.917+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='wcf'/><title type='text'>WCF - inheriting from a common interface</title><content type='html'>At work I have a few dozen (and will at some point get to hundreds) workflows with the same structure:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;[XmlSerializerFormat]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;[ServiceContract(Namespace&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/"&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;IBasicContract&amp;lt;TRequest,&amp;nbsp;TResponse&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TRequest&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TResponse&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[XmlSerializerFormat]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[OperationContract(Name&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"GetReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Action&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReplyAction&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetReportResponse"&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[ServiceKnownType(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(Aggregate))]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;TResponse&amp;nbsp;GetReport(TRequest&amp;nbsp;inquiry);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[XmlSerializerFormat]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[OperationContract(Name&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"GetRawReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Action&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetRawReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReplyAction&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetRawReportResponse"&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetRawReport(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[XmlSerializerFormat]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[OperationContract(Name&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"GetArchiveReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Action&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetArchiveReport"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReplyAction&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"http://schema.company.com/messages/GetArchiveReportResponse"&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[ServiceKnownType(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(Aggregate))]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;TResponse&amp;nbsp;GetArchiveReport(&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I have long wanted to refactor all the workflows to use a common interface, instead of copy-pasting the same code all over the place. Today, after spending 3 days on this, I finally made it :) so I'm saving it here for reference.&lt;br /&gt;&lt;br /&gt;This is the common implementation of the above interface:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;[ServiceBehavior(Namespace&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"http://schema.company.com/messages/"&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;abstract&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicWorkflowSvc&amp;lt;TRequest,&amp;nbsp;TResponse,&amp;nbsp;TWorkflow&amp;gt;&amp;nbsp;:&amp;nbsp;IBasicContract&amp;lt;TRequest,&amp;nbsp;TResponse&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TRequest&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TResponse&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TWorkflow&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;TResponse&amp;nbsp;GetReport(TRequest&amp;nbsp;inquiry)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TResponse&amp;nbsp;res&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;wr&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;WorkflowRuntime())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;waitHandle&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;AutoResetEvent(&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wr.WorkflowCompleted&amp;nbsp;+=&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;delegate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;sender,&amp;nbsp;WorkflowCompletedEventArgs&amp;nbsp;e)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res&amp;nbsp;=&amp;nbsp;(TResponse)&amp;nbsp;e.OutputParameters[&lt;span class="string"&gt;"wfOutput"&lt;/span&gt;&lt;span&gt;];&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;waitHandle.Set();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;arguments&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;arguments.Add(&lt;span class="string"&gt;"wfInput"&lt;/span&gt;&lt;span&gt;,&amp;nbsp;inquiry);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;wi&amp;nbsp;=&amp;nbsp;wr.CreateWorkflow(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(TWorkflow),&amp;nbsp;arguments);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wi.Start();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;waitHandle.WaitOne();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;res;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetRawReport(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;db&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;DBAccess())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;db.LoadGUID(guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;abstract&lt;/span&gt;&lt;span&gt;&amp;nbsp;TResponse&amp;nbsp;GetArchiveReport(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is the client used to call the workflow:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient&amp;lt;TRequest,&amp;nbsp;TResponse&amp;gt;&amp;nbsp;:&amp;nbsp;ClientBase&amp;lt;IBasicContract&amp;lt;TRequest,&amp;nbsp;TResponse&amp;gt;&amp;gt;,&amp;nbsp;IBasicContract&amp;lt;TRequest,&amp;nbsp;TResponse&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TRequest&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TResponse&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpointConfigurationName)&amp;nbsp;:&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;base&lt;/span&gt;&lt;span&gt;(endpointConfigurationName)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpointConfigurationName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;remoteAddress)&amp;nbsp;:&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;base&lt;/span&gt;&lt;span&gt;(endpointConfigurationName,&amp;nbsp;remoteAddress)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpointConfigurationName,&amp;nbsp;EndpointAddress&amp;nbsp;remoteAddress)&amp;nbsp;:&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;base&lt;/span&gt;&lt;span&gt;(endpointConfigurationName,&amp;nbsp;remoteAddress)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient(Binding&amp;nbsp;binding,&amp;nbsp;EndpointAddress&amp;nbsp;remoteAddress)&amp;nbsp;:&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;base&lt;/span&gt;&lt;span&gt;(binding,&amp;nbsp;remoteAddress)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;TResponse&amp;nbsp;GetReport(TRequest&amp;nbsp;inquiry)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Channel.GetReport(inquiry);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetRawReport(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Channel.GetRawReport(guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;TResponse&amp;nbsp;GetArchiveReport(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;guid)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Channel.GetArchiveReport(guid);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is how I call the workflow, using the address retrieved from&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;wf&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicSvcClient&amp;lt;ProductRq_Type,&amp;nbsp;ProductRs_Type&amp;gt;(&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;BasicHttpBinding(&lt;/span&gt;&lt;span class="string"&gt;"httpsDataEndpoint"&lt;/span&gt;&lt;span&gt;),&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;EndpointAddress(tools.FindEndpointAddress(&lt;/span&gt;&lt;span class="string"&gt;"Product.IProductSvc"&lt;/span&gt;&lt;span&gt;))))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;txtConfirmation.Text&amp;nbsp;=&amp;nbsp;wf.GetReport(request).AsXML();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, these are the helper functions (in the tools static class):&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;ChannelEndpointElement&amp;nbsp;FindEndpoint(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpointName)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;cf&amp;nbsp;=&amp;nbsp;(ClientSection)&amp;nbsp;ConfigurationManager.GetSection(&lt;span class="string"&gt;"system.serviceModel/client"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ChannelEndpointElement&amp;nbsp;endpoint&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;cf.Endpoints)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(endpoint.Name&amp;nbsp;==&amp;nbsp;endpointName)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpoint;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;FindEndpointAddress(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpointName)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;endpoint&amp;nbsp;=&amp;nbsp;FindEndpoint(endpointName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;endpoint&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;?&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;:&amp;nbsp;endpoint.Address.ToString();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Well... hope this helps anyone else who has this idea :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2618910450014917324?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2618910450014917324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2618910450014917324' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2618910450014917324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2618910450014917324'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/05/wcf-inheriting-from-common-interface.html' title='WCF - inheriting from a common interface'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5071663217107501573</id><published>2009-05-22T00:42:00.003+03:00</published><updated>2009-05-22T00:53:05.159+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Multi-threaded server</title><content type='html'>This is a reply to &lt;a href="http://stackoverflow.com/questions/869744/how-to-write-a-scalable-tcp-ip-based-server"&gt;this question on stackoverflow&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Many people "feel" that allocating a thread per socket is a bad idea. This might be true for 10,000 sockets, I don't know; however, for 300 threads which are idle most of the time, this is really not an issue - and hasn't been in Windows since at least Windows 2000.&lt;br /&gt;&lt;br /&gt;Here's how this would look on my system:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_61yEjRUm8Pg/ShXMrwfDsqI/AAAAAAAABq0/NczQ915QEq0/s1600-h/manyThreads.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_61yEjRUm8Pg/ShXMrwfDsqI/AAAAAAAABq0/NczQ915QEq0/s320/manyThreads.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5338397985439199906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am going to put the code in the answer to the stackoverflow question; this is just a placeholder for the above image, mostly :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5071663217107501573?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5071663217107501573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5071663217107501573' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5071663217107501573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5071663217107501573'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/05/multi-threaded-server.html' title='Multi-threaded server'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_61yEjRUm8Pg/ShXMrwfDsqI/AAAAAAAABq0/NczQ915QEq0/s72-c/manyThreads.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5654876.post-2362310346271873029</id><published>2009-03-17T15:59:00.001+02:00</published><updated>2009-03-17T16:01:23.230+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>Acting good without being good</title><content type='html'>From &lt;a href="http://slacktivist.typepad.com/slacktivist/2006/01/lb_gods_battere.html?cid=12637014#comment-12637014"&gt;this comment&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;I seem to be known to many of those around me as an all around nice guy, a good guy even. But I'm an asshole, a self-absorbed prick. (...) I often find that I'm doing good things out of an awareness that I should want to do them, than because I actually feel that desire.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This could have been written by me. Ouch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2362310346271873029?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2362310346271873029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2362310346271873029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2362310346271873029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2362310346271873029'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/03/acting-good-without-being-good.html' title='Acting good without being good'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2156509674611150189</id><published>2009-02-10T13:40:00.002+02:00</published><updated>2009-02-10T13:49:21.088+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Single Responsibility Principle - a practical application</title><content type='html'>Many times during the lifetime of a project I find myself writing something like this:&lt;br /&gt;&lt;br /&gt;method A(){&lt;br /&gt;  ...&lt;br /&gt;  var something = B();&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;method B(){&lt;br /&gt;  ...&lt;br /&gt;  var somethingElse = C();&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;It doesn't take long to realize that this could be written in a different way:&lt;br /&gt;&lt;br /&gt;method A(){&lt;br /&gt;  ...&lt;br /&gt;  var somethingElse = C();&lt;br /&gt;  var something = B(somethingElse);&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;method B(somethingElse){&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The problem is - which way should I prefer? Which way is "better"? I have struggled with this for a while now.&lt;br /&gt;&lt;br /&gt;Today I just realized something: SRP (as applied to methods) says each method should only have one reason to change. (I was reading &lt;a href="http://www.kismith.co.uk/wordpress/index.php/2009/01/17/why-unit-test/"&gt;this article&lt;/a&gt; when I had this epiphany.) If something changes in C(), that effect will "ripple" to both B and A in the first case. In the second case, it is much more likely that it will only affect A. Which is fine - it is A's responsibility to "join together" the two other methods, so it's ok if it's affected by them. B, however, has other responsibilities and only needs a result from C() - so it should be isolated from it, as it were.&lt;br /&gt;&lt;br /&gt;Somewhat abstract so far :) I will try to add a concrete example to this post the next time I hit this issue. Who knows, I might be wrong :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2156509674611150189?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2156509674611150189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2156509674611150189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2156509674611150189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2156509674611150189'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/02/single-responsibility-principle.html' title='Single Responsibility Principle - a practical application'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2634799333397037843</id><published>2009-01-22T19:59:00.000+02:00</published><updated>2009-01-22T20:00:33.674+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>I love Paul</title><content type='html'>&lt;a href="http://www.biblegateway.com/passage/?search=1%20cor%206:12&amp;version=31"&gt;1 Cor 6:12&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Everything is permissible for me" — but not everything is beneficial. "Everything is permissible for me" — but I will not be mastered by anything.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2634799333397037843?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2634799333397037843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2634799333397037843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2634799333397037843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2634799333397037843'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/i-love-paul.html' title='I love Paul'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-1130211204480900149</id><published>2009-01-22T19:40:00.003+02:00</published><updated>2009-01-22T19:44:38.606+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>I'm an idiot</title><content type='html'>I worked on a crapload of small ASP.NET projects where I spent a lot of time on user management: add users, edit users, change roles, verify roles and so on. This includes tiny projects like a tiny website where the content of about 10 pages can be edited by the customer (mostly by adding news). They'll never have more than one person doing these edits, their primary business is totally unrelated to computers.&lt;br /&gt;&lt;br /&gt;Well, I was reading &lt;a href="http://www.hanselman.com/blog/RealWorldAppsInDaysNotWeeks.aspx"&gt;this article&lt;/a&gt; by Scott Hanselman and what do I see:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Does it need an administrative console?, I ask. He says that'd be nice, but it wasn't spec'ed out. He figured this would be pretty low rent. The client even suggested (gasp) that they could just maintain a local XML file.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;How on Earth can I be so stupid? I always knew that ASP.NET had this feature... it just never crossed my mind to use it. Dammit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-1130211204480900149?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/1130211204480900149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=1130211204480900149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1130211204480900149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1130211204480900149'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/im-idiot.html' title='I&apos;m an idiot'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-867686040740268194</id><published>2009-01-22T18:59:00.003+02:00</published><updated>2009-01-22T19:05:38.411+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Yes to mentoring, no to certification</title><content type='html'>&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/01/19/mentoring-other-developers.aspx"&gt;Great article here&lt;/a&gt;. I hate the programmers dragging the certification bogey-man every time they have a problem with someone's code. Yeah, we really want to have the problems of the medical field. This article is a breath of fresh air.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-867686040740268194?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/867686040740268194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=867686040740268194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/867686040740268194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/867686040740268194'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/yes-to-mentoring-no-to-certification.html' title='Yes to mentoring, no to certification'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-930033514239960332</id><published>2009-01-21T23:29:00.002+02:00</published><updated>2009-01-21T23:30:26.120+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Take that, ServiceLocator denigrators!</title><content type='html'>From &lt;a href="http://www.martinfowler.com/articles/injection.html"&gt;Inversion of Control Containers and the Dependency Injection pattern&lt;/a&gt; by Martin Fowler:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ha! :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-930033514239960332?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/930033514239960332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=930033514239960332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/930033514239960332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/930033514239960332'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/take-that-servicelocator-denigrators.html' title='Take that, ServiceLocator denigrators!'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-889192796993176881</id><published>2009-01-21T23:05:00.007+02:00</published><updated>2009-01-23T17:45:18.300+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>More on MVC</title><content type='html'>Follow-up to &lt;a href="http://mdpopescu.blogspot.com/2009/01/mvc-explained.html"&gt;this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is the structure I've settled on for the time being:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;View&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Controller&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Service&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Model&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Repository&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Data layer (eg, Linq to SQL)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Data storage (eg, SQL database)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The View, Controller and Service communicate through DTOs (aka ViewModels); the View and Controller never see the (domain) Models. I'm not 100% decided about the Service - Repository interface: should the Model objects be the same as the Data Layer objects? For purity reasons I'd say no - it's a bad idea to return Linq to Sql objects to the Service because it will cause problems when trying to switch to (say) Entity Framework. However, I haven't yet worked on a project big enough that the benefits of this separation outweigh the drawback of creating 3 different classes for the same entity (Linq Order, Model Order, DTO Order). I'll have to see what happens when I actually do work on a larger project (with this architecture I mean, I work on huge projects but not with this structure).&lt;br /&gt;&lt;br /&gt;The Service has two types of methods:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Reads, where it asks the repository for a list of Models (eg Products).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Writes, where it asks the repository for a Model and then asks the Model to do something.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This way I avoid the &lt;a href="http://www.martinfowler.com/bliki/AnemicDomainModel.html"&gt;anemic domain anti-pattern&lt;/a&gt; - the Service layer can stay thin and let the Models provide (most of) the business logic - querying is not completely a business logic concern. (It is more of a reporting concern instead of a transaction concern.)&lt;br /&gt;&lt;br /&gt;Speaking of that, I also need to come up with a way of saying "commit" when I'm doing transactions; each Service method must be a transaction, but I still haven't come up with a way of doing that. (Maybe the EntityService base class - all my Services inherit from it - should have a Commit method that in turns calls for example DataContext.SubmitChanges(). However, that would link the Service to a specific Data Layer, bypassing the repository/ies, which I'd rather not do. Hmm.&lt;br /&gt;&lt;br /&gt;I already clarified the structure of the repository (if only to myself, since I haven't posted my last changes to the interfaces and Linq implementation ). In theory, it shouldn't be a big deal (a day or two) to write a Data Layer for, say, SQLite.&lt;br /&gt;&lt;br /&gt;Well. Good place to save my current thinking on the subject. Hopefully I'm not too far off-mark.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-889192796993176881?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/889192796993176881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=889192796993176881' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/889192796993176881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/889192796993176881'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/more-on-mvc.html' title='More on MVC'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-735617473474012479</id><published>2009-01-14T19:01:00.003+02:00</published><updated>2009-01-14T19:05:24.127+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>TDD and discipline</title><content type='html'>In a comment on &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2008/12/15/oxite-oh-dear-lord-why.aspx"&gt;his article&lt;/a&gt;, Karl Seguin has this to say about the usefulness of TDD:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;My best suggestion was to unit test as you go, and most of these problems would have ironed themselves out. They never would have gotten the 100+ line controller actions under test, and would have had to address the problem upfront.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Well... unfortunately, that only works for someone who truly believes in the value of TDD, figures out the "hint" - and then is disciplined enough to do the right thing. You know what my reaction is, in these cases? Screw the tests, I have code to write!&lt;br /&gt;&lt;br /&gt;Which, of course, is the wrong thing to do. I feel the need for a serenity prayer...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-735617473474012479?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/735617473474012479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=735617473474012479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/735617473474012479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/735617473474012479'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/tdd-and-discipline.html' title='TDD and discipline'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4701771195983081067</id><published>2009-01-14T00:11:00.003+02:00</published><updated>2009-01-21T23:20:54.597+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Nice methods in the ServiceLocator class</title><content type='html'>I just like the way these methods look. I'd take the ServiceLocator class to a job interview :)&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;This&amp;nbsp;is&amp;nbsp;used&amp;nbsp;by&amp;nbsp;the&amp;nbsp;application&amp;nbsp;when&amp;nbsp;it&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;that&amp;nbsp;the&amp;nbsp;application&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;An&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetInstanceOf(Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;lock&lt;/span&gt;&lt;span&gt;&amp;nbsp;(containerLock)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(container.ContainsKey(T))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;container[T]();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;CreateInstance(T)&amp;nbsp;??&amp;nbsp;(OnTypeNotFound&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;?&amp;nbsp;OnTypeNotFound(T)&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;Creates&amp;nbsp;a&amp;nbsp;new&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;nbsp;using&amp;nbsp;the&amp;nbsp;"best"&amp;nbsp;constructor&amp;nbsp;(the&amp;nbsp;one&amp;nbsp;with&amp;nbsp;the&amp;nbsp;biggest&amp;nbsp;number&amp;nbsp;of&amp;nbsp;arguments&amp;nbsp;that&amp;nbsp;are&amp;nbsp;known&amp;nbsp;to&amp;nbsp;the&amp;nbsp;service&amp;nbsp;locator,&amp;nbsp;with&amp;nbsp;the&amp;nbsp;default&amp;nbsp;constructor&amp;nbsp;being&amp;nbsp;the&amp;nbsp;last&amp;nbsp;attempt)&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;instantiate&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;A&amp;nbsp;new&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;nbsp;or&amp;nbsp;null&amp;nbsp;if&amp;nbsp;no&amp;nbsp;suitable&amp;nbsp;constructor&amp;nbsp;has&amp;nbsp;been&amp;nbsp;found&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;CreateInstance(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;constructor&amp;nbsp;=&amp;nbsp;GetBestConstructor(T);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;constructor&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;?&amp;nbsp;constructor.Invoke()&amp;nbsp;:&amp;nbsp;Activator.CreateInstance(T);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;ConstructorInfo&amp;nbsp;GetBestConstructor(Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;(from&amp;nbsp;c&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;T.GetConstructors(BindingFlags.Public)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let&amp;nbsp;parameters&amp;nbsp;=&amp;nbsp;c.GetParameters()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orderby&amp;nbsp;parameters.Length&amp;nbsp;descending&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&amp;nbsp;parameters.All(p&amp;nbsp;=&amp;gt;&amp;nbsp;Contains(p.ParameterType))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select&amp;nbsp;c)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.FirstOrDefault();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;Invoke(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;ConstructorInfo&amp;nbsp;constructor)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;arguments&amp;nbsp;=&amp;nbsp;constructor&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.GetParameters()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.Select(p&amp;nbsp;=&amp;gt;&amp;nbsp;GetInstanceOf(p.ParameterType))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.ToArray();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;constructor.Invoke(arguments);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4701771195983081067?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4701771195983081067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4701771195983081067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4701771195983081067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4701771195983081067'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/nice-methods-in-servicelocator-class.html' title='Nice methods in the ServiceLocator class'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7007226944828027174</id><published>2009-01-13T12:01:00.007+02:00</published><updated>2009-01-13T15:35:54.746+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Really weird C# code</title><content type='html'>My ServiceLocator (which has been further updated since my last post on it, so on the off chance that anybody wants the latest version, leave me a comment) can only register functions with no parameters - Func&lt;t&gt;. What happens if one wants to register a function with one or more parameters?&lt;br /&gt;&lt;br /&gt;As an example, let's say that I have many possible connection strings, and in some cases when I want an instance of DataContext I have to initialize it with one of those. Since my ServiceLocator doesn't accept functions with parameters, I cannot write&lt;br /&gt;&lt;br /&gt;&lt;div class="dp-highlighter" id="hlDiv1"&gt;   &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var dc = ServiceLocator.GetInstanceOf&amp;lt;DataContext&amp;gt;(connectionString);&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here's a way of transforming a function with parameters to one without: create a function that returns the original function. That is, given&lt;br /&gt;&lt;br /&gt;&lt;div class="dp-highlighter" id="hlDiv2"&gt;   &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Func&amp;lt;T1, T&amp;gt; f;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I need another function that will return f:&lt;br /&gt;&lt;br /&gt;&lt;div class="dp-highlighter" id="hlDiv3"&gt;   &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Func&amp;lt;Func&amp;lt;T1, T&amp;gt;&amp;gt; g = () =&amp;gt; (a) =&amp;gt; f(a);&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So, in order to register my DataContext I am now going to use the following syntax:&lt;br /&gt;&lt;br /&gt;&lt;div class="dp-highlighter" id="hlDiv4"&gt;   &lt;div class="bar"&gt;&lt;/div&gt;    &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Bind&amp;lt;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;, DataContext&amp;gt;&amp;gt;.To(() =&amp;gt; (connectionString =&amp;gt; &lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt; DBDataContext(connectionString)));&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and to retrieve the instance and initialize it correctly, I must use:&lt;br /&gt;&lt;br /&gt;&lt;div class="dp-highlighter" id="hlDiv5"&gt;   &lt;div class="bar"&gt;&lt;/div&gt;    &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var dc = ServiceLocator.GetInstanceOf&amp;lt;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;, DataContext&amp;gt;&amp;gt;()(connectionString);&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Not extremely clear, so some helper functions (and confining in a library of sorts) are probably needed.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit&lt;/i&gt;: I just made a change to the ServiceLocator code; one can now write:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var&amp;nbsp;dc&amp;nbsp;=&amp;nbsp;ServiceLocator.GetInstanceOf&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;,&amp;nbsp;DataContext&amp;gt;(&lt;/span&gt;&lt;span class="string"&gt;"connectionString"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is the overload for one argument:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv7" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;GetInstanceOf&amp;lt;T1,&amp;nbsp;T&amp;gt;(T1&amp;nbsp;arg1)&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetInstanceOf&amp;lt;Func&amp;lt;T1,&amp;nbsp;T&amp;gt;&amp;gt;()(arg1);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I only have 3 overloads (up to Func&lt;T1, T2, T3, T&gt;) but that should be enough for anything I might need in the foreseeable future. Oh, and I can still have / use the initial binding too (the one with no connection string). Cool :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7007226944828027174?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7007226944828027174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7007226944828027174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7007226944828027174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7007226944828027174'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/really-weird-c-code.html' title='Really weird C# code'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7514868816288922947</id><published>2009-01-09T15:39:00.004+02:00</published><updated>2009-01-09T15:53:22.381+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Be careful with sample code</title><content type='html'>Found this code somewhere, it doesn't matter where:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;ValidateUser(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strPassword)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;function&amp;nbsp;you&amp;nbsp;need&amp;nbsp;to&amp;nbsp;write.&amp;nbsp;It&amp;nbsp;can&amp;nbsp;do&amp;nbsp;anything&amp;nbsp;you&amp;nbsp;want.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//The&amp;nbsp;code&amp;nbsp;below&amp;nbsp;is&amp;nbsp;just&amp;nbsp;one&amp;nbsp;example.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;strName&amp;nbsp;is&amp;nbsp;really&amp;nbsp;an&amp;nbsp;email&amp;nbsp;address&amp;nbsp;in&amp;nbsp;this&amp;nbsp;implementation&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;validation&amp;nbsp;of&amp;nbsp;the&amp;nbsp;user&amp;nbsp;and&amp;nbsp;password&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolReturn&amp;nbsp;=&amp;nbsp;oUser.ValidateUsersPasswordForLogon(strPassword);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The comments are there because it's a sample, not because they should be there in production code, so that's fine. My problem is with the boolReturn variable.&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;First of all, one rule (&lt;i&gt;Code Complete&lt;/i&gt; should really be required reading for programmers) is that you want to keep assignments to a variable as close as possible to the place where the variable is used. The oUserProvider and oUser variables have nothing to do with the boolReturn, so let's switch the order:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Ok... is the boolReturn variable used anywhere after the return? Not before it's reassigned. That means that, for all intents and purposes, the scope of the variable boolReturn ends here, and a *new* boolReturn variable is created. (Think about it.)&lt;br /&gt;&lt;br /&gt;Let's rewrite the code accordingly (think it through to verify that nothing was changed in the meaning of the code):&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;ValidateUser(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strPassword)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;function&amp;nbsp;you&amp;nbsp;need&amp;nbsp;to&amp;nbsp;write.&amp;nbsp;It&amp;nbsp;can&amp;nbsp;do&amp;nbsp;anything&amp;nbsp;you&amp;nbsp;want.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//The&amp;nbsp;code&amp;nbsp;below&amp;nbsp;is&amp;nbsp;just&amp;nbsp;one&amp;nbsp;example.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;strName&amp;nbsp;is&amp;nbsp;really&amp;nbsp;an&amp;nbsp;email&amp;nbsp;address&amp;nbsp;in&amp;nbsp;this&amp;nbsp;implementation&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;validation&amp;nbsp;of&amp;nbsp;the&amp;nbsp;user&amp;nbsp;and&amp;nbsp;password&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolReturn2&amp;nbsp;=&amp;nbsp;oUser.ValidateUsersPasswordForLogon(strPassword);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;boolReturn2;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Progress. This change makes visible another problem: why set a variable if you're only using it once? (Ok, it makes sense for complicated calculations, but it's not the case here.)&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;ValidateUser(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strPassword)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;function&amp;nbsp;you&amp;nbsp;need&amp;nbsp;to&amp;nbsp;write.&amp;nbsp;It&amp;nbsp;can&amp;nbsp;do&amp;nbsp;anything&amp;nbsp;you&amp;nbsp;want.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//The&amp;nbsp;code&amp;nbsp;below&amp;nbsp;is&amp;nbsp;just&amp;nbsp;one&amp;nbsp;example.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;strName&amp;nbsp;is&amp;nbsp;really&amp;nbsp;an&amp;nbsp;email&amp;nbsp;address&amp;nbsp;in&amp;nbsp;this&amp;nbsp;implementation&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;validation&amp;nbsp;of&amp;nbsp;the&amp;nbsp;user&amp;nbsp;and&amp;nbsp;password&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;oUser.ValidateUsersPasswordForLogon(strPassword);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Frankly, I find the ?: operator to be a great help, so my code would tend to look like the next example, but I understand some people get confused by it, so take your pick:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;ValidateUser(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;strPassword)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;function&amp;nbsp;you&amp;nbsp;need&amp;nbsp;to&amp;nbsp;write.&amp;nbsp;It&amp;nbsp;can&amp;nbsp;do&amp;nbsp;anything&amp;nbsp;you&amp;nbsp;want.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//The&amp;nbsp;code&amp;nbsp;below&amp;nbsp;is&amp;nbsp;just&amp;nbsp;one&amp;nbsp;example.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;strName&amp;nbsp;is&amp;nbsp;really&amp;nbsp;an&amp;nbsp;email&amp;nbsp;address&amp;nbsp;in&amp;nbsp;this&amp;nbsp;implementation&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;Here&amp;nbsp;is&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;user&amp;nbsp;object&amp;nbsp;connecting&amp;nbsp;to&amp;nbsp;your&amp;nbsp;custom&amp;nbsp;membership&amp;nbsp;database&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUserProvider&amp;nbsp;oUserProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyUser&amp;nbsp;oUser&amp;nbsp;=&amp;nbsp;oUserProvider.FindUser(strName);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;oUser&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;?&amp;nbsp;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;oUser.ValidateUsersPasswordForLogon(strPassword);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, what's up with the (bad) Hungarian notation? The fact that the name (or email, whatever) is a string or something else is relevant for the compiler, not for the programmer. The &lt;b&gt;good&lt;/b&gt; Hungarian notation can be useful, but most people seem to only know about the bad variant. Let's get rid of it altogether:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv7" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;ValidateUser(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;name,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;password)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;userProvider&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyUserProvider();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;user&amp;nbsp;=&amp;nbsp;userProvider.FindUser(name);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;user&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;?&amp;nbsp;&lt;span class="keyword"&gt;false&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;user.ValidateUsersPasswordForLogon(password);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To me, this looks much better than the original. Doesn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7514868816288922947?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7514868816288922947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7514868816288922947' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7514868816288922947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7514868816288922947'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/be-careful-with-sample-code.html' title='Be careful with sample code'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7405965913725668701</id><published>2009-01-08T16:51:00.014+02:00</published><updated>2009-01-16T19:49:46.553+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>MVC explained</title><content type='html'>... to myself, as I'm trying to learn it :)&lt;br /&gt;&lt;br /&gt;This is how I'm organizing a project I'm currently working on:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;View&lt;/b&gt; - this is used to render the model as HTML, since this is an ASP.NET project. The View can contain view logic, like displaying negative numbers in red.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;ViewModel&lt;/b&gt; - this is not &lt;b&gt;necessarily&lt;/b&gt; the domain model (database table), but a view-specific model. An Order view, for example, needs to display data from an Order, multiple OrderDetails, a Customer and possibly a Seller (and maybe more). Right now, I handle this case by making a composite class with several properties:&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;OrderModel&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;Order&amp;nbsp;Order&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;lt;OrderDetail&amp;gt;&amp;nbsp;Details&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;Customer&amp;nbsp;Customer&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;Address&amp;nbsp;ShippingAddress&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;CanEditShipping&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is basically a DataTransferObject and is used as such by the view. I realize it would be safer if I created an immutable struct with the necessary data and pass that to the view, but I am too lazy and don't have a tool to do that for me right now. I think this is what Microsoft tried to do with their ViewData dictionary, since it's (normally) strictly write-only for the controller and read-only for the view. This might be easier in C# 4.0, because I can discover properties at runtime, so I can write something like this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;View(&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;{&amp;nbsp;Order&amp;nbsp;=&amp;nbsp;order,&amp;nbsp;OrderDetails&amp;nbsp;=&amp;nbsp;order.Details,&amp;nbsp;Customer&amp;nbsp;=&amp;nbsp;customer,&amp;nbsp;ShippingAddress&amp;nbsp;=&amp;nbsp;order.ShippingAddress,&amp;nbsp;CanEditShipping&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;true&lt;/span&gt;&lt;span&gt;&amp;nbsp;});&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and still use Model.CanEditShipping in the view. (It still requires some discipline to use Model.OrderDetails instead of Model.Order.Details, of course.)&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Controller&lt;/b&gt; - this has three responsibilities in my application: to use the business logic to retrieve the domain models (representing records), combine those into the model as defined above and choose the right view to apply &lt;b&gt;or&lt;/b&gt; the correct path to re-route to (this is the "controller logic"). The controller is very "skinny", usually a couple of lines per action.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Repository&lt;/b&gt; - this is the business logic.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Domain model&lt;/b&gt; - aka tables / records / plain C# objects. Can contain "model logic", like a GetMainImage() method on the Product object that can decide to "promote" an image as main if none of those associated with the product have been flagged as such.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Any glaring mistakes?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit&lt;/i&gt;: I just found &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/12/15/domain-models-in-presentation-frameworks.aspx"&gt;this article by Jimmy Bogard&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit (Jan 16, 2009)&lt;/i&gt;: &lt;a href="http://martinfowler.com/bliki/AnemicDomainModel.html"&gt;Oopsie.&lt;/a&gt; It seems that I'm going to have to revise this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7405965913725668701?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7405965913725668701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7405965913725668701' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7405965913725668701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7405965913725668701'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/mvc-explained.html' title='MVC explained'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7679079597441733955</id><published>2009-01-07T23:48:00.003+02:00</published><updated>2009-01-07T23:57:16.770+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>ServiceLocator anti-pattern?</title><content type='html'>&lt;i&gt;I was trying to reply to &lt;a href="http://blogs.msdn.com/nblumhardt/archive/2008/12/27/container-managed-application-design-prelude-where-does-the-container-belong.aspx"&gt;this article&lt;/a&gt; but for some reason I cannot leave a comment there... there's no error message, my comment is simply ignored. So I'm replying here, hopefully I'll be able at some point to at least reply with the address of this article.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Ok... so if I understand this correctly, Nick's problems with the ServiceLocator pattern are:&lt;br /&gt;&lt;br /&gt;1) Because it's global, it cannot be tested&lt;br /&gt;2) Sometimes we want to return the same instance for all Resolve() calls, sometimes a thread- or HttpContext-specific instance, sometimes a new instance each time; can't do that with a dictionary&lt;br /&gt;&lt;br /&gt;(I'm ignoring the points in the "Problems with..." section because I can't understand any of them. "All of the robustness that is achieved by forcing components to publicly declare dependencies is lost." - why? "When dependencies are retrieved from a global container, the container does not know the identity of the requestor, and is forced to return the same implementation every time." - this is a GOOD thing. You want an instance of X, it shouldn't depend on the requestor - if it does, make many kinds of Xs - it's obviously not the same X. "Concurrency, re-entrancy, circular reference detection, and component lifetime management are much harder/messier in a global container based solution." - again, why?)&lt;br /&gt;&lt;br /&gt;It's weird, a real coincidence, but a few days after he wrote this article (which I've only discovered half an hour ago) I wrote a ServiceLocator implementation. &lt;a href="http://mdpopescu.blogspot.com/2008/12/5-minute-dependency-injection-in-c-i.html"&gt;This&lt;/a&gt; was my first post on the subject, followed by &lt;a href="http://mdpopescu.blogspot.com/2008/12/servicelocator-redivivus-this-is-so-far.html"&gt;this one&lt;/a&gt; and finally &lt;a href="http://mdpopescu.blogspot.com/2009/01/more-on-servicelocator-caching.html"&gt;this&lt;/a&gt;. As shown in the last post, this is one way it can be used:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Bind&amp;lt;IProductRepository&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;.To(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;.CacheBy(InstanceScope.HttpContext);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Can you take a look at this and point out where I'm wrong? I agree, right now I do NOT use any kinds of magic to get rid of the&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var&amp;nbsp;repository&amp;nbsp;=&amp;nbsp;ServiceLocator.GetInstanceOf&amp;lt;IProductRepository&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;calls, but I do not actually find that a problem (at least not yet). In fact, if I could find a way that doesn't look forced to replace it with something else, I will probably look into it. (Decorating properties or constructors with [Inject] attributes looks a little weird, but maybe I'm mistaken.)&lt;br /&gt;&lt;br /&gt;I've started using this in a project and, so far, everything seems to be OK. I'm definitely open to the idea that problems are lurking in the background though, so I'll appreciate any hint you can give me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7679079597441733955?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7679079597441733955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7679079597441733955' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7679079597441733955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7679079597441733955'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/servicelocator-anti-pattern.html' title='ServiceLocator anti-pattern?'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5654876.post-6595276879908430816</id><published>2009-01-07T15:46:00.004+02:00</published><updated>2009-01-07T16:03:03.976+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Returning a default value in case of errors</title><content type='html'>Ever wrote something like this?&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(a&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;a.b&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;a.b.c&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;a.b.c.d;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I hate it. Given that I'm processing some XML files whose schemas I cannot change, there's not much to be done but bite the bullet.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.objectmentor.com/articles/2009/01/05/abstracting-away-from-exceptions"&gt;This page&lt;/a&gt; gave me the idea for the following helper functions:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;Eval&amp;lt;T,&amp;nbsp;ExceptionClass&amp;gt;(Func&amp;lt;T&amp;gt;&amp;nbsp;func,&amp;nbsp;Func&amp;lt;ExceptionClass,&amp;nbsp;T&amp;gt;&amp;nbsp;onError)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;ExceptionClass:&amp;nbsp;Exception&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;try&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;func();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;catch&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ExceptionClass&amp;nbsp;e)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;onError(e);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;Eval&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt;&amp;nbsp;func,&amp;nbsp;Func&amp;lt;Exception,&amp;nbsp;T&amp;gt;&amp;nbsp;onError)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Eval&amp;lt;T,&amp;nbsp;Exception&amp;gt;(func,&amp;nbsp;onError);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;Eval&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt;&amp;nbsp;func,&amp;nbsp;T&amp;nbsp;defaultValue)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Eval&amp;lt;T,&amp;nbsp;Exception&amp;gt;(func,&amp;nbsp;e&amp;nbsp;=&amp;gt;&amp;nbsp;defaultValue);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now I can write this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;result&amp;nbsp;=&amp;nbsp;Helper.Eval(()&amp;nbsp;=&amp;gt;&amp;nbsp;a.b.c.d,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As an aside, it's really annoying not being able to write something like this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;Something&amp;lt;T&amp;gt;(Func&amp;lt;T[]&amp;gt;&amp;nbsp;func)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;instead of writing say 5 overloads for Func&amp;lt;T&amp;gt; to Func&amp;lt;T1, T2, T3, T4, T&amp;gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6595276879908430816?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6595276879908430816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6595276879908430816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6595276879908430816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6595276879908430816'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/returning-default-value-in-case-of.html' title='Returning a default value in case of errors'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5124706461024603144</id><published>2009-01-03T01:15:00.002+02:00</published><updated>2009-01-03T01:18:29.765+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>More on ServiceLocator - caching</title><content type='html'>&lt;p&gt;I got an idea while watching &lt;a href="http://blog.wekeroad.com/mvc-storefront/mvcstore-part-13/"&gt;this webcast with Rob Conery and Jeremy Miller&lt;/a&gt; - Jeremy was talking about StructureMap and how you can set caching with it. It took me a few hours but I managed to duplicate that functionality. Of course, it doesn't work when you call Discover() - that one will still be the regular un-cached call (I think Jeremy calls it PerInstance).&lt;/p&gt;  &lt;p&gt;This is an usage example:&lt;/p&gt;  &lt;div class="dp-highlighter" id="hlDiv1"&gt;   &lt;div class="bar"&gt;&lt;/div&gt;    &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Bind&amp;lt;DataContext&amp;gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; .To(() =&amp;gt; &lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt; DBDataContext())&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; .CacheBy(InstanceScope.Singleton);&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;Bind&amp;lt;IProductRepository&amp;gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; .To(() =&amp;gt; &lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt; ProductRepository())&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; .CacheBy(InstanceScope.HttpContext);&amp;#160; &lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;  &lt;p&gt;Here are the helper classes in all their glory:&lt;/p&gt;  &lt;div class="dp-highlighter" id="hlDiv2"&gt;   &lt;div class="bar"&gt;&lt;/div&gt;    &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt; System;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt; System.Collections.Generic;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt; System.Threading;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt; System.Web;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt; Helper&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;{&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;// usage:&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;// Bind&amp;lt;ISomething&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;//&amp;#160;&amp;#160; .To(() =&amp;gt; new Something())&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;//&amp;#160;&amp;#160; .CacheBy(InstanceScope.ThreadLocal);&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;/// Fluent interface simplifying the registration of implementations&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;typeparam name=&amp;quot;T&amp;quot;&amp;gt;Type to implement&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;example&amp;gt;Bind&amp;amp;lt;IRepository&amp;amp;gt;.To(() =&amp;gt; new Repository());&amp;lt;/example&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt; Bind&amp;lt;T&amp;gt; where T : &lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="comment"&gt;/// Maps T to Func&amp;amp;lt;T&amp;amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="comment"&gt;/// &amp;lt;param name=&amp;quot;func&amp;quot;&amp;gt;Function returning an instance of T&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt; BindHelper&amp;lt;T&amp;gt; To(Func&amp;lt;T&amp;gt; func)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ServiceLocator.Register(func);&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt; BindHelper&amp;lt;T&amp;gt;(func);&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt; BindHelper&amp;lt;T&amp;gt; where T : &lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt; Func&amp;lt;T&amp;gt; func;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt; BindHelper(Func&amp;lt;T&amp;gt; func)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;.func = func;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt; CacheBy(InstanceScope scope)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ServiceLocator.Unregister&amp;lt;T&amp;gt;();&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ServiceLocator.Register(Memoize(scope));&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt; Dictionary&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt; cache = &lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt; Dictionary&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;();&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt; Func&amp;lt;T&amp;gt; Memoize(InstanceScope scope)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Func&amp;lt;Type, &lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt; GetTypeKey;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;switch&lt;/span&gt;&lt;span&gt; (scope)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;case&lt;/span&gt;&lt;span&gt; InstanceScope.NoCaching:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt; func;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;case&lt;/span&gt;&lt;span&gt; InstanceScope.Singleton:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetTypeKey = type =&amp;gt; type.ToString();&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;break&lt;/span&gt;&lt;span&gt;;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;case&lt;/span&gt;&lt;span&gt; InstanceScope.ThreadLocal:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetTypeKey = type =&amp;gt; type + &lt;span class="string"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span&gt; + Thread.CurrentThread.ManagedThreadId;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;break&lt;/span&gt;&lt;span&gt;;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;case&lt;/span&gt;&lt;span&gt; InstanceScope.HttpContext:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetTypeKey = type =&amp;gt; type + &lt;span class="string"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span&gt; + HttpContext.Current;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;break&lt;/span&gt;&lt;span&gt;;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;case&lt;/span&gt;&lt;span&gt; InstanceScope.Hybrid:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetTypeKey = type =&amp;gt; type + &lt;span class="string"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span&gt; + HttpContext.Current ?? Thread.CurrentThread.ManagedThreadId.ToString();&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;break&lt;/span&gt;&lt;span&gt;;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;default&lt;/span&gt;&lt;span&gt;:&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GetTypeKey = type =&amp;gt; type.ToString();&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;break&lt;/span&gt;&lt;span&gt;;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt; () =&amp;gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt; result;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt; (!cache.TryGetValue(GetTypeKey(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;(T)), &lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt; result))&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cache[GetTypeKey(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;(T))] = func();&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt; cache[GetTypeKey(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;(T))] &lt;/span&gt;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt; T;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;}&amp;#160; &lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;  &lt;p&gt;By all means, if you can figure out a way to simplify this, let me know :)&lt;/p&gt;  &lt;p&gt;Ah, I forgot the InstanceScope enum:&lt;/p&gt;  &lt;div class="dp-highlighter" id="hlDiv3"&gt;   &lt;div class="bar"&gt;&lt;/div&gt;    &lt;ol class="dp-c"&gt;     &lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt; Helper&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;{&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160; &lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;#160;&lt;/span&gt;&lt;span class="keyword"&gt;enum&lt;/span&gt;&lt;span&gt; InstanceScope&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; {&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; HttpContext,&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; Hybrid,&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; ThreadLocal,&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; Singleton,&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;&amp;#160;&amp;#160;&amp;#160; NoCaching&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class=""&gt;&lt;span&gt;&amp;#160; }&amp;#160; &lt;/span&gt;&lt;/li&gt;      &lt;li class="alt"&gt;&lt;span&gt;}&amp;#160; &lt;/span&gt;&lt;/li&gt;   &lt;/ol&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5124706461024603144?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5124706461024603144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5124706461024603144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5124706461024603144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5124706461024603144'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2009/01/more-on-servicelocator-caching.html' title='More on ServiceLocator - caching'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5018103911257855115</id><published>2008-12-31T01:06:00.001+02:00</published><updated>2008-12-31T01:07:53.168+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='copyright'/><title type='text'>I couldn't possibly say this any better...</title><content type='html'>Comment by LKM on &lt;a href="http://www.codinghorror.com/blog/archives/001201.html"&gt;http://www.codinghorror.com/blog/archives/001201.html&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;About convenience:&lt;br /&gt;&lt;br /&gt;Pirated media is not free to the pirate. He pays with his time. Now you can't compete with the price of time for people who don't work. To most teenagers, time is way less valuable than money. No matter how convenient you make buying your stuff, these people won't give you their money. However, that is not the case for people who have jobs. To people like us, even finding a working torrent file may not be worth the hassle if we can instead open the Amazon MP3 store, type the name of the song we want and click "buy".&lt;br /&gt;&lt;br /&gt;In many cases, the price doesn't even enter the equation. To me, whether I have ten bucks more or less on my credit card statement at the end of the month simply doesn't matter at all. What matters is whether I spend ten minutes looking for a song, or ten seconds.&lt;br /&gt;&lt;br /&gt;Ironically, DRM makes it *less* convenient to buy, thus giving potential customers more incentive to pirate.&lt;br /&gt;&lt;br /&gt;About instant gratification:&lt;br /&gt;&lt;br /&gt;If possible, allow users to download whatever you're selling. Don't make them wait for the Amazon package to arrive if you can avoid it. Give them a file they can download right after clicking "buy", and don't make them pay additionally for the privilege.&lt;br /&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5018103911257855115?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5018103911257855115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5018103911257855115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5018103911257855115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5018103911257855115'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/12/i-couldnt-possibly-say-this-any-better.html' title='I couldn&apos;t possibly say this any better...'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2719345671169666565</id><published>2008-12-30T19:50:00.007+02:00</published><updated>2009-06-06T10:27:50.426+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Repository pattern</title><content type='html'>&lt;span style="font-style:italic;"&gt;[Edited on June 6, 2009.]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is my implementation of the Repository pattern in C#; I am using the ServiceLocator defined in &lt;a href="http://mdpopescu.blogspot.com/2008/12/servicelocator-redivivus-this-is-so-far.html"&gt;my previous post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is the main interface:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;IRepository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TEntity:&amp;nbsp;IEntity&amp;lt;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Returns&amp;nbsp;all&amp;nbsp;entities&amp;nbsp;in&amp;nbsp;the&amp;nbsp;repository&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;List&amp;nbsp;of&amp;nbsp;entities&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;GetAll();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Returns&amp;nbsp;all&amp;nbsp;entities&amp;nbsp;matching&amp;nbsp;a&amp;nbsp;criteria&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="criteria"&amp;gt;Criteria&amp;nbsp;to&amp;nbsp;be&amp;nbsp;matched&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;All&amp;nbsp;entities&amp;nbsp;matching&amp;nbsp;the&amp;nbsp;criteria;&amp;nbsp;should&amp;nbsp;not&amp;nbsp;be&amp;nbsp;null,&amp;nbsp;but&amp;nbsp;it&amp;nbsp;can&amp;nbsp;be&amp;nbsp;an&amp;nbsp;empty&amp;nbsp;list&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;FindAll(Expression&amp;lt;Func&amp;lt;TEntity,&amp;nbsp;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;criteria);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Returns&amp;nbsp;the&amp;nbsp;first&amp;nbsp;entity&amp;nbsp;matching&amp;nbsp;a&amp;nbsp;criteria&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="criteria"&amp;gt;Criteria&amp;nbsp;to&amp;nbsp;be&amp;nbsp;matched&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;The&amp;nbsp;first&amp;nbsp;entity&amp;nbsp;that&amp;nbsp;matches&amp;nbsp;a&amp;nbsp;criteria;&amp;nbsp;can&amp;nbsp;be&amp;nbsp;null&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;TEntity&amp;nbsp;Find(Expression&amp;lt;Func&amp;lt;TEntity,&amp;nbsp;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;criteria);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Finds&amp;nbsp;a&amp;nbsp;record&amp;nbsp;with&amp;nbsp;a&amp;nbsp;given&amp;nbsp;id&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="id"&amp;gt;Key&amp;nbsp;to&amp;nbsp;search&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;The&amp;nbsp;record&amp;nbsp;with&amp;nbsp;the&amp;nbsp;given&amp;nbsp;id&amp;nbsp;or&amp;nbsp;null&amp;nbsp;if&amp;nbsp;none&amp;nbsp;exists&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;TEntity&amp;nbsp;Find(TId&amp;nbsp;id);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now, I am always creating a primary key for each table, and nowadays I call it Id. It's normally an autoincrementing integer, but for users or other sensitive information I will probably switch to GUIDs, so the type of the primary key should be a parameter. Here is the entity interface, representing a record in a table:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt;&amp;nbsp;Helper&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEntity&amp;lt;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TId&amp;nbsp;Id&amp;nbsp;{&amp;nbsp;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the only relevant thing is the primary key :)&lt;br /&gt;&lt;br /&gt;I've extracted the updates to another repository... this is incompletely refined, you might need more granularity (some repositories might support updates but not deletes, for example).&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;IUpdateableRepository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TEntity&amp;nbsp;:&amp;nbsp;IEntity&amp;lt;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Adds&amp;nbsp;an&amp;nbsp;entity&amp;nbsp;to&amp;nbsp;the&amp;nbsp;repository;&amp;nbsp;the&amp;nbsp;repository&amp;nbsp;may&amp;nbsp;change&amp;nbsp;the&amp;nbsp;entity's&amp;nbsp;Id&amp;nbsp;on&amp;nbsp;adding&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="entity"&amp;gt;Entity&amp;nbsp;to&amp;nbsp;add&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Add(TEntity&amp;nbsp;entity);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Deletes&amp;nbsp;an&amp;nbsp;entity&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="entity"&amp;gt;Entity&amp;nbsp;to&amp;nbsp;delete&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Delete(TEntity&amp;nbsp;entity);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Updates&amp;nbsp;an&amp;nbsp;entity&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="entity"&amp;gt;Entity&amp;nbsp;to&amp;nbsp;update&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Update(TEntity&amp;nbsp;entity);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Commits&amp;nbsp;all&amp;nbsp;changes&amp;nbsp;made&amp;nbsp;so&amp;nbsp;far&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Commit();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, this is a possible implementation of a repository, using the DI pattern (and the ServiceLocator class):&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Repository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;:&amp;nbsp;IRepository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TEntity&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;,&amp;nbsp;IEntity&amp;lt;TId&amp;gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;protected&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;data;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;Repository(IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;data)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;.data&amp;nbsp;=&amp;nbsp;data;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#region&amp;nbsp;IRepository&amp;lt;TEntity&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;GetAll()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;data;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;lt;TEntity&amp;gt;&amp;nbsp;FindAll(Expression&amp;lt;Func&amp;lt;TEntity,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;criteria)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;cond&amp;nbsp;=&amp;nbsp;criteria.Compile();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;from&amp;nbsp;entity&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;data&amp;nbsp;where&amp;nbsp;cond(entity)&amp;nbsp;select&amp;nbsp;entity;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;TEntity&amp;nbsp;Find(Expression&amp;lt;Func&amp;lt;TEntity,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;criteria)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;cond&amp;nbsp;=&amp;nbsp;criteria.Compile();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;(from&amp;nbsp;entity&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;data&amp;nbsp;where&amp;nbsp;cond(entity)&amp;nbsp;select&amp;nbsp;entity).FirstOrDefault();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;virtual&lt;/span&gt;&lt;span&gt;&amp;nbsp;TEntity&amp;nbsp;Find(TId&amp;nbsp;id)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Find(entity&amp;nbsp;=&amp;gt;&amp;nbsp;entity.Id.Equals(id));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#endregion&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;LinqRepository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;:&amp;nbsp;Repository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;,&amp;nbsp;IUpdateableRepository&amp;lt;TEntity,&amp;nbsp;TId&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;where&amp;nbsp;TEntity&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;,&amp;nbsp;IEntity&amp;lt;TId&amp;gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;protected&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;DataContext&amp;nbsp;db;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;LinqRepository()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;(ServiceLocator.GetInstanceOf&amp;lt;DataContext&amp;gt;())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;LinqRepository(DataContext&amp;nbsp;db)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;base&lt;/span&gt;&lt;span&gt;(db.GetTable&amp;lt;TEntity&amp;gt;())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;.db&amp;nbsp;=&amp;nbsp;db;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#region&amp;nbsp;IRepository&amp;lt;TEntity&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#endregion&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#region&amp;nbsp;IUpdateableRepository&amp;lt;TEntity&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Add(TEntity&amp;nbsp;entity)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;((Table&amp;lt;TEntity&amp;gt;)&amp;nbsp;data).InsertOnSubmit(entity);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Delete(TEntity&amp;nbsp;entity)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;((Table&amp;lt;TEntity&amp;gt;)&amp;nbsp;data).DeleteOnSubmit(entity);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Update(TEntity&amp;nbsp;entity)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;((Table&amp;lt;TEntity&amp;gt;)&amp;nbsp;data).Attach(entity,&amp;nbsp;&lt;span class="keyword"&gt;true&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Commit()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;db.SubmitChanges();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="preprocessor"&gt;&amp;nbsp;&amp;nbsp;#endregion&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note: since I initially wrote this, I have read a few more articles discussing the need of using the Repository pattern at all. Here's a list of pro and con articles... decide for yourself :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx"&gt;Ayende's article&lt;/a&gt;, first one I read on the subject.&lt;br /&gt;Greg Young's &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx"&gt;first&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2009/04/23/repository-is-dead-long-live-repository.aspx"&gt;second&lt;/a&gt; and &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2009/04/24/more-on-repository.aspx"&gt;third&lt;/a&gt; article.&lt;br /&gt;Richard Dingwall's &lt;a href="http://richarddingwall.name/2009/01/19/irepositoryt-one-size-does-not-fit-all/"&gt;article&lt;/a&gt;.&lt;br /&gt;&lt;a href="http://thinkbeforecoding.com/post/2009/04/08/Back-on-Repositories-and-Paging-Introducing-reporting"&gt;This article&lt;/a&gt; suggests an interesting split - you should have two domains, one for changing your domain and one for querying it, and the two would have very different repositories. I have to think about it :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2719345671169666565?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2719345671169666565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2719345671169666565' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2719345671169666565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2719345671169666565'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/12/repository-pattern.html' title='Repository pattern'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-8527044712248498450</id><published>2008-12-30T14:15:00.013+02:00</published><updated>2008-12-30T20:02:31.960+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>ServiceLocator redivivus</title><content type='html'>This is the (so far) final form of the ServiceLocator class:&lt;br /&gt;&lt;br /&gt;&lt;!-- Code --&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System.Collections.Generic;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System.Linq;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System.Reflection;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt;&amp;nbsp;Helper&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;ServiceLocator&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;Dictionary&amp;lt;Type,&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;container&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Dictionary&amp;lt;Type,&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;containerLock&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;Func&amp;lt;Type,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;OnTypeNotFound&amp;nbsp;=&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type&amp;nbsp;=&amp;gt;&amp;nbsp;{&amp;nbsp;&lt;span class="keyword"&gt;throw&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotSupportedException(&lt;/span&gt;&lt;span class="string"&gt;"Cannot&amp;nbsp;resolve&amp;nbsp;type&amp;nbsp;"&lt;/span&gt;&lt;span&gt;&amp;nbsp;+&amp;nbsp;type);&amp;nbsp;};&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Discovers&amp;nbsp;all&amp;nbsp;the&amp;nbsp;classes&amp;nbsp;decorated&amp;nbsp;with&amp;nbsp;the&amp;nbsp;Register&amp;nbsp;attribute&amp;nbsp;and&amp;nbsp;registers&amp;nbsp;them&amp;nbsp;as&amp;nbsp;implementations&amp;nbsp;of&amp;nbsp;the&amp;nbsp;ImplementedType&amp;nbsp;argument&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Discover()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;types&amp;nbsp;=&amp;nbsp;Assembly.GetCallingAssembly().GetTypes().ToList();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;types.ForEach(type&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;attr&amp;nbsp;=&amp;nbsp;type.GetCustomAttribute&amp;lt;RegisterAttribute&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(attr&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Register(attr.ImplementedType,&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;Activator.CreateInstance(type));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Helper&amp;nbsp;function&amp;nbsp;to&amp;nbsp;return&amp;nbsp;a&amp;nbsp;custom&amp;nbsp;attribute&amp;nbsp;of&amp;nbsp;a&amp;nbsp;specified&amp;nbsp;type&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Desired&amp;nbsp;type&amp;nbsp;for&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;attribute&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="type"&amp;gt;Type&amp;nbsp;searched&amp;nbsp;for&amp;nbsp;the&amp;nbsp;custom&amp;nbsp;attribute&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;The&amp;nbsp;custom&amp;nbsp;attribute&amp;nbsp;or&amp;nbsp;null&amp;nbsp;if&amp;nbsp;it&amp;nbsp;was&amp;nbsp;not&amp;nbsp;found&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;GetCustomAttribute&amp;lt;T&amp;gt;(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;ICustomAttributeProvider&amp;nbsp;type)&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;type.GetCustomAttributes(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T),&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;true&lt;/span&gt;&lt;span&gt;).FirstOrDefault()&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Maps&amp;nbsp;the&amp;nbsp;type&amp;nbsp;T&amp;nbsp;to&amp;nbsp;a&amp;nbsp;function&amp;nbsp;returning&amp;nbsp;T&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;requested&amp;nbsp;by&amp;nbsp;the&amp;nbsp;application&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="func"&amp;gt;Function&amp;nbsp;returning&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Register&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt;&amp;nbsp;func)&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Register(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T),&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;func());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Maps&amp;nbsp;the&amp;nbsp;type&amp;nbsp;T&amp;nbsp;to&amp;nbsp;a&amp;nbsp;function&amp;nbsp;returning&amp;nbsp;T&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;requested&amp;nbsp;by&amp;nbsp;the&amp;nbsp;application&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="func"&amp;gt;Function&amp;nbsp;returning&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Register(Type&amp;nbsp;T,&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;func)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(Contains(T))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;throw&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ArgumentException(&lt;/span&gt;&lt;span class="string"&gt;"Type&amp;nbsp;"&lt;/span&gt;&lt;span&gt;&amp;nbsp;+&amp;nbsp;T&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"&amp;nbsp;already&amp;nbsp;registered."&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;lock&lt;/span&gt;&lt;span&gt;&amp;nbsp;(containerLock)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;container.Add(T,&amp;nbsp;func);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Removes&amp;nbsp;the&amp;nbsp;association&amp;nbsp;for&amp;nbsp;type&amp;nbsp;T&amp;nbsp;(for&amp;nbsp;example&amp;nbsp;as&amp;nbsp;a&amp;nbsp;preparation&amp;nbsp;for&amp;nbsp;another&amp;nbsp;registration)&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;unregister&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Unregister&amp;lt;T&amp;gt;()&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Unregister(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Removes&amp;nbsp;the&amp;nbsp;association&amp;nbsp;for&amp;nbsp;type&amp;nbsp;T&amp;nbsp;(for&amp;nbsp;example&amp;nbsp;as&amp;nbsp;a&amp;nbsp;preparation&amp;nbsp;for&amp;nbsp;another&amp;nbsp;registration)&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;unregister&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Unregister(Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;lock&lt;/span&gt;&lt;span&gt;&amp;nbsp;(containerLock)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;container.Remove(T);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Returns&amp;nbsp;true&amp;nbsp;if&amp;nbsp;the&amp;nbsp;type&amp;nbsp;T&amp;nbsp;is&amp;nbsp;registered&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;check&amp;nbsp;for&amp;nbsp;an&amp;nbsp;existing&amp;nbsp;registration&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;True&amp;nbsp;if&amp;nbsp;T&amp;nbsp;is&amp;nbsp;registered&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;Contains&amp;lt;T&amp;gt;()&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Contains(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Returns&amp;nbsp;true&amp;nbsp;if&amp;nbsp;the&amp;nbsp;type&amp;nbsp;T&amp;nbsp;is&amp;nbsp;registered&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;check&amp;nbsp;for&amp;nbsp;an&amp;nbsp;existing&amp;nbsp;registration&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;True&amp;nbsp;if&amp;nbsp;T&amp;nbsp;is&amp;nbsp;registered&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;Contains(Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;lock&lt;/span&gt;&lt;span&gt;&amp;nbsp;(containerLock)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;container.ContainsKey(T);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;This&amp;nbsp;is&amp;nbsp;used&amp;nbsp;by&amp;nbsp;the&amp;nbsp;application&amp;nbsp;when&amp;nbsp;it&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;that&amp;nbsp;the&amp;nbsp;application&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;An&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;GetInstanceOf&amp;lt;T&amp;gt;()&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetInstanceOf(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T))&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;This&amp;nbsp;is&amp;nbsp;used&amp;nbsp;by&amp;nbsp;the&amp;nbsp;application&amp;nbsp;when&amp;nbsp;it&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;that&amp;nbsp;the&amp;nbsp;application&amp;nbsp;needs&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;returns&amp;gt;An&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetInstanceOf(Type&amp;nbsp;T)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;lock&lt;/span&gt;&lt;span&gt;&amp;nbsp;(containerLock)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Func&amp;lt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;result;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(container.TryGetValue(T,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;result))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;result();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;OnTypeNotFound&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;?&amp;nbsp;OnTypeNotFound(T)&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Features:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;OnTypeNotFound() - function mapping a type to an object if there is no explicit mapping for it. By default it will throw an exception, but you can replace it if you want, for example, to automatically Mock all types not explicitly mapped.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Discover() - this will inspect the calling assembly and automatically register as implementations all types decorated with the Register attribute.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Register() - maps a type (normally an interface type, but that's not required) to a Func&lt;&gt; returning an instance of that type. This allows, for example, a singleton implementation where the Func&lt;&gt; always returns the same object. Register() will throw if the type was already registered to avoid overwriting a registration by mistake; for intentional overwriting, use Unregister() first.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Unregister() - removes an existing mapping; does not throw even if one does not exist.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Contains() - can be used to verify that a type is registered, as GetInstanceOf() will by default throw if it's not.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;GetInstanceOf() - this finds the function mapped to the given type and executes it, returning its result; if a mapping for this type is not found, GetInstanceOf() returns OnTypeNotFound() - which implicitly throws but can be overwritten.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The automatic registration (the Discover() method) needs implementation classes to be decorated with the Register attribute:&lt;br /&gt;&lt;br /&gt;&lt;!-- Code --&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt;&amp;nbsp;Helper&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Use&amp;nbsp;this&amp;nbsp;attribute&amp;nbsp;to&amp;nbsp;decorate&amp;nbsp;classes&amp;nbsp;that&amp;nbsp;should&amp;nbsp;be&amp;nbsp;registered&amp;nbsp;as&amp;nbsp;implementations&amp;nbsp;of&amp;nbsp;the&amp;nbsp;argument&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;example&amp;gt;[Register(IRepository)]&amp;lt;/example&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;[AttributeUsage(AttributeTargets.Class,&amp;nbsp;AllowMultiple&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;true&lt;/span&gt;&lt;span&gt;)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;RegisterAttribute&amp;nbsp;:&amp;nbsp;Attribute&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;Type&amp;nbsp;ImplementedType&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;RegisterAttribute()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;RegisterAttribute(Type&amp;nbsp;implementedType)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ImplementedType&amp;nbsp;=&amp;nbsp;implementedType;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, I have also created a helper class for manual registration:&lt;br /&gt;&lt;br /&gt;&lt;!-- Code --&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt;&amp;nbsp;Helper&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Fluent&amp;nbsp;interface&amp;nbsp;simplifying&amp;nbsp;the&amp;nbsp;registration&amp;nbsp;of&amp;nbsp;implementations&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;typeparam&amp;nbsp;name="T"&amp;gt;Type&amp;nbsp;to&amp;nbsp;implement&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;example&amp;gt;Bind&amp;amp;lt;IRepository&amp;amp;gt;.To(()&amp;nbsp;=&amp;gt;&amp;nbsp;new&amp;nbsp;Repository());&amp;lt;/example&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Bind&amp;lt;T&amp;gt;&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;Maps&amp;nbsp;T&amp;nbsp;to&amp;nbsp;Func&amp;amp;lt;T&amp;amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;///&amp;nbsp;&amp;lt;param&amp;nbsp;name="func"&amp;gt;Function&amp;nbsp;returning&amp;nbsp;an&amp;nbsp;instance&amp;nbsp;of&amp;nbsp;T&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;To(Func&amp;lt;T&amp;gt;&amp;nbsp;func)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ServiceLocator.Register(func);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Decorating a class is obvious:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;[Register(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(DataContext))]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;partial&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;DBDataContext&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In the initial part of the application (like Global.asax.cs) you can do either this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;ServiceLocator.Discover();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;or this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;Bind&amp;lt;DataContext&amp;gt;.To(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;DBDataContext());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;Bind&amp;lt;IProductRepository&amp;gt;.To(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;Bind&amp;lt;IImageRepository&amp;gt;.To(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ImageRepository());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally (!), replace all "new class()" with:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv7" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var&amp;nbsp;repository&amp;nbsp;=&amp;nbsp;ServiceLocator.GetInstanceOf&amp;lt;IProductRepository&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In fact, it is recommended that you do not "hide" the dependencies, which means creating (usually) two constructors: one explicitly indicating dependencies and a default one calling the first, like this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv8" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController&amp;nbsp;:&amp;nbsp;Controller&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;IProductRepository&amp;nbsp;repository;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController()&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;(ServiceLocator.GetInstanceOf&amp;lt;IProductRepository&amp;gt;())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController(IProductRepository&amp;nbsp;repository)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;.repository&amp;nbsp;=&amp;nbsp;repository;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Whew :) Please let me know if this helps, or if you find any problems with it :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-8527044712248498450?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/8527044712248498450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=8527044712248498450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8527044712248498450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8527044712248498450'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/12/servicelocator-redivivus-this-is-so-far.html' title='ServiceLocator redivivus'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-1505052090444787673</id><published>2008-12-28T20:43:00.025+02:00</published><updated>2008-12-30T15:26:41.033+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>5-minute dependency injection container in C#</title><content type='html'>I found &lt;a href="http://misko.hevery.com/"&gt;Misko Hevery's&lt;/a&gt; talks on the usefulness of Dependency Injection to be quite persuasive, so I have started using constructor DI in my projects. Unfortunately, some of those involve ASP.NET WebForms applications, and even in the one I just started using ASP.NET MVC there are classes I do not create myself (like the controllers). This means that when I write something like&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository&amp;nbsp;repository;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repository&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I am hard-coding a dependency on the concrete ProductRepository class inside ProductController.&lt;br /&gt;&lt;br /&gt;There are (at least) two solutions to this. One of them would be to create a property in the ProductController class:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;IProductRepository&amp;nbsp;Repository&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and change the constructor to&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Repository&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is the usual property dependency injection, and it works quite well. However, I find it annoying to do this for every class, not to mention that I don't like the idea of adding a public property just so I can test the class, since this breaks the information hiding tenet.&lt;br /&gt;&lt;br /&gt;A variant of this option is to have two constructors:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController():&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController(IProductRepository&amp;nbsp;repository)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Repository&amp;nbsp;=&amp;nbsp;repository;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;A second option would be to use a DI container and do this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductController()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;repository&amp;nbsp;=&amp;nbsp;Container.Get&amp;lt;IProductRepository&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and somehow instruct the program, in the initialization part (like Global.asax.cs), to return a new ProductRepository instance every time I ask for an IProductRepository.&lt;br /&gt;&lt;br /&gt;This seems to me a bit more fluent, however the association part in (most of) the existing DI containers seem to be overkill.&lt;br /&gt;&lt;br /&gt;So... I came up with a home-made DI container by using the pattern in my &lt;a href="http://mdpopescu.blogspot.com/2008/12/important-pattern-in-c-while.html"&gt;previous post&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;GenericContainer&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;Dictionary&amp;lt;Type,&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;nbsp;container&amp;nbsp;=&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;Dictionary&amp;lt;Type,&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Register&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt;&amp;nbsp;func)&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;container.Add(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T),&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;func());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Unregister&amp;lt;T&amp;gt;()&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;container.Remove(&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;Get&amp;lt;T&amp;gt;()&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;container[&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T)]()&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(The Register() method uses a trick here to convert a Func&amp;lt;T&amp;gt; to a Func&amp;lt;object&amp;gt; so that it can be saved in the dictionary - I should be able to get rid of this once we get covariance / contravariance in .NET 4.0 and Visual Studio 2010.)&lt;br /&gt;&lt;br /&gt;The usage is quite simple - this call will associate a type with a function returning instances of that type:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv7" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;GenericContainer.Register&amp;lt;IProductRepository&amp;gt;(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and this call will replace the "new ProductRepository()" call:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv8" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;GenericContainer.Get&amp;lt;IProductRepository&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(Of course, I don't &lt;b&gt;have to&lt;/b&gt; use interfaces here; I can use any type.)&lt;br /&gt;&lt;br /&gt;Note that the flexibility of the function allows me to also handle the use cases where I want a singleton returned:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv9" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var&amp;nbsp;productRepository&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductRepository();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;GenericContainer.Register&amp;lt;IProductRepository&amp;gt;(()&amp;nbsp;=&amp;gt;&amp;nbsp;productRepository);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;During testing I will want to replace the object being returned with a mock object I control:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv10" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;GenericContainer.Register&amp;lt;IProductRepository&amp;gt;(()&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MockProductRepository());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's that simple!&lt;br /&gt;&lt;br /&gt;As you can see, I'm quite excited about this... it might not have all the bells and whistles of a mainstream DI container, but I find it quite good for what I need.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit:&lt;/i&gt; Ok, this might be more of a Service Locator pattern instead of Dependency Injection... I am unclear on the terminology. Useful in any case, though :)&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit 2:&lt;/i&gt; It looks like this pattern does have a problem: it hides dependencies. The constructor dependency injection shows clearly that class A depends on classes B, C, and D. Using a service locator &lt;a href="http://blog.vuscode.com/malovicn/archive/2008/06/07/design-for-testability-transparent-and-opaque-dependencies-part-8.aspx"&gt;hides that&lt;/a&gt;. I think the compromise suggested in the article - create two constructors, one exposing the dependencies and one using the service locator - is the best way for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-1505052090444787673?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/1505052090444787673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=1505052090444787673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1505052090444787673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1505052090444787673'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/12/5-minute-dependency-injection-in-c-i.html' title='5-minute dependency injection container in C#'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-9023935286238008759</id><published>2008-12-11T12:42:00.006+02:00</published><updated>2008-12-30T15:34:45.615+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Important pattern in C#</title><content type='html'>While programming, one sometimes needs static methods - methods that cannot meaningfully be associated with an object (a class instance). One example that comes to mind is Math.Abs, but Factory.CreateCustomer might be another. On the other hand, static methods make the methods that use them hard to test - what do you do if you try to test a method that calls Factory.CreateCustomer()? You don't want it to do that, you might want to return a fake customer, or null, or a NullCustomer - any of a number of choices.&lt;br /&gt;&lt;br /&gt;One solution - the most recommended one, in fact, as far as I can tell - is to extract the method in an interface (IFactory.CreateCustomer) and pass an instance of that interface to either the constructor of the class under test, or directly to the tested method. Which is nice, except sometimes you can't alter the constructor of a class (like Pages in ASP.NET and Entities when working with Linq to Sql), and passing the interface to each method looks somewhat ugly.&lt;br /&gt;&lt;br /&gt;A few days ago I found another method (I think it was on &lt;a href="http://ayende.com/Blog/"&gt;Ayende's blog&lt;/a&gt;, but I'm not sure):&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;Factory&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;Func&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;?,&amp;nbsp;Customer&amp;gt;&amp;nbsp;FindCustomer&amp;nbsp;=&amp;nbsp;customerID&amp;nbsp;=&amp;gt;&amp;nbsp;GetDB().FindCustomer(CustomerID);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This declares FindCustomer as a delegate to a function taking a nullable int (the customer ID) and returning a Customer, and initializes this delegate to point to a specific function. However, and here is the great part, nothing prevents one from overwriting this function in testing to return a mock customer or whatever.&lt;br /&gt;&lt;br /&gt;It's too early for me to tell if this is a great idea or a bad one, so I might change my mind later; but so far I'm pleased with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-9023935286238008759?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/9023935286238008759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=9023935286238008759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9023935286238008759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9023935286238008759'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/12/important-pattern-in-c-while.html' title='Important pattern in C#'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3942314444642022799</id><published>2008-11-22T00:27:00.005+02:00</published><updated>2008-12-30T15:51:35.016+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>Biblical laws</title><content type='html'>During the last few years I have slowly come to a conclusion: the reason for a lot of Biblical laws is not actually religious (as in, God has decided that something should not be done and that's that); it is the fact that non-religious commandments would have required explanations beyond the Jews' knowledge at the time or at least that they would have not obeyed them for long otherwise.&lt;br /&gt;&lt;br /&gt;Take incest, since it does make for a rather glaring weirdness. Most people - an overwhelming number - consider incest to be "yuck"... the term cannot be discussed in polite company, only among porn freaks. When people ask "who did Adam and Eve's sons marry?" and receive the obvious answer "their sisters", they go "that's disgusting".&lt;br /&gt;&lt;br /&gt;And yet... incest was not forbidden for a long time in the Bible. A quick search on Google reveals &lt;a href="http://www.christian-thinktank.com/qincest.html"&gt;this page&lt;/a&gt; where we can see that Abraham married his half-sister, Moses' father married his aunt, and even when incest started to be prohibited it started with father-child relationships and only later were siblings added.&lt;br /&gt;&lt;br /&gt;Why is this? Well, why are incestuous relationships prohibited today, even for non-religious people? As it happens sometimes, the state actually has some sort of justification here: people seldom pay attention to reproduction until it's too late and children between close relatives will have a much higher probability of genetic defects. So, since prohibiting only the "having children" part is difficult and would require genetic testing for each birth - and then, what do you do with an "illegal" baby? - the state found it much easier to prohibit the sexual relationship altogether.&lt;br /&gt;&lt;br /&gt;Now. Genetic defects. What exactly would be the way to explain that to a tribe of Jews five thousand years ago? How can you tell them "if you do this, &lt;b&gt;in the long run&lt;/b&gt; (generations) your tribe will die out"? Well, making it a religious commandment would be one way :)&lt;br /&gt;&lt;br /&gt;If that is the case, why wait a few thousand years? Why not start prohibit this right away? Well, the reason is very likely the catastrophic diminishing of the gene pool at the Flood. Prior to that we have no way of knowing how good the genetic material was, but we can safely bet that the eight saved people on Noah's boat were not the most perfect specimens - and even if they were, it would still be too small a population. Which meant that genetic defects would very soon start to propagate... and what do you know, the average age starts falling rapidly after the Flood, from around a thousand years to around a hundred. (Incidentally, this means that living to a thousand years is a viable possibility for humans, we just have to discover what got lost.) Therefore, the most likely conclusion is that the prohibition was not needed before - there were few enough defects that the chance of two parents having the same recessive one (thus increasing the chance of it being dominant in a child) was too small to matter.&lt;br /&gt;&lt;br /&gt;What about another example: basic hygiene. Read &lt;a href="http://www.biblegateway.com/passage/?version=31&amp;search=Lev%2015"&gt;Leviticus 15&lt;/a&gt; and get stunned by the detailed instructions. Would a plain "wash yourselves so you don't get sick" have worked? In fact, there's even a mention of the reason for this commandment: "You must keep the Israelites separate from things that make them unclean, so they will not die in their uncleanness". How could you persuade a bunch of stubborn tribesmen to obey it? Why, make it religious: "... for defiling my dwelling place, which is among them".&lt;br /&gt;&lt;br /&gt;What about having a day of the week off? Well... in 1922 Ford &lt;b&gt;reduced&lt;/b&gt; the workweek to 48 hours (see &lt;a href="http://en.wikipedia.org/wiki/Henry_Ford#Labor_philosophy"&gt;Wikipedia&lt;/a&gt;) so it was even longer before then. That's in the richest country in the world. Can you imagine any employer granting an employee a non-working day a thousand years ago, let alone five thousand, unless it was a religious commandment?&lt;br /&gt;&lt;br /&gt;Ok... wrapping it up. It seems that whoever wrote (or at least directed the writing of) the Bible had a lot of knowledge for the time. Prophecies can be claimed to have been added after the fact; how do you add genetics and hygiene and worker rights in a thousand-years old book?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3942314444642022799?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3942314444642022799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3942314444642022799' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3942314444642022799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3942314444642022799'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/11/biblical-laws-during-last-few-years-i.html' title='Biblical laws'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5208696383246357459</id><published>2008-11-20T14:20:00.008+02:00</published><updated>2008-12-30T15:52:49.332+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='economics'/><title type='text'>More on incentives</title><content type='html'>While watching a concert I started thinking about the amazing cooperation needed for such a task - there are dozens of people on stage, playing various instruments in very specific ways, and hundreds of people in the audience, whose only responsibility for a successful concert is to stay quiet during performances and maybe applaud in between. The performers are rewarded financially if they perform well, and they risk being fired if they don't. The audience risks being fined or even jailed if they don't behave.&lt;br /&gt;&lt;br /&gt;Given all that distinction - disassociation on one hand, jail on the other - who do you expect to cause more &lt;b&gt;intentional&lt;/b&gt; trouble on the average? My money is on the audience, of course [grin].&lt;br /&gt;&lt;br /&gt;Market incentives work a lot better than force incentives. To me, this is a beautiful example of capitalism versus socialism. Even though the risks of disobeying the state are much greater than the risks of disobeying an employer or a business associate (there's no meaningful distinction between employer and customer), cooperation is still more likely to be encountered in the market.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5208696383246357459?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5208696383246357459/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5208696383246357459' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5208696383246357459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5208696383246357459'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/11/more-on-incentives-while-watching.html' title='More on incentives'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-1932646232792797172</id><published>2008-11-20T13:57:00.004+02:00</published><updated>2008-12-30T15:53:05.326+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='economics'/><title type='text'>Socialism does not scale</title><content type='html'>I was deleting some spam and reflecting on the whole issue... as I was telling someone a few weeks ago, the problem with spam will be stopped when it will become a serious issue. Right now, the problem is distributed: a few benefit and a lot have to pay for it. (Just like in politics [grin].) Worse, there is a socialism of sorts in the relationship between internet providers: the sender doesn't have to pay the carriers for the traffic it sends through them. This messes up the incentives completely.&lt;br /&gt;&lt;br /&gt;A simple scheme like a hundredth of a cent per email would make it too expensive to send bulk emails ($100 per million emails) while not affecting regular users in any way; legitimate companies would have already a large enough internet subscription that any email charge would be drowned in the noise; finally, large, voluntary mailing lists like RISKS would need something on the order of maybe a few dollars a day - again, irrelevant when compared with the price for the actual equipment and internet service fee.&lt;br /&gt;&lt;br /&gt;Furthermore, this scheme would create the proper incentives - the ISPs would penalize other ISPs who allow spam through them, the PC owners who don't secure them and let their PCs become spambots would suddenly have a financial interest to fix the problem, which would in turn put pressure on the OS makers (well, on Microsoft [grin]) to improve their software and so on.&lt;br /&gt;&lt;br /&gt;Socialism works in small settings, like the family or small comunities, which is probably why it seems so natural to people. Free markets are much better at solving large-scale situations though. They can be thought of as real-life optimization machines - neural networks made of people, if you will.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-1932646232792797172?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/1932646232792797172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=1932646232792797172' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1932646232792797172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/1932646232792797172'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/11/socialism-does-not-scale-i-was-deleting.html' title='Socialism does not scale'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2053744130289731489</id><published>2008-11-08T09:29:00.005+02:00</published><updated>2008-12-30T15:57:05.338+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Extracting named variables from an array</title><content type='html'>My code uses the following pattern in a lot of places:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;nbsp;array&amp;nbsp;=&amp;nbsp;GetSomeData();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;Debug.Assert(array.Length()&amp;nbsp;&amp;gt;=&amp;nbsp;3);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;m_Member&amp;nbsp;=&amp;nbsp;array[0];&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;m_Password&amp;nbsp;=&amp;nbsp;array[1];&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;m_SomeOtherInfo&amp;nbsp;=&amp;nbsp;array[2];&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;... and so on. This is happening often enough that I tried finding a clearer way of expressing it. I even asked a question on &lt;a href="http://stackoverflow.com/questions/264817/variable-number-of-results-from-a-function"&gt;stackoverflow&lt;/a&gt;. The answers I got aren't bad, but I came up last night with a solution I like more. (It doesn't mean it's the best, and it does look a little kludgy, but I like the way my code looks.)&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System.Diagnostics;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;ArrayExtractor&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Extract&amp;lt;T1&amp;gt;(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;[]&amp;nbsp;array,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;T1&amp;nbsp;value1)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&amp;nbsp;T1&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.Assert(array.Length&amp;nbsp;&amp;gt;=&amp;nbsp;1);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value1&amp;nbsp;=&amp;nbsp;array[0]&amp;nbsp;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Extract&amp;lt;T1,&amp;nbsp;T2&amp;gt;(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;[]&amp;nbsp;array,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;T1&amp;nbsp;value1,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;T2&amp;nbsp;value2)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&amp;nbsp;T1&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&amp;nbsp;T2&amp;nbsp;:&amp;nbsp;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Debug.Assert(array.Length&amp;nbsp;&amp;gt;=&amp;nbsp;2);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value1&amp;nbsp;=&amp;nbsp;array[0]&amp;nbsp;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value2&amp;nbsp;=&amp;nbsp;array[1]&amp;nbsp;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T2;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This only shows the code for 2 values, I'm going to write it for up to 10 values or so. It's not as elegant as the other solutions but now I can simply write&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;fileName;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;contents;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;ArrayExtractor.Extract(array,&amp;nbsp;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;fileName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;contents);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;or even better&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;array.Extract(&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;fileName,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;contents);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2053744130289731489?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2053744130289731489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2053744130289731489' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2053744130289731489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2053744130289731489'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/11/extracting-named-variables-from-array.html' title='Extracting named variables from an array'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-9133585526572196764</id><published>2008-09-12T11:28:00.005+03:00</published><updated>2008-12-30T15:58:08.778+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Comments are evil</title><content type='html'>I just spent an hour hunting a "blablabla.ini" file all over the drive because that's what the comments said it was using. At some point, I gave up and started reading the code. It was actually taking the application name and replacing the ".exe" with ".ini". Found that file in two seconds.&lt;br /&gt;&lt;br /&gt;Misquoting House: comments lie.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-9133585526572196764?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/9133585526572196764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=9133585526572196764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9133585526572196764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/9133585526572196764'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/09/comments-or-why-im-firmly-in-camp-of.html' title='Comments are evil'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6664436998445373830</id><published>2008-08-13T08:36:00.006+03:00</published><updated>2008-12-30T15:58:31.976+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>The verb "is"</title><content type='html'>When arguing about something, the verb "is" should be avoided as much as possible because of its ambiguity. "A is B" can represent:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Identity: life is life.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Membership to a class: a car is an object.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;An attribute: this apple is green.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A relationship: 5 is greater than 3.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A modification of a verb: John is walking.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;... probably other meanings I'm forgetting now.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Of course, in colloquial language "is" cannot be avoided and is not normally a problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6664436998445373830?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6664436998445373830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6664436998445373830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6664436998445373830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6664436998445373830'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/08/verb-is-when-arguing-about-something.html' title='The verb &quot;is&quot;'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6275298603030376319</id><published>2008-07-30T10:44:00.004+03:00</published><updated>2008-12-30T15:59:59.160+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Symmetry</title><content type='html'>Just wanted to save a nice expression I read about yesterday:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;1&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;n&amp;nbsp;&amp;gt;&amp;gt;&amp;nbsp;1&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The value returned is 2^n/2, or 2^(n-1). I just thought it looked lovely :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6275298603030376319?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6275298603030376319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6275298603030376319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6275298603030376319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6275298603030376319'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/symmetry-just-wanted-to-save-nice.html' title='Symmetry'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-874679588559749278</id><published>2008-07-17T07:25:00.006+03:00</published><updated>2008-12-30T16:27:23.765+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><title type='text'>On 0.999...</title><content type='html'>While trying to explain to someone that &lt;a href="http://en.wikipedia.org/wiki/0.9"&gt;0.999... aka 0.(9) is equal to 1&lt;/a&gt; - not almost equal, but equal - one of the "arguments" he used was that recurring decimals are not really numbers, you can't do mathematical operations with them. While the idea is mind-boggling - 0.(1) is 1/9 which is a rational number - I thought of a proof that doesn't use recurring decimals: using base 9.&lt;br /&gt;&lt;br /&gt;0.(1)&lt;sub&gt;10&lt;/sub&gt; = (0.1)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;&lt;br /&gt;(0.0)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.1)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.1)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.2)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.2)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.3)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.3)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.4)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.4)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.5)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.5)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.6)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.6)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.7)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;(0.7)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (0.8)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;&lt;br /&gt;Finally,&lt;br /&gt;&lt;br /&gt;(0.8)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = ?&lt;br /&gt;&lt;br /&gt;Well... in any numeration base, when you finished the digits you restart at 0 and add 1 to the next order, so:&lt;br /&gt;&lt;br /&gt;(0.8)&lt;sub&gt;9&lt;/sub&gt; + (0.1)&lt;sub&gt;9&lt;/sub&gt; = (1.0)&lt;sub&gt;9&lt;/sub&gt;&lt;br /&gt;&lt;br /&gt;Recasting the above in base 10, we have&lt;br /&gt;&lt;br /&gt;0.(8) + 0.(1) = 1.0&lt;br /&gt;&lt;br /&gt;However, in base 10 we still have a digit left, so it is equally valid to write&lt;br /&gt;&lt;br /&gt;0.(8) + 0.(1) = 0.(9)&lt;br /&gt;&lt;br /&gt;just as it is valid to write 0.(7) + 0.(1) = 0.(8).&lt;br /&gt;&lt;br /&gt;Given that the left side is identical, it follows that 1 = 0.(9). QED.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-874679588559749278?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/874679588559749278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=874679588559749278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/874679588559749278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/874679588559749278'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/on-0.html' title='On 0.999...'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3822592886198041461</id><published>2008-07-15T16:46:00.008+03:00</published><updated>2009-01-13T16:25:03.545+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>You want horror? Here's horror!</title><content type='html'>Jeff Atwood latest article, &lt;a href="http://www.codinghorror.com/blog/archives/001152.html"&gt;Maybe Normalizing Isn't Normal&lt;/a&gt; is a real beauty. If you like idiots, that is. (Cue &lt;a href="http://dbdebunk.com"&gt;Fabian Pascal&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;This is by far the worst Jeff has ever wrote. I cannot believe that someone who claims to offer advice to programmers can say anything but "NEVER denormalize". For fuck's sake, educate yourself before you discuss a subject as anything but "hey, I heard somewhere that shooting yourself in the foot is a good idea, what do you think?". (Maybe I should have realized how smart he is when he associated with Joel "exceptions are evil" Spolsky.)&lt;br /&gt;&lt;br /&gt;Let me quote a comment that explains the problem very succinctly:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Speaking from long experience, if you don't normalize, you will have duplicates. If you don't have data constraints, you will have invalid data. If you don't have database relational integrity, you will have orphan "child" records, etc. Everybody says "we rely on the application to maintain that", and it never, never does.&lt;br /&gt;&lt;br /&gt;A. Lloyd Flanagan on July 15, 2008 06:34 AM&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Jeff, stay away from databases. If your programming skills are similar to your logical skills, stay away from programming too...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Oh... let me start checking the articles he uses to support his idea.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://radar.oreilly.com/2006/04/web-20-and-databases-part-1-se.html"&gt;First article&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Our feeling is that this is ultimately far more scalable than black-box clustering.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Wow. Imagine that. Their &lt;b&gt;feeling&lt;/b&gt;. Definitely a good argument.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://radar.oreilly.com/2006/04/database-war-stories-3-flickr.html"&gt;The third&lt;/a&gt; is already ridiculous: they denormalize the database for "performance" and then discover the reason normalization exists: they lose consistency and they have to write a lot of code (that, one would assume, will take a lot of time) to fix that:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;a lot of the flickr code infrastructure deals with ensuring data is consistent and well balanced and finding and repairing it when it's not&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Note that: not &lt;b&gt;if&lt;/b&gt;, &lt;b&gt;when&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Good job. Yeah, denormalization ftw!&lt;br /&gt;&lt;br /&gt;I'll stop here. I believe I made my point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3822592886198041461?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3822592886198041461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3822592886198041461' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3822592886198041461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3822592886198041461'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/you-want-horror-heres-horror-jeff.html' title='You want horror? Here&apos;s horror!'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5291117424059482589</id><published>2008-07-10T23:50:00.007+03:00</published><updated>2008-12-30T16:06:57.327+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Static virtual in C#</title><content type='html'>Argh, this is annoying. I need a Handler type with a virtual string GetProduct() method so that derived types "know" what product they are for. However, I don't want to have to create an instance of the actual class every time I need to ask for its product... I want it to be a virtual method. Too bad - C# doesn't allow virtual static methods.&lt;br /&gt;&lt;br /&gt;What I ended up with was this: each class derived from Handler has a read-only &lt;b&gt;static&lt;/b&gt; string property Product, each of them returning the product that class can handle. In the method where I need that product (when populating a drop-down for example) I use reflection to get the value of the property:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(handlerType.BaseType&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(Handler))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;var&amp;nbsp;product&amp;nbsp;=&amp;nbsp;(&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;)&amp;nbsp;handlerType.GetProperty(&lt;/span&gt;&lt;span class="string"&gt;"Product"&lt;/span&gt;&lt;span&gt;).GetValue(&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I'm not really happy with this - I miss Delphi's "class" type which allowed a much more elegant solution. I'll edit this if I find something I like better.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Edit:&lt;/i&gt; Heh, I found a solution I like better: attributes. I define the following class:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;[AttributeUsage(AttributeTargets.Class)]&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;internal&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductInfo:&amp;nbsp;Attribute&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;Product&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;get&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;ProductInfo(&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;product)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Product&amp;nbsp;=&amp;nbsp;product;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now I can decorate the handlers with a &lt;pre&gt;[ProductInfo("xxx")]&lt;/pre&gt; attribute and extract the product name with&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;var&amp;nbsp;attributes&amp;nbsp;=&amp;nbsp;handlerType.GetCustomAttributes(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ProductInfo),&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;true&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(attributes.Length&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;var&amp;nbsp;product&amp;nbsp;=&amp;nbsp;((ProductInfo)&amp;nbsp;attributes[0]).Product;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;First time I create a custom attribute. Helpful and elegant, so it won't be the last.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5291117424059482589?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5291117424059482589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5291117424059482589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5291117424059482589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5291117424059482589'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/static-virtual-in-c-argh-this-is.html' title='Static virtual in C#'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-2140530051266838147</id><published>2008-07-06T00:18:00.005+03:00</published><updated>2008-12-30T16:27:33.852+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='probabilities'/><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><title type='text'>More on probabilities</title><content type='html'>This is in regards to the often-repeated saying "improbable events happen all the time" (even Dembski says that... which only serves to show that even people on "my" side can be idiots).&lt;br /&gt;&lt;br /&gt;I just read something that was &lt;b&gt;so&lt;/b&gt; apropos of this:&lt;br /&gt;&lt;br /&gt;Heroic Law of Probabilities: One-in-a-million chances happen 9/10&lt;br /&gt;&lt;br /&gt;(Look for it on &lt;a href="http://forums.spacebattles.com/showthread.php?t=106612&amp;page=10"&gt;this page&lt;/a&gt;, it makes more sense in context.)&lt;br /&gt;&lt;br /&gt;That is just too great for words, I will keep quoting that "law" every time the subject comes up. I have to read &lt;a href="http://www.fanfiction.net/s/2530396/1/"&gt;that story&lt;/a&gt;, even though I'm not a fan of Marvel stuff. (Plus, the main character has a Romanian name. Yay :P)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-2140530051266838147?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/2140530051266838147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=2140530051266838147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2140530051266838147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/2140530051266838147'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/more-on-probabilities-this-is-in.html' title='More on probabilities'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5337520097166590378</id><published>2008-07-05T09:45:00.005+03:00</published><updated>2008-12-30T16:10:44.446+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>Speculation</title><content type='html'>I believe that the mind and the brain are distinct things, while the mind and the soul are the same. However, memory is pretty clearly located inside the brain... which means that we lose our memory when we die. That would imply that the purpose of our life here is only to educate our soul... to transform us into better people. It also means that we do not know who we were or what we did - which would be good, because otherwise a lot (most? all?) of us would have to somehow come to terms with the shame of what we did. Not really compatible with heavenly bliss.&lt;br /&gt;&lt;br /&gt;No basis in anything, really, just some idle speculation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5337520097166590378?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5337520097166590378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5337520097166590378' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5337520097166590378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5337520097166590378'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/07/speculation-i-believe-that-mind-and.html' title='Speculation'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5889301884250685247</id><published>2008-06-28T23:33:00.005+03:00</published><updated>2008-12-30T16:11:58.254+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puzzle'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>It's Raganwald's fault this time...</title><content type='html'>I just spent a day trying to write a program to solve &lt;a href="http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html"&gt;Raganwald's puzzle&lt;/a&gt; (at the end of the article). Until now I thought I was a very intelligent guy. Tough :P&lt;br /&gt;&lt;br /&gt;At least I added a few more extension methods to my tools class :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5889301884250685247?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5889301884250685247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5889301884250685247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5889301884250685247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5889301884250685247'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/06/its-raganwalds-fault-this-time.html' title='It&apos;s Raganwald&apos;s fault this time...'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3290682780565688201</id><published>2008-06-27T01:49:00.009+03:00</published><updated>2008-12-30T16:12:18.029+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='reliability'/><title type='text'>Reliability</title><content type='html'>As far as I know, I've always been a proponent of "worse is better" - I favor "cheap and bad" over "expensive and good". I don't wear brand clothing, I don't use brand appliances and I definitely hate brand computers.&lt;br /&gt;&lt;br /&gt;The price/performance ratio is one reason.&lt;br /&gt;&lt;br /&gt;Case A. One $100,000 computer with a guaranteed up-time of 99.9999% - that's less than an hour of downtime in a &lt;b&gt;year&lt;/b&gt;. (I sincerely believe that any actual computer with such a guarantee would cost a lot more than that.)&lt;br /&gt;&lt;br /&gt;Case B. Several computers with a guaranteed up-time of 90% - that's one day of downtime in ten, or more than a month of downtime in a year.&lt;br /&gt;&lt;br /&gt;How many computers are needed to obtain the same reliability as the first system?&lt;br /&gt;&lt;br /&gt;Well... the chance of one such system failing is 1 - 90% = 10%. The chance of two of them failing at the same time is 10% x 10% = 1% (therefore, the up-time of two cheap systems has increased from 90% to 99%). Adding a third computer will increase that to 99.9%... and each new system added to the cluster will add another "9" to that figure. Which means that we only need &lt;b&gt;six&lt;/b&gt; cheap computers for the same 99.9999% reliability.&lt;br /&gt;&lt;br /&gt;Ok, this doesn't take into account the infrastructure needed when you have a cluster as opposed to a single system. Let's say that we want to be absolutely sure and use &lt;b&gt;ten&lt;/b&gt; cheap computers for reliability, and that the cost of the additional infrastructure is the same as that of the computers. Which means that each individual computer needs to be cheaper than $5,000 in order for solution B to be more profitable than A. (And let's not forget that the expensive system needs a lot of infrastructure too - to guarantee 99.9999% up-time you need controlled cooling, a back-up generator and so on.)&lt;br /&gt;&lt;br /&gt;$5,000 for a system that fails one day out of ten? The worst junk I ever used was a lot better than that, and I never paid that much for a system. I think $3,000 was the highest.&lt;br /&gt;&lt;br /&gt;The moral of the story: do not underestimate the power of many cheap systems. Google is the best example :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3290682780565688201?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3290682780565688201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3290682780565688201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3290682780565688201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3290682780565688201'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/06/reliability-as-far-as-i-know-ive-always.html' title='Reliability'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-3420491948150586971</id><published>2008-06-26T13:37:00.006+03:00</published><updated>2008-12-30T16:13:35.732+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fanfiction'/><title type='text'>FanFiction.net</title><content type='html'>I used to hate the FanFiction.net site because it doesn't have a "save the whole story" button. Which is annoying, because I want to use my &lt;a href="http://ebookwise.com"&gt;ebookwise reader&lt;/a&gt; to read the whole book while sitting in bed, not on a chair looking at the screen.&lt;br /&gt;&lt;br /&gt;So... at some point I got pissed bad enough that I felt like writing an application to do it. Since I don't actually have any readers for this blog :P I won't bother with documentation or anything. I've included both the source files and the executable in the &lt;a href="http://80.96.16.232/public/FanFiction.zip"&gt;archive here&lt;/a&gt;. (Yes, I know, I should get a domain, it's not that expensive. I'll do that if I ever decide to actually keep blogging.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-3420491948150586971?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/3420491948150586971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=3420491948150586971' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3420491948150586971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/3420491948150586971'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/06/fanfiction.html' title='FanFiction.net'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-4319415664862775724</id><published>2008-06-26T13:30:00.006+03:00</published><updated>2008-12-30T16:15:44.249+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hoax'/><category scheme='http://www.blogger.com/atom/ns#' term='911'/><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='Christianity'/><title type='text'>Zeitgeist</title><content type='html'>I watched &lt;a href="http://video.google.com/videoplay?docid=-1817848131611744924"&gt;Zeitgeist the movie&lt;/a&gt; yesterday. Nice movie, I recommended it to a few friends for the 2nd and 3rd parts :) (Nice = it fits in with my previous beliefs, of course :P)&lt;br /&gt;&lt;br /&gt;As for the first one... well, the whole Horus/Jesus thing is a hoax. &lt;a href="http://stupidevilbastard.com/index/seb/comments/ending_the_myth_of_horus/"&gt;This thread&lt;/a&gt; is a request by someone for actual evidence... now, the thread is huge, reading it all will take more time than seeing the movie :D, but the thing is, even Acharya's attempt at one point to substantiate her claims fails flat on its face. The conclusion - even by some atheists commenting on the thread - is that the whole thing is Massey's invention, which Acharya parrots because it sells books. (Who knew Dan Brown will practically spawn a new industry, huh?)&lt;br /&gt;&lt;br /&gt;So... still a nice movie, and I did learn a lot even from the first part. (Yes, I have long known that the Catholic Church took over a lot of pagan holidays to make Christianity easier to swallow.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-4319415664862775724?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/4319415664862775724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=4319415664862775724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4319415664862775724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/4319415664862775724'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/06/zeitgeist-i-watched-zeitgeist-movie.html' title='Zeitgeist'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-964338570624909760</id><published>2008-06-25T10:45:00.010+03:00</published><updated>2008-12-30T16:22:40.363+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>A few helper methods in C#</title><content type='html'>Just a few methods I find myself using in a lot of projects...&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;ConvertToInt(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;value,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;def)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;result;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Int32.TryParse(value,&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;out&lt;/span&gt;&lt;span&gt;&amp;nbsp;result)&amp;nbsp;?&amp;nbsp;result&amp;nbsp;:&amp;nbsp;def;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;ConvertToInt(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;value)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;ConvertToInt(value,&amp;nbsp;-1);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;s&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"123"&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;Console.WriteLine(s.ConvertToInt());&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;ForEach&amp;lt;T&amp;gt;(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;lt;T&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;,&amp;nbsp;Action&amp;lt;T&amp;gt;&amp;nbsp;action)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Debug.Assert(&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"set"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Debug.Assert(action&amp;nbsp;!=&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"action"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;item&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action(item);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;ForEach(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;IEnumerable&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;,&amp;nbsp;Action&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;action)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Debug.Assert(&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"set"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Debug.Assert(action&amp;nbsp;!=&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"action"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;item&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;set&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action(item);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I find it much more expressive to use this ForEach extension method instead of a foreach loop:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;list.ForEach(item&amp;nbsp;=&amp;gt;&amp;nbsp;{&amp;nbsp;...&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;do&lt;/span&gt;&lt;span&gt;&amp;nbsp;something&amp;nbsp;with&amp;nbsp;item&amp;nbsp;...&amp;nbsp;});&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;rather than&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;foreach&lt;/span&gt;&lt;span&gt;(var&amp;nbsp;item&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;in&lt;/span&gt;&lt;span&gt;&amp;nbsp;list)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;...&amp;nbsp;&lt;span class="keyword"&gt;do&lt;/span&gt;&lt;span&gt;&amp;nbsp;something&amp;nbsp;with&amp;nbsp;item&amp;nbsp;...&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's probably just a quirk of mine, but I prefer it.&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;AsXML(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;obj)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(obj&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="string"&gt;"&amp;lt;NULL&amp;nbsp;/&amp;gt;"&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;str;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Encoding&amp;nbsp;utf8&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;UTF8Encoding();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;objType&amp;nbsp;=&amp;nbsp;obj.GetType();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;var&amp;nbsp;xmlatt&amp;nbsp;=&amp;nbsp;(XmlTypeAttribute)&amp;nbsp;Attribute.GetCustomAttribute(objType,&amp;nbsp;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(XmlTypeAttribute));&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;ms&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MemoryStream())&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;x&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;XmlTextWriter(ms,&amp;nbsp;utf8)&amp;nbsp;{Formatting&amp;nbsp;=&amp;nbsp;Formatting.Indented})&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;xs&amp;nbsp;=&amp;nbsp;xmlatt&amp;nbsp;==&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;?&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;XmlSerializer(objType)&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;XmlSerializer(objType,&amp;nbsp;xmlatt.Namespace);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xs.Serialize(x,&amp;nbsp;obj);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str&amp;nbsp;=&amp;nbsp;utf8.GetString(ms.GetBuffer(),&amp;nbsp;0,&amp;nbsp;(&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;)&amp;nbsp;ms.Length);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;str;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;AsObject(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;xml,&amp;nbsp;Type&amp;nbsp;type)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;(var&amp;nbsp;sr&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;StringReader(xml))&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;XmlSerializer(type).Deserialize(sr);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;As&amp;lt;T&amp;gt;(&lt;/span&gt;&lt;span class="keyword"&gt;this&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;xml)&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;xml.AsObject(&lt;/span&gt;&lt;span class="keyword"&gt;typeof&lt;/span&gt;&lt;span&gt;&amp;nbsp;(T))&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;as&lt;/span&gt;&lt;span&gt;&amp;nbsp;T;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Good when you need to (de)serialize pesky objects. Usage:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv7" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;MyClass&amp;nbsp;x&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;MyClass();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;s&amp;nbsp;=&amp;nbsp;x.AsXML();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;x&amp;nbsp;=&amp;nbsp;s.As&amp;lt;MyClass&amp;gt;();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-964338570624909760?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/964338570624909760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=964338570624909760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/964338570624909760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/964338570624909760'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/06/few-helper-methods-in-c-just-few.html' title='A few helper methods in C#'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5418934224492343246</id><published>2008-02-18T09:47:00.003+02:00</published><updated>2008-12-30T16:27:54.361+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>Magic</title><content type='html'>Wizard&lt;br /&gt;Warlock&lt;br /&gt;Sorcerer&lt;br /&gt;Mage&lt;br /&gt;&lt;br /&gt;Several words describing people who can use magic... even though none of them ever existed.&lt;br /&gt;&lt;br /&gt;Right...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5418934224492343246?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5418934224492343246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5418934224492343246' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5418934224492343246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5418934224492343246'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2008/02/magic-wizard-warlock-sorcerer-mage.html' title='Magic'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-5491478745668852608</id><published>2007-11-15T13:53:00.001+02:00</published><updated>2008-12-30T16:29:13.146+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><title type='text'>Too many people</title><content type='html'>Overcrowding is a common fear these days, just like global warming and other similar crap. I just thought I'd save here a quick calculation to put things in perspective.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Living area for a single person: 100 m^2 (this would make it 400 m^2 for a 4-people family)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Number of people you can fit in a km^2: 10,000 (because 1 km^2 = 1 million m^2)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Land area of the Earth: 148 million km^2 (see &lt;a href="http://en.wikipedia.org/wiki/Earth"&gt; Wikipedia&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Say only a fifth of that area is available for people, that would be 30 million km^2. Multiplied by 10,000 this gives us 300 billion people.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;300 billion people. With no many-stories buildings, no overcrowding a la Asimov's fiction (how on Earth could he estimate only 40 billion people for Trantor I cannot imagine) and no food problems ('cause we have four fifths of the land area for that - in fact, even if we remove 30% of the total area as &lt;a href="http://members.aol.com/pakulda/dsstyg.htm"&gt;desert&lt;/a&gt; it still leaves us with 70 million km^2 for animals and crops).&lt;br /&gt;&lt;br /&gt;One other thing - what the overcrowding gang never mention is this: on average, people will &lt;b&gt;necessarily&lt;/b&gt; produce more than they consume (because they need to produce for their own consumption, for the new population and to improve the living standard). More people means &lt;b&gt;more&lt;/b&gt; resources, not less - well, unless governments interfere with the process, of course.&lt;br /&gt;&lt;br /&gt;Finally - these calculations are useless for persuading anyone. If it's not population, it's food. (Malthus said that people grow exponentially while food grows arithmetically, so we're going to run out of food sooner or later. That he was an idiot is not necessarily a surprise; that there are millions of other idiots who repeat that without realizing that food is also biological, and therefore should also increase exponentially, is the really weird part.) If it's not those, it's water (I'd try calculating the amount of water in a single glacier but it would also be pointless) or energy or who knows what else.&lt;br /&gt;&lt;br /&gt;So. I guess the conclusion is: we're all gonna die. Yay :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-5491478745668852608?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/5491478745668852608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=5491478745668852608' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5491478745668852608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/5491478745668852608'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/11/too-many-people-overcrowding-is-common.html' title='Too many people'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-8643419985896094324</id><published>2007-11-08T14:06:00.003+02:00</published><updated>2009-01-09T19:18:00.714+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Non-nullable reference types in C#</title><content type='html'>C# 1.0 has non-nullable value types (an int variable must always have a valid int value, it cannot be null) and nullable reference types (a string variable can be null). C# 2.0 added nullable value types (an int? variable - note the "?" - can be null). There are unfortunately no non-nullable reference types (a string variable which can never be null). Patrick Smacchia has a &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2007/07/25/i-want-non-nullable-types-in-c-4.aspx"&gt;summary&lt;/a&gt; of a possible notation and also of the issues that could appear.&lt;br /&gt;&lt;br /&gt;However, until Microsoft decides to add non-nullable reference types, there's a way of doing the same thing with a somewhat more complicated notation.&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;using&lt;/span&gt;&lt;span&gt;&amp;nbsp;System;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt;&lt;span&gt;&amp;nbsp;Extensions&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;struct&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull&amp;lt;T&amp;gt;&amp;nbsp;where&amp;nbsp;T&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;class&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;readonly&lt;/span&gt;&lt;span&gt;&amp;nbsp;T&amp;nbsp;value;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull(T&amp;nbsp;arg)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(arg&amp;nbsp;==&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;throw&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;ArgumentNullException(&lt;/span&gt;&lt;span class="string"&gt;"arg"&lt;/span&gt;&lt;span&gt;);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;arg;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;convert&amp;nbsp;non-nullable&amp;nbsp;to&amp;nbsp;regular&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;implicit&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;operator&lt;/span&gt;&lt;span&gt;&amp;nbsp;T(NotNull&amp;lt;T&amp;gt;&amp;nbsp;arg)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;arg.value;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;convert&amp;nbsp;regular&amp;nbsp;to&amp;nbsp;non-nullable&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;implicit&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;operator&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull&amp;lt;T&amp;gt;(T&amp;nbsp;arg)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull&amp;lt;T&amp;gt;(arg);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//&amp;nbsp;explicit&amp;nbsp;cast&amp;nbsp;to&amp;nbsp;non-nullable&amp;nbsp;--&amp;nbsp;needed&amp;nbsp;when&amp;nbsp;T&amp;nbsp;==&amp;nbsp;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;Cast(&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;arg)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;new&lt;/span&gt;&lt;span&gt;&amp;nbsp;NotNull&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;gt;(arg);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;ToString()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;value.ToString();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;Equals(&lt;/span&gt;&lt;span class="keyword"&gt;object&lt;/span&gt;&lt;span&gt;&amp;nbsp;obj)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;value.Equals(obj);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;override&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;&amp;nbsp;GetHashCode()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;value.GetHashCode();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;operator&lt;/span&gt;&lt;span&gt;&amp;nbsp;==(NotNull&amp;lt;T&amp;gt;&amp;nbsp;left,&amp;nbsp;NotNull&amp;lt;T&amp;gt;&amp;nbsp;right)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;Equals(left,&amp;nbsp;right);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;operator&lt;/span&gt;&lt;span&gt;&amp;nbsp;!=(NotNull&amp;lt;T&amp;gt;&amp;nbsp;left,&amp;nbsp;NotNull&amp;lt;T&amp;gt;&amp;nbsp;right)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;!Equals(left,&amp;nbsp;right);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;A method enforcing a not-null argument would look like this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;Test(NotNull&amp;lt;&lt;/span&gt;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;nbsp;s)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;ss&amp;nbsp;=&amp;nbsp;s;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;return&lt;/span&gt;&lt;span&gt;&amp;nbsp;ss.Substring(0);&amp;nbsp;&lt;/span&gt;&lt;span class="comment"&gt;//&amp;nbsp;no&amp;nbsp;need&amp;nbsp;to&amp;nbsp;test&amp;nbsp;for&amp;nbsp;null&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and would be called like this:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;public&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;TestNotNull()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt;&lt;span&gt;&amp;nbsp;s;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;s&amp;nbsp;=&amp;nbsp;&lt;span class="string"&gt;"something"&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Test(s);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;s&amp;nbsp;=&amp;nbsp;&lt;span class="keyword"&gt;null&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Test(s);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Incidentally, this notation also serves as a form of specification - this parameter should not be null. I was thinking of using attributes but I think it would lead to a more verbose notation in case of several non-nullable parameters. I hope this helps someone :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-8643419985896094324?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/8643419985896094324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=8643419985896094324' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8643419985896094324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8643419985896094324'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/11/non-nullable-reference-types-in-c-c-1.html' title='Non-nullable reference types in C#'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7674960629049991044</id><published>2007-11-03T00:51:00.008+02:00</published><updated>2008-12-30T16:51:22.048+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Structure of Object-Oriented systems</title><content type='html'>&lt;h4&gt;Objects are state machines&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Real-life entities have state. Your checking account has an amount of money; your car has a mileage, a gas level, a speed and so on. Objects in an application should also have a state and a set of operations that can manipulate that state. (You can change the color of your car or add money to your checking account; you cannot do the opposite.)&lt;br /&gt;&lt;br /&gt;That being said, we normally want to hide the state and expose operations because it reduces coupling, which in turn reduces the "brittleness" of the whole system.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Tell, don't ask&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Objects shouldn't have getters and setters; this is sometimes called the &lt;a href="http://c2.com/cgi/wiki?TellDontAsk"&gt;"tell, don't ask" principle&lt;/a&gt;. There are two cases where getters appear to be necessary:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Asking an object for some information and then deciding what how to change the state of the same object. This code could be a fragment of a ping-pong game:&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv1" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ball.Y&amp;nbsp;&amp;lt;&amp;nbsp;0&amp;nbsp;||&amp;nbsp;ball.Y&amp;nbsp;&amp;gt;&amp;nbsp;MAX_Y)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;ball.SpeedY&amp;nbsp;=&amp;nbsp;ball.SpeedY&amp;nbsp;*&amp;nbsp;-1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;A much better way to do this is:&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv2" class="dp-highlighter"&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span&gt;ball.CheckYBounds();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;thus encapsulating logic having to do with the ball inside the ball object.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What about when you ask an object for its status and then modify *another* object depending on that status?&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv3" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ball.Y&amp;nbsp;&amp;lt;&amp;nbsp;0&amp;nbsp;||&amp;nbsp;ball.Y&amp;nbsp;&amp;gt;&amp;nbsp;MAX_Y)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;ball.SpeedY&amp;nbsp;=&amp;nbsp;ball.SpeedY&amp;nbsp;*&amp;nbsp;-1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;sound.Bell();&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Hmm. Changing this to having the ball object invoke &lt;code&gt;sound.Bell();&lt;/code&gt; doesn't seem that good now. It creates a dependency between the ball object and the sound object. Even worse, what about drawing the ball on the screen? &lt;a href="http://www.holub.com"&gt;Allen Holub&lt;/a&gt; suggests having a method &lt;code&gt;ball.DrawOnScreen();&lt;/code&gt; - but this seems way too weird. The ball object is a "model world" object. It should only "know" about model world stuff - moving around, having coordinates, a size and a speed, interacting with other object. Having it know about drawing stuff seems dangerous. What if I want to save its state to a database? Should it know about that too? This is definitely a violation of the &lt;a href="http://c2.com/cgi/wiki?SingleResponsibilityPrinciple"&gt;Single Responsibility principle&lt;/a&gt; (aka SRP) - an object should only have one reason to change.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Communication between objects&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;One thing I read in the Turbo Pascal 6 manuals was this: every time you need object A to communicate with object B, think about adding a new object X in between them. At first, it sounds weird. However, if you need to add objects C, D and E to the mix, and all of them need to communicate with each other, then it pays for all of them to go through X: this way, you only need to have "send to X" and "receive from X" algorithms, instead of all the combinations. The clipboard is a good example of this: Word doesn't need to know how to communicate with Excel, Notepad, and a zillion other programs; it only needs to know how to put stuff into the clipboard and get stuff out of it.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So - how can this solve the above problem? How can the ball object inform the sound object that it needs to sound the bell, without creating a dependency between the two?&lt;br /&gt;&lt;br /&gt;My solution would be a messaging system. We can have the ball object invoke the messaging object, which in turn invokes the sound object.&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv4" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Ball.CheckYBounds()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ball.Y&amp;nbsp;&amp;lt;&amp;nbsp;0&amp;nbsp;||&amp;nbsp;ball.Y&amp;nbsp;&amp;gt;&amp;nbsp;MAX_Y)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ball.SpeedY&amp;nbsp;=&amp;nbsp;ball.SpeedY&amp;nbsp;*&amp;nbsp;-1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Messaging.SendMessage(SOUND_BELL);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Sound.OnBell()&amp;nbsp;&lt;/span&gt;&lt;span class="comment"&gt;//&amp;nbsp;answers&amp;nbsp;to&amp;nbsp;SOUND_BELL&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Ok... the ball object is now free of the dependency on the sound object... it doesn't even have to know about the Sound class. However, it still has to know about the SOUND_BELL message. Why would a Ball know about making sounds? What if I want to reuse the Ball class in another application, where it's not supposed to make sounds when it gets reflected by the up and down edges? What if it's also supposed to flash when this happens - should I change the Ball class when I need to make a change to the way the ball is displayed? We're back to violating the single responsibility principle.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Inform, don't direct&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Here is a great way of removing all such dependencies: don't have the object decide what &lt;i&gt;other&lt;/i&gt; objects should do; just inform them of the state change and let the interested ones react to it (or not):&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv5" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Ball.CheckYBounds()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span&gt;&amp;nbsp;(ball.Y&amp;nbsp;&amp;lt;&amp;nbsp;0&amp;nbsp;||&amp;nbsp;ball.Y&amp;nbsp;&amp;gt;&amp;nbsp;MAX_Y)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ball.SpeedY&amp;nbsp;=&amp;nbsp;ball.SpeedY&amp;nbsp;*&amp;nbsp;-1;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Messaging.SendMessage(BALL_HIT_HORIZONTAL_EDGE);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This has a few beneficial effects:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The message sent by the ball is defined in the Ball class itself, where it makes sense. It made sense for the SOUND_BELL message to be defined in the Sound class, but in that case we still would have had a dependency from Ball to Sound, and the Ball class did not care about sounds. Any object that wants to react to the BALL_HIT_HORIZONTAL_EDGE message shouldn't have a problem about having a dependency on the Ball class - after all, it obviously cares about the Ball class. If we don't want the Sound class itself to have this dependency on Ball, that's fine: we can have a BallSounds object with dependencies on both Ball and Sound:&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="hlDiv6" class="dp-highlighter"&gt;&lt;div class="bar"&gt;&lt;/div&gt;&lt;ol class="dp-c" start="1"&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Ball.CheckYBounds()&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Messaging.SendMessage(Ball.BALL_HIT_HORIZONTAL_EDGE);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;Sound.OnBell()&amp;nbsp;&lt;/span&gt;&lt;span class="comment"&gt;//&amp;nbsp;answers&amp;nbsp;to&amp;nbsp;Sound.BELL&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;//...&amp;nbsp;ring&amp;nbsp;a&amp;nbsp;bell&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;BallSounds.OnBallHitHorizontalEdge()&amp;nbsp;&lt;/span&gt;&lt;span class="comment"&gt;//&amp;nbsp;answers&amp;nbsp;to&amp;nbsp;Ball.BALL_HIT_HORIZONTAL_EDGE&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;{&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="alt"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;Messaging.SendMessage(Sound.BELL);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=""&gt;&lt;span&gt;}&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note that both the compile-time and the run-time dependencies are in the directions we want: the Ball and the Sounds objects do not know about each other, and they also do not know about the BallSounds object. All the objects know only about the messaging system.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A second advantage is that we've created an actual plug-and-play architecture, which has been a long-held dream of programmers, as far as I know. Let's say we decided to log one or more (or all) messages flowing through the system for debugging purposes. Simply create a new object, subscribe it to all the relevant messages (maybe add an &lt;i&gt;all&lt;/i&gt; flag to the messaging system for this purpose) and have it log them when invoked. &lt;b&gt;None&lt;/b&gt; of the other objects need to be modified in any way for this.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This is the architecture I'm envisioning:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_61yEjRUm8Pg/SOhZR0FTPnI/AAAAAAAABS4/i96MJ6DlIpo/s1600-h/objects+and+messages.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_61yEjRUm8Pg/SOhZR0FTPnI/AAAAAAAABS4/i96MJ6DlIpo/s320/objects+and+messages.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5253547127901208178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The important point to keep in mind is this: an object should not send messages telling other objects what to do; it should inform them on what has been done and let them react to that.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;to be continued...&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;!--&lt;br /&gt;- trimite obiecte (intr-o forma serializata?) in loc de mesaje&lt;br /&gt;  - da, serializate, pentru ca vreau sa pot folosi un mecanism gen MSMQ&lt;br /&gt;- trimite mesajele catre o coada comuna de mesaje, nu catre un alt obiect&lt;br /&gt;- fiecare obiect poate sa isi inregistreze un numar de metode care sa raspunda la un numar de mesaje&lt;br /&gt;  - sa fac cate o coada pentru fiecare tip de mesaj... in mod normal intr-o aplicatie vor fi doar cateva zeci, poate sute de (tipuri de) mesaje... e mai simplu decat sa incerc sa am zeci/sute de obiecte Windows Event&lt;br /&gt;- lock-free queue, vezi articolul lui James Bucknall&lt;br /&gt;- mesajele sunt asincrone si nu e garantat nimic pentru ele - nici ordinea livrarii, nici macar daca sunt livrate sau nu&lt;br /&gt;  - de ce sa nu incerc sa folosesc socketi UDP pentru livrare? par sa se potriveasca exact pe ce-mi trebuie. in cazul asta nu am cate o coada pe tip (clasa) de mesaj ci cate un port UDP&lt;br /&gt;  - singura problema apare ca nu e simplu sa ai un handler pentru &lt;b&gt;toate&lt;/b&gt; tipurile de mesaj... decat daca tratez aceste handler-e in mod special (handler-e de genul asta sunt bune pentru debugging/tracing)&lt;br /&gt;- auto-reglarea fps: trebuie sa am un obiect/thread de prioritate minima care sa raspunda la fiecare mesaj. Nu se trece la frame-ul urmator (nu se executa tick-ul urmator de ceas) pana cand nu a ajuns controlul la acest obiect. De fapt, acest obiect poate fi chiar "ceasul" - de cate ori a ajuns controlul la el, genereaza un tick.&lt;br /&gt;--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7674960629049991044?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7674960629049991044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7674960629049991044' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7674960629049991044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7674960629049991044'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/11/structure-of-object-oriented-systems-i.html' title='Structure of Object-Oriented systems'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_61yEjRUm8Pg/SOhZR0FTPnI/AAAAAAAABS4/i96MJ6DlIpo/s72-c/objects+and+messages.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5654876.post-7375782616975148085</id><published>2007-10-24T11:41:00.005+03:00</published><updated>2009-01-09T16:05:21.388+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='copyright'/><title type='text'>It's all Bram Cohen's fault</title><content type='html'>Charles Petzold on why he doesn't sell &lt;a href="http://www.charlespetzold.com/blog/2007/04/290143.html"&gt;as many books as he used to&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(Undoubtedly another factor contributing to crummy book sales is BitTorrent, but that's so painful an issue I can barely bring myself to discuss it.)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This is &lt;b&gt;so&lt;/b&gt; much bullshit. Every idiot who comes up with this excuse should be required to pay a zillion bucks for a lecture by Eric Flint. The simple fact is that if a well-paid US computer programmer finds it &lt;b&gt;cheaper&lt;/b&gt; to spend a few hours looking for a book torrent on the 'net and downloading it, then you're doing something really wrong. Where is the link to the ebook variant, Charles? Put it on the freaking web for 10 bucks and you'll have removed any incentive to look for a free version. Anyone still doing that would never have bought the paper version of your book anyway. (I paid $25 for &lt;a href="http://www.lulu.com/content/435417"&gt;The Tomes of Delphi&lt;/a&gt; and another $50, if I remember correctly, for shipping.)&lt;br /&gt;&lt;br /&gt;Another problem, of course - as Eric points out - is that most people never &lt;b&gt;know&lt;/b&gt; about a particular book. He has a very good example: go in a bookstore that has your book and see how many people &lt;b&gt;see&lt;/b&gt; the book in a day. Not browse it, not buy it - just &lt;i&gt;see&lt;/i&gt; the book. For all those who do not, it might as well not exist. &lt;b&gt;That&lt;/b&gt; is why you need color and bullets - so that people talk about it and advertise it to their friends. Jeff Atwood's article was free advertising - too bad your book couldn't measure up to the competition.&lt;br /&gt;&lt;br /&gt;As mentioned above, &lt;a href="http://baens-universe.com/articles/The_Economics_of_Writing"&gt;Eric Flint is way better at this than I could ever be&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Oh well. Ranting. What else is a blog for if not that? :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7375782616975148085?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7375782616975148085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7375782616975148085' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7375782616975148085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7375782616975148085'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/10/charles-petzold-on-why-he-doesnt-sell.html' title='It&apos;s all Bram Cohen&apos;s fault'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6683408291991341401</id><published>2007-08-18T06:52:00.002+03:00</published><updated>2009-01-09T16:07:50.605+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='copyright'/><title type='text'>Copyright considered harmful</title><content type='html'>Like that's any news coming from me :) However, I just found this page - &lt;a href="http://forums.relicnews.com/showthread.php?p=1297879"&gt;Unofficial Honorverse Mod&lt;/a&gt; in which (at the bottom) a Chris Roensch explains how his company cannot allow fans to create a free Homeworld mod based on the Honorverse because it would dilute their "intellectual property" rights (whoever invented this phrase should be shot) for their upcoming movies and games based on the same universe.&lt;br /&gt;&lt;br /&gt;Of course, it will came as no great surprise that no such games and movies have been produced since the end of 2005... and I'm willing to bet that movies, at least, never will. (Not to mention that I'm also quite certain that any games that will be produced officially will suck big time. They usually do.)&lt;br /&gt;&lt;br /&gt;So, another thing that does NOT get created because of the so-called IP rights. Yay for progress.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6683408291991341401?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6683408291991341401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6683408291991341401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6683408291991341401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6683408291991341401'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/08/copyright-considered-harmful-like-thats.html' title='Copyright considered harmful'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-7060143024866215611</id><published>2007-07-04T00:58:00.002+03:00</published><updated>2009-01-09T16:08:32.484+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>TDD, or not TDD?</title><content type='html'>I'm pretty convinced that TDD (or better yet, &lt;a href="http://dannorth.net/introducing-bdd"&gt;BDD&lt;/a&gt;) is the way to go. As usual when I get to this stage, I no longer care a lot to discuss the issue. However, I just hit on an interesting &lt;a href="http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html"&gt;article&lt;/a&gt;... one that I find particularly weird.&lt;br /&gt;&lt;br /&gt;Ravi's point appears to be that TDD is rather useless... and / or that Peter Norvig is a much better programmer than Ron Jeffries. The thing is, as I said &lt;a href="http://mdpopescu.blogspot.com/2007/06/sudoku-and-tdd-for-last-few-months-ive.html"&gt;here&lt;/a&gt; I managed to solve the whole thing in about 8 hours total. Worse, I only did that once I started with a consistent test-first approach, my previous 3 or 4 attempts ended in failure.&lt;br /&gt;&lt;br /&gt;So. While I have a huge ego (not so huge not to accept Peter Norvig as a better programmer than me though), I have strong doubts that I'm a better programmer than Ron Jeffries. I think that &lt;a href="http://vladimirlevin.blogspot.com/2007/04/tdd-is-not-algorithm-generator.html"&gt;Vlad's article&lt;/a&gt; hits on part of a problem: discovering an algorithm using TDD is at least difficult, if not impossible - and TDD was not meant for that. I also think that Ron simply gave up - in fact, I also did that, several times - because the effort required to figure out the solution was not warranted by the importance of the problem. He started on what was probably the wrong idea and hasn't tried to get out of that box and re-think. If you will, he is guilty of having a (wrong) design up-front &lt;i&gt;[grin]&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;(In my case, the issue was never the algorithm: I had in mind from my first attempt the final algorithm: try to discover "forced" values, where a cell can only have a single value, and repeat that until there's no such constrained cell left; after that, go with a "greedy" recursive algorithm where the first possible value of a cell is chosen, the whole algorithm is re-invoked, and if no solution is found go back and try the next possible value. I must admit that Peter's optimization "try the cell with fewest possible values first" never crossed my mind.)&lt;br /&gt;&lt;br /&gt;So. In my opinion, TDD / BDD is quite useful... even for writing a Sudoku program :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-7060143024866215611?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/7060143024866215611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=7060143024866215611' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7060143024866215611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/7060143024866215611'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/07/tdd-or-not-tdd-im-pretty-convinced-that.html' title='TDD, or not TDD?'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-421365928777815837</id><published>2007-06-29T19:21:00.002+03:00</published><updated>2009-01-09T16:13:06.022+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Databases and objects</title><content type='html'>I have long been a fan of &lt;a href="http://www.dbdebunk.com"&gt;Fabian Pascal's database ramblings&lt;/a&gt; (not his political and economical ones, the man has absolutely no clue on those). Yes, the relational theory is actually set algebra, and therefore a relational database is the most complete and powerful type of database, bar none. Object databases, hierarchical databases (registry), network databases (objects) - they all have problems which simply do not exist in an RDB.&lt;br /&gt;&lt;br /&gt;However, I was re-reading an article about the object / relational mismatch problem -  &lt;a href="http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx"&gt;Interoperability happens&lt;/a&gt; and I got to this part:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font size="smaller"&gt;Developers simply give up on relational storage entirely, and use a storage model that fits the way their languages of choice look at the world. Object-storage systems, such as the db4o project, solve the problem neatly by storing objects directly to disk, eliminating many (but not all) of the aforementioned issues; there is no "second schema", for example, because the only schema used is that of the object definitions themselves. While many DBAs will faint dead away at the thought, in an increasingly service-oriented world, which eschews the idea of direct data access but instead requires all access go through the service gateway thus encapsulating the storage mechanism away from prying eyes, it becomes entirely feasible to imagine developers storing data in a form that's much easier for them to use, rather than DBAs.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;So... an application could simply forget about the whole database thing and completely take over the storage and management of objects. It can also handle the problem (mentioned in that article) of other parts of the same enterprise wanting to use the data by exposing it through services, so that nobody can have access to the underlying objects (and thus nobody needs to change their own application if this application is refactored). True, such an "object database" lacks a lot of the powerful advantages of a relational one, like ad-hoc querying - but maybe for &lt;b&gt;this&lt;/b&gt; application, You Ain't Gonna Need It.&lt;br /&gt;&lt;br /&gt;Interesting idea. I think I read somewhere that Robert Martin starts what are to everyone else obvious database applications by ignoring that part... because he might not need a database after all, and he definitely does not need it to start with. I never understood that until now :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-421365928777815837?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/421365928777815837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=421365928777815837' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/421365928777815837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/421365928777815837'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/06/databases-and-objects-i-have-long-been.html' title='Databases and objects'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6570193163505019579</id><published>2007-06-13T12:24:00.001+03:00</published><updated>2009-01-09T16:14:08.722+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Sudoku and TDD</title><content type='html'>For the last few months, I've been trying on and off to write a program to solve a &lt;a href="http://www.google.com/search?q=sudoku"&gt;Sudoku&lt;/a&gt; game. The "easy" ones are easy, you just use a rudimentary algorithm:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;each cell has a list of possible values associated with it&lt;/li&gt;&lt;br /&gt;&lt;li&gt;start by associating all values 1-9 to each cell&lt;/li&gt;&lt;br /&gt;&lt;li&gt;repeat until solved:&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;for each cell, remove any values already present in the same line, column, or box&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;By this process of repeated elimination you can solve a lot of the "easy" tables. However, this algorithm is too limited and it will go into an infinite loop if you have a situation where, for example, two cells in the same row can accept values 1 and 5, but at this point you have no way of knowing which is which.&lt;br /&gt;&lt;br /&gt;Now, of course the solution to &lt;b&gt;that&lt;/b&gt; problem is simply a recursive backtracking algorithm:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;save the current state&lt;/li&gt;&lt;br /&gt;&lt;li&gt;pick one value and try to solve the rest of the table; if it worked, all is good; if not, go back to the saved state and try the next value&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The devil, however, is in the details. I would go into some weird state where suddenly I had a row with two cells having the same value... which of course ruined everything else. And debugging something which is five recursion levels deep and goes through 81 cells each time... I wasn't willing to spend all that effort for a stupid problem, especially with the number of programs already available solving it.&lt;br /&gt;&lt;br /&gt;That was the case until one night when I was really bored and wanted to program something for fun :) But I had also just read yet another article on Test-Driven Design and decided to try it. It took me a few hours that night, and a few more hours the next morning, but I managed to make it work. Hehe. That's a cool feeling, especially since, while I have tried TDD before, this was the first time I actually felt it helped.&lt;br /&gt;&lt;br /&gt;That's code I'd take to an interview :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6570193163505019579?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6570193163505019579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6570193163505019579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6570193163505019579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6570193163505019579'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/06/sudoku-and-tdd-for-last-few-months-ive.html' title='Sudoku and TDD'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-6798929851772536710</id><published>2007-05-14T22:19:00.001+03:00</published><updated>2009-01-09T16:14:58.274+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>Shape of the Earth</title><content type='html'>One of the very stupid things you learn in school is about the shape of the Earth. You are told that the Earth is not exactly spherical - it has a "geoid" shape (which basically means it has a shape like the Earth... very intelligent). Like in the &lt;a href="http://www.wocka.com/3157.html"&gt;Microsoft joke&lt;/a&gt;, this is technically true, but rather pointless. The Earth's radius is 6500km; the deepest trench in the ocean is 11km and the highest mountain is almost 9km. Which makes it a pretty damn good sphere, with a precision of about 1:600.&lt;br /&gt;&lt;br /&gt;Think about it this way: the same precision on a billiard ball with a radius of 3cm would mean a maximum error of 0.05mm, or 50 microns. I'd call that a perfect sphere...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-6798929851772536710?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/6798929851772536710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=6798929851772536710' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6798929851772536710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/6798929851772536710'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/05/shape-of-earth-one-of-very-stupid.html' title='Shape of the Earth'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-8432413805237207645</id><published>2007-05-09T01:03:00.002+03:00</published><updated>2009-01-09T16:22:54.035+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='economics'/><title type='text'>Ricardo's Law</title><content type='html'>While reading &lt;a href="http://www.tthfanfic.com/Story-12463/spikeNdru+Snakes+on+a+Plane.htm"&gt;Snakes on a Plane&lt;/a&gt; (I'm a big fan of Buffy, and of Buffy crossovers) I got to &lt;a href="http://www.tthfanfic.com/Story-12463-5/spikeNdru+Snakes+on+a+Plane.htm"&gt;this part&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Did they even have stores selling clothes and groceries and stuff back then, or did everybody make their own clothes and grow their own food? That seemed like a lot of wasted effort to Buffy. If you were good at making clothes or something, shouldn't that be, like, your job? And then you could sell the clothes you made or trade them to somebody who was good at growing things.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This is something that most people seem to understand intuitively. If you're better at making bread, and I'm better at making clothes, we should specialize and trade with each other, instead of each of us trying to make both. We'll have products of a better quality (or a greater quantity, depending on the meaning of "better" in the previous statement). This is why, for example, it makes sense to grow corn in Kansas and bananas in Kenya and trade, instead of each trying to do both.&lt;br /&gt;&lt;br /&gt;What some people don't realize, because it is counter-intuitive, is that you don't even need an absolute advantage for trade to be beneficial. Consider the case of a good lawyer (ok, &lt;em&gt;efficient&lt;/em&gt; lawyer [&lt;em&gt;grin&lt;/em&gt;]) with a bad assistant:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;the lawyer can get $200 an hour for legal advice&lt;/li&gt;&lt;br /&gt;&lt;li&gt;he can also type and file well enough to generate an income of $50 an hour&lt;/li&gt;&lt;br /&gt;&lt;li&gt;his assistant would only be able to get $10 an hour for legal advice&lt;/li&gt;&lt;br /&gt;&lt;li&gt;not being as good an assistant, he would also only do work worth $20 an hour&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Even in this case, with the lawyer having a devastating advantage in both legal and secretarial work, it still pays off for him to only handle the legal advice and to hire the assistant for the rest. That's because of an important, but overlooked thing: during the time he's doing a &lt;strong&gt;good&lt;/strong&gt; job typing or filing or whatever, he's not doing a &lt;strong&gt;great&lt;/strong&gt; job getting paid for legal advice. In other words, for every hour spent doing the work of an assistant, he &lt;em&gt;loses&lt;/em&gt; $150. Given that fact, it is better if he hires the assistant for $20 - he saves $130 for each hour he would have otherwise spent doing a less financially rewarding job.&lt;br /&gt;&lt;br /&gt;More information can be found &lt;a href="http://en.wikipedia.org/wiki/Comparative_advantage"&gt;in the Wikipedia article&lt;/a&gt;... while I'm not a big fan of Wikipedia (way too many socialists in the world), this is actually a well-written article.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-8432413805237207645?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/8432413805237207645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=8432413805237207645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8432413805237207645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/8432413805237207645'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/05/ricardos-law-while-reading-snakes-on.html' title='Ricardo&apos;s Law'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-250045428191857360</id><published>2007-05-08T09:44:00.001+03:00</published><updated>2009-01-09T16:22:40.530+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><title type='text'>Predictions of creationism</title><content type='html'>What would be true if creationism were true, but false if not? I don't mean "well, God would exist"; I mean what would we expect to happen differently?&lt;br /&gt;&lt;br /&gt;Well, there's the whole "the universe is comprehensible" thing, which has been discussed in other places (and I do believe it's a great argument). But I just had an idea: the universe is &lt;strong&gt;huge&lt;/strong&gt;. It has either been created by impersonal natural laws, or by God. In the second case, we expect it to have been created for our use, just like the Earth, and therefore at some point we will develop / discover a practical way of faster-than-light travel - just as we developed a way of crossing the oceans. Such an expectation is not warranted in the first case, since it's irrational to expect impersonal laws to care for our wishes.&lt;br /&gt;&lt;br /&gt;So there. FTL technology. I can barely wait. &lt;em&gt;grin&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-250045428191857360?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/250045428191857360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=250045428191857360' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/250045428191857360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/250045428191857360'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/05/predictions-of-creationism-what-would.html' title='Predictions of creationism'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-28596147794759829</id><published>2007-05-07T10:08:00.001+03:00</published><updated>2009-01-09T16:25:02.343+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>Ideas are worthless</title><content type='html'>I have a friend who is normally a very intelligent man, and an extraordinary computer programmer. However, he has an IDEA, and he's unwilling to publish it in detail on his site - he wants to discuss it with a big company, to get the cash he believes he deserves for his idea.&lt;br /&gt;&lt;br /&gt;I was unable to persuade him that ideas are worthless.&lt;br /&gt;&lt;br /&gt;Here's an idea that would be worth a lot of money... if ideas were worth anything. Let's get rid of 99% of the existing government bureaucracy. (I'm an anarchist, I want to get rid of all government, but that's harder to sell. Most people would agree that 99% of the government is useless, though. &lt;span style="font-style: italic;"&gt;grin&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;Just think of the advantages:&lt;br /&gt;* you save on salaries and bribes&lt;br /&gt;* you force the leeches to actually work for a living and make something even marginally useful (like hamburgers)&lt;br /&gt;* a lot less spending on "feel-good" projects like houses for the poor which cost a million bucks a piece and look pretty much like a shack&lt;br /&gt;* ... and I'm sure a lot more, you get the point&lt;br /&gt;&lt;br /&gt;What about getting rid only of the armies? I mean, most people are scared of guns. And if guns are bad, and people shouldn't have them, then the place we should start removing them is definitely the army - after all, we &lt;span style="font-weight: bold;"&gt;know&lt;/span&gt; that armies kill people, that's their job description :D&lt;br /&gt;&lt;br /&gt;Now, are these ideas worth anything? Not even the time I spent writing them down. The &lt;span style="font-weight: bold;"&gt;implementation&lt;/span&gt;, on the other hand, would be worth billions. Get &lt;span style="font-weight: bold;"&gt;that&lt;/span&gt; perfected, sell it to the Americans, and become the richest man in the world. Eat your heart out, Bill Gates! &lt;span style="font-style: italic;"&gt;grin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;See? It's worthless to think "&lt;span style="font-style: italic;"&gt;hey, I don't really like the links Yahoo returns, what about making a better search engine?&lt;/span&gt;". You have to actually work your butt off and &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt; it to become Google. If you're the kind of person that has great ideas, you probably have a dozen a day. They're worthless to you, and they're worthless to everyone else - make a couple of them real, and everything changes.&lt;br /&gt;&lt;br /&gt;Just a rant, of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-28596147794759829?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/28596147794759829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=28596147794759829' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/28596147794759829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/28596147794759829'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2007/05/ideas-are-worthless-i-have-friend-who.html' title='Ideas are worthless'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-108202787085035880</id><published>2004-04-15T14:17:00.001+03:00</published><updated>2009-01-09T16:25:29.659+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><title type='text'>Julian Simon</title><content type='html'>In &lt;i&gt;Ultimate Resource II&lt;/i&gt;, Julian Simon argues against the doomsayers that claim that everything will go from bad to worse. The ultimate expression of this gloomy vision, he says, is the second law of thermodynamics - which he argues against, by saying (approx. quote): "Where have they seen this? If we look around us, we will discover that things have, on the contrary, evolved from the smallest micro-organism to life as it is now. What second law? What we know of the world should show the opposite of entropy."&lt;br /&gt;&lt;br /&gt;This is a classical example of reaching the right conclusion for the wrong reasons. There's no such thing as evolution. However, there is &lt;b&gt;one&lt;/b&gt; thing that, each day, overcomes the second law: intelligence. Intelligence is the only known way of defeating entropy - of getting something more complex than what we put in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-108202787085035880?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/108202787085035880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=108202787085035880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/108202787085035880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/108202787085035880'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2004/04/julian-simon-in-ultimate-resource-ii.html' title='Julian Simon'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-106362724617522016</id><published>2003-09-15T15:00:00.001+03:00</published><updated>2009-01-09T16:26:13.220+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><title type='text'>Analogy</title><content type='html'>A repeated accusation on the &lt;a href="http://groups.yahoo.com/group/TrueOrigin"&gt;true origin list&lt;/a&gt; is that I incorrectly consider everything with a probability smaller than 10^-150 (but greater than zero) to be impossible. Well, I do, but is it incorrect?&lt;br /&gt;&lt;br /&gt;The analogy I want to make here is between "any event with a probability smaller than 10^-150 is impossible (in this universe)" and "any cube with a length smaller than 10^-40 cm is impossible (in this universe)". Why the second claim? Because the Planck limit, 10^-33 cm, dictates how small objects can be - &lt;strong&gt;nothing&lt;/strong&gt; can be smaller than this, in our universe. The universe is discrete at this scale - you can find to points between which there is no other.&lt;br /&gt;&lt;br /&gt;So, saying "a cube with a length smaller than 10^-40 cm (or anything smaller than 10^-33 cm) is impossible" is not wrong; it is actually correct. By analogy, saying that "anything with a probability less than 10^-150 is impossible" is not wrong - it really is impossible in our universe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-106362724617522016?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/106362724617522016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=106362724617522016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106362724617522016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106362724617522016'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2003/09/analogy-repeated-accusation-on-true.html' title='Analogy'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-106140485476262985</id><published>2003-08-20T21:40:00.003+03:00</published><updated>2009-01-09T16:29:36.884+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><title type='text'>Human DNA</title><content type='html'>&lt;em&gt;Is the probability of obtaining a DNA sequence which codes for a human (ie, a living being capable of interbreeding with humans) by any combination of random processes and deterministic functions (like natural selection) less than 10^-150?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Let's assume we already have the humans' alleged ancestor race, call it apes. Is it possible for random mutations to change an ape DNA into a human DNA?&lt;br /&gt;&lt;br /&gt;Let &lt;strong&gt;S = {A, C, G, T}&lt;/strong&gt; the possible values for a codon, and &lt;strong&gt;S* a sequence s[1] ... s[n] where s[i] is in S&lt;/strong&gt;. We define&lt;br /&gt;&lt;br /&gt;dist* (a, b) with a, b in S* = the number of point mutations needed to change a into b (or viceversa):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;dist* (a[1] ... a[n], b[1] ... b[m]) = sum (i = 1, n, dist (a[i], b[i])) + m - n&lt;/strong&gt;, with m &gt;= n &gt;= 1&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;dist (a, b) = {0 if a = b, 1 otherwise}&lt;/strong&gt;, with a, b in S&lt;br /&gt;&lt;br /&gt;In other words, if everything works out perfectly, it takes at least dist* (A, B) point mutations to convert one into the other, where A is a member of the ape DNA set, and B is a member of the human DNA set.&lt;br /&gt;&lt;br /&gt;How close are these sets? It is alleged that they are very close - that the resemblance is between 95% and 99%. Out of 3 billion codons, this would give a difference of 30 to 150 million codons. If we go further and claim that only 1 in 10,000 of the DNA is actually relevant - the rest being "junk DNA" - we are left with a relevant difference of only 3 to 15 thousand "letters".&lt;br /&gt;&lt;br /&gt;This means that we need between 3 and 15 thousand point mutations to get from apes to humans. How probable is that, using purely random mechanisms? Well, the problem is equivalent to getting from AAA...A to CCC...C, both strings having 3,000 letters, changing one letter at each step into one of the values A, C, G, or T - at random. At each step, the probability of getting the right one is 1/4; since we need 3,000 lucky changes, the probability of getting them through purely random means is 1/4^3,000 = &lt;strong&gt;2^-6,000&lt;/strong&gt;. This is WAY below 2^-500.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;What about the &lt;strong&gt;Weasel&lt;/strong&gt; program? (You can find an example &lt;a href="http://www.answersingenesis.org/home/area/Magazines/tj/docs/weasel.zip"&gt;here&lt;/a&gt;.) Couldn't such a program get much faster from AAA...A to CCC...C? Yes, of course it could. But the problem with the weasel program - or any similar algorithm - is that it already knows its target. In other words, the weasel program is equivalent to the following one:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;print "CCC...C"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Unless someone can convincingly argue that evolution's goal was to transform apes into humans, any algorithm with a predefined target (which can be reduced to the above) is out. This includes more "roundabout" algorithms that try to conceal the fact that they know their target, like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;for i = 1 to 3000&lt;br /&gt;  print chr(-i + ord("A") + (2 * i + 6) / 2 - 1)&lt;br /&gt;next&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;What about using an evaluation function (for the natural selection part)? Those can serve as probability amplifiers (they &lt;strong&gt;lose&lt;/strong&gt; information, instead of adding new one, but that's ok in this case - we already have a source of information, randomness; we now need something to "guide" that information).&lt;br /&gt;&lt;br /&gt;Well, we have two relevant classes of such functions:&lt;br /&gt;1) functions that know the target - and we're back to the above case - and&lt;br /&gt;2) functions that calculate a "fitness", and it so happens that the fitness of the CCC...C string is greatest, while the fitness of the AAA...A string is lowest.&lt;br /&gt;&lt;br /&gt;Option 2 is a viable one, &lt;strong&gt;provided that&lt;/strong&gt; someone produces such a function for the real-life case of human DNA. (I know it's easy to do it for our strings.) Can this be done, without using any post-facto rationalization (like "humans are smarter than apes, therefore the function must give them more points")? [Remember, this must work for any pair of ancestor - evolved species. Such a function won't help with bacteria. The No Free Lunch theorems would suggest that there is no such function that works for all cases.]&lt;br /&gt;&lt;br /&gt;So, the final conclusion would be: if evolution's goal is &lt;strong&gt;not&lt;/strong&gt; to produce humans, and if there's no general algorithm that nevertheless happens to favor "closer-to-human DNA" over "closer-to-ape DNA", human DNA can't have occurred by chance - even with the help of natural selection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-106140485476262985?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/106140485476262985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=106140485476262985' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106140485476262985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106140485476262985'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2003/08/human-dna-is-probability-of-obtaining.html' title='Human DNA'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-106088809849416932</id><published>2003-08-14T22:08:00.002+03:00</published><updated>2009-01-09T16:29:18.084+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><title type='text'>Clarification</title><content type='html'>For me, the idea of a string having a probability is absurd - I can't parse it at all. Let me clarify this with an example: what is the probability of a chair? Both a chair and a string are objects. Ok, the string is an informational entity, not a physical object. What is the probability of an equation? Neither of these questions make any sense.&lt;br /&gt;&lt;br /&gt;Now, if we want it to make sense, we must start to expand the question. What is the probability that a 500-bit string will occur? Still not good enough - out of thin air? In my daily emails? So let's try again: what is the probability of a 500-bit string occuring in the following experiment: "write down 500 bits"? Well, 1 if you do it, 0 if you don't. In NO case is it going to be any other value.&lt;br /&gt;&lt;br /&gt;How do you fill the blanks so that "what is the probability of a 500-bit string ..." gives you any other result? Please &lt;a href="mailto:mdpopescu@yahoo.com"&gt;email me&lt;/a&gt; if you found a way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-106088809849416932?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/106088809849416932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=106088809849416932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106088809849416932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106088809849416932'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2003/08/clarification-for-me-idea-of-string.html' title='Clarification'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-106026039206426797</id><published>2003-08-07T15:46:00.002+03:00</published><updated>2009-01-09T16:29:04.652+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><title type='text'>Information</title><content type='html'>Let's define I(E) = -log2 P(E), where E is an event. This is the amount of information contained in (imparted by) that event, or in other words the amount of uncertainty removed by that event, and is measured in bits. (Why uncertainty? Let {E*} be the set of possible relevant events, of which E is a member. Before E, any of the {E*} elements could have occured; the fact that we obtained E decreased that uncertainty. P(E) is, of course, 1 / the number of elements in {E*}.)&lt;br /&gt;&lt;br /&gt;Using the value we determined earlier, the "cutoff value" of 10^-150, the information contained in an event E with that probability is -log2 10^-150, which is 500 bits. Therefore, another way of specifying the "point of no return" is this: &lt;em&gt;anything with an informational content larger than 500 bits could not have occured without the intervention of an intelligence&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;What are possible sources for this information? Well, as far as I know (please &lt;a href="mailto:mdpopescu@yahoo.com"&gt;let me know&lt;/a&gt; if you find another one), only 3 exist: intelligence, randomness, and laws (deterministic functions). Of these 3, the last one doesn't actually create information (more on this below), but can be used to move it from one place to another. (Eg, a program drawing a rembrandt painting doesn't create the information: it copies it from whatever storage source it is using to the screen or printer.)&lt;br /&gt;&lt;br /&gt;Why can't deterministic functions create information? Well, let's see:&lt;br /&gt;&lt;br /&gt;P(A &amp; B) = P(A) x P(B) -- where A and B are independent&lt;br /&gt;I(A &amp; B) = I(A) + I(B) -- this follows from I(A) = -log2 P(A)&lt;br /&gt;&lt;br /&gt;However, we're interested in information produced by functions. That is, what is I(A &amp; f(A)). Well, f(A) is definitely not independent from A, so we will use I(B | A) for "the (conditional) information of B, given A". From this, we obtain that&lt;br /&gt;&lt;br /&gt;I(A &amp; B) = I(A) + I(B | A) -- note that, for independent A and B, I(B | A) = I(B), so we get back to the previous formula&lt;br /&gt;&lt;br /&gt;I(A &amp; f(A)) = I(A) + I(f(A) | A)&lt;br /&gt;&lt;br /&gt;What is I(f(A) | A)? It will be helpful to get back to probabilities:&lt;br /&gt;&lt;br /&gt;I(f(A) | A) = -log2 P(f(A) | A)&lt;br /&gt;&lt;br /&gt;But f is a &lt;strong&gt;deterministic&lt;/strong&gt; function - that is, f(A) is completely determined by A; given A, f(A) has a probability of 1:&lt;br /&gt;&lt;br /&gt;P(f(A) | A) = 1&lt;br /&gt;&lt;br /&gt;which means that&lt;br /&gt;&lt;br /&gt;I(f(A) | A) = 0&lt;br /&gt;&lt;br /&gt;Getting back to our initial problem,&lt;br /&gt;&lt;br /&gt;I(A &amp; f(A)) = I(A) + I(f(A) | A) = I(A)&lt;br /&gt;&lt;br /&gt;In other words, we obtained that &lt;strong&gt;deterministic functions add no information&lt;/strong&gt;. (This is common knowledge in the field of cryptography, another hobby of mine, where it's expressed as "functions cannot create entropy".)&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;We have now an interesting result. Functions cannot add information. Randomness can, but no more than 500 bits. So the only conclusion we can draw is this: &lt;strong&gt;any piece of information more than 500 bits long (or, any event with a probability lower than 10^-150) must have an intelligent cause&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;It is important that we keep thinking about the issue in terms of both information and probability, or we might get confused. For example, someone objected that it is possible to accumulate any amount of information "piece-by-piece", one bit at a time. None of the individual bits is outside the realm of randomness, but together they can break the 500 bits barrier. Or, it could be objected that a random process - like flipping a coin - can easily generate 500 random bits. We need to get back to the first part of this (&lt;strong&gt;Statistics&lt;/strong&gt;) and talk about probabilities again. (The answer to both objections seems to me obvious; however, if you're of a different opinion, &lt;a href="mailto:mdpopescu@yahoo.com"&gt;email me&lt;/a&gt; and I'll detail what I mean.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-106026039206426797?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/106026039206426797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=106026039206426797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106026039206426797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106026039206426797'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2003/08/information-lets-define-ie-log2-pe.html' title='Information'/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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-5654876.post-106023969108376294</id><published>2003-08-07T10:01:00.001+03:00</published><updated>2009-01-09T16:31:08.052+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='creationism'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><title type='text'></title><content type='html'>&lt;h2&gt;Statistics&lt;/h2&gt;&lt;br /&gt;I met this gem on the &lt;a href="http://groups.yahoo.com/group/TrueOrigin/"&gt;TrueOrigin&lt;/a&gt; list:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;I asked her to pick a digit (0 through 9). Then do it again, and again, 53 times. You will have picked a number with 53 digits. The apriori probability that you would have picked that number is 1 chance in 10^53, but you did the impossible.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Is it true that the chance of doing what is described above is indeed very small (10^-53)? Let's see.&lt;br /&gt;&lt;br /&gt;In my country, we have a lottery called "6 out of 49". You have a 7x7 grid, with numbers from 1 to 49, out of which you are supposed to pick the winning six. Let's say you bought a ticket and picked 6 numbers at random. What is the chance of winning the lottery?&lt;br /&gt;&lt;br /&gt;Well, the total number of combinations is C(49, 6), which is 49! / (6! x (49 - 6)!), where "n!" (read: &lt;em&gt;n factorial&lt;/em&gt;) means "1 x 2 x 3 x ... x n". Calculating it gives us 13,983,816 possibilities (if I made a mistake, please let me know).  So, the probability of picking the right combination is approximately 1 / 14 million, or 7.15 x 10^-8.&lt;br /&gt;&lt;br /&gt;Now, what is the probability that &lt;strong&gt;you picked 6 random numbers&lt;/strong&gt;? Put this way, the question sounds silly: the probability is 1, of course. You just did it, it's a past event - it either happened or it didn't, so the probability is either 1 or 0. And &lt;strong&gt;this&lt;/strong&gt; is what the above "experiment" is all about: picking 53 random numbers, and then asking "how probable is that you in fact picked 53 random numbers?", can only have one answer: the probability is 1.&lt;br /&gt;&lt;br /&gt;How do we distinguish between the two cases? We need what is called a &lt;strong&gt;specification&lt;/strong&gt;. The second case had one such specification: the winning combination. In other words, we must be able to ask the question: what is the probability that the sequence we just picked (call it x) is equal to &lt;strong&gt;T&lt;/strong&gt;? We can do that in the second case; but in the first, we have nothing to replace T with - except for x, in which case the question becomes "what is the probability that x = x?". Once we have a specification, we can calculate the probability. Once we have &lt;strong&gt;that&lt;/strong&gt;, we can determine whether the event was random or not: anything below a specific value (we'll use 10^-150) cannot be random. (More on this value later.)&lt;br /&gt;&lt;br /&gt;What conditions must the specification meet? Well, only one: it must be &lt;strong&gt;independent&lt;/strong&gt;. To borrow an example from Dembski, an archer that shoots at a wall, then paints a bullseye around the arrow is &lt;strong&gt;not&lt;/strong&gt; a very good archer. (The probability of hitting the target - the probability of x being equal to T, to use the symbols above - is 1, since T is defined by x. The two are anything but independent.) On the other hand, if the bullseye is already painted, and the archer hits it 20 times right in the center, then we can be quite sure this was no random event. (I am, of course, ignoring various way to "rig" this, like a bullseye 20 meters across, with the archer standing two feet before it, and other variations.)&lt;br /&gt;&lt;br /&gt;Should the specification occur &lt;strong&gt;before&lt;/strong&gt; the event? No, this is not necessary. A process generating 3141592 will hint that it's not random. A process generating the first 100 digits of pi will absolutely tip us off. An independent specification is enough to calculate probabilities, whether it's made known before or after the fact.&lt;br /&gt;&lt;br /&gt;Can we make mistakes? In other words, is it possible to consider that an event is random when it isn't, or the other way around?&lt;br /&gt;&lt;br /&gt;1. We might not realize that there is a specification. A process generating 2030481... might seem random, until we realize that each digit is the corresponding digit of pi, minus one. Or, some message might be encrypted with a good algorithm, and the resulting string would appear to be random to all statistics tests (like &lt;a href="http://www.csis.hku.hk/~diehard/"&gt;diehard&lt;/a&gt;). False negatives are a possibility.&lt;br /&gt;&lt;br /&gt;2. On the other hand, I don't see any way for false positives. If the "cutoff value" is low enough - like the 10^-150 I'm using (which I borrowed from Dembski) - there is no way it can happen randomly (that is, without an intelligence involved). [I am not a subscriber to the QM "anything possible is necessary" many-worlds interpretation.] Of course, with a cutoff value too large - like 1 in 10 - false positives &lt;strong&gt;can&lt;/strong&gt; happen. This is why Dembski picked 10^-150, to avoid any possibility of a false positive.&lt;br /&gt;&lt;br /&gt;Finally, why 10^-150?&lt;br /&gt;&lt;br /&gt;It is estimated that there are about 10^80 particles in the known universe.&lt;br /&gt;The Planck time is the smallest meaningful unit of time: 10^-45 seconds. This means that nothing physical can change state more than 10^45 times per second.&lt;br /&gt;Finally, the universe is estimated to be more than a billion times younger than 10^25 seconds.&lt;br /&gt;&lt;br /&gt;Multiplying these figures, 10^80 x 10^45 x 10^25 gives 10^150. This means that, if all the particles in the known universe, for a billion times longer than they (allegedly &lt;a href="#1"&gt;[1]&lt;/a&gt;) existed, "tried" to generate new combinations, they wouldn't have exhausted 10^150 such combinations. That is, there are simply not enough resources in this universe to account for an event with a probability smaller than 10^-150. Which means that, if we encounter an event whose probability (reminder: we need an independent specification to be able to calculate this probability) is smaller than 10^-150, an intelligence must have been involved.&lt;br /&gt;&lt;br /&gt;In other words, if P(E) &lt; 10^-150, E was caused by an intelligence.&lt;br /&gt;&lt;br /&gt;Whew!&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;a name="1"&gt;[1]&lt;/a&gt; I'm an young-earth creationist. I believe the universe to be less than 10,000 years old.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5654876-106023969108376294?l=mdpopescu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdpopescu.blogspot.com/feeds/106023969108376294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5654876&amp;postID=106023969108376294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106023969108376294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5654876/posts/default/106023969108376294'/><link rel='alternate' type='text/html' href='http://mdpopescu.blogspot.com/2003/08/statistics-i-met-this-gem-on.html' title=''/><author><name>Marcel</name><uri>http://www.blogger.com/profile/13951354231483245521</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></feed>
