So you're using .Net, but your last language was vb6? Odds are you're guilty of breaking several of these rules.
Do:
- Check Intellisense for new versions of old functions. Especially string functions. It's not that hard. Len() becomes .Length(). Trim() becomes .Trim(). Replace() becomes .Replace(). InStr() becomes .Contains() or .IndexOf(). Don't forget the newer methods for handling files, as well. Intellisense is your friend.
- Use paramterized queries when talking to a database.
- Use exceptions (Try/Catch/Finally) for error handling rather than On Error.
- Use StringBuilder for concatenating strings.
- Declare variables and function with explicit types (ie: Dim myVar As String, Function MyFunction() As Integer, etc). They said this for vb6, too, but a lot of programmers got away with variant types anyway. In .Net it is much more important.
- Use generic collections instead of arrays or ArrayList.
- Use the new logical operators (AndAlso, OrElse).
- Use Validator controls in ASP.Net
Don't:
- Use CreateObject(). Ever.
- Use Response.Write() in a web app, if you can avoid it.
- Use exceptions/errors for execution flow control.
- Use <% %> blocks in ASP.Net (there are a few exceptions here, but it's mostly true).
- Use Access for a web database. Or a desktop database for that matter (see SQL Server Compact Edition for a better alternative for most scenarios).
- Use CType(). I know it's tempting, but DirectCast() is faster if it's available, and otherwise Convert.ToTypeName() or Typename.Parse()/Typename.TryParse() are more appropriate.
- Use hungarian-ish prefixes for variables like obj, str or even just o. Microsoft's .Net style guide specifically recommends against it.
- Use Application.DoEvents(). .Net includes several more robust ways to keep your application responsive during long-running tasks. The BackgroundWorker control is one good alternative.
Another post prompted by questions seen in programming forums. Actually, this was prompted by several questions; it's a pet peeve list of common issues I see at programming help sites. I plan to come back to this post from time to time and add new items. Hopefully in a month or two it will develop into something actually useful to new .Net programmers rather than just a rant piece.
It's been very busy at work this week. I missed my Monday post and all I have ready today is a short update on my home server project. I have a private post where I keep a queue of ideas for future topics, and I have enough items there to keep me going a couple months. But most of them still need more refinement than I can do quickly when I'm in a time crunch, so there you go.
On to the server. I've installed MySQL and set up a dyndns.org account. I'm still lacking inspiration for exactly what the web site on the machine should look like. I just know the bare minimum for what I want it to do: point to the ftp shares and allow me to highlight specific file on the front page for family to view (mainly pictures of my daughter for the grandparents).
I decided to add another file share. If Melody wants to upload a large photo to her portfolio she has to sit and wait for a few minutes while each photo finished. If I happen to be in a game at the time the game gets screwed up. I'm going to create a share where she can drop in photos, and it will upload them automatically very early in the morning when no one is using the connection. Then she only has to wait for them to copy over the local network, and my game isn't interrupted.
On one final personal note, Melody's ultrasound is this evening. This is where we find out (probably) if we're having a boy or a girl.
Update (3/31): Set up dasBlog over the weekend. Oh, and it's a boy ;)
... and why maybe I should switch to C# after all.
Technical people are known for their 'religious wars': Windows vs linux, Emacs vs vi, and of course C vs VB. I am a rarity among programmers: one who has switched sides from the C curly brace camp to the VB.Net camp. I hear about the reverse situation all the time: VB6 programmers who were forced to learn C# when .Net came along and never looked back. That doesn't even take into account the countless programmers who learn one style first and continue to prefer that style for their entire careers. But I started out with C++, and in the end decided I like the VB-ish syntax. Why? Here are a few of the reasons I feel more comfortable with VB today:
- Case Sensitivity. VB is not case sensitive. I will never have to worry about a mis-placed shift key breaking my program. This isn't to say that VB is not case-aware. If that were true I would probably prefer C#. Instead the compiler takes note of the case used when you create a variable and will automatically format any further use of the variable to match that case. This helps spot typos as you write code, and is a real help for someone like me who makes typos frequently. To clarify, it's not that I prefer case-insensitive code. What I like is that IDE removes the need to care about case at all.
- That brings me to the next feature: Background Compilation. This really annoys some people, but I like it a lot. It provides instant feedback on what you're working on. I think perhaps this feature has to work with your coding style. It would be annoying indeed if you tend to write a lot of code that's just wrong until you add the final curly brace at the last moment. But that isn't me.
- Declaring new objects. In C#, if you want to declare and instantiate a new object you have to key the type name twice:
LongTypeName myVariable = new LongTypeName();
It's even worse if there's a namespace in there, which leads C# programmers to import a dozen namespaces at the top of each code file, even if they're only using one instance of one class in the namespace. I rarely need more than three of four namespaces, myself. VB's "Dim" is annoying at times, but for this scenario it results in much cleaner syntax. - Implicit Casting. There's a fine line to walk with this one. I don't like implicit casting from one type to another. But I do like implicit casting from child or parent objects to the actual type. In otherwords, if you could use DirectCast() in VB, the implicit cast is probably okay. The usually implies the target of the cast is part of the same inheritance tree as the source of the cast. An important addition to that general rule is implicitly calling an object's .ToString() method, which VB will also do for you automatically.
- End vs }. When I was learning C++, } was just another part of the language. You never even notice it. Even when I first learned VB.Net I didn't really know what was I missing at first. But it's just like getting a bigger monitor or a scroll wheel for your mouse. You don't notice the improvement until you've used it for a while, and then also need to go back to a system without the new feature. Only then will you be painfully aware of the short-coming. Many C-style programmers actually scoff at End If, End While, End Sub, and so on. But they've never used it. Give it a chance, and trust me, it will grow on you. I think there are two reasons I prefer this. One is that it many curly-brace programmers give the opening brace a line to itself, meaning the End-style syntax saves you a line of code. That's not really a big deal, but the other is that the End style syntax specifies the type of block that is ending and the compiler enforces it. This makes matching the opening and closing of blocks much simpler and less error-prone.
- Optional Parameters. This one is real simple. C++ has optional parameters. Heck, even C has them (of a sort). Why doesn't C#?
So there you have it. Six reasons I prefer VB.Net over C#. But let's take a closer look. Two are IDE features rather than language features. One goes away completely in .Net 3. Another can be mostly fixed by just adding a quick comment (though not quite). The only items here that C# won't address to some degree is implicit casting and optional parameters, and if you want to use Option Explicit (which in many cases I do) the casting issue isn't relevant at all. Let me elaborate on each of the others:
Case-awareness as I described it is a service provided by the IDE, not a feature of the language. I could write VB code in notepad with mis-matched cases and it would still compile. I can envision an equally useful feature for C# that allows me to type in all lower case, and if it recognizes that I've typed a variable or class name with the wrong case it corrects if for me. If there's a more than one variable with that name (ie, they differ only by the case of the letters), then it prompts me with a list. I would prefer that even over VB's style. Visual Studio almost already does this for C#, but in my opinion it doesn't get the implementation quite right. There's also no reason Visual Studio couldn't implement a background compilation method for C# that simply doesn't report certain errors until the programmer has a chance to fix it (like later adding the ending brace or semi-colon, etc). So this, too, is more a service provided by the IDE than truly a part of the language.
C# 3.0 adds a new var keyword that works like VB's Dim for easier object declarations. Don't be confused though; var is really a misnomer in C#-- it's not a variant type at all. It's just a promise to the compiler that, "Yes, I will give this variable a type. I just don't want to yet." The type of a C# var is fixed by the compiler; it's just not fixed until you actually assign an object to it. So now you can have code that looks like this, with no requirement to double-enter the type name:
var myVariable = new LongTypeName();
The disassembly for that code is identical to my earlier example. Doesn't that look a lot like VB?
This leaves implicit casting and the End syntax. I've already touched on implicit casting, and you can partially emulate End syntax by adding a comment to lines with a closing brace. The compiler still won't enforce the type of block, and you still have to deal with Visual Studio automatically creating files with about 5 ending braces all together by default, but once the code and comments are correct it's an improvement to anyone who tries to read it later.
So should I switch? Well, that depends. Let's look at what I would gain. For my trouble, I'd get yield break/yield return and anonymous delegates. I'd also get access to unsafe code, and maybe a few other things as well that I don't really care that much about. On the other hand, I'd be giving up a few things I like. Note that there's no fix in C# at all for the the case-awareness feature yet. There are no optional parameters either, but since my VB code often ends up in a library that might be called by a C# program I need to avoid those anyway. Even what I'd gain mostly isn't available in .Net 2.0, which we'll be using where I work for some time to come. Hopefully a hypothetical Visual Studio 2010 will address my remaining concerns, and maybe the office will actually switch to it. I look forward to that day.
Until then, I'm happy with VB.Net.
Once upon a time I was a C++ Builder fanatic. I first used C++ Builder 5 back in 2000, and I still have the free version of C++ Builder 2006 installed on my computer. I just got along really well with the IDE. When I first learned GUI development in college I started the big C++ Builder project an hour before it was due, turned it in on time, and got the only perfect score in the class. If I worked on software that was targeted to the general public I'd still choose C++ Builder over Visual Studio for it's ability to link just the parts VCL that you use directly with the application; there's no separate framework to deploy.
That's not my situation, however. Where I work we use Visual Studio, and pretty much all the code I write is for internal use at the company. Any personal projects are for the web, where .Net is my platform of choice. On one hand, this is a shame. Microsoft was just catching up to C++ Builder with Visual Studio 2005 more than 5 years later. In some ways they're still behind, for example the aforementioned static linking of just the parts of the framework you need for deployment.
On the other hard, they have made some significant advances as well. My favorite is Intellisense. In case you don't know, intellisense is what they call the little window that pops up everytime you enter the name of a recognized object or type (which is most everything you type that isn't a comment). The window shows you available properties and methods for the item and provides autocompletion, helping you write better code faster. Back when I was using C++ Builder I became pretty familiar with the VCL (Visual Component Library- the C++Builder equivalent to .Net's CLR), or at least the parts I used regularly. You had to; without rich intellisense if you don't already know about a class, it doesn't exist. But it took some time. With Intellisense you can just start working.
This brings me to what I think is the big benefit of intellisense: discoverability. Intellisense allows you to take an API about which you know very little and start using it almost immediately. It works because at any point you can inspect what types are available and the interface provided by each type. After that it's just a matter of connecting the dots. When I took my first job in .Net I knew almost nothing about the CLR, but it didn't really matter. Thanks to intellisense I was able to find my way around quickly.
Of course, there is a dark side to intellisense, as well. The disoverability benefit depends on using meaningful and consistent names throughout your library. Without those it's really not much help. While it helps you get started faster, it slows learning. Because I was able to rely on intellisense it took much longer to become familiar with the CLR than it did for the VCL. I'm still lost without it in certain areas. And, of course, there are those times when intellisense can lead you down the wrong path.
The problem here is that it becomes very tempting, easy even, to use an object without fuly understanding the implications. Issues like this aren't really 'mistakes', as such. The code works, and probably even makes it through QA. But it's not what it could be. Certainly from a performance standpoint there will be room for improvement. Maybe you're just re-implementing something that's already done for you in another part of the API. Or maybe you're using a class that behaves differently from what you expect, but in a very subtle way that isn't caught at first.
What we need now is a tool that can catch potential issues created by trusting too much in intellisense. Of course, I don't expect the IDE to work magic, or know exactly what you're thinking. I especially don't expect the IDE to try to second guess the programmer based on some fuzzy-logic that no one understands. I'm talking about providing a place where class library developers can anticipate common issues and tell the IDE how to spot and flag them. In many cases this could be as simple as adding some more information to the remarks section of an XML comment. In other cases it might be a little more complex, perhaps resulting in a compiler warning.
Here are a few examples that I think demonstrate where this could be helpful:
- String Concatenation. Strings in .Net are immutable, one result of which is that concatenation in .Net is notoriously slow. Most of the time this doesn't matter. Even .Net's slow string concatenation is unlikely to be a bottleneck when compared to database or network performance. But there is still room for improvement. To help mitigate this problem .Net includes a StringBuilder class that can work much more quickly. It would be nice if the IDE could catch loops that include appending values to strings and prompt the programmer to use a StringBuilder instead.
- Generic Collections. Starting with .Net 2.0 there's really no reason to use an ArrayList ever again. Odds are there's a generic type that covers what you need, and if there's not you can make one. The generic collections perform much better and are much less error prone. If you're using an ArrayList, or other untyped collection, the IDE should prompt you to try a generic alternative.
- Query Parameters. SQL Injection is one of the most serious and common security problems out there today. In my opinion it's second only to social engineering attacks. Hardly a day goes by I don't see database code posted to a programming forum with a glaring injection vulnerability. Since these are often students it might be forgiveable, but often switching to a query parameter would also solve the specific problem that caused the post. The IDE should be able to detect a database query that accepts user input and does not use parameters, and warn the programmer.
Okay, so you can already solve a word search. It's not hard. But can you do it without knowing the word list? You might be surprised to learn that it's not that hard.
Yesterday we had a 'morale day' where I work, and as part of the festivities they passed around a word search. While I was solving it, I noticed that the word search looked familiar. So I thought about it for a while, and I realized there was a system to how the words were hidden; a system that was repeated in many other word searches I'd done over the years. I can't guarantee this will work for every word search. For example, if you get one of those books with 100 searches I'd hope they have a few more algorithms than this. But using this method, you should be able to get most of the way through a word search without ever seeing the word list.
So let's get started. The first thing you want to do is pick a letter in very middle of the word search. It doesn't have to be exactly in the middle, but it should be close. Odds are good that this letter is part of a diagonal word, so let's check that. The word could be forward or backward and the diagonal could go either direction, so you've got some checking to do. If you check a few letter going across both diagonals and don't recognize them as part of a word, move left or right one letter and try again. If you still don't find anything, move one more letter and try one last time. At this point, you should have found at least one word. If you haven't, this puzzle may use a different system.
Now that we've found one word, let's look for more. Find the letter in the approximate center of the word. If you move left two letters from this spot you will probably be looking at a letter in word that's arranged in the same diagonal direction of the word you just found. If you move two more letters you'll find another word on that diagonal, and so on. This also works if you go the right instead of left. What if you go just one letter? In that case, you'll probably find a word on the opposite diagonal. Once you have one of those words, keep moving two letters to find more words on the same diagonal. This works because by placing a word on the same diagonal every other letter, you are guaranteed not to have a conflict between two words from opposing diagonals because no two words will use the same letter. The puzzle looks completely scrambled, even though the words are ordered very neatly.
When you've you found all the obvious diagonal words you should have a sort of 'X' near the middle of the search. To find the remaining words, look around the outside of the 'X'. You should find horizontal words above and below the 'X', and vertical words to either side.
By the time you've finished checking all four edges you should have found most of the words in your puzzle. You're probably not missing more than one or two. And this is without ever even looking at the word list.
... or lack thereof.
I've been a fan of WordPerfect since version 5.1. That goes way back to the days of dos, when office users could legally bring it home from work and install it on their personal machines for free. I think I was still in junior high at the time. Even after MS Office achieved dominance I still preferred WordPerfect. The two things I liked most verses Office were creating outlines and the "Make it Fit" feature, which would subtly adjust font size, spacing, and margins to make your document exactly fill a given number of pages. To this day Office has yet to match that feature, and it's outline mode is still unusable. Of couse, I haven't used WordPerfect in ages; it's still around, but pretty much irrelevant.
I am heartened, however, at the recent resurgence of competition in the space. Office is still dominant, of course, but Open Office is acknowledged more and more as a legitimate competitor. And let's not forget the plethora of online office suites, from Google Docs to Zoho. Even if you're still using Office the competition is forcing Microsoft to put more work into it, resulting in a better product. In fact, the new Office 2007 has some significant improvements, even if you discount the ribbon.
The biggest thing about the new version of office is the new document format. Office is a product that has evolved significantly over the years, and the format is no exception. The number of legacy issues in the old format was becoming burdensome to support. The new format is much simpler, and more robust. More significantly, for the first time in a decade it leaves Microsoft's Office business vulnerable.
In the past, even if you had a far superior product (*cough* WordPerfect *cough*), you were pretty much excluded from the market. Your office suite had to not only read and write MS Office files, but had to do it perfectly. This is pretty much impossible. As I've already stated, the number of legacy issues involved is significant. You might get close: say 85%. But that other 15% would just kill you. The only app that can correctly read a Word document is... Word.
Now all of a sudden three things have changed, making real competition possible. First, the format lock-in is gone. The new office format is much simpler to emulate and render correctly. You have a shot of getting 99% there, and 99% might just be good enough. Not only that, but the old format is going away. Secondly, the conversion is forcing many users, large business and government especially, to consider long-term archiving and accessibility issues. This means actually taking an objective look at what format is going to be best for the business in the long term, and picking the application as secondary: an accessory to the format rather than vice versa. Finally, we have a real contender again: the Open Document Format.
If it's just Office vs everyone else, where everyone else is a hodgepodge of other proprietary formats, Office will win again. But what we have now is one format that's come to the top. It's relatively accessible and portable, and there are a number of applications that can read it, as well as software components that make building more simple. In other words, it's not Office vs everyone else. It's Open XML vs ODF. And ODF isn't going away anytime soon. If you've got a competing product, your best bet is to pick one or the other and support that as your 'native' format.
So which format is better? Well, it's hard to say. With so much at stake, the debate has been politicized by both sides, and the true merits of either format are often lost in the shuffle. It's such a shame, but any real discussion quickly devolve's into a programmer's religious war, a la Emacs vs vi or C# vs VB. Just today I saw an article about the U.S. Government's participation in the standards vote for Open XML.
Microsoft has too much to lose by allowing ODF to take over, so they spent a lot of money pushing Open XML as a real standard. This includes opening it up significantly for use by third party applications. Of course, it's still closed in certain ways. There are other concerns as well. The open source crowd has been pushing ODF pretty hard, but ODF has some problems of it's own (look under the Criticisms heading on Wikipedia). The powerful scripting available for the old Office format was what finally drew me away from WordPerfect, and it remains an advantage for Open XML now. This doesn't even touch on performance or file size questions. Performance doesn't really matter much, but as cell phones and PDAs start doing more and more office work, it becomes a valid concern.
So who will win: docx or odf? I'm rooting for wpd.
Let's talk about web sites and validation. I'll start with the basics:
Whenever you have a web form, you must validate server-side. This is because you can never trust anything sent from the user over the web. The user could simply disable javascript, or a more malicious user might send a specially crafted HTTP request. Either way, your server-side code needs to be prepared.
Additionally, you should validate client-side. This is so you can provide faster, more dynamic feedback to user, and also to reduce the load on your server. If you have some javascript that 99% of users run that catches an invalid form before submission, that's a good thing.
Unfortunately, this creates a burden for web developers. There are now two places that need code to accomplish the same task. That may seem petty to a non-developer who's only thinking about the initial creation work, but it really has a huge maintenance cost over the life of the app. The problem is that it becomes real easy to make a change in one place and not the other, which results in a broken web site.
One of the nice things about ASP.Net is that much of the time you don't have to duplicate client-side and server-side validation. It includes a set of generic validation controls that will automatically do the client-side and server-side work with one set of code. Unfortunately, these controls have several limitations.
One limitation is that you can only validate one control at a time. For example, let's say you have several fields on your form and want to require the user to enter data in at least one of them. To do that right now you would need to use a CustomValidator control, which usually also means writing separate javascript or not validating client-side. Another limitation is that they won't validate checkbox controls (you can get around this now by attaching a custom validator to a random textbox, but that's an ugly hack).
So what is a developer to do? Well, in my case, I derived a new generic validation control: the AtLeastOneOfValidator. Since one of my main problems with Vox right now is that it's not easy to post code, I created a separate write-up for the control and posted it over at codeproject. Anyone can read the full details there now, and if you create a (free, non-intrusive) login you can download the code and binary. Here are some of the highlights:
- In addition to the normal controls supported by validators, it will accept CheckBox, CheckBoxList, RadioButton, RadioButtonList, and Calendar. You could use it to require a checkbox (for example, "check this to accept terms") by including the checkbox as the only control with the validator.
- It uses simple dropdown lists to select supported controls, just like any other validator control (I'm a little proud of myself for getting that working, even though it turned out to be pretty easy), up to ten controls. Beyond 10 controls there is a string property you can use to enter a comma-delimited list of control names.
- Client-side validation works for everything but the calendar control. If you use the calendar control, it will post back to the server to finish validation. Since the stock calendar control pretty much sucks and posts back all the time anyway, this shouldn't really surprise anyone. I debated with myself whether to support this control at all.
The control has been tested to work well with IE7 and the latest FireFox 3 (beta 2 at the time of writing). I'm looking for people to test in FireFox 2 and older, IE6, the IE8 beta, Opera, Safari, Nautilus, and Camino. If you see this and can put the control through it's paces in any of those platforms, please post a comment to let me know how it goes.
Once again, you can get the details here.
I have something almost ready, but it needs some more work yet. If I can get it done today I'll post it. Otherwise it'll wait until Monday.
Update: Finished.
http://www.packers.com/news/releases/2008/03/04/1/
That's all folks: Brett Farve rides off into the sunset. It's sad to see him go. Hopefully Aaron Rodgers turns out to be half as good.
My current home system is based on a socket 939 motherboard. I bought the board about one month before socket AM2 was announced, while AMD still had a good performance edge over Intel. It supports up to 4GB of RAM (I currently only have 1GB), SLI, and dual (maybe even quad) core processors. That was pretty nice 2 years ago, and I bought the board hoping it would be the core of my system through numerous upgrades.
Unfortunately, this dream is obsolete. This week I was checking processor prices, and a decent dual-core processor that I could just drop in my board would cost about $150, if you can find one at all. For that amount I can get a new AM2 motherboard, 1GB DDR2 RAM, and the equivalent AM2 CPU all at once. Yep- for just the price of a processor I can update just about everything in my system that matters.
Of course, the only thing I've gained here performance-wise is the advantage of moving the memory controller to the processor, which benchmarks proved isn't as useful as hoped. Some even believe that it was focusing too hard on this improvement that caused AMD to lose the performance crown.
But there are other things outside of performance. By making that change I set myself up for a cheap memory upgrade (RAM for this board is faster and is less than half the price of RAM for the old one). Even if that upgrade never happens or the price of DDR2 jumps to make way for DDR3, I've still moved myself a notch up the technology ladder. Of course, that benefit is mostly psychological, but it doesn't mean it's any less real. I'd have options.
All this means that if you have or are considering a socket 939 system, there's something out there that's better in every respect: price, performance, and even power consumption. 939 is dead. And if you've moved up the market to AM2, you really ought to consider the far superior line from Intel as well.