Subscribe | Alerts via Email
View All Quotes
“An expert is a man who has made all the mistakes that can be made in a very narrow field.”
-Niels Bohr
<September 2007>
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

©2010 Cal Zant
Sign In
Total Posts: 106
This Year: 5
This Month: 1
This Week: 0
Comments: 2

Back in March I attended DevConnections in Orlando, and sat in one of Rob Howard's sessions on CodeSmith.  I have always had a pretty negative outlook on "code generators", because most tools don't give you enough control over what code is actually created.  I take a lot of pride in writing applications that are extremely scalable, and frankly some of the code that is generated is not as efficient or isn't as optimized for my particular application and environment as I would like.  So before I even sat down in that session, Rob already had an uphill battle to fight.

However, the tool that Rob showed us was quite different than any other code generator I had ever seen.  Simply put, CodeSmith is a template-based code generator that is commonly used to generate ORM-type architectures based on your database and settings.  The key phrase in that sentence is template-based.  There are a ton of templates available that are provided by a community and open source.  This means that you can download one of the proven architectures like .netTiers, CSLA, NHibernate, Wilson's ORMapper, or others and if something isn't coded, commented, or formatted exactly how you would like it ... you have the full ability to modify the template to your liking.  This means you don't have to write the entire architecture, but have control to change any line of generated code if you need to.  In my experience since using the product, you really don't have to mess with them too much, but it really gives me piece of mind to know that I could change the behavior instead of just having to live with whatever code the black-box generator spits out.

It is kind of hard to conceptualize what all CodeSmith has the ability to do.  It can generate C# and VB.NET code, but can also generate anything else: T-SQL, JavaScript, XML, RTF, or a language you just made up.  This was hard for me to grasp at first, but CodeSmith Studio (the IDE used to create/view/edit templates) looks and feels a look like Visual Studio.  But instead of writing code in Visual Studio that at the end of the day will become a software applications, you write code in CodeSmith Studio in a way that feels extremely similar to .NET and when you compile and run the code the output is generated code, XML, T-SQL scripts, or could even be documentation.  So it is kind of open-ended as to what you can actually use the tool to generate.  I will try to post some examples on the site sometime soon that demonstrates some of the significantly different types of things you can generate.

Bottom line of CodeSmith: This software is one of the most useful development tools I've seen.  In fact, I see CodeSmith and the RedGate Tools as must-buys for serious developers, and are almost on the same plain as Visual Studio itself.  Both of those tools are extremely reasonably priced, and the time saved developing and maintaining an app far outweigh their cost.  At the time this was written, CodeSmith Standard was $99/license, and CodeSmith Professional was $399.  For more info go to CodeSmithTools.com.

Saturday, September 29, 2007 11:03:54 AM (Central Standard Time, UTC-06:00)  # 

As IT professionals we are always dumbfounded when we see a user who has passwords written on sticky notes and then used to decorate the edges of a monitor.  We are even guilty of keeping track of some passwords in a spreadsheet from time to time, which is also not a security best practice, and we don't even like to think about people who really just have one or two passwords they use for everything.  Why do we do this?  Too many passwords.  I currently have around 40 passwords I have to remember for various software, networks, and web sites.

Most of my time is spent developing and maintaining my company's intranet/extranet, and I have it set up to use a hybrid forms/windows authentication.  That way if the user is already signed into a computer on our domain, the site will pull their windows credentials, match it up with a user in the database, and automatically log them in through forms authentication.  This happens in less than a second and the user never knows it happened.  But, users outside the company (that aren't signed into our network) can use the classic username/password form and gain access to the site without needing a user account in Active Directory. 

However, there are times when an employee who typically access the site from inside the network need to look at something from home or on the road.  Since they aren't signed into the domain, the site won't automatically pull their windows credentials ... so they are sent to the classic forms authentication log in page.  What credentials should they try to use?  Well, we could give them one more username/password to keep track of ... or the solution I went for is if the credentials don't match up with any forms authentication user in the database, query active directory from code to see if the credentials the user provided are valid domain credentials.  So in reality, on the classic forms authentication page the user could enter forms authentication credentials (validated against the database), or enter domain credentials (validated against Active Directory).

There are other solutions out there (like this one) that allow you to use forms authentication with Active Directory, but really the code that I needed was very simple.  It is based on a snippet I found in Developing More-Secure Microsoft ASP.NET 2.0 Applications.  It uses LDAP queries to authenticate a given set of credentials against Active Directory, but creating a DirectoryEntity object with those credentials and then forcing them to bind.  If it returns an error code of 2147023570, that indicates a login failure ... which means the credentials the user provided are not valid domain credentails.  If no error occurs, that means the credentials matched a user in Active Directory.


/// <summary>
/// Returns true if the given credentials match a valide forms authentication user in the database or an account in Active Directory, 
/// and false otherwise.
/// </summary>
public static bool ValidateCredentials(string Username, string Password)
{
    bool IsValid;
    using (SqlConnection thisConnection = new SqlConnection(Common.ConnectionString))
    {
        string SprocName = "sproc_ValidateCredentials";
        SqlCommand thisCommand = new SqlCommand(SprocName, thisConnection);
        thisCommand.CommandType = CommandType.StoredProcedure;
        thisCommand.Parameters.AddWithValue("@Username", Username);
        thisCommand.Parameters.AddWithValue("@Password", Password);
        thisConnection.Open();
        IsValid = Convert.ToBoolean(thisCommand.ExecuteScalar());
    }

    if (!IsValid)
        IsValid = AuthenticateAgainstActiveDirectory(Username, Password);

    return IsValid;
}

/// <summary>
/// Returns true if the given UserID and Password were valid network credentials according to Active Directory, and false otherwise.
/// The code uses LDAP to communicate with Active Directory, and simply creates a DirectoryEntry object using the given credentials
/// and then takes some action that causes a bind.  If no error occurs, the user would be allowed to log onto the domain.
/// </summary>
public static bool AuthenticateAgainstActiveDirectory(string Username, string Password)
{
    // Strip everything but the Username out from the text the user provided
    Username = Username.ToLower().Replace(@"DomainName\", "");

    // Create the entity that will connect to the LDAP server
    DirectoryEntry thisEntry = new DirectoryEntry(@"LDAP://192.168.0.1", Username, Password);

    try
    {
        // Perform an action that will force the bind to ActiveDirectory ... if this doesn't throw
        // an error then a user would be able to log onto the network with the given credentials
        thisEntry.RefreshCache();
        return true;
    }
    catch (System.Runtime.InteropServices.COMException thisExc)
    {
        // Make sure the error that got thrown was a login failure, and if it wasn't rethrow the error
        if (thisExc.ErrorCode != -2147023570)
            throw;

        return false;
    }
}
Friday, September 28, 2007 6:40:50 AM (Central Standard Time, UTC-06:00)  # 

By Jim Collins

300 pages

http://www.amazon.com/Good-Great-Companies-Leap-Others/dp/0066620996

 

I have read quite a few management-related books lately: 21 Irrefutable Laws of Leadership, IT Manager’s Handbook, The Fred Factor, The Five Dysfunctions of a Team, Fish, The One Minute Manager, etc. and this one is clearly a cut above the rest.  I like it because it was extremely analytical (like me), and was based on hard evidence drawn from exhaustive research.

 

The content in this book is based on a five year research project in which Jim Collins and his 21 person team looked at over 1,400 companies, read 6,000 articles, and conducted an absurd amount of interviews.  Unlike other books of this type, the team didn’t go into it with preconceived ideas or theories about business they were looking to prove.  Instead they tried to simply conduct the research with clear minds and then make “empirical deductions directly from the data.”  This fresh approach yielded some surprising results.

 

Collins and his team combed through every company that ever made the Fortune 500, looking for those who had made a “good-to-great transition.”  They clearly defined that transition as a companies’ having “fifteen-year cumulative stock returns at or below the general market, punctuated by a transition point, then cumulative returns at least three times the market over the next fifteen years.  We picked fifteen years because it would transcend one-hit wonders and lucky breaks (you just can’t be lucky for fifteen years) and would exceed the average tenure of most chief executive officers (helping us separate great companies from companies that just happened to have a single great leader).  We picked three times the market because it exceeds the performance of most widely acknowledged great companies.  For perspective a mutual fund of the following ‘marquis set’ of companies beat the market by only 2.5 times over the years 1985 to 2000: 3M, Boeing, Coca-Cola, GE, Hewlett-Packard, Intel, Johnson & Johnson, Merck, Motorola, Pepsi, Procter & Gamble, Wal-Mart, and Walt Disney.”

 

The research team found 11 companies who made this transition, and picked them apart to find the comment elements.  I won’t give away the ending, but trust me … this one is worth the time.  No wonder Collins has sold a gazillion copies.

Wednesday, September 26, 2007 7:54:10 AM (Central Standard Time, UTC-06:00)  # 

You know what I mean ... every IT professional has been faced with this dilemma, and you have probably known radicals on either side of the argument.  I admit that I myself have swayed pretty wildly on this issue in the past, but after some serious thought and research I think I have boiled this debate down to its crucial elements.  I will refrain from the overused (but often true) adage of "it depends."  One article I found written by Bruce Lewis presents a good overview of the argument.  It was the primary basis of the drawback sections below, but I trimmed it down some and added parts I thought were missing.

Drawbacks of the Buy option

Companies pursue the buy option because it will be easier and faster than building custom software. Nevertheless, buying the right software is a project in itself.

  • Evaluation: When buying software, it is often difficult to determine which packages you want to look at seriously. Marketing literature is often vague and unhelpful. If you're lucky, you can download an evaluation copy either by paying a nominal sum, or by providing personal information so that their marketing people can contact you. If you're unlucky, you'll have to negotiate with them to obtain an evaluation copy.
  • License Hassles: Once you've settled on a particular product and installed it, the particulars of the licensing agreement begin to bite you. If you use a license server, will you be unable to use the software when that server is down? The last thing a serious operation needs is another point of failure. If you're licensing server-side software, do you need another license for a hot spare? What if you want to do testing on a separate server? What happens if the license is tied to some kind of hardware ID and a disaster forces you to restore from backup onto different hardware? A site license might be helpful, but what if you have users who may want to run licensed client software from home through their own ISP? Does the site license cover that case?
  • Lack of Customizability: At best, buying off-the-shelf software gives you most of the functionality you want at relatively low cost, but there's always some functionality you wanted that isn't there. Often there are simple changes that could make the software much more suitable for your task. Measured over the lifetime of the software, such changes might save the users a lot of time (a.k.a. money), but you have no way of making those changes.
  • Obsolescence: Ever been stuck with a piece of software you can't legally run anymore? Ever sink money into "the standard" only to have its support discontinued a few months later? People who buy software because they think it will protect them from obsolescence often get a rude surprise.  This happens because bought software, if it stops generating enough revenue to support marketing, legal and other departments necessary to run a software company, dies completely. It's unlikely that another company will pick it up.
  • Urgent Bugs: Even the best-laid business plans can be waylaid by software bugs. What happens then? No amount of money can force a large software company to put your bug at the top of their list, no matter how urgent it is for you.
  • Integration: It is often difficult to integrate off-the-shelf software with other business applications, and it is sometimes even necessary to create an additional software layer to help the two communicate.  And even if you can get it working with the rest of your stuff, several different pieces of software that have been patched together are typically complex and less stable.

Drawbacks of the Build option
To a developer, this almost always seems like the obvious choice ... because you design every detail, in the end you have exactly what you wanted (hopefully).  But this shouldn't be "the default" decision either, because there are significant cons we sometimes conveniently forget about.

  • Lack of Maintainability: The biggest nightmare of software built in-house or by a contractor is that the author will leave, and nobody else will know how the code works, how to recompile it, or sometimes even where the code is. This situation means job security for the author, but insecurity for the organization.  Beyond that, after software has been built there is a “hidden” cost of the ongoing maintenance and support required that most people forget to weigh in the decision.
  • Lack of Standardization: There's a training cost associated with software you build yourself. New employees need to be brought up to speed on your system, even if they've used software elsewhere that performs similar functions. This is one of the most common reasons why people choose to buy software even if it doesn't completely fit their needs.
  • Obsolescence: You usually choose to build your own software when nothing else is available to fit your needs. But what happens if off-the-shelf or free software later becomes available that would fit those needs and do even more? You find yourself supporting an obsolete product.
  • Urgent Bugs: Build-it-yourself software does have an advantage over bought software in that you can fix urgent bugs yourself. The down side is that you have to drop all the other important things you're doing to fix the bug, and usually only one person knows the code well enough to fix it.

What It All Boils Down To

 

“Buy rather than build where differentiation isn’t critical” - Joe Morgan

 

That is a quote that really sparked me to write this article.  I ran across it in the September 17, 2007 edition of Information Week, in their “CIO Values” column, which highlights a different CIO in every edition.  This is part of what Joe claimed as his guiding principles (the other part was to create services for reusable business components … also important).

 

I love that quote because it is so clear-cut and simple, but let me try to put some more flesh on the concept I am trying to drive home.  If the functionality you need is something that is unique to your business, core to your company’s strategies, and provides a significant competitive edge over competitors … then even a slight difference between the ideal software you could build and an off-the-shelf product is critical and might be enough to justify building a custom solution.  However, if the functionality you are trying to attain isn’t something unique to your business, and there is a product out there that may not be completely ideal, but includes most of the elements you are looking for … then “differentiation isn’t critical” and you should buy it.

 

I think of Joe’s quote almost every time I find myself questioning whether we should buy a particular software package, software components, or tools.  Of course we could probably build anything if we wanted to dedicate the time to it … but is that always the best long-term choice for the company?  Probably not.  There has to be a balance there.  Buy software when you can, and build it when you must.  Ask yourself "Is this something unique to my business, and is the differentiation critical?"

Tuesday, September 25, 2007 10:51:04 AM (Central Standard Time, UTC-06:00)  # 

Back in March, I attended the spring DevConnections conference in Orlando (which was awesome).  I sat in one of Scott Guthrie's sessions named "ASP.NET 2.0, ASP.NET AJAX, and Visual Studio 2005 Tips and Tricks."  He showed a ton of cool stuff in that session, but one of the things that caught my eye was the new $get function available in ASP.NET AJAX.  It is really just an alias to the document.getElementById function in the DOM. 

However, I saw some potential in it that might solve one of the issues that constantly frustrated me when using master pages ... so I sent Scott and email to suggest some functionality that his team might consider building into future versions of the framework.  To my surprise Scott emailed me back the next day (which was a Sunday) with a really simple work-around that has really helped me out.  So I thought I would share it with the rest of the world.  Here is the guts of my original email followed by Scott's response:


The guts of my original email to Scott:

It is my understanding that the $get command is simply a shorthand version of the document.getElementById() method.  One thing that has been frustrating since I switched over to the ASP.NET 2.0 way of doing things, is when you use MasterPages you have to account for how ASP.NET will rename your server-side elements when it renders them to the client.  Since I do find myself writing quite a bit of JavaScript, finding and accounting for these fully qualified names is probably more of a hassle than it should be.  Is there any way you guys could work into the .NET Framework v3.5 a way use the $get command to retrieve values without having to use their fully qualified name.  I realize one option is to render JavaScript from the server to dynamically insert the assigned ID, but that seems like quite a bit of overhead, and if it was built into the framework your team could also tune it for better performance as well.

It seems that MasterPages are so useful, but as JavaScript becomes more prevalent throughout web applications I am tempted to revert back to the “old school” approach of PageStart and PageEnd user controls to encapsulate a page instead of MasterPages.  I have put a lot of thought into this and realize it is a complicated problem to solve, but I just wanted to mention it because I think it is really important and will become more important with the rise of technologies like AJAX.


Scott's response:

Hi Cal,

Right now $get() is indeed just a short-cut for document.getElementByID().  We are looking to improve the ID naming of elements over the next year to give you more control over how they are rendered.

In the meantime, you can use a technique where you render the client name into JavaScript using the Control.ClientID property:

   var myControl = <%= MyControl.ClientID %>;

You can then write this JavaScript code to dynamically load the control regardless of where it is used on the page:

   $get(myControl);

Hope this helps,
Scott


Here is an example of how I use it most the time:

var txtName = $get('<%= txtName.ClientID %>');
txtName.value = "Lorem ipsum";

Monday, September 24, 2007 2:18:50 PM (Central Standard Time, UTC-06:00)  #