- Hidden Gems in Visual Basic 2008 from the VB Team themselves
- Visual Basic 9.0 Feature Focus a series of posts from Bart De Smet's B# blog
- Syntactic Sugar, Compiler Candy, and Other Sweets from James Kovac (C# biased, but applicable for VB9 too)
This is my personal blog - stuff not directly connected to my work goes here - some of it's a little spicy, so watch out for heartburn. Of course if you're lucky you'll find something valuable in the mix of product development, Agile development, innovation, technology and marketing that I write about.
Thursday, January 17, 2008
New in VB9
Wednesday, January 16, 2008
2008 has arrived!
- Windows 2008 Server
- SQL Server 2008
- CommunityManager.NET compiled under Visual Studio 2008 (targeting .NET 3.5 )
Coatesy gave us a kind word too.
Big props to Balaji (where's your blog man?) for putting in the hard work to make sure the CM code could compile and run under .NET 3.5. Craig mentions some of the other heroes that helped get this done, but Rajesh, Imad and Yul missed mentions there, so here's thanks to them too!
Saturday, January 12, 2008
VB.NET is the illegal immigrant of Microsoft languages
[NOTE: Another accidental thing that denigrates VB is that we must put ".NET" at the end if we are talking about 'real' development, because VB as a term covers such a broad range of languages. This alone makes C# seem exclusive and more 'grown-up'.
The Pragmatic Programmer
Internally however Microsoft have a culture that prefers people using C#. In practice this means that the 'cheap' option is always to do code samples and demo code in C# and not VB (or some other .NET language), because it is simply more convenient to do so. When asked why a given example is not also in VB, this is the answer given (and the occasional plea for help). There is however a tendency to see VB developers as somehow inherently less capable that C# developers - perhaps this is a view that the 'best' work at Microsoft, or maybe it's a hangover from the "Basic" part of VB's name. Most probably it also has a lot to do identifying VB users with using a persona called 'Mort', whilst C# is Elvis and C++ Einstein (thanks usability guys).
A few months ago Bill McCarthy, a VB MVP, ranted about this issue in his post Is VB the n*gg*r of programming languages?. Leaving aside a controversial choice of words (for which he was smacked down), he had a very good point. My post's title is a reference to his point (with a more PC turn of phrase).
Bill points out that how to videos (for beginners?) are often coded in VB, but the SDKs have C# examples (for real developers?).
A more recent balancing view comes from Scott Hanselman, who asks Is rooting for Visual Basic like rooting for the Red Sox?. Leaving aside the unfortunately humorous connotations of 'rooting' to us Aussies, his point is that VB is making something of a comeback in popularity, but old-timers (like Bill?) still want to feel like underdogs. Reading the rest of Scott's blog shows that he's been exploring beyond the homely environs of C# and hanging out with people who are pragmatic enough to use whatever works.
Personally I think this last point is the one that makes the most sense. In The Pragmatic Programmer Andy Hunt and David Thomas said:
“Computer languages influence how you think about a problem, and how you think about communicating ... Designing a solution with Lisp in mind will produce different results than a solution based on C-style thinking, and vice versa. Conversely, and we think more importantly, the language of the problem domain may also suggest a programming solution.”
All of this is what has attracted me to the ALT.NET movement (see the first use of the term, the conference last year, it just had a leadership summit and a Yahoo! group). Martin Fowler weighed in and said this about ALT.NET:
“The alt.net mind-set is one that is very familiar to me. It has that mix of agile + object-orientation + patterns + TDD + DDD which is very much the school of software development that I favor. (Lacking a proper name for it, I'm inclined to call it the OOPSLA school of software development.) There is certainly a belief that there is a mainstream Microsoft orthodoxy at the moment, one that doesn't fit the OOSPLA school. And there's some frustration with that. But the point here is that it's not that the alt.net community thinks that the perceived mainstream Microsoft route should be erased, but that the Microsoft world is big enough for different approaches.”To all this I say a big hooray! But ... it seems everyone who wants to do something with ALT.NET is a devoted fan of C# (or at least NOT a fan of VB). So every code sample, explanation or tool is aimed at C# and either requires much grokking to be used in VB, or in many cases, cannot be used with VB at all.
The answer I'm afraid is that I must use more C# if I want to become more agile, practice TDD or play with ASP.NET MVC. The fact that I get paid to work with VB.NET is not a good enough reason to stick with it. VB is the illegal immigrant of .NET languages, it snuck into .NET when it should have been told to stay away (perhaps forcibly deported) and the sooner any of us who use it realise that, the better. Shifting to a true .NET citizen like C# is clearly the only responsible thing to do - and using those Johnny-come-latelys like IronRuby or IronPython (or Boo) is a joke - they are only toy languages, not super-strong doers of great deeds like C# is.
Still, at least there is one hope on the horizon, with Silverlight assuming such importance in Microsoft's plans for the web, perhaps VBx will come to our rescue? With VB moving into the DLR perhaps VB developers can all become the new, new boys on the block, and start looking down on those poor C# types who are unable to duck-type or use Jasper. And my persona? Let's just call him Ben.
Wednesday, January 09, 2008
Cargo Cult Programming
“Cargo cult programming is a style of computer programming that is characterized by the ritual inclusion of code or program structures that serve no real purpose.”
Tuesday, January 08, 2008
Buggy VS2008 debugging
Monday, January 07, 2008
Partial classes and methods in VB.NET
To be clear, the generator would create seven files:
- Basic entity class (e.g. Group.vb)
- Collection class (GroupCollection.vb)
- A DAL class (e.g. GroupDAL.vb)
- Insert stored procedure
- Update stored procedure
- Delete stored procedure
- Select stored procedure to get a single record by primary key(s)
The first step was to add more smarts to the templates so that the generator could handle some difficult situations (multiple primary keys, non-identity single primary keys) and to add in some additional base functionality (collection sorting, object caching, OnValidate checking that the IList interface is not being abused).
For a good article on strongly typed Collection classes check out this one on Builder AU.
Next we looked at the range of customisation we already had in existing data layer classes and ways of separating this out so that we could add ways of getting data that meet specific business requirements without polluting our generated classes. The answer of course was to use partial classes.
Our DAL classes now start like this:
1 Imports System
2 Imports System.Data.SqlClient
3 Imports System.Data
4 Imports System.Text
5 Imports System.Collections
6 Imports Elcom.Common.Data
7
8 ''' <summary>
9 ''' Data Access layer (DAL) class for Group entity objects.
10 ''' </summary>
11 ''' <remarks>
12 ''' Auto-generated by Elcom Code Generator at 4/01/2008 4:01:03 PM.
13 ''' </remarks>
14 Partial Public Class GroupDAL
15 Inherits BaseDAL
16
17 ''' <summary>
18 ''' Constructor method is declared and made private to ensure
19 ''' class is a singleton.
20 ''' </summary>
21 Private Sub New()
22 End Sub
23
24 ''' <summary>
25 ''' Public 'Instance' method allows external objects to access
26 ''' the current singleton instance.
27 ''' </summary>
28 ''' <returns>
29 ''' Returns a reference to the single GroupDAL object
30 ''' in memory.
31 ''' </returns>
32 Public Shared ReadOnly Property Instance() As GroupDAL
33 Get
34 If _instance Is Nothing Then
35 SyncLock GetType(GroupDAL)
36 If _instance Is Nothing Then
37 _instance = new GroupDAL()
38 End If
39 End SyncLock
40 End If
41 Instance = _instance
42 End Get
43 End Property
The DAL additional class looks like this:
1 Imports System
2 Imports System.Data.SqlClient
3 Imports System.Data
4 Imports System.Text
5 Imports System.Collections
6 Imports Elcom.Common.Data
7
8 ''' <summary>
9 ''' Data Access Layer class for Group
10 ''' </summary>
11 ''' <remarks>
12 ''' Old code brought in as Additional partial class by Angus
13 ''' on 4/01/2008 for CM 5.5.
14 ''' </remarks>
15 Partial Public Class GroupDAL
16
Unfortunately we were still left with a major issue, some of the customisation we had made involved making changes to the way we saved some data items (e.g. encrypting users' passwords before saving them to the database), or having additional read-only data items that were not instantiated in the database table but properly belonged to the entity. The partial class solution allowed us to add extra properties, but did not enable us to override the basic Save() method, so what were we to do?
One option was to implement an alternative Save() method that differed either via parameter signature or name, but that would leave the incorrect one hanging around. Another trade off would be to customise the generated class file and just live with the necessity to not generate that file (problematic and prone to human error).
The answer turned out to be partial methods. The VB team blogged about these last year:
“Partial methods enable code generators to write extremely flexible code by creating a lot of "hooks", where developers can provide their own custom functionality that integrates into the "boiler plate" code created by the generator. Because the hooks are optimized away if they aren't used, no performance penalty is introduced by defining them. This is really useful if generated code needs to be used in high performance scenarios. For example, partial methods are used by the DLINQ designer for exactly this purpose. Developers wishing to invoke custom code on their data objects when properties are set can do so without requiring all users of DLINQ to suffer performance problems.”So we ended up adding in calls to partial methods in all of our property setting code:
14
15 Public Property intGroupID() As Int32
16 Get
17 Return _intGroupID
18 End Get
19 Set (ByVal value As Int32)
20 ' partial event method to allow insertion of
21 ' behaviour using partial class
22 OnSettingintGroupID(value)
23 _intGroupID = value
24 End Set
25 End Property
26
We also ended up adding pre/post save calls to partial methods to allow us to intervene and tweak either data to be saved or to handle other behaviour post the save operation. An example of a typical save operation is below:
70
71 ''' <summary>
72 ''' Public method allows external objects to save changes to a Group object.
73 ''' </summary>
74 Public Sub Save(ByRef objGroup As [Group], ByVal blnForUpdate As Boolean)
75 Dim parameters As ArrayList = New ArrayList()
76 Dim sproc As String
77
78 parameters.Add(New SqlParameter("@strName",objGroup.strName))
79 parameters.Add(New SqlParameter("@intURLID",objGroup.intURLID))
80 parameters.Add(New SqlParameter("@blnAllowAddressUpdateInEshop",objGroup.blnAllowAddressUpdateInEshop))
81 parameters.Add(New SqlParameter("@blnShowAdminInTopMenu",objGroup.blnShowAdminInTopMenu))
82 parameters.Add(New SqlParameter("@strLDAPGroupName",objGroup.strLDAPGroupName))
83 parameters.Add(New SqlParameter("@strLDAPIdentifier",objGroup.strLDAPIdentifier))
84 parameters.Add(New SqlParameter("@blnSystemsAdministrator",objGroup.blnSystemsAdministrator))
85 parameters.Add(New SqlParameter("@blnRestrictAccessBaseFol",objGroup.blnRestrictAccessBaseFol))
86 parameters.Add(New SqlParameter("@blnRestrictArticleOptAttr",objGroup.blnRestrictArticleOptAttr))
87 parameters.Add(New SqlParameter("@blnRestrictFolderOptAttr",objGroup.blnRestrictFolderOptAttr))
88 parameters.Add(New SqlParameter("@blnForceSelectTemplate",objGroup.blnForceSelectTemplate))
89 parameters.Add(New SqlParameter("@blnRestrictChangeLayout",objGroup.blnRestrictChangeLayout))
90 parameters.Add(New SqlParameter("@blnRestrictAddElements",objGroup.blnRestrictAddElements))
91 parameters.Add(New SqlParameter("@blnRestrictCreateTempFromArt",objGroup.blnRestrictCreateTempFromArt))
92 parameters.Add(New SqlParameter("@blnAllowEventStatusUpdate",objGroup.blnAllowEventStatusUpdate))
93 parameters.Add(New SqlParameter("@blnAllowVenueLimitUpdate",objGroup.blnAllowVenueLimitUpdate))
94 parameters.Add(New SqlParameter("@blnAllowAddAttendee",objGroup.blnAllowAddAttendee))
95 parameters.Add(New SqlParameter("@blnAllowDeleteAttendee",objGroup.blnAllowDeleteAttendee))
96 parameters.Add(New SqlParameter("@blnAllowOnbeHalfRegistration",objGroup.blnAllowOnbeHalfRegistration))
97 parameters.Add(New SqlParameter("@blnAllowMoveEvent",objGroup.blnAllowMoveEvent))
98
99 ' partial event method to allow insertion of behaviour using partial class
100 PreSave(parameters, objGroup, blnForUpdate)
101
102 If blnForUpdate And objGroup.intGroupID > 0 Then
103 parameters.Add(New SqlParameter("@intGroupID",objGroup.intGroupID))
104 sproc = "proc_GroupUpdate"
105 ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, sproc, parameters)
106 Else
107 sproc = "proc_GroupInsert"
108
109 Dim intNewKey as Integer
110 intNewKey = CType(ExecuteScalar(ConnectionString, CommandType.StoredProcedure, sproc, parameters), Integer)
111 objGroup.intGroupID = intNewKey
112 End If
113
114 ' partial event method to allow insertion of behaviour using partial class
115 PostSave(objGroup, blnForUpdate)
116
117 ' refresh the cached version of this object
118 Dim cacheName As String = String.Format("Group:{0}", "" + objGroup.intGroupID.ToString() + "" )
119 RemoveFromCache(cacheName)
120 AddToCache(cacheName, objGroup)
121 End Sub
122
The end result for us was a much more flexible system of generated code which meant that we can now fix problems with out data classes in the templates directly and then just re-generate the code and replace the files in our project folders and commit to our source code repository (it helps that we use Subversion via TortoiseSVN).
Note: Thanks to Guy Burstein for taking the time to migrate the Copy Source as HTML addin to VS2008, even though it seems to have problems with my my colour scheme. Mazal Tov with that new MS job too!