请选择 进入手机版 | 继续访问电脑版

NoahFrame

 找回密码
 Register Now
搜索
热搜: redis mysql tutorial
查看: 2808|回复: 0

第七章 NF分布式服务器解决方案--面向接口&数据开发方法

[复制链接]

30

主题

112

帖子

668

积分

Administrator

Rank: 9Rank: 9Rank: 9

积分
668
发表于 2016-12-30 10:22:15 | 显示全部楼层 |阅读模式
NF(https://github.com/ketoo/NoahGameFrame)全称为 NoahFrame/NoahGameFrame。


NF最早为客户端设计,后来随着时代的变化,而为自己又转为服务器开发,故在吸收了众多引擎的优点后(包含Ogre的插件模式&模块化管理机制,Bigworld的数据管理&配置机制,类似MYGUI的接口层次设计),经过多年演化和实践,变成了一套游戏开发J解决方案。方案中包含开源的服务器架构,网络库(站在libevent的肩膀上),和unity3d的demo源码。现在NF已经在多个公司的多个项目中使用,其中包含知名产品 《全民无双》。


关键词


NoahGameFrame/NoahFrame/NF
集群/负载均衡/分布式
网关服务器 GateServer 心跳 多线程/线程池 开源网络框架/模型
一致性hash算法/ConsistentHash
游戏开发中的设计模式/数据结构
Socket Nagle/粘包/开源游戏服务器/ Game Server





可能有同学觉得,从头到尾,我们都在吹嘘面向数据开发,那么,何为面向数据开发?
关于这一新概念,我想了很久,那么就从最原始的面向过程,面向对象,面向接口来然后进化到面向数据来说吧。

话说很就很久以前,鸿蒙世界刚开始有文明的时候,大家码代码是怎么码的呢? 看下面:
  1. push esi
  2. mov esi,ecx
  3. mov eax,dword ptr ds:[esi]
  4. mov ecx,dword ptr ds:[eax+0x4]
  5. call XXOO
复制代码




认真一看,简直就是非正常人类语言,码农们觉得这样写太琐碎了效率太低了且其他人看不懂不小心就蓝屏啊蓝屏,于是部分聪明的码农折腾出了C,并提出了(Procedure Oriented)的概念。意思就是,写代码,就应该以过程为中心,面条一样执行就好了。因为面向过程编程将程序分成了"数据"和"处理函数"两部分,程序以"处理函数"为核心,如果要执行什么操作,就将"数据"传给相应的"处理函数",返回我们需要的结果(其实NF的Module处理机制也是类似,这样无需记录状态的机制,维护成本降低不小)。比如说要用程序语言描述人起床,吃饭,上班这个事情:

面向过程是这样的:

  1. 起床(人);
  2. 吃饭(人);
  3. 上班(人);

  4. ========>

  5. void WakeUp(User* p)
  6. {
  7.     // todo
  8. }
  9. void BreakFast(User* p)
  10. {
  11.     // todo
  12. }

  13. void Working(User* p)
  14. {
  15.     // todo
  16. }

  17. 使用场景:

  18. User* p = new User();
  19. WakeUp(p);
  20. BreakFast(p);
  21. Working(p);
复制代码




初看起来很美好,可是当有大量的这样的行为的时候,怎么归纳,分类,管理代码呢。。。因为。。起床的是人啊,吃饭的也是人,工作的也是人,除了这3样,人还要做很多事情,泡吧啊蹦极啊登山啊泡妞啊,我吃饭想拉个小伙伴一起啊,虽然我在工作,但是我也准备跳槽了再找工作等等等等。


面向过程只能分析出这样的步骤,这样一个过程一个过程来做,后期内容多了对于状态的维护,执行期间复杂的逻辑,维护性大大降低。于是聪明的程序员们捣鼓出了面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息(又或说调用接口函数)。


于是上面的起床,吃饭,工作的代码变成了如下:


  1. class User
  2. {
  3. public:
  4.     void WakeUp()
  5.     {
  6.         //
  7.     }
  8.     void BreakFast()
  9.     {
  10.         //
  11.     }

  12.     void Working()
  13.     {
  14.         //
  15.     }
  16. };

  17. 使用场景:

  18. User u;
  19. u.WakeUp();
  20. u.BreakFast();
  21. u.Working();

复制代码

是不是很干净?而这个只是最基本的面向对象,其实我们知道,当封装了细节,抽象了接口后,面向对象的效果会更好,而且还有编程各种模式的支持,相比面向过程编程,面向对象再编程效率几何级上升以及维护成本是几何级下降。

他们的执行概念图大概是这样的:

OOPs-Vs-Procedural-Programming.jpg

可是,面向对象固然也有他的缺点:

1:相比面向过程来说,更难以理解,低水平的程序员开发的代码,耦合可能更高;
2:过度的封装也可能导致难以维护,新成员接受维护难度几何级加大;
3:一些简单的业务,使用面向过程开发反而更快速;

因此很多事情,不是偏左或者偏右就是好,组合取优才是硬道理。

于是在面向对象的基础上,就又有了面向接口编程(PO->OO->IO)。

面向接口从更深层次的反应了业务开发的本质,它轻松的融入了面向对象和面向过程的优点,更深层次的再次封装了对象个层次的综合业务需求为各种对外业务接口,彰显了业务中业务员对于系统的理解程度,从此编程不再是偏向技术,而是更偏向业务分析。它增强了对象与对象之间,模块与模块的之间的低耦合性,是软件系统更容易维护、扩展。

这里我说的面向接口编程,并非语言机制上的面向接口“编程”(JAVA/C#的interface,C++的抽象类),我是在说“面向接口”编程,而不是面向接口“编程”。
在面向接口编程的概念中,一切业务均接口。接口抽象出业务员分析的需求(业务分析),内部可以让程序员用各种面向对象机制来实现(抽象继承多态)。


上面的代码,现在写一下,可能又类似回归了一些:
  1. class User
  2. {
  3. public:

  4. int nState;

  5. };


  6. class IHumanBehaviour
  7. {
  8. public:
  9. virtual void WakeUp(User* p) = 0;

  10. virtual void BreakFast(User* p) = 0;

  11. virtual void Working(User* p) = 0;

  12. virtual void DailyActivities(User* p) = 0;
  13. };
复制代码

上面的代码,简化一下就是:
  1. User* pUser = new User();
  2. IHumanBehaviour* pHumanBehaviour = new CHumanBehaviour();
  3. pHumanBehaviour .DailyActivities(pUser);
复制代码




在面向接口编程中,使用者只要能够关心业务接口而非对象本身(好像有点回归面向过程了?),它更利于业务接口的抽象。从某种抽象粒度上来说,它比面向对象更灵活,可粗可细;在各种设计模式的应用中,它可以更好更快的去实现;在重构代码的过程中,利用分层接口可以轻松封装各种复杂恶心的各种子业务和子系统;各种测试驱动开发模式各种插件开发架构。。。等等等等,好处多多。


那但是,为什么我后面还要提出面向数据编程,这个是个什么鬼?
回想我们一路面向XX的过程,肯定能抓到重点了,面向数据编程的重点当然就是:数据。


不管是面向过程,对象,接口,最终到来的都是操作数据,产生数据,影响数据,依赖数据。对象的各种行为结果,最终也是以数据的方式存储在这个世界上,那么我们合不再来一个更高层次的抽象,直接从数据结果方向来抽象业务呢?Designer关心的是行为产生的结果数据,而不是业务的细节!因此编程变成了业务结果导向而非业务分析导向(并非业务分析不重要,请参考PO-OO-IO过程)。

比如古时习武,或是为了击杀对象;现在我告诉你又一个方法,可以直接起作用,那是什么呢? 死亡笔记! 我只要轻松写上你的名字就可以了, 这个比喻就类似传统开发和面向数据开发。甚至有同学有对破解软件有了解的话,第一个学习课程应该就是学习如何jump验证逻辑,直接跳转到运行验证成功结果逻辑,这个称为暴力破解,也类似面向数据开发,它是一种以业务结果为导向的开发方法,而非传统的业务过程啰嗦,它简单粗暴,可以让业务需求提出者直接设计业务结果需求而不是原始需求!


而在面向数据编程中,如何有效的管理数据利用数据,成为进入此领域的第一道门槛, 我大体总结了几个要素,欢迎其他人补充:


1:数据的管理,无需因为增加类似数据而另外实现业务模块
2:数据的定义应符合人类直观逻辑需求(跨业务部门合作,并非针对程序员)
3:数据应有统一且唯一的身份标志
4:数据应有统一的访问/设置/加载等接口
5:是否有数据驱动模型架构
6:是否有对业务分析过程提供抽象对象的支持


当有了这些基础支持,之前面向接口编程中,我们的业务员上升一个抽象层次,把数据结构抽象出来即可,他们关心业务逻辑正确与否体现在关心数据是否被正确操作,数据的上下文值是否正确,而非业务接口如何如何;而测试人员则可以直接通过观察数据的变化流程而直接判断业务执行是否正确,这比传统的开发方法(当然也包括TDD等)开发效率更高,业务实现更精准(好吧,直接参考NF引擎吧)。


之前的代码,我们甚至可以进一步的抽象去掉User类,增加NFIObject来代替User,并增加GUID来代替各种接口中的参数,抽象通用的数据管理类等方法(其实就是根据上面的6条原则进行修改)。

具体实现方法,请各位看官就参考NF引擎,这里就不实现了,因为并非简单几行代码可以描述清楚。



NF项目为开源的分布式服务器解决方案,其中包含了网络库,actor库,以及数据驱动等新技术,能大幅提升开发效率节省开发周期以及提高程序的稳定性。
项目地址 https://github.com/ketoo/NoahGameFrame
如感觉对您有帮助,请给与star,同时也邀请广大同行参与开发和维护,作者QQ 342006,交流QQ群 341159815。
欢迎转载,转载请注明来源,本文版权归作者所有!



回复

使用道具 举报

您需要登录后才可以回帖 登录 | Register Now

本版积分规则

 

GMT+8, 2018-12-12 02:25 , Processed in 0.141893 second(s), 30 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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