Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 10 | Comments: 37

filter by tags archive

CodePlex, TFS and Subversion

time to read 2 min | 227 words

Interestingly enough, Subversion support is the most requested feature for CodePlex. I suggest reading the discussion, it is very interesting. The major points against TFS and for SVN seems to be:

  • Weak offline access support
  • No patching
  • No anonymous access

The points above makes TFS a poor choice for an OSS project, which requires all three (but especially anonymous access and patching). For corporate scenarios, there is another advantage to Subversion over TFS. Subversion is a Zero Friction tool, TFS is anything but. A memorable quote can be found here:

Source control is a utility.  It's a tool.  It should help you do what you need and stay out of the way when it's not.  I love developer tools, which is probably why so many of my open source projects involve building new ones, but I firmly believe that if you have to ever think about the tool then the tool is not doing it's job.

CodePlex SNAFU

time to read 2 min | 231 words

I found this mostly by accident, but it looks like a few weeks ago CodePlex has lost the source code for some of the projects hosted on the site. I would like to address the part about "free means no guarantees" that came up in the post:

CodePlex is a free service.  They've provided complete source code hosting along with one heck of a website and never asked for a cent in return.  So, I really can't hold it against them.

I would.

Regardless of the legalese involved. I have certain expectations from such a service. And having reliable backups is one of those. I don't care if it is free, SourceForge had ensured that there wouldn't be much point in charging for source control for open source projects, so I am not surprised that it is offered as a free service.

CodePlex's stated goals are to host and support open source projects, I assume that it is also meant to show off Microsoft's technologies. That is nice, except that the fact that a project is OSS doesn't mean that its source is not mission critical data that really should be safe.

Passonaite at Team System? Depending on which direction

time to read 1 min | 118 words

Roy is hiring Team System people, I was amused by the post title:

We're hiring Team System People - Are you passionate enough?

The answer it my case would be "Yes, to avoid it" :-)

And the reason would be that it absoutely not a zero friction tool.

As long as we are talking about Roy, he posted a poll about mocking frameworks for his upcoming book about unit testing. I am impressed by the amount of votes (and the comments) for Rhino Mocks, thanks.

A developer so retarded

time to read 2 min | 294 words

I just run into this post, that talks about a presentation about mocking, and included this statement (about using Rhino Mocks):

I once heard a story about a developer so retarded that he and his team spent a good amount of time trying to debug a mock only to find out that he forgot about ReplayAll()*.  Who hires guys like that anyway?

That developer, it would be me, and it can happens quite often. And I wrote the tool, so I should know what I am doing when I am using it.

Stuff happens, it is easy to forget a line of code and waste some time as a consequences. The most common sentence from me when I am developing is "Oh, man, I am so stupid that I did that".

To give an example that would be a bit easier to grok, what is wrong with this code:

using(TransactionScope scope = new TransactionScope())
{
   Appointment[] appointments = SpanOnCalendar(appointmentSepc, DateTime.Today, DateTime.Today.AddDays(7));
   foreach(Appointment appointment in appointments)
       appointment.Save();
}

 

Paged data + Count(*) with NHibernate: The really easy way!

time to read 15 min | 2877 words

Christian Maslen ping me about this article, which shows how to use NHibernate to execute multiply statements in a single round trip. Christian suggest a much neater solution:

SELECT  C.*,

        COUNT(*) OVER() AS TotalRows

FROM    Customers AS C

I was sure that it wouldn't work, but it does, and I consider this extremely cool. So, now I needed to figure out how to make NHibernate understand this. There are several options, but extending HQL is simplest one in this case.

NHibernate uses a dialect to let bridge the gap between Hibernate Query Language with is a database agnostics relational/object querying lanaguge. This allows NHibernate to work against multiply databases easily. The key here is that one of the extension points that NHibernate is offering is the ability to define your own custom functions, which can translate to arbitrary SQL.

In this case, here is the query that I want to end up with:

select b, rowcount() from Blog b

Here is the dialect extension:

public class CustomFunctionsMsSql2005Dialect : MsSql2005Dialect

{

       public CustomFunctionsMsSql2005Dialect()

       {

              RegisterFunction("rowcount", new NoArgSQLFunction("count(*) over",

                     NHibernateUtil.Int32, true));

       }

}

We register a new function, called rowcount, which translate to "count(*) over" string. The final "()" are added by NHibernate when rendering the function. Now, we need to register our new dialect:

<property name="hibernate.dialect">MyBlog.Console.CustomFunctionsMsSql2005Dialect, Blog.Console</property>

And here is the code we end up with:

IList list = session.CreateQuery("select b, rowcount() from Blog b")

              .SetFirstResult(5)

              .SetMaxResults(10)

              .List();

foreach (object[] tuple in list)

{

       System.Console.WriteLine("Entity: {0}", ((Blog)tuple[0]).Id);

       System.Console.WriteLine("Row Count: {0}", (int)tuple[1]);

}

The generated SQL is:

WITH query AS (

     SELECT TOP 15 ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__, 

          blog0_.Id as Id4_,

          blog0_.Title as Title4_,

          blog0_.Subtitle as Subtitle4_,

          blog0_.AllowsComments as AllowsCo4_4_,

          blog0_.CreatedAt as CreatedAt4_,

          blog0_.Id as x0_0_,

          count(*) over() as x1_0_

     from Blogs blog0_)

SELECT * FROM query

WHERE __hibernate_row_nr__ > 5

ORDER BY __hibernate_row_nr__

Oh, and thanks for Fabio Maulo for helping me figure out the correct usage of custom functions.

By foul moon

time to read 10 min | 1942 words

Because I know that I will need it...

# Not very accurate, but apperantly good enough for most purposes

# source: http://www.faqs.org/faqs/astronomy/faq/part3/section-15.html

def IsFullMoon(dateToCheck as date):

      two_digit_year as decimal = dateToCheck.Year - ((dateToCheck.Year/100)*100)

      remainder as decimal = two_digit_year %19

      if remainder > 9:

            remainder -= 19;

      phase as decimal = (remainder * 11) %30

      if dateToCheck.Month == 1:

            phase+=3

      elif dateToCheck.Month == 2:

            phase+=4

      else:

            phase+= dateToCheck.Month

      phase+=dateToCheck.Day

      if dateToCheck.Year < 2000:

            phase -= 4

      else:

            phase -= 8.3

      phase = phase % 30

      return 14.5 < phase and phase < 15.5

Expected usage:

if IsFullMoon(DateTime.Now):

      raise SqlException("""Transaction (Process ID 179) was deadlocked on lock resources with another
process and has been chosen as the deadlock victim. Rerun the transaction."""
)

Update: I am still struggling with the code for WasChickenSacrifised(), will be glad to get suggestions...

Open source and the programmer's dilemma

time to read 1 min | 170 words

Nick Carr is quoting an IEEE article about OSS Economics. I am going to respond to the article later, rigth now I wanted to comment on this piece:

Given the natural imbalance between employers and employees, this aspect of open source is likely to increase competition for jobs and drive down salaries.

I have one word to say to it, rubbish! I have stated it before, working on open source software means that you have credentials. There is nothing that speaks louder than code for developers. And experianced developers are worth quite a bit, regardless of their choice of platform or license.

This statement seems to assume that the only thing that separate developers from one another is prioprietry knowledge aquired in mystic rights at the dark of the moon.

MSDN vs. Google

time to read 3 min | 514 words

Here is a small experiment, I want to read the documentation for IDispatchMessageInspector

Just to give an idea, here is the wget output for this address:

wget http://msdn2.microsoft.com/en-us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx
--00:59:48--  http://msdn2.microsoft.com/en-us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx
           => `system.servicemodel.dispatcher.idispatchmessageinspector.aspx'
Resolving msdn2.microsoft.com... 207.46.16.251
Connecting to msdn2.microsoft.com|207.46.16.251|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 122,022 (119K) [text/html]

100%[========================================================>] 122,022        5.74K/s    ETA 00:00

01:00:12 (5.74 KB/s) - `system.servicemodel.dispatcher.idispatchmessageinspector.aspx' saved [122022/122022]

That is right, over a minute half a minute to download just the HTML content of a single page, over two minutes just to get the simplest page to load.

Let me contrast that with the comparable experience:

  • Go to google.com
    Load time: faster than I can measure
  • Put IDispatchMessageInspector and hit enter
    Load time: ~2 Seconds
  • Go to the first result's cached content
    Load time: ~7 seconds

You know what the real sad part is? The google approach is faster than locally installed MSDN!

Maintainability as a first level concern

time to read 2 min | 214 words

I have no idea how I missed this post from Anders Norås. It is talking about some of the problems in using traditional software factories (code-gen) vs. using smarter frameworks. It is a long read, but it is excellent.

Maintainability is the enabler of all the other "itities" of an architecture. Experience shows that typical EJB applications often was hard to maintain even if code generation made them easy to develop. The IDE driven code generation for EJB paved way for vendor lock-in.

The software factories of today will be part of Visual Studio "Orcas", but I would not count on this to lock users into the IDE and Microsoft Patterns & Practices way. Even with million-dollar investments in high-end application servers the enterprise Java community has largely moved from EJBs to light-weight frameworks. This has proven to be a economically healthy choice because of improved productivity and flexibility.

 

LINQ to SQL - Dynamically Constructing Queries - Um... No!

time to read 2 min | 336 words

Mike Taulty is talking about constructing queries dynamically in Linq to SQL. Sorry, but my response to that is Yuck! Here is the code that he shows:

  NorthwindDataContext ctx = new NorthwindDataContext("server=.;database=northwind");

   var query = from c in ctx.Customers
               where c.Country == "Germany"
               select c;

   if (RuntimeCriterionOneApplies()) 
   {
    query = from c in query
            where c.City == "Berlin"
            select c;
   }

   if (RuntimeCriterionTwoApplies())
   {
    query = from c in query
            where c.Orders.Sum(o => o.Freight) > 100
            select c;
   }

   foreach (Customer c in query)
   {
    Console.WriteLine(c.CustomerID);
   }

This is not constructing queries dynamically, it is choosing a query dynamically. This isn't what I talk about when I am talking about constructing a query dynamically. You can look here as what I consider a complex query that is being constructed dynamically.

Mike, how would you handle that scenario in Linq?

Update:  I really should pay more attention when I am reading the code. Sorry Mike, the code that you have will work for the scenario that I have. I don't think that the syntax is very elegant for this scenario, but it will work. I missed the "from q in query" and read is as if a new query were constructed in each if.

FUTURE POSTS

  1. Production postmortem: The case of the memory eater and high load - about one day from now
  2. Production postmortem: The case of the lying configuration file - 3 days from now
  3. Production postmortem: The industry at large - 4 days from now
  4. The insidious cost of allocations - 5 days from now
  5. Find the bug: The concurrent memory buster - 6 days from now

And 4 more posts are pending...

There are posts all the way to Sep 10, 2015

RECENT SERIES

  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    14 Aug 2015 - The case of the man in the middle
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats