Scott Hanselman

Back to Basics - Do namespace using directives affect Assembly Loading?

July 4, '08 Comments [29] Posted in Back to Basics
Sponsored By

Jeff Atwood had a great post a while back called "Strong Opinions, Weakly Held." It's good to feel strongly about something, but important to be open to changing your opinion if you're faced with new evidence.

Last week a reader pointed me to this post at the Microsoft StyleCop blog that shows some interesting examples of using directives outside and inside the namespace declaration.

For example, this compiles fine:

using Guid = System.Guid;

namespace Microsoft.Sample
{
public class Guid
{
public Guid(string s){}
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}

}

However this one with the using moved inside the namespace doesn't compile:

namespace Microsoft.Sample
{
using Guid = System.Guid;

public class Guid
{
public Guid(string s){ }
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}
}

The code fails on the following compiler error, found on the line containing Guid g = new Guid("hello");

CS0576: Namespace 'Microsoft.Sample' contains a definition conflicting with alias 'Guid'

In the first example, there's an alias created, but it doesn't matter because the second Guid class is in local scope (there's no scope conflict) and the compiler chooses the inner Guid class.

In the second example, there are two "Guids" declared in the same scope and that's a conflict that the compiler can't resolve automatically. The style rule/argument the post makes is that you will only see these kinds of conflicts if you put your using directives inside your namespaces. To this, I say, "meh." Sure, if it makes you happy and you use lots of namespace aliases, sure, but it's an edge case. I simply prefer to have my namespaces outside.

Read Twice, Test Once

However, the second rule in the post said:

"However, placing the using statements [Ed. Note: They mean "directives"] within a namespace element allows the framework to lazy load the referenced assemblies at runtime. In some cases, if the referencing code is not actually executed, the framework can avoid having to load one or more of the referenced assemblies completely. This follows general best practice rule about lazy loading for performance."

This stopped me in my tracks. This rocks the very bedrock that my knowledge of the CLR stands on. I'm like, NO WAY, and then I oscillated back and forth between denial and acceptance. Then, I settled on denial. I don't buy it. A using directive is for aliasing and is a kind of syntactic sugar. Ultimately the IL is the same. Assembly loading won't be affected as the assembly manifest doesn't change.

Here's what my experiment showed. I believe it's true until I find out from someone on the CLR Loader team that it's not true. ;)

First Test

using System;
using System.Xml;

namespace Microsoft.Sample
{
public class Program
{
public static void Main(string[] args)
{
Guid g = Guid.NewGuid();
Console.WriteLine("Before XML usage");
Console.ReadLine();
Foo();
Console.WriteLine("After XML usage");
Console.ReadLine();
}

public static void Foo()
{
XmlDocument x = new XmlDocument();
}
}
}

I ran this program outside the debugger but compiled in debug mode. At the point there the first ReadLine() hits, the program pauses and waits for an Enter key. I loaded up Process Explorer and saw:

image

Then, I hit Enter, executing the Foo() method and new'ing up an XmlDocument. You can see that System.Xml just got loaded (specifically the native image) into the process.

image

Second Test

If I do the same thing with the usings INSIDE the namespace I get identical results.

namespace Microsoft.Sample
{
using System;
using System.Xml;

public class Program
{
public static void Main(string[] args)
{
Guid g = Guid.NewGuid();
Console.WriteLine("Before XML usage");
Console.ReadLine();
Foo();
Console.WriteLine("After XML usage");
Console.ReadLine();
}

public static void Foo()
{
XmlDocument x = new XmlDocument();
}
}
}

In fact, the only thing that changed the way the assemblies got loaded was switching to release mode. Running the app in release mode had all the assemblies in my trivial app loaded immediately. I thought it was weird for a second, but then realized it had nothing to do with debug vs. release. It was simply that the Foo() method was either inlined or there was a Tail Call Optimization as I explored in this post: Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks.

I'm 99.99% sure at this point that using directives can't change your assembly loading behavior and I think I was right to be suspicious. However, I'm going to ask some people on the Fusion (assembly loader) and C# teams who are smarter than I and I'll update this post as I learn more!

However, the Back to Basics Tips here are:

  • Don't believe everything you read, even on a Microsoft Blog.
  • Don't believe this blog, either!
  • Decide for yourself with experiments if you need a tiebreaker!

And be ready to be wrong anyway! It only takes one negative experiment to disprove a theory. Of course, the real question is, what does the specification say? 

UPDATE #1: Ian Griffiths had a similar reaction and a similar test!

What do you think, Dear Reader?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Weekly Source Code 30 - VB.NET with XML Literals as a View Engine for ASP.NET MVC

July 3, '08 Comments [12] Posted in ASP.NET | ASP.NET MVC | VB | XML
Sponsored By

I was literally in the middle of writing the post when I saw a message from Andrew Davey about how he had implemented the same idea! Of course, his is way better, so I got to code via subtraction. That means subtracting out the crap I had written in a few minutes and dig into his code.

There are no unique ideas, right? ;) Either way, it's fun when the same idea is being thought about simultaneously.

Here's the general concept. A few weeks back I was talking with Avner Aharoni, a Language Program Manager, and he had been kicking around the idea of VB9's XML Literals making friendlier Views within ASP.NET MVC.

I've blogged about VB9's rocking sweet XML support before. It lets you create XML like this. Note the lack of strings...the XML is there in the language and the compiler and intellisense are all aware of it.

 Dim books = <bookstore xmlns="http://examples.books.com">
<book publicationdate=<%= publicationdate %> ISBN=<%= isbn %>>
<title>ASP.NET Book</title>
<price><%= price %></price>
<author>
<first-name><%= a.FirstName %></first-name>
<last-name><%= a.LastName %></last-name>
</author>
</book>
</bookstore>

Views in ASP.NET MVC

Starting with the Northwind ASP.NET MVC Sample Code for Preview 3 that Phil updated, let's look at the List View:

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<h2><%=ViewData.CategoryName %></h2>
<ul>
<% foreach (Product product in ViewData.Model.Products.Model) { %>
<li id="prod<%= product.ProductID %>">
<%= product.ProductName %>
<span class="editlink"">
(<%= Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID })%>)
</span>
</li>
<% } %>
</ul>
<%= Html.ActionLink("Add New Product", new { Action="New" }) %>
</asp:Content>

This is straight from the ASPX page with inline C#.

ASP.NET MVC Views using VB9's XML Literal Support

imageNow, we thought it'd be cool/interesting/potentially-something if we could use the XML Literal support to get, as Andrew puts it "compiled, strongly typed, intellisense friendly views." Sure, we mostly get that with the ASPX pages, but perhaps this would be better/easier/something? Keep in mind here that we're playing.

Your opinions on if this is a good idea or something to move forward would be useful. Leave comments and I'll compile and give them directly on to the VB and MVC team(s)! Remember, it can look like however you think it should, so don't be constrained by my spike or Andrew's.

Here's why Andrew thinks it's cool, quoted from a post on the ALT.NET mailing list:

Some key features I've used.
- <%= From ... Select ... %> to create repeated elements
- VB's ternary "If" operator for conditional output
- X-linq to post process the HTML before sending it
- choose between indented and compressed XML output
- modules of functions as "controls" - it's so simple :)

Here's what my solution looks like in Visual Studio. See how the ListVB.aspx has no "+" sign. There's no code-behind .cs file there even though this is a C# project. The meat of the View is in another assembly (although you could conceivably do something freaky and get VB and C# to live in the same assembly (be sure to read the comments)).

Actually, the ListVB.aspx file is VB, not C# and refers not to to a code-behind, but another class in another DLL, specifically the VBViews assembly.

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" 
AutoEventWireup="true" Inherits="VBViews.ListVB" Title="Products" %>
<%@ Import Namespace="NorthwindModel" %>
<%@ Import Namespace="System.Collections.Generic" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2><%=ViewData.Model.CategoryName%></h2>
<% = GetList() %>
</asp:Content>

Here's the Visual Basic code in the other assembly.

Imports System.Xml.Linq
Imports NorthwindDemo.Models

Partial Public Class ListVB
Inherits System.Web.Mvc.ViewPage

Function GetList() As XElement
Dim c As Category = CType(ViewData.Model, Category)
Return <ul><%= From product In c.Products _
Select _
<li id=<%= "prod" & product.ProductID %>>
<span class="editlink">
<a href=<%= "/Products/Edit/" & product.ProductID %>>
<%= product.ProductName %>
</a>
</span>
</li> %>
</ul>
End Function
End Class

This won't really be clear without some syntax highlighting to make the point, so here it is again, but this time as a screenshot. See now the VB code, XML and <% %> blocks are all together in same line? VB is just generating XElement's which in turn will turn into a string when "rendered" by the ASPX page.

The same VB9 code as before, except this time in color.

Andrew's Take #2 on the VB9 XML Literals as ASP.NET MVC Views

Andrew Davey's NRest project is more than just VB9 Views. It's a REST web framework for ASP.NET using the Nemerle programming language (using the May CTP). You can browser or GET his code with SVN here: http://svn.assembla.com/svn/nrest/trunk/. It's also a nicely laid out solution that uses the Ninject IOC but I'll cover that later. Do check out Andrew's screencast about his NRest project.

His code is a mix of C#, Nemerle and VB. The Website, Tests and Services are in C# and the Ninject modules are in Nemerle, along with the meat of the main NRest project. I think he could have used more of System.MVC, specifically the View Engines, that he did, but I'm still grokking his intent.

He's got a hierarchy in VB with a MainPageBase, Page, in order to achieve a kind of Master Pages:

Public Class MainPageBase(Of TChrome As MainChrome, TContent)
Inherits Page(Of TChrome, TContent)

Public Overrides Function GetHtml() As XElement
Return _
<html>
<head>
<title><%= Chrome.Title %></title>
<link href="/styles/demo.css" type="text/css" rel="Stylesheet"/>
<%= GetHeadContents().Elements() %>
</head>
<body>
<h1><%= Chrome.Title %></h1>
<%= GetBodyContents().Elements() %>
</body>
</html>
End Function

Public Overridable Function GetHeadContents() As XElement
Return <_></_>
End Function

Public Overridable Function GetBodyContents() As XElement
Return <_></_>
End Function

End Class

So a Hello World page in VB would be very simple, just this:

Public Class CustomerPage
Inherits MainPageBase(Of CustomerPageData)

Public Overrides Function GetBodyContents() As XElement
Return _
<_>
<p>Hello <%= Content.FirstName & " " & Content.LastName %></p>
</_>
End Function
End Class

All of this is a work in progress, but it's really cool that we're all trying to push the envelope and not afraid to try crazy stuff in order to make things better. It'll be cool for me to read this post in a year and either say "ew" or "cool!" depending on what direction we all went.

Have you done anything cool or crazy with Views and ViewEngines, Dear Reader?

Related Posts

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Back to Basics - This is not the object you're looking...wait, oh, it is the object

July 2, '08 Comments [27] Posted in Back to Basics | Learning .NET | Windows Client
Sponsored By

Downcasting is kind of something you usually want to avoid, but sometimes it's not easily avoided. It depends on the situation. Because it's not an idiom you'll find yourself doing every day, sometimes you'll forget to do it entirely and what you're looking for is right there under your nose.

The Problem

A buddy was trying to host the WebBrowser control in his WinForms application. It was a locally run application that was using the WebBrowser control to generate part of the UI. The user might click on a link, and you'd want to do something based on the click of an link/anchor in the HTML.

In this trivial example, I add the words "Add Comment" to a page I've navigated to within my WinForms Application.

image

First, we make some new elements within the WebBrowser control itself, like this.

HtmlElement div = webBrowser1.Document.CreateElement("div");
div.SetAttribute("style", "color:blue;");
webBrowser1.Document.Body.AppendChild(div);

HtmlElement anchor = webBrowser1.Document.CreateElement("a");
anchor.InnerText = "Add Comment";
anchor.Id = "lnkAddComment";
anchor.SetAttribute("href", "#");
anchor.Click += new HtmlElementEventHandler(doit);
div.AppendChild(anchor);

Notice that we can hook up a managed event handler to the anchor, and that the anchor's href attribute points to nothing, by setting it to "#".

anchor.Click += new HtmlElementEventHandler(doit);

My friend hooked up the event to doit() that had a standard EventHandler signature like this:

public void doit(object sender, HtmlElementEventArgs e)

You've likely seen this "object sender, SomeEventArgs e" method signature before. He started digging around in the HtmlElementEventArgs object, trying to find something he could use to known if the user had clicked on the link called lnkAddComment. He was bummed to find nothing he could use.

image 

There's a couple of thing to learn here. First, just hovering over the sender object in the debugger shows us a lot. We can see that the type of sender isn't just object, but rather System.Windows.Forms.HtmlElement. This is a CLR type, and not a JavaScript type or a type you'd know about if you were familiar with the DOM and were expecting something more DOM-like.

The DOM element in this case, is there, but it's a COM Object and is part of the IE DOM object model and you'd be better off using Visual Basic if you care deeply about getting into it as we've recently learned.

image

Downcast, Damned Spot!

However, it's an HtmlElement and it has and id property with the string "lnkAddComment," and that's useful. At this point one could down-cast it. That means, telling the compiler that we know more than it does and that we're totally sure and are willing to risk our necks.

HtmlElement foo = (HtmlElement)sender;
if (foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}

There's some interesting things we can think about here. First, what if we're wrong? Well, bad things for one:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Unable to cast object of type 'Something.You.Did.Not.Plan.On' to type 'System.Windows.Forms.HtmlElement'.
   at WindowsFormsApplication1.Form1.doit(Object sender, HtmlElementEventArgs e) in C:\Yay\Form1.cs:line 32

And that sucks. However, in this case we are pretty darn sure, but we should be more defensive about it.

public void doit(object sender, HtmlElementEventArgs e)
{
if (sender is HtmlElement)
{
HtmlElement foo = (HtmlElement)sender;
if (foo != null && foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}
}
}

But that is kind of verbose, we can try a defensive cast:

HtmlElement foo = sender as HtmlElement;
if (foo != null && foo.Id == "lnkAddComment")
{
MessageBox.Show("woot");
}

In this case, if sender isn't an HtmlElement, we'll get back null. The same code in VB is pretty clear also. See the TryCast?

Public Sub doit(ByVal sender As Object, ByVal e As HtmlElementEventArgs)
Dim foo As HtmlElement = TryCast(sender,HtmlElement)
If ((Not foo Is Nothing) AndAlso (foo.Id = "lnkAddComment")) Then
MessageBox.Show("woot")
End If
End Sub

The IL (Intermediate Language) instructions are interesting also as it's asking explicitly if that object is what I think it is:

L_0001: ldarg.1 
L_0002: isinst [System.Windows.Forms]System.Windows.Forms.HtmlElement

I suppose that means I could just ask myself, but that's largely stylistic as the resulting IL is virtually the same, with the defensive cast being a simpler.

But Why the Downcast at All?

At this point you might be asking, Why did I have to downcast at all? Doesn't that mean the EventHandler pattern is lame? Maybe, but here's the thinking as described by Jeffrey Richter on page 228 of his most excellent CLR via C#, 2nd Edition (with [contextual edits and emphasis] by me so it makes sense in this post).

A lot of people wonder why the event pattern requires the sender parameter to always be of type Object. After all, since the [HtmlElement] will be the only type raising an event with a [HtmlElementEventArgs] object, it makes more sense for the callback method to be prototyped like this:

void MethodName(HtmlElement sender, HtmlElementEventArgs e);

The pattern requires the sender parameter to be of type Object mostly because of inheritance. What if [HtmlElement] were used as a base class for [DerivedHtmlElemen]? In this case, the calIback method should have the sender parameter prototyped as an [DerivedHtmlElement] instead of HtmlElement, but this can't happen because [DerivedHtmlElement] just inherited the Click event. So the code that was expecting an [DerivedHtmlElement] to raise the event must still have to cast the sender argument to an [DerivedHtmlElement]. In other words, the cast is still required, so the sender parameter might as well be typed as Object.

The next reason for typing the sender parameter as Object is just flexibility. It allows the delegate to be used by multiple types that offer an event that passes a [HtmlElementEventArgs] object. For example, a [PopHtmlElement] class could use the delegate even if this class were not derived from [HtmlElement].

One more thing: the event pattern also requires that the delegate definition and the callback method name the EventArgs-derived parameter e. The only reason for this is to add additional consistency to the pattern, making it easier for developers to learn and implement the pattern. Tools that spit out source code (such as Microsoft Visual Studio) also know to call the parameter e.

If you're interested in this kind of stuff, you should totally buy his book.

Can we avoid the cast completely?

Why did we downcast in the first place? We wanted to get ahold of the HtmlElement.Id property so we could do a string comparison in order to tell if an object is the one we're looking for. Perhaps we can check for that object's identity using something a little cleaner than a string.

In this case, since we were the ones that created the anchor in the first place we can check the "object sender" against a saved reference to our anchor by checking object identity. Are these the same two objects? Is the object I added to the object model the same one that is coming back to me as the sender parameter to this Event Handler?

HtmlElement anchor;
public void doit(object sender, HtmlElementEventArgs e)
{
if (sender.Equals(anchor))
{
MessageBox.Show("woot");
}
}

Is this a good idea? What about using == instead? In this case, I CAN use == because HtmlElement has explicitly created equality operators, so when I'm using == to compare these two instances I'm ACTUALLY calling a static op_Equality(HtmlElement, HtmlElement) on the HtmlElement type. It's static because both side might be null and I can't call methods on null instances.

HtmlElement anchor;
public void doit(object sender, HtmlElementEventArgs e)
{
if (anchor == sender)
{
MessageBox.Show("woot");
}
}

However, while operator overloading is common in C++ it's generally considered to be unnecessarily obscure in C# and moreover, you just can't count on folks to be consistent. For example, when I say == do I mean value equality or reference equality? In the case of HtmlElement they mean reference equality. In C++ an overloaded == is usually done for deep value comparisons.

I will get this warning if I try anyway:

Possible unintended reference comparison; to get a value comparison, cast the right hand side to type 'System.Windows.Forms.HtmlElement' 

I like to use Equals() myself for clarity's sake, but touché! It's going to just do this internally anyway:

public override bool Equals(object obj)
{
return (this == (obj as HtmlElement));
}

Commenter Adam makes the excellent point that using Object.ReferenceEquals is explicitly clear in expressing intent. The result would be:

public void doit(object sender, HtmlElementEventArgs e)
{
if (Object.ReferenceEquals(anchor,sender))
{
MessageBox.Show("woot");
}
}

Of course, the implementation of ReferenceEquals is just this again. ;)

public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}

What's the point?

Know your options, but above all, know your intentions and make sure that the code you're writing correctly expresses your intent.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

How to Programmatically tell if an IIS AppPool is 32-bit or 64-bit

July 1, '08 Comments [2] Posted in ASP.NET | IIS
Sponsored By

I've blogged before about 32-bit vs. 64-bit .NET under IIS and how different Framework-bitnesses need different Application Pools (AppPools).

Someone asked how you find out what AppPools are on a machine and how do you find out which ones are 32-bit? There's a number of ways, depending on your needs:

If you're running a batch file or command-line script and IIS7, you might use the standard IIS7 appcmd.exe tools. You'll need to be Administrator, of course, as we're talking about Web Server configuration here.

To list all AppPools:

c:\Windows\System32\inetsrv\appcmd list apppool
APPPOOL "Joe" (MgdVersion:v2.0,MgdMode:Integrated,state:Started)
APPPOOL "Sally" (MgdVersion:v1.1,MgdMode:Classic,state:Started)
APPPOOL "Fred" (MgdVersion:v2.0,MgdMode:Integrated,state:Started)

To list just 32-bit AppPools:

c:\Windows\System32\inetsrv\appcmd list apppool /enable32BitAppOnWin64:true
APPPOOL "Fred" (MgdVersion:v2.0,MgdMode:Integrated,state:Started)
Basically, any way, be it WMI, COM, PowerShell, or AppCmd.exe that lets you look at the Enable32BitAppOnWin64 property of an AppPool will get you your answer.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Spirit of Open Source - Netiquette can be subtle

June 30, '08 Comments [41] Posted in Musings
Sponsored By

I got a disturbing email today on Flo's mailing list (of Notepad2 fame). Florian Balmer is the author of the most excellent Notepad2. This is a great "it just works" editor. It's Notepad, but goes one better, I like to say. I've promoted it on my Tools List and in countless talks. Notepad2 has been developed over ten years and is in active, ongoing development. Florian has posted most recently about his adventures in Unicode.

Flo was surfing and discovered http://www.notepad3.org.

This is uncool for a number of concrete reasons.

UPDATE/CORRECTION: I screwed up the licensing so my only complaints to the author of Notepad3 is that the name makes for a tacky fork and that the changes appear to be not significant in their scope. I apologize.

Notepad3 is a fork of a older version of Notepad2, specifically the GPL'ed Notepad2 1.0.12 rather than the BSD Licensed Notepad2 2.1.19. The GPL'ed Notepad2 was released on June 25th, 2004. The BSD licensed version was released on April 7th, 2007.

See, it turns out Netiquette CAN be subtle!

  • The distributor of Notepad3 did not include Florian's license. 
    • UPDATE/CORRECTION: The license still is intact in the .c source code files, just not in the main license.txt. The full copy of the original Notepad2 license.txt also appears in Notepad3's source zip in c165/license.txt.
    • Notepad2 is distributed with this license (I snipped the copyright all caps at the end for brevity) as its main license.txt.
  • Florian's name doesn't appear anywhere within the Notepad3 root license.txt, which appears to be an aggregate of a number of licenses of the sub-components.
    • UPDATE/CORRECTION: Flo's website is referenced in the license.txt's header.
  • The Notepad3 "creator" didn't make any attempts to include his changes in Notepad2 or give Florian a heads-up.

Now, these next reasons are my own opinions, and possibly subtle. You tell me. These are my opinions.

  • Mildly Tacky: They made up a new name and registered a new domain for the project. The new source can be only by found by digging around the main site. Can you find it?
    UPDATE/CORRECTION: I think the source should be linked directly to from the main page. Rather, it's under download/src using the navigation on the left of their site.
  • Tacky: The new entity, Notepad3, arguably doesn't contain substantive improvements, certainly not enough to be called an entirely new version, and definitely not Notepad3. You can see the sum total of the changed lines on Flo's post.
  • Rather Tacky: They took the time to put the new entity has been put up on Softpedia and promote it without a single reference to Florian or Notepad2.

It's not that Florian doesn't appreciate improvements. He has put a number of modified versions his side, including a very minor update by Wesner Moise and I. If he wanted to incorporate these changes into the mainline he could easily. I included a source diff for him, but most importantly I didn't make it look like his work was mine!

Modified Versions of Notepad2

When people do Open Source work, one of the things that is almost universal is the natural human need for appreciation. For attribution. One overarching intent of the whole Creative Commons with Attribution license and most Open Source Licenses is "just don't remove the part that says *I did this!*"

Flo says it well, albeit with some understandable passion:

Nonetheless, the author has chosen the name "Notepad3". Compared with the original Notepad, Notepad2 represents an evolution with new features. "Notepad3" implies the same, but with even less features, without any new development. Seems that the play on words is used to fool users into believing that "Notepad3" is something more advanced. The popularity of Notepad2 is being taken advantage of to attract some attention ― I have no idea what else might be the motivation of the author.

The author justifies the publication of "Notepad3" with the added installation and documentation (which is actually my documentation, and has always been there). Innovation equals zero. This causes confusion about the different versions available, and the reputation of my software is harmed when associated with that kind of sloppy, offending descendants (and, it makes me think how indiscriminate some well-known software sites are concerning additions to their repositories).

I have no problem with new versions of my software being released, even with minor changes ― my licensing conditions are fully met. The problem here is that the author made minor changes to the code and branded it in a very disingenuous and deceiving manner.

Perhaps this is just a faux pas, a minor misunderstanding. However, I would encourage Readers who are interested in getting into Open Source to think about these issues when getting involved in projects.

My Own Experiences in Open Source

I've had a lot of great experiences and one speed bump.

WatirMaker

When I wrote WatirMaker and released the source, I had written it from scratch. Each time it got forked or written again or modified, the folks who did it let me know! They asked for help! I offered help! It was a lovefest - the kind of lovefest that I think Open Source should be.

The email conversations usually went like this:

Dude, heads up, I want to do _____

Sweet! Rock on, let me know if you want help with ____ or if/when/how we can put _____ back into the source. Wanna join the project!

Sweet! Dude! Rock on!

Yay! <Hugs.>

And the results were cool.

Notice how everyone is genial, chatting, and attributing? Even in Richard's WatinRecorder post, by now likely a complete re-write of my stuff, was thoughtful enough to thank a bunch of folks.

DasBlog

DasBlog, now the work of dozens, originally came from Clemens Vasters, who originally got it from Chris Anderson's BlogX had a similar issue happen when a gentleman forked our Source Code and created an entirely different project out of it with an all new name. This happened two years ago and he's since changed/refactored the project pretty substantially, but it still felt crappy at the time and the team was rightfully torqued. At the time, all that had been done was a recompile under VS2005 and a check-in as a new project with a new name.

Justice Gray blogged about it soon after:

Saying that "in the long term, ThinkJot will move away from the original dasBlog source code",  implies that all you've done is make some minor project ports, throw in a new DatePicker and call this your own project.  For sure, it's probably legally fine given the terms of the open-source license, but it leaves a bad taste in my mouth.  How would you feel if you worked on something for a long time and then someone just took all the work you did, rebranding it and called it their own?  I mean, c'mon!

Fortunately the author posted about this later and admitted this most important point:

"My biggest mistake has been that I never talked to the dasBlog team previously about this. I admit it, and apologize."

And I give him full credit for that simple admission. Folks that copy/fork are rarely evil or malicious. We're all just trying to move the ball forward, and perhaps that's the same in the case of Notepad3. However, that doesn't change the fact that talking to folks up front can make all the difference.

Unfortunately, at this point, this issue has soured Florian considerably:

I have been working on Notepad2 over more than 10 years, altogether. The above hacks may have been done in a few minutes.

There have been similar cases in the past, already, but this one really beats everything. I'm not sure if I'm going to release any more open source versions of Notepad2, in the future. Ain't fun like that.

Let's encourage Florian to keep up the great work and as we go about our lives as members of the Open Source community, let's remember to appreciate all the hard work that folks put into their various projects and that just because Copy/Paste is easy doesn't make it right.

My Tips? When in Doubt...

If you're doing Open Source and you're unclear about Netiquette, then:

  • Just ask.
    • Ask someone working on a project how they do it.
  • Err on the side of attribution.
    • You can't attribute or thank too many people, especially if you've copy/pasted something.
  • Reach Out.
    • Email the authors. Talk to people, join mailing lists and for goodness sake, avoid working in a vacuum.
    • I still get emails about GlucoPilot, a shareware app I wrote almost 8 years ago. If I had the rights to the source, I'd give to the world. (Still working on that, actually)
  • Appreciate your peers and everyone that contributes to the community.

What do you think?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.