Monday, October 17, 2011

Story Points vs Hours

In the Agile methods many suggest using something called Story Points instead of time when estimating the time a task would require for implementation. Rather than saying that it will take two days they would say it takes, for example, four Story Points. They then track what is called Velocity to see how many Story Points the team can complete in a week and suggest that about that many Points, let's say 20, is what the team can implement in a week.

I find this very awkward. Is it just a technique to hide the hours? Because, after all, most of us are still payed by the hour, and we also want to have an idea about the dates we might expect things to be finished. Story Points take this away. What would you say to the carpenter who you pay by the hour if he said he will have your bathroom done in 80 Story Points? He expects to burn about 20 Story Points per week, he adds. I would think he was a freak!

The only reasonable reason I find to use Story Points instead of Hours (or Days) is the notion that different coders may need different amounts of time to solve a task. With Story Points two coders may estimate a task to, for instance, four, while using days one might need two days and the other three days. That would implicitly say that coders are linear to each other in skill difference, since for the equation to sum up you'd need them to agree that the next task, estimated to two Story Points, would take the former one day and the later one and a half. Something I strongly disbelieve.

The more unreasonable reason is that as estimates are hard to do, you put a metric on them that is hard to understand to get away with them easier. If you say that something will take three days it's easy to see if you were right, while estimating it will take three Story Points will keep you safe. Who are to say how long a Story Point is? Hardcore agilists laughs at such a silly question.

I guess I'm missing something, but I have a hard time seeing the Point of Story Points. Feel free to enlighten me using the comment field!

p.s. I've never tried Story Points, so I might be totally wrong. It may be Gods gift to software developers. d.s.

Friday, October 14, 2011

EPiServer 6.0 compare bug

I've spent most of today, and a couple of hours yesterday, to figure out a weird problem with the function that allow you to compare two versions of a page in the EPiServer 6.0 edit mode. As soon as I clicked the compare button I got the YSOD telling me that a NullReferenceException was thrown from the method ComputeVaryCacheKey deep down in the ASP.NET rendering.

I hooked up the debugger and found that everything seemed to be in order. Altho, we had a few customized renderings in the chain so I started by disabling them one by one to find the cause. Once they were all removed I still had the problem tho, so I started on another track. Next thing I did was to look at the output caching used. Starting with simplifying the GetVaryByCustomString method in Global.asax so it should be almost impossible to have a problem there didn't help. Next thing was removing the OutputCache directives on my controls one by one and in the end - bingo! When the last OutputCache directive was removed I got some other error instead from the compare button.

So it comes down to that adding an OutputCache directive with VaryByCustom would make that ComputeVaryCacheKey crash when trying to compare two pages... I really need my output caching, but for the sake of coming to the bottom of this I left them out looking at the new error message. Maybe it could be the root course and if that was solved I could add the caching again?

The new error said "']]>' is not allowed within '<!CDATA[' blocks" or something like that. Well, fair enough. I looked at the source of the page being compared and there were a couple of CDATA blocks in the scripts generated by ASP.NET but none of them seemed to be malformed. At this point I decided to fire up another EPiServer site and see if the CDATA blocks looked the same, and if they would like being compared on that site. The CDATA blocks looked the same and they did like being compared in that context... Odd. Here I decided to add the OutputCache directive to a control on this site and see if it would work here - And it DID! There was a difference tho - this site was build on EPiServer 6 R2.

At this point I contacted the EPiServer support that within an hour reported back to me that this was a known bug in EPiServer 6.0 that had been solved in R2. The general advise was to upgrade to R2, but in case I couldn't do that I also was send a custom "CompareProvider" written by the support guy that should work with 6.0. So I put that in the bin directory, configured the site as he instructed me for activating this new provider and gave it a go. I still got that "']]>' is not allowed within '<!CDATA[' blocks"... but the good part was that I could add my OutputCache directives again and still getting that error!

Well, now at least I had my own custom code running closer to the problem. I reflected the provider that the support guy sent me and it was only one class. I copied the code to a class in my own project allowing me to set a breakpoint in there. When I had the code it was also obvious that the CDATA issue was addressed in it, but apparently it didn't address the problem well enough. I started by just removing the CDATA start and end block from the input to the compare function and then it worked! Or well, kind of. It didn't seem to have support for css being added with @import so I got a comparison of the page without styling... still, it was the best yet!

Hacking away even more I hardcoded an addition of the primary css to the source, and now it looked good too! A bit too hacky tho, for my taste, it struck me that I could reflect the source from the EPiServer 6 R2 binaries to see how they solved it there. The first line in that version was the Obsolete attribute - use "HtmlDiffProvider" instead it said. Wonder if that works with 6.0 I pondered, and reflected that source and added it to my project next to the code from the support guy. Then executed... and boom! That first NullReferenceException from the caching again! Dang. But, with the code from these two providers I managed to create a one provider that worked fine with EPiServer 6.0!

During this entire episode I did of course do a lot of searching on the web for guidance... getting none! Hence I decided to write this post to help the next person that enters this moat. It's not your fault! It's a bug in the platform! Stop wasting your time looking for problems in your project, and instead add your own CompareProvider.