<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Goblincave</title>
	<atom:link href="http://goblincave.net/feed" rel="self" type="application/rss+xml" />
	<link>http://goblincave.net</link>
	<description>WPF, C# i den lidt større sammenhæng</description>
	<lastBuildDate>Tue, 12 Jan 2010 08:55:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Performancetuning &#8211; what a b&#8230;</title>
		<link>http://goblincave.net/01/2010/performancetuning-what-a-b.php</link>
		<comments>http://goblincave.net/01/2010/performancetuning-what-a-b.php#comments</comments>
		<pubDate>Tue, 12 Jan 2010 08:55:32 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[English posts]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=345</guid>
		<description><![CDATA[We have gone through some major refactorings lately due to performance problems. And while our performance has drastically improved &#8211; we are now at a point where further optimizations will prove futile. The reasons are many &#8211; the time we spend on performance tuning is now approaching a diminishing return, complexity in code is approaching [...]]]></description>
			<content:encoded><![CDATA[<p>We have gone through some major refactorings lately due to performance problems. And while our performance has drastically improved &#8211; we are now at a point where further optimizations will prove futile. The reasons are many &#8211; the time we spend on performance tuning is now approaching a diminishing return, complexity in code is approaching problematic levels thus increasing cost of maintenance to name a few. I would now much rather throw hardware at it until it goes away. </p>
<p>Interesting bugs also rear their ugly head &#8211; it turns out that running our developement on the newest of the newest in terms of hardware and software versions is problematic, since our test customer is running on an erhm&#8230; let us say technically challenged platform. We are using every tool in the shed in terms of query-optimization in NHibernate &#8211; and it turns out there is a corner-case where certain combinations will work on SQL server 2005 but not SQL server 2000. I&#8217;m working on testing it on a small test project to prove that it is not us, that are idiots. For those interested &#8211; our bug manifested using HQL, a sorted query on a class that has joined subclasses with collections that we wanted to use subselects on in a paged resultset &#8211; and no lazy-load (yeah, not the simplest of scenarios&#8230;). NHibernate tries an optimization that uses the function Row_Number() which only works on on 2005 and later, thus throwing an exception. And yes, we use the MSSQL2000 dialect option in NHibernate.</p>
<p>So, before we do any further optimization on their solution, I want them to change to at least a newer version of their database software and get some decent hardware to go along with it. Next step will be cleaning up their workstations (4+ year-old-installations of XP perform&#8230; uhm&#8230; interestingly) and maybe upgrading them with DirectX 10. The problem is that they really do not want to spend much on their IT-infrastructure as they are planning on outsourcing it next summer, but right now their employees are suffering. Originally the plan was that they would have outsourced it already &#8211; we made it clear in the beginning that this new software would be hardware-hungry, but as the saying goes &#8211; &#8220;No battleplan is worth anything once the battle has started&#8221;, so we will adapt and overcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/01/2010/performancetuning-what-a-b.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tilbage til undervisning</title>
		<link>http://goblincave.net/10/2009/tilbage-til-undervisning.php</link>
		<comments>http://goblincave.net/10/2009/tilbage-til-undervisning.php#comments</comments>
		<pubDate>Sat, 31 Oct 2009 20:14:13 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Rants]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Kursus]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=342</guid>
		<description><![CDATA[Så er mit første kursus vel overstået. Det var en fornøjelse at prøve at undervise igen. Alt taget i betragtning gik det også godt. Deltagerne var positivt stemte og havde bortset et par mindre ting omkring kursusmaterialet ikke det store at indvende.
Jeg var lidt nervøs før vi gik i gang &#8211; jeg havde kun mødt [...]]]></description>
			<content:encoded><![CDATA[<p>Så er mit første kursus vel overstået. Det var en fornøjelse at prøve at undervise igen. Alt taget i betragtning gik det også godt. Deltagerne var positivt stemte og havde bortset et par mindre ting omkring kursusmaterialet ikke det store at indvende.</p>
<p>Jeg var lidt nervøs før vi gik i gang &#8211; jeg havde kun mødt den ene af deltagerne og var i tvivl om niveauet, jeg skulle lægge for dagen. Det viste sig dog at jeg havde ramt tæt på bortset fra at vi nåede lidt længere end forventet. De får naturligvis en opdateret version af kursusmaterialet, når jeg har opdateret det med det ekstra.</p>
<p>Undervisningen blev en blanding af en hardcore-design session og så en gennemgående øvelse, hvor de fik lov at bygge en Outlook-klon. Ikke fordi det er nogen banebrydende øvelse &#8211; mange før mig har brugt netop Outlook som baggrund, men det gav mig en chance for at visualisere alle de ting i WPF, som hører hjemme i et crash-course. Jeg var samtidig lidt heldig med de deltagere jeg havde. De havde begge prøvet WinForms og Delphi, så det var rutinerede kræfter, som blot skulle omskoles til WPF.</p>
<p>De næste kurser bliver en udfordring dog &#8211; det her kursus ville jeg kunne holde stort set uden forberedelse. Næste gang bliver det med en eksempel-applikation, hvor abstraktionsniveauet kommer til at lægge langt højere og der skal arbejdes for at gøre det til en strømlinet oplevelse. Kursusmaterialet er godt og vel halvt færdigt &#8211; så det tegner til at alt nok skal lykkes.</p>
<p>Nu mangler jeg bare at få solgt kurserne til nogle flere&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/10/2009/tilbage-til-undervisning.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nyt kursuskatalog ved TransSoft A/S</title>
		<link>http://goblincave.net/09/2009/nyt-kursuskatalog-ved-transsoft-as.php</link>
		<comments>http://goblincave.net/09/2009/nyt-kursuskatalog-ved-transsoft-as.php#comments</comments>
		<pubDate>Mon, 28 Sep 2009 11:56:53 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Diverse]]></category>
		<category><![CDATA[Danske indlæg]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=340</guid>
		<description><![CDATA[Fra i dag har vi åbnet tilmeldingen til vores nye kursuskatalog ved min arbejdsgiver, TransSoft A/S. Det vil indebære en tilbagevenden til uddannelse for mig. Jeg har tidligere undervist og glæder mig til at komme i gang igen. Jeg vil dog stadig have mit primære fokus på udvikling &#8211; men jeg håber at undervisningen kan [...]]]></description>
			<content:encoded><![CDATA[<p>Fra i dag har vi åbnet tilmeldingen til vores nye kursuskatalog ved min arbejdsgiver, <a href="http://transsoft.dk/kursus-afdeling.aspx">TransSoft A/S</a>. Det vil indebære en tilbagevenden til uddannelse for mig. Jeg har tidligere undervist og glæder mig til at komme i gang igen. Jeg vil dog stadig have mit primære fokus på udvikling &#8211; men jeg håber at undervisningen kan inspirere mig i min daglige udvikling.</p>
<p>Kurserne er bredt fordelt over emnerne WPF og agil programmering, hvor undertegnede primært skal varetage WPF-delen.</p>
<p>Vi holder kun kurser i emner, som vi har en aktuel og dyb indsigt i &#8211; og dermed kun de ting, som vi selv benytter til daglig. Vi håber at vi på den måde virkelig kan tilbyde kursisterne noget &#8216;andet&#8217; end det de er vant til. Vi har selv haft problemer især på WPF-fronten med at finde kurser, der var på højt nok niveau og som samtidig blev afholdt i Nordjylland. Det er der hermed rådet bod på!</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/09/2009/nyt-kursuskatalog-ved-transsoft-as.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usability &#8211; the usual pit-falls</title>
		<link>http://goblincave.net/09/2009/usability-the-usual-pit-falls.php</link>
		<comments>http://goblincave.net/09/2009/usability-the-usual-pit-falls.php#comments</comments>
		<pubDate>Sat, 26 Sep 2009 20:48:59 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Usability]]></category>
		<category><![CDATA[English posts]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=337</guid>
		<description><![CDATA[Everyone has seen them &#8211; every developer has fallen in at some point &#8211; the common pit-falls that are usability no-no&#8217;s. But how they are perceived varies. Developers with enough time under their belt will be at least partially blind to them &#8211; for some reason, active development will make you unable to judge usability [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone has seen them &#8211; every developer has fallen in at some point &#8211; the common pit-falls that are usability no-no&#8217;s. But how they are perceived varies. Developers with enough time under their belt will be at least partially blind to them &#8211; for some reason, active development will make you unable to judge usability unless you educate yourself.</p>
<p>This may sound a bit harsh &#8211; but it is actually true. When you know at least part of what is probably going on under the hood &#8211; you take a lot of things for granted. Of course that functionality is in the menu under Tools -> Settings &#8211; that&#8217;s the garbage can for any developer&#8230; but of course you should just right-click, hold control and drag it across the screen waiting two-thirds of a second for Windows to update the UI before moving out of the listbox.</p>
<p>And the things that annoy developers are unlikely to be the things that annoy Joe the Plumber and vice versa. Developers will complain &#8211; &#8220;But I have 47 controls &#8211; and if I don&#8217;t use up three rows in the tool-panel, the user will never see my brilliant functionality and I&#8217;ll spend hours explaining how to reach them&#8221;. </p>
<p>So, what to do? It&#8217;s actually quite simple, start looking at things that you don&#8217;t remember using &#8211; without looking, tell me how you activate the rear-view wind-shield viper? Most cannot. They will still be able to do it, when they sit in the car, but they will be unable to tell you. It is a combination of placement and icons incl. mapping. Cars must meet certain usability demands for drivers not to endanger themselves and everyone else on the road. All critical functions must be doable without taking your eyes of the road.</p>
<p>So, what does the car manufacturers do better than your average software developer? They spend a lot of time and energy on making sure buttons are where people expect them to be, make them of varying size and texture to allow the driver to find them without looking. And they place all the controls you need the most (steering wheel, gear stick, the horn and light-controls) at the most convenient positions. The less-used controls are not hidden away, but placed in secondary positions and less convenient to avoid taking the focus from the critical ones. (And of course, the car stereo designer still has not learned anything &#8211; I count 34 buttons on mine &#8211; 33 of them identical in size, colour and texture with tiny icons with made-up acronyms on them).</p>
<p>And they don&#8217;t start switching the brake-pedal with the accelerator, because it just seemed more aesthetically pleasing! Nor do they start making the car turn right when you turn the steering wheel counter-clockwise. (So, for goodness sake, stop placing the cancel-button to the left of the ok-button) In other words &#8211; they follow conventions even if it might conflict with other goals.</p>
<p>To sum up &#8211; to make better UI-designs &#8211; stop trying to invent the new and better wheel &#8211; and rely on already established conventions and use the hard-earned lessons other people have learned before you. </p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/09/2009/usability-the-usual-pit-falls.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usability &#8211; where to start</title>
		<link>http://goblincave.net/09/2009/usability-where-to-start.php</link>
		<comments>http://goblincave.net/09/2009/usability-where-to-start.php#comments</comments>
		<pubDate>Thu, 17 Sep 2009 05:38:50 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[* Usability]]></category>
		<category><![CDATA[English posts]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=334</guid>
		<description><![CDATA[I recently started re-aligning my preferences when coding. Up until now, I&#8217;ve been focused on learning the technology and reaching a competent level of understanding why the technology works the way it does. Also, I wanted to write better code. I&#8217;m in no way among the most competent in these areas, but it is mostly [...]]]></description>
			<content:encoded><![CDATA[<p>I recently started re-aligning my preferences when coding. Up until now, I&#8217;ve been focused on learning the technology and reaching a competent level of understanding why the technology works the way it does. Also, I wanted to write better code. I&#8217;m in no way among the most competent in these areas, but it is mostly a matter of using my new-found capabilities rather than gaining theoretical knowledge. So, I need new reading-material &#8211; and I started throwing myself at &#8220;<a href="http://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0465067107/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1253164469&#038;sr=1-1">The design of everyday things</a>&#8221; and &#8220;<a href="http://www.amazon.com/Universal-Principles-Design-William-Lidwell/dp/1592530079/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1253164401&#038;sr=1-2">Universal Principles of Design</a>&#8220;.</p>
<p>I&#8217;ve always had a pet-peeve with badly designed software, but being unable to express what was actually wrong with it &#8211; I realized I had no vocabulary in usability. So, I started with these two books that are recognized as must-reads for designers generally. What I learned was not so much how to design beautifully nor how to design in the first place, but rather a vocabulary to express what I already knew and also, some research to back up my understanding of why design is important. These two books are not aimed at software designers in particular but rather the principles behind design in general. As such, many of the principles don&#8217;t really apply to software.</p>
<p>Most developers face a challenge when confronted with the word usability. They all know it exist, but most do not see the problems because having a technical insight makes you blind to the problems non-technical users have with their creations. Concerns are discarded just because the developer a) does not see the problem and b) cannot relate to the underlying cause. </p>
<p>The catch-phrase from my reading has been: &#8220;The user must see the conceptual model to understand the interface&#8221;. For us software developers, this means that if we are unable to convey the conceptual model of what we wish to accomplish in the GUI, the user will most likely fail. The conceptual model is basically &#8220;what happens under the hood&#8221; &#8211; in other words, it is everything the user cannot see. Humans are adaptable beings and jump to conclusions. This is why we have users saying &#8220;the computer freezes everytime I turn on the coffee-machine, so, since I started drinking tea, it has been running fine&#8221;. We (the IT-people) know this simply cannot be the under-lying cause, but the user does not know the technical bits &#8211; he saw to circumstances happen at the same time, and concluded that they must be intertwined. </p>
<p>So, what to do? Should we start educating users to be IT-minded &#8211; maybe throw in a MCP to make the users understand why stuff works the way it works? It would certainly make Microsoft happy&#8230; but no, it is not a viable solution. Instead, we need to focus on making better GUI. We need to make the conceptual model clearer and simpler. When the application fails, the error-message should not read: &#8220;Exception occured in major module hj_uuullk. Fatal failure reading harddrive kl_llij at position 0xE3F2E5&#8243;. It should read: &#8220;There was a problem with opening your document &#8211; you did nothing wrong. Technical staff has been informed about the problem and will fix it as soon as possible. If you want to follow progress: &gt;link&lt;. Please, do not attempt to open this particular document before technical staff gives the go-ahead. Other documents should work fine. If you need the document before, contact jim@farkvad.com.&#8221;. The user gains no insight from the first error message. Basically, he has no way of knowing if he did something wrong or it was a software mishap. All he knows that something went wrong, but he is left thinking&#8230; &#8220;Maybe my coffee cup was too close to the screen&#8230; hmm&#8230; could be that it was due to reading an e-mail at the same time&#8230;&#8221; The chances of him reaching the correct conclusion is slim-to-none.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/09/2009/usability-where-to-start.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Small update to layout</title>
		<link>http://goblincave.net/09/2009/small-update-to-layout.php</link>
		<comments>http://goblincave.net/09/2009/small-update-to-layout.php#comments</comments>
		<pubDate>Tue, 15 Sep 2009 10:12:13 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Misc.]]></category>

		<guid isPermaLink="false">http://goblincave.net/09/2009/small-update-to-layout.php</guid>
		<description><![CDATA[The wife has kindly updated my wordpress installation and restored my old theme for your viewing pleasure.
I will return shortly with a series of posts around usability and general design concerns.
]]></description>
			<content:encoded><![CDATA[<p>The wife has kindly updated my wordpress installation and restored my old theme for your viewing pleasure.</p>
<p>I will return shortly with a series of posts around usability and general design concerns.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/09/2009/small-update-to-layout.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Random NHibernate gotchas</title>
		<link>http://goblincave.net/09/2009/random-nhibernate-gotchas.php</link>
		<comments>http://goblincave.net/09/2009/random-nhibernate-gotchas.php#comments</comments>
		<pubDate>Sun, 06 Sep 2009 20:13:26 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[English posts]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=330</guid>
		<description><![CDATA[Nhibernate is extremely flexible and powerfull. Some details will have you tearing your hair out in frustration, though &#8211; at least untill you get that&#8230; &#8216;Ahaaah&#8217; experience. Below, I&#8217;ll try to give you a few of the ones, that had me scratching my head:
The whole collection-issue that I mentioned in my last post can be [...]]]></description>
			<content:encoded><![CDATA[<p>Nhibernate is extremely flexible and powerfull. Some details will have you tearing your hair out in frustration, though &#8211; at least untill you get that&#8230; &#8216;Ahaaah&#8217; experience. Below, I&#8217;ll try to give you a few of the ones, that had me scratching my head:</p>
<p>The whole collection-issue that I mentioned in my last post can be frustrating if you missed the point with NHibernate using reference equality. In most situations you will not notice that one untill it is too late as it will be non-noticable in small datasets (if you are not paying attention to the SQL output, of course). </p>
<p>Another thing about equality &#8211; often, you will have entities publish an ID-field mapped to an Identity-column in the DB (for look-up purposes) and have it backed by a field. If you decide to use the ID for equality-purposes and have the property mapped with access: field be aware that any proxy from that persistent class will have different values for the field versus the property &#8211; the field will always be 0! So, always use the property in Equals(). Also, when considering equality in general, be sure not to use any lazy-loading entities as they will be loaded whenever equality has to be determined (WPF does a lot of that!). A rule of thumb is to use all properties for a value-type class (as per the DDD-terms) and only the ID for persistent aggregates (especially when they will be used as attached aggregates). The reason for this is that lazy-loaded entities do not have to be </p>
<p>evaluated (ie. loaded) to determine equality. I used to be a DBA in former employments and have spent a lot of time normalizing tables and I grew accustomed to mapping each fine-grained object to it&#8217;s own table &#8211; this is performance-killing! Consider the traditional simple Customer-class consisting of an accountnumber, a physical address, a billing address and billing information. If you map this to three-four tables (one for the customer, one or two for the addresses, one for the billing information) &#8211; NHibernate will unleash a LEFT OUTER JOIN hell of magnitudes (or a series of SELECT&#8217;s that will have your DB spinning out of control if you have yet to mark it to use sub-selects or outer joins)&#8230; Now consider when you start using the customer in other objects&#8230; The lesson here is that your typical one-to-one relationships with objects that will most likely not be null should be mapped as components and thus for the DB&#8217;s sake exist in the same table. Only consider a seperate table, if the associated class will often be null, or rarely used (lazy-load).</p>
<p>Inheritance and generics is another issue &#8211; just because NHibernate supports both, doesn&#8217;t mean you have to use it! It is most often not a perfect match and you will be twisting NHibernate into a knot to conform to your domain or vice versa. Also, remember that if you have an associated aggregate that is mapped with the base class &#8211; the resulting lazy-loaded proxy will always be the same type as the base class &#8211; never one of the derivatives. (See <a href="http://ayende.com/Blog/archive/2009/09/03/answer-the-lazy-loaded-inheritance-many-to-one-association-orm.aspx">Ayende&#8217;s blog</a> for further details as to why). Use it sparringly and be aware that mapping files do not support open generics &#8211; so, if your inheritance tree consists of a generic superclass &#8211; you cannot use it as the base class in the mapping unless it is a closed generics (and then it is a really advanced case &#8211; and you should really try for a simpler solution&#8230;). Generally speaking &#8211; using generics and inheritance in your mapping files will most often lead you into a world of hurt when the dependencies evolve and a key class in the inheritance chain will suddenly no longer conform to the dependencies. It is bad enough to have that happen to your domain &#8211; if you add data-migration head-aches to that mix&#8230; you&#8217;ll end up being wary of making needed changes to your domain.</p>
<p>All this said &#8211; if you stay clear of the pitfalls, NHibernate is a very nice fit for most agile TDD/BDD/DDD projects with databases as the early iterations will benefit from the easy DB-schema generation and the reduced DB-work. Later on, you&#8217;ll have to somehow solve the data-migration issues for projects in production &#8211; most customers will not take it lightly when you drop their databases for the new version to take effect&#8230; I have yet to find a silver-bullet there (there are products out there, but I have yet to need one badly enough to actually test them). My experience is that Active Record (which uses NHibernate under the covers) is really good for the early iterations &#8211; and then shift to full-blown NHibernate when you start running into the advanced stuff. DBA&#8217;s may seem like they get the short end of the stick and be out of a job, but it is actually a win-win situation &#8211; they get to do the fun performance-tuning part of their job in favour of the error-prone database generation part.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/09/2009/random-nhibernate-gotchas.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MVVM &#8211; a story of pain, misery and finally relief</title>
		<link>http://goblincave.net/08/2009/mvvm-a-story-of-pain-misery-and-finally-relief.php</link>
		<comments>http://goblincave.net/08/2009/mvvm-a-story-of-pain-misery-and-finally-relief.php#comments</comments>
		<pubDate>Wed, 12 Aug 2009 19:30:48 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[English posts]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=326</guid>
		<description><![CDATA[To be brutally honest, when learning about coding patterns &#8211; there were a few patterns that I just found to be &#8230; cumbersome or just plain without relevance (thinking they were the remnants of C++ times long gone&#8230;). The Model-View ViewModel (MVVM) and Monostate, to name a few seemed like things you&#8217;d never use. Monostate&#8230; [...]]]></description>
			<content:encoded><![CDATA[<p>To be brutally honest, when learning about coding patterns &#8211; there were a few patterns that I just found to be &#8230; cumbersome or just plain without relevance (thinking they were the remnants of C++ times long gone&#8230;). The Model-View ViewModel (MVVM) and Monostate, to name a few seemed like things you&#8217;d never use. Monostate&#8230; why in the name of all that is good do we need monostate when we have Singleton? Well, I got wiser&#8230;now, I tend to never use singletons (aside from IoC-enforced) and always use monostates for my own classes when shared state is needed. Not having to deal with locking-and threading issues, lazy versus eager loading just to name a few of the problems with singletons is well worth the less time spent implementing them (wait, isn&#8217;t that actually a good thing when you aren&#8217;t paid by the hour&#8230;).</p>
<p>But MVVM &#8211; for the life of me, I just couldn&#8217;t see the benefits &#8211; handling the mismatch between the string-typed world of UI and the many-typed world of the domain classes were beautifully handled with shared ValueConverters (thanks, WPF) and nice services. So, I was left thinking &#8211; I&#8217;ll end up duplicating logic, duplicating all interfaces and all I&#8217;ve got to show for it was no implementation of INotifyPropertyChanged in my domain-classes? No way, Jose! </p>
<p>Let&#8217;s just say &#8211; things went well for about a 8-9 months period &#8211; and then pain came creeping. Performance was dwindling faster than you can say *cough*poorly-matched domain-model*cough* and I simply didn&#8217;t understand why. Everything was coded both to satisfy a rich end-user experience, caches were used to share common DB-queries and patterns were used to relieve coding smells when they emerged, but still performance kept dropping&#8230; And some weird persistence bugs kept re-emerging (&#8220;Why is this entity suddenly detached and this one screaming it has a transient one&#8230; when they should be one and the same?&#8221;).</p>
<p>Then it dawned on me (reading &#8220;Nhibernate in action&#8221;) &#8211; everything keeps ending up dirty whether I&#8217;ve touched it or not after retrieving it from the database making for endless useless round-trips when there should have been none. Investigating the matter further, I came to a clue: Every-time an entity had a collection of custom type, it wasn&#8217;t dirty when retrieved, but as soon as it was shown in the UI, it became dirty. WTH!? I started investigating in all the wrong places, WPF Binding bugs might be it, doing an extra setter somewhere &#8211; maybe the NHibernate Interceptor taking care of audit &#8211; and I just kept drawing blanks.</p>
<p>Then (going back to reading NHibernate in Action) it finally dawned on me&#8230; collections => dirty when databinding to it&#8230; I found code-snippets like this all-over our domain-model (truth be told, I made them myself&#8230; They did not appear by magic):</p>
<blockquote><p>private IList&lt;ISomeClass&gt; _list;<br />
public ISomeClassCollection List<br />
{</p>
<blockquote><p>if(!(_list is ISomeClassCollection))<br />
{</p>
<blockquote><p>_list = new SomeClassCollection(_list);<br />
OnPropetyChanged(&#8220;List&#8221;);</p></blockquote>
<p>}<br />
return _list as ISomeClassCollection;</p></blockquote>
<p>}</p></blockquote>
<p>The reason for the ISomeClassCollection was a work-around to better support INotifyCollectionChanged as ISomeClassCollection would act as a wrapper around the original list and notify UI of changes to the collection. Can anyone spot the problem? NHibernate identifies dirty-state in collections by ReferenceEquality on the collection and equals on the content of the collection&#8230; So, the first time, UI would ask for the current collection to show it in a ListBox or a DataGrid, it would mark the entity dirty because the retrieved collection was no longer&#8230; Collected as common garbage, you might say&#8230;</p>
<p>So, back to the drawing-board for that one. Before turning to NHibernate in Action I had just plowed through HeadFirst Patterns and Design Patterns (Amazon them, I couldn&#8217;t be bothered to find a link) and I came to the conclusion why MVVM would be a good idea here&#8230; Not only would entities stop being marked dirty all the time without cause, but I could support 1 level undo, simply by copying the state of the entity when read, and only setting it when the conversation was over and the user had agreed to the changes reducing the number of round-trips even further.</p>
<p>Later, when implementing it, I also discovered a nice side-effect, I hadn&#8217;t considered. The domain-classes are now very compact and it is much easier to enforce how to use the domain. Since collections used for full-fledged databinding needs to both implement IList and INotifyCollectionChanged, the collections in the domain tended to be full of features, that weren&#8217;t used (and shouldn&#8217;t be used, since they lacked the logic of the proper methods). </p>
<p>So, now collections are usually IEnumerable and the ratio of value-type compared to entity-types (in the sense of DDD&#8217;s notion of value-type and entity) has reached an all-time record of 65%! Having a value-type with only getters and a few methods and then letting the ViewModel have the setters and all the handling of the user&#8230; it just makes for real simplicity in the domain. Yes, the ViewModel can end up cluttered with all kinds of weird tricks to satisfy the demanding master of UI-updates, but that&#8217;s what it&#8217;s there for!</p>
<p>I still have a few things to iron out (mainly with duplicate logic to support notifications to the UI without touching the domain entity when services and dependant objects are in play), but just the first round of refactorings has increased my satisfaction with the domain-model ten-fold. It turned from being just wrapping the domain objects to a complete refactoring of the interfaces of the domain and complete re-working of the database-schema, but it is well worth it in my oppinion. For certain it would have been much more critical to do it after it had gone to production (the mind boggles at the amount of data-conversions to be done&#8230;). </p>
<p>The lesson? I, Magnus, do hereby solemnly swear, never to let UI-concerns enter my domain model again! I now understand it will be my doom and much pain will be caused&#8230; mainly to me. (And I&#8217;ll swear again, the next time it happens!)</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/08/2009/mvvm-a-story-of-pain-misery-and-finally-relief.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My current favorite libraries</title>
		<link>http://goblincave.net/08/2009/my-current-favorite-libraries.php</link>
		<comments>http://goblincave.net/08/2009/my-current-favorite-libraries.php#comments</comments>
		<pubDate>Wed, 12 Aug 2009 18:24:32 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[English posts]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Prism]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=316</guid>
		<description><![CDATA[I use a lot of frameworks and 3rd party libraries &#8211; but I am getting increasingly picky which gets to stay for more than a brief acquaintance. Below, I&#8217;ll describe which and why I use them:
Testing

NUnit &#8211; A classic. Really, I could have used MS&#8217; own test-framework, but I just don&#8217;t trust it yet. I [...]]]></description>
			<content:encoded><![CDATA[<p>I use a lot of frameworks and 3rd party libraries &#8211; but I am getting increasingly picky which gets to stay for more than a brief acquaintance. Below, I&#8217;ll describe which and why I use them:</p>
<h3>Testing</h3>
<ul>
<li>NUnit &#8211; A classic. Really, I could have used MS&#8217; own test-framework, but I just don&#8217;t trust it yet. I don&#8217;t use anywhere near 1% of the framework (the attributes, Assert&#8230; and that&#8217;s pretty much it), since my projects are simply not that advanced&#8230; well, they are in terms of WPF, but NUnit has no inherit support for WPF-testing (a.k.a. VisualTree-walking).</li>
<li>Rhino Mocks v. 3.5 &#8211; also a classic. I&#8217;m a huge fan of the new AAA style although I tend to apply it with StoryQ&#8217;s approach. Also, the new .AssertWasCalled combined with lambda expressions makes for really nicely condensed code. I have yet to find a better mocking framework.</li>
<li>StoryQ &#8211; the new-comer. Basically StoryQ is a way for Acceptance-tests to make their way into your test-code. It plays well with NUnit and is a relatively light-weight API, that really lends well to minimizing the number of small interface-driving spec-tests. I was skeptical at first, but now, I&#8217;m convinced that it makes for better and more condensed code and also, to keep that red thread throughout my test-procedures making it far more readable.</li>
</ul>
<h3>Persistence</h3>
<ul>
<li>NHibernate &#8211; also a classic. I started out using NHibernate when I started using ORM&#8217;s. I have yet to find a fatal flaw in the design. Usually it has been my ignorance that lead to the problems introduced. I&#8217;m currently reading NHibernate In Action (which has lead to a few realizations &#8211; more info on that later) and my usage is still far from ideal due to limited understanding of the architecture.</li>
</ul>
<h3>WPF</h3>
<ul>
<li>WPF Toolkit &#8211; I use this sparringly due to a number of irritating errors in the implementations. I primarily use the DataGrid and the DatePicker. Sadly, it shines through that it is a glorified CTP-version out there.</li>
<li>Prism &#8211; my favorite among the frameworks emerging for WPF. Very light-weight framework for supporting pluggable architectures. Some problems, of course, but 3-4 of the ideas are usefull out of the box and the rest only need minor tweaking.</li>
</ul>
<h3>IoC</h3>
<ul>
<li>Windsor &#8211; most thoroughly tested. Feature-list is far beyond my skills as I use IoC mainly for Service Locating problems. I tend to favour fluent configuration and a static service locator for the small hobby&#8217;ish applications.</li>
<li>Unity &#8211; MS&#8217; try at IoC container. Have yet to find any bugs and is the default container in Prism &#8211; so usually end up using Unity while the project is in the early stages. Usually shift to Windsor when the going gets tough and I need run-time evaluation of services. Has the most annoying exception-handling of the IoC containers I&#8217;ve tried. Wrapping the exception every GD time it is rethrown&#8230; that just makes for dull debugging in VS.</li>
</ul>
<p>I use other libraries, but so far they are easy come &#8211; easy go. They usually don&#8217;t end up staying. Going to attend a meeting comparing NHibernate and Entity Framework &#8211; very much looking forward to seeing the giraffe. Otherwise, my main focus will probably shift from Prism (pretty much exploiting every corner of it at the moment &#8211; so nothing much left to discover) towards a new series of Usability challenges. I will begin reading up on it and probably attend a few courses over the next 6-9 months. Very much looking forward to that. And I&#8217;ll try to keep you updated with my findings.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/08/2009/my-current-favorite-libraries.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GoblinCave på vej på de evige bitmarker (EDIT: aflyst/canceled)</title>
		<link>http://goblincave.net/03/2009/goblincave-pa-vej-pa-de-evige-bitmarker.php</link>
		<comments>http://goblincave.net/03/2009/goblincave-pa-vej-pa-de-evige-bitmarker.php#comments</comments>
		<pubDate>Tue, 10 Mar 2009 13:22:19 +0000</pubDate>
		<dc:creator>GoblinHero</dc:creator>
				<category><![CDATA[* Coding]]></category>
		<category><![CDATA[* Diverse]]></category>

		<guid isPermaLink="false">http://goblincave.net/?p=311</guid>
		<description><![CDATA[In danish:
Jeg har besluttet at begrave GoblinCave som blog. EconomyDeluxe ligger stadig til fri download, men der vil ikke komme opdateringer foreløbig. Bloggen vil ligge online indtil næste gang domænet skal fornys. Grundene er flere men i sidste ende ligegyldige for dig som læser. Jeg kan nås på duckhero@gmail.com.
På engelsk:
I&#8217;ve decided to send GoblinCave the [...]]]></description>
			<content:encoded><![CDATA[<p>In danish:<br />
Jeg har besluttet at begrave GoblinCave som blog. EconomyDeluxe ligger stadig til fri download, men der vil ikke komme opdateringer foreløbig. Bloggen vil ligge online indtil næste gang domænet skal fornys. Grundene er flere men i sidste ende ligegyldige for dig som læser. Jeg kan nås på duckhero@gmail.com.</p>
<p>På engelsk:<br />
I&#8217;ve decided to send GoblinCave the way of the lost bit. EconomyDeluxe will still be available for download, but updates will be scarce. The blog will continue to be online come next registration-date. The reasons are several but ultimately of no consequence for you as a reader. I can be reached at duckhero@gmail.com.</p>
<p>So long and thanks for all the fish.</p>
<p>UPDATE: Jeg har valgt at genoptage blogningen &#8211; jeg har fundet et emne, som det er værd at beskæftige mig lidt nærmere med. Mere info senere.</p>
<p>UPDATE: I&#8217;ve chosen to start blogging again &#8211; I&#8217;ve found a subject worth investigating further. More info to follow.</p>
]]></content:encoded>
			<wfw:commentRss>http://goblincave.net/03/2009/goblincave-pa-vej-pa-de-evige-bitmarker.php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
