<?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-7289061379610528811</id><updated>2011-09-26T19:59:08.225+04:00</updated><title type='text'>IKickAndIBite</title><subtitle type='html'>Me, myself, .Net, and that crazy world of ours. The short version.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7289061379610528811.post-3828669481854249614</id><published>2011-08-24T20:02:00.002+04:00</published><updated>2011-08-24T20:03:40.371+04:00</updated><title type='text'>Good enough</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Saw a great talk today -- made by Eric Evans about DDD. Among other things he said that "Some things have to be good enough, while others have to really be good".&lt;br /&gt;
&lt;br /&gt;
For me it basically means don't be running around trying to make design everywhere better, focus on the core (domain) instead.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-3828669481854249614?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/3828669481854249614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2011/08/good-enough.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3828669481854249614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3828669481854249614'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2011/08/good-enough.html' title='Good enough'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-6002364085521200304</id><published>2011-07-19T00:48:00.000+04:00</published><updated>2011-07-19T00:48:16.989+04:00</updated><title type='text'>In short</title><content type='html'>Well, it's been a while since I posted. In short, I've got a new woman, a new job, and version one of my opensource project has just been released. Check it out at&amp;nbsp;&lt;a href="http://poolkit.codeplex.com/"&gt;http://poolkit.codeplex.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-6002364085521200304?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/6002364085521200304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2011/07/in-short.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6002364085521200304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6002364085521200304'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2011/07/in-short.html' title='In short'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-7256337557703827281</id><published>2011-03-13T11:54:00.001+03:00</published><updated>2011-03-17T00:14:53.005+03:00</updated><title type='text'>Algorithms</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;While looking for a job I went on an interview which was focused on my ability to come up with solutions to algorithmic problems, and fast. The interviewers were sure it is the essence of the job (job title read: Senior C# Developer). I have always believed, my job is to create architectures that last and -- among other things -- I do like patterns that make algorithms unimportant, interchangeable. From my experience, it's rarely even required to optimize algorithms, and I never do this until a performance impediment arises (which is also rarely the case).&lt;br /&gt;
&lt;br /&gt;
What's your take on this? Must a good software developer be fast and efficient when creating algorithms -- or is it more like a nice-to-have-but-not-necessary thing? (The answer may depend on the specifics of your project.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-7256337557703827281?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/7256337557703827281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2011/03/algorithms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/7256337557703827281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/7256337557703827281'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2011/03/algorithms.html' title='Algorithms'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-5674810921721750932</id><published>2011-01-17T23:50:00.001+03:00</published><updated>2011-01-17T23:56:10.221+03:00</updated><title type='text'>Latest Brainbench Test</title><content type='html'>I've scored 4,51 on a .Net Framework 3.5&amp;nbsp;Fundamentals&amp;nbsp;Brainbench test today. The transcript is &lt;a href="http://www.brainbench.com/transcript.jsp?pid=8194000"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
It says: "Scored higher than 99% of all previous test takers."&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;(Boasting does not really suit me. It can very well be the case that I was the second guy to take the test in the whole world. And that other guy fainted after the 3-rd question because his heater had burned out all oxygen in his room!)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-5674810921721750932?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/5674810921721750932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2011/01/latest-brainbench-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/5674810921721750932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/5674810921721750932'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2011/01/latest-brainbench-test.html' title='Latest Brainbench Test'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-5297556237357826704</id><published>2010-12-27T13:54:00.004+03:00</published><updated>2011-01-03T01:38:28.833+03:00</updated><title type='text'>State and CycledEnumerator</title><content type='html'>The GoF State pattern is not on top of my list of favorites (Decorator is), but I am using it from time to time. And as you probably are aware there is this question about the implementation of State: whoever will switch between states and when?&lt;br /&gt;
&lt;br /&gt;
I thought that Iterator -- another GoF pattern -- might be a good example of something that encapsulates state switching logic in some cases, when the states are switched strictly in the order you know beforehand. I realize that not every State implementation is that simple, but if yours is, you might want to use the idea: just pass the IEnumerable of IState to the implementation of State, and use MoveNext() and Current {get;} on the Enumerator internally to switch states. If you are doing something like this, it might be a good idea to jump back to State #1 after you've reached State #Last. I've written a little helper class to do just that:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c-sharp;"&gt;using System;
using System.Collections.Generic;

namespace Primitives
{
    public class CycledEnumerator&amp;lt;T&amp;gt; : IEnumerator&amp;lt;T&amp;gt;
        where T : class
    {
        private LinkedList&amp;lt;T&amp;gt; _chainedObjects;
        private LinkedListNode&amp;lt;T&amp;gt; _currentObject;

        public CycledEnumerator(IEnumerable&amp;lt;T&amp;gt; objectsToChain)
        {
            if (objectsToChain == null)
            {
                throw new ArgumentNullException("objectsToChain");
            }

            _chainedObjects = new LinkedList&amp;lt;T&amp;gt;(objectsToChain);

            if (_chainedObjects.Contains(null))
            {
                throw new ArgumentException("Nulls are not allowed.", "objectsToChain");
            }

            if (_chainedObjects.Count &lt; 1)
            {
                throw new ArgumentException("Need at least one item in the set.", "objectsToChain");
            }

            this.MoveBeforeFirstElement();
        }

        private void MoveBeforeFirstElement()
        {
            _currentObject = null; // I don't like nulls at all, but I'm putting it here for the sake of consistency with Microsoft's implementations of Enumerator (which is a variant of GoF Iterator pattern).
        }

        public T Current
        {
            get
            {
                return _currentObject.Value;
            }
        }

        public void Dispose()
        {
        }

        object System.Collections.IEnumerator.Current
        {
            get
            {
                return _currentObject;
            }
        }

        public bool MoveNext()
        {
            if ((_currentObject == null) || (_currentObject.Next == null))
            {
                MoveToFirstElement();
            }
            else
            {
                _currentObject = _currentObject.Next;
            }

            return true;
        }

        private void MoveToFirstElement()
        {
            _currentObject = _chainedObjects.First;
        }

        public void Reset()
        {
            this.MoveBeforeFirstElement();
        }
    }
}&lt;/pre&gt;
&lt;br /&gt;
(That said, I don't like Iterator much (and all of its buddies, like the Enumerator): it exposes too much of its state to the client, and has too complex a contract. It's all like "if MoveNext() returns true, then Current contains the next element", or: "after initialization the Enumerator is positioned before the first element, and you should call MoveNext() to get anything from it".)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-5297556237357826704?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/5297556237357826704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/12/gof-state-pattern-is-not-on-top-of-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/5297556237357826704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/5297556237357826704'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/12/gof-state-pattern-is-not-on-top-of-my.html' title='State and CycledEnumerator'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8475460820168313017</id><published>2010-12-27T13:26:00.000+03:00</published><updated>2010-12-27T13:26:46.362+03:00</updated><title type='text'>Gang Of Four Patterns</title><content type='html'>Some days I find myself really believing that Gang Of Four patterns describe about 90% of all domain-model-related software design tasks out there. On our last design meeting I only had to name the applicable patterns, and that about did it: "Huh, this can be done with a Visitor", or "Sounds like an ordinary Composite to me"... That is not to say I'm good, but rather to reiterate what this guy told me once: "Everything has already been written".&lt;br /&gt;
&lt;br /&gt;
("Design Patterns: Elements of Reusable Object-Oriented Software" was one of the first books I've read on the subject, years ago, and it's a really good read.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8475460820168313017?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8475460820168313017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/12/gang-of-four-patterns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8475460820168313017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8475460820168313017'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/12/gang-of-four-patterns.html' title='Gang Of Four Patterns'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-3809395581056269577</id><published>2010-08-23T00:12:00.001+04:00</published><updated>2010-09-12T21:54:47.571+04:00</updated><title type='text'>Databases vs. everchanging model</title><content type='html'>This sprint I've been struggling hard to postpone the creation of a database to back up WCF service operations 'till next sprint. Last sprint I've insisted on keeping the store of service objects in memory - so the service loses all data upon restart. This was enough to make an iteration (and I think it was a good decision) but a lot of people on the team pushed back.&lt;br /&gt;
&lt;br /&gt;
The reason I don't want a database from day 1 is our domain model is undergoing such changes that it would have taken us an entire sprint redesigning the database for every change, if we had decided to go down that road. We've spent that time on useful things instead, I hope.&lt;br /&gt;
&lt;br /&gt;
Last week we, again, came to a point where a decision was needed on whether to create the database or not. And once again I pushed back, so we've chosen to save all data into a single file (having more than one would require extra work for reconstructing object references) using plain old data contracts. A question came up though: how do you save all those different collections of domain model elements preserving object references between those collections? The answer to that was dumping all objects into a List&amp;lt;object&amp;gt;, creating a DataContractSerializer around it (with exactly that type - List&amp;lt;object&amp;gt;), feeding to the serializer a list of known types made of all types of contracts (note that it's no longer domain model elements) that are used to store the state of the service, telling the serializer to preserve object references. Of course, all of this would still be hard to do (because of reference fixups), if we had not decided to use data contracts everywhere for the state of the service - as opposed to domain model objects we had in sprint 1.&lt;br /&gt;
&lt;br /&gt;
Note that this is a temporary solution, we will migrate to a database at some point. That said, I suppose modifying data contracts is slightly easier than modifying the database -- I may be exaggerating the complexity of making changes to the databases since I haven't seen any database refactoring tools, and there must be some.&lt;br /&gt;
&lt;br /&gt;
(When putting the reconstructed object graph' elements back to their collections we've iterated thru deserialized elements and added them to appropriate collections depending on the type of element).&lt;br /&gt;
&lt;br /&gt;
Could post the code proving the concept works, if anyone is interested.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-3809395581056269577?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/3809395581056269577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/08/databases-vs-everchanging-model.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3809395581056269577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3809395581056269577'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/08/databases-vs-everchanging-model.html' title='Databases vs. everchanging model'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-6638905163919838469</id><published>2010-06-26T22:24:00.006+04:00</published><updated>2010-07-03T21:05:57.087+04:00</updated><title type='text'>Generics</title><content type='html'>Generics this generics that. Surely, generics were one of the main hits of .Net FW 2.0 and you all know the advantages they give you, but what about disadvantages? The books I've read on software development are hardly giving anything for disadvantages, and that's suspicios because nothing is ideal and if you gain something, that means losing something the very same moment you gain.&lt;br /&gt;
&lt;br /&gt;
The pain in the ass generics give you can be described as follows:&lt;br /&gt;
- generic classes and interfaces with more than two type parameters are hard to understand and maintain;&lt;br /&gt;
- generic class, say, List&amp;lt;B&amp;gt; is not convertible to List&amp;lt;A&amp;gt; if B is subclass of A (as of .Net FW 3.5), moreover there is no direct relationship between List&amp;lt;A&amp;gt; and List&amp;lt;B&amp;gt; which could be described in terms of OO paradigm;&lt;br /&gt;
- generics cypher the code to some extent: when you see an instance of Mine.MyGenericType&amp;lt;Mine.MyType1, Mine.MyType2, Mine.MyType2&amp;gt; in code you have to scratch your head to figure out which parameter means what, because they only have names internal to MyGenericType and don't mean anything outside of that class (this is somewhat less of a problem when you are writing the code, thanks to intellisense);&lt;br /&gt;
- generics used solely for type safety scare me a bit: the main drivers for introducing generics were code reuse, type safety and performance (in that order). There is usually a way or two to avoid using generics without losing type safety.&lt;br /&gt;
&lt;br /&gt;
That's my humble opinion and don't get me wrong, I absolutely love generics. Just make sure you don't rely on them too much.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-6638905163919838469?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/6638905163919838469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/06/generics.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6638905163919838469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6638905163919838469'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/06/generics.html' title='Generics'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-4967139652434669184</id><published>2010-05-26T23:05:00.002+04:00</published><updated>2010-05-26T23:19:07.132+04:00</updated><title type='text'>Buggy trace listener</title><content type='html'>Recently a colleague of mine ran into the troublesome &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.textwritertracelistener.aspx"&gt;TextWriterTraceListener&lt;/a&gt;. As the name suggests, it's a trace listener that writes trace messages to a file. The way you use it, as any other listener, is as follows: either you instantiate the listener in code and add it to the static Trace.Listeners collection, or let the runtime do the same thing for you by saying so in App.config -- then you dispatch trace messages to this and other trace listeners hooked up, thru the static Trace class.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The TextWriterTraceListener and the Trace class work together just fine, as long as you don't try to use them from a finalizer when your application is terminating. &lt;/b&gt;You say "Trace.Writeline("Hi John, got some bad news for you!")" in the finalizer of your class which happens to run -- among other cases -- during application shutdown, and doh! -- you get a marvelous error saying that the FILE has already been closed. Isn't it just nice?&lt;br /&gt;
&lt;br /&gt;
(The listener references a FileStream which has a finalizer of its own and finalizers run in no particular order: chances are your finalizer (calling into Trace) will be out of luck, calling into a dead trace listener. There are several ways in which you can make that listener do a better job, but I ended up not using Trace and TextWriterTraceListener at all. This is definitely a design flaw in both Trace and that particular listener. It should be fixed from the inside, I don't want to work around this).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-4967139652434669184?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/4967139652434669184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/05/buggy-trace-listener.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/4967139652434669184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/4967139652434669184'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/05/buggy-trace-listener.html' title='Buggy trace listener'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-1125848804561152543</id><published>2010-04-09T01:22:00.004+04:00</published><updated>2010-04-09T01:40:01.918+04:00</updated><title type='text'>AppDomains and true isolation</title><content type='html'>As you may very well know, .Net Application domains (or AppDomains for short) are the "lightweight processes", according to authors of several books on .Net Framework (FW) I've read, and -- to a great many developers I've spoken to. For most part I agree with the metaphor, but there is one thing the AppDomains do not provide you with, while processes do: fault tolerance. The operating system doesn't crash if one of its processes crashes. But as of .Net FW 2.0 an unhandled exception in any AppDomain in a process brings that process down. I tend to think in terms of corner cases, worst case scenarios (my analyst complains about that a lot), so for me this basically means that Appdomains hardly provide any isolation at all.&lt;br /&gt;
&lt;br /&gt;
Let's look at the ways of fixing that. One way to go would be to create a custom CLR host which would override the standard policy for unhandled exceptions. I will not cover this option as I'm not an expert at customizing CLR hosts. Another way is to revert to .Net FW 1.0/1.1 policy for unhandled exceptions, AND (this is very important) to emulate .Net FW 2.0 policy for the main Appdomain of the application, and to unload other domains, should they encounter an unhandled exception. This is the way I'm going to show and explain.&lt;br /&gt;
&lt;br /&gt;
First, let's prove that the problem exists. The following code crashes the process for good (see for yourself by compiling it in a console application). Run it without the debugger attached -- to not be stuck on the line where the exception is being thrown:&lt;br /&gt;
&lt;pre class="brush: c-sharp;"&gt;class Program
{
    private static AppDomain _subDomain;

    static void Main(string[] args)
    {
        _subDomain = AppDomain.CreateDomain("CodeRunningDomain");

        try
        {
            _subDomain.DoCallBack(delegate()
            {
                new Thread(delegate()
                {
                    throw new InvalidOperationException();
                }).Start();
            });
        }
        catch
        {
            // this block is for demonstration purposes only,
            // generally it's not a good idea to catch System.Exception.
            // this block is never hit, of course
        }

        Thread.Sleep(TimeSpan.FromDays(2)); // the process is torn down faster than in 2 days, you will see.
    }
}
&lt;/pre&gt;&lt;br /&gt;
Not much to explain here -- an unhandled exception by now-standard .Net policy tears down the process. I agree that this is a great default policy due to possible state corruptions related to an error that went unhandled. But in case you're building a host, say for running plugins in their own AppDomains, or trying to execute a piece of code you don't trust in its own AppDomain, you don't want your host to die because a plugin has errored out, or because the code you did not trust, proved right your assumptions about it.&lt;br /&gt;
&lt;br /&gt;
First step to work around the issue is to put the crappy .Net FW 1.0/1.1 unhandled exception policy back to business. According to this policy, the process is not torn down, when an exception goes unhandled, as you may know. To achieve this, paste the following to a newly created application configuration file for the Console Application you've probably created to run the code above:&lt;br /&gt;
&lt;pre class="brush: c-sharp;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;runtime&amp;gt;
    &amp;lt;legacyUnhandledExceptionPolicy enabled=&amp;quot;true&amp;quot;/&amp;gt;
  &amp;lt;/runtime&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Now everything runs without crashing and the program will block for years, if you let it. But that's not what we want: .Net FW 2 policy for exceptions happens to be cool, we want it back, but only for the main AppDomain. Here is what we do: we hook up the handlers for every unhandled exception in every AppDomain. When an exception propagates up the main AppDomain (it does propagate), we look which domain has it originated from, if it's not from the main AppDomain, we unload the offending AppDomain and carry on. Otherwise we tear the process down, as (not exactly, but close) the CLR does in these cases. Of course, we're working under the assumption that a failure in one AppDomain does not (and mustn't) affect the other domains. Keep in mind that this bold assumption is not always true. I don't want to bore you to death, here is the code. (Again: run it without the debugger attached -- to not be stuck on the line where the exception is being thrown.)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c-sharp;"&gt;using System;
using System.IO;
using System.Threading;

namespace ProperAppDomainIsolation
{
    class Program
    {
        private static AppDomain _subDomain;

        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException +=
              new UnhandledExceptionEventHandler(MainDomain_UnhandledException);

            _subDomain = AppDomain.CreateDomain("CodeRunningDomain");

            _subDomain.UnhandledException +=
              new UnhandledExceptionEventHandler(Subdomain_UnhandledException);

            try
            {
                _subDomain.DoCallBack(delegate()
                {
                    new Thread(delegate()
                        {
                            throw new InvalidOperationException();
                        }).Start();
                });
            }
            catch (Exception)
            {
                // log, throw, do something.
            }

            Thread.Sleep(TimeSpan.FromDays(2));
        }

        static void MainDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
   // runs in main AppDomain
            Exception exception = e.ExceptionObject as Exception;

            if (exception == null)
            {
                Environment.FailFast("Very descriptive message");
            }

            Console.WriteLine("Got an exception in main application domain.");

            try
            {
                Marker exceptionMarker = ExceptionMarker.GetExceptionMarker(exception);

                Console.WriteLine("Retrieved marker: " + exceptionMarker.Value);
                Console.WriteLine("Offending AppDomain: " + _subDomain.Id);

                if (exceptionMarker.Value.Equals(_subDomain.Id.ToString(), StringComparison.Ordinal))
                {
                    new Thread(delegate()
                        {
                            try
                            {
                                Console.WriteLine("Unloading the offending application domain...");

                                AppDomain.Unload(_subDomain);
                                _subDomain = null;

                                Console.WriteLine("Unloaded the offending application domain...");
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.ToString());
                            }
                        }).Start();
                }
            }
            catch (InvalidOperationException)
            {
                // exception is not marked - originates from the main application domain. Demonstration code - a more specific exception type is required.
                Environment.FailFast("Terminating to an unhandled exception in the main Application Domain.");
            }
        }

        static void Subdomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
   // runs in subdomain
            Exception exception = e.ExceptionObject as Exception;

            if (exception == null)
            {
                Environment.FailFast("Very descriptive message");
            }

            ExceptionMarker.MarkException(exception, new Marker(AppDomain.CurrentDomain.Id.ToString()));
        }
    }
}
&lt;/pre&gt;&lt;br /&gt;
On my box the output of the program is as follows:&lt;br /&gt;
&lt;br /&gt;
Got an exception in main application domain.&lt;br /&gt;
Retrieved marker: 2&lt;br /&gt;
Offending AppDomain: 2&lt;br /&gt;
Unloading the offending application domain...&lt;br /&gt;
Unloaded the offending application domain...&lt;br /&gt;
&lt;br /&gt;
Now we've got ourselves a host! The only fun part here is in distinguishing between the exceptions that came from the main AppDomain and all other domains.&lt;br /&gt;
&lt;br /&gt;
(ExceptionMarker adds a special marker to the Exception's property bag - in the subdomain, and then reads the marker in main domain; if there is no marker attached to exception, then it originates from the main AppDomain, and the process is doomed. Full source code is &lt;b&gt;&lt;a href="http://sites.google.com/site/ikickandibite/ProperAppDomainIsolation.zip"&gt;here&lt;/a&gt;&lt;/b&gt;.)&lt;br /&gt;
&lt;br /&gt;
P.S. Originally I thought that attaching a configuration file (like the one shown above) to the domains where the code runs, would suffice. Plus I planned on taking care to unload the domains when an exception occurs inside each of them. That didn't work: legacyUnhandledExceptionPolicy seems to affect the main application's AppDomain only.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-1125848804561152543?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/1125848804561152543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/04/appdomains-and-true-isolation.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/1125848804561152543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/1125848804561152543'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/04/appdomains-and-true-isolation.html' title='AppDomains and true isolation'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8520532857515007006</id><published>2010-02-08T00:19:00.001+03:00</published><updated>2010-02-08T00:19:46.371+03:00</updated><title type='text'>lamron</title><content type='html'>"Develop a normal C# class that implements the interface you just defined".&lt;br /&gt;
&lt;br /&gt;
(The fun word here is "normal".)&lt;br /&gt;
&lt;br /&gt;
In overall, it's a great guideline.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8520532857515007006?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8520532857515007006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/02/lamron.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8520532857515007006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8520532857515007006'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/02/lamron.html' title='lamron'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-2582469060704142850</id><published>2010-01-05T00:27:00.001+03:00</published><updated>2010-01-05T14:43:26.542+03:00</updated><title type='text'>Could not have said it better</title><content type='html'>“No one scheme of classification, more than any&amp;nbsp;other, represents the real structure or order of nature. Nature indifferently submits&amp;nbsp;to any and all divisions which we wish to make among existing things. Some classifications&amp;nbsp;may [seem to] be more significant than others, but only by reference to our interests,&amp;nbsp;not because they represent reality more accurately or adequately”.&lt;br /&gt;
&lt;br /&gt;
This quote is from "Object Oriented Analysis and Design". I like the book a lot (although, it could have been shorter), and it's the best part there. If you stop to think about what it says, you will probably find that it's very true. Not only does this apply to object-oriented classification, but for any other classification or schema out there. I could talk for hours about this, but since I promised to keep everything short, I will just say: the life itself is incomprehensible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-2582469060704142850?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/2582469060704142850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2010/01/could-not-have-said-it-better.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/2582469060704142850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/2582469060704142850'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2010/01/could-not-have-said-it-better.html' title='Could not have said it better'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-253948036600237010</id><published>2009-12-31T00:32:00.001+03:00</published><updated>2010-01-03T01:18:17.158+03:00</updated><title type='text'>Short sentences as names of interfaces</title><content type='html'>&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;I've always disliked that rule (most coding standards I saw, had such a rule) about starting names of interfaces with "I". It feels like the Hungarian notation is back. And I found myself using that leading "I" in such a way that the letter really means something. For example, instead of IInputValidator, I would create an interface named&amp;nbsp;IValidateInput. This is a very reader-friendly name, in my opinion: it doesn't force you into using a word that doesn't really exist ("validator" is, obviously, a verb turned into a noun; it's not in the dictionary, according to Merriam-Webster). Also, this name explains what the implementer does, and explains in a natural way. "What is your responsibility?" - you ask the interface. "I validate input", - it replies.&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Of course, all of the above applies only if the interface describes something that does one thing. In general, I prefer nouns and adjectives when naming interfaces.&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-253948036600237010?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/253948036600237010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/12/short-sentences-as-names-of-interfaces.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/253948036600237010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/253948036600237010'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/12/short-sentences-as-names-of-interfaces.html' title='Short sentences as names of interfaces'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-860982944110683875</id><published>2009-12-20T00:10:00.021+03:00</published><updated>2010-07-21T00:04:39.389+04:00</updated><title type='text'>Countdown Latch, take #1</title><content type='html'>OK, enough ranting. It's time to post something useful. Here is a Countdown Latch&amp;nbsp;I wrote some time ago. A countdown latch is a thread-safe object that has a counter associated with it. The latch allows threads to block until that counter -- you can only decrement the counter -- reaches zero. I always missed it in .Net FW, and one is going to be in FW 4 -- finally!&lt;br /&gt;
&lt;br /&gt;
(UPDATE: of course, only after writing this I've discovered an easier solution -- one using Monitor.Wait() and Monitory.PulseAll()).&lt;br /&gt;
&lt;br /&gt;
Here is the listing:&lt;br /&gt;
&lt;pre class="brush: c-sharp;"&gt;using System;
using System.Globalization;
using System.Threading;

namespace Primitives.Threading
{
    /// &lt;summary&gt;
    /// A thread-safe counter (goes only down) that is capable
    /// of blocking threads until the counter's value reaches zero.
    /// &lt;/summary&gt;
    public class CountdownLatch : IDisposable
    {
        private int currentCount;
        private ManualResetEvent countHasReachedZero = new ManualResetEvent(false);
        private object disposalCriticalSection = new object();
        private ManualResetEvent allWaitingThreadsAreGone;
        private const int MaximumNumberOfWaiters = int.MaxValue - 1;

        /// &lt;summary&gt;
        /// Note: it's safe to access/manipulate the value of this
        /// field only under a lock for disposalCriticalSection,
        /// or using the Inrerlocked methods.
        /// &lt;/summary&gt;
        private int numberOfWaitingThreads;

        private bool disposed;

        public CountdownLatch(int initialCount)
        {
            if (initialCount &amp;lt;= 0)
                throw new ArgumentOutOfRangeException(
                    "initialCount",
                    "Must be greater than zero.");

            this.currentCount = initialCount;
        }

        /// &lt;summary&gt;
        /// Decreases the latch' counter value by one.
        /// Does not throw, if the count has already reached zero.
        /// &lt;/summary&gt;
        /// &lt;exception cref="ObjectDisposedException"&gt;&lt;/exception&gt;
        public void Decrement()
        {
            lock (this.disposalCriticalSection)
            {
                this.MakeSureTheLatchHasNotBeenDisposed();

                if (this.currentCount &amp;gt; 0)
                {
                    this.currentCount--;

                    if (this.currentCount == 0)
                    {
                        this.countHasReachedZero.Set();
                    }
                }
            }
        }

        /// &lt;summary&gt;
        /// Current latch counter value.
        /// This is for informational purposes only.
        /// &lt;/summary&gt;
        public int CurrentCount
        {
            get
            {
                return Thread.VolatileRead(ref this.currentCount);
            }
        }

        /// &lt;summary&gt;
        /// Blocks the calling thread until the latch count becomes zero.
        /// &lt;/summary&gt;
        /// &lt;exception cref="ObjectDisposedException"&gt;&lt;/exception&gt;
        /// &lt;exception cref="InvalidOperationException"&gt;&lt;/exception&gt;
        public void WaitUntilCountIsZero()
        {
            lock (this.disposalCriticalSection)
            {
                this.MakeSureTheLatchHasNotBeenDisposed();

                this.IncrementNumberOfWaiters();
            }

            try
            {
                this.countHasReachedZero.WaitOne();

                this.ThrowIfHandleHasBeenSetByDispose();
            }
            finally
            {
                this.DecrementNumberOfWaitersSignalingTheHandleIfDisposing();
            }
        }

        /// &lt;summary&gt;
        /// This is an insane precaution: even having that many threads is simply impossible.
        /// &lt;/summary&gt;
        /// &lt;exception cref="InvalidOperationException"&gt;&lt;/exception&gt;
        private void IncrementNumberOfWaiters()
        {
            this.numberOfWaitingThreads++;

            if (this.numberOfWaitingThreads == MaximumNumberOfWaiters)
            {
                this.numberOfWaitingThreads--;

                throw new InvalidOperationException(
                    String.Format(
                        "Cannot block - only as many as {0} waiting threads are supported.",
                        MaximumNumberOfWaiters));
            }
        }

        private void DecrementNumberOfWaitersSignalingTheHandleIfDisposing()
        {
            lock (this.disposalCriticalSection)
            {
                this.numberOfWaitingThreads--;

                if (this.disposed &amp;amp;&amp;amp; (this.numberOfWaitingThreads == 0))
                {
                    this.allWaitingThreadsAreGone.Set();
                }
            }
        }

        /// &lt;summary&gt;
        /// Blocks the calling thread until the latch' counter value
        /// is zero or specified amount of time passes.
        /// &lt;/summary&gt;
        /// Amount of time to wait for latch'
        /// counter value to reach zero.
        /// &lt;returns&gt;True, if the latch has signaled (counter reached zero)
        /// before specified Time Span elapsed; False, otherwise.&lt;/returns&gt;
        /// &lt;exception cref="ObjectDisposedException"&gt;&lt;/exception&gt;
        /// &lt;exception cref="ArgumentOutOfRangeException"&gt;&lt;/exception&gt;
        /// &lt;exception cref="InvalidOperationException"&gt;&lt;/exception&gt;
        public bool WaitUntilCountIsZero(TimeSpan waitTimeSpan)
        {
            lock (this.disposalCriticalSection)
            {
                this.MakeSureTheLatchHasNotBeenDisposed();

                if (waitTimeSpan &amp;lt; TimeSpan.Zero)
                    throw new ArgumentOutOfRangeException(
                        "waitTimeSpan",
                        "Must be greater than TimeSpan.Zero.");

                this.IncrementNumberOfWaiters();
            }

            try
            {
                bool gotZero = this.countHasReachedZero.WaitOne(waitTimeSpan);

                if (gotZero)
                {
                    this.ThrowIfHandleHasBeenSetByDispose();
                }

                return gotZero;
            }
            finally
            {
                this.DecrementNumberOfWaitersSignalingTheHandleIfDisposing();
            }
        }

        private void ThrowIfHandleHasBeenSetByDispose()
        {
            lock (this.disposalCriticalSection)
            {
                if (this.disposed &amp;amp;&amp;amp; (this.currentCount != 0))
                    throw new ObjectDisposedException(this.GetType().FullName);
            }
        }

        /// &lt;summary&gt;
        /// Disposes of all unmanaged resources allocated by the latch.
        /// (The kernel objects used, are released).
        /// Also: releases all waiting threads.
        /// &lt;/summary&gt;
        public void Dispose()
        {
            bool needToWaitForWaitersToFallOff = false;

            lock (this.disposalCriticalSection)
            {
                if (this.disposed)
                    return;

                this.countHasReachedZero.Set();
                this.disposed = true;

                if (this.numberOfWaitingThreads &amp;gt; 0)
                {
                    this.allWaitingThreadsAreGone = new ManualResetEvent(false);
                    needToWaitForWaitersToFallOff = true;
                }
            }

            if (needToWaitForWaitersToFallOff)
            {
                this.allWaitingThreadsAreGone.WaitOne();
                this.allWaitingThreadsAreGone.Close();
            }

            this.countHasReachedZero.Close();
        }

        private void MakeSureTheLatchHasNotBeenDisposed()
        {
            if (this.disposed)
                throw new ObjectDisposedException(this.GetType().FullName);
        }
    }
}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-860982944110683875?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/860982944110683875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/12/countdown-latch-take-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/860982944110683875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/860982944110683875'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/12/countdown-latch-take-1.html' title='Countdown Latch, take #1'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-4171434788990605430</id><published>2009-08-10T19:05:00.022+04:00</published><updated>2009-12-20T00:58:08.846+03:00</updated><title type='text'>FIFO, fairness and synchronization primitives</title><content type='html'>Recently I ran a few multithreaded tests to figure out whether FIFO principle (First In, First Out) is respected for ManualResetEvent, AutoResetEvent, ReaderWriterLockSlim or the Monitor. I'm glad to report: all those nice things mentioned above do not support FIFO.&lt;br /&gt;
&lt;br /&gt;
Why bother with FIFO in the first place? Well, it's a question of fairness: say you have a ReaderWriterLockSlim (or any other primitive from the list above) along with 2 writers waiting for a lock, one of them has been waiting for a minute and a half, and the other one has been waiting for only 2 seconds -- are they really equal like ReaderWriterLockSlim assumes, or are they not? I think, in the scenario described, we should favor the writer that started waiting earlier. You can &lt;strong&gt;use queues to achieve &lt;/strong&gt;just &lt;strong&gt;that&lt;/strong&gt; (at least this is what I did). This &lt;span style="font-weight: bold;"&gt;applies to &lt;/span&gt;&lt;strong&gt;any synchronization primitive&lt;/strong&gt;.&lt;br /&gt;
&lt;br /&gt;
Monitor seems to be the nicest of all four: it behaves perfectly well in terms of FIFO on a single-CPU, single-core PC. However, this is not the case with Quad-core processors, for instance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-4171434788990605430?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/4171434788990605430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/08/fifo-fairness-and-synchronization.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/4171434788990605430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/4171434788990605430'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/08/fifo-fairness-and-synchronization.html' title='FIFO, fairness and synchronization primitives'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-3559813440957424941</id><published>2009-07-29T22:06:00.000+04:00</published><updated>2009-07-29T22:26:21.457+04:00</updated><title type='text'>Moving in</title><content type='html'>This is my first entry here. I've just moved from &lt;a href="http://idontwasteink.spaces.live.com/blog/"&gt;http://idontwasteink.spaces.live.com/blog/&lt;/a&gt; with all my entries.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-3559813440957424941?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/3559813440957424941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/moving-from-spaces-at-livecom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3559813440957424941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/3559813440957424941'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/moving-from-spaces-at-livecom.html' title='Moving in'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-6946448789130110492</id><published>2009-07-15T22:23:00.000+04:00</published><updated>2009-07-29T22:23:43.242+04:00</updated><title type='text'>Best class' description of all time</title><content type='html'>ConfigurationErrorsException class (.Net Framework) is described precisely this way: "The current value is not one of the EnableSessionState values".

Very informative, to say the least. I think it's worth noting that this class is also not a Godzilla and not a Popsicle.

Of course, we all make mistakes (I personally make dozens of them every day, and if it wasn't for TDD...), I'm just trying to stress the same old point: do not cipher your code, it's hard enough to read as it is. And misleading class' description can be nasty (although it's way worse to cipher names of classes).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-6946448789130110492?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/6946448789130110492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/best-class-description-of-all-time.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6946448789130110492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6946448789130110492'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/best-class-description-of-all-time.html' title='Best class&apos; description of all time'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8533245828917649465</id><published>2009-07-08T22:22:00.001+04:00</published><updated>2009-12-27T01:57:51.064+03:00</updated><title type='text'>Would not it be nice</title><content type='html'>&lt;div class="bvMsg" id="msgcns!2EA4BA959BE42E47!143"&gt;T-SQL and the likes have disappointed me years ago. I'm not sure though what hurts readability more -- the wildcard star in "SELECT * FROM ...", or the tragically misplaced "&lt;a href="http://www.merriam-webster.com/dictionary/where" target="_blank"&gt;WHERE&lt;/a&gt;" statement (e.g. "SELECT FirstName FROM ... WHERE..."). &lt;em&gt;[Instead it could have been: "RETRIEVE DATA &lt;everything&gt; FROM MyTable INCLUDING/EXCLUDING (...set of filters goes here...)" -- I didn't give a lot of thought to this imaginary query, therefore, the language used may not be sufficient for defining any query on the planet, but, in my opinion, it's much easier to read and understand than the modern SQL counterparts].&lt;/everything&gt;&lt;/em&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;
&lt;/i&gt;&lt;br /&gt;
"I'm used to reading/writing SQL statements the way they are being defined now, -- you might argue, -- And those statements make perfect sense to me!" Of course, it makes sense, but it's just another cipher you had spent some time breaking, memorized the ciphering/deciphering algorithm and voila: you understand SQL queries. Would not it be nice, if there were fewer ciphers (there are thousands in IT) to break and memorize? That would boost IT-productivity and make our work less complicated.&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8533245828917649465?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8533245828917649465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/would-not-it-be-nice.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8533245828917649465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8533245828917649465'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/would-not-it-be-nice.html' title='Would not it be nice'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-2990907441042465533</id><published>2009-06-26T22:21:00.001+04:00</published><updated>2009-12-27T02:03:09.328+03:00</updated><title type='text'>Sharp stuff</title><content type='html'>If something is math-related, it's unreadable.  Long live C#, die F#, die LINQ. I ain't fucking touching anything with lambda in it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-2990907441042465533?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/2990907441042465533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/06/sharp-stuff.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/2990907441042465533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/2990907441042465533'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/06/sharp-stuff.html' title='Sharp stuff'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-775987453389840866</id><published>2009-06-24T22:20:00.005+04:00</published><updated>2009-09-26T13:47:54.815+04:00</updated><title type='text'>ROI for WCF and WF</title><content type='html'>This spring I had a lot of time and no job. So I was lying on the floor, weighting the possibilities: I could become a bum, sell my yacht, dig deeper into Windows Workflow Foundation (WF), or I could go with Windows Communication Foundation (WCF). I had all the books I needed to decide -- three on WF, two on WCF. I carefully looked at those books, read all the introductions inside, and it became clear to me that WCF had a better return-on-investment (ROI). First, books about WCF are 20-30% thinner than those about WF (you invest less time). Second (you get more possibilities in return), WCF seemed to be more valuable for a whole lot of my possible employers: I think WCF-services will become no less popular than web-services pretty soon, and WCF is a unified platform (there are limitations) for building distributed applications. Those are in high demand these days.&lt;br/&gt;&lt;br/&gt;
WF, on the other hand, provides a unified platform for running and designing workflows, for automation of business processes. If you decide to spend time learning WF, you will end up with business process logic decomposed into workflows, which are made out of activities. If the design will be ok, you will be able to get the stuff automated with less software developers and more analysts. But it's not clear to me who would want to translate business logic from, say, pure C# to a well-designed workflow with corresponding activity libraries (let's assume those will also be created with C# code) -- the effort required to do the job is substantial. At the same time when you're migrating from, say, a web-service to a WCF-service, almost all code just stays the same in majority of scenarious.&lt;br/&gt;&lt;br/&gt;I must also note that if you want to automate business-processes, all you need to know is C#. That's a great unified platform by itself. WF adds value, but increases costs, while WCF adds more, and it decreases costs, as it really provides a common model for coding distributed applications. WCF &lt;span style="font-weight: bold;"&gt;isolates &lt;/span&gt;you from excess information to a degree: you don't have to be intimately familiar with ASMX, WSE, MSMQ, IIS or whatever to start creating distributed applications, all you need is WCF (and an experienced architect). Therefore, WCF seems to be more newcomer-friendly and a great investment.&lt;br/&gt;&lt;br/&gt;In short, I'm sure it takes longer to see the benefits of WF in action, than it is with WCF. I may be wrong, and I haven't covered all bases here, but that's what I was thinking while choosing between WCF and WF.&lt;br/&gt;&lt;br/&gt;P.S.&lt;br/&gt;
Maybe WPF or Entity Framework, or another fancy new thing is great too, but it's out of my area of expertise. And for me it's one thing at a time.&lt;br/&gt;&lt;br/&gt;
P.P.S.&lt;br/&gt;
I had some experience with both WCF and WF, when I was lying on the floor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-775987453389840866?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/775987453389840866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/roi-for-wcf-and-wf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/775987453389840866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/775987453389840866'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/roi-for-wcf-and-wf.html' title='ROI for WCF and WF'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8596691404259678620</id><published>2009-06-21T22:19:00.002+04:00</published><updated>2010-12-24T21:26:32.101+03:00</updated><title type='text'>Usage Errors and ArgumentException</title><content type='html'>&lt;div class="bvMsg" id="msgcns!2EA4BA959BE42E47!127"&gt;&lt;span lang="EN-US"&gt;I'm a bit defensive when I write software. I'm careful with the preconditions in every method and I always validate arguments of all methods. So I throw ArgumentExceptions a lot. The question is: should the code, which is calling into my code, catch and handle those exceptions or should it let the CLR kill the executing process by letting the exception propagate to the top of call stack unhandled? Many people say it's a good idea not to catch ArgumentExceptions, because those exceptions usually indicate usage errors, therefore, erroneous code must be recompiled, retested and reshipped.  I am not sure about this idea being good. Why should everything crash if a method is has been called with improper arguments? The logic that acts as the argument guard must precede any business logic in a method, so if you get an ArgumentException it also says that there is no inconsistency in the system state (there is -- only produced by callers up the stack). So I catch ArgumentExceptions, log them, send error reports (optionally), recover from those exceptions (fixing inconsistency produced up the stack, if any) and continue running the application.&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;Yes, maybe you get an ArgumentException because a subsystem (a piece of logic, a function, a feature) is not working in the current release. So be it, maybe we should turn this failing feature off then? -- after we get a certain number of similar exceptions? Yes, this requires a bit of management, domain expertise, and some architectural effort, but I, as a user, fucking hate crashing applications.&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;Take a text processor for example. Imagine that every time you click «File-&amp;gt;Save as…» in the menu, a usage error occurs, an ArgumentException is thrown -- should we close the application and report an error, or can we report the error and continue running the application? I vote for option #2: nothing critical has happened, and I would prefer either just logging the error, reporting it or blocking the erroneous execution path for the release (e.g. by disabling the menu item) to closing the app, losing &lt;/span&gt;&lt;span lang="EN-US"&gt;the document that the user had been editing&lt;/span&gt;&lt;span lang="EN-US"&gt; and then trying to recover it.&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;P.S. of course, there are ArgumentExceptions indicating that the application is unusable -- it depends on which component throws and under which circumstances.&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span lang="EN-US"&gt;UPDATE: I have changed my opinion three months after posting this. I do prefer to not catch ArgumentException-s.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8596691404259678620?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8596691404259678620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/06/usage-errors-and-argumentexception.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8596691404259678620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8596691404259678620'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/06/usage-errors-and-argumentexception.html' title='Usage Errors and ArgumentException'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8527844752795068916</id><published>2009-03-17T21:17:00.000+03:00</published><updated>2009-07-29T22:18:29.357+04:00</updated><title type='text'>Quote of the day</title><content type='html'>&lt;div id="msgcns!2EA4BA959BE42E47!126" class="bvMsg"&gt; &lt;div&gt;"Sometimes a toolkit class that's designed for reuse isn't reusable..."
("only because its interface doesn't match the domain-specific interface an application requires").

&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;From my experience: class that's designed for reuse is rarely indeed reusable.&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;Or I can go even further: any class is barely usable.

&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;The guideline, therefore, is this: do not use classes           :P&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8527844752795068916?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8527844752795068916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/03/quote-of-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8527844752795068916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8527844752795068916'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/03/quote-of-day.html' title='Quote of the day'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-808856570317102845</id><published>2009-02-16T22:16:00.000+03:00</published><updated>2009-07-29T22:16:47.773+04:00</updated><title type='text'>kick #2</title><content type='html'>Here I'm continuing what I've started the last time.&lt;span style="font-weight: bold;"&gt;

Coding: technical aspects, part #1&lt;/span&gt;

Everyone knows, there are best practices for handling exceptions. One of the design guidelines for exception-handling says: "Avoid handling errors by catching non-specific exceptions, such as System.Exception, System.SystemException, and so on, in application code."

That's a great piece of advice (yes, you can never handle all the exceptions), as long as you don't use .Net Framework (.Net FW). One reason for this is you never know for sure which types of exceptions can be raised by the code (MSDN or intellisense not always help here, believe me, I've dug though some call stacks pretty deep just to get the exception types).
There are other problems:
1) invoking same methods can produce different types of exceptions in different versions of .Net FW (see how the Mutex class behaves in v1.1 and v2.0). So if you're writing anything forward-compatible (that's you're planning to move to the next FW version someday), you'll have to retest every piece of Framework code for exceptions before actually migrating to the new FW. So some developers prefer catching non-specific exceptions and then filtering irrecoverable exceptions and throwing them no matter what -- this breaks another design guideline which says "Do not exclude any special exceptions when catching for the purpose of transferring exceptions". BTW, MS guys themselves do love filtering exceptions.
2) .Net FW throws exceptions of type System.Exception (WMI is written particularly badly and does just that in many places) -- how I'm supposed to _handle_ this ugly stuff in a nice way, I wonder?

Therefore, most of the time we, developers end up either filtering exceptions by type (by throwing only some of 'em) after cathing the most general System.Exception or even worse -- not filtering and just catching. It's just impossible to do proper exception handling at a 100% in .Net FW at the moment. I see only one way through this mess: make all developers decorate every method with attributes which tell what types of exceptions the method throws (throwing SystemExceptions or just Exceptions must be prohibited).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-808856570317102845?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/808856570317102845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/02/kick-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/808856570317102845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/808856570317102845'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/02/kick-2.html' title='kick #2'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-8573635518595178985</id><published>2009-02-08T22:13:00.000+03:00</published><updated>2009-07-29T22:14:21.882+04:00</updated><title type='text'>A kick in the arse</title><content type='html'>Looks like the IT industry is going to take a break for tea and biscuits in coming years. And you know what? -- we sure as hell asked for this. We needed a major kick in the ass to get real, and here it is finally.

&lt;span style="font-weight: bold;"&gt;Unreadable code&lt;/span&gt;
What makes me think we're in deep shit? Well, I've worked on a few projects last 18 months for a large US company that loves to outsource, and I had to take a deep dive into some of .Net Framework's source code. Some of our projects we had to build over those projects other outsourcers had already completed. I've seen a lot of scary stuff (more on .Net later, in other posts), tons of barely readable texts. Yes, it's texts we're actually writing, guys, think twice about how you're gonna name your next class, next method, even next local variable. I'm sure that the vast majority of software developers is not even up for the job -- I mean crafting readable software not only takes a good developer, it takes one that has gut-feeling for simplicity, one that has his/her way with words, it might even take one that is not a developer at all. Right now maintainability of the vast majority of applications is lower than negative infinity. Make 'em usability tests if you're not sure you've created a good class (after the design meeting) -- drop a class diagram by your colleagues, make your manager approve this "time-waster", step up.

I thought of giving a little (rather ill) example. Meant to tell you about how much time I've killed over a method which was named something like PrettyPrintAnErrorMessage(...) -- and it actually filtered exceptions inside, threw some kinds and swallowed others. The point of the story would have been: give a meaningful name to a method -- the one saying what the method _really_ does. I called that example rather ill because naming was not the only problem there -- it's just so not the way to handle exceptions (me and my guys had to do helluva job when we've found out about that _pretty_ printing). I decided to cut the story short because the computer science, the OO theory itself, C# language construct's names present some bigger issues.

I'm gonna take the singleton pattern to make a point. You have to define the singleton as a class, right? But it's not a class at all -- a class is &lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;&lt;/strong&gt; "a group, set, or kind sharing common attributes". You see where I'm going with this? The computer science, the OO theory, C# encourages us to write crap that only we understand, encourages by having a vocabulary where many words (like class) we might use in everyday life have odd meanings. By making the science's vocabulary (every science has one) simpler, by removing those cross-vocab intersections, we could make texts -- I mean code -- more readable. But it's a little late for that change, isn't it? The only thing we can do, as our part of the job, is to admit: we, software developers, are regular people, and so is the vocabulary we're using most of the time. Leave with it. No fancy names, just plain and simple stuff. I mean this: even the names of domain classes are to be reviewed if they're cryptic. Domain experts are regular people too, they may suck at giving names to things -- as much as we suck at naming classes today.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-8573635518595178985?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/8573635518595178985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/looks-like-it-industry-is-going-to-take.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8573635518595178985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/8573635518595178985'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/looks-like-it-industry-is-going-to-take.html' title='A kick in the arse'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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-7289061379610528811.post-6536047993367455832</id><published>2009-01-09T22:14:00.000+03:00</published><updated>2009-07-29T22:15:43.169+04:00</updated><title type='text'>Starting up</title><content type='html'>Starting today I will be blogging about software development.

I'll try to keep it short and up-to-the-point. Hopefully, somebody will find my notes helpful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7289061379610528811-6536047993367455832?l=ikickandibite.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ikickandibite.blogspot.com/feeds/6536047993367455832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/starting-up.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6536047993367455832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7289061379610528811/posts/default/6536047993367455832'/><link rel='alternate' type='text/html' href='http://ikickandibite.blogspot.com/2009/07/starting-up.html' title='Starting up'/><author><name>Michael</name><uri>http://www.blogger.com/profile/02654985911594195772</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>
