发表日期: 2021-04-27 08:51:05 浏览次数:96
邳州网站推广【邳州办理400电话】邳州SEO优化、邳州微信公众号APP客户端小程序开发、邳州网站托管、邳州APP开发
邳州,简称“邳”,江苏省徐州市代管县级市, [1-2] 古称良城、邳国、下邳、邳县,位于苏鲁交界,东接新沂市,西连徐州市铜山区、贾汪区,南界睢宁县,北邻山东省兰陵县。 [3] 1992年撤县设市。
邳州历史悠久,境内大墩子文化遗址距今6000年,是江苏文明最早的起源之一。境内有邳州市艾山风景名胜区、沙沟湖水杉公园、国家银杏博览园、小萝卜头纪念馆等旅游景点。邳州的城市精神是“创新、争先、开放、包容”。 [4]
邳州发展的目标是东陇海产业带重要的水陆交通枢纽、新兴工贸城市,京杭运河沿岸具有水乡特色和历史文化底蕴的生态宜居城市。
2019年7月,邳州入选国家知识产权强县工程试点县(区)。2019年,邳州位居全国综合实力百强县市第37位、经济竞争力百强第40位、全国投资潜力百强县市第18位、全国绿色发展百强县市第33位、全国科技创新百强县市第36位、全国新型城镇化质量百强县市第51位。
有了明确业务规则的单元测试作指引,接下来遵循ADM分层模式,便可进行逐步分解,最后得到井然有序、易于理解、可测试的代码。以下是加入家庭圈Api接口层的实现代码片段。
// Family-2.0$ vim ./Apps/Fami/Api/Group/Member.phpclass Api_Group_Member extends PhalApi_Api {
public function getRules() {
return array(
'joinGroup' => array(
'groupNum' => array('name' => 'group_num', 'require' => true, 'min' => 4),
'groupPwd' => array('name' => 'group_pwd', 'require' => true, 'min' => 4),
'deviceType' => array('name' => 'device_type', 'type' => 'enum', 'range' => array('all', 'cube', 'scale'), 'default' => 'all'),
),
);
}
public function joinGroup() {
$rs = array('code' => Common_Def::CODE_OK, 'group_id' => 0, 'msg' => '');
DI()->userLite->check(true);
//step 1. check
$domain = new Domain_Group();
$groupId = $domain->getGroupIdByGroupNum($this->groupNum);
$rs['group_id'] = $groupId;
if ($groupId <= 0) {
$rs['code'] = 1;
$rs['msg'] = T('group {number} not exists', array('number' => $this->groupNum));
return $rs;
}
//step 2. check pwd
if (!$domain->checkPassword($groupId, $this->groupPwd)) {
$rs['code'] = 2;
$rs['msg'] = T('group passwrod wrong');
return $rs;
}
//step 3. check has joined
$memberDomain = new Domain_Group_Member();
if ($memberDomain->hasJoined($this->userId, $groupId, $this->deviceType)) {
$rs['code'] = 3;
$rs['msg'] = T('has joined the group memeber');
return $rs;
}
//step 4. join
$memberDomain->joinGroup($this->userId, $groupId);
$rs['group_id'] = $groupId;
return $rs;
}复制代码代码虽然有点长,但并不影响它的阅读性以及可理解性。在Api_Group_Member::getRules()成员函数中,配置了接口服务所需要的参数,分别是用户的UUID、四位数的家庭号和四位数的家庭密码、设备类型。接下来,是加入家庭圈的实现代码。在Api_Group_Member::joinGroup()中,最前面通过User扩展类库进行了登录态的检测。然后便是加入家庭圈的业务流程,第一步先检测待加入的家庭号是否合法;第二步校对家庭圈密码;第三步判断是否已加入;最好第四步进行加入操作。可以看到,很明显地,前面三步都是查询操作,而最后一步属于命令式操作,即会产生副作用。这也是符合命令查询职责分离模式原则的。而这些操作,也是在同一个高度的层次,对业务规则进行了很好的表达。至于具体内部的业务实现规则,可以再深入到对应的领域业务类,看下它又是如何表达和实现规则的。
例如,对于负责家庭圈成员的Domain_Group_Member领域业务类。一如我们所期望的,在判断用户是否已加入家庭圈的实现代码中,果然依赖了来自Model层的数据。
// Family-2.0$ vim ./Apps/Fami/Domain/Group/Member.phpclass Domain_Group_Member {
public function hasJoined($userId, $groupId, $detectDeviceType = 'all', $deleteState = Domain_Group_Helper::GROUP_NOT_DELETE) {
$model = new Model_GroupMember();
return $model->hasJoined($userId, $groupId, $detectDeviceType, $deleteState);
}}复制代码这对于项目开发来说,是一件很棒的事情!因为遵循ADM分层模式的代码具有可预测性,不管是哪位开发人员来实现,最后产出的代码都是和我们共同所期待的结构是一致的。这样,则可以大大降低了代码的维护成本。再来看下在Domain_Group_Member领域业务类中加入家庭圈的实现代码, 下面代码是否和你想象的相差无几?
// Family-2.0$ vim ./Apps/Fami/Domain/Group/Member.phpclass Domain_Group_Member {
public function joinGroup($userId, $groupId) {
if ($userId <= 0 || $groupId <= 0) {
return false;
}
$newData = array();
$newData['user_id'] = $userId;
$newData['group_id'] = $groupId;
$model = new Model_GroupMember();
$id = $model->insert($newData);
return $id > 0 ? true : false;
}}复制代码最后,稍微看一下对应Model层的实现代码片段。
// Family-2.0$ vim ./Apps/Fami/Model/GroupMember.php class Model_GroupMember extends PhalApi_Model_NotORM {
protected function getTableName($id = null) {
return 'group_member';
}
public function hasJoined($userId, $groupId, $detectDeviceType = 'all', $deleteState = Domain_Group_Helper::GROUP_NOT_DELETE) {
$num = $this->getORM()
->where('user_id', $userId)
->where('group_id', $groupId)
->count('id');
return $num > 0 ? true : false;
}}复制代码就这样,通过层层分解,我们再一次优雅地消化了复杂的领域业务,以一种可预测、职责划分明确的方式完成了代码的编写,功能的开发。当然,每个接口服务所布面临的领域业务不尽相同,这里只是作为一个示例,希望能给大家提供一些启发性。
完成了既有接口服务的重写任务后,下一步将要进行的是开发新增的接口服务。下面,介绍的是在开发新接口服务过程中所遇到的难题,以及解决的思路和方案。
在Faimly 2.0 项目中,需要新增的功能业务线是母婴营养称。而在母婴营养称中,比较有趣的是用户通过家里的电子称上报的体重数据。这份体重数据是整个业务的数据基础,因此它的重要性很高。在开发与体重数据相关的接口服务时,不仅要考虑到功能性的要求,还要满足非功能性的要求。
图6-7 体重上报与列表设计稿
如图6-7所示,用户可以通过家里的电子称获得体重数据后,经过蓝牙传递给移动App,最后点击“保存数据”即可上传体重数据。然后可以在移动App中查看自己的休重历史记录,并获得相应的营养建议。考虑到这份基础数据有着可预见性的增长,因为用户每时每刻都有可能在测量上传体重数据,所以我们对其进行了分表设计,并分为512张数据库表,为区分与原来系统间的数据库表,新业务所用的数据库表使用前缀“scale_”,表名为:sweight,即分表分别是:scale_sweight_0、scale_sweight_1、scale_sweight_2、scale_sweight_3、……、scale_sweight_511。体重表的基础表字段如下:
