<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-928795371668874325</id><updated>2011-10-04T18:13:17.324-07:00</updated><category term='vs2008'/><category term='linux'/><category term='C#'/><category term='windows'/><category term='peace in the universe'/><category term='linq'/><category term='sql server ce'/><category term='dal'/><category term='python'/><category term='ms sql'/><category term='basics'/><category term='lists'/><title type='text'>Learning.Net</title><subtitle type='html'>Crossing the bridge...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-1900814262065835528</id><published>2009-02-16T06:42:00.000-08:00</published><updated>2009-02-16T09:54:43.493-08:00</updated><title type='text'>Sharepoint ISO Week Number</title><content type='html'>Finding the week number for a date in Sharepoint cand be a real pain in the ass. The Internet provides some solutions, but they don't adhere to the ISO standard concerning week numbers:&lt;div&gt; - weeks start on monday&lt;/div&gt;&lt;div&gt; - the first week of the year is the one containing the fist Thursday of the year&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The starting point for the formula below can be found &lt;a href="http://www.proesite.com/timex/wkcalc.htm"&gt;here&lt;/a&gt;. It's pretty complex, and I suggest that first you should build some helper calculated functions for the most used values: day of week (DOW) of the current date, DOW of the first day of the current year, current day/month/year.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And here it is (replace "the_date" with the name of your date column):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;=INT(&lt;/div&gt;&lt;div&gt;    IF(AND(MONTH([the_date])=1,&lt;/div&gt;&lt;div&gt;           5 &amp;lt; WEEKDAY(DATE(YEAR([the_date]),1,1)), &lt;/div&gt;&lt;div&gt;           WEEKDAY(DATE(YEAR([the_date]),1,1)) &amp;lt; 9 - (DAY([the_date])-1)),&lt;/div&gt;&lt;div&gt;      &lt;/div&gt;&lt;div&gt;      (IF(WEEKDAY(DATE(YEAR([the_date]),1,1)) &amp;lt; 6,1,0)) + &lt;/div&gt;&lt;div&gt;      44 +&lt;/div&gt;&lt;div&gt;      (59+WEEKDAY(DATE(YEAR([the_date])-1,1,1))-WEEKDAY(DATE(YEAR([the_date]),1,1)))*9 / 64,&lt;/div&gt;&lt;div&gt;      &lt;/div&gt;&lt;div&gt;      IF(AND(MONTH([the_date])=12,&lt;/div&gt;&lt;div&gt;            30-(DAY([the_date])-1) &amp;lt; WEEKDAY(DATE(YEAR([the_date])+1, 1, 1)) - 2,&lt;/div&gt;&lt;div&gt;            WEEKDAY(DATE(YEAR([the_date])+1,1,1)) &amp;lt; 5),&lt;/div&gt;&lt;div&gt;         &lt;/div&gt;&lt;div&gt;         1,&lt;/div&gt;&lt;div&gt;         &lt;/div&gt;&lt;div&gt;         (IF(WEEKDAY(DATE(YEAR([the_date]),1,1)) &amp;lt; 6,1,0)) +&lt;/div&gt;&lt;div&gt;         4*(MONTH([the_date])-1) +&lt;/div&gt;&lt;div&gt;         (2*(MONTH([the_date])-1)+(DAY([the_date])-1)+WEEKDAY(DATE(YEAR([the_date]),1,1))-WEEKDAY([the_date])+6)*36/256)))&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;... I know, it's horrible... if you have time, make it pretty...&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-1900814262065835528?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/1900814262065835528/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=1900814262065835528' title='3 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1900814262065835528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1900814262065835528'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2009/02/sharepoint-iso-week-number.html' title='Sharepoint ISO Week Number'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-3399014444241910274</id><published>2009-01-12T21:30:00.001-08:00</published><updated>2009-01-12T21:31:13.862-08:00</updated><title type='text'>Death to the ORMs</title><content type='html'>&lt;p&gt;“Necessary evil” is just an excuse for incompetence in finding a solution for a hard problem. There is a long history of applications that didn’t require the user to rewrite the database schema in order to access the data: xBase, MS Access, SSMS, LINQPad. I can’t stand the nonsense surrounding the so called solutions for accessing data from a database, not counting the religious wars on what’s the best ORM. They’re all crap.&lt;/p&gt;  &lt;p&gt;Most programming languages, especially the OO breed, are not adapted to data manipulation as good as the plain old SQL. Microsoft made some progress on this front with LINQ and the Entity framework. But that’s not enough, and it has a fundamental flow: it should have been started as a “Set-Based”, not “Entity” framework.&lt;/p&gt;  &lt;p&gt;So, a decent set of requirements that an acceptable development platform for enterprise data applications should provide to its users is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;set based data access&lt;/li&gt;    &lt;li&gt;standard GUI toolkit, geared towards data manipulation (NOT web based)&lt;/li&gt;    &lt;li&gt;standard business logic specifications&lt;/li&gt;    &lt;li&gt;database based security&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Subject for the next post: how crappy are web based data applications.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-3399014444241910274?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/3399014444241910274/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=3399014444241910274' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/3399014444241910274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/3399014444241910274'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2009/01/death-to-orms.html' title='Death to the ORMs'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-2451776611767981892</id><published>2008-12-05T03:24:00.000-08:00</published><updated>2008-12-05T04:27:38.622-08:00</updated><title type='text'>Thoughts on Software Security</title><content type='html'>Here's something that grinds my gears: &lt;blockquote&gt;You still use bla bla bla Internet Navigator v13.2.256.2?!  Don't you know that it's full of security holes? You should usee YYY Firedog 2012 because it's &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;secure&lt;/span&gt; and hip, and soon everybody will be using it!&lt;/blockquote&gt;&lt;div&gt;From my experience there are &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;no&lt;/span&gt; perfect software programs, from the security perspective. The only thing that matters is the number of exploited security holes. And that number tends to be directly proportional to the popularity|number of users and number of functionalities of the software application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or worse. My theory is that the users of public software applications (meaning software meant for the masses, not for X company's HR department), with small user bases, tend to be more technically savvy. As the number of users grows, due to the increassing popularity of that software, the average naivety level tends to go up. This is the first step when things start to go bad, because the easiest security exploits rely on user ignorance.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second step occurs when the application suffers a surge of new functionalities. This usually happens when it starts supporting some form of plugins or automation, because this greatly increasese the area exposed by that application to the world: longer borders=&gt;more border patrols are needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So there is no real security comparison between two software applications, unless they have comparable user bases, have been available for the same period of time and support roughly the same major functions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My conclusion is this: educate the user! Software doesn't need to be foolproof. Time spent on dumbing down the user interface (and I don't reffer here only to the GUI, but the whole end user experince) can be better employed on improving its functionalities.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Help the user make informed decisions. Even if this means saying "Pushing this button exposes you to the following risks: money loss, health loss, pride loss, etc.". Software applications should not follow the marketing propaganda of consumerism. In a medium where information is a de facto currency, there are better ways to advocate the use of your software. Make a commitment to inform the users what are the &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;strong and week&lt;/span&gt; points of your application, when it can and when it shouldn't be used.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-2451776611767981892?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/2451776611767981892/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=2451776611767981892' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/2451776611767981892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/2451776611767981892'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/12/thoughts-on-software-security.html' title='Thoughts on Software Security'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-667128619021701026</id><published>2008-12-02T00:59:00.000-08:00</published><updated>2008-12-02T01:02:47.853-08:00</updated><title type='text'>Thoughts on Programming Languages</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; "&gt;&lt;div style="font-family: arial, sans-serif; font-size: 83%; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; overflow-x: hidden; overflow-y: hidden; background-color: rgb(255, 255, 255); "&gt;&lt;span&gt;1. Use declarative code for the UI (XAML, HTML)&lt;/span&gt;&lt;div&gt;&lt;span&gt;2. OO code for infrastructure (data access, etc...)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;3. Functional programming for logic implementation and data manipulation&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;4. Python has one of the nicest syntaxes of all programming languages&lt;/span&gt;&lt;/div&gt;&lt;div&gt;5. F# could have gotten a better syntax, even if it had broke OCAML compatibility.&lt;/div&gt;&lt;div&gt;6. Identation for code block delimitation rocks! I wish C# would have something like that... that might be an interesting idea: a precompiler for C# that just wraps indented blocks in curly braces.&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-667128619021701026?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/667128619021701026/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=667128619021701026' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/667128619021701026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/667128619021701026'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/12/thoughts-on-programming-languages.html' title='Thoughts on Programming Languages'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-8978348098328130639</id><published>2008-11-28T01:35:00.000-08:00</published><updated>2008-11-28T01:42:04.969-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='peace in the universe'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Running Linux Apps Seamlessly Insinde Windows for 100EUROS or Less</title><content type='html'>&lt;ol&gt;&lt;li&gt;Get a license and install windows (&lt;span class="misspell" suggestions="P,X,SP,PP,WP"&gt;XP&lt;/span&gt;/2003/Vista): blah, blah, blah, next, next, finish ... ~100E for Vista Home Premium&lt;/li&gt;&lt;li&gt;Download &amp;amp; install Virtual Box: blah, blah, blah, next, next, finish ... 0E&lt;/li&gt;&lt;li&gt;Download &amp;amp; install &lt;span class="misspell" suggestions="Bunt,Bantu,Bounty,Unburnt,Urbanity"&gt;Ubuntu&lt;/span&gt; (latest): blah, blah, blah, next, next, finish ... 0E&lt;/li&gt;&lt;li&gt;Press &amp;lt;Host key&amp;gt; + L ... priceless&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span class="misspell" suggestions="Tad,Tads,Ada,Dada,Tadd"&gt;Tada&lt;/span&gt;!&lt;br /&gt;&lt;br /&gt;PS: this post was written with Google Docs on Firefox running on Ubuntu linux running on Microsoft Windows 2003.&lt;br /&gt;PPS: only one operating system was restarted during the creation of this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-8978348098328130639?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/8978348098328130639/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=8978348098328130639' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8978348098328130639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8978348098328130639'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/11/running-linux-apps-seamlessly-insinde.html' title='Running Linux Apps Seamlessly Insinde Windows for 100EUROS or Less'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-7284499753485855371</id><published>2008-11-19T08:01:00.000-08:00</published><updated>2008-11-19T08:07:29.612-08:00</updated><title type='text'>My Plea to Microsoft</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Make&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Windows&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Free!&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-7284499753485855371?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/7284499753485855371/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=7284499753485855371' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/7284499753485855371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/7284499753485855371'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/11/my-plea-to-microsoft.html' title='My Plea to Microsoft'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-4620571904283780321</id><published>2008-10-18T14:49:00.000-07:00</published><updated>2008-10-18T15:04:24.436-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ms sql'/><title type='text'>Python can do:</title><content type='html'>Connect to an MS SQL database with integrated security (sample from a TurboGears aplication, using SQL Alchemy + Elixir + pyodbc):&lt;br /&gt;sqlalchemy.dburi="mssql://&lt;server&gt;&amp;lt;server name|named instance&amp;gt;/&amp;lt;database name&amp;gt;&lt;database&gt;?sspi=true"&lt;br /&gt;&lt;br /&gt;Next step: run TurboGears behind IIS in order to use Integrated Windows Security.&lt;br /&gt;Even further: investigate if IronPython fits somewhere.&lt;/database&gt;&lt;/server&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-4620571904283780321?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/4620571904283780321/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=4620571904283780321' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/4620571904283780321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/4620571904283780321'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/10/python-can-do.html' title='Python can do:'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-353916294783259991</id><published>2008-10-18T14:45:00.001-07:00</published><updated>2008-10-18T14:48:15.796-07:00</updated><title type='text'>For all our real problems are technical...</title><content type='html'>...not social, financial, political or religious:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thezeitgeistmovement.com/"&gt;The Zeitgeist Movement&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.thevenusproject.com/"&gt;The Venus Project&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-353916294783259991?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/353916294783259991/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=353916294783259991' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/353916294783259991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/353916294783259991'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/10/for-all-our-real-problems-are-technical.html' title='For all our real problems are technical...'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-8465379899441967569</id><published>2008-08-15T00:12:00.001-07:00</published><updated>2008-08-15T04:37:49.367-07:00</updated><title type='text'>Internet Censorship</title><content type='html'>&lt;p&gt;I thought that the Internet’s purpose was breaking communication barriers:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/mihai.foltache/SKUsasVkolI/AAAAAAAAACU/i_Cfhyrs4KI/s1600-h/cens%5B2%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="cens" border="0" alt="cens" src="http://lh4.ggpht.com/mihai.foltache/SKUsbFTO_BI/AAAAAAAAACY/EIVirS_7CTU/cens_thumb.png?imgmax=800" width="244" height="158" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I’ve seen this situation becoming more and more common. What’s interesting is that it’s not a subtle limitation. They could have made all the links going to the limited content not available to people outside the USA. Hmm…&lt;/p&gt;  &lt;p&gt;Update: &lt;a title="http://timheuer.com/blog/archive/2008/08/13/nbc-olympics-behind-the-scenes.aspx" href="http://timheuer.com/blog/archive/2008/08/13/nbc-olympics-behind-the-scenes.aspx"&gt;http://timheuer.com/blog/archive/2008/08/13/nbc-olympics-behind-the-scenes.aspx&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-8465379899441967569?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/8465379899441967569/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=8465379899441967569' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8465379899441967569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8465379899441967569'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/08/internet-censorship.html' title='Internet Censorship'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/mihai.foltache/SKUsbFTO_BI/AAAAAAAAACY/EIVirS_7CTU/s72-c/cens_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-6621856103223688150</id><published>2008-08-14T02:55:00.001-07:00</published><updated>2008-08-14T02:55:42.593-07:00</updated><title type='text'>Punitive Software Development</title><content type='html'>&lt;p&gt;The current project manager I’m working with, answers to all my whinnying about things that I don’t like in the current project with “M, you’re always complaining about the project and what a torture it is to work on it. You should take my example: I’ve been working on crappy software projects for the last 1134 years and I’ve never complained!”.&lt;/p&gt;  &lt;p&gt;To which I respond “Yeah you’re kind of right, but I want my life expectancy to be greater than 50, and I don’t find premature gray hair sexy”. Of&amp;#160; course, I don’t say it out loud.&lt;/p&gt;  &lt;p&gt;What did I learn from my experience with software projects:&lt;/p&gt;  &lt;p&gt;- software projects are always short on time&lt;/p&gt;  &lt;p&gt;- software projects must build upon and fix older, incomplete-or-completely-failed, software projects&lt;/p&gt;  &lt;p&gt;- there aren’t enough good developers around&lt;/p&gt;  &lt;p&gt;- developers have to completely rely on business analysts for the communication with the client&lt;/p&gt;  &lt;p&gt;- business analysts will always be more focused on gathering request from the client, rather than trying to find solutions for their problems with the tools that the developers can provide&lt;/p&gt;  &lt;p&gt;- the test team will be treated as if they are from Bangladesh even if they work in an office next to yours&lt;/p&gt;  &lt;p&gt;- agile techniques are just for showing off: “Yeah, we have a two week release period for each of our builds, and we hold daily scurm meetings, and we are so agile and so extreme that I just can’t stop looking at myself in a mirror”. Yeah you dumb agile &lt;a href="mailto:f@#k"&gt;f#*k&lt;/a&gt;. Just a little more agile and you could lick you own balls. You think you’re agile, but you still plan a project into requirements gathering, development and implementation. Really agile, no waterfall in here. If you wouldn’t have realized that regular testing ensures that your piece of crap software is less shitty (this is the original test driven development: give the test team something that barely resembles a software product and hope they will guide you towards an acceptable application), you’d still be doing testing at the end of the development phase.&lt;/p&gt;  &lt;p&gt;All of this must change…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-6621856103223688150?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/6621856103223688150/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=6621856103223688150' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/6621856103223688150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/6621856103223688150'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/08/punitive-software-development.html' title='Punitive Software Development'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-8787580892288314855</id><published>2008-08-01T05:19:00.001-07:00</published><updated>2008-08-14T04:20:22.035-07:00</updated><title type='text'>Code Generation Is Bad, M’kay?</title><content type='html'>&lt;h5&gt;Code generation: problem solver.&lt;/h5&gt;  &lt;h5&gt;Composition, abstraction, design patterns, a walk in the park &lt;u&gt;thinking&lt;/u&gt; of a better solution: constructive techniques.&lt;/h5&gt;  &lt;p&gt;It often tempts me to use code generation when I’m facing a problem that requires a lot of code to be written in order to solve each of it’s instances (ex: classes in the data access layer). It is the case when I’ve already used all the tools in my (small) development arsenal, and it seems I can no longer simplify and reduce the code that needs to be written by the clients of the solution. The clients being, in most cases, myself.&lt;/p&gt;  &lt;p&gt;And the most annoying thing is that I feel there is still too much repetitive code or logic, and there must be a better way around it. But the programming language doesn’t want to help me anymore, and I can’t think of any other solution. And I try to scribble other designs, and when I think I’m onto something, and try to translate the new solution into code, there is always a catch, some missing feature of the framework library, or of the language itself, or a glitch in my logic. &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;And there’s the Code Generator behind me, grinning, telling me: “You know you can’t avoid me…”. But I keep on trying: “Go away, leave me alone, there must be a better solution to all this crap (that I’m mostly to blame for)!”. And he goes: “Don’t ignore me, I might be your best friend at the moment.” - “But I hate you! You are possessive, you give my code inertia, and I suffer headaches when I try to make even the smallest change.” - “Hmm, that’s an oxymoron: the best friend you hate the most. C’mon, see the bright side, your code will barely change. It will look as young as when you first wrote it, even after years of use and abuse. It will become &lt;em&gt;immortal&lt;/em&gt; :).”&lt;/p&gt;  &lt;p&gt;Finally I give up and I try to make up for the compromise I’m committing: “At least I will generate very beautiful code, with all the comments it needs and exception handling and bells and whistles. And there will be extension points, so I will be able to add more features to the definition, like automatic validation-based-on-some-obscure-rules-that-I-will-come–up-with…”. And I feel sad…&lt;/p&gt;  &lt;p&gt;Well, I can’t be sad about my work. I’m still a programmer because I like programming, and I expect that software development should bring me joy and fulfillment, not frustration and sorrow. That’s the moment I start to think that if my system was built the right way, every feature should be replaceable. I don’t have to bang my head into finding a perfect solution for a functionality, that will probably be replaced in the future. &lt;/p&gt;  &lt;p&gt;Ok, so what I really need to take care of is that the generated code is isolated enough so other parts of the system don’t have direct dependency on it, but rather on a contract the generated code implements. Maybe a smarter person will find a solution for my problem, and they usually do. At that time I’ll be able to end my unpleasant relation with the code generator, and look behind and smile.&lt;/p&gt;&lt;p&gt;Resources&lt;/p&gt;&lt;p&gt;http://c2.com/cgi/wiki?CodeGenerationIsaDesignSmell&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-8787580892288314855?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/8787580892288314855/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=8787580892288314855' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8787580892288314855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8787580892288314855'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/08/code-generation-is-bad-mkay.html' title='Code Generation Is Bad, M’kay?'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-220499989566978278</id><published>2008-07-23T03:56:00.001-07:00</published><updated>2008-07-31T03:35:48.887-07:00</updated><title type='text'>The Evils of Shared Check Out</title><content type='html'>&lt;p&gt;I won’t discuss the obvious what-do-you-do-when-somebody-else-checked-in-before-you-and-now-you’ve-ended-up-resolving-the-conflicts. I think there are more subtle motives why the version control shared check out has negative impact on modern software development.&lt;/p&gt;  &lt;p&gt;I believe that the shared check out feature of most source control system (svn, cvs, tfs) originated in a time when developers worked on huge code files, when solving one bug meant making adjustments in more than one of these monstrosities at the same moment. In a time of stone age development tools, when modern programming concepts like OOP and FP were in still in the realm of academia and of obscure languages.&lt;/p&gt;  &lt;p&gt;The tools and languages evolved, but the way they were used had its own inertia, based on human habit and familiarity with a way of “doing things”. Forget about &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;one class - one concern&lt;/a&gt;, some people are still struggling with one function – one concern.&lt;/p&gt;  &lt;p&gt;The conclusion is that if you are aware of a couple of development techniques, there will be no need for shared check out. One class should be modified for only one reason, so two people don’t have to edit it at the same time.&lt;/p&gt;  &lt;p&gt;Of course there are counter examples. I already hear people shouting “configuration files”, “generated code files” etc. Those are exceptions and at the same time, they are not. If you’re willing to break the structure into small, manageable parts, you’ll find a solution for them. And if you really need to store many things into one file, be sure to set rules for how people should edit it, so they know how to not get into trouble. This is a similar problem to using only pure functional programming. FP is great, but you’ll need to modify state sometime: make sure you’re doing it in a standard, isolated way, so when a problem arises you’ll know what you’re dealing with.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-220499989566978278?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/220499989566978278/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=220499989566978278' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/220499989566978278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/220499989566978278'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/07/evils-of-shared-check-out.html' title='The Evils of Shared Check Out'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-306653472013677365</id><published>2008-07-22T23:03:00.000-07:00</published><updated>2008-07-22T23:20:25.396-07:00</updated><title type='text'>Why You Should Write Your Own O/R Mapper ... Or At Least Try</title><content type='html'>Because you will not use it. But in the process you'll probably learn a lot of things about what a data access layer is. And more important, you'll be able to judge the existing O/R mappers and chose the one that fits most of your needs.&lt;br /&gt;&lt;br /&gt;The down side is that the period of time before you choose to "upgrade" to an already existing solution will seem a waste, and all the code you've written must be thrown away. That won't be an issue if you keep in mind that things are replaceable and if you build a loosely coupled designed so components, like the data access layer, can be replaced, almost, effortless.&lt;br /&gt;&lt;br /&gt;This pattern applies to other general "patterns", like dependency injection containers. Hands on experience with their "entrails" should give you a better understanding of how they work, and a better appreciation of the ones that are already available. And chances are you've already tried to build something similar but never knew exactly what you wanted, or what the big picture of the solution is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-306653472013677365?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/306653472013677365/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=306653472013677365' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/306653472013677365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/306653472013677365'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/07/why-you-should-write-your-own-or-mapper.html' title='Why You Should Write Your Own O/R Mapper ... Or At Least Try'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-5965297021611694531</id><published>2008-07-18T06:46:00.000-07:00</published><updated>2008-07-19T09:33:40.287-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dal'/><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>Nice Design Example for a Simple Data Access Layer</title><content type='html'>If you are in the process of implementing a small data centric application, you'll probably need to write some data access code. I've recently stumbled upon &lt;a href="http://www.lostechies.com"&gt;Los Techies&lt;/a&gt;, which is a wonderful resource for good programming practices. I especially enjoyed Jimmy Bogard's series on the problem of &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separation of concerns&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The series is centered towards refactoring an existing solution to a better design, employing well known patterns and practices. But the interesting part is that at the end the result is a nice blue print for a general data access layer based on Linq. And a really good start point if you're trying to build one.&lt;br /&gt;&lt;br /&gt;Below are links for the six parts of the series:&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/06/17/separation-of-concerns-how-not-to-do-it.aspx"&gt;Separation of Concerns - how not to do it&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/06/19/separation-of-concerns-by-example-part-1.aspx"&gt;Separation of Concerns by example: Part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/06/24/separation-of-concerns-by-example-part-2.aspx"&gt;Separation of Concerns by example: Part 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/06/26/separation-of-concerns-by-example-part-3.aspx"&gt;Separation of Concerns by example: Part 3&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/10/separation-of-concerns-by-example-part-4.aspx"&gt;Separation of Concerns by example: Part 4&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/17/separation-of-concerns-by-example-part-5.aspx"&gt;Separation of Concerns by example: Part 5&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-5965297021611694531?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/5965297021611694531/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=5965297021611694531' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/5965297021611694531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/5965297021611694531'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/07/nice-design-example-for-simple-data.html' title='Nice Design Example for a Simple Data Access Layer'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-1651470775150859761</id><published>2008-07-17T00:43:00.000-07:00</published><updated>2008-07-17T01:06:06.495-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server ce'/><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>Linq to SQL Server CE and uniqueidentifier columns</title><content type='html'>There will be a couple of issues if you you try to use linq to sql with a SQL Server CE database. First of all the VS2008 designer doesn't allow adding tables from this type of database. The solution is to use the SqlMetal command line tool in order to generate the dbml or the code file (see &lt;a href="http://blogs.msdn.com/sqlservercompact/archive/2007/08/21/linq-with-sql-server-compact-a-ka-dlinq-over-sql-ce.aspx"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The second issue is that uniqueidentifier columns with the rowguid property will not work. More precisely, they will not autogenerate a value upon inserting a new row. Setting the column property to IsDbGenerated in the dbml mapping file is even worst: it will crash the insert operation. There is a workaround for this problem: in the partial class of the respective table entity, create the partial method "OnCreate" and manually set a new Guid for the new record: &lt;br /&gt;&lt;br /&gt;partial void OnCreated()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ID == Guid.Empty) ID = Guid.NewGuid();&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-1651470775150859761?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/1651470775150859761/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=1651470775150859761' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1651470775150859761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1651470775150859761'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2008/07/linq-to-sql-server-ce-and.html' title='Linq to SQL Server CE and uniqueidentifier columns'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-623540992583076686</id><published>2007-12-03T11:35:00.001-08:00</published><updated>2007-12-03T11:54:53.494-08:00</updated><title type='text'>Implementing a Double Linked List in C# - part III</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Welcome to the third part of the series on implementing a double linked list. It is now time to finalize the basic functions of the list, as well as some extra helper functions. The latter have the purpose of easing the use of the list for its users.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In this episode we'll cover the following:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Delegate some of the concerns of the list to its nodes;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Implement the IEnumerable interface, and the associate iterator;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add a bit of "closure" to our list.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Removing items from the list&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;Preamble&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The main difference between our implementation of the doubly linked list and &lt;a href="http://msdn2.microsoft.com/en-us/library/he2s3bh7.aspx"&gt;the one provided by the .Net framework&lt;/a&gt;, is in the accessibility of data. While the .Net framework version exposes the data through the nodes containing it, we, on the other hand, expose it directly. This might be a shortcoming in terms of flexibility for navigating locally in the list. But the benefits come in form of structural integrity of the list, while permitting low level alteration of the structure of the list, and a better user experience in terms of accessing the data. What I mean by keeping control over the structural integrity of the list is that the consumer of the list can't make modifications that could break the chain of references or desynchronize the count of nodes, but the list can make modifications at that level internally. Of course these low level operations are also available to the inheritors of the list.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;Revisiting the Node Class&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Until now we've managed to ignore the Node class, but she "feels" that and tells us: "Listen, I'm pretty good at holding hands (references) with my left and right neighbors, so let me add new neighbor nodes as well as remove myself from the list". So we delegate to the Node class the concern of "keeping up references" during the operation of the list.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Adding a neighbor to the left of a node, means that we have to change:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;the reference of the original left node to its right node, to the new node;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;the reference &lt;strong&gt;to&lt;/strong&gt; the original left node, to the new node;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;the reference of the new node's left node, to the original left node;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;the reference of the new node's right node to the current node.&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;public Node&amp;lt;T&amp;gt; EnchainBefore(T item)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node&amp;lt;T&amp;gt; node = new Node&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.Data = item;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.Previous = Previous;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.Next = this;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Previous.Next = node;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Previous = node;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return node;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Removing the current node means we have to make its two neighbors reference each other:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public void RemoveFromChain()&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Previous.Next = Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next.Previous = Previous;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;Implementing the IEnumberable Interface&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The interesting part is not implementing the IEnumerable interface, but the IEnumerator. The twist is that the enumerator must "enumerate" through the list in two directions: forward as well as backward. Essentially the iterator will follow the chain of references starting with the left sentinel and ending with the right sentinel for forward enumerating. The iterator will go the other way around for backward iteration. This logic is embodied into the MoveNext method:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public bool MoveNext()&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (forwardDirection)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current = current.Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return current != rightSentinel;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current = current.Previous;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return current != leftSentinel;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The rest of the code is just plumbing and we shall not go over it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;A Little Bit of Closure&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We need a way of applying some function to the list of nodes. The process must be controled by the function, meaning that the function can dictate when to stop the process.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Introducing &lt;a href="http://msdn2.microsoft.com/en-us/library/bfcke1bz.aspx"&gt;the predicate&lt;/a&gt;. The predicate is a delegate with one generic parameter, which returns a boolean value. We could have built our own delegate, and in one way it would have been better, because we are abusing the purpose of the predicate as intended by its creators. But why reinvent the wheel when it's already there.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So let's define the Apply method, which applies a predicate received as parameter to each node, as long as the predicate evaluates to (returns) true and there are still items in the list:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Public virtual void Apply(Predicate&amp;lt;T&amp;gt; predicate)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node&amp;lt;T&amp;gt; node = leftSentinel.Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (node != rightSentinel &amp;amp;&amp;amp; predicate(node.Data))&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node = node.Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Removing items from the list can be easily implemented by using the Apply method. What I intend to do is iterate through the list as long as the current node does not contain the value we are trying to remove, and when we find it we'll ask the containing node to remove itself from the list and stop the iteration:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Apply(delegate(Node&amp;lt;T&amp;gt; node)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (item.Equals(node.Data))&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.RemoveFromChain();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count--;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;});&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Another method that coud use the help of the predicate is the Add method. This way we could make the items beig added to the list obey certain rules:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public virtual void Add(T item, Predicate&amp;lt;T&amp;gt; check)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node&amp;lt;T&amp;gt; node = leftSentinel.Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (node != rightSentinel &amp;amp;&amp;amp; !check(node.Data))&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node = node.Next;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AddBefore(node, item);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Now we have to tools to implement an ordered list:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public class SortedList : DoubleLinkedList&amp;lt;int&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public override void Add(int item)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Add(item, delegate (int data)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return data &amp;lt; item;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;That's all for this episode. Remember you can find the source code &lt;a href="http://learning-dot-net.googlecode.com/svn/trunk/%20learning-dot-net/CodeLibrary/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-623540992583076686?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/623540992583076686/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=623540992583076686' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/623540992583076686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/623540992583076686'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2007/12/implementing-double-linked-list-in-c.html' title='Implementing a Double Linked List in C# - part III'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-8101359051829454435</id><published>2007-12-01T00:53:00.000-08:00</published><updated>2007-12-01T01:03:33.862-08:00</updated><title type='text'>Creating a Double Linked List in C# - Intermezzo</title><content type='html'>Day by day I am amazed by Google's other services, besides web searching. One of the useful collaboration services offered by Google is &lt;a href="http://code.google.com/"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;a&gt;Google Code&lt;/a&gt;. It is a free service for project hosting, which provides SVN version control.&lt;br /&gt;&lt;br /&gt;You can now find the source code for the double linked list series at &lt;a href="http://learning-dot-net.googlecode.com/svn/trunk/%20learning-dot-net/CodeLibrary/"&gt;this&lt;/a&gt; location.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-8101359051829454435?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/8101359051829454435/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=8101359051829454435' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8101359051829454435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/8101359051829454435'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2007/12/creating-double-linked-list-in-c.html' title='Creating a Double Linked List in C# - Intermezzo'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-1958058548290042720</id><published>2007-11-29T06:57:00.001-08:00</published><updated>2007-11-29T06:59:20.144-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vs2008'/><title type='text'>Headache Installing Visual Studio 2008</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Last night I've tried to install Visual Studio ‚Orcas' RTM, but the setup kept crashing at the fisrt step of the installation (installation of the 3.5 framework). Digging into the setup log files I've traced the problem to the installation of the 3.0 framework  SP1. After some trials and misses (I've even uninstalled the MacAfee antivirus), I've downloaded the framework 3.5 setup &lt;a href="http://download.microsoft.com/download/6/0/f/60fc5854-3cb8-4892-b6db-bd4f42510f28/dotnetfx35.exe"&gt;redistributable&lt;/a&gt; (the full install package). The setup went flawlessly, and after it ended I was able to install the new Visual Studio.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I hope this information will help someone in need.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-1958058548290042720?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/1958058548290042720/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=1958058548290042720' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1958058548290042720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/1958058548290042720'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2007/11/headache-installing-visual-studio-2008.html' title='Headache Installing Visual Studio 2008'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-2528602189681170479</id><published>2007-11-28T12:51:00.001-08:00</published><updated>2007-11-28T13:15:33.380-08:00</updated><title type='text'>Implementing a Double Linked List in C# - part II</title><content type='html'>&lt;span xmlns=""  style="font-size:100%;"&gt;&lt;p&gt;In the &lt;a href="http://learning-dot-net.blogspot.com/2007/11/first-post-implementing-double-linked.html"&gt;previous post&lt;/a&gt; we've discussed the domain and the requirements of an implementation of a double linked list. It is now time descend the ladder of abstraction to the level where we can construct an usable artifact.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We'll start by analyzing the domain description and requirements, as we try to synthesize some sort of blueprint for the implementation. Right from the beginning we discover our two main entities: the list, and the nodes. It's pretty obvious we'll have different classes for each of them. Let's begin with the nodes.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The node has two major concerns: it has to hold data, and it has to retain references to it's left and right neighbors. As we've decided that any data can be stored into our list, and presuming the users of the list are kind enough to group multiple fields of data into types, we can make our nodes generic. Anything else is not important at this time.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;On the other hand, the list has a bit more concerns. First of all, it has to hold some reference to the data. This is done by the means of the two sentinels. When a list is created, the sentinels hold a reference with each other. As nodes are inserted the references are changed, in such a way as to form a chain o references starting form the left sentinel, and ending with the right sentinel.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The list also has to know the number of nodes stored in the list (excluding the sentinels). We have to do this, without counting the nodes every time this value will be needed. This implies that we must control the process of altering the structure of the list in order to keep an updated count of its elements.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The main source of errors, as far as we are concerned at the moment, are boundary crossings. This can be easily solved by checking the value of received indexes, and throwing the appropriate exceptions.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;As we have decided that the list must behave as a collection, it is time to decide on an interface that we'll implement, in order to provide the users of the list with a familiar experience. Searching the MSDN documentation, the IList&amp;lt;T&amp;gt; springs into attention, as it covers most of our needs. Actually, all the necessary functionality of the list will come from implementing this interface. Any other added functionality will only have the purpose of easing the use of the list.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;At this moment we can start sketching the implementation of the list. Take note that the comments and documentation were removed for the sake of brevity.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The Node class is short and self explanatory:&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; T Data;&lt;br /&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; Previous;&lt;br /&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; Next;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Next we start constructing the list:&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;DoubleLinkedList&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: rgb(43, 145, 175);"&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt; count;&lt;br /&gt;&lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:blue;"&gt;readonly &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; leftSentinel;&lt;br /&gt;&lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:blue;"&gt;readonly &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; rightSentinel;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The sentinels and node count will be initialized in the constructor. Remember that the list starts with the two sentinels referencing each other:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; DoubleLinkedList()&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;leftSentinel = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;        rightSentinel = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;        leftSentinel.Next = rightSentinel;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;rightSentinel.Previous = leftSentinel;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span xmlns=""&gt;&lt;span style="font-family:Arial;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;        count = 0;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The insert algorithm works in the following steps:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Check boundaries.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Search the n'th node. If there are no nodes, or the specified index is next to the last existing node, return the right sentinel.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Insert the new value into a new node between the node found above, and its left neighbor.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Increment the node count.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We will separate the last two steps of the algorithm into a helper method, AddBefore, as we will use them in another insert method, which will add an item directly at the end of the list.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; AddBefore(&lt;span style="color: rgb(43, 145, 175);"&gt;Node &lt;/span&gt;&amp;lt;T&amp;gt; node, T item)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; newNode = &lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br /&gt;newNode.Next = node;&lt;br /&gt;newNode.Previous = newNode.Previous;&lt;br /&gt;newNode.Data = item;&lt;br /&gt;node.Previous.Next = newNode;&lt;br /&gt;node.Previous = newNode;&lt;br /&gt;count++;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The search method can be reused in some other cases(item retrieval and removal), so we'll move the boundary check inside it:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; Find(&lt;span style="color:blue;"&gt;int&lt;/span&gt; index)&lt;br /&gt;{&lt;br /&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (index &amp;lt; 0 || index &amp;gt;= count)&lt;br /&gt;{&lt;br /&gt;&lt;span style="color:blue;"&gt;throw &lt;/span&gt;&lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ArgumentOutOfRangeException&lt;/span&gt;(&lt;span style="color: rgb(163, 21, 21);"&gt;"index"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;        &lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; currentNode = rightSentinel.Next;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;        &lt;span style="color:blue;"&gt;while&lt;/span&gt; (index &amp;gt; 0)&lt;br /&gt;{&lt;br /&gt;currentNode = currentNode.Next;&lt;br /&gt;index--;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;        &lt;span style="color:blue;"&gt;return&lt;/span&gt; currentNode;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now we can finish the implementation of the two insert methods:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; Insert(&lt;span style="color:blue;"&gt;int&lt;/span&gt; index, T item)&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;Node&lt;/span&gt;&amp;lt;T&amp;gt; nextNode = index == count ?&lt;br /&gt;rightSentinel : Find(index);&lt;br /&gt;AddBefore(nextNode, item);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; Add(T item)&lt;br /&gt;{&lt;br /&gt;AddBefore(rightSentinel, item);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Unfortunately, it seems that the posts in this series are getting longer than expected, so I'll have continue the implementation on the next episode.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;P.S.: As I've mentioned in the first post, additional requirements will be specified en route:&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span xmlns=""  style="font-size:100%;"&gt;&lt;p&gt;thread safety;&lt;/p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span xmlns=""  style="font-size:100%;"&gt;&lt;p&gt;serialization;&lt;/p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span xmlns=""  style="font-size:100%;"&gt;&lt;p&gt;performance;&lt;/p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span xmlns=""  style="font-size:100%;"&gt;&lt;p&gt;implement the filter, map and reduce algorithms.&lt;/p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-2528602189681170479?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/2528602189681170479/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=2528602189681170479' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/2528602189681170479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/2528602189681170479'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2007/11/implementing-double-linked-list-in-c.html' title='Implementing a Double Linked List in C# - part II'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-928795371668874325.post-6010145909429905684</id><published>2007-11-27T08:41:00.001-08:00</published><updated>2007-11-27T11:10:12.493-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='basics'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>First post: Implementing a Double Linked List in C# - part I</title><content type='html'>&lt;div&gt;&lt;span style="font-size:130%;"&gt;Hello World!&lt;/span&gt;&lt;span xmlns=""&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;The first blog post is dedicated to a basic, but important data structure: &lt;a href="http://en.wikipedia.org/wiki/Linked_list"&gt;the double linked list&lt;/a&gt;. It is intended to be an academic exercise, rather than a practical one.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Acknowledgement: I'm not a native English speaker, and despite Word's spell &amp;amp; grammar checker, please indulge my language faults. Still, constructive criticism is appreciated!&lt;/p&gt;&lt;p&gt;I've separated the plan of this project into 3 parts: the description of the domain of the problem at hand, definition of the requirements and, finally, the design. The article will be separated into two parts, leaving the design into the second part. A third, bonus, part might be included into the series. &lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;First let's describe the DOMAIN of the problem&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Wikipedia comes to our help with a definition of a double linked list (approx.): the (double) linked list is a &lt;a href="http://en.wikipedia.org/wiki/Data_structure"&gt;data structure&lt;/a&gt;. It consists of a sequence of nodes, each containing arbitrary data fields and two references, to the next and previous nodes.&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5137568804622356786" style="margin: 0px auto 10px; display: block; text-align: center;" alt="" src="http://bp1.blogger.com/_uHqE2vLjG9A/R0xPm5ik0TI/AAAAAAAAAAc/vu_4Czwym3k/s400/double+linked+list.png" border="0" /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Some implementations provide two special nodes, called &lt;a href="http://en.wikipedia.org/wiki/Sentinel_node"&gt;sentinels&lt;/a&gt;. These nodes are placed at the beginning and end of the list, and do not contain any data. Their purpose is to provide a uniform way of treating the insertion and removal of standard nodes.&lt;br /&gt;&lt;/p&gt;The main purpose of the linked lists is to be a base for other data structures, like stacks and queues. The main benefit over conventional &lt;a href="http://en.wikipedia.org/wiki/Array"&gt;arrays&lt;/a&gt; is that they support the insertion and removal of elements, without creating a new instance of the structure. The advantage of the double linked list over other linked lists is that they can be traversed backwards as well as forwards.&lt;br /&gt;&lt;p&gt;In the .Net world, support for sequential data structures, besides arrays, is provided through collections. Collections are defined by a set of interfaces, which provide a uniform set of patterns for manipulating collections, and the concrete implementations of several types of collections: lists, dictionaries, hash tables and so on.&lt;br /&gt;&lt;/p&gt;Another feature of the .Net framework, available from the v2.0 version, is generics. They enable the user to generalize the definition of types, by leaving a part of the implementation of the type to be provided when the type will be consumed. This will enable the list to contain any type of data, as long as it is of the same type (of course, a collection of &lt;strong&gt;object&lt;/strong&gt; objects will hold &lt;strong&gt;any&lt;/strong&gt; data, but that's not the point). &lt;p&gt;&lt;span style="font-size:130%;"&gt;REQUIREMENTS prescription&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The requirements for our double linked list represent what is expected from it. They fall into two categories, what is expected from a double linked list, and what is expected from a collection. The two categories are overlapping. The list of requirements is by no means exhaustive, and might be improved in the course of the implementation.&lt;br /&gt;&lt;/p&gt;A double linked list should: &lt;ul style="margin-left: 54pt;"&gt;&lt;li&gt;Provide storage for data into nodes. &lt;/li&gt;&lt;li&gt;Permit the insertion of new node(s) when the list is empty as well as when the list has existing items. &lt;/li&gt;&lt;li&gt;Permit the removal of a specified item. &lt;/li&gt;&lt;li&gt;Return the number of existing nodes. &lt;/li&gt;&lt;li&gt;Return a specific node. &lt;/li&gt;&lt;li&gt;Provide a consistent mechanism for dealing with errors. &lt;/li&gt;&lt;li&gt;Provide the next and previous nodes for a given node. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A collection should:&lt;br /&gt;&lt;/p&gt;&lt;ul style="margin-left: 54pt;"&gt;&lt;li&gt;Provide for data into items. &lt;/li&gt;&lt;li&gt;Permit the addition of new item(s). &lt;/li&gt;&lt;li&gt;Permit the removal of item(s). &lt;/li&gt;&lt;li&gt;Iterate over its values. &lt;/li&gt;&lt;li&gt;Permit the retrieval of a specified item. &lt;/li&gt;&lt;li&gt;Permit the alteration of the order of its item (ex. Sorting). &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This ends the first two parts of our plan. Next time we will see how we can get from a list o requirements to an usable artifact.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/928795371668874325-6010145909429905684?l=learning-dot-net.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://learning-dot-net.blogspot.com/feeds/6010145909429905684/comments/default' title='Postare comentarii'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=928795371668874325&amp;postID=6010145909429905684' title='0 comentarii'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/6010145909429905684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/928795371668874325/posts/default/6010145909429905684'/><link rel='alternate' type='text/html' href='http://learning-dot-net.blogspot.com/2007/11/first-post-implementing-double-linked.html' title='First post: Implementing a Double Linked List in C# - part I'/><author><name>M</name><uri>http://www.blogger.com/profile/07267505085325455448</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_uHqE2vLjG9A/R0xPm5ik0TI/AAAAAAAAAAc/vu_4Czwym3k/s72-c/double+linked+list.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
