发表日期: 2021-04-27 08:48:27 浏览次数:211
邳州微信公众号开发【邳州网络推广】邳州建站、邳州网站维护、邳州网页制作、邳州微信小程序代运营公司
邳州,简称“邳”,江苏省徐州市代管县级市, [1-2] 古称良城、邳国、下邳、邳县,位于苏鲁交界,东接新沂市,西连徐州市铜山区、贾汪区,南界睢宁县,北邻山东省兰陵县。 [3] 1992年撤县设市。
邳州历史悠久,境内大墩子文化遗址距今6000年,是江苏文明最早的起源之一。境内有邳州市艾山风景名胜区、沙沟湖水杉公园、国家银杏博览园、小萝卜头纪念馆等旅游景点。邳州的城市精神是“创新、争先、开放、包容”。 [4]
邳州发展的目标是东陇海产业带重要的水陆交通枢纽、新兴工贸城市,京杭运河沿岸具有水乡特色和历史文化底蕴的生态宜居城市。
2019年7月,邳州入选国家知识产权强县工程试点县(区)。2019年,邳州位居全国综合实力百强县市第37位、经济竞争力百强第40位、全国投资潜力百强县市第18位、全国绿色发展百强县市第33位、全国科技创新百强县市第36位、全国新型城镇化质量百强县市第51位。
下面是评论领域业务类的相关代码片段,这些代码展示了在分表的情况下,如何编写代码。
// Family-2.0$ vim ./Apps/Fami/Domain/Feed/Comment.php
/**
* 分表存储 + 刷新评论数量
*/
protected function commonComment($newData) {
$model = new Model_FeedComments();
$id = $model->insert($newData, $newData['feed_id']);
//刷新评论数量
$domain = new Domain_Feed();
$domain->refreshCommentNum($newData['feed_id']);
return intval($id);
}复制代码细心的读者可以发现,在调用insert方法进行添加数据时,会添加第二个参数$newData['feed_id']。此参数表示是动态ID字段,用于进行分表的依据。并且注意到在为动态添加评论内容后,需要刷新动态的评论总数量,以便缓存耗时但每次查询结果都一样的值。
在有一定历史的旧系统中,最为常见的是什么都做的“万能类”。这些类,往往没有明确的职责,而是当有新的功能代码时不加思考,为图方便就直接加在里面,久而久之,就慢慢变成了一个“万能类”。在它里面的方法,大部分都是静态方法,并且在一定程序上有所关联,看起来更像是糅合了多个协作类的全部接口功能。
对于“万能类”,在重写或者平时重构过程中,应该将其进行分解,使之更符合单一职责原则。那么问题是,面对臃肿,成千上万行的代码,我们应该怎么有序地进行分解?在我曾经入职的一家公司,我的上级跟我说过:最终结果和方式、过程,同样重要。下面来看下,使用什么方式,如何分解“万能类”。
先来介绍一个有用的工具,它虽然简单,但非常实用。它的名字叫特征草图,出自某本技术书籍。它的使用过程是这样的:打开需要分解的类,准备笔和草稿纸,以成员属性为矩形,成员函数为椭圆,并用实线的单向箭头表示依赖使用关系,最后便可得到此类的特征草图。下面是一个简单示例类:
<?phpclass Person {
protected $name;
protected $money = 0;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function earn($money) {
$this->money += $money;
}
public function getMoney($money) {
return $this->money;
}}复制代码Person是一个表示人员的类,它有两个成员属性,分别是表示名字的$name和表示所持有的金钱$money。对于名字,有简单的getter方法,而对于金钱,除了简单的getter方法外,还有赚钱的成员函数。根据绘画特征草图的方法,可以得到图6-4。
图6-4 Person类的特征草图
通过手动绘画类的特征草图,不仅操作简单,而且可以清晰地发现成员函数和成员属性在逻辑上的依赖关系。例如在上面的Person类中,可以分解为两个类,一个类只负责人员基本信息,而另一个类则只负责赚钱。
当然,实际中根据历史遗留系统中的“万能类”画出来的特征草图并没有那么简单,但也能从中发现一些端倪。一个经验法则是,通常在特征草图中会存在一个汇点,以此汇点为切入点画一条直线,便可把原来庞大的类一分为二。你发现的汇点越多,最终分解的类就越清晰。那么汇点是什么呢?它往往是某个成员函数,并且是承上启下的一个关键节点,类似两个逻辑世界的通道。如图6-5,灰色的椭圆节点即为汇点,虚线表示可以把上、下两组成员函数和成员属性分解到两个类中。
图6-5 带有汇点的特征草图
那汇点本身这一成员函数应该划分在哪个拆分类里呢?汇点箭头以下的部分,使用抽取子类的重构方法,可以得到一个分解后的类。通常汇点应通过提取子函数的重构方法迁移到分解后的新类中,而在原来的成员函数里,使用委托,调用新的类方法。
如此,通过使用特征草图作为参考依据,结合恰当的重构方法,便可对臃肿的类进行很好的分解,最终得到职责更单一,更内聚的类。
Family 2.0 一个很重要的业务是加入家庭圈。图6-6的交互设计图展示了从创建家庭圈到加入家庭圈这一过程。具体的场景可描述为:用启根据四位数字的家庭号和密码,可加入指定已创建的家庭圈。这一过程因为有着各种规则,蕴含着领域业务,因此在开发实现上是有一定复杂度的。下面,一起来看下如何消化复杂的领域业务。
图6-6 加入家庭圈的操作流程
为了更加了解这其中细致的业务规则,让我们来看下当时为加入家庭圈这一接口服务所写的测试用例。
// Family-2.0$ vim ./Apps/Fami/Tests/Api/Group/Api_Group_Member_Test.php
public function testJoinGroup()
{
DI()->notorm->group_member->where('user_id', 110)->delete();
// Step 1. 构建请求URL
$url = 'app_key=mini&client=ios&version=1.0.0&service=Group_Member.JoinGroup&sign=8c3b4&__debug__=1&UUID=A3D779AF491F86ECFCD22F05CD6A9D1C9F8719CFE4BCEA06B0&group_num=1763&group_pwd=1111';
// Step 2. 执行请求
$rs = PhalApi_Helper_TestRunner::go($url);
// Step 3. 验证
$this->assertNotEmpty($rs);
$this->assertArrayHasKey('code', $rs);
$this->assertArrayHasKey('group_id', $rs);
$this->assertEquals(0, $rs['code']);
$this->assertGreaterThan(0, $rs['group_id']);
// 不能再次加入
$rs = PhalApi_Helper_TestRunner::go($url);
$this->assertEquals(3, $rs['code']);
// 家庭圈密码错误
$url = 'app_key=mini&client=ios&version=1.0.0&service=Group_Member.JoinGroup&sign=8c3b4&__debug__=1&UUID=A3D779AF491F86ECFCD22F05CD6A9D1C9F8719CFE4BCEA06B0&group_num=1763&group_pwd=1112';
$rs = PhalApi_Helper_TestRunner::go($url);
$this->assertEquals(2, $rs['code']);
// 家庭圈不存在
$url = 'app_key=mini&client=ios&version=1.0.0&service=Group_Member.JoinGroup&sign=8c3b4&__debug__=1&UUID=A3D779AF491F86ECFCD22F05CD6A9D1C9F8719CFE4BCEA06B0&group_num=4444&group_pwd=1111';
$rs = PhalApi_Helper_TestRunner::go($url);
$this->assertEquals(1, $rs['code']);
}复制代码上面的测试用例不是特别好的写法,因为它里面同时测试了几个场景。但通过这些测试场景,可以看到,我们验证了一个ID为110的用户,凭家庭圈密码1111加入了家庭号为1763的家庭圈这一Happy Path。此外,验证了不能重复加入同一个家庭圈、以及家庭圈密码错误、家庭圈不存在这些异常的场景。

邳州微信公众号开发【邳州网络推广】邳州建站、邳州网站维护、邳州网页制作、邳州微信小程序代运营公司