张逸说

出口成张,逸派胡言

0%

最近一段时间,电商圈出了一件大事情,拼多多再次吸引了大家的眼球。2019年1月20日,拼多多出现了数额巨大的羊毛Bug,起因在于一张无门槛的优惠券,券面价值100元,可以全场通用(特殊商品除外),有效期一年。如果仅仅从业务角度分析,定义这样的优惠券自身并没有任何问题。当然,也有人说像这样的无门槛券本身就不该用于花费充值、Q币充值等几乎等于现金业务的商品,这是从促销层面去考虑的问题。还有人提到风控问题,为何等到损失达200亿(事后拼多多说明这些优惠券涉及到千万)才发现问题?更有人质疑这是一次别出心裁的炒作。

从薅羊毛的角度看这个Bug,似乎是因为该无门槛券可以被无限次使用导致的。本质上,这确实是一个Bug,我不明白这样的Bug是如何产生的,是测试不到位,还是说该优惠券本身是一个内部测试数据,被不小心放到生产环境?正好,最近正在考虑如何利用分析模式建立电商系统中的促销模型,算是应景之作吧。

阅读全文 »

在一个产品长期的研发过程中,必须时刻对代码保持警惕,一旦发现代码有腐烂的迹象,就需要考虑及时重构,剔除代码的坏味道,让代码焕然一新。然而,在进度的逼迫下,我们承受了及时交付功能的压力,团队成员对糟糕代码的敏感度又不够高,在这二者的夹击之下,稍有疏忽,整个代码库就有可能变得积重难返。

多数时候,我们疲于应对各种需求。一方面,我们发布的版本正在支撑着客户的生产应用;另一方面,我们还需要不断地开发新功能,以满足客户不断提出的新需求或者需求变更。同时,我们对产品有着雄心勃勃的计划,希望它能够在不断的演化下变得更加强大。我们清醒地感知到,若任由代码如此发展下去,代码腐烂的结果会进而导致架构的腐烂。就像一架正在执行飞行任务的航空器,明知到缺少足够的燃料,需要返回基地加油,却又不得不继续飞行,否则无法按时到达目的地。这时,我们就需要针对代码库进行“空中加油”。

理想的方式是对现有的代码库进行小步重构,然而众多阻力让我们没有信心驾驭重构。这些阻力包括:

  • 随着功能的增加,代码库开始变得庞大
  • 代码的腐烂情况较为严重,需要在结构上做重大调整
  • 团队成员欠缺对大型代码库的重构能力
  • 单元测试与集成测试的测试覆盖率太低
  • 重构与新功能开发同时进行,破坏原有功能的风险太大

显然,想要通过重构实现空中加油,谈何容易!但为了避免未来架构的腐化,对现有代码库进行手术又势在必行。因此,基于当前代码库现状、产品需求与团队成员能力,我确定了“重构+重写”的改造策略,美其名曰“空中加油”。

阅读全文 »

2014年,ThoughtWorks的Martin Fowler与James Lewis对一种新的架构风格——微服务(微服务这个术语最早诞生2011年在威尼斯召开的一次软件架构师工作坊)——提供了完整的定义。随着他们的定义,微服务这种架构风格迅速地成为软件行业的热词,并被许多互联网公司采纳,陆续开始迈入微服务的演进过程。如今微服务已经进入所谓的Service Mesh 2.0时代,诸多微服务框架、平台以及设计原则如雨后春笋般出现。在微服务走入成熟的时刻,再来重读Martin Fowler对微服务的定义,或许会另有一番收获。

微服务的完整定义来自Martin Fowler的文章《MicroServices》。作者是James Lewis与Martin Fowler,他们对微服务的定义如下所示:

根据这个定义,我们可以勾勒出微服务的基本构成要素:

  • 每个服务运行在自己的进程中;
  • 微服务之间采用轻量级通信;
  • 微服务应基于业务能力进行构建;
  • 采用自动化部署机制实现微服务的独立部署;
  • 服务的管理应采用最小的中心化管理。
阅读全文 »

不管是因为规模与结构制造的理解力障碍,还是因为变化带来的预测能力问题,最终的决定因素还是因为需求。Eric Evans认为“很多应用程序最主要的复杂性并不在技术上,而是来自领域本身、用户的活动或业务”。因而,领域驱动设计关注的焦点在于领域和领域逻辑,因为软件系统的本质其实是给客户(用户)提供具有业务价值的领域功能。

阅读全文 »

需求

针对某通信产品,我们需要开发一个版本升级管理系统。该系统需要通过由Java开发的管理后台,由Telnet发起向前端基站设备的命令,以获取基站设备的版本信息,并在后台比较与当前最新版本的差异,以确定执行什么样的命令对基站设备的软件文件进行操作。基站设备分为两种:

  • 主控板(Master Board)
  • 受控板(Slave Board)

基站设备允许执行的命令包括transfer、active、inactive等。这些命令不仅受到设备类型的限制,还要受制于该设备究竟运行在什么样的终端。类型分为:

  • Shell
  • UShell

对命令的约束条件大体如下表所示(不代表真实需求):

通过登录可以连接到主控板的Shell终端,此时,若执行enterUshell命令则进入UShell终端,执行enterSlaveBoard则进入受控板的Shell终端。在受控板同样可以执行enterUshell进入它的UShell终端。系统还提供了对应的退出操作。整个操作引起的变迁如下图所示:

执行升级的流程是在让基站设备处于失效状态下,获取基站设备的软件版本信息,然后在后端基于最新版本进行比较。得到版本之间的差异后,通过transfer命令传输新文件,put命令更新文件,deleteFiles命令删除多余的文件。成功更新后,再激活基站设备。因此,一个典型的升级流程如下所示:
0. login (Master Board Shell)

  1. inactive (Master Board UShell)
  2. get (Slave Board Shell)
  3. transfer(Master Board Shell)
  4. put(Slave Board Shell)
  5. deleteFiles(Slave Board Ushell)
  6. active(Master Board UShell)
  7. logout

整个版本升级系统要求:无论当前基站设备属于哪种分类,处于哪种终端,只要Telnet连接没有中断,在要求升级执行的命令必须执行成功。如果当前所处的设备与终端不满足要求,系统就需要迁移到正确的状态,以确保命令的执行成功。

阅读全文 »