Thursday, July 31, 2008

Don't you hate DEMOs?

You've heard about jolly good presentation, which you missed, to your deepest regret. But luckily a downloadable version is available, so you go there, get it, run and... Cripes! The page, promising the "self-explanatory code which will make it all clear for you" is followed by an empty one with a big fat "DEMO" and nothing else.

90% of Microsoft presentation seems to be like that - it is like there is a corporate standard enforced. Presenter could spend two/thirds of the the time, presenting the code, but still do not include code snippets in the presentation itself or at least accompany online version with the source code.

Please, don't do that.

P.S. Newly adopted screencasts suffer from the same problem, but there is joint fault of both presenter and operator. It is even more annoying to stare at the presenter while he is pointing out how "this class is neatly mapped with this tricky instance". Please, don't do that too.

Wednesday, July 30, 2008

One more time about a "Triumph of the (group) will"

What is undoubtedly good about ThoughtWorks - is that thoughts are definitely at work there.

Patrick Kua just had a post about a group thinking vs. thinking of groups. He has a lovely picture:

That was an easy one - Cathy Sierra had a great post back in 2007 about "Dumbness of crowds":

So superiority of the collective thinking is not the law of nature. The dullness of averaging is just one side of the problem, though. It is not just a committee is incapable of producing the next Google - the unified thinking can make a team miss the point.

I would argue for the "Collective Intelligence" vs. "Wisdom of Crowds" - the way of harvesting individual contributions in order to produce something what customer actually wanted:

CollectiveThinking

P.S. And I just couldn't help it: In a team you reach the goal. In Soviet Russia goal reaches you :)

P.P.S. And of course Patrick's intention wasn't to advocate the clone thinking and he points this out in the comment. It's just the original post was allowing too much room for misinterpretation. You can have an opinion, but in Soviet Russia opinion has you!

Tuesday, July 29, 2008

In Soviet Russia...

In Extreme Programming, you continually test your code. In Waterfall, your code continually tests you.

© Tim Lesher & Yakov Smirnoff

Friday, July 25, 2008

Lazy TryParse

This is my second attempt on the TryParse with the C# 3.0 Extension Methods.

I just noticed that I am copy-pasting a lot of the Integer and Boolean parsing in my current project. Maybe I just don't know any better but I ended up using TryParse this way:

int intParsed;
value= int.TryParse(reader["Value"].ToString(), out intParsed) ? intParsed : 0;

or a little bit simpler:

int intParsed= int.TryParse(reader["Value"].ToString(), out intParsed) ? intParsed : 0;

I will appreciate if somebody would show me simpler solution but so far it is as it is. I am stuck with .NET 2.0 for now, but would it be 3.5, I'd put together an extension method. It started as a pretty simple extension of a Int32 type, but quickly evolved to the more generic solution, which uses some kind of Duck Typing guessing:

public static class TryParseExtender
{
public static T LazyTryParse<T>(this T instance, object input)
{
Type type = typeof (T);
MemberInfo[] members = type.FindMembers(
MemberTypes.Method,
BindingFlags.Public | BindingFlags.Static,
(objMemberInfo, objSearch) => objMemberInfo.Name.Equals(objSearch.ToString()),
"TryParse"
);
foreach (MemberInfo info in members)
{
try
{
bool boolResult;
object[] paramArray=new[]{input, instance};
object objResult = ((MethodInfo) info).Invoke(instance, paramArray);
if (bool.TryParse(objResult.ToString(), out boolResult)) return (T)paramArray[1];
break;
}
catch {}
}
throw new ApplicationException(type+ " doesn't support TryParse");
}
}
It is not the prettiest code but does the job. Return statement assumes that types which expose TryParse are able to cast the Object type to themselves. Unfortunately the C# Extension Methods are not that powerful as the Ruby's Monkey Patching and I am already far enough into the Ruby to recognize what power (and elegance) I am missing.

Here is the test harness for the extension, which also shows the usage patterns (generic inference makes code look simpler):

[TestFixture]
public class TryParseExtenderTest
{
[Test]
public void TestIntParsing()
{
string input = "230";
int result = 0;
result = result.LazyTryParse(input);
Assert.AreEqual(230, result);
}

[Test, ExpectedException(typeof(ApplicationException),
ExpectedMessage = "System.String doesn't support TryParse")]
public void TestStringParsing()
{
int input = 230;
string result = "";
result = result.LazyTryParse(input);

Assert.AreEqual("230", result);
}

[Test]
public void TestBooleanParsing()
{
string input = "true";
bool result = true;
result = result.LazyTryParse(input);
Assert.AreEqual(true, result);
}

[Test]
public void TestDateTimeParsing()
{
string input = new DateTime(2008, 12, 1).ToString();
DateTime result = DateTime.Now;
result = result.LazyTryParse(input);
Assert.AreEqual(new DateTime(2008, 12, 1), result);
}
}

Monday, July 21, 2008

Prepare for the future

It's coming.

Warning: graphic images, weird sense of humor. Not suitable for all audiences. Actually - for anybody.

Clean, Lola, clean!

The CCleaner tool is the best friend of a contractor when it is time to leave.
Also it is useful on a daily basis. I just figured out (after a year of procrastinating) what needs to be tweaked in the settings in order to avoid the annoying disappearance of the Window Explorer settings. You know, when the sorting, appearance, etc. used to be set as you like - and suddenly it's all gone?

image

If you like it squeaky clean - go ahead, check all boxes, but leave the Window Size/Location Cache out.

Awesome, awesome tool (a rightful nominee of the SH2007UDPUTL for Windows list). I've just run it after a three day break and it has found a 68 Mb of trash.

Sunday, July 20, 2008

Worktime music: Florent Pagny

Ma liberté de penser

Caruso

Saturday, July 19, 2008

Shark!

The advocacy group The Shark Project holds a Photo Award. Here is the teaser:

I noticed that the workflow is missing some important steps (especially considering the subject) and I couldn't resist to fill in the gap:

But reality is not that funny. Those fierce insatiable predators are unstoppable and claim increasingly more lives every year. I am talking about humans. The shark elimination rate is astonishing. It is hard to believe the statistics but apparently from 38 to 200 million(!) sharks are being killed annually. These numbers are beyond any comprehension: it is like losing the entire US population in a single year, Canada - in two months or having World War II occur every quarter.

The fear and loathing are understandable - we are challenged outside of our natural habitat. Unless you are a Navy Seal, it is not really fair game. A bear is much more dangerous but we more or less understand our own land creatures, so we can put up with the necessity to stay away from their ground. If we ended up in the Amazonian jungle or in the Kenyan savannah in their better days, our chances of survival would be slimmer than us going into shark infested waters, but who wants to eliminate rainforest? We are so easily influenced by the media, that despite the fact that sharks are an important part of the ecosystem, the though of protecting them is somehow unsettling. Saving bears is OK, but not sharks? What do we think of the guy who got injured after approaching a lion pride or she-bear with a cub? A dumb schmuck! But we would call that a scuba diver attacked by a shark, he is always a victim, because most of the time sharks dare to interrupt our holiest activity - the entertainment. If sharks are a part of the thrill, one should be ready for what comes of it.

According to the Australian Museum (Australia could win a "shark country" contest with her eyes closed) the human death toll from 1980-1990 was based on the following reasons:

Activity Total Deaths Average/Year
Crocodile Attacks 8 *** 0.7
Shark Attacks 11 ** 1
Lightning Strikes 19 * 1.7
Bee Stings 20 * 1.8
Scuba Diving Accidents 88 **** 8
Drowning/Submersions 3367 * 306
Motor Vehicle Accidents 32772 * 2979


* from the Australian Bureau of Statistics, Canberra
** from John West, Shark Attack File, Taronga Zoo, Sydney
*** from Dr Graham Webb, Darwin
****from Dr Doug Walker, Operation Sticky Beak, Sydney

Following this logic, we had hunt down Ford executives! Compared to the 60 attacks per year (with less than 10 fatal), sharks are taking casualties of 3 500 000 to 1.

Nature is a smart beast - this improbable survival despite the fierce genocide shows that life, uh... finds a way. We may be surprised one day, and not pleasantly.

Friday, July 18, 2008

Class Field Inheritance Pattern

Off topic: this is one difficult book to read. Not that it's written in a tangled language (try reading this). It is just that the understanding of content will come with the practice, otherwise the knowledge will evaporate momentarily. But how often does one make architectural decision on the enterprise level? And how often does one decide to use a new set of patterns? So the actual "reading" will take quite some time and I have been reading it on and off for four years already. Yes, I am slow reader.

The only downside is examples. As a sport ignoramus, I have no idea why a Footballer would inherit from a Player but a Bowler should inherit from a Cricketer. So examples are not from my real life and confuse me more than actually explain anything. Instead of understanding relations from entities I have to go in the opposite direction. Bugger.

Now back to the title: "what object-relational pattern would be more lightweight than the Class Table Inheritance and less normalization-refuting than the Single Table Inheritance?"

Meet the Class Field Inheritance pattern.

The idea is that the base class shares a single table with children and the child-specific fields are serialized into a single field. You would use it if:

1. Base class is equal in rights with children classes and has to be instantiated.
2. Child classes have very few extra properties.
3. There is no requirement for an extensive analysis of the child-specific fields.
4. There is no requirement for a raw child-specific data to be available for a database objects (e.g. reporting tools, functions or procedures).

All these requirements are not 100% solid. If the performance is negotiable, concrete child properties can be lazily deserialized, thus enabling a business layer analysis. The raw data from the filed can be "unfolded" using user functions, providing concrete tables to join on them if required.

Pattern is fast in the implementation - one stored procedure will serve it all, and the logical flow is very clear. One can go nuts with Strategies, Abstract Factories and Dependency Injections. Now tell me that it is not a beauty!

Thursday, July 17, 2008

Attempting on Domain Driven Design. Again.

 

I think I keep making the same mistake when I try to read the fundamental Eric Evans work. This time I was advised to skip the first four chapters and hopefully, this will prevent me from dozing off again.

 

Also, I plan to sneak on DDD with this podcast and a squeezed version of the original DDD bible (106 pages versus 500). It is available for free (in a PDF format) from the InfoQ (run and subscribe to their beautiful personalized feed).

Should you fear or embrace dynamic languages?

Yesterday John Lam (the brain behind a Microsoft IronRuby effort) delivered an excellent (as usual) presentation for a Metro Toronto .NET User Group audience - "IronRuby: Should you fear or embrace dynamic languages?".

John is an exceptionally inspiring speaker. If you ever have a chance to attend his performance presentation - drop all your appointments and go! Don't worry even if the presentation is about a Roman cubic art - he is notorious for deviating from the topic and you will hear about many other things. What he will most likely to achieve is make you aspire to be better at whatever you do.

Ruby perspectives look good. So do the .NET's. By the end of the presentation both questions from the topic are answered for me. Those answers most likely are what John wanted to communicate but the reasons behind them are [possibly|slightly] different: No - you shouldn't fear the dynamic languages as a concept and No - an average C# Joe should not be afraid of Ruby sneaking up on him and taking his job away. C# 3.0 matches a Ruby's syntactic sugar in a lot of cases and there is (hopefully) more to come. And Yes - you must try Ruby at the least. The presentation has finally convinced me that doing so will make me a better developer. A better C# developer.

So go ahead and learn Ruby. By the time you are more or less done, the IronRuby will ship (spring 2009 was mentioned) and you will be able to make an informed decision - get hooked on this new cool drug or stick with the good old one :)

Saturday, July 12, 2008

Sorting a grid with ObjectDataSource

ObjectDataSource is a lazy way to power a grid control (let's say a GridView for example). Surprisingly, the Microsoft team didn't give good thought to any Data Source controls except SqlDataSource.

The "It just works" approach just doesn't work with ObjectDataSource sorting. I like using generic lists a lot but ObjectDataSource can not sort them: "The data source 'mySource' does not support sorting with IEnumerable data. Automatic sorting is only supported with DataView, DataTable, and DataSet". If they were aware of this flaw - why didn't they just fix it and provide nice sorting support?

Thus the hack is up to us.

The first step would be supplying the Comparer for our custom class. And if you're rightfully lazy to write a full set of Comparers for each property, then reflection is to the rescue:

public class ToyComparer : IComparer<Toy>
{
private readonly string _property;

public ToyComparer (string propertyName)
{
_property = propertyName;
}

public int Compare(Toy x, Toy y)
{
PropertyInfo property = x.GetType().GetProperty(_property);
if (property == null)
throw new ApplicationException("Invalid property " +_property);
return Comparer.DefaultInvariant.Compare
(property.GetValue(x, null), property.GetValue(y, null));
}
}

The class's List Select Method uses Comparer to sort the output list:


private static List<Toy> GetToys(string propertyName)
{
//list creation is omitted ...
if (!string.IsNullOrEmpty(propertyName))
{
list.Sort(new ToyComparer(propertyName,order));
}
return list;
}

The second step is to add a Select parameter to the ObjectDataSource:


<asp:ObjectDataSource ID="mySource" SelectMethod="GetToys" TypeName="Toy"...>
<SelectParameters>
<asp:Parameter Name="propertyName" Direction="Input" Type="String"/>
</SelectParameters>
</asp:ObjectDataSource>

And last but not the least - we need to set the property of the ObjectDataSource and cancel the grid Sorting event to prevent the exception:


protected void gridMaster_Sorting(object sender, GridViewSortEventArgs e)
{
mySource.SelectParameters["propertyName"].DefaultValue = e.SortExpression;
e.Cancel = true;
}

If necessary we can pass the sorting order the same way.

Friday, July 04, 2008

Subversion 1.5 + TortoiseSVN 1.5 + VisualSVN 1.5

Subversion 1.5 is released, with the TortoiseSVN 1.5 following.

Make sure that you've read the release notes carefully and if you're a happy user of VisualSVN - upgrade it to the version 1.5 as well.

Introverted programming: Office Kung Fu - art of The Crouching Master

It is nice to work for a good company. It is enviable to be respected by your colleagues and respect them in return and looking forward to the next workday. A fat paycheck would top this off and make it your dream job.

But beware the Office Kung Fu masters. It will take just one to contaminate a healthy collective. As soon as you detect the following main stances of Office Kung Fu, it is time to master them yourself. When the Big S hits the fan, your survival may depend on these very moves: Deny, Blame and Take Credit.It wasn't my fault but I have a pretty good idea...

Deny - the main defence stance. Distance yourself from any failure, even potential one, which is not (and especially if it is) your fault.
A simple "it's not me" defence is too low-power. You may need to practice higher techniques: phrase "I don't think this is OUR group" will likely recruit others to fight on your side (The Summoning Block). Master the swift transition to the attack, do not give your opponent any time to regroup.

Figure 1: Master blocks the accusation and demonstrates readiness to put blame in return.

 

I have four reasons why these three individuals should be held responsible...Blame is a crashing attacking blow. Be the first to point fingers. Don't hesitate even if the accused is another Office Kung Fu Master - he/she has to first repel your thrust and his/her responce can be easily depicted as a personal attack on you, the very person who cares about the company so much. The Leech Spree is an example of an indirect attack, which can be executed by a phrase like "Somebody changed this file". This will ignite an avalanche of blame. Be careful when blaming groups - the other Master may use the Summoning Block against you.
Figure 2: Master prepares to attack three people at once and his blame is supported by four sound arguments - very powerful Blame By Authority attack.

 

Take credit - powerful shift-of-power move. Don't cut others any slack. They will rob you of your (or their own) success behind your back, so hurry up and claim it first. Successfully applied, this attack will strengthen your position while weakening the opponent. 
We fixed that build!I hate to brag, but...Precede blaming attack by taking credit first, thus multiplying the destructive effect (The Tsunami Swoosh). On the contrary, you can emphasize your value to the organization by putting the blame first and taking credit immediately after (The Slapping Blossom).

While novices can use a highly energetic version (Fig.3), a true master prefers the carefully calculated move (Fig.4) which is likely to bring a lasting recognition (The Humble Ploy). 

 

 

The highest art of Office Kung Fu is to combine all these techniques within one sweeping motion: "It is not me, it was Nick's fault but I successfully fixed the problem.".

Deny, blame and take credit - and you'll never go home without a promotion.

Thursday, July 03, 2008

Programming geniuses and death by risk aversion

When you read about architecture astronautics and programming geniuses it seems like a good idea to keep an eye on creativity outbursts. There is some popular medicine out there like KISS and YAGNI which can help you cope with that insane yearning for Yet Another Framework.

But as usual the coin has two sides: you still need to empower your users with innovations. Setting computer dreamers free will result in stagnation as their heavy all-inclusive solutions are difficult to maintain and difficult to advance. The more effort is put into the particular architecture, the more people are hesitant to take the risk of making radical changes or let it go altogether, so eventually the solution becomes more obstacle than enabler.

If there is a ready recipe to mix evolution and revolution successfully it most likely is heavily guarded by the corporation which got filthy rich implementing it.

Dependency injection and composition with extension methods

Muddling through the C# 3.0 updates, a colleague and I (inheritance junkies we are) came upon an interesting observation. We departed from the normal base class MyClass:

public class MyCLass
{
public void Update()
{
MyProperty="new value";
DoSomething(this);
}
}


Then we extended the class collection with an extension method (this nice code is shamelessly stolen from the Umbrella library):



public static ICollection ForEach<T>(this ICollection items, Action<T> action)
{
if (items != null)
{
foreach (T item in items)
{
action(item);
}
}
return items;
}


Intended inheritance-driven usage of this method was something like this:


var list = new List<MyCLass>();
list.ForEach(a => a.Update());


Technically there were not much sense in implementing an extension method to use it this way. So we proceeded forward and took the Update method content out of the class and injected it through the extension method:

list.ForEach
(
a =>
a.MyProperty="new value";
DoSomething(a);
)



Now we do not really need instance Update method anymore and can defer the implementation until we will be really using it.


Of course, the above implementation has significant limitations, especially if it concerns private or protected members. Also this code is not exactly DRY-friendly. From another point of view, the dependency injection pattern contradicts the concept of the "black box" to some point.


I wouldn't repeat that "LINQ is cool" but adopting this approach could bring some interesting results, what do you think?

Wednesday, July 02, 2008

Little Subversion trick to improve VisualSVN

VisualSVN is a great product. It is stable, intuitive and if you know TortoiseSVN - you pretty much know it all. Until (relatively) recently, the Ankh was practically the only Visual Studio plug-in for the Subversion. Unfortunately, it suffered from performance and reliability problems and lost a lot of trust. They claim that problems are solved, but I personally would need something very convincing to try it again. Like a direct order from management.

Unfortunately the VisualSVN is not resolving the old problem with multiple working copies (you know - when you have a framework and share it between numerous solutions). For some reason neither a Subversion nor a Team System approve of this very DRY approach. As a result the Solution Explorer in the Visual Studio doesn't track the changes in the project which resides outside the solution's working folder. Not a big deal if the framework is stable but it becomes pretty annoying if some work is still being done.

To overcome this problem in the Team System you had to sacrifice a black lamb on the intersection of six roads at a full moon and hire a Gemini-born Microsoft consultant within forty days. Subversion provides a more environmentally friendly solution - the svn:externals property.

svn propedit svn:externals Framework http://svn.repository/Framework/trunk

If you use this property on the main solution folder, the framework project will be checked out inside it and become the eligible (and version controlled) part of the solution. Instead of using the single physical copy of the framework project you would have multiple underneath each of the solutions but all of them will be tracked to the single code base in the SVN.


The svn:externals property still seems a little bit like a hack and has some stability issues and limitations with branching. Nevertheless it is a reasonable solution - the SVN properties can be managed by a build master and developers don't really need to do any extensive learning.

Tuesday, July 01, 2008

Intellisense in NAnt build file editor

This is a great article about adding Intellisense to the XML editor - a very useful feature. This also works perfectly with VS 2008 - just use Visual Studio 9 instead of 8. If the registry key in the article is truncated - it is 412B8852-4F21-413B-9B47-0C9751D3EBFB.

Unfortunately NAntContrib tasks are not included in the original schema but these articles provide some insight.


© 2008-2013 Michael Goldobin. All rights reserved