Tuesday, March 06, 2007

Some times I just clap when I'm excited.  It's a bit Rain man-has-spoken.  Maybe I was stung by a bee when I was a child, I can't explain it. I clapped for the Litware HR overview doco.

According to SaaS Sample Application.pdf, the following bits that are required:

  • Windows Server 2003 SP1 or R2
  • IIS 6.0
  • SQL Server 2005 Full Cream or Express editions
  • Microsoft Visual Studio 2005 Pro or Team Suite (recommended)
  • .NET Framework 3.0
  • Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation)
  • Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP
  • Enterprise Library for .NET Framework 2.0
  • Active Directory Application Mode (ADAM) SP1
  • Guidance Automation Extensions
  • Guidance Automation Toolkit  

...and that is all that you need to take over the world.

ADAM is what jumped out at me.  I have managed to not have much exposure before now however get the feeling ADAM and I are going to get a bit better aquainted before this exercise is done.

I'm building up a VPC image with all the bits now and I'm taking Friday off work to sit at home with my DeLonghi Metropolis 1385 Espresso machine and the coolest SaaS guidance around and I'm not coming out until I have a business plan or my head explodes.  (I'd say you will know by Monday, if you are curious)

Tuesday, March 06, 2007 12:11:34 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [4]  | 

Amazing.  I just noticed that the term SaaS has only had the most fleeting of references on my blog thus far, and then only in jest.

This is amazing to me because as anyone who has had a yarn with me about the ISV space over a couple of glasses of wine knows its hard to shut me up about it.

What does this prove?  I don't blog after a couple of glasses of vino.  :-)

Situation rectified 

Listening to: Kings of Leon

Tuesday, March 06, 2007 11:47:50 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, February 27, 2007

Just a follow-up on my post of yesterday about the intent of exposing a read-write property of an Array/Collection type.

Practical Guidelines and Best Practices has the following guidance (i'm paraphrasing)

13.13 To protect the state of a backing var for properties that return arrays, consider

get { return DirectCast(_arr.Clone(), string()); }

which is good protection, but less efficient.  Or, provide indexed access to the array by an indexed property or function.  Getting close...

13.14 Properties that return a collection should be read-only to prevent clients replacing the whole array with a new one, or with a null reference as that could break assumptions elsewhere in the class. Disco! 

Thanks lads!

Tuesday, February 27, 2007 7:53:36 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, February 26, 2007

This one came up in discussion last week and could be worth mentioning.

Consider the following property:

private List<SchemaAttribute> _attributes = new List<SchemaAttribute>();
public List<SchemaAttribute> Attributes
{
   get
   {
      return _attributes;
   }
   set
   {
      _attributes = value;
   }
}

NCover/NCoverExplorer reliably inform me that this property has only 50% coverage
in my tests.

By hereto unexplored forces of nature, every consumer of this class calls
.Attributes.Add()

or, itterates over it as so:
foreach (SchemaAttribute element in instance.Attributes)
{
   // ...
}

The keen eye will notice that neither of these ways to access the property actually hit the setter! 

Two possible paths present themselves:

  1. Write a test that just exercises the setter.  This seems to me pointless. 
    If we are to consider that our tests can serve to express our intention
    in a repeatable fashion, what is our intent?  To see if a Generic List still works?
  2. Consider makeing the property read-only.  Including braces I could own three lines less code.  Yay!
    And also now I have had cause to think about it, it's not my intention that the
    List be set as a list, for this class it just dosen't make sense right now.

Next step?  Consult Francesco & Giuseppe!

Sleep.  The best 10 hours of the week.

Listening to:  Nick Cave and the Bad Seeds - Abattoir Blues

Monday, February 26, 2007 1:02:40 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, February 21, 2007
Rob Farley posted a very interesting codegen post on scripting objects this morning, and as a reforming codegen junky I just couldn't let it go without comment :-)

Firstly, I modified his query as so:

select quotename(si.name) as "@IndexName", quotename(ss.name) AS "@SchemaName", quotename(so.name) AS "@ObjectName",
    stuff((select ',' + quotename(sc.name)
            from sys.index_columns sic
            join sys.columns sc
                on sc.column_id = sic.column_id
            where so.object_id = sic.object_id
                and sic.index_id = si.index_id
                and sc.object_id = so.object_id
            order by sic.key_ordinal
            for xml path('')),1,1,'') as "@IndexColumns"
from sys.indexes si
join sys.objects so
    on so.object_id = si.object_id
join sys.schemas ss
    on ss.schema_id = so.schema_id
where so.type = 'U' and si.type = 1
for xml path('index'), root('indexes')


Things I'll point out:
  • Adding the extra for xml clause, this time specifying a better row element name than 'row' and also adding a document node
  • Once the outter for xml clause is in place, we can alias the columns using @ to have them come out as elements in the results
We can feed the results of that query straight into the following XSLT:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"
/>
   
    <xsl:template match='/'>
    <xsl:apply-templates select ='indexes/index'
/>
    </xsl:template>

  <xsl:template match='index' >
create index <xsl:value-of select='@IndexName'
/>
  on <xsl:value-of select='@SchemaName'
/>.<xsl:value-of select='@ObjectName'/> (<xsl:value-of select='@IndexColumns'/>)
  </xsl:template>
 
</xsl:stylesheet>

I'm not claiming this method is superior, just different, which I think is in keeping with the spirit of Rob's post :-)  and I have learned more about the improvements of the for xml clause in SQL Server 2005 in the process.

I'll leave final judgment on the utility of this approach as an exercise to the reader; my instinctive reaction is to include it as a build step to help you snapshot schema changes between check-ins, or as Rob suggests to take objects from one database and create slightly different objects in another database – there are no wrong answers and if you think of something interesting please leave a comment :-)

Grab the source files here: ScriptObjects.zip (.78 KB)
Wednesday, February 21, 2007 5:32:28 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [2]  | 
 Monday, February 19, 2007

In my commute this morning I was listening to my weekly dose of DotNetRocks - Show 214 with guest Billy Hollis and Billy mentioned something on Agile to illustrate a point, and it has stuck with me all day.

He was referring to a presentation he attended where an advocate said he was writing 2 or 3 lines of unit test code for each line of production code.  Billy's objection to this is hardly a challenge to intuition: Are we getting 4x the value for 4x the code?

One of my metrics for the unit tests that I write is that they don't hurt.  Some can be a couple of lines long, some can be heavily copied-n-paste'd.  Customizing a CodeRush template is time well spent.  There are no wrong answers, however you get them in there is really OK.

It makes sense:  You're writing a unit test.  The aim is to isolate a gizmo of your choosing in your code and exercise it.  The cumulative weight of the unit tests should really function as an expression of your intent for the gizmo.  I outlined what I think of the high importance of naming your tests in a prior post.

Monday, February 19, 2007 3:48:15 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, February 16, 2007

I love finding little nice features.  I just discovered the following combination in CodeRush:

alt-UP/alt-DOWN - Change visiblility (public/private/protected/friend) of property, variable or class that the cursor is inside

I've got to hang around late tonight for a conference call with London (on a Friday night no less!) but finding that has made my day.

We should all try to remember the importance of little units of joy in the software we make.

 

Friday, February 16, 2007 2:23:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, February 15, 2007
WCF is at SDNUG tonight...

...and also came across it here today:

Image courtesy Gary Costa Pereira

[?] After Blog Mint:  Juval Lowy was great at SDNUG last night.  Not a semi-colon in sight!  The presentation was mostly about architecture with the IDesign method.  Well worth it. 

Also, Justin, if you're reading this... sorry about spilling beer on you at the Paragon :-)

Thursday, February 15, 2007 7:32:45 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, February 07, 2007

with apologies and thanks to Sir Winston for giving me the courage to continue on with WiX :-)

The two links that make my WiX world turn are:

Wednesday, February 07, 2007 5:11:45 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, February 06, 2007

Some of the problems a modern cow developer has to face... (thanks Brian - keep posting the funnies)

My contribution:


WATERFALL:  18 months ago, one cow went into the milking shead.  The method was sound, but you don't need milk any more.

AGILE:  Only milk when necessary. 

EXTREME PROGRAMMING:  You have two cows.  They milk each other.

TEST-DRIVEN DEVELOPMENT:  Know the bucket before milking any cows.

OPEN SOURCE:  I have a cow, you and some other guy from Norway milk it on weekends or when ever you have some free time. 

CONTINUOUS INTEGRATION:  Your team of two cows checks-in to the milking sheads every day.  Everyone has access to the milk.  Everyone feels good.

SERVICE-ORIENTED ARCHITECTURE:  We agree a schema for a cow.  No one feels dependant on any breed of cow, but no one has actually seen a complete cow.

SCRUM:  There is a backlog of milk orders.  Cows decide how they are to be milked.  Every 30 days the cows, pigs and chickens agree on an amount of potentially shippable milk.  The pigs and chickens get to decide when no more milk is needed.

SaaS:  You don't own the cows.  You rent access to them and pay for it out of OpEx.  Owning cows is outside of core business - you just need some milk.

Tuesday, February 06, 2007 12:53:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  |