配色: 字号:
腾讯大讲堂05-面向对象应对之道
2020-02-28 | 阅:  转:  |  分享 
  
面向对象开发课程开发:penghao2008-04-01课程目的描述面向对象编程的一般性的手法,原则和技巧工欲善其事,必先利
其器。课程大纲引言面向对象的表达方法面向对象的五个原则面向对象的几个设计模式我们面对的是什么?这种情况下的应对之道
规模大且服务不断的情况下对应的非功能性需求就会要求比较多.变化多且持续变化的情况下要求程序具有良好的结构。本文档所关注的核心
。程序,服务具有良好结构有两个层面的考虑大粒度的结构设计。关注的层面比较宏观。这一块的知识参考《面向模式的体系结构》卷一。
本文档不关注。细粒度结构设计-本文档关注的核心什么代码写得好?什么叫坏的代码?有标准吗?坏代码举例僵化:很难对系统进行改
动,因为每个改动都会迫使许多对系统其他部分的改动。脆弱:对系统的改动会导致系统综合改动的地方在概念上无关的许多地方出现问题。牢
固:很难解开系统的纠结,使之成为一些可重用的组件。粘滞:做正确的事情比做错误的事情要困难。不必要的复杂:设计中包含不具有任何直
接好处的基础结构。不必要的重复:晦涩:很难阅读,理解。(引用于《敏捷软件开发:原则,模式与实践》强烈推荐该书。)好代码的
近似标准介绍OO(或者说语言)的核心思想OO的五大技术原则(标准)从OO看合理的分层架构OO(或者说语言)的核心思想—表达
领域概念语言的语法都是比较简单的。不过同样的语法写出来的代码却有好坏高低之分。重要的区别就在于表达领域概念的水平重要的原则
就是:“程序(代码)应该反映人的思想,而不是相反。”Martinfowler.(《分析模式》)如何来表达一个mmog-静态
视图?针对某个领域对象粗分操作,行为,职责。通过对领域概念应用OO原则,分析模式,设计模式等等手段对对象职责进行抽象,细分职责
。形成最终静态对象图。通过对用例画时序图,确认对象职责是否可行,恰当。实际mmogAI表达的例子表达概念的几种类型释意
接口。表达实体对象表达约束表达流程(服务)表达规格隐含机制表达“在初学面向对象时对它们并不熟悉。每学会一个这样的表
达的类型,我的设计水平就又进了一步”“Mydesignsbecamesharperwitheachoneofth
eseIleaned.”EricEvans《领域驱动设计》强烈推荐该书释意接口的例子intCPlayer::St
andUp(intiSessionID){ intiOpenNum=0; iOpenNum=m_Sess
ions.GetLastIdx(); //下面两个判断判断违法情况。 if(iSessionID<0) { }
elseif(iSessionID>iOpenNum) { }}推荐写法如下:RoomSessio
n提取成一个对象(类),提供CheckRoomIDValid接口。intCPlayer::StandUp(intiS
essionID){iRet=m_Session.CheckValid(iSessionID);If(iRet){
}}这种是完全达到了隐藏实现,消除了代码重复,又充分表意的目的。特别在此强调释意接口。好的类应该是每个函数都比较短,五,六
十行。然后有二,三十个方法。这个类形成一个接近封闭的类型。具有充分的自我表达能力。实体表达的例子charsNowD
ate[20]={0}; charsLastDate[20]={0}; GetDate(time(NULL),sNowDat
e); GetDate(iReserve[LastGive],sLastDate); if(strcmp(sNowDate,
sLastDate)>0) { } else { }同一个功能的另外一种写法也是实际代码。intCGive
Daily::OnGive(CAttachpPA,intiHE){ DatedToday(time(NULL));
DatedLastDay(pPA->GetGiveHELastTime()); if(dLastDay==dToday
) { } else { }}可以看出抽取出了日期类,用日期类来表达人的思想,而不是只记得使用哪个API来实现
功能。日期这个概念在这个需求里面是比较重要的一个概念。面向对象就表达出了这个概念。约束表达的例子有时候某些约束表达的是领域
逻辑。通常隐式的表达,将他们显示表达出来能够极大地改进设计。比如QQGame里面进入房间限制。实际产品对进房需求的演化第一
个版本:限制一下玩家最低,最高积分。第二个版本超级玩家和网管要优先进房第三个版本如果是出租房间需要是承租方才能进房第四个版本
如果是比赛房间需要是比赛方才能进房第五个版本需要拥有某种道具第六个版本如果是欢乐场房间需要检查欢乐豆上下限制。产品的需求演
化说明进房约束是个热点问题。抽象出约束接口,把约束的增加,约束的实现,变更对进房主流程屏蔽起来。流程(服务)表达的例子基本行
为流程概念的表达,对于产品同事不断提及到的流程概念表达。行为概念流程表达的好处把规格用对象来表达验证。选择(查询)按需创
建隐含概念表达实例在QQGame里面对房间模式的描述结构如下。不同的房间模式,具有不一样的基本行为。我们通过不同的工厂实现来
屏蔽掉这一层变化。不同的房间聚合不同的生成工厂。房间模式是挖掘出来的概念,抽象工厂表达出了这个概念。OO的五项技术原则是什么?
(讨论,提问)OO的五项技术原则单一职责—事情不要太复杂。开闭原则—让易变的容易变化,不变的稳定。依赖倒置—让易变的依赖于
稳定,而不是相反。接口隔离可替代 OCP(Open-ClosedPrinciple):开放-关闭原则 对扩展要
说YES,对修改说NO。 LSP(LiskovSubstitutionPrinciple):LSP原则 父母要对
孩子负责。 SRP(SingleResponsibilityPrinciple):单一职责原则感情要单一,不要
脚踏两支船。 DIP(DependencyInversionPrinciple):关系返转原则 不要一天打10个电话给
我,有结果我会通知你。 ISP(InterfaceSegregationPrinciple):接口隔离原则 让李部长只
负责开发吧,市场就让辛部长做吧学习面向对象中最主要的一点就是,理解面向对象原则。如果你还没有真正理解这些原则,那你做出的设计可能
不是最好的设计,那你学习设计模式也不能真正理解它的真谛。五项技术原则实例-单一职责实际代码例子classCDBCtrl
{public: CDBCtrl(); ~CDBCtrl(); intInitialize(constchars
zCfgFile); intPrepareToRun(); intRun(); voidoperatornew(
size_tnSize); voidoperatordelete(voidpMem); staticint
CountSize(); staticCSharedMempCurrentShm;private: intReadC
fg(constcharszCfgFile); intLoadProxyCfgFromFile(charszProx
yFile,int&iProxyNumber); intLoadGivenRuleFromFile(charszRul
eFile,int&iRuleCount); intLoadForbidRuleFromFile(charszRule
File,int&iRuleCount); intReadPublicCfg(constcharszCfgFile)
; intLoadCreditConfig(constcharszCfgFile); intCheckRunFlag
s(); intConnectToProxys(); intCheckAndDispatchInputMsg(); in
tRoutineCheck(); intDispatchOneCode(shortnCodeLength,BYTEp
byCode); intPostInternalMsgToHandle(intiHandleID,CMsgpMsg);
intNofityDBHandles(CMsgstMsg); TDBCfgm_stDBCfg; CTCPCon
nm_astProxyConn[MAXPROXYNUMBER]; CDBHandlem_apHandles[MAXHAN
DLENUMBER]; intm_iUdpSoket; CASqlExem_apExecers[MAXHANDL
ENUMBER]; CExceptionTabm_stExceptionTable;};classCMainCt
rl{public: CMainCtrl(); virtual~CMainCtrl(); virtualint
Initialize(); virtualintRun(); intReloadCfg(); intCheckR
unFlag();protected:private:};职责表达了负责的变化,有多个维度的职责,就有多个维度的变化五
项技术原则实例-开闭原则QQGame最经典的例子,MainFrame可以不动代码,游戏服务可以源源不断输出新的游戏。觉得这个
是最核心的规则。(下图引用自zengyu《QQGame服务器架构技术》)五项技术原则实例-依赖倒置问题界面控件,比如Butt
on,ListBox,等。它们都是想做成通用的,也就是说和业务逻辑不相关。但是事件响应是通过界面控件传递到逻辑的。问怎么做到界
面控件和业务逻辑隔离?五项技术原则实例-接口隔离实际代码例子:classCmdObserver{public: Cm
dObserver(); virtual~CmdObserver(); virtualintCmdDone(CComma
ndpCmd,intiResult=CmdSucceed);};classMsgObserver{public
: MsgObserver(){} virtual~MsgObserver(){} virtualintOnMsg(C
MsgpMsg)=0;};五项技术原则实例-可替换子类必须能够替换掉它们的基类型。问题:正方形是特殊的长方形
吗?从OO看合理的分层结构用户界面层:负责向用户显示信息,解析用户命令。不一定面对的是人,可能是一条狗。应用层:定义软件可
以完成的工作,指挥具有丰富含义的领域对象来解决问题。这个层要保持简练,不包括业务规则和知识,只是给下一层相互协作的领域对象协调任务
,委托工作。领域层:负责表示业务概念,业务状况以及业务规则。业务软件核心。将领域层分离出来至关重要。基础结构层:为上层提
供通用的技术能力:应用的消息发送,领域持久化,绘制窗口等。业务层根据EvansDDD,可以再细分为应用层和领域层两种,在业务层
设计编码中,大量应用OO设计原则和设计模式。领域层定义:负责表达业务领域概念、业务状态以及业务规则,是整个业务软件核心和重点。
应用层定义:负责完成功能,并且协调丰富的领域对象来实现功能,不能包括业务规则,无业务状态;从开发每个过程看OO方法论的应
用1.需求分析,用户活动图,软件需求规格说明书,领域建模。--OOA2.概要设计/详细设计—OOD分析和设计的边界很难明确
分开。3.编码/测试--OOP4.发布5.从1再循环到4需求分析-OOA第一步,建立用户活动图。不关注实现。仅关注用
户流程,实体。第二步,画实体关系图,着重类概念,类之间关系。第三步,画时序图,对关键活动,用例用时序图来分析职责是否合理。
OOA实例系统需求:考评系统。某XX公司要建立一个考评系统。大体上领导考虑要从德智体等几个方面综合考虑。德包括考勤,同
事意见,领导意见等;智包括技术各项指标,比如操作系统,网络,领域理解等;体包括体育各项指标,比如羽毛球,乒乓球等。从这些方面给一
个人打分。请用OO描述一下这个对象系统.实例一:把各个实体概念及其之间关系表达出来实例二:进行抽象,使概念表达更具灵活性,和可
扩展性。设计-OOD设计模式介绍《深入浅出设计模式》强烈推荐此书。设计模式某个环境下,对某个设计问题的一种解决方式的描述
。设计模式强调把容易变化和不变部分分离。让变化部分容易变化。在日常开发中,找到变化点,积累变化面是重要的。模板方法观察者
抽象工厂桥职责链组合Reactorac设计模式实例—模板方法在一个框架里面,比如MFC,要做本身框架的初始化代码
,又要给不同的业务留下初始化各自业务的空间。同时框架代码是以二进制形式发布的,不能在里面添加代码。怎么办?一个MFC应用程序的W
inMain函数哪里去了?MFC的解决实例模板方法类图结构设计模式实例—观察者一个分层的架构,越下层的结构往往越通用,
下层不能依赖于上层。但是下层又有东西要通知上层。比如网络层不能依赖于领域层,问怎么能做到?观察者实际代码例子classCm
dObserver{public: CmdObserver(); virtual~CmdObserver(); vi
rtualintCmdDone(CCommandpCmd,intiResult=CmdSucceed);};设
计模式实例—抽象工厂OO比较强调创建这个行为。一方面创建有时候本身很复杂;另一方面,程序很多的灵活性需要通过一种合适的创建方式才
能获得。当new一个对象的时候,写new的这个代码的类就产生了对new出对象的依赖。我们当然希望频繁变化的逻辑不要被上层依赖。
那么为了能做到这一点,就需要有合适的创建方式。简单的工厂抽象工厂抽象工厂特征1.抽象工厂强调的是一系列相关的变化聚合在一起
,有几个系列,就有几个具体的工厂。2.切换的时候,打一个开关就可以了。使得变化相当的容易,明显。3.工厂创建的东西互相不干扰。
各干各的活。设计模式实例—桥有一类模块,对外提供抽象接口,实现一个功能。它有两个维度的变化。一个维度是提供的抽象功能,可能在
变化。另一个维度是实现抽象功能的实现方式也会变化。另外一种情况是提供的抽象功能给外部接口,不希望这个接口频繁变化,给外部带来困
扰。问怎么实现这个需求?ACEReactor-实现视图设计模式实例-职责链应用层协议确定分发问题:比如我们要分析网络
上各种应用层协议内容。包括smtp,http,pop3,ftp等等。应用层协议是会增加的。现在问题是一个网络连接,我们无法知道它走
的是什么协议。一个简单的端口是无法准确判断的。问怎么做这个问题的设计方案。职责链好处如下各个协议分开,各干各的活不会
互相干扰。做到高内聚,低耦合。新协议的增加是很简单的,甚至可以做到动态增加。可以做到开闭原则。设计模式实例-组合模式请
用OO描述QQGame的目录树结构。请在这个描述结构上计算目录树各层人数。设计模式实例—Reactor做许多网络服务器/客户
端的时候,基本上每一个都会用到select或类似功能函数。多线程/多进程模式除外。当select检测到某个fd有数据的时候,我
们再去读取数据。基本上这部分代码和我们的业务逻辑代码混合在一起。在一个网络服务器里面,基本都需要定时器的操作。这些每一个网络服
务器都需要的东西,能否提取出来?形成一个通用解决框架。设计模式实例—异步命令模式高效的网络服务器/客户端经常遇到异步操作问题。异步响应回来的时候,如何知道异步请求时候的状态是什么一直是个问题。这个操作超时,完成,失败和业务逻辑的隔离也存在问题。ACT异步回调TOKEN的概念。异步命令模式框图时序图谢谢Q&A观察者标准类图classCCommand{public: CCommand(); virtual~CCommand();virtualintRegisterObserver(CmdObserverpObserver); virtualintNotifyObserver(intiResult=CmdSucceed);private: CSetm_ObserverSet;};这个实例中,命令是属于基础设施层的东西,但是要通知上层业务逻辑,自己的状态变迁。所以使用观察者。经典的解决办法(参考QQGame大厅设计以及《敏捷软件开发》)2-5
献花(0)
+1
(本文系新用户18771...首藏)