October 2007 - Posts

Schemas in the scheme of things...

I got an interesting email today, which, to paraphrase, said:

I would like a syntax where I can say “an XElement that follows this XSD"

This question actually digs deep into the issue of strong typing versus dynamic typing and what it really is we want from a type system.

A lot of people think of strong typing as a forced constraint that ensures that types used are are of a particular type and that this constraint can then be used to facilitate design time checking and the intellisense experience. Although this is true, people often forget that the strong typing doesn't eliminate type errors, it just limits them. For example, whenever you do a narrowing cast you risk a runtime error not a design time one.  In .NET the need for narrowing is pretty common: one only needs to think of the standard event signatures where sender is always As Object. So what strong typing does is "shift" some of the errors.  When it comes to XML the concept of shifting the validation of the object becomes even more important

To address the problem of strong typing with an XElement, you could use inheritance but this raises a lot of issues. Factory methods such as Load return an XElement, so you'd have to provide your own Load methods. In the end it'd probably be easier to have your object model not inherit from XElement, rather just use XElement as the internal container.  This would give you the ability to write POCO (plain old CLR Objects) classes for your data, but in doings so you face a couple of serious design issues.  If you choose to validate the data at load time, that can cause excessive delays in loading the XML especially if parts of it are not used. If you don't validate at load, your object model can actually have an invalid state and do unpredictable things such as throw exceptions when a property is accessed.  And there's also the issue that XML can contain more data than the schema dictates. Do you loose that data or preserve it ? If you preserve it, then how do you provide access to it while also preserving the other data integrity ?

As you can probably see, there's a mismatch here between POCO and XML

If the goal is to validate the XML, you can do that with XDocument by providing a XMLReader with the XMLReaderSettings set to validate against a schema. Alternatively you can let the exceptions occur when a member is accessed. So XElement provides a flexible way of validating either when loaded or when accessed. But what's missing still is the design time experience...... 

So how can we get a great design time experience with an XElement akin to strong typing but without all the drawbacks strong typing and POCO present ?  I think the answer is in dynamic interfaces that are XElements, not POCO.  For example let's say I could write a:

Public XInterface IPerson
    <Name> As String
    <Age> As Int32
    @ID As GUID
End XInterface

You could then define an XElement parameter or variable as IPerson, and get a great design time experience.  You'd still have to decide if you wanted to validate your XML when you load it, or just wait and see, but really that's a great performance flexibility :)

The XInterface above is a simple model where you define the values in term of CLR types, so when accessed the appropriate conversions will be done from you from XML to that type. For more complex models it's be nice if you could also define a XInterface from a schema, and the compiler would infer the appropriate CLR types from the XML types. In this case you'd have to provide the schema to define the interface.

Imports XElement IPerson = "myPersonSchema.xsd"

Where "mypersonSchema.xsd" would be the name of a file in the project or a file path or URL/URI.

With dynamic interfaces that are based around XElement, you could provide a really great rich design time experience for XML.

Posted by bill | with no comments
Filed under: , , ,

I was robbed ...

of one hour of my birthday time thanks to day light savings :) The good news is it means summer is here !!

Oh, and I counted seven clocks I had to set the time on: 3 timers, 2 clock radios, 1 phone/answering machine, 1 car stereo. No wonder I don't wear a watch ;)

Posted by bill | 5 comment(s)
Filed under:

Is VB the n*gg*r of programming languages ?

When VB moved to .NET the claim was made it would be a first class citizen on the .NET platform. Despite that claim VB is often not supported in new SDKs or emerging platforms. Two major platforms where Microsoft has chosen to omit VB are:

  • XNA
  • .NET Micro Framework

Over the last month or so I've noticed an alarming trend in SDKs released that provided C# samples but no VB samples.  These SDKs include:

  • WCF LOB Adapter SDK
  • Health Vault SDK
  • Live ID SDK
  • Windows Search SDK

to name just a few. Typically when the issue of why isn't VB included is raised, the response is to blame resource constraints or similar. A typical example is the reply from Eric Gunnerson (formerly of the C# team) :

Currently, all our examples are C#. If there is sufficient partner interest in providing the samples in VB we will consider doing that, but we are currently focused on expanding our sample set.

When quizzed on this further, Eric elaborated to say:

It's hard to give an answer to the "how much interest" question because it would depend on a lot of other factors, but my guess is that we'd need feedback from a number of partners for us to commit the resources.

Just how many does it take remains un-answered.  I would have thought if it was a "first class citizen" it shouldn't take any, but surely one voice should suffice.  Perhaps they need VB'ers to gather together and protest loudly and write petitions ?  I'm sure we've all seen how successful that has been in the past.

Even when people inside Microsoft do hear the VB'ers asking for VB to be supported, the response is often just to ignore that.  Take for example the XNA framework. Over a year ago Gary Kacmarcik of Microsoft wrote :

From the cries of outrage that I've seen so far, I would be surprised if VB was not supported as a first-class citizen in a future release.

I wonder if he really was surprised when the new version was recently announced and VB was yet again omitted.  Earlier this year I heard MVPs raise the same question. The response from Microsoft was that XNA was too hard for VB'ers.  From a recent newsgroup posting, a VFP MVP summed this up well:

The last time I attended a summit, the VFP crowd was shoehorned into a VS
presentation where this was made abundantly clear. The speaker described VB
developers as "needing special help", and various other denigrating and
downright insulting remarks followed. Amazingly arrogant and insulting.

We walked out en masse after about 15 minutes.

However, in some areas though Microsoft does go out of it's way to ensure VB is well represented. Joe Stagner from Microsoft explains why the "How do I ?" videos are recorded in VB instead of C#. Joe says "There are more VB programmers than C# developers". I'm not quite sure why he felt one group are "programmers" and the other "developers", but one thing is clear is that Microsoft believes there are more VBers than C#ers. 

Microsoft itself primarily chooses to use C# internally, yet , even though they know there are more VB customers, they don't take any balancing action to ensure that VB is included in the SDKs or frameworks. It's no coincidence that VB is omitted from the cutting edge technologies, but extra care is given to ensure that the "How do I? " videos are in VB. It's all part of the patronizing viewpoint Microsoft portrays of it's VB customers.  Hence the title of this post.

Many of you may remember John and Yoko Lennon's song "woman is the n*gg*r of the world". When asked about the song, John quoted Congressman Ron Dellums, the then Chairman of the Congressional Black Caucus:

If you define n*gg*rs as someone whose lifestyle is defined by others, whose opportunities are defined by others, whose role in society is defined by others, then good news! You don't have to be black to be a n*gg*r in this society.

For VB Microsoft sets the rules, defines the lifestyle and opportunities for the language.  In terms of programming languages, Microsoft chooses to be all white males only (C#) yet takes no affirmative action to ensure VB is treated equally.  It's not that VB is lesser as a language, it is the way Microsoft treats it, and those who use it, that is the issue of extreme prejudice.

I can't help but think of the movie "the commitments" when they said "The Irish are the n*gg*rs of Europe".  More so than the message there, the name of the band.... Microsoft caused a lot of pain to the VB community when they abandoned VB6 and moved to .NET. At the time they promised that the changes would hold VB in good stead as a first class citizen on the .NET framework.  They made a commitment to us all. And for all intensive purposes VB as far as programmatic functionality is concerned is equal to C#, just as man is equal to woman, and man is equal to man. But that's not the way Microsoft treats it

 

Sadly, it seems that VB is the n*gg*r of Microsoft's programming languages.

Posted by bill | 35 comment(s)
Filed under: ,

When is something ready to be marked as Deprecated ?

Of programming languages, VB has in many ways had a checkered history mainly due to the changes from VB6 to VB7 (VB.NET). I remember clearly the change from "Wend" to "End While".  Some folks claimed that was "gratuitous".  To me, I couldn't see what the big deal was about... the IDE would fix it if I typed Wend, and the language itself was clearer/more consistent. I think that's the real problem with deprecation, not the fact that changes might actually be good, but more so some folks will make lots of noise about any change that is made.  Paul ventures into this territory again... perhaps now folks that are using VB (.NET) are over the VB6 to 7 round of changes ;)

Looking at Paul's list :

  • Type characters.  I never use them and can only remember $ for string.  It'd be nice if you could type Dim s$ and have the IDE auto-magically spell that out as Dim s As String  :)
  • Copying of boxed value types.  That's a big can of worms.  At present VB attempts to make value types behave as value types when boxed. I'd say leave well enough alone unless there are specific reasons to change this. That time evaluating and making the change might be better used elsewhere ;)
  • Mid$ assignment. How will this impact on upgrading code ? I think it's actually deceptive given the way strings work in .NET is different from the Ole strings, so a truer upgrade would be to change the code to an assignment, e.g  s = Mid(s, 2, 3, "abc"), or even better a Replace overload on String, such as s = s.Replace(2,3,"abc").  Unfortunately there is no Replace method on String that provides that functionality.  Until there is, I'd leave this one alone too.
  • End statement.  Well I used this just the other week.  It was in an upcoming article I wrote on using NamedPipes to replace the issue ridden VB single instancing framework. In my case, the "My" framework was just initializing, so their was no My.Application that could be used.  I probably could have used System.Environment.Exit, but that seems like a step backwards somehow.  A quick peak in reflector shows that End also ensures that any files opened the old fashioned way are still closed.  So removing this could have upgrade issues.  I also don't see any gain in removing it other than perhaps the impact it has on statement completion and line continuation.  If it's removal is needed for support for line continuation without the _'s, then I'd vote for a replacement, such as VB.End or Micsosoft.VisualBasic.End
  • Erase statement.  Yes it's useless and deceiving.  The big issue is ensuring an update wizard addresses this properly, including one Vb6 to VB 10, and VB7, 7.1, 8 and 9 to 10.
  • REM  I think the only person I've seen using them is Erik ;)  But is there much gain in removing them ?

 

Where I'd like to see deprecation address is Option's.  First Option Compare Text should be completely deprecated. There's other ways to do those comparisons and it really does add a LOT of baggage to VB's string comparisons. Option Explicit Off is also one of the most useless error prone options a language could have. Option Strict Off does have usages, but the language should instead provide explicit ways of doing the late binding that provides,such as dynamic identifiers and dynamic operators.  With them in place Option Strict becomes obsolete.  And that leaves us with Option Infer. If these other options are removed then there is no longer a need for Option Infer. 

Posted by bill | with no comments
Filed under: , ,

VB 10 thoughts (part 9)

 

31. Templates for anonymous types

It'd be nice if you could change the template used for anonymous types, such as to include INotifyPropertyChanged or other functionality. If you add a template to your project, you could then specify which template to use, e:g

Dim customer = New With{.FirstName="Fred", .LastName="Flintstone"} BasedOn mytemplate
 

Similarly:

Dim projection = From c in Customers _
                            Where c.LastName="Flintstone" _
                            Select New {c.LastName, c.FirstName} BasedOn mytemplate

 

32. Scripting support

Runtime features like creating new types on the fly (including support for templates as per #31), an Eval function, and general ease of dynamic interaction.

 

33. Support for parallel programming

Full support and possible language enhancements around multiprocessor architecture and parallel programming.

 

34. Lean and Mean option


Ability to turn off, or make it a warning anytime any VB helper functions are used, as well as make the assembly as light weight as possible.  For example, if I had Option LeanAndMean On, a If string1 = string2 statement would use String.Equals rather than any VB helper library functions.

Posted by bill | 4 comment(s)
Filed under: , ,

VB 10 thoughts (part 8)

Today I was only going to add one, item, #29, but in writing the samples for it two more items came to mind. One however was an IDE thing more than a language thing, so just 2 items for the list today :)

 

29. Embrace declarative style coding

VB led the way with declarative coding in .Net with declarative events and interface mapping. LINQ, WPF and WCF all encourage us to move towards declarative style coding, and this is a good thing. But today many of the common patterns we use are still implemented imperatively rather than declaratively.

For example, a bit over 3 years ago I blogged about Custom Events in VB, and how I thought it missed the mark because all we got was low level nuts and bolts to then write our own imperative code.  What I suggested at the time was look at the reasons people use custom events and from there provide simple to use declarative style syntax. Have a read of that blog entry to see what I mean.

Let's look at other examples to get just a hint at how broad this could be.  For example you might raise a PropertyChanged event inside your property Set. That pattern might look a bit like this today

 

   Private m_Name As String

 

   Public Property Name() As String

      Get

         Return m_Name

      End Get

      Set(ByVal value As String)

         If value <> m_Name Then

            m_Name = value

            OnPropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Name"))

         End If

      End Set

   End Property

 

 

   Protected Sub OnPropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs)

      RaiseEvent PropertyChanged(sender, e)

   End Sub

 

 

Wouldn't that be a lot nicer if we could just write that as :


  <RaisesPropertyChanged> _
  Public Property Name() As String


 

Likewise we could start looking at declarative patterns, be it common binding or range validation, etc.  Embrace declarative :)

 


 

30. Allow seeing the types in ambiguous namespaces

In their infinite wisdom, the Windows.Forms team created a System.Window.Forms.ComponentModel namespace.  And because the default imports for a VB Winforms project is System and System.Windows.Forms, you can't use the ComponentModel namespace in either, instead you have to fully qualify it. What a right royal PITE.  You should be able to use the types in there, and only on the types that are ambiguous should this raise an error asking you to qualify the name.

 

.

Posted by bill | 3 comment(s)
Filed under: , ,

VB 10 thoughts (part 7)

I've still got some more thoughts, but these are beginning to be big items, so I'm only touching on two more today

  1. Backing fields nested inside Properties

     

       Public Property Name() As String

          Dim m_Name As String 
          Get

             Return m_Name

          End Get

          Set(ByVal value As String)

             m_Name = value

          End Set

       End Property



    In the above example the backing field is nested inside the property. This provides a lot more flexibility in the code editor experience as well as possibilities to limit the accessibility of the backing field. Typically you could access m_Name through-out the class. With this pattern that could be limited to only inside the property. This could be modified perhaps with an attribute, such as VisibleTo(VisibilityEnum), to indicate accessibility is the Property, Class, or PropertyAndConstructors. The later is useful for deserealisation when you want to set the backing fields only in constructors (or the property itself)
    The nice thing about this pattern is it is compact.  If you collapse the property the backing field is hidden, in fact it would look very much like a backed property short syntax, in fact it could be. With this syntax you can expand the property and set a break point on the property Set while not setting one on the property Get.

  2. Mixins

    Although interesting, I'm not convinced of their real value. For VB they could raise a whole set of issues around interfaces. Still, when you do need/want them, they'd certainly come in handy.
Posted by bill | with no comments
Filed under: , ,

VB 10 thoughts (part 6)

  1. Standardization

    IOSO or ECMA standardization, to allow fully open development and meet organizational and governmental requirements for open standards.  At present part of the language is under Patent protection, making it unclear for example if a third party provider can use the IsNot operator for example.

  2. start of a statement with ()'s

    Instead of having to create a temporary variable to start a thread:

    Dim th As New Thread(AddressOf bar)

    th.Start()


    be able to call it as such:

    (New Thread(AddressOf bar)).Start()



  3. Range Expressions

    It'd be nice to be able to write
        If 50 < x <= 100 Then


  4. Namespace escaping

    I like using VB's root project namespace features, but at times I'd like to change that for one particular class or set of classes in a project. The only way to do that at present is remove the default namespace for the project. Where it be:
    Namespace  Global.NewRootNamespace
    or:
    Namespace  ...NewRootNamespace
    or:
    Namespace  \NewRootNamespace

    as long as there is a way to do it :)
Posted by bill | 3 comment(s)
Filed under: , ,

Playing with Extensions and Expressions

Expression trees allow you to walk through all the information about an expression.  So you can use this to create a NameOf function similar to the one I outlined in my post on VB 10 thoughts (part 5)

 

   <Extension()> _

   Function NameOf(Of T1)(ByVal obj As T1, ByVal fn As Expression(Of Func(Of T1, Object))) As String

      Dim op = fn.Body.Cast(Of UnaryExpression).Operand

      Select Case op.NodeType

         Case ExpressionType.Parameter

            Return op.Type.Name

         Case ExpressionType.MemberAccess

            Return op.Cast(Of MemberExpression).Member.Name

         Case Else

            Return Nothing

      End Select

   End Function

 

 

   <Extension()> _

   Function Cast(Of T)(ByVal obj As Object) As T

      Return DirectCast(obj, T)

   End Function

 

 

To use the method you still need to pass in a lambda, e.g :

Console.WriteLine(obj.NameOf(Function(x) x.FirstName))  'returns "FirstName"

Console.WriteLine(obj.NameOf(Function(x) x)) 'returns obj's Type's Name



Of course this all happens at runtime, so it isn't probably the best way to go about it. But it's fun seeing what you can do with Expressions ;)

Posted by bill | with no comments
Filed under: , , ,

VB 10 thoughts (part 5)

 

  1. a NameOf operator
    you could use this similar to TypeOf, but to get the name of a class or a method or property etc.

    NameOf could be used :
    - without any operand to return the name of the current method/property, e.g NameOf()
    - using an object reference ot get a typename, e.g NameOf(Me) gives the name of the current class
    - get the name of the current class in a Shared method by using the Class keyword, NameOf(Class)
    - get the name of a method as a string, NameOf(Foo.Bar) returns "Bar". Although this last case doesn't seem important, it does allow for compiler verification

       
         Public Property Text As String
              Get
                  ...
              End Get
             Set(ByVal value as String)
                 OnPropertyCahnged(NameOf())
             End Set
         
          End Property

  2. Shared Class'es
    Although a Module is basically a Shared Class, I would like to be able to use Shared Class instead and in particular would like to be able to stop the implied importing of the Module namespace that currently occurs.

  3. Extension methods in classes
    This would be handy to provide methods that are Shared in nature, while allowing for member evaluation. For example, let's say you have a Class Foo and it has a Count property.  If you were to write obj.FooProperty.Count you could get a null reference exception if obj.FooProperty is Nothing. If however Count was an extension method, you could decide to return -1 if FooProperty was Nothing.


  4. Properties as Extension members
    I saw this posted by a fellow MVP the other day, and think it would be a nice addition. Just as you can have extension methods, have extension properties.
Posted by bill | 2 comment(s)
Filed under: , ,

VB 10 thoughts (part 4)

still teasing out thoughts from the cobwebs

  1. Date literals
    today in VB you can only specify date literals in the format of #MM/dd/yyyy#
    That's incredibly USA centric. I'd like to input date literals in the form of dd/MM/yyyy, but because that would cause an ambiguity, I'd really like to see dd MMM yyyy, or failing that the ISO 8601 standard format of yyyy-MM-dd and yyyy-MM-ddThh:mm:ss
  2. select case object
    I've been asking for this one for so long I forgot about it till I read the comments on Paul's blog.
    Ideally in the format of :

       Select Case sender Is
            Case TextBox1
                 ....
            Case TextBox2
                 ....

    similarly

  3.    Select Case TypeOf(sender) Is
            Case TextBox
                 ....
            Case Label
                 ....



  4. Catches in Using blocks
    Again this is one that I had forgotten about.

    Using aDisopable As  .....

    Catch Ex As Exception

    End Using
     
  5. Calling partial methods
    VB 9 gives us partial methods, but the partial method itself has to be empty. It would be nice if there was a default method generated which you could still use, similar to the capabilities or Overrides but without the inheritance need.  I thought the use OverWrite could be used, e.g:
     
  6.    'generated code
       Overwriteable Sub Foo()
          Dosomething()
       End Sub
       'user code
       Overwrite Sub Foo()
          DosomethingElse()
    Overwriten()'calls the generated overwriteable method End Sub

     
     
Posted by bill | 4 comment(s)
Filed under: , ,

Inline casting

I wrote a couple of really simple extension methods, Cast, and TryCast, that allow me to write code such as sender.Cast(Of Control).Text = "hello world"

   <Extension()> _
   Function Cast(Of T)(ByVal obj As Object) As T
      Return DirectCast(obj, T)
   End Function

   <Extension()> _
   Function [TryCast](Of T As Class)(ByVal obj As Object) As T
      Return TryCast(obj, T)
   End Function

 

Note how the TryCast method requires the AS Class contraint on T. This is because the operation returns a null reference if obj is not of type T. (which you can't do for value types, instead you'd get a default value type, hence the need for the constraint)

Posted by bill | with no comments
Filed under: , ,
More Posts Next page »