【建站服务】永兴微信公众号开发【永兴网络推广】永兴建站、永兴网站维护、永兴网页制作、永兴微信小程序代运营公司-域名申请
作者: 风兰 . 阅读量: 6 . 发表时间:2022-09-20 13:23:19
上往建站提供服务器空间服务商,百度快照排名,网站托管,百度推广运营,致力于设计外包服务与源代码定制开发,360推广,搜狗推广,增加网站的能见度及访问量提升网络营销的效果,主营:网站公司,百度推广公司电话,官网搭建服务,网站服务企业排名,服务器空间,英文域名等业务,专业团队服务,效果好。
永兴微信公众号开发【永兴网络推广】永兴建站、永兴网站维护、永兴网页制作、永兴微信小程序代运营公司
永兴县是郴州市下辖县,地处湖南省东南部、郴州市北陲,东邻资兴市,南连苏仙区,西靠桂阳县,北接安仁县及衡阳市耒阳,辖10镇4乡2街道办事处,总人口71.1万人(常住54.4万人),是郴州市人口第二大县,国家“城市矿产”示范基地。 [1]
地域狭长貌似蚕形,东西长90公里,南北宽56公里。全县土地总面积为1979.4平方公里,占湖南省土地总面积的0.93%,东部多山,西部以丘陵为主,中部丘岗平原间布,京广铁路、京珠高速公路、国道G107、省道S212纵横境内,耒水上游的便江四季通航。
2020年7月,全国爱卫会决定命名永兴县为2017-2019周期国家卫生县城。
很多框架关心性能,而不关心人文;很多项目关心技术,而不关注业务。
就这造成了复杂的领域业务在项目中得不到很好地体现和描述,也没有统一的规则,更没有释意的接口。最终导致了在“纯面向对象”框架里面凌乱的代码编写,为后期的维护扩展、升级优化带来很大的阻碍。这就变成了,框架只关注性能,项目只关心技术,而项目却可怜地失去了演进的权利,慢慢地步履维艰,最终陷入牵一发而动全身的困境。
很多人都不知道该如何真正应对和处理领域的业务 ,尽管领域业务和单元测试都是如此重要并被广泛推崇。正如同表面上我们都知道单元测试却没有具体真实地接触过,并且一旦到真正需要编写一行单元测试的代码时就更迷惑了。
在一个项目架构里面,有三个主要模型:设计模型、领域模型和代码模型。设计模型在选择PhalApi时已大体确定,领域模式则需要项目干系人员消化、理解并表达出来。对于开发人员,代码模型则是他们表达的媒介。 所以Domain这一层,主要关注的是领域业务规则的处理。让我们暂且抛开外界客户端接口调用的签名验证、参数获取、安全性等问题,也不考虑数据从何而来、存放于何处,而是着重关注对领域业务数据的处理。
曾经我在进行一个接口项目开发时,与iOS资深开发同学@Aevit有过一段有趣的编程体验。当时我们正在为F项目共同开发第三方联登的接口服务。由于Aevit是首次接触PHP开发,也是首次接触PhalApi开发,他在参考我编写的微信登录后,很快就交付了微博和QQ登录这两个接口服务。
但令我为之惊讶和兴奋的不是他的速度,而是他所编写的代码是如此的优雅美丽,犹如出自资深PHP开发人员之手。这让我再一次相信,使用在TDD下讲述故事的方式来开发接口服务,专注于领域业务规则,不仅能让代码更易于传送业务逻辑,也能为更多的同学乃至新手接受并更高效率地产出高质量的代码。
下面,我们将走进Domain领域业务层的内部,深入探索其中的奥秘,为讲真实、动听、丰满的故事做好准备。
释意接口
领域的逻辑是对现实业务场景的再解释。现实的因素充满变数并且由人为指定,所以不能简单的在计算机中“推导”出领域逻辑。在项目开发过程中,要特别对这些领域逻辑理解透彻,以便后面接手的同学可以更容易理解和明白这些流程、限制和规则。其中一个有力的指导就是释意接口。
对接口签名甚至是对变量命名的仔细推敲都是很有益处的,因为名字能正名份,不至于混淆或者含糊不清。释意接口的作用和成效很大,它可以让后来维护项目的同学在端详一个接口时,无须深入内部实现即可明白它的用意和产生的影响。如一个getter系列的操作,我们可以推断出它是无副作用的。但如果当时的开发者不遵守约定,在里面作了一些“手脚”,则会导致产生“望文生义”的推断。
简单来说,释意接口会将“命令-查询”分离、会将多个操作分解成更小粒度的操作而保持同一层面的处理。根据《领域驱动设计》一书的说法:
“类型名、方法名和参数名一起构成了一个释意接口(Intention-Revealing Interface),以解释设计意图,避免开发人员需要考虑内部如何实现,或者猜测。”
在我曾经任职的一个游戏公司里面,我常根据接口的命名来推断它的作用,但往往会倍受伤害。因为以前的开发人员没有遵守这些约定,当时的Team Leader还责怪我不能太相信这些接口的命名。然而我想,如果连自己团队的其他成员都不能相信,我们还能相信谁呢?我们是否应该反思,是否应该考虑遵守约定编程所带来的好处?任何一个问题,都不是个人的问题,而是一个团队的问题。如果我们经常不断地发生一生项目的问题而要去指责某个人时,我们又为何不从一开始就遵守约定而去避免呢?
如下面在F项目中的家庭组成员领域业务类:
<?phpclass Domain_Group_Member {
public function joinGroup($userId, $groupId) {
//TODO
}
public function hasJoined($userId, $groupId) {
//TODO
}}复制代码我们可以知道,Domain_Group_Member::joinGroup()用于加入家庭组,会产生副作用,是一个命令操作;Domain_Group_Member::hasJoined()则用于检测用户是否已加入家庭组,无副作用,则是一个查询操作。
业务规则的描述
“规则出现且仅出现一次。”
领域之所以复杂,在于规则众多。如果不能很好地把控这些规则,当规则发生变化时,就会出现很大的问题。在开发过程中,要注意对规则进行提炼并且放置在一个指定的位置。如对游戏玩家的经验计算等级时,这样一个规则就要统一好。不要到处都有类型相同的计算接口。当代码出现重复时,我们都知道会面临维护的高成本。而当规则多次出现时,我们更知道当规则发生变化时所带来的各种严重的问题,这也正是为什么总有一些这样那样的BUG的原因。系统出现问题,大多数上都是业务的问题。而业务的问题在于我们不能把规则收敛起来,汇集于一处。
在以往的开发中,我都很注意对业务规则统一提取、归纳,并在必要时进行重构。这使得我可以非常相信我所提供业务的稳定性,以及在给别人讲解时的信心。例如有一次,在一个大型的系统中,需要对某个页面跳转链接的生成规则进行调整。我跟另一位新来的同事说,这个需求只需修改一处时,他仍然很惊讶地问我:“怎么可能?!”因为他看到是这么多场景,如此多的页面,怕会有所遗漏。然而,事实证明,最终确实只需要改动一处就可以了。
类似这样的URL拼接规则,我们可以这样表示:
<?phpclass Domain_Page_Helper {
public static function createUrl($userId) {
return DI()->config->get('app.web.host') . '/u/' . $userId;
}}复制代码规则出现且仅出现一次,可以说是一个知易行难的做法,因为我们总会有不经意间重复实现规则。有时会忽略已有的规则,有时会出于当前紧张的开发进度而暂且容忍,有时可能多了几步就懒得去统一。但把规则的实现统一起来再重复调用,而非重生实现,会让你在今后的项目开发中长期收益。没错,真的会长期收益。
而这些业务规则,都应该封装Domain领域业务层,并统一进行维护管理。
代码保持在同一高度
领域层关注的是流程、规则,所以当你进行用户个性化分流和排序时,不应该把底层网络接口请求的细节也放到这里流程里面。把底层技术实现的细节和业务规则的处理分开是很有好处的,这样便于更清晰领域逻辑的表达,也助于单元测试时的测试桩模拟。
不可变值
通常,我们在程序中处理的变量可以分为:值和实体。简单来说,值是一些基本的类型,如整数、布尔值、字符串;实体则是类对象,有自己内部的状态。当一个实体表示一个值的概念时(如坐标、金额、日期等),我们可以称之为值对象。明显地,系统的复杂性不在于对值的处理,而在于对一系列实体以及与其关联的另一系列实体间的处理。
如同其他语言一样,如果也在PHP遵循不可变值与无状态这两个用法,我们的接口系统乃至业务方都可以从中获益。
不可变值是指一个实体在创建后,其内部的状态是不可变更的,这样就能在系统内放心地流通使用,而无须担心有副作用。
举个简单的例子,在我们国际交易系统中有一个金额为100 RMB的对象,表示用户此次转账的金额。如果此对象是不可变值,那么我们在系统内,无论是计算手费、日记纪录,还是转账事务或其他,我们都能信任此对象放心使用,不用担心哪里作了篡改而导致一个隐藏的致使BUG。
也就说,当你需要修改此类对象时,你需要复制一个再改之。有人会担心new所带来的内存消耗,但实际上,new一个只有一些属性的对象消耗很少很少。
要明白为什么在修改前需要再创建新的对象,也是很容易理解的。首先,我们保持了和基本类型一致的处理方式;其次,我们保持了概念的一致性,如坐标A(1, 2)和坐标B(1, 3)是两个不同的坐标。当坐标A发生改变,坐标A就不再是原来的坐标A,而是一个新的坐标。从哲学角度上看,这是两个不同的概念。
在PhalApi中,我们可以看到不可变值在Query对象中的应用:
$query1 = new PhalApi_ModelQuery();$query1->id = 1;$query2 = new PhalApi_ModelQuery($query1->toArray());$query2->id = 2;复制代码
这样以后,我们就不再需要小心翼翼维护“漂洋过海”的值对象了,而是可以轻松地逐层传递,这有点像网络协议的逐层组装。
这又让我想起了《领域驱动设计》一书中较为中肯的说法:
把值对象看成是不可变的。不要给它任何标识,这样可以避免实体的维护工作,降低设计的复杂性。
无状态操作
PHP的运行机制,不同于长时间运行的语言或系统,PHP很少会在不同的php-fpm进程之间共享实体,最多也只是在同一次请求里共享。
这样,当我们在一次请求中需要处理两个或两个以上的用户实体时,可以怎么应对呢?
关于对实体的追踪和识别,可以使用ORM进行实体与关系数据库映射,但PhalApi弱化了这种映射,取而代之的是更明朗的处理方式,即:无状态操作。
因为PhalApi都是通过“空洞”的实体来获得数据,即实体无内部属性,对数据库的处理采用了表数据入口模式 。当我们需要获取两个用户的信息时,可以这样:
$model = new Model_User();$user1 = $model->get(1); //$user1是一个数组$user2 = $model->get(2);// 而不是$user1 = new Model_User(1); //$user1是一个对象$user2 = new Model_User(2);// 或者可以这样批量获取$users = $model->multiGet(array(1, 2)); //$users是一个二维数组,下标是用户的ID复制代码
这样做,没有绝对的对错,可以根据你的项目应用场景作出调整。但我觉得无状态在PhalApi应用,可以更简单便捷地处理各种数据以及规则的统一,以实现操作的无状态。因为:
+ 1、可以按需取得不同的字段,多个获取时可以使用批量获取 + 2、在单次请求处理中,简化对实体的追踪和维护 + 3、换种方式来获得不可变值性的好处,因为既然没有内部状态,就没有改变了
Domain层作为Api-Domain-Model分层模式中的桥梁,主要负责处理业务规则。将值对象与无状态操作引申到Domain层,同样有处于简化我们对数据和业务规则的处理。
我们可以根据上述的家庭组成员领域类来完成类似下面功能场景的业务需求:
$domain = new Domain_Group_Member();if (!$domain->hasJoined(1, 100)) {
$domain->joinGroup(1, 100);}if (!$domain->hasJoined(2, 100)) {
$domain->joinGroup(2, 100);}if (!$domain->hasJoined(3, 100)) {
$domain->joinGroup(3, 100);}复制代码即:如果用户1还没加入过组100,那么就允许他加入。用户2、用户3也以此类推。
当我们在领域业务层把业务规则划分为更细的维度时,就能更轻松上组装不同的业务功能,满足不同的业务场景,讲述不同的故事。
故事,因为真实,所以生动。
对于前面的示例,对于商品快照信息的获取,假设不能返回价格为0或负数的商品信息。则可以添加对价格有效性判断的业务规则处理:
// $ vim ./Shop/Domain/Goods.php<?phpclass Domain_Goods {
public function snapshot($goodsId) {
$model = new Model_Goods();
$info = $model->getSnapshot($goodsId);
if (empty($info) || $info['goods_price'] <= 0) {
return array();
}
return $info;
}}复制代码休息一下,接下来,继续探讨Model数据

永兴微信公众号开发【永兴网络推广】永兴建站、永兴网站维护、永兴网页制作、永兴微信小程序代运营公司
上往建站提供搭建网站,域名注册,官网备案服务,网店详情页设计,企业网店,专业网络店铺管理运营全托管公司咨询电话,服务器空间,微信公众号托管,网页美工排版,致力于域名申请,竞价托管,软文推广,全网营销,提供标准级专业技术保障,了却后顾之忧,主营:虚拟主机,网站推广,百度竞价托管,网站建设,上网建站推广服务,网络公司有哪些等业务,专业团队服务,效果好。
服务热线:400-111-6878 手机微信同号:18118153152(各城市商务人员可上门服务)
关键词:网站建设,企业网站,网站制作,网页设计,高端网站建设,企业网站制作,网页制作,制作网站,网站设计,高端网页设计,高端网站设计,做网站,自适应网站


