This blog contains reflections and thoughts on my work as a software engineer

torsdag den 29. januar 2009

TDD and mocks

I just found a nice post on TDD and mocks / stubs written by Gabriel Schencker - if you want a thorough introduction to the subject of mocking his post is a good place to start. Check it out :o)

/ Regards K.

mandag den 26. januar 2009

SubSonic - day #2

Did you ever see this errormessage: "Can't find the SubSonicService section of the application config file" when trying to get your autogenerated Subsonic DAL to work across multiple projects? Well, I did - and I took the liberty to blog about my bad experiences after trying SubSonic for the first time. Today I decided to tinker a little with the sourcecode of the SubSonic project to see if I could get my ideal configuration scheme set up. My idea was to have a separate configuration file (subsonic.config) placed in the project together with your autogenerated code. Configuration stuff related to database belongs to the DAL layer, I believe, so that's where I would like it to place it physically. I would then add the configuration file to the projects needing dataaccess using the "Add as link" feature in Visual Studio. This way I would have only one configurationfile for my dataaccess which could be shared across multiple projects regardless of their nature (console apps, webapps etc).

I solved it within an hour or two - this is how it was done:

I downloaded the code and quickly discovered that the code basicly traverses the application directory for either web.config or app.config. Afterwards the ConfigurationManager is used to read the various sections into wrapper objects inheriting from System.Configuration.ConfigurationSection - nothing new here.

I decided to attack the DataService class, specifically the static method LoadProviders(). It generates a SubSonicSection class which wraps the SubSonicService section of your app.config or web.config. This is how the code looks:

 

public static void LoadProviders()

{
// Avoid claiming lock if providers are already loaded
if(defaultProvider == null)
{
lock(_lock)
{
// Do this again to make sure DefaultProvider is still null
if(defaultProvider == null)
{
//we allow for passing in a configuration section
//check to see if one's been passed in
if(section == null)
{
section = ConfigSectionSettings ?? (SubSonicSection)ConfigurationManager.GetSection(ConfigurationSectionName.SUB_SONIC_SERVICE);


//if it's still null, throw an exception
if (section == null)
throw new ConfigurationErrorsException("Can't find the SubSonicService section of the application config file");
}

...[snip]...
}
}
}
}


 



I modified it method to create a SubSonicSection based on the contents of subsonic.config if it had failed creating a section based on web/app.config:



 



public static void LoadProviders()



{
// Avoid claiming lock if providers are already loaded
if(defaultProvider == null)
{
lock(_lock)
{
// Do this again to make sure DefaultProvider is still null
if(defaultProvider == null)
{
//we allow for passing in a configuration section
//check to see if one's been passed in
if(section == null)
{
section = ConfigSectionSettings ?? (SubSonicSection)ConfigurationManager.GetSection(ConfigurationSectionName.SUB_SONIC_SERVICE);

if (section == null)
{
string configPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath, "subsonic.config");

if (!File.Exists(configPath))
throw new ConfigurationErrorsException(string.Format("Unable to read configuration file {0}", configPath));

var execfg = new ExeConfigurationFileMap();
execfg.ExeConfigFilename = configPath;
var cfg = ConfigurationManager.OpenMappedExeConfiguration(execfg, ConfigurationUserLevel.None);
section = (SubSonicSection)cfg.GetSection(ConfigurationSectionName.SUB_SONIC_SERVICE);
}

//if it's still null, throw an exception
if (section == null)
throw new ConfigurationErrorsException("Can't find the SubSonicService section of the application config file");
}

...[snip]...
}
}
}
}

I then created a subsonic.config resembling the following:







<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="SubSonicService" type="SubSonic.SubSonicSection, SubSonic" requirePermission="false"/>
</configSections>

<connectionStrings>
<add name="ExceptionLog" connectionString="Data Source=localhost\SQLExpress; Database=ExceptionLog; Integrated Security=true;"/>
</connectionStrings>

<SubSonicService defaultProvider="ExceptionLog">
<providers>
<clear/>
<add name="ExceptionLog" type="SubSonic.SqlDataProvider, SubSonic" connectionStringName="ExceptionLog" generatedNamespace="DataAccess"/>
</providers>
</SubSonicService>
</configuration>

...and placed it in my ErrorLoggerAPI project which contains all the autogenerated SubSonic DAL code in the folder DataAccess:







Untitled




Next to follow was to add the subsonic.config using Add As Link in my webproject - like this:







Untitled


Very important: Change the property "Copy to output directory" from "Do not copy" to "Copy when newer" on your linked copy of subsonic.config - otherwise it won't be copied into your buildfolder when you build your project and the following code will fail.









That's it! I now have complete separation between my web project and the corresponding storage working behind the scenes. The only dependency is the linked configuration file I named subsonic.config. When changes occur in my configuration (i.e. a database migration or relocation of the database server) I only have to alter the subsonic.config, rebuild the code in ErrorLoggerAPI and distribute the new subsonic.config to whatever application that's using it.


Last, but not less important: Since the configuration settings are now stored in a file called subsonic.config you will have to create a bat-file to execute the generation of your files. I haven't found a better way to do this so I created a file called deploy.bat and placed it in ErrorLoggerAPI:







Untitled



The Subsonic documentation (referring the command "sonic.exe help" from the command line)dictates that if you haven't got a web.config or an app.config you will have to provide the database and databasename in the arguments when calling sonic.exe. You can still point to a configuration file where the remaining SubSonic configuration stuff can be placed.


The final deploy.bat looks like this:







"%programfiles%\SubSonic\SubSonic 2.1 Final\SubCommander\sonic.exe" generate /out DataAccess /db ExceptionLog /server "localhost\SQLExpress" /config subsonic.config






Until next time... :o)







Regards K.

søndag den 25. januar 2009

ASP.Classic on IIS7 - the story

So - my encounter with Classic ASP on IIS7  goes like this:

I got a new server set up at home. I installed Windows 2008 Standard Server and mingled with it a bit to get used to it's new user interface etc.

It didn't take long for me to install Internet Information Server. I think it went quite well but I also knew that ASP.Classic websites appearently could cause a few headaches because of security and - well - because it's ASP Classic. Need I say more?

After that I just spent three hours of doing this: Making a simple "Hello world" ASP.Classic page work - like this one:

<%Response.Write("Hello world")%>


How hard could it be? I installed IIS, winged off the right checkboxes (ASP.Classic for one) and Next'ed my way through to "You've succesfully installed blablabla". I rebooted just to be sure that everything was running OK, opened Firefox, hit my webpage and got



403: Forbidden. Access denied



"Sure enough", I thought - "security stuff on ASP.Classic in an IIS7 world". I researched a bit and found numerous examples of people having trouble. So I set up an alternative AppPool - no luck, still 403 error. I checked ISAPI extensions - everything looked good. I tried enabling everything under Authentication - no luck. Actually I was starting to be a little worried until I discovered in Windows Explorer that my default.asp document was being recognized as a Text document. "That's a bit weird" I thought and a cold chill started to build up from the back of my neck and all of a sudden it became painfully clear to me that I just made the brainfart of the Millenium:



When I created default.asp I rightclicked in my webpage folder in Windows Explorer and created a new textfile called "default.asp". However - on my old Win2000 server (and every other machine I operate on) I always uncheck the "Hide extension for known file types"



Untitled 



Thit little, bleeding checkbox is enabled per default in every Windows installation there is - I know because I always turn it off whenever I get a chance to. This time I actually created a file called "default.asp.txt" and guess what? There isn't (and never will be) any default handler for .txt files in IIS7  so it threw 403 errors at me just like it was supposed to do - I just didn't have the brain to breathe for a while and brainstorm on the errormessage thrown at me. I even tried hitting the website with /default.asp because I thought there was something awry with the default extension handler and got this odd message telling me that "default.asp" didn't exist - but even that didn't make me think twice about my "This security IIS7 hell won't get me down" bruteforce problemsolving strategy.



It took me about 2 seconds to rename default.asp.txt to default.asp and a mere 6 to 8 seconds to uncheck the "Hide extension for known filetypes" checkbox. After that everything worked like a charm. Consider this a late New Years Eve Resolution: I promise I'll never mention this to anybody paying my monthly payroll.



Regards Kristian.

onsdag den 21. januar 2009

Subsonic - not so good enough

For a week or two I've been researching the market for ORM-tools. I know quite a few by name but never tried any of them except Linq2Sql - and with the change in strategy by Microsoft (they've decided to go with Entity Framework instead) it doesn't look like a choice for the future so I went looking for something else. And Entity Framework isn't one of them - for obvious reasons.

I have tried SubSonic on a project I've been working on for the last two evenings. I was thrilled after watching the screencast and made it work within an instant in a demo application I made while watching the video the second time.

So - I fired up a new VS solution, added a website project and another class library in which my DAL abstractions would live - like this:

image

And then I was soooo disappointed to learn that once I hit a method in ErrorLoggerAPI which encapsulates Subsonic controller classes I would still need to have a SubSonic section in the web.config of my ErrorLoggerWeb project! There is a workaround to this where you programmaticly initialize your connection but it requires extra work and all your SubSonic controller classes has to be modified to make this work. I wasn't exactly thrilled by this discovery - the maturity index dropped quite a lot uncovering this flaw (I call it a flaw - so sue me... I'm a bit grumpy right now)

Of course one could download the source files from the SubSonic project, make the changes and call it a day... Until a new version comes and the problem persists in the new version. Or one could contribute to the SubSonic project and solve the problem for the entire community for eternity. Or one could just get it off one's chest by writing on his blog and conclude that nothing never is as good as it seems. SubSonic looks promising and there might be a better way to solve this problem but it was a showstopper on my current project. I don't want to pollute my web.config file with configuration stuff about persistence - why should my website be concerned with issues like that? It should be handled by configuration stuff elsewhere - in business logic and persistence layers where stuff like that belongs.

Regards K.

onsdag den 14. januar 2009

How to resize IE with just a click of a button

I'm won't take credit for this one - but I nevertheless want to spread the word:

  • Create a shortcut in your IE Favorites or in you Links folder.
  • Rename this shortcut/favorite to "Resize Window to 1024x768".
  • Edit the properties of the shortcut and place the following line of javascript in the URL property.
    javascript:window.resizeTo(1024,768)
    Note:
    You will receive a warning prompt. Simply proceed.
  • Save the properties and then click your new favorite Resize Window to 1024x768.

    You should give Mark Wagner a pad on the shoulder next time you see him - :o)

    Regards K.

    P.S. - It only works if you have only a single tab open - nothing happens when multiple tabs are open at the same time


    UPDATE: Download the Internet Explorer 8 Beta II and use the bundled Developer Tools to resize your browser window - regardless of how many tabs are open.

    tirsdag den 13. januar 2009

    Teach yourself X in Y days

    Did you know it takes about 10 years to become good at something? Read the following paragraphs:
    You probably know them - "Teach yourself X in Y days" - let X be Java, C#, Webforms and Y could be anything ranging from 7 to 30 days.

    I read a post today on Coding Horror - you really should subscribe to his writings if you don't do already. He has quoted from Peter Norvigs "Teach yourself programming in Ten Years" - basicly, he says, it is old news that it takes time to become a superstar in anything:

    Researchers have shown it takes about ten years to develop expertise in any of a wide variety of areas, including chess playing, music composition, telegraph operation, painting, piano playing, swimming, tennis, and research in neuropsychology and topology. The key is
    deliberative practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability, trying it, analyzing your performance while and after doing it, and correcting any mistakes. Then repeat. And repeat again.

    There appear to be no real shortcuts: even Mozart, who was a musical prodigy at age 4, took 13 more years before he began to produce world-class music. The Beatles seemed to burst onto the scene with a string of #1 hits and an appearance on the Ed Sullivan show in 1964. But they had been playing small clubs in Liverpool and Hamburg since 1957, and while they had mass appeal early on, their first great critical success, Sgt. Peppers, was released in 1967.

    I don't know much about Norvig (I heard about him but never read anything) - I need to visit my favourite online book-pusher in the nearest future... :o)

    Regards K.

    P.S. - Actually I think this Mr. Norvig is a bit of a geek (a major one actually) - who would ever get a kick out of a "world's longest palindrome contest"?

    onsdag den 7. januar 2009

    Different roles in a SCRUM team - how to do?

    A few months ago we decided to extend our team with a new role - the design role. The reason for choosing to employ a designer rather than another serverside developer was to improve our ability to guide and reason our Product Owners about the layout and design of the systems we're working on. Being serverside guys the layout and design process incorporated the de-facto It's-Ugly-But-It-Works standards seen worldwide. So - a designer was employed in Mid-October and has worked with us on a project that began 1. of October.

    Today after a Sprint Planning One our new designer raised concerns about the stories we are to work on during the sprint in February. We realized that questions such as "What's the identity of this new website we're launching February 1st" had never been answered properly so the stories we created before the October sprint and up until today didn't reflect any thoughts about layout and graphics. What we had was a lot of functionality (a feed-reader, data-standards, a Lucene index for searching etc.) which reflected what the user was supposed to be able to retrieve... Not a single story about design of the markers on the Google-map which is a vital part of the new website. Nothing about what the logo should try to express or if the site should have a visual pattern or layout which would enable a user to recognize it as a subsite of our main website. It has resulted in our new designer working on tasks not directly related to the stories we've created and estimated - some times she's been working completely on her own without anything being reflected on the task board which breaks our SCRUM process in terms of visibility and ability to provide feedback to our Product Owner.

    We knew before hiring a designer that bringing in a new role to our consolidated team of serverside developers would be a challenge - we couldn't really point our finger to how it would show itself but It struck me how used I've become to think in terms of functionality when reflecting upon stories in our backlog - for example: "I need to know where data is coming from before I know when it's done". That's what I think about when reading a story description - I never come to think about how it is supposed to look and feel on the website. I consider it to be similar to my wife at home who once every three months points a finger at me and tell me that I mess a lot at home. I do - because I don't see my three jackets hanging over three different chairs in the living room instead of resting on a coathanger in the hallway. I don't see that all the pillows are stacked in one end of the sofa - it's not that I don't want to I just don't see it. I guess it's the same way when I read a user story - it's not that I don't want to see the design challenges and issues - I just don't see them and I could imagine that the same rule applies to a lot of serverside, hardcore .NET developers with a hang for unittesting, automated builds using CruiseControl.NET, deploymentscripts etc. etc. It's hard to see things or problems you don't know exist and that's the challenge we're facing right now.

    The way we're trying to overcome this challenge right now is to implement the following:

    • This sprint will have a story called something like "Design and identity of website". The tasks are to be defined during Sprint Planning II (this afternoon). This story is not estimated so it will act as a placeholder for the design tasks requested prior to launching February 1st. The main goal is to improve our understanding of the tasks related to the design process.
    • Upcoming projects will have stories focused on design and identity during the first sprint(s).
    • Working in Adobe Photoshop shouldn't be regarded as "Design" tasks. We're a team (swim or sink as one) so at least one of the remaining teammembers should at least have a clue about where to find PSD files and be able to navigate in them.

    We had a discussion about the fact that if you're working in a team everybody is working on the same story always. Is this always true - is it impossible to have a Design role working on future project's identity and wireframes while the rest of the team are working on implementing features on the project which is up for release? I think it is like having a Tester role - they should be able to work on enhancing i.e. test suites for the entire suite of projects regardless of what the Software Programmer role is doing. If you define a role as being what are most likely to be doing on a daily basis - is it wrong to even think in terms of roles in a SCRUM team? Note: the Product Owner and ScrumMaster are SCRUM roles - I'm talking about the different roles within the role SCRUM Team.

    We have committed ourselves to be doing SCRUM by the book so I'm curious to know how other teams are integrating different roles in their daily work using SCRUM. Please leave a comment if you have something to share - I'm all ears  :o)

    Regards K.

    mandag den 5. januar 2009

    Definition of SOLID

    What's SOLID? I've came across the acronym a few times but never took the time to look it up (I guess a Google search would have taken no longer than for you to read these two sentences...)

    Anyway - I came across it again while reading a post submitted to DotNetKicks and found a link to Pablo's topic of the month. Basicly SOLID is an acronym built upon five acronyms (no, it's not April 1st) - and they are:

    • SRP: Single Responsibility Principle
    • OCP: Open/Closed Principle
    • LSP: Liskov Substitution Principle
    • ISP: Interface Segregation Principle
    • DIP: Dependency Inversion Principle

    That's what SOLID is. All in all five architectual best-practice design principles which are good to know in order for you to get things "right" in the design of whatever system you're working on. Agreed - I'm really only paying attention to the first one since so I won't preach the importance of all five of them to you.

    There are numerous links to a detailed explanation of each of the five acronyms so I won't repeat them here - go check it out for yourself :o)

    Regards K.