Tuesday, November 22, 2005

Screen Design

When exiting a screen, prompt the user to determine if unsaved changes should be saved. When possible, saves should be done by screen. An exception would be a quick pop-up form to collect information.


It is ok to use bound controls.


It is good to merge and inherit menus.

Designing Modules and Procedures


Give procedures and modules descriptive names
Give every procedure a single exit point
Give every procedure a clearly defined scope (Public, Friend, Private)

Use parameters to pass data between procedures,
Always validate parameters – never assume you have good data
Use enumerations when a parameter accepts only a small set of values

Call procedures in a consistent and self-documenting manner

Return values from a function by using the Return statement.

This in conjunction with the Finally for code cleanupIt is good to raise events and have modules respond to the event as necessary.

Variables

Note: in VB a long is now an integer in .Net and a .NET long is much larger than it ever was before.

Never use the plus sign for string concatenation.

Use the Option Strict to enforce strict typing


Use the string’s length property to determine whether it’s empty
Bad: if strMyString = “” Then …
Good: If strMyString.Length = 0


Use positive variables for Boolean values
Examples: bIsUnderAge, bIsEndOfFile

Take advantage of the .NET array features like the use of hash tables and dictionary arrays.

Commenting Code

  1. Document the purpose of the code
  2. Document the why rather than the how
  3. If you need to violate good programming style, explain why in the code.
  4. Comment before writing code
  5. Use solid-character comment lines only for major comments
  6. Avoid creating comment boxes
  7. Give each procedure a comment header
    Purpose
    Accepts
    Returns
  8. Document code processes by using inline comments

Handling Exceptions

Handling Exceptions
All top level events will have exception handling to prevent the application from crashing.
Important: Variables declared within the Try block of an exception handler have block scope – they aren’t available to any Catch or Finally blocks, and they aren’t available outside the Try..End Try construct. For this reason, it’s best to leave declarations outside of the Try block unless the declaration has an inherent risk of throwing an exception.

Important: You should always include a Catch section to deal with exceptions.

Ignoring an exception (by not including a Catch section) is worse than not including exception trapping to begin with because exceptions will occur and neither you nor your customers will know about them

When specifying multiple Catch blocks for an exception handler, order them from most specific to least specific. This ensures that exceptions are handled correctly.

A central exception handler will be used for unpredictable errors to keep exception handling from becoming tedious.

Programming Objects

Programming Objects

  1. Early bind objects whenever possible.
  2. Use .Net objects rather than API calls whenever possible.
  3. Expose public properties, not public variables.
  4. Always close what you open
    m_dstContacts.Close()
    m_cnADOConnection.Close()
  5. Use Overloads to create a property or method with the same name as another property or method but with a different argument list.
  6. Create Dispose methods for all your objects.
    Place cleanup code in that method
    Call the Dispose on each and every object that has one, once you are finished with the object.
    Note: When creating shared components, you must be careful about the code you place in a custom Dispose method. Releasing the resource could cause problems for the remaining clients that are sharing the object.
  7. Create constructors for a class whenever possible
    Note: You cannot use the keyword Overloads on constructors, even though creating multiple constructors is indeed creating overloaded methods.
  8. Add a finalizer to a class only when necessary.
    Caution: You should avoid referencing other objects in your finalize code because the nature of garbage collection is such that the finalizers aren’t executed in any special order.
  9. Use With..End With to increase performance and make code more readable.

Events should have only two arguments

Events should have only two arguments:
an Object argument named sender,
which represents the the object that's raising the event;
and an argument named e,
which exposes teh event's arguments throught its fields or properties. This second
argument should be a System.EventsArgs object or an object whose class inherits from
the System.EventsArg (The name of such a class should end with EventsArgs.)
This naming convention requires only a little extra code today, but it might simplify
your job a great deal tommorrow.

Friend Sub NewAgreement()
RaiseEvent CreateNew(Me, New System.EventArgs)
End Sub

Monday, November 21, 2005

re-throwing an exception with a paramenter it resets StackTrace

How about Throw without the ex

The Throw statement without an agrument rethrows the current exception object and must appear in a Catch clause to be valid.

If you throw an exception with a paramenter it resets StackTrace property of the exception object (as if a brand-new exeption were created).

The version without an argument is perferable for rethrowing the same exception becuase it lets the caller routine determine exactly where the exception occured.

Additional Notes:
- Throw an InvalidOperationException if a property or method call occurs when the object is in a state that can't handle the method call
- Throw and ArgumentException (or a class that inherits for the AgrumentException) if a bad argument is passed.
- Stick to predefined exceptions, and don't define custom exceptions unless strictly required.
- Don't throw expetions for relatively common errors, such as end-of -file or timeout; instead return a special value to the caller.

Thursday, September 15, 2005

VB6 debug temp directory and required files

VB6 Notes
I discovered that when you are running vb in debug mode, the executable directory is C:\Program Files\Microsoft Visual Studio\VB98

If your application needs to refer to a subdirectory below the executable, you will need to create a reports sub in the VB6 temp exe directory. For example, here is a folder call "Reports".; C:\Program Files\Microsoft Visual Studio\VB98\Reports

A .NET dll expects the reports to be in a "Reports" subdirectory of the executable.

Friday, May 06, 2005

interop When not to use Register for COM interop?

interop When not to use Register for COM interop?: "I have a solution with several .NET assemblies that are required to be

COM registered for use in C++, VB, Delphi etc.

I have the 'Register for COM Interop' build setting set to true.
However this causes problems with DLLs being cached in the
'C:\Documents and Settings\jjboswel\Local Settings\Application
Data\assembly\dl2\
' subfolders (as reported in other threads).
So periodically if we see strange debugging problems we delete our
cache folder and everything works again.

VB RAD tips on .net interop

VB RAD


  1. Create a strong key by running sn –k mykey.snk from the command line.
  2. Add the path of this generated file to your AssemblyInfo.vb or .cs file in the following manner:
    VB.NET: <Assembly: AssemblyKeyFile("c:\path\mykey.snk")>
    C#: [assembly: AssemblyKeyFile(@"c:\path\mykey.snk")]
  3. After compiling your assembly to a DLL, you must register it for COM Interop from the command line: regasm c:\path\MyDll.dll /tlb:MyDll.tlb
  4. Finally, you should install the DLL into the Global Assembly Cache by dragging the .DLL file into the c:\windows\assembly folder
  5. VB.NET: <ClassInterface(ClassInterfaceType.AutoDual)>
  6. Verify, VB.NET: VB.NET: <GuidAttribute("BA713700-522D-466e-8DD4-225884504678")>
  7. Verify, VB.NET: Imports System.Runtime.InteropServices

Wednesday, May 04, 2005

VB6 calling .NET DLL Interop

Imports System.Runtime.InteropServices

<System.Runtime.InteropServices.ProgId("HC65Reports_NET.HC65Reports"), _
ClassInterface(ClassInterfaceType.None)> _
Public Class cHC65Reports
Implements _IReports

The imports and the class interface go together. This is what gives VB6 the references in the object explorer. Without it you will only have a high level class stub in your VB6 object browser.

You use the REGASM to register the dll and create the typelib file for visual basic to reference. Once you have created the tlb file you can reference it in visual basic.

All the files created in the bin directory need to reside in the same directory as your visual basic exe. I compiled my VB6 program exe and copied it to the .net bin directory to test.

Alternatively, the dll could be assign a strong name key (snk) and registered in the GAC. However, are trying to avoid GAC entries. We would like to use copy deployment if possible.

When VB6 in debug mode, it will get a runtime error stating that it cannot find a file or assembly name. I am guessing that this is because VB6 is running the code from a temporary directory and not the actual directory of your project.

You can run your visual studio .net in debug mode using your vb6 executable as the startup program.

See http://radio.weblogs.com/0124037/stories/2003/08/18/debuggingComInterop.html

I would like to be able to tell VB to use the .net bin folder when running in debug mode.

If you try to reference the .net dll file instead of the .tlb file you will get an error when trying to reference it and you will get an "Two different copies of MSCOREE.DLL have been loaded" when you try to run the VB6 application in debug mode. Restart VB6 to clear the error.

Visual Studio Command Prompt Open Here

Would you like to right click on a directory in windows explorer and open a Visual Studio Command Prompt already set to the current directory? http://objectsharp.com/Blogs/dave/archive/2003/12/10/227.aspx Enter the following text into a file called VsShell.reg Save the file and double click on it to have the entries added to your registery. Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\cmd_vs]@="Open VS Command Prompt Here"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell\cmd_vs\command]@="cmd.exe /k \"C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\Tools\\vsvars32.bat\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Drive\shell\cmd_vs]@="Open VS Command Prompt Here"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Drive\shell\cmd_vs\command]@="cmd.exe /k \"C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\Tools\\vsvars32.bat\""