Transcript Document

Quality in connection of Symbian Code
Presented by:
Abu Rashid,
Student, Researcher.
April 1st, 2005.
Contents








Quality Code
Personal Quality Strategy
Coding Conventions
Critical part of Symbian OS programming
Symbian Coding Standard
Writing Good Code
Internationalization, Cleanup Stack, Exception Handling in
Symbian OS C++
Guidelines to avoid memory leaks
What is quality code?
Definition

Correct

Efficient (time, space)

Sufficient (for the task at hand)

Understandable (readable, maintainable)

Reusable

Extensible

Self Documenting Code
By means of ‘illities’ - reliability, maintainability, readability, enhanceability, performability, scalability, etc. Due to some business factors
some ’illities’ are sometimes magnified and some others ’sacrificed’.
Why quality code matters
Some Questions:
 What you ship to the user is the binary, not the source; nobody
outside your team ever cares to look at it. So does quality code
really matters?
- ”..you will care if you have to maintain it..debug it... and you cost money.
The business cares about that.”


Does quality in coding especially, naming convention results in
measurable business returns?
Compilers also don’t care about source code quality
Some good discussions on quality of code:
-
-
What is good code? :
http://www.artima.com/forums/flat.jsp?forum=106&thread=96404
The Code Quality Myth:
http://www.artima.com/forums/flat.jsp?forum=106&thread=96154
Personal Quality Strategy

Watts S. Humphrey
Quality Stages –
Stage 1: Basic code quality: syntax and coding constructs
- At this stage, quality is personal
- Track, analyze and record the defects to improve the
personal level of basic code quality
Coding Conventions






A common mean to improve software quality
Used to avoid and control the usage of problematic
characteristics in programming languages
Unifies the appearances of source code
Improves readability of the software, allowing engineers to
understand new code more quickly and thoroughly
80% of the lifetime cost of a piece of software goes to
maintenance
Coding conventions are used to ease the programming itself.
Critical part of Symbian OS programming
The critical part of Symbian OS programming –

Error Handling

Cleanup Framework
We will discuss about these in details just after going through
general coding conventions.
Symbian Coding Standard
General Rules:

Reusability: Comments in code can make the code more
understandable and easier to read. However, if the code needs a lot of
explanation, it is probably not clear enough.

Maintainability: [While writing the code] How will the other developers
understand this code?

Build Process: You have to have very good reasons to ignore warnings.
Source Files:

Filenames in lowercase, but with the first letters of words capitalized.

Header files are kept in the directory ".\inc" or in directories mentioned
in the bld.inf file.

Private header files in quotation marks (“”) and public headers are in
angle brackets (<>) in #include directives
Coding Conventions:






Use descriptive name for identifiers
Use terminology applicable to the domain; if clients are actually
customers, then use customer
Use mixed case to make names readable
Use abbreviation sparingly and intelligently: ‘no’ or ‘num’ for
number
Avoid long names (< 15 chars)
Names such as sqlDatabase for an attribute or SqlDatabase for
a class are easier to read than sQLDatabase and
SQLDatabase.
Coding Conventions: Continued




All names should be in English
Join words, avoid numbers and abbreviations in names
Never use ‘_’. Exception: preprocessor macro names in #define
Automatic variables: declare when required, initialize when they are
declared rather than assigning values to them
TInt CTetrisClass::Function() // Member function
{
TInt automaticVariable( KInitialValue ); // Integer variable
TBool status( IsItTrue() ); // Boolean variable
iMemberClass.Method(); // Calls a method
...
}

Never initialize or instantiate multiple items on the same line.
Coding Conventions: Continued

Control Structures: switch() must have a default: clause and
avoid ‘case’ without a break statement. Use braces ({ }) for if (),
else, while (), do..while (), for (), even if there is only a single
statement or an empty block.
Class names: <Symbian OS prefix><Project prefix>Name
Symbian OS prefix:

C (heap-allocated class derived from a base class CBase)

R (resource class containing handles to a real resource, which
is maintained elsewhere)

T (simple type)
 M (mix-in class / interface class)

Use references in preference to pointers
Coding Conventions: Continued
Functions:

Parameter names with ‘a’ (argument) prefix

Use const attribute when a method does not need to change the
parameter

Use trailing L(function that may leave), C(places item on the cleanup
stack) or D(destroys the object in question) to the function name where
appropriate
static CMyClass* newLC(); // may leave and places an item on stack
TInt ExecuteLD(TInt aResource); //may leave and will destroy the object
Automatic variables:

Do not declare until required

Never initialize multiple items on the same line
Coding Conventions: Continued
Global variables:

Use of global variables is discouraged

Start names with a capital letter. If the letter has to be H/T/C, then ‘g’ as prefix,
e.g. gWhatever
Macros:

All capitalized

Underscore separated words, e.g. IMPORT_C, _TEST_INVARIANT

Avoid #defineS, use real constants instead const TInt KMagicNumber = 42;
Constants:

Preceding K uppercase
Enumerated types:

T prefix, uppercase E prefix for enum members

Class CTetrisBlock { enum TBlockType {ESquareBlock, ELBlock};};
Copyright messages:

Copyright (c) 1997-2005 Symbian Ltd. All rights reserved.
Coding Conventions: Continued
Asserts, Panics & Class Invariants:

__ASSERT_ALWAYS & __ASSERT_DEBUG test macros can prevent
many problems
- Many error condition will not trip up the application straight
away, but will lead to side effects later. So check for parameters
coming into functions, null pointers and other error conditions
// Removes text content, commencing at position aPos, over aLength
// number of characters
void CComplexTextObject::Delete(TInt aPos,TInt aLength)
{
__TEST_INVARIANT;
__ASSERT_ALWAYS(aPos>0,Panic(EPosOutsideTextObject));
iTextBuffer->Delete(aPos,aLength);
__TEST_INVARIANT;
}
Coding Conventions: Continued
Multi-inheritance:

Only M classes may be used in multi-inheritance.

Only the interface may be inherited. Therefore all M classes must be
pure virtual.

Inherit from the CBase-derived class first to achieve the correct layout
of the v-table –
class CDerivedClass : public CBase, public MSomeObserver
Cleanup stack:

Use the cleanup stack in preference to TRAP harnesses where
appropriate.

Deriving a class from CBase provides support for using the cleanup
stack. For other classes you can provide explicit cleanup support via
the TCleanupItem class.

Never push member data on the cleanup stack.
Coding Conventions: Continued
Class Design:

Use references in preference to pointers

Use least derived class possible
Class layout:

Always write access control specifiers; special member function at the
top

List the public methods first

List public member data before private member data

Obey the indentation convention
Coding Conventions: Continued
Virtual function:
 Virtual functions that replace inherited behavior should be
grouped together in the header with a comment documenting
which class the behavior is inherited from

It is not necessary to specify the virtual keyword for these
functions

Do not make virtual functions inline, but inline virtual destructor
is ok.
Inline functions:

specify inline explicitly for inline functions

do not implement the inline implementation in the class
definition; this confuses and pollutes the header, making it less
readable

provide inline implementations at the bottom of the header or in
a separate .inl file
Writing Good Code







Build code that gives 0 compiler warnings and 0 link errors
Be consistent in the use of programming conventions
Strive to write tight, efficient code
Minimize on stack usage
Minimize on the number of calls to the allocator
Always ask... what would happen if this code were to leave?
Avoid hard-coding magic numbers; use constants or
enumerations.
Internationalization





Rule of thumb: do not hard code anything that is visible in the
user interface – all text, filenames, sounds, time and date, etc.
Descriptors and charsets – TPtr class should be used for strings
Text – use logical names
Graphics and screenlayout – avoid using text in UI elements; if
text is really needed for graphics, use a text string on top of
graphics. Do not hardcode string sizes
Locale specific data – hardcoded language or countrydependent information such a date, time, currency, etc. should
not be used. Use AVKON resources wherever possible.
Font – Use a resource file and refer the fontname by its logical
name.
Exception Handling in Symbian OS C++




Symbian OS applcations are designed to run for years
without needing to reboot, and on memory constrained
devices, so an out-of-resource error is more likely to
occur than in desktop applications
Conventional error checking(using if statement to check
for out-of-resource) is not used because: introduces
many extra lines of code, if a constructor fails to allocate
resources, there is no way to return an error code as
constructors have no return value.
C++ exception handling (try, catch and throw) is also not
used
Existing C++ programs for other platforms that use
exception handling must be modified before they can be
used.
Exception Handling in Symbian OS C++
Symbian OS provides its own system of exception
handling. The basic operating system support for
exceptions comes from:

The TRAP macro and its variant, TRAPD, which allow
code to be run under a trap harness
TRAPD( error, doExampleL() );
if ( error != KerrNone )
{
// Do some error code
}

The User::Leave() call, which terminates the current
function, and returns to the trap harness, specifying an
error code.
if ( !myObject ) User::Leave(KErrNoMemory);
Symbian OS efficient exception handling rules

Rule 1: Functions that can leave should have a letter L at the end of their
names.
void MyFunctionL()
{
iMember = new (ELeave) CMember;
iValue = AnotherFunctionL();
User::LeaveIfError(iSession.Connect());
}

Rule 2: While allocating memory on the heap, if the pointer is an automatic
variable, it should be pushed on the cleanup stack.
CObject* object = CObject::NewL();
CleanupStack::PushL(object);
object->LeavingFunctionL();
CleanupStack::PopAndDestroy(object);

Rule 3: All the codes that might fail, should be taken out of the constructor, and
put into a constructL() function. This will be called after the constructor has
completed. This is two-phase construction.
Symbian OS efficient exception handling rules: Continued
// Phase #1
MyObject::MyObject()
{
}
// Phase #2
void MyObject::ConstructL()
{
MyMemberData* data = new (ELeave) MyMemberData();
}
// Put both phases together in one function...
MyObject* MyObject::NewL()
{
MyObject * self = new (ELeave) MyObject();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
Symbian OS efficient exception handling rules:
Continued
Note –
 The applcation framework already provides traps in
right places, and code to handle them, so traps
should not be used in normal coding.
 The new operator is overriden to take a parameter
ELeave. In case of memory allocation failure, this
overriden constructor will leave.
 When creating C-class objects, programs should use
newL() if a member variable will point to the object,
newLC(), if an automatic variable will point to it
Using the Cleanup Stack: Why it is needed



When a function leaves, the default TRAP harness inside the
the thread’s Active Scheduler gets control. So all automatic
variables within the function are destroyed. If anyone pointed to
object, then that object is orphaned and memory leak follows.
Solution -> Cleanup Stack.
Automatic variables are used to point C-class objects; objects
are pushed onto the cleanup stack using CleanupStack::PushL()
and popped from it using CleanupStack::PopL().
PopAndDestroy() is normally used instead of Pop().
Object data members which point to other objects must not be
pushed onto the cleanup stack.
Guidelines to avoid memory leaks




Understand the cleanup stack and the Leave/TRAP paradigm.
Build and run code regularly — if a leak appears, it will be more
obvious where it was caused.
When testing, exit the application. Don’t just kill the emulator.
Code reviews are very useful.
Reduce RAM usage:

Use bit fields rather than many Tbools

Use caution with array granularities

Avoid global data

Beware of base class member data

Use cleanup stack correctly

Delete early

Test on hardware with maximum datasets

Break up long, complex operations

Thanks for your time.
 Questions?
References






Harrison, Richard: Symbian OS C++ for Mobile
Phones
Symbian; Symbian OS: Coding conventions in C++,
May 5, 2004
Symbian; Coding idioms for Symbian OS, Oct 2002
Symbian; Symbian OS C++ coding standard, Jan
2003
Halonen & Närvänen & Mikkonen: Automatic
checking of Symbian Coding Conventions.
Humphrey, Watts S.: A personal quality strategy