首页 » 我的课程 » php » 正文

老代码的传人如果”死”了(1):适配器模式、技术原则、黑暗料理

   有句话是描述什么是真的死了:

   1、第一层死亡:你的身体在医学上判断为死亡

   2、第二层死亡:葬礼上你的亲朋好友都来了。代表你在社会上的地位死了

   3、第三层:最后记得你的人死了,那这时:你就真的死了

   那么老代码也是这样。

   很多公司都有老代码,有的甚至是六脉单传,或者有的根本已经失传,一旦出了问题大家第一个想到的不是怎么修复BUG,而是通过外围想办法来掩盖BUG.

   我之前看到过一个案例:某程序运行了一段时间后必然会内存不够,吃光。然而该团队告诉我,这个代码是万年老代码,是单传的,至今没人敢动。最关键的是最后的传人前段时间和公司发生纠纷,离职了。(真的”死”了)。

   于是,最后解决问题的方法只有一个:加硬件配置来掩盖系统本身的问题(其实系统的并发200都不到)。据说加了好几次了,反正是客户出钱。实在不行上小型机嘛~~~

   我们来看下其中一种老代码(使用PHP演示,其他语言区别也不大)

 

interface UserService { function login($name,$pass); }  class TeacherService implements UserService  {      function login($name,$pass) //教师登录的业务逻辑      {      }  }  class StudentService implements UserService  {      function login($name,$pass)//用户登录的业务逻辑      {      }  }

这是很普遍的代码

1、设计时 有个接口,代表用户相关

2、教师和学生 都继承,因为他们都有一个方法及叫做login (登录).这没毛病

3 、当时的业务就是需要传入用户名和密码(必须,且老师和学生都一样)。  那么在接口中写死,目前也没啥毛病

 

后来,由于为了安全,客户要求在教师登录的时候 还需要传入授权码。(因为后来发现,某些学生用老师的账号登录进去胡作非为了)。

于是:接口会被这样改 (第一种)


interface UserService {    function login($name,$pass,$code); //注意这里,加上了授权码$code,为了客户要求 。接下来下面所有继承的类都要手工改一下参数

}  class TeacherService implements UserService  {      function login($name,$pass,$code){} //教师登录的业务逻辑,某猿会写上注释 :有了授权码,必须传  }  class StudentService implements UserService  {      function login($name,$pass,$code){}  //某猿会写上注释,学生调用时$code不用传,或者传任意字符串,反正没用  }

当然,这是第二种版本


interface UserService {   function login($name,$pass); function loginForTeacher($name,$pass,$code); }  class TeacherService implements UserService  {      function login($name,$pass){} //教师登录的业务逻辑,这个方法作废了。别调,调了也没用    

function loginForTeacher($name, $pass, $code){}  //这是新的教师登录代码,因为SB客户要求加授权码  }  class StudentService implements UserService  {      function login($name,$pass){}  //学生登录      function loginForTeacher($name, $pass, $code){} //空代码,没用.劳资就写在这了,咋样?       }

以上代码都是 “让我们的代码”最终成为越来越“复杂”的老代码。 因为客户的需求经常会变的。

也许有一天,客户告诉我们: 授权码不要了。还是用原来的 用户名和密码登录就可以了。

那么,你咋办? 之前的方法可能你还得启用。

所以有的时候不能怪程序员,客户实在太变态。

于是一个叫做适配器模式的代码就很用了 。  实际上也没啥神秘的,就是接口继承,套一层适配类,技术本身就是两害取其轻的一个过程。 要么增加代码量,要么增加维护难度。你自己看着办

1、如果你碰到的是一个善变的用户,或者你的需求真的是经常反反复复。那么代码使用设计模式是需要的

2、如果你的需求只会改一次,而且客户板上钉钉告诉你不用改了。那么没必要写这么多设计模式代码。

 

interface TeacherService2017  //代表2017年用户提出了 这个SB需求 .万一 2018年又来了一个,那就得再写一个。这样可以来回切换  

{      function login($name,$pass); }  class TeacherService2017Adapter implements TeacherService2017  //这是真正的关键代码 ,当然你不高兴继承interface也可以。你喜欢就好。PHP不是java。

 {      private   $ts;      private $code;      function __construct(TeacherService $teacherService,$code)//看参数,这里放入了 授权码参数      {          $this->ts=$teacherService;          $this->code=$code;      }      function login($name, $pass)      {         //这里执行 有授权码 的 代码 ,自由发挥吧          echo "适配后的教师登录";      }  }

调用方式

$teacherService=new TeacherService(); $teacherService=new TeacherService2017Adapter($teacherService,"fuck"); //这句话注释掉,一切回归原来的状态 $teacherService->login("shenyi","123");


这里的特征如下:

1、原来的代码不用改。万一客户说,恢复原来的方式,那么我们只要把第二句

  “$teacherService=new TeacherService2017Adapter($teacherService,”fuck”);”  这句话给注释掉就可以了。

2、代码量增加了 一些。但是“根据两害取轻”的原则,如果你碰到反复无常的客户。是值得的。

最后来一句黑暗料理:

   代码开发大家可能碰到过很多原则:什么单一职责原则、开闭原则等等。  其实总结下来就是“两害取其轻”。你要明白你到底需要什么,以及在你“程序生涯的有生之年”,你这么写是否真的值得。

  设计模式很好、很有逼格。但是不一定适用任何场景。 我们写的系统也不一定真的能传承万年(也许你一离职,就被你的下一任给说成屎,然后废掉)。

  就像前端开发,很多人讨论要不要用redux,得看你的项目情况。如果你的项目就是去取新闻,然后展示一下,分分页。那要这玩意儿有何用? 反过来,如果你的项目很复杂,那么你不用这类玩意儿那就是“六脉单传老代码的鼻祖了”

发表评论