成长,就是不断向自己妥协的过程

引言

​ 在新东家实习已经快一个月了,环境还可以,工作也相对轻松。

​ 公司主要业务是电商SAS平台,开发部门算上我有5个人,3个后端两个前端,我负责后端,算一个比较正规的小团队吧。

​ 实习期间呢,我全力负责SAS平台的三个模块后台的业务开发,分别是素材库、社区(帖子)、商学院(课程)。

​ 这些需求对久经沙场的我来说,自然不在话下,没到一个月就完成了初步的开发,接下来只需要与前端对接完就可以了。

事情经过

但是这几天与leader发生了一些摩擦和争执,百般无奈下,我也只好向他妥协。

主要两个件事:

  1. 字段必填

    ​ 起初的时候我给课程设计了两个字段,一个是课程的开课和结束时间。(后面我仔细看了下需求,并不需要这两个字段)我数据库给这两个字段约束了”必填“ 就是 不能为null。

    ​ 他可能迁移数据的时候,报了这两个字段没有默认值导致错误了吧~ 于是截图给了我,什么也不说。然后我就解释说,这两个字段设置必填才合理,不应该设置默认值。

    ​ 然后他给我的回应是:必填也要有默认值 (我一头雾水...)

  2. 代码冗余

    ​ 继 ”字段“ 事件后,他也对我写的一个接口进行了审查。 我写的一个 推荐产品的Api接口,可以根据不同的分类,筛选出可选的产品。

    ​ 举个例子:

    ​ 产品类型有:商品 和课程

    ​ 我需要根据这个类型 去对应的表拿可选的数据。后台添加数据的时候也有这个需求,于是我就写在了一个Api,前端和后台都可以共用这个接口。

    ​ 于是,他就觉得这样不行,要求我拆分开来。 我问他原因呢,他又说不出来,我以为他不了解需求,就不断的向他讲述,最后没有用,结果自然闹得很僵。

    ​ 我们就这样僵了两三天吧,他就找我谈话了,说要我适应环境,把业务都写在一个Function 里,因为昨天同事看了我的代码,跳来跳去的,看不懂~ ,

    ​ 我说我可以对我这块业务写个详细的文档,这也不行,无奈下,我也只好妥协。刚来不久,很多东西都不能硬性的去改变,也只能去适应他们的开发方式。

    ​ 接着,他对我的接口设计又有意见了。社区下的帖子和商学院里的课程都能评论,回复,点赞。

    于是我把这些各自写成一个接口,只需要传参数识别是课程还是帖子就行了。他要求我把这些拆分出来,就是说课程的评论和帖子的评论不能一个接口。百般的解析下,无用,我也只好再一次妥协。

修改后的对比

修改后的代码我真的不想看~ 感觉要被后面的人挖祖坟~~

就简单帖一个创建评论操作的对比吧~

修改前:

  1. 创建评论操作入口
    /**
     * 创建评论
     * @param CommentRequest $request
     * @param $id
     * @return mixed
     */
    public function createComment(CommentRequest $request, $id)
    {
      //获取type,根据typpe 获取对应的query
        $type = $request->input('type');
        $query = BaseModel::getQuery($type);
        $data = $request->except('type');

      //检查对象是否存在
        try {
            $object = $query->findOrFail($id);
        } catch (ModelNotFoundException $exception) {
            return $this->failed('对象不存在');
        }

        try {
          //把对象和数据传到创建评论操作 createCommentHandle
            NewRetailCommonComment::createCommentHandle($object, $data);
            return $this->success('评论成功');
        } catch (\Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }
  1. CommentRequest.php

Request 中传个类型和内容

<?php

namespace App\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;

class CommentRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'type' => 'required|in:post,course',
            'content' => 'required|min:1'
        ];
    }
}
  1. BaseModel.php

根据类型获取不同的实例

    /**
     * 获取不同的$Query
     * @param $type
     * @return bool|\Illuminate\Database\Eloquent\Builder
     */
    public static function getQuery($type)
    {
        switch ($type):
            case 'post':
                return NewRetailCommunityPost::query();
                break;
            case 'course':
                return NewRetailCourse::query();
                break;
            case 'comment':
                return NewRetailCommonComment::query();
                break;
            case 'replies':
                return NewRetailCommonCommentReplies::query();
                break;
            default:
                return false;
        endswitch;
    }
  1. NewRetailCommonComment.php
/**
 * 添加评论处理操作
 * @param $object
 * @param $data
 * @return bool
 * @throws \Exception
 */
public static function createCommentHandle($object, $data): bool
{
  //判断对象的类型 获取实例
    if ($object instanceof NewretailCommunityPost) {
        $model = new NewretailCommunityPost();
    } elseif ($object instanceof NewRetailCourse) {
        $model = new NewRetailCourse();
    }

  //判断对象是否有效
    $model::isEffective($object);

  //评论功能是否开启
    if (!$model::isComment()) {
        throw new \Exception('评论功能还没有开启哦~~');
    }

  //是否需要审核
    if (!$model::commentIsReview()) {
        $data['status'] = CommunityPostEnum::ONE;
    }

  //返回创建所需的共用数据
    $uuidAndCustomer = BaseModel::getCustomerAndUuid();
  //数组合并
    $data = array_merge($data, $uuidAndCustomer);
  //创建评论
    $object->comment()->save(new NewRetailCommonComment($data));
    return true;
}

修改后:

修改后的话,就是全部放一个Function里。实在没眼看~~

  1. 入口(创建文章评论)
    /**
     * 创建评论
     * @param CommentRequest $request
     * @param NewRetailCommunityPost $post
     * @return mixed
     */
    public function createComment(CommentRequest $request, NewRetailCommunityPost $post)
    {
        $data = $request->all();
        try {
            NewRetailCommonComment::createPostComment($data, $post);
           return $this>success(ErrorCodeEnum::RETURN_ERROR_CODE_MSG[ErrorCodeEnum::ACTION_SUCCESS]);
        } catch (\Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }
  1. NewRetailCommonComment.php
    /**
     * 创建文章评论
     * @param $data
     * @param $post
     * @return bool
     * @throws \Exception
     */
    public static function createPostComment($data, $post): bool
    {
        $model = new NewretailCommunityPost();

        if ($post->is_del
            || $post->status != CommunityPostEnum::ONE
            || Auth::user()->customer_code != $post->customer_code) {
            throw new \Exception(ErrorCodeEnum::RETURN_ERROR_CODE_MSG[ErrorCodeEnum::POST_NO_FOUND]);
        }

        /**
         * 判断是否可以评论
         */
        if (!$model::isComment()) {
            throw new \Exception(ErrorCodeEnum::RETURN_ERROR_CODE_MSG[ErrorCodeEnum::NO_OPEN_COMMENT_PERMISSION]);
        }

        /**
         * 判断是否需要审核
         */
        if (!$model::commentIsReview()) {
            $data['status'] = CommunityPostEnum::ONE;
        }

        $user = Auth::user();
        $data = array_merge($data, [
            'customer_code' => $user->customer_code,
            'uuid' => $user->uuid
        ]);
        $post->comment()->save(new NewRetailCommonComment($data));
        return true;
    }

创建课程评论 又需要 重新差不多的代码~~~

总结

​ 我发这篇文章的本意并不是如何的抬高自己,贬低别人,我也不认为自己写得有多好,写一些业务代码,没什么值得骄傲的。通过这件事,我领悟到了,有时候有些事情,就算你很不喜欢,很不乐意,为了生活,也得适当的妥协。成长,就是不断向自己妥协的过程。

这种环境并不是我向往的,但是生活所迫,暂时任性不了,我还是会保持我的个性。

原文

个人博客

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 21
Summer

字段必填

无论是否必填,都决不能让队友在迁移的时候报错。因为报错了,别人的工作有可能就得停止,等你修复或者帮你修复,这都是容易变成令人恼火的事情。这是团队开发的基准线,不能碰。

至于『必填』无非就是 1. PHP 的责任或者 2. DB 的责任。这是一个备受争议的话题,个人认为两种各选其一,或者两者都选,都有其合理性(这里不展开可以自己去做做功课),团队里达成一致即可。

『代码冗余』

他说: 『同事看了我的代码,跳来跳去的,看不懂』。

行业里有句话:

file

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
—— Martin Fowler

翻译过来大概是:

任何傻瓜都能写机器可执行的代码,而优秀的程序员写的代码傻瓜都能看懂。

你的筛选商品,评论,回复,点赞,这些接口,都有这个问题,就是你写了以后,别人闭着眼睛不知道去哪里寻找。无意而为之的,你已经为团队其他成员造成了不便,因为他们需要花费时间更多的时间去适应你自创的『规则』。而在这一点上,你的领导还是比较负责任的。

Laravel 大部分的 API 程序里大家都会遵循 restful 的设计规范(点击这里查看更多 社区关于 Restful API 的精华文章),遵守规范的好处是,大家写出来的代码就如自己写的一样,不必花时间去适应其他人『自创』的一套写法。假设团队里每个人都按照自己个人喜好的方式去编写代码,可想而知整个团队的效率得多低。

需要知道的一点是:

把你的项目合成一个巨大的 PHP 文件,PHP 解析器也是可以执行的。

那问题就来了,为啥我们要费那个劲搞什么 MVC 模式,Restful API 模式呢?

上面提的那句话就是答案,为了强调,我再重申一次:

任何傻瓜都能写机器可执行的代码,而优秀的程序员写的代码傻瓜都能看懂。

最后非常喜欢作者的性格,懂得坚持。不过大家都有萌新的时候,认知偏差改过来就是成长咯,建议你补一些『软件工程』相关的知识哈。

4年前 评论
leo

当你的能力水平高于团队平均技术水平时,确实会出现这样的问题,正如你给一个十八线城市培训班出来的人解释 Laravel 是如何地优雅,他也只会说「跳来跳去,看不懂,还不如 XX 框架好用」。

而作为团队的技术 Leader,挑选出适合大多数团队成员技术、规范是他的职责(虽然也有可能是他比你菜),所以要么忍,要么滚,要么取代你的 Leader。

4年前 评论

summer大佬已经说得很好了,我这里从另一个角度谈谈我的一点想法。

我相信大部分程序员都有过与楼主这样类似的经历或想法,特别是在刚开始工作不久的时候:当自己的想法(指技术问题)跟同事或上司有冲突时,很容易就跟同事起争执,甚至最后双方都有点不愉快。

当时的想法可能很简单:我这个想法才是对的,或是我的想法比你的好。

然而一段时间以后(也可能是很久以后)再回过头来看这个问题时,你可能会发现原来自己的想法也并没有多好,甚至还很糟糕;又或者你可能会发现当时争执的这个问题根本没啥必要,就算自己是对的,那又怎么样呢?自己得到了什么?为这么点问题而让同事对自己产生反感值得吗?

这个时候你就会明白,以前的自己到底有多傻逼了。

所以说别太把自己的想法当回事,在工作中有时候很多技术问题真的不是问题,不能仅仅只看到技术,而忽略了其他一些也很重要的问题,比如人际关系、团队合作等等。当然我说这些也不是说完全不能坚持自己的想法或意见,而是说在遇到问题时应该多方位考虑问题,分清主次,多想想后果。

PS:个人觉得你发出来的代码并不算一个好的实现方案,推荐阅读一下PHP 代码简洁之道 ( PHP Clean Code),平时可以多看看大佬们是怎么写代码的,多向大佬们学习。

4年前 评论
Natural (楼主) 4年前
野犭 4年前
小李世界 4年前

有工资吗?有,那就听话。没有,那就follow your heart。
你都久经沙场了,心态依旧是少年,祝你周末愉快。

4年前 评论
Natural (楼主) 4年前
Summer

字段必填

无论是否必填,都决不能让队友在迁移的时候报错。因为报错了,别人的工作有可能就得停止,等你修复或者帮你修复,这都是容易变成令人恼火的事情。这是团队开发的基准线,不能碰。

至于『必填』无非就是 1. PHP 的责任或者 2. DB 的责任。这是一个备受争议的话题,个人认为两种各选其一,或者两者都选,都有其合理性(这里不展开可以自己去做做功课),团队里达成一致即可。

『代码冗余』

他说: 『同事看了我的代码,跳来跳去的,看不懂』。

行业里有句话:

file

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
—— Martin Fowler

翻译过来大概是:

任何傻瓜都能写机器可执行的代码,而优秀的程序员写的代码傻瓜都能看懂。

你的筛选商品,评论,回复,点赞,这些接口,都有这个问题,就是你写了以后,别人闭着眼睛不知道去哪里寻找。无意而为之的,你已经为团队其他成员造成了不便,因为他们需要花费时间更多的时间去适应你自创的『规则』。而在这一点上,你的领导还是比较负责任的。

Laravel 大部分的 API 程序里大家都会遵循 restful 的设计规范(点击这里查看更多 社区关于 Restful API 的精华文章),遵守规范的好处是,大家写出来的代码就如自己写的一样,不必花时间去适应其他人『自创』的一套写法。假设团队里每个人都按照自己个人喜好的方式去编写代码,可想而知整个团队的效率得多低。

需要知道的一点是:

把你的项目合成一个巨大的 PHP 文件,PHP 解析器也是可以执行的。

那问题就来了,为啥我们要费那个劲搞什么 MVC 模式,Restful API 模式呢?

上面提的那句话就是答案,为了强调,我再重申一次:

任何傻瓜都能写机器可执行的代码,而优秀的程序员写的代码傻瓜都能看懂。

最后非常喜欢作者的性格,懂得坚持。不过大家都有萌新的时候,认知偏差改过来就是成长咯,建议你补一些『软件工程』相关的知识哈。

4年前 评论
Natural

首先,非常荣幸能收到大佬的指点。

可能我文章描述得不够清楚,或者说我现在的发表也是错误的。

  1. 不是接口找不到

我把一些可复用的代码抽出来,方便下次用的时候不需要再重复写。

就比如 文章中的 是否可以评论,帖子是否存在,是否需要审核等...

  1. 设计问题

我认为呢,帖子和课程都有评论,可能后期又加入别的板块也要求有评论,我就 把评论操作抽成的 一个Api,我认为这样的设计比较合理。

4年前 评论

多看,少说。
要么忍,要么滚

4年前 评论

emm...公司买了 APP,我接手过来,也是一大堆数据库不能为空的报错,后面只能把严格模式去掉了先。

后面也是要迁移,也是只能先设置字段允许为空。

严重同意第二点,短期来看是没什么问题,后期共用代码的时候,还是要拆分,还不如早点弄,遵循一个 function 一个目的。

4年前 评论

我感觉大部分程序员都会过这种问题,是最优解还是普遍解。程序员应该都想着追求自己的代码优雅、高效。也应该在这上面吃过亏。我写代码总想着,这样循环合不合适、用 php 函数效率高还是自己写的效率高;这块的代码又写了一遍,应该考虑复用;结果就是下个版本一改,发现好多能复用的地方变的不一样了,甚至有时自以为豪的数据库设计不适用了,开始了自己的补救之路,有时还得麻烦前端帮忙改点东西,以适应这个版本(原本前端不需要动的部分)。当这次验收之后,看看自己的代码,发现还没有哪种普通设计的好。这是我就很纠结,业务代码需要使用最优的解决方案吗?因为你不知道下个版本会改啥,下下个版本会改啥。很有可能改动的就是你原来设计最满意的地方。我想起一个前辈说的话,“代码不要过早的优化”。虽然我这个不算是优化,但是设计的时候考虑最好导致缺乏了点通用性。我期待着项目可以成熟,稳定。然后好好的设计一把。但是真的可能实现吗?估计只有自己的个人项目里。

4年前 评论
leo

当你的能力水平高于团队平均技术水平时,确实会出现这样的问题,正如你给一个十八线城市培训班出来的人解释 Laravel 是如何地优雅,他也只会说「跳来跳去,看不懂,还不如 XX 框架好用」。

而作为团队的技术 Leader,挑选出适合大多数团队成员技术、规范是他的职责(虽然也有可能是他比你菜),所以要么忍,要么滚,要么取代你的 Leader。

4年前 评论

嘿嘿,没有谁是对的或者错的,只是出发点不同,都是工作嘛,我以前也总和 Leader 顶嘴,后面自己就收起小性子了。别人的规则咱们执行就成了。至于好坏自己心里有底就成了。

4年前 评论

BaseModel.php 文件里的getQuery方法,会不会太冗余了?这样写的目的是什么?

4年前 评论
Natural (楼主) 4年前
pikalu (作者) 4年前
Natural (楼主) 4年前
pikalu (作者) 4年前
Natural (楼主) 4年前
master_520 4年前

如果是团队里面 听leader的 先按团队规则来
你认为规则不合理 可以向leader提建议 简便易操作的先提 看后续的项目leader同不同意新的方式
其实这是个沟通的问题 团队里如果你不是leader 肯定没法按自己的方式来 因为协作方式要统一么
你可以建议leader出个代码规范 不断迭代改进么

4年前 评论
Natural (楼主) 4年前
xiaopi

@Summer 受教了 :+1:

4年前 评论

@leo @Summer 请教一下,不针对事情,只针对代码。这种代码算不算前期过度优化的例子?比如说后面有需求不同类型的模型需要不同的创建规则。可能最开始的时候这些模型是有共性的部分的,但是后面需求增加了之后模型不同的地方越来越多。那这种以BaseModel然后判断对象类型的封装方式是不是很糟糕的封装方式?用trait去做不是更好?

4年前 评论
Summer 4年前
leo 4年前
will_lin (作者) 4年前
Natural (楼主) 4年前

创建课程评论 又需要 重新差不多的代码~~~

有些功能并不是代码差不多就要公用的。。商品评论和论坛话题评论都是评论,难道你要公用代码吗,反而我觉得你的 leader 是个比较负责的 leader ;特别是对那些还没转正的新员工来说,允许新员工按自己的规则来写,然后写个几天就离职,最后搽屁股的还是老员工,基本就是重写

4年前 评论
22 (作者) 4年前
Natural (楼主) 4年前

中途加入项目尽量按项目原有的风格来写,新项目在开始前就要规范风格了

4年前 评论
Natural (楼主) 4年前

summer大佬已经说得很好了,我这里从另一个角度谈谈我的一点想法。

我相信大部分程序员都有过与楼主这样类似的经历或想法,特别是在刚开始工作不久的时候:当自己的想法(指技术问题)跟同事或上司有冲突时,很容易就跟同事起争执,甚至最后双方都有点不愉快。

当时的想法可能很简单:我这个想法才是对的,或是我的想法比你的好。

然而一段时间以后(也可能是很久以后)再回过头来看这个问题时,你可能会发现原来自己的想法也并没有多好,甚至还很糟糕;又或者你可能会发现当时争执的这个问题根本没啥必要,就算自己是对的,那又怎么样呢?自己得到了什么?为这么点问题而让同事对自己产生反感值得吗?

这个时候你就会明白,以前的自己到底有多傻逼了。

所以说别太把自己的想法当回事,在工作中有时候很多技术问题真的不是问题,不能仅仅只看到技术,而忽略了其他一些也很重要的问题,比如人际关系、团队合作等等。当然我说这些也不是说完全不能坚持自己的想法或意见,而是说在遇到问题时应该多方位考虑问题,分清主次,多想想后果。

PS:个人觉得你发出来的代码并不算一个好的实现方案,推荐阅读一下PHP 代码简洁之道 ( PHP Clean Code),平时可以多看看大佬们是怎么写代码的,多向大佬们学习。

4年前 评论
Natural (楼主) 4年前
野犭 4年前
小李世界 4年前

楼主的第一条,可以站在 CTO 的立场上看问题,可以协同解决问题,或者给他善后问题,或者直接帮他解决问题,而不是对解决问题过程中的一个点上挑问题。

他知道你说的没错,但是不能解决问题,有些东西其实都是可以妥协。

接手的项目,那个人是懂前后端和业务的老板,做 APICloud 的,他跟我交接完这个项目后,他接了机构的单子,30多万,公司五个人。

我接手项目的时候,也是吐槽,各种 bug ,function 几百行,各种炼狱回廊(if else 十多层,我的显示器都没那么长),但是人家会赚钱,他知道可以重构,但是却花时间在其他上面。

我说的总结就是,事物都是一分为二,没有对错,关键是协调(协调当中也包含单方妥协(褒义))。

4年前 评论
Natural (楼主) 4年前
try {
} catch (\Exception $exception) {
}

解释

大多数情况,不要捕获这个异常,所有的 Exception 都会走到该类,但是!有些不是“我们”所能处理的,比如说:数据库异常,假如捕获了,Laravel 本身的错误处理机制都不会工作,意味着没有错误日志,生产环境报错,没有错误日志是很头大的事情。

改进

改进的方法很简单,定义自己的异常类,必要的时候抛出自定义异常类,只捕获自定义异常类。或者说是我们应捕获我们所能处理的异常

class MyException extends Exception {
}
if(...) {
    thrown new MyException('妈妈说要按时吃饭!');
}

try {
} catch (MyException $exception) {
}
4年前 评论
Natural (楼主) 4年前
小黄 4年前
aen233 4年前
  1. 不知道笔者以前是如何在团队中进行开发的。

    我们团队开发,是求同存异的。
    但是!当你有自己的想法,要先和大家沟通,问问 leader 他之前设计这个功能时候的想法。
    做好一个团队项目,是一个团队的工作,而不是你个人的工作。

  2. 另外承接大佬发的那句名言,推荐笔者去看看《Clean Code》这本书。

    注释毕竟是代码之外的东西,远不如把代码写好,让人阅读起来更加直观。

    • 如果你能用代表阐述清楚你的意图,那么你的代码是诗。
    • 如果你的代码用注释能解释清楚你的意图,那么你的代码还算是可读。
    • 如果你的代码用注释都无法解释清楚,那么一段时间之后,你就会发现 “曾经的你,给现在的你造成了极大的困扰”。
4年前 评论
Tricker (作者) 4年前

如果是初入团队,建议还是多看一下别人写的代码。毕竟,团队之间只有协同合作。有幸维护了一段代码,为了实现一个功能,里面包含了大量的 ifelse,原生sql也写的很6。不知过去了多久,等到需要增加需求时,这个地方已经没人能搞懂原有的业务逻辑是怎样的了。随着项目越来越大,越来越多。简单的改动,都会影响到其它项目的运行,甚至抛出了一堆又一堆的bug。

适当封装,同时也要考虑到未来一段时间内的可扩展性,更要想到这段代码,可能成为别人眼中的 long long ago的上古代码。

其实感觉楼主写的代码还好,看起来也不会杂乱无章,就是在整体理解上差了一丢丢。可能每个人写代码的风格不一样吧。举个栗子:像异常抛出那块,我会封装到类里,包括一些异常的状态码,会使用变量或常量。控制器里面尽可能的只做逻辑层面的处理,这样的好处,不管业务多么复杂,都能一目了然。而不至于我把整个源码看完了才知道做了些啥。(毕竟还有那么多美好的事要去记)其次,注释这一块,可以尝试去精简一些。

论坛里大神太多,话就不多说了。

4年前 评论

在生活面前什么代码,什么工程师,什么技术,都不值一提,赚钱最重要,不要做这种无病呻吟

4年前 评论
playmaker

遇到情况,定要稳住 ,情绪压住,面带微笑。 心里大声说:너 바보 아니야 ?(你怕不是个傻子吧?) 脸上同时也不妨碍 Make Believe Respect file file 笑一个吧,功成名就不是目的,让自己快乐快乐,这才叫做意义。 Happy Coding :)

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!