如何成为一名优秀的工程师(语义篇)

阿里云幸运券
不要让其他人读不懂你的代码,其他人可能就是一周后的你。时刻以“如果你写的这段代码出现故障,一个陌生人接手你的代码需要多久能处理完这个bug”来监督自己。

日常中应该多多刻意提升自己语义表达,百利而无一害。那么我们应该从哪些细节去做好语义表达呢?

image.png

以下代码全为我的艺术创作,不属于任何实际项目
命名
案例1
function getGoods($query, $shopId)
{
g o o d s I d = G o o d s : : a d d ( goodsId = Goods::add( goodsId=Goods::add(query[“uid”], q u e r y [ " n a m e " ] ) ; r e t u r n S h o p : : a d d ( query["name"]); return Shop::add( query["name"]);returnShop::add(goodsId, $shopId);
}

class Goods
{
public static function add($uid, $name)
{
$id = mt_rand(1, 100000);
return $id;
}
}

class Shop
{
public static function add($goodsId, $shopId)
{
$id = mt_rand(1, 100000);
return $id;
}
}
image.png

案例2
function getUserInfo($teamId, $youId = [])
{

}
如果仅仅有这个函数名和参数名,谁能猜到参数的意义呢?
image.png

案例3
class Db
{
/**
* @param string $table 数据库表名
* @param array $data 新增数据
*
* @return int 新增主键
*/
public static function insert(string $table, array $data)
{
$id = mt_rand(1, 1000);
return $id;
}
}

class ViewLogStore
{
private $table = “view_log”;

function setHistory($data)
{
    Db::insert($this->table, $data);
}

}
image.png

案例4
假如业务代码里有这些类

class WechatUserModel{

}

class WechatGroupModel{

}

class WechatMessageModel{

}
而我们查询数据库发现
image.png

这样我们根据业务代码就非常不方便找到对应的表,而且其他人接手我们项目的时候,也会摸不着头脑。或者说这可能是三个人三次迭代开发造成的,那么他们彼此都没有去参考前面人的命名规则。

来自灵魂的拷问

image.png

注释
说完命名,下面说下注释。注释里还有什么学问?Are you kidding me?
一个数组对象成员,你知道怎么写吗?
类的魔术方法调用的注释,你知道怎么写吗?
腾讯云代金券

对象数组
/**

  • @var Ads[]
    */
    public $adsList = [];
    image.png

$blocks = [];/** @var $blocks Block[] **/
image.png

@method 的使用
/**

  • @link http://manual.phpdoc.org/HTMLframesConverter/default/

  • @method static int search(string $query, $limit = 10, KaTeX parse error: Expected group after '_' at position 67: …tatic function _̲_callStatic(method, $arguments)
    {
    if (!method_exists(“SearchService”, $method)) {
    throw new \LogicException(CLASS . “::” . $method . " not found");
    }

     try {
         $data = call_user_func_array(["SearchService", $method], $arguments);
     } catch (\Exception $e) {
         error_log($e->getMessage());
         return false;
     }
    
     return $data;
    

    }
    }
    image.png

@deprecated 使用
class SearchService
{

/**
 * @param string $query
 * @param int    $limit
 * @param int    $offset
 *
 * @return array
 * @deprecated
 */
public static function search(string $query, $limit = 10, $offset = 0)
{
    return [
        ["id" => 1, "aaa"],
        ["id" => 2, "bbb"],
    ];
}

}
image.png

注释其他注意事项
注释解释张冠李戴,方法名更新,方法的功能业务注释没更新;复制别人的代码把 @author 信息也复制过来了,错误了还要把锅甩给别人。

注释更多参考 http://manual.phpdoc.org/HTML
函数、方法
案例1
先说明一句,不好的代码不妨碍它成为一个优秀的软件。PHP MySQL 烂代码多的去了。
找到一个开源软件里面的代码,功能非常抢到,但是这个方法内容太多,一些不足点我标注出来了。
image.png

案例2
拿上面我举例子,还记得下面这种图吗?
image.png

优化方案1

class ArrayUtils{
public static function fetch($arr, $keys, $setNull = false)
{
r e t = a r r a y ( ) ; f o r e a c h ( ret = array(); foreach( ret=array();foreach(keys as KaTeX parse error: Expected '}', got 'EOF' at end of input: … if (setNull)
{
r e t [ ret[ ret[key] = a r r [ arr[ arr[key];
}
else
{
isset( a r r [ arr[ arr[key]) && r e t [ ret[ ret[key] = a r r [ arr[ arr[key];
}
}
return $ret;
}
}

class ViewLogStore
{
private $table = “view_log”;

function record($data)
{
    $fields = array(
        'uid',
        'url',
        'referer',
        'created_time'
    );
    $data = ArrayUtils::fetch($data, $fields);
    Db::insert($this->table, $data);
}

}
优化方案2

class Db
{
/**
* @param string $table 数据库表名
* @param Entity $data 新增对象
*
* @return int 新增主键
*/
public static function insert(string $table, Entity $data)
{
$array = d a t a − > t o A r r a y ( ) ; v a r e x p o r t ( data->toArray(); var_export( data>toArray();varexport(array); // test

    $id = mt_rand(1, 1000);
    return $id;
}

}

class ArrayUtils
{
/**
* 针对成员都是私有属性的对象
*
* @param $obj
* @param bool $removeNull 去掉空值
* @param bool c a m e l C a s e ∗ ∗ @ r e t u r n a r r a y ∗ / p u b l i c s t a t i c f u n c t i o n O b j 2 A r r a y ( camelCase * * @return array */ public static function Obj2Array( camelCase@returnarray/publicstaticfunctionObj2Array(obj, $removeNull = true, $camelCase = true)
{
KaTeX parse error: Expected 'EOF', got '\ReflectionClass' at position 15: reflect = new \̲R̲e̲f̲l̲e̲c̲t̲i̲o̲n̲C̲l̲a̲s̲s̲(obj);
$props = $reflect->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED);

    $array = [];
    foreach ($props as $prop) {
        $prop->setAccessible(true);
        $key = $prop->getName();

        // 如果不是驼峰命名方式,就把对象里面的 createTime 转成 create_time
        if (!$camelCase) {
            $key = preg_replace_callback("/[A-Z]/", function ($matches) {
                return "_" . strtolower($matches[0]);
            }, $key);
            $key = ltrim($key, "_");
        }

        $value = $prop->getValue($obj);

        if ($removeNull == true && $value === null) {
            continue;
        }

        if (is_object($value)) {
            $value = self::Obj2Array($value);
        }

        $array[$key] = $value;
    }

    return $array;
}

}

class Entity
{
public function toArray(){
return ArrayUtils::Obj2Array($this);
}
}

class ViewLogEntity extends Entity
{
/**
* @var int
*/
private $uid;

/**
 * @var string
 */
private $url;

/**
 * @var string
 */
private $referer;

/**
 * @var string
 */
private $createdTime;

/**
 * @param int $uid
 */
public function setUid(int $uid)
{
    $this->uid = $uid;
}

/**
 * @param string $url
 */
public function setUrl(string $url)
{
    $this->url = $url;
}

/**
 * @param string $referer
 */
public function setReferer(string $referer)
{
    $this->referer = $referer;
}

/**
 * @param string $createdTime
 */
public function setCreatedTime(string $createdTime)
{
    $this->createdTime = $createdTime;
}

}

class ViewLogStore
{
private $table = “view_log”;

function record(ViewLogEntity $viewLogEntity)
{
    Db::insert($this->table, $viewLogEntity);
}

}

// 测试

$viewLogEntity = new ViewLogEntity();
$viewLogEntity->setUid(1);
$viewLogEntity->setReferer(“https://mengkang.net”);
$viewLogEntity->setUrl(“https://segmentfault.com/l/1500000018225727”);
$viewLogEntity->setCreatedTime(date(“Y-m-d H:i:s”,time()));

$viewLogStore = new ViewLogStore();
v i e w L o g S t o r e − > r e c o r d ( viewLogStore->record( viewLogStore>record(viewLogEntity);
案例3
这还是函数吗?(不仅仅是语义,属于错误)

/**

  • @method mixed fetchList(string $sql, array $argv);
    */
    class Model
    {

    public function __construct($table)
    {

    }
    }

function getUserList($startId, $lastId, KaTeX parse error: Expected '}', got 'EOF' at end of input: …100) { if (lastId > 0) {
$startId = $lastId;
}

$sql = "select * from `user` where id > ? order by id asc limit ?,?";

$model = new Model('user');
return $model->fetchList($sql, [intval($startId), intval($limit)]);

}
s t a r t I d 和 startId和 startIdlastId两个参数重复

案例4
尽量减少参数引用

function bad($input1, KaTeX parse error: Expected 'EOF', got '&' at position 9: input2, &̲input3)
{
//…logic

$input3 = "xxx";

return true;

}
案例5
参数类型明确,返回值类型明确,不要出现 mixed。这个我直接拿官方的函数来举例,对权威也要有怀疑的眼光。纯属个人看法。
image.png

案例6
image.png

上面例子中你会发现这个addUser写得不想一个函数(方法)而像一个远程api接口。而且在右边的代码中需要每次使用的时候都要用is_array来判断。这是非常不友好的语义表达。PHP Java 这样的高级语言有异常,我们要善用异常。

image.png

好的语义表达是团队协作中高效迭代的润滑剂,好的语义表达是线上未知代码问题排查的指南针。这篇博客到这里就结束了,不知道你是否有一些收获呢?
image.png
腾讯云代金券

原文链接

https://segmentfault.com/a/1190000018373101

服务推荐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值