Not Gonna’ Rebuild My Hard Disk This Time ‘Round
As I face the upcoming release of Visual Studio 2010, I am contemplating a machine cleanup. It’s been six months, my drives tend to gather a lot of junk.
And I’ve rejected the notion of rebuilding my drive. It takes time I don’t have, and far worse, it’s scary and I’m trying to remove scary things from my life. It’s scary because it means I have to lean out on my safety line. My safety line is my backups, and yes I make sure the knot looks good. But my Dad once leaned out on a safety line in a tree stand and, well, let’s just say we’re glad he’s still here.
So, the options as I see it are what I really want – a new T400s, with dual monitor support, multi-touch, solid state 256Gb drive, etc. Well, OK, let’s get real I don’t have a spare 3 grand, and my mechanic says I need a new car – what’s with that?
The option I can live with is a new 320GB 7200RPM drive for my current T400. That’s $120 bucks. I’ll slide my current drive (same specs), into the ultra bay thingee where I yanked out the DVD (who needs a DVD?), slide the six month old drive into a SATA USB enclosure I also just ordered, and live happily ever after. When I did this six months ago, it was to finally move up from my 5400RPM drive. This time, it’s
just to save some time and hassle.
There’s a catch though. It’s a bigger waste/carbon load on the planet. Thus, I need to ride my bike to the gym every day (well, every day I go) from now until the snow flies to earn back my karma points.
Anyway, with the Visual Studio 2010 launch a few weeks away, you should decide now if you’re going to cycle drives or rebuild your drive in time to get it ordered.
And yes, I’m working on a bluegrass song with the title of this post.
The Problem with Immutability
I’m writing this partly because I think there must be a happy solution and I just can’t find it.
I love immutability. Not all the time, but many times. I’d like to identify values which either because problems when they are changed, or they just do nothing. Of course reference variables generally need to be immutability, but they can also generally be initialized without any data – for example you can set a collection variable to an empty list in the declaration or the constructor.
The problem occurs with data happy classes – classes with strings or dates or integers or strings – where it is either dangerous or useless to set the values.
In traditional coding where you explicitly call a constructor, all is happy because you can create read only variables. You can assign to these variables in the constructor and they can’t be assigned to again.
But enter composition, MEF, IoC, whatever. Now, how do you manage those immutable values?
I’ve come up with four solutions:
a) Provide an Initialize method with positional parameters
b) Provide an Initialize method with optional named parameters
c) Write ugly code that tracks values and issues runtime errors
d) Provide a second interface that allows the sets
e) Use a singleton factory strongly bound to the actual class
f) Forget immutability
I’ll veto c for my work. Not only is it extra stupid code everywhere, but it throws runtime, not compile time errors.
If you need things to be “kind of, sort of” immutable, the interface trick would work. In some cases you might be able to limit visibility of the interface. But it’s not immutable.
I hate initialize methods. You have to remember to call them and its extra thinking. Without optional/named parameters they are extremely fragile to parameter list changes. And, it would be so weird to call Initialize twice on an object that I’m OK with the runtime error for that, and it can refuse to reset the values so you have nearly true immutability.
It’s not true immutability because the variables must be writable from within the class – for example, you could use private setters. This means within the class, the values can be changed rendering them less than fully immutable.
You could solve this problem if you created custom factories for every class you would instantiate items of. Instead of retrieving the new value via composition/MEF, retrieve the singleton factory. The factory could be hard wired to the actual class and thus directly call the constructor. A method like “Instantiate” could take as many parameters as needed, and could use optional and named parameters to avoid parameter list fragility issues.
This leaves me less than enamored with PartInitializer. It encourages us to skip immutability or to take shortcuts that leave our classes less than fully immutable. I’m not enamored with custom factories either. They are only a few lines of code, but they barf an implementation detail all over our code. Significant ceremony.
I’d beat up on the MEF team if I could figure out a way they could solve this with minimal ceremony.
Anyone have a great solution?
Silverlight Catastrophic Failure Message
I’m not convinced this error is nearly as catastrophic as Silverlight made it out to be, but I thought I’d share anyway. I received the following error while working before breakfast, I’m blaming it on the lack of Wheaties in my system.
? e.ExceptionObject
{System.Exception}
Data: {System.Collections.ListDictionaryInternal}
InnerException: Nothing
Message: "Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))"
StackTrace: " at MS.Internal.XcpImports.GetClassFullName(String coreClassName) at System.Windows.DependencyProperty.LookupAttachedCoreProperty(String propertyName) at System.Windows.PropertyPathParser.GetDpFromName(String name, Boolean namespaceMappingAvailable) at System.Windows.PropertyPathParser.ReadAttachedPropertyStepDescriptor(Boolean calledFromParser) at System.Windows.PropertyPathParser.ReadStepDescriptor(Boolean calledFromParser) at System.Windows.PropertyPathParser.Parse() at System.Windows.Data.Binding..ctor(String path, Boolean calledFromParser) at MS.Internal.FrameworkCallbacks.CreateBindingExtension(String constructorArgument, IntPtr& nativeOutValue)"
From searching the web I found a number of things that might cause this. Apparently it’s Siverlight 3’s way of saying “you confused me”. I didn’t find any issues relating to my problem, which happened to be on a date picker.
I had this code:
<controls:DatePicker Grid.Row="1" Grid.Column="0"
Name="StartDate"
DisplayDate="{Binding Values(0), Converter={StaticResource ObjectToDateConverter}}"/>
Did you catch it?
It was early, it was a VB project, I didn’t notice that I had reflexively used parentheses instead of square brackets on the binding to the Enumerable member.
VS 2008 Debugger Issue
I was trying to debug a Silverlight application when I encountered the error
“The debugger cannot continue to run the process. Process was terminated.”
Happily I found a thread that discussed this issue because it was certainly not what I was expecting or looking for.
I was touching a property which called an initialization process in its Get accessor (did I mention this was a really, really bad idea). I had added code that touched the property in an overriding method that was called from the Initialize method.
Unexpected recursion.
I can’t say whether there are other things that can cause this error, but if it occurs I suggest that you check carefully for recursion.
One of the reasons this error can behave bizarrely is that it may occur because of recursion as one of the automatic watch windows such as Locals is displayed.
Bruce McKinney on Visual Basic.NET
Many mixed feelings about posting this on the first day of the MVP summit. I got this email from Bruce McKinney this morning:
We haven’t talked for a while. I thought I’d let you know that I just posted a version of our discussion of VB.NET on my web site. Check out:
www.pobox.com/HardcoreVB/vbnet2.htm
How far out-of-date is this description of VB.NET in 2008?
It’s bizarre to think that most of the people on the VB Team have probably never heard of Bruce McKinney. I’m going to post this now because I received it now, and delaying it would be as much editorializing someone else’s post as deliberately timing it would have been. I did not. It came out of the blue this morning. Had I wished this to be main topics at the summit, I would have tried to get these things into our conversations weeks ago. I do not.
Obviously many of you do not know who Bruce McKinney is. Perhaps you don’t know who Dan Appleman is either. Perhaps you’re a C# programmer and think you just don’t care. But merging business programming and platform power started with VB (we’re comparing with Dbase and C++ in this time frame). The success of this merge is part of the history of C#, part of why the market existed in 2000. Bruce McKinney and Dan Appleman (and a few others) are the ones who proved that power mattered in such languages. They proved that business programmers could do great things and that they needed a powerful language to do it. Thankfully VB.NET/C# moved us an order of magnitude closer to the metal and allowed us to do the amazing things we do today.
That’s what Bruce meant to our collective history. Do you care what Bruce meant to me? As I look at the future and the work I’m doing to provide easier development and the thinking I’m doing to about the next level of abstractions, Bruce and Dan remain prophets. We can’t separate from the metal – which is why my current mantra is that we need to abstract application writing while not abstracting debugging and not hiding what’s really going on. Code still matters. Dropping down from an abstraction to the metal still matters. Anyone for in-line DSL? In line 3GL in a DSL? I believe understanding 3GL will eventually become as unnecessary as understanding assembly is today, but we can’t get there with a declaration or in a single jump or just because we want to get there. It’s a decade. We can only get there with a long iterative process that will require we go to the metal, understand why we went to the metal, and iterate again. Unlike VB6, we sit on an amazing platform where this process will work. .
If you still can’t quite recall where you heard that name before – Bruce McKinney wrote Hardcore Visual Basic which was on the bookshelf of most of the people that pushed the edges of Visual Basic. And if you read Bruce’s piece, remember this is one of the smartest guys there was in VB6.
Tip on Debugging Stable Composition Problems in MEF
My debugging strategy is to develop a hypothesis or two, pick the easiest most valuable one to test, test it in the easiest manner, and go on. I’m working to disprove the hypothesis because this is far easier to do and helps avoid me getting stuck on a particular notion of what is wrong. A test is more valuable if it cuts out a greater portion of the possibilities for failure, which John Robbins calls the divide and conquer approach.
I bring this up to explain that I rarely use the reporting MEF provides to solve stable composition errors. Maybe one day I will, but its much faster for me to find the missing part and begin adding the “AllowDefault=true” parameter to the Import attribute. I’m not being chaotic or random, it just works for me.
This morning I remained a bit stumped by a stable composition error. I realized it was a stable composition error because it went away when I said “AllowDefault=true”. But, my own reporting and other tests showed that the implementation was clearly in the container. So, what was going on.
A passing hypothesis flitted through my head “what would happen if there were two?”
It was a quick test to put a break point right after composition competed and request the exports for the part. Voila there were two!
Two tips:
- Stable composition fails when cardinality is not correct. A big word say Import fails when there are zero or more than one match.
- If you have multiple discovery directories, it is very easy for common assemblies to wind up in more than one directory. This results in multiple matches, and why I had the cardinality failure.
Killer Feature for VNext – Language Embedded DSL
VS 2010 is nearly out the door, so it’s time to start fantasizing about killer features in the next version of .NET and Visual Studio.
The feature I want to see is “embedded DSL.”
Like many killer features, success comes from doing in a great way something you can already do halfway. So, I’ll demonstrate this feature in relation to T4 and a MEF scenario where it’s useful today. But before I get there…
I want to see DSL embedded in a language – maybe VB since it oddly enough has become the platform for experimentation, and since we’ve already started embedding other stuff in the language (XML). DSL implies particular syntax issues, but ultimately its metadata for code generation. I want to do code generation that is under my control in a fragmented way within the scope of normal code. Here’s a potential syntactic example:
Public Sub New()
‘ Normal Code
End Sub
{PropertyPattern}
{Property Name=”DisplayName” Type=String}
{Property Name=”DataName” Type=String}
{End PropertyPattern}
‘ More normal code
In this simplistic DSL, the Property metadata is just a pretty syntax for filling data into an interface. Wait, wait, you can’t stuff data into an interface. Right. You need an implementation which you can discover in real time (MEF anyone?) and that implementation can provide defaults for all the other values! And an include pattern here should let you reuse metadata defined once in your application.
PropertyPattern refers to a generation template – like an extended version of T4 – that can output real code in response to the metadata that’s passed. It’s an extended version because it’s strongly typed to the metadata defined via the metadata/DSL interface. The pattern is also discovered (MEF anyone?), which, well just trust me on this, allows a full governance model (customizing and governance on templates is one of my specialties, but let’s not geek out on that right in the middle of a hot fantasy). In simple terms, the governance model means a fallback mechanism through project (assembly), to group, to organization, to defaults/in the box.
Before I go further, let me say this is not a replacement for application generation. Application generation and code generation aren’t the same thing. Application generation is either a closely linked set of templates where the interrelations are as important as the templates, or application generation is architecture generation which is a new and emerging field.
Back, to the fantasy, because it’s an important part of a bigger picture of changing how we write applications…
Is this fantasy just Kathleen on too much MEF?
Actually no MEF required at all this morning… let me show you how to do this today – no compiler changes, no new dependencies, you can do this right now in VS 2008 (if you download the DSL Toolkit so you have T4, which you already did anyway, right?).
Well, OK, just a little MEF to get our morning started… the scenario is a MEF scenario, although there is no MEF in the solution. When you work with MEF and you want to create a MEF friendly interface for later discovery, you create an interface that a part will later fulfill, a separate interface of composition metadata, and a custom export attribute, which allows you to define a part just by implementing the first interface and tossing on the attribute. Whew! This means there is an annoying tedious (but technically elegant and necessary) pattern that I’ve implemented perhaps a billion times. What’s worse, the pattern obscures information about the interface, which of course I should also include in XML Documentation so I’m not in the code in the first place checking out the info – but see, more internal redundancy. And oh, by the way, if you screw up the pattern, the bugs can be very hard to track. Let’s fix it…
[NOTE: The implementation jumped back and forth between VB and C#. In VB, I’d implement this as XML literals which makes a more concise syntax with way less code in the included template, but T4 barfed at the XML literals and I didn’t feel like bothering with it today. Without XML literals, C# has better syntax because of the collection initializers which don’t make it into VB until 2010. There is no relation between the syntax of the DSL and the output syntax. I happen to be outputting VB.]
I created a T4 template. If you’re in VS2010, this is a normal Text Template, not a preprocessed one. If you’re in 2008, create a text file and give it a .tt extension. Also copy in the MefInterfaceDsl.t4 file that I’ve attached into your project. (I tested in VS 2008, in VS 2010, you may need to change the extension to .tx) Yes, your DSL will be written in T4 and yes, your DSL T4 template will have a different extension than the supporting one. That’s because Visual Studio outputs code for a file with a .tt extension and does not for one with a .t4 extension. You want output only from your DSL T4.
Here’s the template, then more talk:
<#@ template debug="false" hostspecific="false" language="C#v3.5" #>
<#@ assembly name="System.Core" #>
<#@ output extension=".vb" #>
<#@ include file="MefInterfaceDsl.t4" #>
<#=
new Interface()
{
Name = "ISearchModelBase",
Scope = Scope.Public,
CompositionInfo =
{
new Property() {Name="TargetType", PropertyType="Type"}
},
Members =
{
new Property() {Name="DisplayName", PropertyType="string"},
new Property() {Name="DataName", PropertyType="string"}
}
}.Output()
#>
Wow, is that really a DSL? Yes, but I won’t claim it’s a very good one. It’s a hack to allow the concept to work in VS 2008 and VS 2010, in hopes that we can get an elegant syntax in VS 20Next.
The initial four lines are a necessary T4 distraction. I’ve stated that the template language is C# with 3.5 extensions (not necessary in VS 2010). I’ve included core because it makes 3.5 work. I’ve stated that output will be in .vb. The actual syntax for the output is in the include file. Remember this is a working sample, if you wish to use this, you’ll want to enhance the MefInterfaceDsl.t4, including rewriting it to output C# if that’s your current flavor preference.
The include file has a class named Interface, Property and a few others. Initializers and collection initializers build the graph for the ISearchModelBase interface which has two properties, and one composition metadata property. The Interface class has an Output method that returns a string with the code output. Visual Studio places this output in a dependent file (select Show All Files to see this in VB). I included it below so you don’t have to run a project just to see the output.
Since the artifact is generated, I don’t have to remember the pattern and I’ll never be bit by forgetting to set AllowMultiple=false. Since the DSL/metadata is in the project beside the artifact, I can find an work with it (this would not be appropriate for application generation DSL/metadata whose artifacts spanned many projects, solution, and platforms).
So why is a normal T4 template a DSL? Because a DSL is a way to define generation information (metadata) in a way that is friendly to the human, followed by artifact generation.
I want this extended to be a true embedded part of the language to avoid these limitations and supply these features (and probably a bunch more stuff I haven’t thought of):
- - Can be any part of any normal code file
- Not limited to entire files (although the T4 output can be partials)
- The DSL/metadata is a holistic part of the code
- - Artifact patterns (templates) are discoverable (can be anywhere by anyone)
- - DSL/metadata patterns are discoverable (default values and pattern extensions
- - Intellisense on the DSL
- - Better syntax (drop the new and other class residuals)
- - No reliance on file location (the T4 support file must be in relation to your project)
- - No ugly opening stuff about T4 unrelated to the task at hand
- - Standard extensible metadata/DSL patterns provided
- - Standard extensible artifact patterns provided
Here’s the output:
Option Strict On
Option Explicit On
Option Infer On
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.ComponentModel.Composition
public Interface ISearchModelBase
Property DisplayName As string
Property DataName As string
End Interface
public Interface ISearchModelBaseComposition
Readonly Property TargetType As Type
End Interface
< MetadataAttribute() > _
< AttributeUsage(AttributeTargets.Class, AllowMultiple:=False) > _
public Class SearchModelBaseAttribute
Inherits ExportAttribute
Implements ISearchModelBaseComposition
Public Sub New( ByVal targetType As Type)
MyBase.New(GetType(ISearchModelBase))
_targetType = targetType
End Sub
Private _targetType As Type
Public Readonly Property TargetType As Type Implements ISearchModelBaseComposition.TargetType
Get
Return _targetType
End Get
End Property
End Class