Naming Conventions

Share

I’ll get to “Naming Conventions” after a short story, so please humor with your time for a short moment… It’s relevant, I promise!

People tend to get really emotional when choosing a naming convention that they’re going to apply to the software they write. That’s too bad, because that closes their mind to improvement. When I started programming in 1982, naming conventions were neither a concern of mine nor a possibility because of the limitations in the languages I was using (AppleSoft BASIC and 6502 Machine Language). AppleSoft BASIC only allowed a whopping TWO unique characters for variable names. Subroutine names were non-existent because code was identified not by labels, but by line numbers. In Machine Language, routines were identified by the memory address the instructions resided and variables were also memory address (in HEX).

As time moved onward and technology improved, I got involved in Pascal around 1984. It was Apple Pascal and I never did much with it. I pretty much stuck to what I knew which was still AppleSoft BASIC and Machine and Assembly Language. In 1988 I started college and was reintroduced to Pascal. I never adopted a naming convention on that platform (MVS Pascal) because my assignments were so short, my programs had at most, 5 procedures.  And, the concept of a naming convention was still foreign to me at the time.

But, I got a part time job at a local company doing computer graphics and first heard about a language called "C". It sounded intriguing so I bought Microsoft Quick C. It came on 5.25" floppy disks and I ran it on a 2 floppy drive Z80 PC clone card plugged into my Apple ][GS. I got pretty heavy into C and achieved "Hacker" status (this was back when "Hacker" was a good thing… it meant it was someone who spent all their waking time trying to learn everything about a particular piece of technology regardless of whether they used their knowledge for good or evil). I was a "good" hacker. Bad hackers were called "crackers" in those days.

Anyway, as I upgraded my computer to a 386sx 25MHz machine with an actual hard drive in it and Super VGA graphics, I wanted an Apple ][GS emulator, so I decided to try to write one (yes, I know… a huge undertaking that was doomed to never finish). I had all 3 volumes of the Apple ][GS Toolbox manuals (hard cover, in those days). I never got very far with that project. Instead, it turned into a different project… a GUI library for DOS programs. I have to say, to this day, it’s probably my proudest piece of work. It provided full GUI capability for DOS programs.

So, what about naming conventions???

OK, OK! The point of all that was to lead you into where why and how I came about a conscious choice to implement an actual naming convention in my code. As I was discussing the DOS GUI library… Apple had already implemented a naming convention for their toolbox libraries. It basically went like this:

  1. PascalCase (everything is lowercase, unless it’s made of multiple words, in which case, the 1st letter of each word is uppercased).
  2. No underscores.

Uh, OK. I think that was pretty much it. I liked the way the code was easy to read (no cryptic, half-hazardly, made up abbreviations or prefixes. Since my DOS GUI library used many of the same data structures that were in the Apple manuals, I had already, by default, started using that convention.

Function names were basically made up of a verb plus a noun. For example:

  • ShowWindow()
  • HideWindow()
  • SetText()

and so on… The naming convention was good, but it was not perfect. For example, the type name I used for say a window structure was called "Window" and some of my variables of type "Window" were also called "Window". This made parts of the code somewhat confusing, because when you saw "Window", was the code referring to a type or an object? Later, I upgraded to C++ (around late ’89 or so) and basically continued the same naming convention.

Along came Borland with Delphi. Well, actually, Turbo Pascal had been around for quite a while. Around 1993 or ’94, I got neck deep in Delphi. Borland used basically the same naming convention, but they had extended it. I didn’t realize it at first, but they prefixed all of their types with "T" (meaning "Type", not "Turbo" as I had thought for years looking at Turbo Pascal code). I thought that was a pretty cool idea. That separated the type name from the variable name. So, my code that declared a variable named "Window" of type "Window" went from looking like this:

Window Window;

to this:

TWindow Window;


Now, it was pretty clear. TWindow was the type and Window was the object. This added another similar benefit: By sticking with a convention on type names, I guaranteed to completely avoid the problem of having to think up some less than prime name for a variable. For example, with the old convention, to avoid naming a window variable with the same name as the Window type, I’d have to do something dorky like this:

Window TheWindow;

I hated that. I looked really unprofessional and was unnecessary. Now, when I have a variable that represents a window, I can actually call it "window" and have NO naming conflicts! I stuck with that convention for nearly 10 years.

2001: Along comes .NET
With the introduction of .NET, came the introduction of Microsoft’s new naming convention; the .NET naming convention. It was, not surprisingly, nearly identical to the naming convention I’d been using, with the following modifications:

  1. No prefixes.
  2. No abbreviations
  3. Acronyms more than 2 characters long are lower case except for the 1st letter.
  4. camelCase instead of PascalCase.
  5. No underscores "_".

The rest of the naming convention was pretty much the same. This is "no prefixes" rule meant not prefixing my types with "T". It also FAILED to address a way to distinguish between type names and variable/object names. Because of that, I continued to keep the "T" prefix for a year or so. Later, I decided to follow the "No Prefixes" rule by changing it to a suffix and to follow the "no abbreviations" rule, so that meant spelling it out "Type".

So, now a type that represents a window is now called, "WindowType". I decided to enforce this on myself for ALL types (not just classes), but for structs, classes, enumerations, etc… For the most part, this has worked out well.

As I wrote more and more software, I started noticing shortcomings of both mine and Microsoft’s naming convention. For example, what do I name a MenuItem object? Suppose that I’ve got a menu bar with a "User" menu and a "Group" menu. Let’s suppose that both of them have the following menu items under them:

  1. New
  2. Find
  3. Edit
  4. Delete

Well, you can’t have 2 menu items called "NewMenuItem" (one for the User menu and one for the Group menu)… The compiler just won’t allow it. So, there needs to be a way to specify that one belongs to the User’s menu and the other to the Group’s menu. Easy, just call the one under the User menu, UserNewMenuItem and the one under the Group menu, GroupNewMenuItem. Seems like problem solved, right? Wrong. Supposed the program allows you to select multiple items and edit them together… as a group. See where I headed yet? If I had a menu for that, I might want to label it "Group Edit". So, the menu item would be called "GroupEditMenuItem". So, what do I call the Edit menu item under the Group menu? According to the rule, it’d be "GroupEditMenuItem". Believe it or not, I’ve run into this type of situation in the real world countless times! So, I extended the naming convention to account for this problem. Violate the "No underscores" rule and put an underscore between the menu name and the menu item name. So, the Edit menu item under the Group menu would be called, Group_EditMenuItem. The menu item labeled "Group Edit" that allows the user to edit multiple items together, as a group, would be called "GroupEditMenuItem". Problem solved. Yah, really this time it is.

This new convention solves similar name conflicts in dialog boxes with tabs or group controls. For example, you may have a dialog box with multiple tabs. Each tab may have an "Edit" button. You certainly can’t call each one EditButton. Instead, you prefix each edit button with the text from the tab in which it resides. So, if you had a dialog box with three the three tabs, "User", "Group", "Security", and each of those tabs had buttons with "Edit" on the label, the first one would be "UserTab_EditButton", then "GroupTab_EditButton", and finally, "SecurityTab_EditButton".

Just call it what it is. Call a button a button.
Notice VB scripters, that I do not name my buttons "cmdEdit" etc…? There are multiple reasons for this:

  1. Buttons are "Buttons", they’re NOT "Commands" nor "Command Buttons". That terminology is unique to ONLY Visual BASIC. No other language or technology has that naming oddity.
  2. "cmd" is an abbreviation and is confusing to non VB programmers.
  3. "What it is" belongs at the end of the name, not the beginning. When you’re speaking, you don’t say, "Click the button EDIT". You say, "Click the Edit button". So, if you name your edit button as "EditButton", it reads like you speak. It’s much clearer and looks much better.
  4. DotNet actually has objects of type "Command" that have nothing in the world to do with buttons, so "cmd" looks like it’s talking about a command object, NOT a button object.

Avoiding Abvs
I’ll bet you at least 30% of the readers had a hard time deciphering "Abvs". Question: Why should I write anything that I know will be confusing to a large percentage of the readers? The answer is, "I should not!". This means, NO ABBREVIATIONS! Just spell it out. The extra keystrokes will not give you a heart attack from the extra exorcise. Believe it or not, for the past 15 years, at least, source code editors have had search as you type features built in. I rarely type the full name of any of my types, variables, or methods. So, I’m not saving keystrokes by crunching my label names down so low. And, in this day of hundreds of gigabyte hard drives, I’m not really saving space either. Hard drives are so big that I couldn’t even dream of filling one up with my own keystrokes.

By avoiding abbreviations:

  1. My code is legible by 100% of all readers.
  2. Readers of my code don’t have to make out a cheat sheet with all of my funky abbreviations.
  3. Joe Blow’s abbreviation rules might conflict with mine, so why have them?
  4. My abbreviations will be confusing to you. Your abbreviations will be confusing to me.
  5. What’s the universal rule for abbreviating a brand new type? Answer: There isn’t one.

So, every one’s better off when you avoid abbreviations.

Well, I’ve babbled on long enough. I’ll conclude with the formal list of rules for a good naming convention that can work in almost any programming language without modification:

  • By default, everything is lowercase.
  • If a label is made of multiple words, capitalize the 1st letter of each word (PascalCase).
  • Put "Type" at the end of all types (except enumerations).
  • Enumerations: End with "Enum" or "Types" (with an "s"). Name your instances "TypeOf…" For example:

  1: private enum DataBaseTypes
  2: {
  3:    Microsoft,
  4:    Oracle,
  5:    MySql,
  6:    FireBird
  7: }
  8: 
  9: private DataBaseTypes TypeOfDatabase;
 10: 

  • Objects are given a descriptive name + object type. For example, type WindowType, instance window.
  • Visual components are given the same name as the displayed text on them, when feasible. For example, a button with "OK" on it would be called, "OKButton". A check box with the text "Enabled" would be "EnabledCheckBox", etc…
  • Components in a hierarchy (like menu items in a menu structure, objects in a multi-tab control) have the name of the parent objects prefixed in front of them and each parent is separated from its child in the name with an underscore.

Conclusion:

When you’re writing code, you’re producing two products:

  1. The compiled software product.
  2. The source code.

It’s our responsibility, as programmers, to make the users’ jobs as easy as possible. It’s our responsibility to each other to make each other’s jobs as easy as possible. This means avoiding the ancient practice of saving bytes or keystrokes by making cryptic source code and instead making our source code read as much like English as we can. This makes our source code self-documenting in most cases and a pleasure to maintain.

The Microsoft .NET Naming Convention Guidelines can be seen here:

http://msdn.microsoft.com/en-us/library/ms229002.aspx

Share

Pass BLOBs to Oracle Stored Procedures

Share

Probably the most difficult task that I’ve had to conquer in quite a while is something that’s so mundane and so simple in other database products… that being the the ability to pass a large binary object (a.k.a. “BLOB”) to a stored procedure in Oracle.

My God! Were these people smoking crack when they designed this “feature”?? They would have to try really hard to make it more difficult than they did. At first try, it seemed to have worked, I mean, I successfully sent binary streams of files to my first Oracle stored procedure that accepts BLOBS. Then, later, it all fell apart with odd errors. As it turns out, you can pass up to 32KB directly into a stored procedure BLOB parameter with no problems. It’s when you pass a BLOB that’s BIGGER than 32KB to an Oracle stored procedure where all the “fun” begins!

But first, let’s take a look at a simple Microsoft SQL Server stored procedure that accepts BLOBs (and works incredibly well with BLOBs as large as 2GB):

create procedure MicrosoftBlobProcedure(@MyBlob image) as begin

    insert into MyBlobTable (MyBlobField) values (@MyBlob);

 

end

Pretty straight forward right? Well yes… for Microsoft SQL Server that is. Now, let’s look at the equivelent for Oracle:

 

create or replace procedure OracleBlobProcedure(p_MyBlob blob)
as begin
insert into MyBlobTable (MyBlobField) values (p_MyBlob);
end;

OK, the above Oracle procedure works just fine as long as you’re passing in 32KB or less!!! If you try passing in anything greater than 32KB, you’ll start getting useless error messages.

So, how do you fix it? You must change BOTH your procedure and radically change the code that calls it. First, the rewrite of the stored procedure:

 

 

create or replace OracleBlobProcedure(p_MyBlob out blob)
as
l_MyBlob blob;
begin
insert into MyBlobTable (MyBlobField) values (Empty_Blob());
l_MyBlob := p_MyBlob;
return l_MyBlob;
end;

So, what’s up with that you say? Here’s what: Notice that the parameter is now defined as an OUT variable?!?!? Instead of passing your data IN to the procedure, the procedure will pass the variable OUT to you! Just hang on! It gets worse!

Like I said, you don’t pass data INTO the procedure, instead it passes a reference back out to your calling code. Instead of the procedure inserting your BLOB data directly into the table, the procedure instead inserts the results of a call to the function Empty_Blob(). This basically creates a reference to an empty BLOB object. Then assigns it to your local blob variable, then returns the local blob variable back to your code that called the stored procedure. It gets worse!

So, the stored procedure is now DONE and you haven’t passed your data in!!! Well, you do that AFTER the stored procedure completes. No really! Wait! Where are you going?

OK, now we have to jump over to your calling code. We’ll use C# as an example. First, you have to create a transaction (from your calling code) before you call the stored proc. Then you open your database connection, then call the stored proc (passing it NOTHING!). You’ll get back a reference to the empty BLOB created inside the stored procedure. From here, you write your bytes to the referenced object, then end your transaction, then close your connection.

Makes perfect sense, right??? NOT! But that’s the ONLY way to do it! Here’s the C# code to accomplish this:

 

 

using System.Data.OracleClient;

/*… bunch of clutter …*/

private void WriteBlobToOracleAsIfImSmokingCrack(byte[] MyBytes)
{
OracleCommand command = new OracleCommand();
command.connection = new OracleConnection();
command.connection.ConnectionString = “”;
Transaction tx = command.connection.BeginTransaction();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = OracleBlobProcedure;
OracleParameter parm = new OracleParamter(“p_MyBlob”).Direction = out;
command.Parameters.Add(parm);

    command.connection.Open();
command.ExecuteNonQuery();
OracleLob MyLob = command.Parameters[“p_MyBlob”].value;
MyLob.write(MyBytes, 0, MyBytes.Length());
tx.EndTransaction();
command.connection.Close();
}

So there you have it. It was all so obvious, right! I am at a loss as to what in the world they were thinking when they came up with this!! It’s just pure insanity!

Please visit my online store: www.MichaelsAttic.com.

Share