Coding guideline - CatGlobe

From Catglobe Wiki
Revision as of 08:26, 19 December 2008 by Catglobe (talk | contribs)
Jump to: navigation, search

Introduction

This guideline contains CatGlobe-specific coding rules.

Exception

Exception handling

  • Only catch exception if you can do some thing with it.
  • All re-thrown exception must include the original exception in its inner exception.
  • DO: always catch specific exception type. You are allowed to catch generic exception and re-throw a specific exception; for example in CGScript all exceptions are caught and a RuntimeException is re-thrown afterward.
  • DO NOT: empty and undocumented catches; using unspecific catches, unless they are documented well in the design document and are approved by the PMs.

Create a new custom of exception

  • Naming rule: the new exception must be suffixed with “Exception”.
  • All custom exceptions must inherit from another exception class.
  • The exception should be serializable in order to use in CatTask service. Refer to Serializable exceptions for more details. Notice: when the new CatTask service is done, this may be obsolete.
  • Namespace rule:

        - If the being created exception is used in multiple places, it must be placed in the CatGlobe.Framework.Exceptions namespace.

        - Otherwise, if it is used for a specific class only, it can be placed in the namespace where it is used.

Working with threads

  • Usages of threads must be specified in the Technical design and approved by PMs.
  • Use CatGlobe.Framework.Security.AsyncHelper class to start a thread with auto-impersonate, access factory and webconfig manager.

Web pages – web controls

Code behind (ASPX and ASCX)

  • Code behind must be documented with request parameters, usage, purpose.
  • Use Register…(JavascriptConstant…) to include javascript files in the code behind.
  • Web page must inherit from the PageBase class, control must inherit from the ControlBase class and Web Service must inherit from the WebServiceBase class.
  • DO NOT override the OnError event, unless it is approved in the technical design.

ASPX file

  • Replace the auto-generated DOCTYPE by this one: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
  • A page must have a title using text resource.
  • All the validation warnings which the Visual Studio shows must be fixed.
  • Adding references to user controls and using of tagPrefixes: must following this guideline Tag prefixes for user controls and web controls
  • You are allowed to reference to javascript files in the aspx files directly. However, you must use the JavascriptConstant to reference to them.
  • If a page or a control contains more than 3 methods or more than 20 lines, move it to a separate js file.

ASCX file

  • DO NOT reference to javascript files in the ascx files.

Text resources

  • When you need to register a text resource to the client side, use the PageBase.CGClientScript.RegisterTextResource method. The method will encode registered text resources for you.
  • Setting for text resource files of web pages:

        - Need to be set to the [filename].aspx.resx file only.

        - Custom tool namespace: x (yes, only the letter 'x').

        - Build action: None

        - Custom tool: ResXFileCodeGeneratorEx

  • Setting for text resource files of an enumeration file:

        - Custom tool namespace: aenum

        - Build action: Embedded Resource

        - Custom tool: ResXFileCodeGeneratorEx

Events handling

  • When you override an event, always call to base class method.
  • Only handle an event when you have something to do with it. On this example, the OnInit method should be removed because we have nothing to do with it:
protected override void OnInit(EventArgs e)
{ 
 base.OnInit(e);
}

Request

  • All the arguments which can be passed to the url must be documented.
  • Each request parameter must have it own getter property. Handling of the request parameters must always be inside the getter properties.
  • All request parameter getters must be put in a region called “REQUEST PARAMETERS”.

Session

  • Use SessionManager to work with Session.
  • Objects which are put into the Session must be serializable.
  • Examples about good and bad usages of Session, in the share-data-between-pages context:

         - Good if the data is complicated and cannot be render to the clientside or pass via url easily. A good example is the search criterion of the search page.

         - Good if the data is incompleted, so it is not ready to be saved to the database yet, for example the data which is collected through a wizard: we collect some pieces of information in step 1, put them into Session and navigate to the step 2, and so on...

         - Good if the data takes too much resources (IO, CPU, time) to retrieved. For example a fully-initialized Questionnaire, means all of its questions, question properties, sub questions, answer options are initialized.

         - Bad if the data in Session can be changed by multiple pages/forms by multiple ways. For example: the page A shows some information about a report, which is put in the session. The user opens the Report compact dialog in another tab. When the user saves the report in the CRD, it is the database is updated, not the report object in the Session. Now the user backs to the page A and modifies the report. Obviously he will get a concurrency problem.

Javascript

  • Do not use browser-specific script. All the javascript must work in both IE and FireFox.
  • Javascript should be written in OOP style using AJAX .NET. One class should be in one file.
  • Functions must be documented about their usages and their parameters. Types of parameters must also be specified.
  • In order to utilize the intellisense feature of VS2008:

       - Put summary inside function:

Javascriptsummary.jpg

  • To get intellisense work in a javascript file, you have to add a reference to the source JavaScript file. There are two situations need to be considered here:

      - If the source JavaScript file is a embedded resource, use the declaration below:

               /// <reference name="registered name of that embeded JavaScript file" />

      - If the source JavaScript file is an included file, use the declaration below:

               /// <reference path="path file name of that JavaScript file"/>

Javascriptreference.jpg

  • To get intellisense work in a ASPX file:

      - If your page is implementing AJAX, reference to the source JavaScript file in ScriptManager control: <source lang="csharp" line="1"> <asp:ScriptManager runat="server" id="scriptManager"> <Scripts> <asp:ScriptReference path="virtual path file name of the JavaScript file" /> </Scripts> </asp:ScriptManager> </source>       - Otherwise, reference to the source JavaScript file in a script element declaration:

                <script src="virtual path file name of the JavaScript file" type="text/javascript" >

Data access layer

AccessFactory

  • Special uses of AF must be approved in the TD. They can be:

        - Where you need to create an AF by yourself.

        - Where you need to call Commit or Abort.

        - Where you need to call CloseOverwritenConnectionWithNoGlobalTransaction and OverwriteConnectionToNoGlobalTransaction. 

Access class

  • Every access class of a domain class needs two callback methods and two delegates which are used when creating and saving objects.
  • The callback method which is used when creating object is named Create. In this method, data is read from the IDataReader to build an object. Signature of the Create method is:

<source lang="csharp" line="1"> static private T Create(ref CreateOrd co, IDataReader reader) </source>

where T is a domain class, for example User, Attachment or EmailAddress.

  • The callback method which is used when saving object is named Save. In this method, the primary key of the being saved object is read from the IDataReader and update to the object. If the object is a Resource, version is read and update too. Signature of the Save method is:

<source lang="csharp" line="1">

static private void Save(T emailerror, IDataReader reader) </source>

  • Create two delegates for the two methods above. These delegates are passed to the AccessBase.Execute[Action] methods:

<source lang="csharp" line="1"> static readonly CreateDelegateGen<T> create = Create;

static readonly SaveDelegateGen<T> save = Save; </source>

Building query

When building a query:

  • Only make your own sql builder function if you can’t find an appropriate one in the GenericSqlBuilder class.
  • All the methods in the MySqlBuilder layer must begin with “Build” and end with “Sql”.
  • Use StringBuilder to build your queries.
  • Always use provider constant to get table names and column names.
  • MySqlBuilder methods should take the same parameters as calling method from the Access layer, except when multiple methods from the Access layer call the same builder.
  • Make your input parameters as strict as possible. For example, if the input is a provider table of a resource view, its type shouldn’t be ProviderTable, but ProviderResourceViewTable.
  • Always use GetLiteral functions to convert a value to a string which can be appended to the query. Usage of GetLiteral is not required when data type of the value is number.
  • Append every condition of the where clause in a separate line. Operants of an OR operator should be written in one line.
  • Example:

Wrong:
<source lang="csharp" line="1"> StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.Append("SELECT ID"); sqlBuilder.Append(" FROM "); sqlBuilder.Append(" USER_RESOURCE "); sqlBuilder.Append(" WHERE "); sqlBuilder.Append(" NAME "); sqlBuilder.Append(" = "); sqlBuilder.Append(userName); sqlBuilder.Append(" AND "); sqlBuilder.Append(" (Access_Expiration <= "); sqlBuilder.Append(CGDateTime.Now.ToString()); sqlBuilder.Append(" OR "); sqlBuilder.Append(" Access_Expiration is NULL) "); </source>

Correct:
<source lang="csharp" line="1"> StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.AppendFormat("SELECT {0} ", PC.UserResource.Id); sqlBuilder.AppendFormat("FROM {0} ", PC.UserResource.TableName); sqlBuilder.Append("WHERE "); sqlBuilder.AppendFormat("{0} = {1} ", PC.UserResource.ShortName.Name, GetLiteral(userName)); sqlBuilder.AppendFormat("AND ({0} <= {1} OR {0} is NULL)", PC.UserResource.AccessExpiration.Name, GetLiteral(CGDateTime.Now)); </source>


Performance

  • If using lazy evaluated property on a collection of objects, then the properties should be initialized before usage to prevent the lazy evaluation. Naming for that function is InitAll[PropertyName].
  • The InitAll[PropertyName] functions should be implemented using the CatGlobe.Domain.Common.GenericInitAllHelper class.
  • When you need to check for access of a user to many resources, do it once directly in the query.
  • Similarly for navigation accesses checking: there is a method to check for many navigation accesses in the PageBase class.
  • Use string.Format when you want to concatenate more than 2 string objects in one line.
  • Use StringBuilder when you want to concatenate string objects in many lines, or inside a loop.
  • Use generic types like Dictionary<> and List<> instead of HashTable, ArrayList. ArrayList can be used for return type of Server methods.
  • When you have a list of items, you may want to use Dictionary or List to store them. The rule is:when you want to store values to look up quickly, use the Dictionary class. Otherwise, use List.

Auto-generated files

There are a few auto-generated files in Catglobe:

  • ConfigurationConstants.
  • ProviderConstants.
  • Text resource classes.
  • Resx files.
  • Designer files.
  • SessionManager.
  • JavaScriptFileConstants
  • LINQ to XSD generated files.
  • WSDL generated files.
  • WCF generated files.

Rules:

  • DO NOT: modify it manually.
  • DO: modify the source file and then generate the source code file.


Webconfig

  • A new key must be approved by CORE.
  • You need to add a validation method for the new key in the WebconfigValidation class.
  • DO NOT: read the key directly from webconfig.
  • DO: make a new property in the WebconfigManager class to read it.


Data validation

  • Specify the maximum length of character input fields.
  • Specify the minimum and the maximum value of numeric input fields.
  • Validation, if possible, should be done first on the client side. Data then must always be validated again on the server side.
  • Try to use control which supports data-restriction. For example, the WebNumeric control allows us to specify the minimum and maximum values, allows numbers only.
  • Checking for database constraints, for example if a resource name already exists, should be done before data is actually inserted or updated to the database.
  • Validations may need to be done:
  • If the input value is in the valid range.
  • If length the input value is the valid range.
  • If it contains invalid character.
  • If it meets some specific constraints, for example an email address field must match the email naming rule.


Resource access – navigation access

  • Any page which requires navigation access must be check for navigation access in itself.
  • Any page which shows information of a resource to the user must check for resource access.
  • Given that in page A we have a button called Open which is used to open the page B, which shows information about a User. *Typically, we need to check:
    • In the page A:
      • Check for navigation access to show/hide or to enable/disable the Open button.
      • In some pages you may need to check for resource access to enable/disable the Open button.
    • In the page B: You need to check for both navigation access and resource access again. The reason for this check is that the user may copy the url to open a page and change some of its parameters to open another resource directly to bypass the check in the source page.


Server method

  • DO NOT call server method inside a FOR loop. There is almost always a way to collect all the needed data and call the server method just one time.
  • Important rules
  • Always put the call to a synchronous server method in a try-catch block on the client side. Recall to the empty try catch rule, you may need to show an error message to the user.
  • For asynchronous server methods, refer to ServerMethods' exception handling for more details.
  • Exception handling in a server method should follow the section about exception above.


Localization

  • Data which is shown to the user must be in the culture of the logged in user. In the case of date time, it is also required that the display value must be in the time zone of the logged in user. All exceptions must be specified in the feature design.
  • Use CGDateTime instead of DateTime in the Business logic layer and Domain layer. Usages of the .NET DateTime struct is restricted in GUI only, unless they are approved in TD.
  • If a GUI needs a control to work with date time, use the CGDateTimeControl. However, if the field is an editable-date-only, use the Infragistic.WebDateChooser control.
  • The Turkish culture has a lot of differences from other cultures. Refer to this link for more information: http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html
  • String representation of data which is saved to the database must be in Invariant culture.
  • String representation of data which is passed to the domain layer should also be in Invariant culture.
  • Date time which is stored in the database must be in UTC. If you need to store a string of date time value in the database, its format must be in Invariant Culture and its time zone must be UTC. This includes all data in XMLs.


Commit rule



General



Xml



Utility classes



How to create a CGScript library or function