找回密码
 会员注册
查看: 14|回复: 0

先切入、再深入,从领域到架构的演变

[复制链接]

6

主题

0

回帖

19

积分

新手上路

积分
19
发表于 2024-9-30 16:18:47 | 显示全部楼层 |阅读模式
说在前面的话讲领域切入设计这个话题,是因为之前我记得有个读者问过我2个问题:我们是 xxx 的,但是现在老大感觉后台比较复杂,耦合性高,硬代码太多,想让我们重构,但是我感觉不知道怎么做?根本无从下手。老大每天让我们做提效,讲究设计,还要根据业务进行设计,但是我只知道一些基础的设计模式,感觉没什么好做的,也不知道要做成什么样,太煎熬。哈哈,这边先打个马虎眼,先不忙回答这个问题,先讲讲我身上的一个案例,最后再来回答这个问题。切入领域案例领域我在前端写了7年左右的业务从简单到复杂,然后再到简单,尤其在饿了么,贡献给营销3年的时光,和产品一起设计过,和研发一起重构过,和实际使用者线下调研沟通过,对营销这块有自己的一个摸索的想法,现在写下来供做营销相关的同学一起参考。领域营销。什么是营销?营销大家平常接触的就是卖东西,能联想到就是电商、活动等,但是这个只是一个浅显的大众认知,如果我们要去做一个好的设计,就必须去深入了解它,然后熟悉它,最后运用它。以下是一些专业定义概念的平台对营销的定义。营销的定义百度百科:指企业发现或发掘准消费者需求,让消费者了解该产品进而购买该产品的过程。美国市场营销协会(AMA):营销是创造、沟通与传递价值给顾客,以及经营顾客关系以便让组织与其利益相关人(stakeholder)受益的一种组织功能与程序。通过概念我们知道营销的定义,我们了解了营销是什么,但是营销的目的呢?营销的目的通俗点讲就是:客户获得让利,企业获得利润。专业一点就是:在一种利益之上下,通过相互交换和承诺,建立、维持、巩固与消费者及其他参与者的关系,实现各方的目的。当然现代社会下,对营销的细分,乃至衍生都细化到了很深的程度,也有专业的人去做,所以我们就不深入去说概念,我们将核心点放到,摸索营销业务下的软件设计,如何结合业务进行代码软件设计。常用做法普通开发模式我们一般接到业务的做法是,我们的现状有什么?需要设计什么样的数据模型?需要做什么样的逻辑?对以前的代码结构等等存在是否有影响?我不否认的一点是,对于基础架构设计完毕之后,这样的做法确实没有什么问题,而且有时候需求需要快速上线或者刚接触项目不久,不是很懂,这样做也最符合常规,毕竟不会出问题才是最完美的。“不将就”模式但是作为一个自己以后可能需要长期维护、迭代下去的项目,如果不懂前人的设计,不停地堆代码下去,迟早一天会成为一个 "巨石" 应用,最后苦的还是自己(跑路就当我没说…)。所以该怎么设计呢?一般框架,只解决通用的一类事,类似于设计模式一样,可以用这些设计模式解决一些通用方案,但是针对一个业务领域的设计,一般人都不知道怎么去下手,下面以我对营销的理解直接进入主题。领域思考一句话总结何时、何地、谁、怎样条件、获得什么、使用感受。深入分析何时:限制时间;何地:限制地点或者渠道;谁:限制什么样的人群;怎样的条件:需要达到什么样的门槛;获得什么:客户享受什么样的权益;使用感受:营销的反馈;第一层抽象属性、规则、反馈这3个大概念上的模块,都是没有强耦合的,都可以单独设计,但是这3个太抽象,比如:营销属性具体指什么,什么样的才能界定他是属性?营销规则,具体指什么,一个规则算不算活动的属性?以及营销感受跟前面更没有太搭界的地方,这属于后勤或者售后的工作?就像有3个抽象类一样,什么都没有,就是定义了一个方向,最终实现,还是需要进行考虑和细化的。所以我们还要更细化的抽象。所以根据我们上面的详细分析:虽然时间、地点、人群都是营销的属性,天然存在的,但是我们还要抽离出共性,这些属性不都是做的一些限制么?营销作为一个交换和承诺,当然也有一定的契约,这样的契约下,我们需要达到一定的门槛,才能获得契约约定的结果,从而获得到权益。有了限制,以及公示门槛和权益,完成营销的链路,但是这个营销到底怎么样,需要什么样的评估和反馈呢?亏本还是挣钱?大火还是寥寥无人?怎样反向优化营销。第二层抽象限制、门槛、权益、反馈我们可以借助实际场景进行考虑,举例饿了么百亿补贴活动,自己作为用户是怎么消费这个营销活动的:首先从一个渠道看到了有营销活动(活动预告),新闻呀,进入饿了么app看到的。其次开始看这个营销活动在20年8月27日起,饿了么app里,在124个城市,可与红包和满减叠加,指定商户可以享受。(限制 - 时间、地点、场景、人群) 。需要达到商户的满减门槛。(门槛 - 达到满减门槛)。可以享受百亿补贴的减免金额。(权益 - 得到百亿补贴的减免)。感觉享受到优惠了,给个好评。(反馈 - 营销怎么样)。其实这里的限制和门槛有点类似,至于是否可以合并每个人都有不同的想法,而我将他么分割的想法是这样的:首先营销活动本身的属性,其实都是为了解释营销的的一些具体描述,而这些描述虽然最终都会转化成营销活动的限制,但是最好是单一,可描述,不可拆分的。其次门槛,是从规则中衍生出来的,属于规则类的限制抽象,而规则将是后期超级复杂的一块,将门槛归纳到限制中在我的设计想法中,没必要强糅合,所以我将它单独拆离出来。归根结底,我们是通过第一层抽象继续细分下来的,所以第二层抽象,就是为了将属性和规则界定的更明显和清晰。切入设计我们将营销这块领域进行了深入了解,然后将这块领域以程序的思维进行抽象,那么我们这样就可以进行敲代码了么?当然不!!我们需要了解最核心的理念,我们为什么要将这块领域设计成这样?设计理念是什么?设计初衷复杂领域简单化。设计理念模块化、原子化。营销是一块大领域,基于营销的及时性以及灵活性,我们需要我们的系统设计能够承载更多的变化、更快的响应速度、更加灵活的灵活性。所以,我用一把 “锤子” 直接把这块领域敲碎,只有碎成一块一块的,我们才能更灵活的去组装展现不同的面。具体示例我们切入领域进行了深度思考,从简单看到复杂,然后再从复杂思考到简单,下面做我们的代码设计(使用 node,大家参考设计思路就好了)。示例下载github - demo:具体示例,可点击下载代码结构目录:池子我们已经把领域打碎了,一颗一颗的都是小颗粒原子, 所以我们需要一个池子去盛放我们筛离出来的原子。所以我们需要设计一个池子里的各个数据模型。限制抽象池:pond/limit.jsletlimit={//时间time:null,//地点address:null,//人群people:null,//渠道channel:null}classLimit{//新增限制addLimit(key){limit[key]=null}//删除限制delLimit(key){deletelimit[key]}//设置限制的一项值setLimitValue(key,value){limit[key]=value}getLimit(){let_output={}for(letkeyinlimit){if(limit[key]!==null)_output[key]=limit[key];}return_output}}module.exports=Limit;门槛抽象池:pond/rule.jsletrule={//消费金额consumption:null,//订单数量orderNumber:null}classRule{//新增限制addRule(key){rule[key]=null}//删除限制delRule(key){deleterule[key]}//设置限制的一项值setRuleValue(key,value){rule[key]=value}getRule(){let_output={}for(letkeyinrule){if(rule[key]!==null)_output[key]=rule[key];}return_output}}module.exports=Rule;权益抽象池:pond/benefit.jsletbenefit={//减免金额money:null}classBenefit{//新增限制addBenefit(key){benefit[key]=null}//删除限制delBenefit(key){deletebenefit[key]}//设置限制的一项值setBenefitValue(key,value){benefit[key]=value}getBenefit(){let_output={}for(letkeyinbenefit){if(benefit[key]!==null)_output[key]=benefit[key];}return_output}}module.exports=Benefit;反馈抽象池:pond/feedback.js//定义数据模型//letfeedback={////反馈类型//type:null,////反馈消息//message:null//}//缓存数据letfeedbackArr=[]classFeedback{//设置限制的一项值setFeedback(options){feedbackArr.push({typeptions.type,messageptions.message})}getFeedback(){console.log('>>>',feedbackArr)returnfeedbackArr;}}module.exports=Feedback;这4个池子,将每个抽象进行了归类形象化,且每个类中对细节进行了原子管控,可以对抽象中的细节进行增删改查,这样就打碎了复杂的块,每个都是最小的一块,后面我们就可以将这些小块进行组装了。组装组装工厂 :factory/index.js/***组装更灵活可操作的活动*-该类依赖上游打散的数据集合*-该类将上游数据进行组合出新的活动类型**/constLimit=require('../pond/limit')constRule=require('../pond/rule')constBenefit=require('../pond/benefit')constFeedback=require('../pond/feedback')let_activity=[];classActivity{constructor(){this._limit=newLimit();this._rule=newRule();this._benefit=newBenefit();this._feedback=newFeedback();this._cache={limit:{},rule:{},benefit:{},feedback:[]}}getLimit(){returnthis._limit;}setLimit(obj){this._cache.limit=obj;}getRule(){returnthis._rule}setRule(obj){this._cache.rule=obj;}getBenefit(){returnthis._benefit}setBenefit(obj){this._cache.benefit=obj;}getFeedback(){returnthis._feedback}setFeedback(key,obj){_activity[key].feedback=_activity[key].feedback.concat(obj);}generate(){let_temp=Object.assign({},this._cache);_activity.push(_temp);this._cache={};return{id:_activity.length-1,data:_temp};}getActivityList(){return_activity;}}module.exports=Activity;组装工厂的代码,就是将所有的原子池子导入,然后绑定每个抽象池的原子,最终以一类的方式输出,然后对输出进行糅合,最终输出一个灵活配置的营销活动。最后当然是供上下游进行依赖或者消费。组装工厂的意义就是类似于搭积木一样,每个小块自己可以随意灵活取用,可以拼凑出自己想要的任何模型,这样存在的意义就是,对于规则复杂高、形式高灵活场景,可以完全有把控力,下面我们来测试一下,对于复杂高,高灵活场景的一些case。测试case1 - 2011-11-11、所有人、满60减30(简单)调试代码//运行于调试constActivity=require('../factory/index')//case1:2011-11-11 所有人满60-30活动let_case1=newActivity();//设置限制_case1.getLimit().setLimitValue('time','2011-11-11');_case1.getLimit().setLimitValue('people','all');_case1.setLimit(_case1.getLimit().getLimit())//设置门槛_case1.getRule().setRuleValue('consumption',60);_case1.setRule(_case1.getRule().getRule())//设置权益_case1.getBenefit().setBenefitValue('money',30);_case1.setBenefit(_case1.getBenefit().getBenefit())//生成活动let_res=_case1.generate();//模拟反馈_case1.getFeedback().setFeedback({type:'message',message:'哇塞,活动真优惠!'})_case1.setFeedback(_res.id,_case1.getFeedback().getFeedback());console.log(_case1.getActivityList());result[{"limit":{"time":"2011:11:11","people":"all"},"ruleL":{"consumption":60},"benefit":{"money":30},"feedback":[{"type":"message","message":"哇塞,活动真优惠!"}]}]这是个简单的case,做了一些简单的活动场景配置,最常见的满减活动,当然针对满减还有更杂的,比如多梯度、补贴力度比等,这个可以更深入去看,下面看复杂的场景配置。case2 - B站「919」活动(复杂模拟)限制:2021-09-19、哔哩哔哩APP、安卓、注册用户、会员购渠道、主会场、手办类。规则:总订单满1W、前100名、60s内付款、下单金额满1000。权益:减免200、赠券500-100券。调试代码//运行于调试constActivity=require('../factory/index')//case2let_case2=newActivity();//设置限制_case2.getLimit().setLimitValue('time','2021-09-19');_case2.getLimit().setLimitValue('address','哔哩哔哩APP');_case2.getLimit().setLimitValue('people','已注册用户');_case2.getLimit().setLimitValue('channel','会员购');_case2.getLimit().addLimit('platform');_case2.getLimit().setLimitValue('platform','安卓');_case2.getLimit().addLimit('scene');_case2.getLimit().setLimitValue('scene','主会场');_case2.getLimit().addLimit('category');_case2.getLimit().setLimitValue('category','手办');_case2.setLimit(_case2.getLimit().getLimit())//设置门槛_case2.getRule().setRuleValue('orderNumber','10000');_case2.getRule().addRule('sort');_case2.getRule().setRuleValue('sort','100');_case2.getRule().addRule('payTime');_case2.getRule().setRuleValue('payTime','60');_case2.getRule().setRuleValue('consumption','1000');_case2.setRule(_case2.getRule().getRule())//设置权益_case2.getBenefit().setBenefitValue('money',200);_case2.getBenefit().addBenefit('coupons');_case2.getBenefit().setBenefitValue('coupons','满500-100券');_case2.setBenefit(_case2.getBenefit().getBenefit())//生成活动let_res=_case2.generate();//模拟反馈_case2.getFeedback().setFeedback({type:'message',message:'哇塞,抢到了,不过有点难抢哦!'})_case2.setFeedback(_res.id,_case2.getFeedback().getFeedback());console.log(_case2.getActivityList());console.log(JSON.stringify(_case2.getActivityList()));结果[{"limit":{"time":"2021-09-19","address":"哔哩哔哩APP","people":"已注册用户","channel":"会员购","platform":"安卓","scene":"主会场","category":"手办"},"rule":{"consumption":"1010000","sort":"100","payTime":"60"},"benefit":{"money":200,"coupons":"满500-100券"},"feedback":[{"type":"message","message":"哇塞,抢到了,不过有点难抢哦!"}]}]这个营销场景就相对比较复杂,限制条件比较多,规则门槛和权益都不单一,但是在这样的场景下,我们依然可以通过只需要改上层应用层代码,就能呈现出复杂场景,而不需要修改底层设计,也自然而然的能够支撑更复杂的业务场景。当然,这上面的示例代码使用的是前端的node开发的,但是对于后端(深耕营销领域的)来说,也可以参考设计思维和方式,将抽象的想法和模型落实到后端的数据库表结构设计、将组装代码用后端语言进行组装(Java、go等),最终提供出灵活的营销底层设计方案。对于产品职责的,将设计思路归纳到产品规划中,针对营销进行整个逻辑全盘控制,限制、门槛、权益、反馈形成整体流程的闭环,从产品的设计上线、用户使用、反推搜集、正向推进产品改进,每个节点进行深入,更专业,也能从中找到突破点,打造更爆款、更双赢的营销。问题解答所以,最后我们回到上面的问题,来进行回答:问题一我们是 xxx 的,但是现在老大感觉后台比较复杂,耦合性高,硬代码太多,每次开发都鼓捣很久,还会出现很多千奇百怪的bug,想让我们重构,但是我感觉不知道怎么做?根本无从下手。解答首先深入领域,抛开代码,明确自己是做什么的,然后对这一块领域进行理解、梳理、归纳,达到懂和透彻的感觉(毕竟重构也不是一开始就推动下去的,也需要做很多前期调研等)。在懂和透彻的感觉基础上,再结合现阶段项目运行中存在的一些问题进行一些发散的思考,这些问题引起的具体乃至根本原因是什么?因为这些问题最终暴露在你的项目中,从这些不足中去反推项目中存在的问题(比如哪些灵活性、可维护性、耦合度等等各方各面)。基于 了解领域 + 深度思考,最终将所有的结论进行归纳总结,先抛开个方面的因素,我们如果要从头去做这个项目,基于领域的特性和思考的目标,如何去做这个设计,进行深度探讨,做抽象设计等等了解代码,迭代里很久的代码,虽然打了很多补丁,有时候运行起来又很繁琐,但是确实是在设计运行中,发现了很多不足,不管是code阶段还是代码设计,乃至产品设计方案中,这些补丁将这些问题进行了修复,so,好好善待这些补丁,毕竟是上一个系统的经验,可以在新方案中吸收进去。脑爆 + 雏形,这个阶段对于搜集的第一手经验已经很丰富,可以开始将各种抽象和开放脑洞的想法进行归类和糅合,形成自己初级阶段的雏形。这里的雏形是最重要的,因为这是方向和骨架,只有确定,后面才能将这些东西进行丰富,形成自己的架构和项目。借人,如果有空,可以将你的方案拉个会议进行探讨,借助更多人的脑袋进行思考和优化一遍,因为每个人的经验和想法都不一样,都会带给自己往更好的方向去雕刻这个雏形。最初阶段的雕刻和修改是最容易的,因为不会引发太多的「蝴蝶效应」,但是在上层完全搭建完毕后,这样的结果是不可接受的,因为你会拿更多的补丁去覆盖你上次的补丁,这样对架构的破坏是更永久和致命的。有了明确的方向和设计,下面就可以将你的想法和架构进行丰满,这个阶段,有想法、有设计、有方向、有架构,行动起来就感觉像一气呵成,恨不得今天就搭建完毕。后面就是正常的软件生命周期的流程了,测试验证,细节修改等,就不详细说了。问题二老大每天让我们做提效,讲究设计,还要根据业务进行设计,但是我只知道一些基础的设计模式,感觉没什么好做的,也不知道要做成什么样,太煎熬。解答首先明确一个问题,什么是设计?在我的理解里,设计是为了规范行为、统一行动、高效理解、有迹可循。特别在大公司里,大家都会争夺核心业务,只有手上握着更多业务更多资源,对于自己的组或者老大就有更多资源(HC、年终奖等)和话语权。基于这样的核心目标下,设计的优势就完美体现,不言而喻了。逼叨叨一句,其实小公司也一样,只是偏向的目标不一致:快、更快上线,抢占更多市场。第二点为什么要设计,要做成什么样?其实设计并没有想象的那么高大上,不是说我要把我们整个项目都推翻重做,从头再来。想法是好的,但是一般不可能给那么多时间和资源去给你搞的。设计也可以是很小的,在代码上,比如这段代码在xx场景下太消耗性能,导致整体速度下降,你优化掉,这也是设计;在业务上,这样的场景,其实可以在上一套的能力中衍生,并不要单独开辟一套,优化节省资源和后期维护,这也是设计;在协作上,每次都要造数据(每个项目,每个人),能不能搞一套简单的自动mock数据能力,这样对于长久的时间线上的回报,是付出的无限倍收获,这也是个设计。总结总结一下吧,这是领域切入设计的第一篇,主题思想就是:切入领域、深入领域。只有知道自己在做什么,完全把控住,我们才能自然而然的想到怎么将这些玩意更快、更好的去把他做完。毕竟好的设计,不仅仅局限于代码和软件工程,更多的是对业务形态和领域的深入了解,再结合工程和代码设计,才是最符合当前业务的「 起飞方式 」。这篇博客,从有想法到构思,然后思索案例,最终示例想法,乃至最后的文字校验和美化,前前后后大概鼓捣了快1年时间,希望能给大家带来不一样的启发和想法。当然在现实中,我们并没有这么富余的时间和资源,那我们要怎么搞呢?基于最初业务方案设计,满足最初业务需求。基于增长业务方案重构,满足增长业务需求。基于稳定业务架构演变,满足同类业务需求。未来的变化和需求,谁都不能明确,最初的设计架构,只是针对最初可控,或在一定规则下可控演变的方针。业务,这个最重要的核心。在业务增长和业务变化的规则下,只能不停去重构方案和设计,在调整中,为整体架构开枝散叶,丰富内在。最后,当领域稳定下来,针对于特定领域的抽象和通用解决方案的总结,最后演变成架构。后记其实切入领域,类似于DDD想法的一种自己摸索实践,后面第二篇博客,会将自己摸索出的一些方法论进行分享出来,感谢观看,如有想法,可以一起交流,一起努力,一起成长!:gerry.zhong@outlook.com点击上方关注 · 我们下期再见
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-14 20:46 , Processed in 0.806100 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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