团队协作

几个核心点:
强调PHP语言的基础能力;
熟练掌握PHP的常用函数库;
基础语言能力之外,需要深度理解Unix/Linux操作系统,IO/进程,Socket/TCP/UDP等基础知识。

关于TinyPHP Framework的敏捷开发理念


几个认识

  • 不可只依赖框架:
    • 框架是工程项目开发中的辅助工具和规范约束性团队协作工具,编码者应当加强语言基础的学习,和对PHP手册的精通掌握。
  • 框架只是工具:
    • 喜欢就用,不喜欢就弃。
  • 不可强调某个框架的全天候作业能力:
    • 什么都会的框架意味着什么都做不好,根据需要选择语言工具和语言框架,无需拘泥于某个语言和某个框架。

适用场景

  • 客户端应用(IOS/Android/H5/小程序)的API接口开发:

    • 高性能,大并发。
    • 快速开发
  • Web管理后台:

    • 适用于全栈或不具备设计工程师和前端工程师的研发团队。
    • 集成了tinyphp-ui前端框架,只需少量的JS前端代码。
  • 大规模团队协作:

    • 10-100+人以上的研发团队。
    • 创业团队,产品快速成型,可在较少的研发人力成本下进行高效的敏捷开发。
    • 适用于具备在大规模的高性能应用场景下,通过PHP解决大多数复杂业务的架构。
    • 可将大规模复杂应用的后端语言有效控制为PHP一种后端开发语言,有效降低项目维护成本和团队管理难度。

基于MVC/MVVC的敏捷开发

  • 遵守严格的面向对象编码规范,禁止全局变量穿透对象/高耦合/低内聚等不健康编码方式的滥用。
  • 模型层(Model)
    • 专注于各种业务数据源的处理
    • 模型层次划分清晰;
    • 高度内聚;
    • 面向外部调用的公共接口调用严格遵守确定性的输入输出,以兼容各种运行环境下的数据处理;
  • 视图层(View):
    • 保持轻量级
    • 不加载复杂的模板工具去极大的损耗性能;
    • 在面向客户端应用/API接口编码的情况下,完全省去视图层处理;
    • 推荐JSON数据交互进行接口输出
  • 控制层(Controller):
    • 专注于业务流程和逻辑控制。
    • 保持各种运行环境下的分布式处理和与模型层的低度耦合。

系统设计原则


保持健壮与鲁棒性

少即是多,不做过多封装。 不依赖框架,通过框架的约束和扩展性,处理复杂业务。 多花心思提高性能

防止重复造轮子

每个功能应当只有一个函数/类/接口/实例/命名空间。
成员之间通过协调和沟通,由一人/一个小组负责一个具体模块的所有功能编写。
示例: 按业务模块划分,高度内聚相关模块和功能性接口:

//该命名空间下规划所有用户相关内的子命名空间和类,处理用户所有数据
// application/models/User/
App\Model\User;

// 该命名空间与其他业务的模型交互数据的用户相关数,应规划到命名空间第一层级,统一在该类中开放对外接口,而不是分散在所有的类中
// application/models/UserOrder.php
Class UserOrder 
{
    //根据订单ID获取用户信息
    public function getUserInfoByOrderId($orderId)
    {
         // 调用订单模型获取订单数据
        $orders =  $this->OrdersModel->getOrdersByOrderId($orderId);

    }
}

// 该命名空间处理用户中的后台管理员的所有数据
// application/models/User/Admin/ 
App\Model\User\Admin;

// 处理用户中后台管理员的登录事项
// application/models/User/Admin/Login.php
Class App\Model\User\Admin\Login 
{
    ...
}

一个顶层的命名空间可代表一个业务模块,通过子命名空间和类组合处理分支模块。

抽象原则

通过抽象减少重复代码。
重点功能由负责该模块的主程负责编写,并为其他团队成员提供通用的扩展接口,其他成员继承或扩展,在该模块满足不了实际需求时,应推动负责该模块的主程扩展和优化,无需自己重复写一套。

// 该命名空间处理用户中的后台管理员的所有数据
// application/models/User/Admin/ 
App\Model\User\Admin;

// 处理用户中后台管理员的登录事项
// application/models/User/Admin/Login.php
// author: tom
Class Login 
{
    ...
}

//提供通用接口,扩展其他登录方式
// author:tom
Interface ILogin 
{
    ...
}

// 快捷登录实现,应继承Login类的基础上,调用其实现方式,满足通用接口ILogin, 实现登录的数据交互和持久化
// author: tony
class QucikLogin extend Login implement ILogin 
{
    ...
}

保持简洁优雅

简单是编程的目标。

简单的代码花费时间少,漏洞少,性能高,易于修改。

简单代码需要实现过程清晰一目了然,命名规范,不做过多的封装和分层,更能体现程序员自身的功底。

编码时不需绕来绕去,为了靠近某些流行的前言概念和设计模式,进行各种抽象分层,这种代码看似优雅和专业,其实严重损耗性能,增加他人阅读理解和维护的困难。

流行的东西,总是流行地快,去地也快。

唯有能通过适当少量代码解决复杂业务的方式,才能真正体现算法上的思考和巧妙设计的优雅。

简单的示例:


/**
* 接口的简单化
* 给使用者符合期望的输入输出保持确定性
*/ 
public function getUserInfoById(int $id) : array 
{
    ...
}

/**
* 错误的简单化接口
* 不确定的可自定义的返回字段
* 不确定的获取条件
*/
public function getUserInfo($field = '*', $where)
{
   ...
}

避免创建冗余的代码

除非必要,不要创建新功能。 示例: 不必要的一些冗余代码

  • 穿透类和示例的全局常量和函数,全局类。
  • 过多的抽象和封装。
  • 在简单的MVC外部集成各种工具类和便捷操作的静态类。
  • 在模型层和控制器层的顶部添加巨大的业务配置数组,将应该放在配置文件夹里的配置数据。
  • 在控制器层和模型层顶层,集成过多的抽象基类和工具类。

只做可运行的最简单的事

尽可能做可运行的最简单的事。

保持简单原则。

重构代码时,应该朝不断简化代码的目标优化。

傻瓜式

编写的代码一定要易于读和理解,这样别人才会欣赏,给你提出合理化的建议。

相反,若是繁杂难解的程序,其他人总是会避而远之。

代码里优雅的命名规范,就是最好的注释。

代码结构体间必要的详细注释是最好的编程文档。

针对每一次代码修改留下详细的时间日期索引和注释是必要的。

完整的编码文档和标准接口文档,是团队协作最基础的需求。

开放接口和继承

团队协作中,为方便他人扩展自己的代码,留下足够的Interface类和基类是必须的方式。
在维护他人的代码时,优先考虑继承和扩展,切忌直接动手修改。
针对团队成员的代码,应该首先沟通使其修改满足需求。
针对项目中的开源代码尤其是框架代码,禁止直接修改源码,而应该扩展或者继承实现自己的意图,维护其版权和后续升级更新的必要。

有利于维护

保持简单,易于理解,详细注释。
文件注释,函数注释,类注释严格安装编码规范。
代码仓库每次提交,commit message要详细说明,不要敷衍。
团队协作时,需要团队成员每周专门抽两个小时,review自己近一周内所写的代码,并定下优化计划,快速解决一周内的严重问题,简化自己不太优雅的实现方式。

最小化原则

只写需求所需的最小化功能,别炫技,写太多本来不需要但看起来好像很牛逼的东西。

单一化原则

某个代码的功能,应该保证只有单一的明确的执行任务。

简单的示例:


/**
* 接口的简单化
* 给使用者符合期望的输入输出保持确定性
*/ 
public function getUserInfoById(int $id) : array 
{
    ...
}

/**
* 错误的简单化接口
* 不确定的可自定义的返回字段
* 不确定的获取条件
*/
public function getUserInfo($field = '*', $where)
{
   ...
}

低耦合原则

代码的任何一个部分应该减少对其他区域代码的依赖关系。
尽量不要使用共享参数和可变参数。
低耦合往往是完美结构系统和优秀设计的标志。
错误示例中,Model的SQL字段在控制器中被耦合,这也是通常导致SQL注入攻击后果的主要原因


// application/models/User/Info.php
class Info extends Db 
{
    /**
    * 不确定的可自定义的返回字段
    * 不确定的获取条件
    */
    public function getUserInfo($field = '*', $where)
    {
        ...
    }

    ...
}

// application/controller/User.php
class User extends Controller
{
    /**
    * 不确定的可自定义的返回字段
    * 不确定的获取条件
    */
    public function  indexAction()
    {
        $uid = $this->get['uid'];
        $userinfos = $this->userInfoModel->getUserInfo($uid);
    }

    ...
}

高内聚原则

相似的业务和功能代码应尽量放在一个部分。
良好的文件夹和文件命名规范,用来高度内聚相关的业务模块和功能


// application/models/User 该命名空间存放所有用户相关的业务数据处理
// application/models/User/Admin 该子命名空间存放所有跟用户后台管理相关的业务数据处理
// application/controllers/User 该命名空间存放所有用户相关的业务逻辑处理
// appliaction/views/zh_cn/User 该文件夹存放所有用户相关的视图模板
// 

隐藏实现细节(Hide Implementation Details)

接口设计需要隐藏实现细节原则。
当其他部分发生变化时,能够尽可能降低对其他组件的影响。


/**
* 接口的简单化
* 给使用者符合期望的输入输出保持确定性
*/ 
public function getUserInfoById(int $id) : array 
{
    return $this->getUserInfoFromCache($id);
}

/**
* 对调用公共接口的成员可隐藏具体实现的细节,并通过私有标识防止调用。
*/
private function getUserInfoFromCache(int $id) 
{
   ...
}

最少化原则

代码只和与其有直接关系的部分连接。
比如类的接口设计,传递的参数。


/**
* 公共接口开放,设计尽量简单,具有符合预期的稳定
* 给使用者符合期望的输入输出保持确定性
*/ 
public function getUserInfoById(int $id) : array 
{
    return $this->getUserInfoFromCache($id);
}

/**
* 对调用公共接口的成员可隐藏具体实现的细节,并通过私有标识防止调用。
*/
private function getUserInfoFromCache(int $id) 
{
   ...
}

避免过早优化

除非代码性能比预估要慢,否则别去优化。
假如真的想优化,就必须先测算数据证明速度真的变快。
商业化项目中,因为过早优化多花费的时间和人力,都是成本的巨大浪费,切忌追求不必要的完美。
这也是PHP有诸多不完美之处,仍具有顽强生命力的原因所在,敏捷开发,节省时间就是节省金钱,可以低成本的快速验证业务模式判断可行性。

代码重用原则

提高代码的可读性,缩短开发时间。
与15有些区别的地方,在前期架构和系统设计,代码重用性等方面多花功夫,可以避免后面推到重来浪费更多时间延误项目顺利上线的严重后果。
简而言之,无数惨痛的经验教训告诉程序员们: 磨刀不误砍柴工。

分布式与离散原则

不同类型的模块和功能,应该由不同的代码和最小重迭的模块组成。

拥抱改变

积极面对变化,灵活运用以上规范和约束,善于取舍。
编程语言,编程框架,以至于IDE,编程硬件等等,都只是我们实现自己项目的辅助工具,如果其中任何一种不适应我们的项目需求,应该快速舍弃,换成更适应我们工作的工具。
老鸟都会多学几种语言,才会融会贯通,举一反三。
最后的忠告,不要抱残守缺,墨守成规,然后发现自己在时代的潮流中,落后了。