Changes between Version 27 and Version 28 of CodeBestPractices


Ignore:
Timestamp:
2012-12-01 13:20:14 (7 years ago)
Author:
jeroens
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • CodeBestPractices

    v27 v28  
    55 
    66The following issues are discussed on this page: 
     7 
    78 * [#Robustness Robustness] 
    89   * [#Try_/_Catch Catching unexpected failures (Try / Catch)] 
     
    1314   * [#Mono Mono] 
    1415   * Target processor 
    15  * User-interface design guidelines 
     16 * [#User_Interface_design_guidelines User-interface design guidelines] 
    1617   * Re-use what's already there 
    1718   * Pop-up messages 
     
    2021 
    2122---- 
    22  
    2323== Robustness == 
    24  
    2524Take it from us. Users can find very creative ways to use a software product in ways that a programmer could never, ever have predicted. As such, it is of vital importance that your code is robust to failures, even if you do not know in what ways your product may fail. It's rarely a good think to be caught with your pants down, and this section aims to provide a few simple guidelines. 
    2625 
    2726=== Try / Catch === 
    28  
    2927Make your code robust to failures by encapsulating big function calls in [http://www.homeandlearn.co.uk/net/nets5p4.html Try / Catch] blocks. Public methods in public classes are often the entry point to deeper functionality, and placing a Try / Catch inside the public methods is a good way to capture any internal failures within your code. We've done the same in the plug-in framework, where every plug-in point call is wrapped in a Try / Catch block to make sure EwE is not affected by a failing plug-in point or button click. 
    3028 
    3129Take for instance the code that runs in response to a 'Run' button click on the Run Ecosim form: 
     30 
    3231{{{ 
    3332Private Sub OnRun(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 
     
    4645End Sub 
    4746}}} 
    48  
    4947Note that in EwE we prefer not to rely on exceptions for regular error testing. Exception handling is very processor intensive, and a simple [http://www.homeandlearn.co.uk/net/nets1p20.html If / Then] test is endlessly faster than bluntly executing code and waiting for the exceptions to happen. As such, we suggest to only use exceptions to capture unforeseen problems. 
    5048 
    5149=== Logging events === 
    52  
    5350The EwE Log file, created and managed by the core, and stored in the Windows application data folder, contains a track list of important actions taken by EwE in response to user requests and a track record of failures and successes. The purpose of the log is to provide postmortem diagnostics when an error has occurred. You can use the log as well in your plug-ins. Frankly, we think you should. 
    5451 
    5552If you strategically encapsulate [#try_/_cath Try / Catch] blocks, why not write the result of the exception to the log file, as shown here in the Catch part of the try/catch block: 
     53 
    5654{{{ 
    5755Private Sub OnRun(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 
     
    7068End Sub 
    7169}}} 
    72  
    7370You can write anything to the log. The log class, cLog, lives in the EwECore assembly and is worth exploring. 
    7471 
    7572=== Assertions === 
    76  
    7773Make it a habit to make your code as sound as it can get by testing whether [http://www.homeandlearn.co.uk/net/nets5p1.html your code is properly used]. [http://msdn.microsoft.com/en-us/library/system.diagnostics.debug.assert%28v=vs.71%29.aspx Assertions] are a neat way to slap yourself on the wrist if built-in assumptions in your code are somehow failing. In EwE, we sometimes refer to these checks as ''sanity checks'' ;-) In released versions of EwE assertions will not show up, but they are a good tool to check whether your code is used as it is supposed to while developing. 
    7874 
    7975To illustrate, does the following code make sense? 
     76 
    8077{{{ 
    8178Public Function Div(ByVal dividend As Single, ByVal divider As Single) As Single 
     
    8885End Function 
    8986}}} 
    90  
    9187---- 
    92  
    9388== Compatibility == 
    94  
    9589We want EwE to run on any operating system, and any processor memory model. This section provides some practical tips to keep EwE Operating System-neutral. 
    9690 
    9791=== Mono === 
     92.NET is in theory a system-independent programming platform. .NET applications can be deployed under Unix, Linux, MacOS, etc using runtime environments such as [http://www.mono-project.com/Main_Page Mono]. However, not all .NET features work under Mono, most notably the Microsoft.!VisualBasic assembly. If you wish to enable your code to run on non-Windows operating systems, do the following: 
    9893 
    99 .NET is in theory system-independent, and .NET applications can be deployed under Unix, Linux, MacOS, etc using runtime environments such as [http://www.mono-project.com/Main_Page Mono]. However, not all .NET features work under Mono, most notably the Microsoft.!VisualBasic assembly. When you start a new project in Visual Studio, it is immediately provided with a reference to this assembly. Aargh. You will have to take that away: 
     94Remove the reference to Microsoft.!VisualBasic from a new VB.NET project as follows: 
    10095 
    10196 * Right-click your project in the Solution Explorer and select 'Properties' 
    102  * In the References tab, clear the check beside Microsoft.VisualBasic in the 'Imported Namespaces' 
     97 * In the References tab, clear the check beside Microsoft.!VisualBasic in the 'Imported Namespaces' 
    10398 
    104 Done. 
     99The !VisualBasic assembly provides features that are backward compatible with Visual Basic 6, the pre-cursor of .NET. We redefined only those the features and constants in the Microsoft.!VisualBasic assembly that do NOT have .NET counterparts: 
    105100 
    106 Now, your code may require some of the handy-dandy bits that this assembly provided. We redefined some of the key types and constants from the Microsoft.!VisualBasic assembly in [http://webservice.ecopath.org/Ecopath/Help/Index.aspx EwEUtils]. We did not copy all of 'em, some good .NET equivalents exist for outdated VB6-derived contraptions such as string manipulation functions and file interactions. You should not use Chr, Asc, IIF, !TriState, !MsgBox, UBound, !InStr, vbTab, vbCrLF and a whole whack of other old and familiar constructs if you wish your application to run on any other OS than Windows. 
     101 * [http://webservice.ecopath.org/Ecopath/Help/?topic=html/9b24a241-183a-1f76-0b5d-75fa513cc0aa.htm TriState constants] 
     102 * [http://webservice.ecopath.org/Ecopath/Help/?topic=html/aafcd855-760f-a7a4-78fc-5339a4a116f7.htm Functions such as IIF, Val] 
    107103 
    108 To remove reliance on Microsoft.!VisualBasic simply remove the auto-generated reference in the project properties References page. For most constructs .NET offers a solid alternative (for instance Array.!GetUpperBound()), but for other constructs you may have to be creative (vcTab becomes Convert.!ToChar(9).!ToString() - or do you have a better idea?). 
     104Here is a brief table how Visual Basic 6 constructs map to .NET: 
     105 
     106|| [wiki:VisualBasic !VisualBasic] construct || .NET alternative || 
     107|| vbTab, etc || Convert.[wiki:ToChar](Keys.Tab), etc || 
     108|| vbNewline || Environment.!NewLine || 
     109|| InStr, Left, Mid || See [http://msdn.microsoft.com/en-US/library/system.string_methods%28v=vs.80%29.aspx String class] || 
     110 
     111You should not use Chr, Asc, IIF, !TriState, !MsgBox, UBound, !InStr, vbTab, vbCrLF and other Visual Basic 6 constructs if you wish your application to run on any other OS than Windows. See 
    109112 
    110113=== Target processor === 
    111  
    112114The EwE source code now fully utilizes 64-bit capabilities. In order to make sure that Windows finds the correct 32 or 64 bit Access drivers make sure you always compile your EwE6 main project against x86 or x64, never against AnyCPU in'' Menu > Build > Configuration Manager''. 
    113115 
     
    115117 
    116118---- 
    117  
    118119== User Interface design guidelines == 
    119120Please adhere to the [wiki:UserInterfaceGuidelines User Interface Guidelines] when building user interfaces. 
     
    130131 
    131132---- 
    132  
    133133== Nasty experiences == 
    134134 * Always override ''Dispose(bDisposing)'' to clean up sub-classed UI elements, do not use ''!OnHandleDestroyed'' because the .NET framework, which wraps Win32 controls, may call this method during the regular life span of a .NET control to do housekeeping. The call may be followed by ''!OnHandleCreated'' - it's simply not a valid trigger to assume your control is dying.