quality in connection of symbian code presented by: abu rashid, student, researcher. april 1st, 2005
TRANSCRIPT
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, enhance-ability, 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 stackTInt 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. gWhateverMacros: All capitalized Underscore separated words, e.g. IMPORT_C, _TEST_INVARIANT Avoid #defineS, use real constants instead -
const TInt KMagicNumber = 42;Constants: Preceding K uppercaseEnumerated 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 country-dependent 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
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