by Daniel Monza
- Naming
- Enumerated Domains
- Indent and Spacing
- Structured Data Types
- Strings
- Comments
- Commands and Functions
- Parameters
- Resources
- Companies that use this guide
- Translation
- Colaboradorators
- License
- Amendments
-
1.1 Names must be descriptive
The goal is to name stuff in a descriptive way
// bad Proc: CliCre // good Proc: ClientCreate
-
1.2 Use PascalCase when naming objects,attributes and variables
// bad createclient // good ClientCreate
-
1.3 Do not use underscore at the begining or end of any names for objects, attributes or variables.
This could misguide a programmer more familiar with other languages that theres some privacy meaning to the name.
// bad &_CliNam = "John Doe" &CliNam_ = "John Doe" Proc: _ClientCreate // good &ClientName = "John Doe"
-
1.4 Enumerated domain names must start with the entity and then the type without abreviations, both in singular way. When defining a type we should be specific about the type of what.
This facilitates the definition of attributes and variables based on the domain (GeneXus will do it automatically). Also it makes it easier to reuse the domain - i.e. it's not just a Document-Type is the visibility-type of the document and other things might have the same visibility types.
// bad DocumentsTypes DocumentsType DocType // good DocumentVisiblityType {public,private} TransactionAccountType {credit, debit}
-
1.5 Name related procedures as Entity + Attribute (depending on the case) + Action + Complement.
This facilitates the selection of objects that deal with the same entity. Typical actions are Get, Set, Load (for an SDT), Insert, Update, Delete, etc. The difference between Set and Update is that Set refers to one attribute while Update refers to the entity
// bad CliCre UpdateClient DateClient // good ClientUpsert ClientDelete ClientUpdateDateGet ClientUpdateDateSet ClientNameGet ClientNameSet ClientLoad DocumentRecalculate
-
1.6 Use GIK nomenclature to name attributes. The use of 3 characters for the entity is recommendend when the names cannot exceed 20 characters and it has a clear and shared meaning.
This is the standard since the beginings of GeneXus
// bad CreCliDte DateCreationClient // good CliCreDte // Better ClientCreateDate or CliInsertDate
-
1.7 Transactions should be named after the entity in singular.
This faciliates working with Business Component. and it is required by some patterns GeneXus (ie.: K2BTools).
// bad Trn:Clients Trn:Products // good Trn:Client Trn:Product
-
2.1 Use tabs (tab) instead of "spaces". This way each developer can visualize the space as they prefer since the number of characters in a tab can be configured in GeneXus preferences.
Indent faciliates reading the source code, so if we follow a standard indentation it will make it easier for other developers to follow and understand the code.
// bad if &DocumentOperationType = DocumentOperationType.Sale msg("Sale") endif // bad if &DocumentOperationType = DocumentOperationType.Sale msg("Sale") endif // good if &DocumentOperationType = DocumentOperationType.Sale msg("Sale") endif
-
2.2 Indent conditions in a for-each command
// bad for each where DocumentOperationType = DocumentOperationType.Sale ... endfor // bad for each defined by ClientName ... endfor // good for each where DocumentOperationType = DocumentOperationType.Sale ... endfor
-
2.3 If a for each specifies a WHERE condition, or a DEFINED command, leave a blank space before the next line
// bad for each where DocumentOperationType = DocumentOperationType.Sale if DocumentTotalAmount > &MaxCreditAmount ... endif endfor // bad for each defined by ClientName for each Document ... endfor endfor // good for each where DocumentOperationType = DocumentOperationType.Sale if DocumentTotalAmount > &MaxCreditAmount ... endif endfor // good for each defined by ClientName for each Document ... endfor endfor
-
2.4 Leave a space before each parm.
It makes the parm sentence more readable
// bad parm(in:ClientId,out:&ClientName); // good parm( in:ClientId, out:&ClientName); // bad &Date = ymdtod(2017,01,01) // good &Date = ymdtod( 2017, 01, 01)
-
3.1 Avoid the use of literals when there are many possible values
It makes the code easier to read and avoids typos and confusion
// bad if &HttpResponse = "GET" // good // Create an enumreated domain HTTPMethod with possible values ( POST, GET) if &HttpResponse = HTTPMethod.Get
-
4.1 Use New() when crating an SDT instead of a Clone(). Also do it before the SDT is used for the first time instead of at the end (even though GeneXus supports it)
It improves readibility
// &ClientCollection is aSDT:Client [List] // &Client is a SDT:Cliente // bad for each Client &Client.ClientName = ClientName &ClientCollection.Add( &Client.Clone() ) endfor // good for each Client &Client = new() &Client.ClientName = ClientName &ClientCollection.Add( &Client ) endfor
-
4.1 As GeneXus allows to define a variable as a collection, avoid the creation of SDT of type collection.
When defining the variable of the particular item, mark it as a collection
// bad SDT:Clients : Collection ClientItem ClientNome // good SDT:Client ClientName
-
5.1 Use format to display messages that contain data
If the application will be translated to different languages, there is no need to change the programming
// bad &Msg = "The client #" + &ClientId.ToString() + " is called " + &ClientName // good &Msg = format( "Client # %1 is called %2", &ClientId.ToString(), &ClientName)
-
5.2 Use !"" for strings that do not need translation
A translator can modify constants for specific system codes that can affect the behavior (i.e. for parameters)
// bad &ParmVal = ParmGet( "GLOBAL ENCRYPT KEY") // good &ParmVal = ParmGet( !"GLOBAL ENCRYPT KEY")
-
6.1 Use
/** ... */
to write multi-line comments.// bad // CreateClient creates a new client // parameters: // &ClientName // &ClientAddress sub 'CreateClient' // ... endsub // good /** * CreateClient ceates a new client * parameters: * &ClientName * &ClientAddress */ sub 'CreateClient' // ... endsub
-
6.2 Use
//
for single line comments. These comments should be in the line before the comment-target. Leave a blank line before the comment unless it is the first line of the block.// bad &ClientName = "John Doe" // Assign name to the variable // good // Assign name to the variable &ClientName = "John Doe" // bad sub 'CrateClient' msg( "Creating Client", status ) // Create Client &ClientBC = new() &ClientBC.ClientName = "John Doe" &ClientBC.Save() endsub // good sub 'CreateClient' msg( "Creating Client", status ) // Create Client &ClientBC = new() &ClientBC.ClientName = "John Doe" &ClientBC.Save() endsub // this is also Ok sub 'CreateClient' // Create client &ClientBC = new() &ClientBC.ClientName = "John Doe" &ClientBC.Save() endsub
-
6.3 Start comments with a space to increase readibility.
// bad //Is Active &IsActive = true // good // Is Active &IsActive = true // bad /** *Get the Company name *so we can display it afterwards */ &CompanyName = CompanyGetName( &CompanyId) // good /** * Get the Company name * so we can display it afterwards */ &CompanyName = CompanyGetName( &CompanyId)
- 6.4 Prefix comments with
FIXME
oTODO
help other developers to understand quickly if they are looking at a possible issue that needs review. These are different from other comments as they are supposed to trigger future actions. Actions areFIXME: -- needs a solution
orTODO: -- needs implementation
.
-
6.5 Use
// FIXME:
to highlight issues// FIXME: Check when &Divisor is 0 &Total = &Number / &Divisor
-
6.6 Use
// TODO:
to highlight pending implementations// TODO: Implement Sub Sub "CreateClient" Endsub
-
7.1 Use lowercase when naming commands and system-functions
This makes development faster as commands are used frequently and they dont need PascalCase. The only exception sometimes is Sub because it makes it more visible the start/end of the Subroutine
// bad for Each Where ClientId = &ClientId Msg(ClientName) EndFor // good for each where ClientId = &ClientId msg(ClientName) endfor // bad &Date = YmdToD( 2017, 01, 01) // good &Date = ymdtod( 2017, 01, 01)
-
7.2 Use do case to substitute nested if when possible. Leave a space between each case when the sentences are complex otherwise format to maximize readibility
// bad if &DocumentType = DocumentOperationType.Sale ... else if &DocumentType = DocumentOperationTypes.Purchase ... endif endif // also bad do case case &DocumentType = DocumentOperationType.Sale do 'Something' case &DocumentType = DocumentOperationTypes.Purchase do 'Something Else' endcase // good do case case &DocumentType = DocumentOperationType.Sale do 'Something' case &DocumentType = DocumentOperationTypes.Purchase do 'Something Else' otherwise do 'Something entirely different' endcase // also good - When there are many cases and the action is a one-line piece of code. >This facilitates read all the options without having to scroll do case case &Action = Action.Update do 'DoUpdate' case &Action = Action.Insert do 'DoInsert' case &Action = Action.Regenerate do 'DoRegenerate' case &Action = Action.Clean do 'DoClean' case &Action = Action.Refresh do 'DoRefresh' case &Action = Action.Reload do 'DoReload' otherwise do 'UnexpectedAction' endcase
-
7.3 Use "where" clause in for each commands instead of "if", whenever we are dealing with extended table attributes.
The condition is solved by the DBMS and is optimized.
// bad for each Document if DocumentType = DocumentOperationType.Sales ... endif endfor // good for each where DocumentType = DocumentOperationType.Sales ... endfor
-
7.4 Use "when" in for each commands to simplify the sentence sent to the DBMS.
// bad for each Documentos where DocumentType = DocumentOperationType.Sales where DocumentDate >= &StartDate or null(&StartDate) ... endfor // good for each where DocumentType = DocumentOperationType.Sales where DocumentDate >= &StartDate when not &StartDate.IsEmpty() ... endfor
- 8.1 Use an SDT instead of multiple related parameters
Otherwise code might be harder to read and when parameters are modified we need to review all the callers. This might not be always possible - i.e. in webpanels
```javascript
// bad
parm( in:&ClientName, in:&ClientLastName, in:&ClientPhone, in:&ClientAddress, in:&ClientDOB)
// good
parm( in:&sdtClient )
```
- GeneXus Wiki - GeneXus
- GeneXus Training - GeneXus
- GeneXus Developpers - GeneXus
This is a list of organizations that are using this style guide. Let us know your feedback and if you want to be added to this list (or a specific fork) and we will add you.
This style guide is also available in other languages:
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
based on AirBNB Javascript guide
We encourage you to fork this guide and change the rules to fit your team's style guide. Below, you may list some amendments to the style guide. This allows you to periodically update your style guide without having to deal with merge conflicts.