CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Darrell Norton's Blog [MVP]

Fill in description here...

June 2004 - Posts

  • Notes from James Newkirk's BOF at TechEd Europe

    Benjamin writes an excellent (and thorough) review of the BOF James Newkirk on Integrating Unit Testing into the Software Development Lifecycle at TechEd Europe. Highly recommended!

  • Two new Refactoring resources

    I found the following two new Refactoring resources and added them to my .NET Test Driven Development overview.

    Fowler Refactoring Example by Dave Veeneman
    A C# translation of the 'Starting Point' example in Chapter 1 of Refactoring - Improving the Design of Existing Code by Martin Fowler. 

    Agile .NET Development – Refactoring by Jason Gorman
    A C# tutorial on how developers can improve the design of their systems through a series of small, reversible changes called refactorings.

  • Requirements change

    Requirements will always change. The changes will always cause you to redo existing code or have to write a lot more new code than you estimated. Changes never result in less work. The changes will always seem illogical. Requirements are never finished. Users change their minds faster than useless posts appear on the main feed.

    I feel better now.

  • Movin' on up...

    I am now the proud owner of a big ol' house payment! Luckily, it comes with its own house.
  • New Microsoft group blogs

    There are a few new “group” blogs over on blogs.msdn.com:

  • Review of Debugging the Development Process by Steve Maguire

    I had the opportunity to borrow this book from a friend, so I read it over my “currently reading” book. It's a quick read, and the time was well spent.

    As I was reading Debugging the Development Process, I realized how much agile practices evolved from solid software development experience like Steve Maguire’s. Look at the foundational practices he puts forth:

    • Any work that does not improve the product is potentially misguided
    • The lead (or PM) should eliminate any obstacles that keep developers from working on the product
    • Find out what the true goal is of any activity, then find the most efficient way to get the value of it
    • Establish coding priorities and quality bars to guide the development process

    Maguire ended up fixing a lot of projects at Microsoft until the company changed its scheduling process. His methods bear significant influence on what we call agile practices today. For example, fix bugs before writing new code (Test Driven Development), continually improve the process (Scrum), shorten feedback loops (Lean Software Development), and stem process growth (all agile software development). You can easily see how Maguire’s guideline to “implement features only if they are strategic to the product” bears more than a passing resemblance to the strict prioritization of requirements inherent in most agile processes.

    One thing Maguire challenges is the idea of the daily meeting. In Scrum, subsequently adapted by most agile processes, there is a short (i.e., 15 minute) meeting to report what each person did yesterday, what they are planning to do today, any problems encountered, and any ideas for improvement. Maguire said that he can get the same information from that meeting without having everyone meet. So how does the team get together to interact? He counters with they should be interacting constantly in their place of work, and if not, take the group out to lunch or something similar. Activities that have no negative connotation with them will usually result in better team interaction.

    There is an entire chapter dedicated to “scheduling madness.” The key takeaways are that the PM or lead should never allow the schedule to demoralize the team, yet should be aggressive enough to keep everyone focused. The short iterations in most agile software development processes leave little time, if any, so there is no problem with focus there. Steve also suggested breaking projects into short subprojects (iterations again) and making sure each subproject has an exciting conclusion. I think the agile focus on always creating fully functional software is roughly equivalent.

    There’s more to the book, with chapters covering attitudes, improvement, and how to avoid overtime (that would be my favorite!). There is almost no code in this book, but it is definitely a must-read for people that are taking on project-related duties.

  • Why choose monostate over singleton?

    A while back I was wondering what the pragmatic difference was between singleton and monostate. Recently someone named Ken left a comment that described why someone would use monostate over singleton other than personal preference.

    To recap, the singleton pattern structurally enforces the fact that you can never have more than one instance of a class at a time, and it is obvious to the developers that they are dealing with a singleton. On the other hand, the monostate pattern enforces the behavior of a singleton without the structure of a singleton, e.g., the singleton behavior is encapsulated from the developers.

    So why choose one over the other?

    “If you plan on deriving classes from the singleton and you want those classes to be singletons, your better choice is monostate. That's because all classes derived from a monostate are monostates. Classes derived singleton classes are not singletons by default. You would have to add the static method and attribute to each derived class.”

  • Generate database schema information

    Several times I’ve had to document an existing database structure and I didn’t have Visio or ERWin. So I created this stored proc to generate information on the tables in the stored procedure.

    Just run the stored proc in Query Analyzer and it will return the table name, column name, data type, length (characters for char or varchar, precision and scale for decimals, and number of bytes for other data types), whether the column is part of the primary key, whether the column allows nulls, and what the default value is, if any.

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[GetDatabaseSchemaInformation]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[GetDatabaseSchemaInformation]
    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS OFF
    GO

    CREATE  Procedure dbo.GetDatabaseSchemaInformation AS
    select cols.TABLE_NAME As 'Table Name',
          cols.COLUMN_NAME as 'Column Name',
          cols.DATA_TYPE as 'Data Type',
                      case
                            when cols.DATA_TYPE = 'bigint' then '8 bytes'
                            when cols.DATA_TYPE = 'int' then '4 bytes'
                            when cols.DATA_TYPE = 'smallint' then '2 bytes'
                            when cols.DATA_TYPE = 'tinyint' then '1 byte'
                            when cols.DATA_TYPE = 'bit' then '1 byte'
                            when cols.DATA_TYPE = 'money' then '8 bytes'
                            when cols.DATA_TYPE = 'smallmoney' then '4 bytes'
                            when cols.DATA_TYPE = 'text' then '16 bytes'
                            when cols.DATA_TYPE = 'datetime' then '8 bytes'
                            when cols.DATA_TYPE = 'smalldatetime' then '4 bytes'
                            when cols.DATA_TYPE = 'uniqueidentifier' then '16 bytes'
                            when cols.DATA_TYPE = 'decimal' then convert (varchar,cols.NUMERIC_PRECISION) + ', ' + convert(varchar, cols.NUMERIC_SCALE)
                            else convert(varchar, cols.CHARACTER_MAXIMUM_LENGTH) + ' chars'
                      end as 'Length',
                      case
                            when kcu.CONSTRAINT_NAME is null then 'NO' else 'YES'
                      end as 'PK?',
                      upper(cols.IS_NULLABLE) as 'Allows Nulls',
                      isnull(cols.COLUMN_DEFAULT, '') as 'Default Value'
    from INFORMATION_SCHEMA.COLUMNS cols
          join INFORMATION_SCHEMA.TABLES tabs on cols.TABLE_NAME = tabs.TABLE_NAME and
    tabs.TABLE_TYPE = 'BASE TABLE'
          left join INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE ctu on cols.TABLE_NAME = ctu.TABLE_NAME and ctu.CONSTRAINT_NAME like 'PK%'
          left join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu on ctu.CONSTRAINT_NAME =
    kcu.CONSTRAINT_NAME 
    and cols.COLUMN_NAME = kcu.COLUMN_NAME
    where tabs.TABLE_NAME <> 'dtproperties'
    order by cols.TABLE_NAME, cols.ORDINAL_POSITION

    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS ON
    GO

  • Command line compilation of the Data Access Application Block

    This should do the trick:

    VB
    vbc /imports:System,System.Data,System.Data.SqlClient,System.Xml,System.Collections,Microsoft.VisualBasic,System.Security.Permissions,System.Reflection,System.Runtime.InteropServices /t:library /r:System.Data.dll,System.dll,System.Xml.dll /out:SqlHelper.dll *.vb

    C#
    csc /t:library /r:System.Data.dll,System.dll,System.Xml.dll /out:SqlHelper.dll *.cs

  • Get a record count for all tables in a database

    I developed this stored proc after a testing group said that I had not included required data (data in the database for the application to work properly) in a deployment. It also comes in handy to make sure you’ve copied all records from one database to another.

    To use, just type GetRecordCountsForAllTables in Query Analyzer and you will get a record set returned with a row for every table in the current database with the owner, table name, and row count. Perfect for copying and pasting to Excel.

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[GetRecordCountsForAllTables]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure
    [dbo].[GetRecordCountsForAllTables]
    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET
    ANSI_NULLS OFF
    GO

    CREATE  Procedure dbo.GetRecordCountsForAllTables AS

    select  'Owner'=convert(char(10),t.TABLE_SCHEMA),
          'Table Name'=convert(char(25),t.TABLE_NAME),
          'Record Count'=max(i.rows)
    from
    sysindexes i, INFORMATION_SCHEMA.TABLES t
    where
    t.TABLE_NAME = object_name(i.id)
          and t.TABLE_TYPE = 'BASE TABLE'
    group by t.TABLE_SCHEMA, t.TABLE_NAME
    GO

    SET QUOTED_IDENTIFIER OFF
    GO
    SET
    ANSI_NULLS ON
    GO

  • What the risks of outsourcing mean for IT workers

    Paul Laudeman forwarded a link to an article on outsourcing, IT job strategies: What the risks of outsourcing mean for IT workers. It seems like a fairly balanced look at the effects of outsourcing.

    “Outsourcing is currently viewed as a promising way to cut costs since the biggest ongoing IT expense is payroll for skilled workers.

    But the costs of coordination, communication, and administration are typically higher when a company outsources, especially when the new workers are half a world away and disconnected from the business and corporate culture that they serve. people3 estimates management costs alone can be 4.5 to 15 percent higher.”

    It even includes some real, factual data (well, as factual as a survey can be).

    “According to reports, a survey released Monday by people3, a Gartner research company, revealed:

    • 20 per cent of companies that farmed out IT work did not achieve any cost reductions
    • 9.2 per cent experienced an increase in costs
    • Just 21.1 per cent reported a cost savings greater than 20 percent

    people3 also noted outsourcing  companies faced higher costs associated with the transition period, disruption in work processes, increased turnover of IT staff with critical knowledge and skills, and lower employee morale.”

    That works out to 29.2 percent saved no money or actually lost money, 21.1 saw cost savings of more than 20 percent, and the remaining 49 percent saw modest cost reductions.

    Despite the potential cost savings, some companies have some compelling reasons not to outsource (I wrote about something similar in July 2003 about the future of American programmers).

    “IT managers in government, defense and globally-competitive firms have expressed similar concerns. These organizations must weigh carefully the potential problems if they place vital data in the hands of workers who, for all practical purposes, lie outside the reach of the laws and business practices to which they are accustomed.”

  • Change all database object owners to dbo stored proc

    I hate going back and changing the owner on objects to dbo. While this stored proc is useful, I don’t like having to find all the different user names and running it for each one. So I wrote this proc to generate change owner scripts for all objects in a database not owned by dbo.

    Installation

    Run the sql script to create the stored proc in whatever database you choose.  Prefix it with sp_ and put it in the master database if you expect to use it across several databases on the same SQL Server instance and you don't want to duplicate it in each database (and you have permissions).

    Usage

    Type this in SQL Server Query Analyzer and run it:
    ChangeAllObjectOwnersToDBO

    In the results pane will be the text to change the owner of all non-dbo-owned objects to dbo. Copy all of the results text, paste in Query Analyzer main window, and run.  A warning message will be displayed if there is already an object of the same name owned by dbo.  You should resolve these problems on an individual basis.

    You should see cautionary statements like this:
    Caution: Changing any part of an object name could break scripts and stored procedures.
    Don't worry, that's standard stuff. Hopefully you haven't hard-coded a specific owner! If so, I don't think this stored proc will help.

    if exists (select * from sysobjects where id = object_id(N'[dbo].[ChangeAllObjectOwnersToDBO]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[ChangeAllObjectOwnersToDBO]
    GO
    SET QUOTED_IDENTIFIER  OFF    SET ANSI_NULLS  ON
    GO

    CREATE proc ChangeAllObjectOwnersToDBO
    as
    set nocount on

    declare @uid int
    declare @objName varchar(50)
    declare @userName varchar(50)
    declare @currObjName varchar(50)
    declare @outStr varchar(256)
    set @uid = user_id('dbo')

    declare chObjOwnerCur cursor static
    for
    select user_name(uid) as 'username', [name] as 'name' from sysobjects where uid <> @uid

    open chObjOwnerCur
    if @@cursor_rows = 0
    begin
      print 'All objects are already owned by dbo!'
      close chObjOwnerCur
      deallocate chObjOwnerCur
      return 1
    end

    fetch next from chObjOwnerCur into @userName, @objName
    while @@fetch_status = 0
    begin
      set @currObjName = 'dbo.' + @objName
      if (object_id(@currObjName) > 0)
        print 'WARNING *** ' + @currObjName + ' already exists ***'
      set @outStr = 'sp_changeobjectowner ''' + @userName + '.' + @objName + ''', ''dbo'''
      print @outStr
      print 'go'
      fetch next from chObjOwnerCur into @userName, @objName
    end

    close chObjOwnerCur
    deallocate chObjOwnerCur
    set nocount off
    return 0

    GO
    SET QUOTED_IDENTIFIER  OFF    SET ANSI_NULLS  ON
    GO

  • Convert existing NUnit test harnesses to VS Team System

    James Newkirk has a post on converting existing NUnit tests to use the new Visual Studio Team System testing framework. It uses the using statement assignment functionality that I blogged about here.

    To convert your code all you have to do is something like this:

    // using NUnit.Framework;
    using Microsoft.VisualStudio.QualityTools.UnitTesting.Framework;
    using TestFixture = Microsoft.VisualStudio.QualityTools.
        UnitTesting.Framework
    .TestClassAttribute;
    using
    Test = Microsoft.VisualStudio.QualityTools.
        UnitTesting.Framework
    .TestMethodAttribute;
    using
    SetUp = Microsoft.VisualStudio.QualityTools.
        UnitTesting.Framework
    .TestInitializeAttribute;

  • The most extreme thing that could possibly work

    Jay Bazuzi has an interesting post on the most extreme thing that could possibly work. He brings up an interesting thing like what is the shortest method you could write and still do something useful? 10 lines, maybe 5 lines? How about a 1-line method?

    I have an interesting, non-programming story about this. I was starting my first year in the MBA program at the oldest college in the US (those are some of my classmates in that picture… a few other friends and I designed the site before the IT group took it and represented it as theirs). The first day was a team-building day, entirely outside, at the ropes course. For those that don’t know what a ropes course is, it is a bunch of different obstacles made of wood and, well, ropes, and the obstacles usually require you to overcome your fear and rely on your friends. They are holding your belay line, so if they screw up, you’re toast!

    Get to the point already! Ok, our final challenge was to build a boat out of wood, rope, and inner tubes and be the fastest group to paddle around a course. Restrictions were everyone had to be on the “boat”. Considering it was a couple hundred yards around the course, one team managed to finish in 2 minutes, 45 seconds. Very impressive, but they didn’t win. They were all paddling their fool head off, but they did not win.

    We won (yeah, I like that part). Our official time was 1 second. Every other team worked on shaving a few seconds off someone else’s time. The most extreme thing was to finish in zero time. How? We created one big piece-of-crap boat that everyone else sat on, holding on to the pier, thus preventing the time from starting. Meanwhile, I paddled around the course very slowly, laughing at another group paddling furiously as their boat sank in the middle of the lake, connected to my group by a huge amount of rope. We were still on 1 boat, and we still paddled around the course. They let go of the pier and I touched it; total time was 1 second.

    So don’t look on ideas like 1-line methods with disdain. They can sometimes lead to a spark that can drastically change what you are doing.

    UPDATE: Post now reflects Jay's real name.

  • Please stop the fragmentation of the testing tools market!

    Jamie Cansdale, brilliant VS.NET addin programmer, posts about a System.Testing unifying framework (one testing framework to rule them all!):

    Peter Provost has started a petition to include unit testing support in all versions of Visual Studio 2005. While I agree that unit testing should be essential part of all development, I don't think Visual Studio is the place to introduce an important new API. I think a much more fitting place would be the BCL and SSCLI/Rotor. At the moment the BCL has an extensive set of unit tests. I would be in favor of converting these over to using a core testing framework (say 'System.Testing'). We would then have a standard API for writing tests under all implementations of the CLI. I think this is where real value would come.

    Having said that, there is going to be a need for unit testing support in standard versions of Visual Studio 2005. At the moment I am developing a testing tool what will work in all versions of Visual Studio and integrate with Visual Studio Team System. It will support NUnit, csUnit, MbUnit and the testing framework that comes with VSTS. The idea is to allow those using VSTS to run their existing unit tests unchanged via the Team System extensibility hooks. It will also allow those not using Team System to run tests written using the Microsoft testing framework.

    So long as Team System remains a premium feature of Visual Studio, there is a point carrying on with this and other projects. I am relieved that Microsoft have chosen to tread relatively lightly on the thriving .NET tools community. I think this can only help encourage innovation and cross fertilization.

    Why are people creating all these new testing frameworks? Four different frameworks is at least two too many. While there might be something interesting in csUnit or MbUnit, they aren’t compelling enough for me to leave NUnit (in marketing terms these are known as switching costs). And since I’ll be using Visual Studio Team Server, I’ll very likely be using that testing framework due to all the integration work Microsoft has put into it. Why can’t we roll any functionality from the non-market leaders into the market leader (which I would assume to be NUnit, but pick one and everyone support it)? Is it pride that gets in the way? Really, the important part is to make it easier to develop better software.

    UPDATE: This is not to say that Jamie is fragmenting the testing tools market. I just don't think there should be effort spent on supporting three different open-source/freeware testing tools. One tool, like Jamie proposes, is a great idea!

More Posts Next page »