找回密码
 注册
搜索
查看: 1602|回复: 1

[讨论] 小糊涂学symbian日记(3)

[复制链接]
发表于 2005-10-28 12:58:00 | 显示全部楼层 |阅读模式
小糊涂学symbian日记(3)
三种基本结构,很不错,用点各自都有一定之规
传统的是定制容器空间结构,这个不谈,很多很多的典型symbian程序都是这个模式。
基于对话框的结构,比较适合于简单需要的用户界面交互的那些应用。
使用应用/视图的结构,这个比较高级了,可以提供很多外部程序的外用视图,这个时候AppUi需要继承自CAknViewAppUi,而views则需要继承自CAknView。
60系列的通过用户界面设计模式是MVC模式,ie.Model - View - Controller三者。
用户的交互操作全在这三者上体现了:)
注意构造并显示一个对话框时要使用ExecuteLD,用了这个函数时,就不应该再把对话框置于清除栈中,因为其保证了当异常发生时会释放所分配的内存,一旦用户通过按ok或cancel退出时,ExecuteLD就会返回。
CEikonEnv是一个生成Uikon控件和那些处理这些控件的应用函数的环境,我们可以将它视为是MFC编程中经常出现的CWinApp* pApp = AfxGetApp(),有了这个pApp可以运用程序实体的很多功能。同样每个Uikon应用程序都由框架提供这么一个CEikonEnv的实例,既可以通过CEikonEnv::Static()来访问又可以通过CEikApplication的宏iEikonEnv来访问。之所以讲这个出来,是因为在程序中很多地方你都会看到诸如iEikonEnv->InfoMsg(...)的应用。但注意这个只是适用于调试版本的模拟器,如果需要类似的调式功能,可以使用弹出式的窗口来代替。
我们是靠着控件来和用户交流接收信息,所有的控件都放在控件栈里,我们可以在AppUi的ConstructL()来向控件栈添加控件。View视图通过调用OfferKeyEvent()来将这个事件分配给其包含的各控件,怎么做的那,就在在控件栈里向下转,在控件栈里后进入的控件先接受到这个事件,如果不处理就返回EkeyWasNotConsumed,然后该按键事件就传给下一个项目,实在没有人接受了最终就是到控件栈的最低层AppUi,其他控件不处理的事件都归他处理。
CCoeEnv提供一个生成控件的活动环境。它可以提供一个激活的对象和一个active scheduler,这个东西能提供我们访问window server的功能,它也提供很多有用的函数。
当一个标准事件发生以后,active scheduler调用CCoeEnv::RunL()来处理,当一重绘事件发生后,则调用CCoeRedrawer::RunL()函数处理。
symbian并不使用线程,对这么个小巧的系统使用线程显得很难受它比较消耗电源和电能,它使用的是异步处理,用一个活动对象,而由acitve scheduler的等待循环机制来使得一个单一的线程能够处理多个异步请求。一个活动对象就必须实现两个纯虚函数:RunL()和DoCancle()。任何长时间运行的处理任务都应该在活动对象结构内部被分阶段运行。
接着谈谈程序的本地化实施,只有两个重要法则要记住:一是不要在c++源文件中嵌入文本,另一个就是不要对数据缓冲区尺寸进行绝对编码(在众多的数据转换中就看出来了)。
在示例代码的使用中有很多术语要遵守,下面我们就要谈谈这些个术语。注意我们先阐明一些规则用的术语,这些术语表明了相关规则的作用。
viability 如果代码不遵从这个规则那将无法工作。
reliability 如果代码不遵从这个规则那可能无法好好工作。
maintainability 如果代码不遵从这个规则那可能很难维护。
readability 如果代码不遵从这个规则那可能很难理解。
convention 如果代码不遵从这个规则那将不符合约定束成。
同样规则们也被标记为一般的
c++代码规则
symbain OS特定规则
Nokia推荐规则
--------------现在列举并解释这些术语-------------------
Assertions
——reliability (symbian)
  一个函数体可以由一系列的_ASSERT_ALWAYS()宏开始,以用来检验参数的有效性。
  如果函数不属于公共API,那建议使用ASSERT_DEBUG()来代替。
  提示注意点
  1、如果你要排除一个指针为非空,那就建议使用一个引用来代替它。
  2、如果你要判断一个有范围的值,那建议你使用一个枚举或者T-class对象。
  3、你的构造函数可能会需要一些有关参数的预检查,这个时候最好是将这种检测放在构造函数的函数体当中。
  4、在头文件中,我们应该把函数中用到的Precondition assertions做为注释来描述出来。
  5、Preconditions不应该放在NewL()L或NewLC()中,但可以放在构造函数和ConstructL()。
——reliability (symbian)
  在函数的最后,最好是对返回值作个检查,或者函数是否完成了它应该完成的任务。可以使用ASSERT()来处理这类测试。
  提示注意点
  1、如果函数有多个返回值,那请记得给每个返回值都放上postconditions检查。
  2、如果你要判断一个返回的指针不为空,那建议你返回一个引用。
  3、同样最好把这些判断都做为注释标注起来。
——reliability (symbian)  所有的重要类都要处理invairant的检查。这些Invariants能够在类的成员函数中作为preconditions和postconditions来使用。
  Every public non-static function calls __TEST_INVARIANT at the start
and at the end (or only once if the function is a single line query). Put Invariants before preconditions and after postconditions. The last line in ConstructL() is __TEST_INVARIANT.
  注意点:
  1、如果_DbgTestInvariant()函数中调用了_TEST_INVARIANT那最好不要调用任何函数再。
  2、如果函数有多个返回值那记得要在每个返回之前调用_TEST_INVARIANR!     3、You may call static functions at any time, as static member functions can't check the Invariant, not having any state to verify.

C classes
  (symbian) note C类对象不能被做为一个值来传递或者是返回,但可能通过指针或者引用来使用它。
  (symbian) note Passing C class objects by pointer implies either the transfer of ownership, or that the parameter is optional. To remove this ambiguity, consider overloading functions that have optional parameters.
  (symbian) note Returning C class objects by pointer implies either the transfer of ownership, or that the return value may be NULL. To remove this ambiguity, consider pushing the object on to the cleanup stack before you return it, and adding a trailing C to the function name.
class invariants
class
viability (symbian) 在symbianOS的每个类都必须是下列五个种类之一,要使用前缀(大写字母)C, T, M, S or R。
reliability (symbian) C类必须有个析构函数,那是CBase的一个虚函数。如果是空的,那也要使用注释如//empty destructor
maintainability (c++) 尽量避免使用友类,这会破坏封装。
reusability (c++) 应该在头文件中描述所有的类,如果你要隐藏一个类,那就嵌套使用它们。
convention (nokia) 对每个类都应该有个cpp和h文件,除了嵌套类。
convention
  (symbian) note 任何从CBase中派生的类都必须有个C前缀。
  (symbian) note An M class only has virtual methods, and no data. The methods can at most have only a trivial implementation.
  (symbian) note C类对象可以推入清除栈。
  (symbian) note C class objects must either be newed, or (in rare cases) be a member variable of another C class.
  (symbian) note C classes inherit a private assignment operator from CBase, so it is not necessary for you to define one.
Coding Style
——readability
  如果你要换行,那最好在合适的地方,并且下面的行缩进。
——readability (c++)
  多使用括号来辨析含糊的地方。
——convention (nokia)
  1、主要操作附近不要有空格。
  2、不要在一元操作符和操作数之间插有空格。
  3、不要在函数名或宏名与他们的参数间插入空格。
  4、注意匹配空格和括号。
Comments
——readability
  注意不要把注意变成代码的简单复述,你应该在代码含混不清并且缺少文档的情况下使用这个注释。
——convention
  一个注释块由一个“/**”开始并且由“*/”,每行都以*开始,基本形式如下:
/**
* <BriefDescription>
* <MarkUpTag>
* <MarkUpTag>
...
* <MarkUpTag>
*/
Alternatively a shorter form can be used:
/** <BriefDescription> */
<BriefDescription>一般是一个informal, one-sentence description of the class, operation or member variable.
The <MarkUpTag> entries start with an @ sign and are the first things (after the optional leading asterisk) on the line.
——convention (nokia)
  在cpp文件代码中用//表示permanent comments。
Compilation errors
——reliability (c++)
  你可以没有编译时错误,但不可避免的要发生警告,这是因为你使用的库的原因。
Constants
——convention
  如果是常量那就要在前面加上字母K。
——convention
  常量应该被做如下的处理:
  1、在一个类中使用枚举的形式(e.g. enum { KMagicNumber = 3};,那就是说,没有类型名,并所有的在一行上)
  2、类中的静态成员(e.g. static const TReal KMagicNumber;)这个只能在一个cpp文件中定义一次。Note that this only works for built-in types, and that TInt64 is not a built-in type.
 楼主| 发表于 2005-10-28 13:00:00 | 显示全部楼层
<P>Construcion
  (symbian) note C-classes 是你能new操作的唯一一个类,并且这个是他们被构造的唯一途径。
  (symbian) note All C-class member variables are nulled on creation. </P><P>Constructors
——viability (symbian) ConstructL() should never be a virtual function, since a partially constructed object isn't a polymorphic entity. </P><P>——reliability (symbian) 在C classes中的Constructors和ConstructL()必须作为保护或私有的成员函数。and should be empty apart from a member initialisation list and ASSERT macros. This enforces correct two-phase construction of object. </P><P>——reliability (symbian) 你的C class中必须有一个NewLC()函数。unless it's a nested class where you have a bit more leeway.NewL()是可选的,并且总是应该根据NewLC()来实现。两者都必须有个标准模式,应该调用ConstructL(). Non standard construction make code unclear, and prone to cleanup stack errors. </P><P>——reliability (symbian)
  在ConstructL()的实现中,你必须首先在基类中调用ConstructL()。
  (symbian) note NewL()和NewLC()在c class中必须做为静态函数,通常是公共函数。 </P><P>  (symbian) note 拷贝构造函数在symbianOS总失去了它的作用,一般只有有析构函数的类才有构造函数。 </P><P>consts
——reliability (c++)
  Const correctness should be applied throughout. Most funcions that return a value should not change the object they are applied to.如果你有个成员变量是一个指向某对象的指针,那编译器允许你在一个const函数中调用非const函数,譬如:
Class WorstCaseScenario
{
public:
WorstCaseScenario() : iThis(this)
{
} </P><P>void ChangeTheWorld(); </P><P>TBool InnocentLookingFunction() const
{
iThis-&gt;ChangeTheWorld();
} </P><P>WorstCaseScenario* iThis;
} </P><P>destruction
  (symbian) note 如果一个对象被析构两次,那将是个严重的错误。在什么情况下会发生这类情况那?一般如果一个异常发生时,在清除栈中的对象和析构函数都遭到调用就会发生了。 </P><P>destructors
——reliability (c++)
  在一个析构函数中或者是析构函数调用的函数中,我们并不能保证对象都被适当的构造了,因此你必须检查对象的状态并且能应付各种状况。你不必抛出任何异常。 </P><P>  例如
  MyClass::~MyClass()
  {
    if(iObject) //might be NULL if constructor failed
    {
      iObject-&gt;Close();
      delete iObject;
      iObject = NULL;
    }
    delete iFred; //delete NULL is allowed
    iFred = NULL;
  } </P><P>DLLs
——viability (symbian)
  你不能在DLL中含有any global non-constant data。这包括static member variables. 你能含有的唯一全局数据就是constant static built-in types,即没有构造函数的东东:) </P><P>exceptions
——viability (symbian) note 你不能使用C++风格的异常,这个我们上面已经讲过,那个结构实现复杂很不适合symbian的小巧特性。 </P><P>files
——viability (symbian)
  Place Control IDs, and defines in .hrh files. </P><P>——readability (symbian)
  在资源文件中,总是要有注释,这是为了说明文件的用法。 </P><P>——convention
  .mmp和.rss文件的命名:如果只有一个,那就用project名(如animation.mmp),如果有多个的话,那就用subproject名(如engin.mmp) </P><P>——convention
  一个.mmp文件就应该有洋目录,叫做group,或者是&lt;subproject&gt;,里面包括.mmp.def和readme文件。 </P><P>——convention
  公共头文件应该放在一个inc目录中,或者是&lt;subproject&gt;inc。 </P><P>——convention
  所有的文档都应该在subdirectory,或是&lt;subproject&gt; docs。 </P><P>——convention
  所有和.aif文件有关的文件都必须放在aif目录中。(To avoid name clashes with the .rss file) </P><P>——convention
  Test文件应该放在tsrc目录中或&lt;subproject&gt; tsrc中。 </P><P>——convention
  所有其他的文件都放在src目录中或&lt;subproject&gt; src中。 </P><P>flow control
——reliability (c++)
  Switch语句总是要有个缺省的clause,if default should never occur, the default clause should be an assertion to that effect.例如
switch(value)
{
case 0:
case 1:
case 2:
DoSomething();
break;
case 4:
case 5:
DoSomethingElse();
break;
default:
ASSERT(EFalse);//cannot occur
} </P><P>——maintainability (c++) 永远不要用goto语句 </P><P>funcionts
——maintainability (c++) 不要使用缺省参数(though exceptions can be made for having one default parameter only)。如果你的函数有n个缺省参数,那最好还是把它改为n+个该函数的重载版本。 </P><P>Example:
AddControl(Control&amp; ctrl, ControlObserver* observer = 0); </P><P>Becomes:
AddControl(Control&amp; ctrl);
AddControl(Control&amp; ctrl, ControlObserver* observer); </P><P>Which can be improved further to become:
AddControl(Control&amp; ctrl);
AddControl(Control&amp; ctrl, ControlObserver&amp; observer); </P><P>看出来了,尽量用引用来表现参数。 </P><P>——readability (c++)
  尽量保持函数体精干。 </P><P>——readability (symbian)
  不要返回错误代码,使用异常机制来代替。 </P><P>convention (c++)
  函数名应该由一个大写字母开始。正常Normally Midifiers are expected to do something, and hence the name is in the form of an order. </P><P>——convention (symbian) 所有的内联函数都应该放在inl文件中,记住要加关键字inline。 </P><P>——reliability (symbian) 注意如果函数名由一个C结尾那就表明这个函数最后返回的是个指向已放入清除栈的对象的指针。 </P><P>head files
——convention
  在头文件中,要使用标准的anti-nesting 语句,这个也是一般c++的行规。
  #ifdef _CMYCLASS_
  #define _CMYCLASS_ </P><P>  body of header </P><P>  #endif </P><P>  注意,要使用很清楚的访问控制权限,首先列出public成员,然后是protected成员.然后是private成员。在成员函数之后列出数据成员。在每个section中都先列出特殊的成员函数(如NewL/NewLC/constructors/destructors/operators)。把函数按功能分类组织。把所有的overridden函数都放在一起。还要把出处标记起来(如 //from CMyBase Class)并且不要在这里写上virtual关键字。如
//from CCoeControl
void Draw() const; </P><P>//from MObserver
void Notify();
void StopObserving(); </P><P>——convention (Nokia) 要使用#ifndef当要包含某个头文件在头文件中时。 </P><P>#include
——convention
  首先是系统头文件(用&lt;&gt;来指明)然后跟着的是本地头文件(用"") </P><P>inheritance
——maintainability (c++)
  不要使用多重继承除非是为了interface(i.e mixiin classes).Interfaces不能包括成员变量。也不要什么纯虚函数。 </P><P>——maintainability (c++)
  Never use private or protected inheritance.Consider whether composition would
be more appopriate. </P><P>local variables
——maintainability (c++)
  局部变量最好在使用他们的地方的附近定义最好。靠后点:) </P><P>——maintainability (c++)
  不要使用静态局部变量。 </P><P>M classes
  (symbian) note M类对象cannot be passed or returned by value. The choice between pointer and reference should be made according to whether a NULL value is acceptable. </P><P>macros
——reliability (c++)
  避免宏,使用enums和const static来代替#defining常量。内联函数能代替大多数使用宏的场合。注意#ifdef DEBUG是允许的就象ASSERT这个宏一样。
</P>
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-11-26 11:05 , Processed in 0.099643 second(s), 16 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表