tag:blogger.com,1999:blog-31736793838532359372024-03-14T02:04:20.034-07:00C# | B# | Stay#pursue the <b>#</b>-ness in all thingsAnas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-3173679383853235937.post-46583295799996637642014-01-04T19:23:00.002-08:002014-01-04T19:24:32.312-08:00TFS API: Get Project Collection Team MembersI have been working extensively with TFS (Team Foundation Service) API, and enjoying the miscellaneous challenges therein. One such challenge was to display a list of valid team members to assign work items to. And following the TFS online experience, the Assign To field must display all the user oat the collection level.<br />
<br />
I saw a couple of approaches using the <span style="font-family: Courier New, Courier, monospace;">IGroupSecurityService </span>interface that is a part of the <span style="font-family: Courier New, Courier, monospace;">Microsoft.TeamFoundation.Server</span> but it has been marked as <b>obsolete </b>and instead a hint is provided to use the better alternative which is <span style="font-family: Courier New, Courier, monospace;">IIdentityManagementService</span>. So here is a simple code snippet on how to get a list of team members ordered alphabetically.<br />
<br />
Please note that the <span style="font-family: Courier New, Courier, monospace;">collection</span> variable is simply an instance of the team project collection class<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">new TfsTeamProjectCollection(<i>collectionUrl</i>, <i>credentials</i>)</span></blockquote>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Also note that when developing using the TFS API, you will need the following assemblies and namespaces referenced:</span><br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">using Microsoft.TeamFoundation;<br />using Microsoft.TeamFoundation.Client;<br />using Microsoft.TeamFoundation.Framework.Client;<br />using Microsoft.TeamFoundation.Framework.Common;</span></blockquote>
<br />
among others..<br />
<br />
<span style="font-family: inherit;">Here is the snippet::</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<script src="https://gist.github.com/anas-karkoukli/8263184.js"></script>Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com1tag:blogger.com,1999:blog-3173679383853235937.post-85001901402331192512012-10-05T22:16:00.001-07:002012-10-05T22:19:40.965-07:00A little recognition goes a long wayBlogging is an ambivalent activity. It is simultaneously the source of both gratifying sense of achievement, and at the same time, the source of the dreadful to-do chore that looms undone on your ever growing to-do list. It's an ugly sensation, being weighed down by your own device.. those evil to-do's. <br />
<br />
But this post is not about that. It is more related to, or more precisely, due to one of those rare moments of recognition, that come unsolicited and utterly unexpected. That simple act of being recognized or thanked for your humble work and contribution to the infinitude of collective consciousness and knowledge base of the human civilization.<br />
<br />
In this context, my humble work is an article I wrote for <a href="http://www.codeproject.com/Articles/31308/LINQ-and-WF-Based-Custom-Profile-Provider-for-ASP" target="_blank">CodeProject</a> almost 4 years ago, about implementing a custom Provider using the Workflow Foundation, which at the time was still fresh out of the oven of the Microsoft kitchen. It seems that it still serves some use after all:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKv-AGnyENkM49Vbi1YO6Xj4gV9YA6LXf3vsPCPSptOzsVBXmVVpNkjspDqG9wol_cocw7y0qLxYe5TJN1ZHesBGKH65ZfUaPO6BCRp6NoK6iSuXD2RxyEnrrLWV9NdsgI-gS7IAqoWbE/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKv-AGnyENkM49Vbi1YO6Xj4gV9YA6LXf3vsPCPSptOzsVBXmVVpNkjspDqG9wol_cocw7y0qLxYe5TJN1ZHesBGKH65ZfUaPO6BCRp6NoK6iSuXD2RxyEnrrLWV9NdsgI-gS7IAqoWbE/s640/Capture.PNG" width="640" /></a></div>
<br />
<br />
So stay motivated and always B#!Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-65911978417262391172011-08-23T19:02:00.000-07:002011-08-23T19:06:18.172-07:00But Scully…<p>Ok I could not help this one. I personally rank this Mulder-ian plead as one of top 5 most bizarre and fascinating TV quotes of all time.</p> <p>Season six, episode seven (Terms of Endearment)</p> <blockquote> <p><font color="#4bacc6">“(on the phone): Scully, this is a classic case of demonic foetal harvesting. – what they called in the middle ages: atum nocutrnem…”</font></p></blockquote> <p>Those pesky demon foetal harvester are the worst!</p> <p>Beware of the dark lords of the underworld!</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-19997862415271069762011-08-20T17:11:00.000-07:002011-08-20T17:30:40.444-07:00Balsamiq… The art of software<p>Despite the infinite plethora of software and productivity and tools that have been around for years, most hailed by their users, many condemned for being utterly useless.</p> <p>Every once in a while I stumble upon a gem, a singular piece of software or productivity tool that compels me with teary eyes to exclaim with sheer joy and awe (ok the tears part is an exaggeration).</p> <p>The ability of providing quick intuitive diagrams and mock ups in software development is of paramount importance and using generic graphic software like photoshop is an overkill. </p> <p>Enter <a href="http://balsamiq.com/" target="_blank">Balsamiq</a>… an amazing tool for impressive mock up design. It allows me to produce almost effortlessly intuitive diagrams such as this architectural diagram I was tasked with producing.</p> <p><a href="http://lh3.ggpht.com/-6WkWgwT-gfA/TlBRqY5B9eI/AAAAAAAAACE/jVTFNAEbQKU/s1600-h/Balsamiq_mockup_sample%25255B18%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="Balsamiq_mockup_sample" border="0" alt="Balsamiq_mockup_sample" src="http://lh5.ggpht.com/-8ywU_XuD0s0/TlBRr7x5pVI/AAAAAAAAACI/F1aTKK5ohQM/Balsamiq_mockup_sample_thumb%25255B16%25255D.png?imgmax=800" width="582" height="600"></a></p> <p>I love the artistic style of the graphics and font sets. In short this is a darn cool piece of software. If only more such beautiful tools exist.</p> <p>Enjoy!</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-54897209768730754582011-08-18T18:31:00.000-07:002011-08-18T18:42:13.291-07:00The X-Files… The Third Marathon, I still want to believe<p>Where did this come from? From the #-ness of programming languages to the X – Files. An interesting tangent, being the only topic that compelled me to pollute my blog with non programming posts.</p> <p>Yes, it is my third marathon watching the entire 9 seasons since the show’s finale almost a decade ago now. This is a no trivial undertaking and surely not for the faint of heart. In this day and age of instant gratification and extreme reductionism that plagues the media – yes, I am fed up with the over simplification of all that is television these days, it is difficult to appreciate verbose dialogues and absurd intellectual jousts such as the ones that Scully and Mulder exchanged throughout the series. For me, they are pure joy and a twisted thrill. But I digress..</p> <p>I decided here to share some of the memorable puns/quotes/aphorisms that I immensely enjoyed.</p> <p>This one comes from season 8, episode 10 (Salvage). Mulder has been abducted as a cliff hanger from the previous season. And awaiting his Christ-like resurrection, a great actor (Robert Patrick, as agent DOGGETT) takes his place as a leading man. What an excellent choice. Many of us grew up revering him as T – 1000 from Terminator II. The very reference to which (i.e. his role as the liquid metal menace from the future) is very clear in this piece of dialogue:</p> <blockquote> <p><font color="#4bacc6">“(to Scully on the phone): What are you saying? Ray Pearce has become some kind of metal man? Because that only happens in the movies, Agent Scully”</font></p></blockquote> <p>I just loved the series with all the idiosyncrasies and the Orwellian overtones that flavoured every single Mulder-ian retort!</p> <p>The truth is out there.</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-82750787409708702942011-08-07T19:51:00.000-07:002011-08-08T21:12:31.118-07:00Custom Assembly Versioning with VS 2010 and MSBUILD<p>There is a plethora of resources that deal with auto incrementing build numbers and a wealth of plugins and other gizmos that manage assembly versioning. So why yet another article. The truth is that none of those option solved my problem. I needed something simple, easy to maintain and most importantly flexible with a local .NET flavour. So naturally I had to write my own humble solution.</p> <p>One of the daunting tasks we often face when deploying assemblies, is managing assembly and product versions. In any “decent” .NET solution, there is a need to auto-increment the version with every successful build. For example, incrementing the duild part of the assembly version in this default scheme</p> <p align="center"><font color="#00ff00" face="Courier New"><strong>Major.Minor.Build.Revision</strong></font></p> <p>Sometime, versioning requirements are more elaborate and demanding, we might want to append the build date as well as incrementing the build number, the version scheme might look like</p> <p align="center"><font color="#00ff00" face="Courier New"><strong>Major.Minor.Build.DDMMYYYY</strong></font></p> <p>For that purpose I prefer using the AssemblyFileVersion instead of the AssemblyVersion. The former has an open format and can accommodate virtually any data, whereas the later, AssmeblyVersion is intended for use by the .NET framework and enforces a strict numbering scheme that yields compiler errors if infracted. </p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:753414b0-f4c7-4f55-97aa-7a45069aafff" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; overflow: auto; padding: 2px 5px;">[<span style="color:#0000ff">assembly</span>: <span style="color:#2b91af">AssemblyVersion</span>(<span style="color:#a31515">"4.0.*"</span>)] <span style="color:#008000">//Strict Format, for framework use</span><br> [<span style="color:#0000ff">assembly</span>: <span style="color:#2b91af">AssemblyFileVersion</span>(<span style="color:#a31515">"4.0.20.110708"</span>)] <span style="color:#008000">//Flexible Format more suitable for product versions</span></div> </div> </div> <p>This post describes how to leverage MSBUILD to automate this process and include it in the continuous integration pipeline.</p> <h5><font color="#00ff00">Tips for managing multiple assembly.cs files</font></h5> <p>In a solution with multiple projects and corresponding multiple assembly.cs files where AssemblyVersion and AssemblyFileVersion are kept, it is better to have one such file shared amongst all assemblies. To achieve this, we use a very useful visual studio feature which is Adding Existing Items as Links</p> <p><a href="http://lh3.ggpht.com/-oZqUnhe9v6E/TkCvgxrPP_I/AAAAAAAAABs/qeOtKgRoYDs/s1600-h/Add%252520as%252520Link%252520in%252520VS2010%25255B12%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="Add as Link in VS2010" border="0" alt="Add as Link in VS2010" src="http://lh4.ggpht.com/-TZ4fCDoeQtg/TkCvheYuZ3I/AAAAAAAAABw/GgLOT6R6Vz0/Add%252520as%252520Link%252520in%252520VS2010_thumb%25255B11%25255D.png?imgmax=800" width="394" height="213"></a></p> <p>We use this technique to create one shared assembly info file to be shared amongst all the projects in the solution. This shared file will contain the AssemblyVersion and AssemblyFileVersion assembly attributes are well as any solution wide values, whereas the individual project level assembly.cs will contain project specific information such as:</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:54e9f4f2-b7d8-454f-a85a-a81228029742" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">using</span> System.Reflection;<br> <span style="color:#0000ff">using</span> System.Runtime.InteropServices;<br> <br> [<span style="color:#0000ff">assembly</span>: <span style="color:#2b91af">AssemblyTitle</span>(<span style="color:#a31515">"POC.AssemblyVersioning.Common"</span>)]<br> [<span style="color:#0000ff">assembly</span>: <span style="color:#2b91af">AssemblyCulture</span>(<span style="color:#a31515">""</span>)]<br> <br> [<span style="color:#0000ff">assembly</span>: <span style="color:#2b91af">Guid</span>(<span style="color:#a31515">"bdf2e8b4-41aa-4569-b093-987439090dea"</span>)]</div> </div> </div> <p>And here is how the solution structure will look like with implementing this scheme.. all for the sole purpose of facilitating modifying assembly version automatically.</p> <p><a href="http://lh4.ggpht.com/-y8-ULjEQjJc/TkCvhtqZ0qI/AAAAAAAAAB0/AkjgpmLyWdE/s1600-h/solution%252520view%25255B14%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="solution view" border="0" alt="solution view" src="http://lh3.ggpht.com/-jUacn4fzpJE/TkCviDA6fHI/AAAAAAAAAB4/07p9pan8c7A/solution%252520view_thumb%25255B12%25255D.png?imgmax=800" width="312" height="277"></a></p> <p>And now to the more interesting part</p> <h5><font color="#00ff00">Building custom MSBUILD tasks</font></h5> <p>The reason why I prefer to use custom tasks in build automation as opposed to other scripting solution, is the glaring fact that Build Tasks are plain C# classes, where you can use the goodies that the .NET framework offers. To create a Build Tasks all you have to do is:</p> <ul> <li>Add references to the required .NET assemblies</li></ul> <p><a href="http://lh3.ggpht.com/-zNoJkRPUHjU/TkCvieqle9I/AAAAAAAAAB8/T2AXD6gGFzI/s1600-h/references%25255B5%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="references" border="0" alt="references" src="http://lh5.ggpht.com/-4C1yL7MJ8jk/TkCviuZSGOI/AAAAAAAAACA/nZFV-1fG7DA/references_thumb%25255B3%25255D.png?imgmax=800" width="312" height="206"></a></p> <ul> <li>Create a class that extends <font color="#00ff00" face="Courier New">Microsoft.Build.Utilities.Task</font></li></ul> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b9b71fef-a634-43cc-84ba-95dcc86ec3d7" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #fff; overflow: auto"> <ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"> <li><span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">MyTask</span> : <span style="color:#2b91af">Task</span></li> <li style="background: #f3f3f3">{</li> <li> <span style="color:#008000">// The only behaviour that need be overridden</span></li> <li style="background: #f3f3f3"> <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">bool</span> Execute()</li> <li> {</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">throw</span> <span style="color:#0000ff">new</span> <span style="color:#00008b">NotImplementedException</span>();</li> <li> }</li> <li style="background: #f3f3f3">}</li> </ol> </div> </div> </div> <ul> <li>Add a reference to the custom task inside a msbuild file. Any XML file that references the following namespace <a title="http://schemas.microsoft.com/developer/msbuild/2003" href="http://schemas.microsoft.com/developer/msbuild/2003">http://schemas.microsoft.com/developer/msbuild/2003</a> is a valid msbuild file. Here is a sample file that references a sample task</li></ul> <p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:82b70ece-22b2-43c3-8384-b190b626f2e5" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff"><?</span><span style="color:#a31515">xml</span><span style="color:#0000ff"> </span><span style="color:#ff0000">version</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">1.0</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">encoding</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">utf-8</span>"<span style="color:#0000ff"> ?></span><br> <span style="color:#0000ff"><</span><span style="color:#a31515">Project</span><span style="color:#0000ff"> </span><span style="color:#ff0000">ToolsVersion</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">4.0</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">DefaultTargets</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">AutoIncrement</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">xmlns</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color:#0000ff">></span><br> <span style="color:#0000ff"> <</span><span style="color:#a31515">UsingTask</span><span style="color:#0000ff"> </span><span style="color:#ff0000">AssemblyFile</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">POC.AssemblyVersioning.BuildTask.dll</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">TaskName</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">BuildIncrementTask</span>"<span style="color:#0000ff"> /></span><br> <span style="color:#0000ff"> <</span><span style="color:#a31515">Target</span><span style="color:#0000ff"> </span><span style="color:#ff0000">Name</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">AutoIncrement</span>"<span style="color:#0000ff">></span><br> <span style="color:#0000ff"> <</span><span style="color:#a31515">BuildIncrementTask</span><span style="color:#0000ff"> /></span><br> <span style="color:#0000ff"> </</span><span style="color:#a31515">Target</span><span style="color:#0000ff">></span><br> <span style="color:#0000ff"></</span><span style="color:#a31515">Project</span><span style="color:#0000ff">></span></div> </div> </div></p> <p><font color="#00ff00"></font></p> <p><font color="#ffffff">And to simply invoke this task from a command line, we use this familiar syntax, assuming that the msbuild file was saved as sample.proj</font></p> <p align="center"><font color="#00ff00" size="1" face="Courier New"><strong>msbuild sample.proj /t:AutoIncrement</strong></font></p> <h5><font color="#00ff00">Putting it all together!</font></h5> <p>After having acquainted ourselves with MSBUILD tasks and thought about having one shared assembly file info that hosts the AssemblyVersion and AssemblyFileVersion attributes, I introduce here a simple way to go about updating those attributes through this simple custom task. The task is based on file I/O where the contents of the shared assembly info will be parsed, the attributes update and incremented (or transformed to the desired format) and the content re-written back to the file. Here is the source code for the simple build tasks that will perform the file manipulation. This is for illustration purposes and intended only as a guide to creating your own build task. I encourage you to.</p> <p> </p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:633d9517-c5a4-463a-bba1-0e8ae6c444d7" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #fff; overflow: auto"> <ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"> <li><span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">AutoIncrementTask</span> : <span style="color:#2b91af">Task</span></li> <li style="background: #f3f3f3">{</li> <li> <span style="color:#0000ff">private</span> <span style="color:#0000ff">const</span> <span style="color:#0000ff">string</span> VersionPattern = <span style="color:#a31515">@"\[assembly: AssemblyFileVersion\(\""(\d{1}).(\d{1}).(\d{1,}).(\d{6})""\)\]"</span>;</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> AssemblyInfoPath { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li> </li> <li style="background: #f3f3f3"> <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">bool</span> Execute()</li> <li> {</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">try</span></li> <li> {</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">if</span> (<span style="color:#2b91af">String</span>.IsNullOrEmpty(AssemblyInfoPath))</li> <li> <span style="color:#0000ff">throw</span> <span style="color:#0000ff">new</span> <span style="color:#2b91af">ArgumentException</span>(<span style="color:#a31515">"AssemblyInfoPath must have a value"</span>);</li> <li style="background: #f3f3f3"> </li> <li> <span style="color:#0000ff">string</span>[] content = <span style="color:#2b91af">File</span>.ReadAllLines(AssemblyInfoPath, <span style="color:#2b91af">Encoding</span>.Default);</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">var</span> rx = <span style="color:#0000ff">new</span> <span style="color:#2b91af">Regex</span>(VersionPattern);</li> <li> </li> <li style="background: #f3f3f3"> <span style="color:#0000ff">var</span> newContent = <span style="color:#0000ff">new</span> <span style="color:#2b91af">List</span><<span style="color:#0000ff">string</span>>();</li> <li> content.ToList().ForEach(line =></li> <li style="background: #f3f3f3"> {</li> <li> <span style="color:#0000ff">if</span> (rx.IsMatch(line))</li> <li style="background: #f3f3f3"> line = VersionMatcher(rx.Match(line));</li> <li> newContent.Add(line);</li> <li style="background: #f3f3f3"> });</li> <li> </li> <li style="background: #f3f3f3"> <span style="color:#2b91af">File</span>.WriteAllLines(AssemblyInfoPath, newContent);</li> <li> </li> <li style="background: #f3f3f3"> }</li> <li> <span style="color:#0000ff">catch</span>(<span style="color:#2b91af">Exception</span> ex)</li> <li style="background: #f3f3f3"> {</li> <li> <span style="color:#2b91af">Console</span>.Out.WriteLine(ex);</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">return</span> <span style="color:#0000ff">false</span>;</li> <li> }</li> <li style="background: #f3f3f3"> </li> <li> <span style="color:#0000ff">return</span> <span style="color:#0000ff">true</span>;</li> <li style="background: #f3f3f3"> }</li> <li> </li> <li style="background: #f3f3f3"> <span style="color:#0000ff">private</span> <span style="color:#0000ff">string</span> VersionMatcher(<span style="color:#2b91af">Match</span> match)</li> <li> { </li> <li style="background: #f3f3f3"> <span style="color:#0000ff">int</span> major = <span style="color:#0000ff">int</span>.Parse(match.Groups[1].Value);</li> <li> <span style="color:#0000ff">int</span> minor = <span style="color:#0000ff">int</span>.Parse(match.Groups[2].Value);</li> <li style="background: #f3f3f3"> <span style="color:#0000ff">int</span> build = <span style="color:#0000ff">int</span>.Parse(match.Groups[3].Value);</li> <li> <span style="color:#0000ff">string</span> revision = match.Groups[4].Value;</li> <li style="background: #f3f3f3"> </li> <li> <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"AutoIncrement Assembly {</span><span style="color:#3cb371">0}</span><span style="color:#a31515">"</span>, <span style="color:#2b91af">Path</span>.GetFileName(AssemblyInfoPath));</li> <li style="background: #f3f3f3"> <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Current matched version: {</span><span style="color:#3cb371">0}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">1}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">2}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">3}</span><span style="color:#a31515">"</span>, major, minor, build, revision);</li> <li> </li> <li style="background: #f3f3f3"> ++build;</li> <li> revision = <span style="color:#2b91af">String</span>.Format(<span style="color:#a31515">"{</span><span style="color:#3cb371">0}{1}{2}</span><span style="color:#a31515">"</span>, <span style="color:#2b91af">DateTime</span>.Now.Year.ToString().Substring(2), <span style="color:#2b91af">String</span>.Format(<span style="color:#a31515">"{</span><span style="color:#3cb371">0:d2}</span><span style="color:#a31515">"</span>, <span style="color:#2b91af">DateTime</span>.Today.Month), <span style="color:#2b91af">String</span>.Format(<span style="color:#a31515">"{</span><span style="color:#3cb371">0:d2}</span><span style="color:#a31515">"</span>, <span style="color:#2b91af">DateTime</span>.Today.Day));</li> <li style="background: #f3f3f3"> <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Incremented to version: {</span><span style="color:#3cb371">0}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">1}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">2}</span><span style="color:#a31515">.{</span><span style="color:#3cb371">3}</span><span style="color:#a31515">"</span>, major, minor, build, revision);</li> <li> </li> <li style="background: #f3f3f3"> <span style="color:#0000ff">string</span> result = match.Result(<span style="color:#a31515">"[assembly: AssemblyFileVersion(\"$1.$2.{0}.{1}\")]"</span>);</li> <li> <span style="color:#0000ff">return</span> <span style="color:#2b91af">String</span>.Format(result, build, revision);</li> <li style="background: #f3f3f3"> }</li> <li>}</li> </ol> </div> </div> </div> <p>And here is the corresponding xml MSBUILD file:</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b2f4697a-f1c9-45b9-b1ff-fcc5fa680466" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff"><?</span><span style="color:#a31515">xml</span><span style="color:#0000ff"> </span><span style="color:#ff0000">version</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">1.0</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">encoding</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">utf-8</span>"<span style="color:#0000ff"> ?></span><br> <span style="color:#0000ff"><</span><span style="color:#a31515">Project</span><span style="color:#0000ff"> </span><span style="color:#ff0000">ToolsVersion</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">4.0</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">DefaultTargets</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">IncrementBuild</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">xmlns</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color:#0000ff">></span><br> <span style="color:#0000ff"><</span><span style="color:#a31515">UsingTask</span><span style="color:#0000ff"> </span><span style="color:#ff0000">AssemblyFile</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">PATH_TO_TASK_DLL</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">TaskName</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">AutoIncrementTask</span>"<span style="color:#0000ff"> /></span><br> <span style="color:#0000ff"><</span><span style="color:#a31515">Target</span><span style="color:#0000ff"> </span><span style="color:#ff0000">Name</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">IncrementBuild</span>"<span style="color:#0000ff">></span><br> <span style="color:#0000ff"><</span><span style="color:#a31515">AutoIncrementTask</span><span style="color:#0000ff"> </span><span style="color:#ff0000">AssemblyInfoPath</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">..\SharedAssemblyInfo.cs</span>"<span style="color:#0000ff"> /></span><br> <span style="color:#0000ff"></</span><span style="color:#a31515">Target</span><span style="color:#0000ff">></span><br> <span style="color:#0000ff"></</span><span style="color:#a31515">Project</span><span style="color:#0000ff">></span></div> </div> </div> <p>As you can see, I chose the AssemblyFileVersion as the target for custom product and assembly versioning because there are no compile time checks on the the format of the version and because a product version is more end-user and business stakeholder friendly than the automatic build numbers used internally by the .NET framework.</p> <p>You can include the previous build task as a step in the build process capitalizing on the MSBUILD command line capabilities.</p> <p>Hope this helped… </p> <p>Stay #</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com3tag:blogger.com,1999:blog-3173679383853235937.post-54529174896811489132011-07-09T18:56:00.001-07:002011-08-08T21:16:38.113-07:00You “Try”… and what do you “Catch”… A TryCatchException!<p>This is posted without much ranting, hoping that the humour and the pun is evident and the code snippet self-explanatory. This code was written by someone who apparently regarded the <font face="Courier New"><strong>try{} catch {}</strong></font> construct itself error prone and decided to catch a <font face="Courier New"><strong>TryCatchException</strong></font>. </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">try</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">//Some Magic Code here</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">}</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var exceptionEntry = <span style="color: #0000ff">new</span> TryCatchException(<span style="color: #006080">"Method error"</span>, ex);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">throw</span> exceptionEntry;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><p>I have to admit this one is an original. I particularly like the additional detail (that is completely useless) “Method error”</p><br /><p>Code Responsibly.</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-92019494167864941612011-06-28T21:02:00.000-07:002011-06-28T21:03:01.062-07:00When 55 arguments are just about enough!!<p>In Robert Martin’s “a.k.a Uncle Bob” Clean Code book, he classifies Niladic functions (that have Zero arguments) as the best well behaved functions that are ideal to write and deal with; Monadic and Dyadic functions (that have 1 and 2 arguments respectively) comes as a second best. Anything Polyadic (with more than three arguments) is just pure evil and requires justification. <p>I wonder though how he would feel about a function with 55 arguments!! The following is just the signature of this function <p><font face="Courier New">(Int32,Int32,String,Int32,Int32,String,Int32,Int32,String,Int32 ,String,String,String,Int32,Int32,String,Int32,String,Int32,String ,Int32,String,Int32,Int32,Int32,DateTime,DateTime,String,String ,DateTime,DateTime,String,String,DateTime,DateTime,String,String ,String,String,String,Decimal,Decimal,Decimal,Decimal,Decimal,Decimal ,Int32,Int32,Int32,Int32,Int32,Int32,String,Int32,String)</font> <p>If I were to meet that developer who wrote that function, I would simply ask, WTF were you thinking!? <p>May we survive the coding horrors yet another day! <p>Stay#</p> Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-57383774009157342022010-08-24T06:03:00.000-07:002010-08-24T06:03:58.907-07:00Enter F#... An object oriented introduction to a functional language!Welcome to the very first F# post on my blog. <br />
I thought hard about an appropriate introduction post into the world of F#; and indeed many ideas came to mind. I could blog about currying, function composition, lazy evaluation, and all the other (for many a c# programmer) mystical and ambiguous concepts of functional programming. <br />
Instead, I opted to introduce F# using the decorator pattern example from my previous blog. I thought it would be a nice ice breaker for the uninitiated in functional languages and for those of us, mostly OO practitioners and programmers, who may actually appreciate F#’s ability to be very terse and expressive when it comes to writing object oriented code. <br />
Before presenting the F# version of the query wrappers, I will very briefly cover some key syntactical concepts to help you read the code in this post. <br />
<h5>Code Formatting and Indentation:</h5>Something to note about F#, is that it is sensitive to code indentation and line breaks, so indenting the code is not an aesthetic imperative for code readability, it actually is required to compile the code correctly. For a list of F# coding standard please refer to this <a href="http://msdn.microsoft.com/en-us/library/dd233191.aspx" target="_blank">msdn article</a> <br />
<h5>“let” Bindings</h5>The let keyword is used to associate an identifier with a value or a function. Very simple, but powerful. Here are a few examples: <br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:d86d1701-b248-4f24-b59a-5f0bedf57533" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 120px; overflow: auto; width: 666px;"><div><span style="color: black;">let simpleFloatValue </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">1.0f</span><span style="color: black;">
let squaredFunction x </span><span style="color: black;">=</span><span style="color: black;"> x </span><span style="color: black;">*</span><span style="color: black;"> x
</span><span style="color: green;">//</span><span style="color: green;">let is also used inside type constructors</span><span style="color: green;">
</span><span style="color: black;">type Someclass(name:</span><span style="color: blue;">string</span><span style="color: black;">) </span><span style="color: black;">=</span><span style="color: black;">
let _name </span><span style="color: black;">=</span><span style="color: black;"> name
member </span><span style="color: blue;">this</span><span style="color: black;">.GetName </span><span style="color: black;">=</span><span style="color: black;"> name.ToUpper()</span></div></pre></div><br />
<h5>Type Annotation: </h5>In F#, variables’ types are implicitly inferred at compile time. Optionally, we can provide explicit parameter type. So the following two declarations are identical:<br />
<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:51d7d68f-92fb-4f7c-a278-721871d8de56" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 42px; overflow: auto; width: 666px;"><div><span style="color: black;">let Adder x y </span><span style="color: black;">=</span><span style="color: black;"> x </span><span style="color: black;">+</span><span style="color: black;"> y
let Adder (x:</span><span style="color: blue;">int</span><span style="color: black;">) (y:</span><span style="color: blue;">int</span><span style="color: black;">) : </span><span style="color: blue;">int</span><span style="color: black;"> </span><span style="color: black;">=</span><span style="color: black;"> x </span><span style="color: black;">+</span><span style="color: black;"> y</span></div></pre></div><br />
<h5>Generics:</h5>Here are few examples of how F# supports generics. The first two lists are of type <strong>int</strong> and string respectively. The third example, is a generic function of type <strong>T</strong>.<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:42c51c17-1179-4bbf-b047-6c3992251233" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 60px; overflow: auto; width: 666px;"><div><span style="color: black;">let myIntList : </span><span style="color: blue;">int</span><span style="color: black;"> list </span><span style="color: black;">=</span><span style="color: black;"> [</span><span style="color: purple;">1</span><span style="color: black;">; </span><span style="color: purple;">2</span><span style="color: black;">; </span><span style="color: purple;">3</span><span style="color: black;">];
let myStringList : List</span><span style="color: black;"><</span><span style="color: blue;">string</span><span style="color: black;">></span><span style="color: black;"> </span><span style="color: black;">=</span><span style="color: black;"> [</span><span style="color: maroon;">"</span><span style="color: maroon;">1</span><span style="color: maroon;">"</span><span style="color: black;">; </span><span style="color: maroon;">"</span><span style="color: maroon;">2</span><span style="color: maroon;">"</span><span style="color: black;">; </span><span style="color: maroon;">"</span><span style="color: maroon;">3</span><span style="color: maroon;">"</span><span style="color: black;">];
let myFunction</span><span style="color: black;"><</span><span style="color: maroon;">'</span><span style="color: maroon;">T> (t: </span><span style="color: maroon;">'</span><span style="color: black;">T) : unit </span><span style="color: black;">=</span><span style="color: black;"> printf </span><span style="color: maroon;">"</span><span style="color: maroon;"> value of generic parameter is: %A</span><span style="color: maroon;">"</span><span style="color: black;"> t;</span></div></pre></div><br />
<h5>Unit Type:</h5>In F# the <strong>unit</strong> type represents the absence of a specific value. So for expressions that do not evaluate to a value, the return type is said to be of type <strong>unit</strong>. The equivalent concept in C# or C++ is the <strong>void</strong> type.<br />
<br />
<h5>Pipeline Operator “|>”:</h5>Pipelining enables to write a chain of function calls, such that the output of one function is the input to the following one. This successive call chain is referred to as function pipelining. So the result of the following call chain will be 101. 10 passed to the squared function (becomes 100) and then passed to the incremented function to become 101.<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:04235094-c65c-4c9a-8361-2e5320ac81b9" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 68px; overflow: auto; width: 666px;"><div><span style="color: black;">let squared x </span><span style="color: black;">=</span><span style="color: black;"> x </span><span style="color: black;">*</span><span style="color: black;"> x
let increment x </span><span style="color: black;">=</span><span style="color: black;"> x </span><span style="color: black;">+</span><span style="color: black;"> </span><span style="color: purple;">1</span><span style="color: black;">
let result </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">10</span><span style="color: black;"> </span><span style="color: black;">|></span><span style="color: black;"> squared </span><span style="color: black;">|></span><span style="color: black;"> increment</span></div></pre></div><br />
<h5>Query Wrappers a la F#:</h5>With no further ado, I list here the F# replica of the C# example included in the previous post. Please note here, that I did not use LINQ query, instead I used simple lists. Fist some data setup, a dummy list of 5 employees:<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:6097c1dd-3dd4-4324-9a6f-aa5ee0e518bc" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 177px; overflow: auto; width: 666px;"><div><span style="color: black;">type Employee </span><span style="color: black;">=</span><span style="color: black;"> { Name : </span><span style="color: blue;">string</span><span style="color: black;">; Age : </span><span style="color: blue;">int</span><span style="color: black;">; IsManager : </span><span style="color: blue;">bool</span><span style="color: black;">}
let emp1:Employee </span><span style="color: black;">=</span><span style="color: black;"> {Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: maroon;">"</span><span style="color: maroon;">emp1</span><span style="color: maroon;">"</span><span style="color: black;">; Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">25</span><span style="color: black;">; IsManager </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: blue;">false</span><span style="color: black;">};
let emp2:Employee </span><span style="color: black;">=</span><span style="color: black;"> {Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: maroon;">"</span><span style="color: maroon;">emp2</span><span style="color: maroon;">"</span><span style="color: black;">; Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">50</span><span style="color: black;">; IsManager </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: blue;">true</span><span style="color: black;">};
let emp3:Employee </span><span style="color: black;">=</span><span style="color: black;"> {Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: maroon;">"</span><span style="color: maroon;">emp3</span><span style="color: maroon;">"</span><span style="color: black;">; Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">42</span><span style="color: black;">; IsManager </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: blue;">false</span><span style="color: black;">};
let emp4:Employee </span><span style="color: black;">=</span><span style="color: black;"> {Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: maroon;">"</span><span style="color: maroon;">emp4</span><span style="color: maroon;">"</span><span style="color: black;">; Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">31</span><span style="color: black;">; IsManager </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: blue;">false</span><span style="color: black;">};
let emp5:Employee </span><span style="color: black;">=</span><span style="color: black;"> {Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: maroon;">"</span><span style="color: maroon;">emp5</span><span style="color: maroon;">"</span><span style="color: black;">; Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: purple;">37</span><span style="color: black;">; IsManager </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: blue;">true</span><span style="color: black;">};
let employees </span><span style="color: black;">=</span><span style="color: black;"> [emp1;emp2;emp3;emp4;emp5];</span></div></pre></div><br />
And then the abstractions and the query wrappers.<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:cfd41ab1-504e-460b-82eb-aae595c9df07" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 451px; overflow: auto; width: 666px;"><div><span style="color: black;">[</span><span style="color: black;"><</span><span style="color: black;">AbstractClass</span><span style="color: black;">></span><span style="color: black;">]
type QueryComponent</span><span style="color: black;"><</span><span style="color: maroon;">'</span><span style="color: maroon;">T>() = </span><span style="color: maroon;">
</span><span style="color: black;"> </span><span style="color: blue;">abstract</span><span style="color: black;"> member Query : unit </span><span style="color: black;">-></span><span style="color: black;"> </span><span style="color: maroon;">'</span><span style="color: maroon;">T list </span><span style="color: maroon;">
</span><span style="color: black;">
[</span><span style="color: black;"><</span><span style="color: black;">AbstractClass</span><span style="color: black;">></span><span style="color: black;">]
type QueryWrapper</span><span style="color: black;"><</span><span style="color: maroon;">'</span><span style="color: maroon;">T>(qc:QueryComponent<</span><span style="color: maroon;">'</span><span style="color: black;">T</span><span style="color: black;">></span><span style="color: black;">) </span><span style="color: black;">=</span><span style="color: black;">
inherit QueryComponent</span><span style="color: black;"><</span><span style="color: maroon;">'</span><span style="color: maroon;">T>()</span><span style="color: maroon;">
</span><span style="color: black;"> let _component </span><span style="color: black;">=</span><span style="color: black;"> qc
member self.CallTrailer : </span><span style="color: maroon;">'</span><span style="color: maroon;">T list =</span><span style="color: maroon;">
</span><span style="color: black;"> _component.Query()
type EmployeeQuery() </span><span style="color: black;">=</span><span style="color: black;">
inherit QueryComponent</span><span style="color: black;"><</span><span style="color: black;">Employee</span><span style="color: black;">></span><span style="color: black;">()
</span><span style="color: blue;">override</span><span style="color: black;"> self.Query() </span><span style="color: black;">=</span><span style="color: black;"> employees
type ManagersQuery(qc) </span><span style="color: black;">=</span><span style="color: black;">
inherit QueryWrapper</span><span style="color: black;"><</span><span style="color: black;">Employee</span><span style="color: black;">></span><span style="color: black;">(qc)
</span><span style="color: blue;">override</span><span style="color: black;"> self.Query() </span><span style="color: black;">=</span><span style="color: black;">
</span><span style="color: blue;">base</span><span style="color: black;">.CallTrailer </span><span style="color: black;">|></span><span style="color: black;"> List.filter (fun e </span><span style="color: black;">-></span><span style="color: black;"> e.IsManager)
type EmployeeAgeQuery(qc, age) </span><span style="color: black;">=</span><span style="color: black;">
inherit QueryWrapper</span><span style="color: black;"><</span><span style="color: black;">Employee</span><span style="color: black;">></span><span style="color: black;">(qc)
</span><span style="color: blue;">override</span><span style="color: black;"> self.Query() </span><span style="color: black;">=</span><span style="color: black;">
</span><span style="color: blue;">base</span><span style="color: black;">.CallTrailer </span><span style="color: black;">|></span><span style="color: black;"> List.filter (fun e </span><span style="color: black;">-></span><span style="color: black;"> e.Age </span><span style="color: black;">></span><span style="color: black;"> age)
</span></div></pre></div><br />
That’s basically it!! To test the code, use the F# interactive tool in visual studio. Here are a couple of examples to try:<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:c59a09ad-5d95-4d7c-80d0-cbfd48f2b1c8" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 90px; overflow: auto; width: 666px;"><div><span style="color: green;">//</span><span style="color: green;">Get All Managers</span><span style="color: green;">
</span><span style="color: black;">let managers </span><span style="color: black;">=</span><span style="color: black;"> ManagersQuery(EmployeeQuery()).Query();
</span><span style="color: green;">//</span><span style="color: green;">Get All Employees Older Than 35</span><span style="color: green;">
</span><span style="color: black;">let employeesOlderThan35 </span><span style="color: black;">=</span><span style="color: black;"> EmployeeAgeQuery(EmployeeQuery(), </span><span style="color: purple;">35</span><span style="color: black;">).Query()</span></div></pre></div><br />
The results of running the aforementioned two queries will return respectively, the following:<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:b0be3655-906d-4af2-b7a8-8f2595a3e687" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><pre style="background-color: white; height: 137px; overflow: auto; width: 666px;"><div><span style="color: black;">val managers : Employee list </span><span style="color: black;">=</span><span style="color: black;"> [{Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">"</span><span style="color: black;">emp2</span><span style="color: black;">"</span><span style="color: black;">;</span><span style="color: black;"> Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">50</span><span style="color: black;">;</span><span style="color: black;"> IsManager </span><span style="color: black;">=</span><span style="color: black;"> true</span><span style="color: black;">;</span><span style="color: black;">}</span><span style="color: black;">;</span><span style="color: black;">
{Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">"</span><span style="color: black;">emp5</span><span style="color: black;">"</span><span style="color: black;">;</span><span style="color: black;"> Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">37</span><span style="color: black;">;</span><span style="color: black;"> IsManager </span><span style="color: black;">=</span><span style="color: black;"> true</span><span style="color: black;">;</span><span style="color: black;">}]
val employeesOlderThan35 : Employee list </span><span style="color: black;">=</span><span style="color: black;">
[{Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">"</span><span style="color: black;">emp2</span><span style="color: black;">"</span><span style="color: black;">;</span><span style="color: black;"> Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">50</span><span style="color: black;">;</span><span style="color: black;"> IsManager </span><span style="color: black;">=</span><span style="color: black;"> true</span><span style="color: black;">;</span><span style="color: black;">}</span><span style="color: black;">;</span><span style="color: black;">
{Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">"</span><span style="color: black;">emp3</span><span style="color: black;">"</span><span style="color: black;">;</span><span style="color: black;"> Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">42</span><span style="color: black;">;</span><span style="color: black;"> IsManager </span><span style="color: black;">=</span><span style="color: black;"> false</span><span style="color: black;">;</span><span style="color: black;">}</span><span style="color: black;">;</span><span style="color: black;">
{Name </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">"</span><span style="color: black;">emp5</span><span style="color: black;">"</span><span style="color: black;">;</span><span style="color: black;"> Age </span><span style="color: black;">=</span><span style="color: black;"> </span><span style="color: black;">37</span><span style="color: black;">;</span><span style="color: black;"> IsManager </span><span style="color: black;">=</span><span style="color: black;"> true</span><span style="color: black;">;</span><span style="color: black;">}]</span></div></pre></div><br />
<br />
<h5>Recap:</h5>Again I fully realize that such an example is probably not the best introduction into the world of functional programming but let it serve as an prelude for what is yet to come. The following Blog post will solve the same problem using purely functional approach exposing more of the interesting features of F#.<br />
<br />
Enjoy the #-ness!Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-43949092941227774702010-06-23T09:03:00.000-07:002010-06-28T08:49:36.098-07:00Design Patterns Part I :: Composed LINQ queries using the Decorator PatternThis Blogs series will explore practical uses and applications of design patterns in day to day development practices, using practical examples in C#. The first Blog (one of hopefully many more to come) will cover the Decorator Pattern.<br />
<h1>Introduction and Concepts</h1>Let’s kick off this post with some theory. According to the GoF, the intent of the decorator design pattern is to<br />
<blockquote>“Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality”</blockquote>That was quoted from their seminal work <a href="http://en.wikipedia.org/wiki/Design_Patterns">Design Patterns: Elements of Reusable Object-Oriented Software</a> <br />
<br />
In my humble opinion, one of the greatest pleasures working in software development is when we can successfully implement a pattern, not through a premeditated intent but through natural and organic development of the code at hand. We spot the variation and try to encapsulate it and then lo and behold we end up using one pattern or another fulfilling its intent and purpose. I think a the holy grail of OO software developers (a slightly conceited statement perhaps) is to identify the what is common and what varies in any given requirement and then find a way to encapsulate that change making future (and almost inevitable requirement changes) relatively easy to implement.<br />
<br />
After that brief techno-rant. We can go back to our main topic. The Decorator Design Pattern. Conceptually, here is how the pattern looks like:<br />
<br />
<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicYIVAsZGFZZ2Q5MZu9ZadNFJ4fm4mvgRqM9ADiAXByaXiN93JMw1TBubv2N66uB3f_kbaaWxGlXkkzbT1-IuxD6ONYxvtWtw44u_zRkNI53d3rC25vAWYh1w08EP-dfFfsvOuEfPy_40/s1600/decorator+pattern.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" ru="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicYIVAsZGFZZ2Q5MZu9ZadNFJ4fm4mvgRqM9ADiAXByaXiN93JMw1TBubv2N66uB3f_kbaaWxGlXkkzbT1-IuxD6ONYxvtWtw44u_zRkNI53d3rC25vAWYh1w08EP-dfFfsvOuEfPy_40/s640/decorator+pattern.jpg" width="640" /></a></div><br />
</div>The decorator pattern allows me to create a chain of objects (trail of decorator objects) namely, the decorators that are responsible for the new functionality, and ends with the original object. And the call chain looks like:<br />
<div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ-PfjJcgSzoC5AK2qS51duSAuQi5dIHdNgOP2YvysF4TPg_uwypkgyp4jpSTA7QxkaYZ1BwVH9Ul1xhCZSsAYW_PoC5V7cDx-FE6X4DluZoNbcoO21tgcm_o-9IQJanSZUxAuUcfyCXo/s1600/CallChain.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="56" ru="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ-PfjJcgSzoC5AK2qS51duSAuQi5dIHdNgOP2YvysF4TPg_uwypkgyp4jpSTA7QxkaYZ1BwVH9Ul1xhCZSsAYW_PoC5V7cDx-FE6X4DluZoNbcoO21tgcm_o-9IQJanSZUxAuUcfyCXo/s400/CallChain.jpg" width="400" /></a></div><br />
<br />
<div></div>This is not to be confused with a linked list. Rather it should be regarded as a collection of optional decorating objects.<br />
<br />
One classic example of this pattern is the stream I/O library. For any particular stream there is only one input, but there can zero or more actions to perform on the input stream. For instance, as in the example below, I can read from a memory stream, filter the stream and then read it using a custom stream reader. All these components (the later two are custom objects) implement the stream abstract class and accept a stream object in their constructors. the chain of calls looks like this:<br />
<br />
<pre style="background-color: #eeeeee; border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; border-right: #999999 1px dashed; border-top: #999999 1px dashed; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; width: 100%;"><code>
<div style="background: white; color: black; font-family: Courier New; font-size: 10pt;"><div style="margin: 0px;"><span style="color: #2b91af;">Stream</span> filteredMemoryStream = </div><div style="margin: 0px;"> <span style="color: blue;">new</span> <span style="color: #2b91af;">StreamReader</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">StreamFilter</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">MemoryStream</span>()));</div></div></code></pre><h1>Query Decorators</h1><br />
Personally, I use the decorator pattern to solve the problem of decomposing LINQ queries into more granular and reusable parts. A client can call several LINQ queries that are similar but only have minor variations. The direct result of this is LINQ code duplicated in every query. Another side effect is the tight coupling between the calling client and query composition.<br />
<br />
The fictitious example I use here assumes we're querying an Employees repository and there are multitude of queries that might contain the same expressions and clauses. Say, we need to get all employees who are managers. Another requirement is what we get all employees who are managers and of certain age. We may then need to get the top %20 of those managers. All these extra queries are transformed into reusable decorators as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIP5zYJzuRGnl_5JvQxPAqqo1C3PIO8EwFeV9ixycMVIay5nGPYjzCp46htmspG-ytme87dKbKv4ww0rUJ1F8XVwBw6ckpyGz1RHN0mMphHFfXbZppDn2_mvdoZmHEkk-CiQl56w2_kOE/s1600/QueryDecorator.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="464" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIP5zYJzuRGnl_5JvQxPAqqo1C3PIO8EwFeV9ixycMVIay5nGPYjzCp46htmspG-ytme87dKbKv4ww0rUJ1F8XVwBw6ckpyGz1RHN0mMphHFfXbZppDn2_mvdoZmHEkk-CiQl56w2_kOE/s640/QueryDecorator.png" width="640" /></a></div><br />
<br />
As a direct result of this design, the query composition can be chained inside a factory that instantiates the desired query based on simple conditional logic of perhaps some configuration file:<br />
<br />
<br />
<div style="border-bottom: #000080 1px solid; border-left: #000080 1px solid; border-right: #000080 1px solid; border-top: #000080 1px solid; color: black; font-family: "Courier New", Courier, Monospace; font-size: 10pt;"><div style="background-color: white; overflow: auto; padding-bottom: 2px; padding-left: 5px; padding-right: 5px; padding-top: 2px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">EmployeeQueryFactory</span><br />
{<br />
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">QueryComponent</span><<span style="color: #2b91af;">Employee</span>> GetQuery()<br />
{<br />
<span style="color: green;">/*</span><br />
<span style="color: green;">* We decouple the calling client from the query component instantiation</span><br />
<span style="color: green;">* by using this factory method where we encapsulate all conditional</span><br />
<span style="color: green;">* logic that determines which query component to instantiate</span><br />
<span style="color: green;">* */</span><br />
<br />
<span style="color: green;">//Get all employees who are contractees</span><br />
<span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">ContracteesQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">EmployeeQuery</span>());<br />
<br />
<span style="color: green;">//Get all managers older than 50 </span><br />
<span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">AgeLimitQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">ManagersQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">EmployeeQuery</span>()), 50);<br />
<br />
<span style="color: green;">//Get top %20 of all contractees older than 30</span><br />
<span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">Top20PercentQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">AgeLimitQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">ContracteesQuery</span>(<span style="color: blue;">new</span> <span style="color: #2b91af;">EmployeeQuery</span>()), 30));<br />
}<br />
}</div></div><br />
<br />
And just to add more clarity to the example at hand, I add a simple implementation of the QueryComponent and QueryWrapper respectively, along with a concrete implementation of each.<br />
<br />
<div style="border-bottom: #000080 1px solid; border-left: #000080 1px solid; border-right: #000080 1px solid; border-top: #000080 1px solid; color: black; font-family: "Courier New", Courier, Monospace; font-size: 10pt;"><div style="background-color: white; overflow: auto; padding-bottom: 2px; padding-left: 5px; padding-right: 5px; padding-top: 2px;"><span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">QueryComponent</span><T><br />
{<br />
<span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <span style="color: #2b91af;">IQueryable</span><T> Query();<br />
}<br />
<br />
<br />
<span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">EmployeeQuery</span> : <span style="color: #2b91af;">QueryComponent</span><<span style="color: #2b91af;">Employee</span>><br />
{<br />
<span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: #2b91af;">IQueryable</span><<span style="color: #2b91af;">Employee</span>> Query()<br />
{<br />
<span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">EmployeesRepository</span>().GetAllEmployess().AsQueryable();<br />
}<br />
}<br />
<br />
<br />
<span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">QueryWrapper</span><T> : <span style="color: #2b91af;">QueryComponent</span><T><br />
{<br />
<span style="color: blue;">protected</span> <span style="color: blue;">readonly</span> <span style="color: #2b91af;">QueryComponent</span><T> QueryComponent;<br />
<br />
<span style="color: blue;">protected</span> QueryWrapper(<span style="color: #2b91af;">QueryComponent</span><T> queryComponent)<br />
{<br />
QueryComponent = queryComponent;<br />
}<br />
<br />
<br />
<span style="color: blue;">protected</span> <span style="color: #2b91af;">IQueryable</span><T> CallTrailer()<br />
{<br />
<span style="color: blue;">return</span> <span style="color: blue;">null</span> != QueryComponent ? QueryComponent.Query() : <span style="color: blue;">null</span>;<br />
}<br />
}<br />
<br />
<br />
<span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ContracteesQuery</span> : <span style="color: #2b91af;">QueryWrapper</span><<span style="color: #2b91af;">Employee</span>><br />
{<br />
<span style="color: blue;">public</span> ContracteesQuery(<span style="color: #2b91af;">QueryComponent</span><<span style="color: #2b91af;">Employee</span>> queryComponent)<br />
: <span style="color: blue;">base</span>(queryComponent)<br />
{<br />
}<br />
<br />
<br />
<span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: #2b91af;">IQueryable</span><<span style="color: #2b91af;">Employee</span>> Query()<br />
{<br />
<span style="color: blue;">return</span> CallTrailer().Where(p => p.IsContractee);<br />
}<br />
}</div></div><br />
Lastly, as with every post. I leave you with this quote by <a href="http://en.wikipedia.org/wiki/Christopher_Alexander">Christopher Alexander</a><br />
<blockquote>"We are searching for some kind of harmony between two intangibles: a form which we have not yet designed and a context which we cannot properly describe."</blockquote><br />
Code well and Stay#!Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0tag:blogger.com,1999:blog-3173679383853235937.post-59925876227115763532010-06-04T08:57:00.000-07:002010-06-04T08:58:04.574-07:00The Daily WTFGreetings All Code Monkeys...<br />
<br />
For those of us who have been subjected to unforgettable code atrocities, or for those who would like to seek solace in other people's horrendous coding errors (to feel better about their own!) - yes we all are red handed when it comes to writing code that should never have seen the light of day.<br />
<br />
Check the <a href="http://thedailywtf.com/">The Daily WTF</a> gives you the fix.I love that web site.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://thedailywtf.com/" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="45" src="http://thedailywtf.com/Resources/Images/Primary/logo.gif" width="320" /></a></div>Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com1tag:blogger.com,1999:blog-3173679383853235937.post-42642007125101787462010-05-21T07:21:00.000-07:002010-06-23T09:02:19.007-07:00Developer Tunnel Vision SyndromeI wanted my very first post to be on a rather happier note that celebrates the beauty of learning functional programming with F#, or touts a technical triumph or a breakthrough of mine. But the post is going to be more sombre and talk about Developer Tunnel Vision; a syndrome I have been suffering from over the past couple of days until the eventual breakthrough this morning.<br />
<br />
I say Tunnel Vision, because developers often spend inordinate amounts of time working exclusively in one technology or one programming language (C# for argument’s sake) and forget to touch on some neglected skills like thinking in T-SQL and finding solutions using solely set algebra and set operations.<br />
<br />
To give you a concrete example, I present the problem I had (with contrived data for demonstration purposes): given a list of values (say, velocities) with start/end time range for each velocity; in tabular form the input data looks like:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">Velocity StartTime </span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-size: small;"> </span></span><span class="Apple-style-span" style="font-size: small;"> EndTime </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -------- ------------------- -------------------<br />
40</span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-size: small;"> </span></span><span class="Apple-style-span" style="font-size: small;"> 2009-11-24 05:45:43 2009-11-25 04:23:18<br />
0 2009-11-25 04:23:18 2009-11-26 07:00:00<br />
0 2009-11-26 07:00:00 2009-11-27 06:23:18<br />
40 2009-11-27 06:23:18 2009-11-27 23:57:22<br />
0 2009-11-27 23:57:22 2009-11-28 09:00:00<br />
0 2009-11-28 09:00:00 2009-11-30 01:57:22<br />
0 2009-11-30 01:57:22 2009-11-30 11:00:00<br />
0 2009-11-30 11:00:00 2009-12-02 03:57:22<br />
0 2009-12-02 03:57:22 2009-12-04 05:57:22<br />
40 2009-12-04 05:57:22 2009-12-04 15:45:43</span> <br />
</span></span></span><br />
Using only plain set operations in T-SQL, collapse date ranges for matching velocities, to produce the following:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">Velocity StartTime </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> EndTime </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">-------- ------------------- -------------------</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">40</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> 2009-11-24 05:45:43 2009-11-25 04:23:18</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">0 2009-11-25 04:23:18 2009-11-27 06:23:18</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">40 2009-11-27 06:23:18 2009-11-27 23:57:22</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">0 2009-11-27 23:57:22 2009-12-04 05:57:22</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">40 2009-12-04 05:57:22 2009-12-04 15:45:43</span></span><br />
<br />
Simple at the first glance! So I went forward equipped with what I considered a solid knowledge in SQL and set algebra and started working on the solution.<br />
<br />
I was amazed at how difficult it was, because I recently had spent the good part of the past year or so thinking exclusively in Object Oriented way and I felt my mind struggled to rid itself of inheritance and polymorphism and to think in joins and unions. I eventually got to the answer, not the most elegant or succinct, but a good answer nonetheless (it is irrelevant to post the solution here).<br />
<br />
This morning however, I recanted yesterday’s solution and came up with a 3-line C# LINQ query that produced exactly the desired result.<br />
<br />
<div style="background: white; color: black; font-family: Courier New; font-size: 10pt;"><div style="margin: 0px;"><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">var</span></span><span class="Apple-style-span" style="font-size: small;"> collapsedRecords = records</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> .Aggregate(</span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">new</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">List</span></span><span class="Apple-style-span" style="font-size: small;"><</span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">Record</span></span><span class="Apple-style-span" style="font-size: small;">>(), groupingFunctor)</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> .GroupBy(dco => dco.GroupId, (k, v) => v)</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> .Select(v => </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">new</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">Record</span></span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> {</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> Velocity = v.First().Velocity,</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> ST = v.Min(_ => _.ST),</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> ET = v.Max(_ => _.ET)</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> });</span></div></div><br />
Along with the following simple plumbing:<br />
<br />
<div style="background: white; color: black; font-family: Courier New; font-size: 10pt;"><div style="margin: 0px;"><br />
<span class="Apple-style-span" style="color: #2b91af;"></span><br />
<span class="Apple-style-span" style="color: #2b91af;"></span><br />
<span class="Apple-style-span" style="color: #2b91af;"><div style="background: white; color: black; font-family: Courier New; font-size: 10pt;"><div style="margin: 0px;"><span style="color: #2b91af;">Func</span><<span style="color: #2b91af;">List</span><<span style="color: #2b91af;">Record</span>>, <span style="color: #2b91af;">Record</span>, <span style="color: #2b91af;">List</span><<span style="color: #2b91af;">Record</span>>> groupingFunctor =</div><div style="margin: 0px;"> (list, record) =></div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> record.GroupId = !list.Any() ? 1 : </div><div style="margin: 0px;"> ((list.Last().Velocity == record.Velocity)</div><div style="margin: 0px;"> ? list.Last().GroupId</div><div style="margin: 0px;"> : list.Last().GroupId + 1);</div><div style="margin: 0px;"> list.Add(record);</div><div style="margin: 0px;"> <span style="color: blue;">return</span> list;</div><div style="margin: 0px;"> };</div></div></span></div></div><br />
And<br />
<br />
<div style="background: white; color: black; font-family: Courier New; font-size: 10pt;"><div style="margin: 0px;"> <span class="Apple-style-span" style="font-size: small;"> </span><span style="color: green;"><span class="Apple-style-span" style="font-size: small;">//simple model for the records</span></span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">internal</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">class</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">Record</span></span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> {</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">public</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">int</span></span><span class="Apple-style-span" style="font-size: small;"> Velocity { </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">get</span></span><span class="Apple-style-span" style="font-size: small;">; </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">set</span></span><span class="Apple-style-span" style="font-size: small;">; }</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">public</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">int</span></span><span class="Apple-style-span" style="font-size: small;"> GroupId { </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">get</span></span><span class="Apple-style-span" style="font-size: small;">; </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">set</span></span><span class="Apple-style-span" style="font-size: small;">; } </span><span style="color: green;"><span class="Apple-style-span" style="font-size: small;">//helper property</span></span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">public</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">DateTime</span></span><span class="Apple-style-span" style="font-size: small;"> ST { </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">get</span></span><span class="Apple-style-span" style="font-size: small;">; </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">set</span></span><span class="Apple-style-span" style="font-size: small;">; }</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">public</span></span><span class="Apple-style-span" style="font-size: small;"> </span><span style="color: #2b91af;"><span class="Apple-style-span" style="font-size: small;">DateTime</span></span><span class="Apple-style-span" style="font-size: small;"> ET { </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">get</span></span><span class="Apple-style-span" style="font-size: small;">; </span><span style="color: blue;"><span class="Apple-style-span" style="font-size: small;">set</span></span><span class="Apple-style-span" style="font-size: small;">; }</span></div><div style="margin: 0px;"><span class="Apple-style-span" style="font-size: small;"> }</span></div></div><br />
Now we can digress and start raving about the accumulator pattern in the LINQ Aggregate extension method, or we can get to the point of this post:<br />
<br />
Most of us juggle more than one language and/or technology. And in order to stay sharp (no pun intended!) we must practice, practice and then practice some more lest time and negligence dulls the edge of our skills.<br />
<br />
Finally, I leave you with a bit of Charles Darwin:<br />
<blockquote><span class="Apple-style-span" style="color: #333333; font-family: sans-serif; font-size: 14px; line-height: 20px;">"I have steadily endeavored to keep my mind free so as to give up any hypothesis, however much beloved (and I cannot resist forming one on every subject), as soon as the facts are shown to be opposed to it.</span>"</blockquote>Anas Karkouklihttp://www.blogger.com/profile/11753348509849948575noreply@blogger.com0