惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Vulnerabilities – Threatpost
有赞技术团队
有赞技术团队
小众软件
小众软件
O
OpenAI News
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News and Events Feed by Topic
MongoDB | Blog
MongoDB | Blog
阮一峰的网络日志
阮一峰的网络日志
Hacker News: Ask HN
Hacker News: Ask HN
D
Docker
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
A
About on SuperTechFans
Stack Overflow Blog
Stack Overflow Blog
C
CERT Recently Published Vulnerability Notes
L
LINUX DO - 最新话题
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
Hacker News - Newest:
Hacker News - Newest: "LLM"
G
Google Developers Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Hackread – Cybersecurity News, Data Breaches, AI and More
G
GRAHAM CLULEY
S
Schneier on Security
T
Tor Project blog
Spread Privacy
Spread Privacy
PCI Perspectives
PCI Perspectives
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
F
Fortinet All Blogs
L
Lohrmann on Cybersecurity
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
The Exploit Database - CXSecurity.com
TaoSecurity Blog
TaoSecurity Blog
Apple Machine Learning Research
Apple Machine Learning Research
T
Threat Research - Cisco Blogs
T
Troy Hunt's Blog
罗磊的独立博客

博客园 - Tom Song

招聘net 开发 RAR 协议- 探针协议 Linq To Sql 项目从Beta迁移到RTM注意事项 杀人游戏系列 之三 提供游戏代码下载 Linq To Sql进阶系列 -目录导航 C# 3.0入门系列-目录导航 杀人游戏系列 之一 谈Linq To Sql的优劣--纯个人观点 Linq To Sql进阶系列(七)动态查询续及CLR与SQL在某些细节上的差别 Linq To Sql进阶系列(六)用object的动态查询与保存log篇 数据库中使用 Synonym和openquery SQL 语句中特殊字符的处理及预防sql 注射 Linq To Sql进阶系列(五)Store Procedure篇 C# 3.0与Linq To Sql的学习方法--浅谈 C#3.0入门系列(十二)-Lambda表达式中Lifting Linq To Sql进阶系列(四)User Define Function篇 Linq To Sql进阶系列(三)CUD和Log C#3.0入门系列(十一)-之In, Like操作 Linq To Sql进阶系列(二)M:M关系
杀人游戏系列 之二
Tom Song · 2007-10-15 · via 博客园 - Tom Song

在第一篇中,我们已经引出了话题。在经过初步的分析之后,整个team的思路很明确。从业务逻辑入手,兵分两路,一路向ui开进,一路向database开进。而关键的部分就是中间实体类的设计。

1,模型的重构
在第一篇中,我们已经确定了基本的模型。但是,这个模型准确嘛?无论是平民,还是杀手,以及警察,他们只是游戏中的一个角色。而这个角色真实的身份,应该是用户。这样,先把用户类抽提出来。如下。大家需要注意的是,这里的类图,我是拿OR designer画的。先暂且不管每个property是什么类型的。这个类包含一个user最基本的信息。userid是用来标志他的唯一编号。其中isonline来存储这个用户的状态。winnum和playnum分别是他赢的次数和玩的次数。

在有了user类后,下一个没有争议的类就该是game了。它的定义如下

gameno是每个游戏的唯一标志。这其中还定义了开始时间,结束时间。当然,还定义了谁最终赢得了game,以及平民,杀手,警察的数量。这两个实体,是本程序中,最基本的实体。也能准确体现现实世界中对象。那么,针对一个user,只有把他放在特定的game中,他才能算是一个玩家。如果,他不加入到game中,那他就不算玩家,而只能算是一个user。有的user是平民,有的杀手,而又有的是警察。那又该如何体现user在game中的角色呢?思路有这么两个,第一,从user继承,分别写平民,杀手等类。第二,单独创建一个player类。针对第一个思路,在创建对象的时候,需要new出不同的类,而且在判断user的身份时,需要调用反射,看是什么类的对象才知道。更麻烦的是,如何把它向数据库方向推呢?这个思路写出的代码很容易懂,却也有它的弱点。不知道它弱点的人,就无法使用好它。第二个思路比较简单,切实可行。player类的定义如下。

这个类里,定义了userid和gameno,这样,就很容易和game和user做关联。isactive用来保存这个player是否还活着。roleid则是其身份的标志。deadactivityno是他在那次活动中死去(先不说这个)。这里,roleid作为一个property来判断玩家的身份,避免了不同的类需要反射的问题。更重要的是,这样的设计很容易推向数据库。那roleid 的值实际上被限定在某个集合内。这个集合被定义为枚举类型。如下:

    public enum RoleFlag : int
    
{
        Civilian 
= 1,
        Killer 
= 2,
        Police 
= 4
    }

这里为1,2,4是方便后来的位运算。并没有其他的特殊设置。 这样,最基本的模型确定了。紧跟着需要做的,就是设计各个class中的property一系列的属性了。如图

这是gameno的属性设置。这里它被设成主键。还有,它在clr中的type为int,在server端的data type 为int not null identity。也就是int的自增型。在这里,其他的都好设置,唯独Server Data Type需要设计者对数据库和dbml格式特别熟悉。这也是为什么笔者一直带着大家熟悉dbml。把各个类中的字段的属性设置后,下一步就是建立关系了。
这个模型也很容易懂。一个user在不同时间可以加入不同的game,一个game可以拥有多个user。那这样,正好用player这个实体类将他们联系起来。就是一个user在不同时间,可以扮演不同角色,一个game可以拥有多个角色。那针对player中的roleid这个字段,它只有三个值,又该如何在数据库中体现它呢?大家都知道,数据库中,对于枚举型的,也只有把它们存在一个特殊的表里。然后,把这个表用相关的字段和另一个表的相关字段建里关系就可以了。这样,又从RoleFlag抽像出一个叫Role实体类来。用如下的功能建立关系,右击game类,选择add->Association,

这里把各个实体的关系建立起来。选择合适的字段。需要注意的是,别把parent和child搞反了。这样,整个模型如下:

2 业务逻辑中的对象抽提
单纯从client和server角度讲,它们是通过消息通信的。在本项目中ui 端的所有的对象,包括平民和杀手,他们之间所有的动作,比如,杀人,发言和投票,其实也都是通过消息机制发回server端。如果从这个角度来考虑的话,无论是杀人,投票和发言,均可以理解为一个消息。只是这个消息有三种罢了。这样,就有

Activity实体类定义了这个消息体。又定义了枚举

    public enum ActivityTypeFlag : int
    
{
        Vote 
= 1,
        Kill 
= 2,
        Investigate 
= 4
    }

Activity实体类定义如下

Activity实际是定义的一个消息体。在这里,team发生了争执。boler主张在每个Activity中,可以允许一轮投票可以无法确定结果,不得不重投。Activity可以理解为某一次活动,比如一轮发言,一轮投票,等。按boler的主张,当某次投票决定谁死时,有可能会出现得票相同的结果,然后,不得不重投,然后用RoundCount保存是一共有几次重复。最终,boler在会议上说服了大家。这样,又从Activity,引申出Vote实体类。Activity 和Vote是1 :n的关系。而在一个game中,可以有多次Activity。这样game和Activity的关系为1 :n.  Vote类的定义如下

在这里,RoundNo是第几次。也就是一轮活动中,vote动作有几次重复。Voter是投票人,而Candidate是投给谁。这样,又可以通过这两个键与user类发生关系。综合以上的分析,整个模型为

3 业务层与对象的分离
在通常的思路中,每一个动作,都是由对象发出的。比如,杀人,投票。而在这里,team经过讨论,把业务逻辑彻底的从对象中剥离出来。将业务逻辑做成一个个的静态的方法。这样,对象只是业务逻辑的参与者,而不是发出者。这样,可以把所有的业务逻辑放在一起。这样,有利于检查业务逻辑是否有出错。boler已经完成了业务逻辑流程图。如下:

4 结语。在完成实体类的设计后,Tom发现上海的城市沙滩是今年最后一天营业。他匆匆完成设计,径自去沙滩享受他的假期去了。而这只是实体类。大家都知道,和数据库相关的项目,数据库的配制和部署,依然是很麻烦的事情。那么Tom又该如何完成下面的工作呢?他又为什么这么放心的走呢?peter的工作进展怎么样了呢?请看下篇。

上一篇
杀人游戏系列 之三 提供游戏代码下载
杀人游戏系列 之二
杀人游戏系列 之一

其他:
Linq To Sql进阶系列 -目录导航
C# 3.0入门系列-目录导航