资讯专栏INFORMATION COLUMN

举枪消灭"烂代码"的实战案例

JiaXinYi / 530人阅读

摘要:前言之前我写过一篇如何少写烂代码感觉很多新人对此不太理解。今天以打卡功能为例去讲解其中的奥秘。那篇文章讲过代码开发的过程中分几种类型。增删改的需求查的需求经过多次实际开发验证后,发现完全是多次一举。所以在这里更正下,取消。

前言

之前我写过一篇如何少写PHP "烂"代码 https://segmentfault.com/a/11...
感觉很多新人对此不太理解。今天以打卡功能为例,去讲解其中的奥秘。那篇文章讲过代码开发的过程中分几种类型。

增删改的需求
Route -> Controller -> Service -> Action
查的需求
Route -> Controller -> Service -> Repository

经过多次实际开发验证后,发现Repository完全是多次一举。所以在这里更正下,取消Repository。

Route -> Controller -> Service
打卡系统逻辑架构图

需求是这样的,用户每天打卡获得积分,积分计入用户账户,并且需记录用户积分的获取及消费情况。如图所示,请求到控制器后,通过控制器去调用服务,服务又调用创建用户打卡模块完成打开,在用户打卡过程中对用户账户积分进行变更及记录用户积分获取记录。

数据表结构 打卡数据表
CREATE TABLE `member_attendance` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `member_id` int(11) NOT NULL COMMENT "用户编码",
  `status` enum("0","1") COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT "0" COMMENT "1签到成功",
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
用户钱包表
CREATE TABLE `wallet` (
  `user_id` bigint(20) NOT NULL COMMENT "用户标示",
  `balance` decimal(12,2) NOT NULL COMMENT "钱包余额",
  `integral` decimal(12,2) NOT NULL DEFAULT "0",
  `add_time` int(11) NOT NULL COMMENT "添加时间",
  `update_time` int(11) NOT NULL COMMENT "更改时间",
  UNIQUE KEY `wallet_user_id_unique` (`user_id`),
  KEY `wallet_user_id_index` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
用户积分交易记录表
CREATE TABLE `member_integral_detail` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `member_id` int(11) NOT NULL COMMENT "用户编码",
  `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT "来源或消费",
  `integral` decimal(12,2) NOT NULL DEFAULT "0.00" COMMENT "积分数",
  `type` tinyint(4) NOT NULL DEFAULT "0" COMMENT "类型 0收入 -1支出",
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
具体业务实现 Route
$api->post ("user/attendance","UserController@attendance");
MemberController
public function attendance()
{
    $result = $this->userService->attendance ($this->request);
            
    if ($result) {
        return $this->response->array (Response::return (200, "打卡成功"));
    }
            
    return $this->response->array (Response::return (0, "打卡失败或已打卡"));        
}
MemberService
public function attendance($request)
{
    return (new CreateUserAttendance())->execute ($request);
}
CreateUserAttendance
public function issetToday($userId)
{
    $result = MemberAttendance::where ([
        ["member_id", "=", $userId],
    ])
        ->whereDate ("created_at", date ("Y-m-d", time ()))
        ->exists ();
    return $result;
}
// -------------------- 上述是下方issetToday方法,写在MemberModel中
class CreateUserAttendance
{
    public function execute($data)
    {
            
        if ((new MemberAttendance())->issetToday ($data->user_id)) {
            return false;
        }
        
        $models            = new MemberAttendance();
        $models->member_id = $data->user_id;
        $models->status    = (string)"1";
            
        $result = $models->save ();
            
        if ($result) {
            (new CreateUserIntegralDetail())->execute ($data->user_id, "打卡", 10, 0);
            return true;
        }
            
        return false;
    }
}
CreateUserIntegralDetail
interface integralDetail
{
    public function execute($userId, $title, $integral, $type);
}
    
class CreateUserIntegralDetail extends UpdateUserWalletIntegral implements integralDetail
{
    public function execute($userId, $title, $integral, $type)
    {
        parent::exec ($userId, $integral, $type);
            
        $models            = new MemberIntegralDetail();
        $models->member_id = $userId;
        $models->title     = $title;
        $models->integral  = $integral;
        $models->type      = $type;
            
        return $models->save ();
    }
}

上述代码继承了更新用户积分的动作,在每次打卡成功后,我们调用父类方法直接更新用户积分。

UpdateUserWalletIntegral
class UpdateUserWalletIntegral
{
    public function exec($userId, $integral, $type)
    {
        if ($type == 0) {
            Wallet::where (["user_id", "=", $userId])->increment ("integral", $integral);
        } else {
            Wallet::where (["user_id", "=", $userId])->decrement ("integral", $integral);
        }
    }
}
致谢

感谢你看到这里,希望本篇文章可以帮到你。有什么问题可在下方评论区留言。谢谢

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29246.html

相关文章

  • Laravel-Action 对代码改造

    摘要:前言以往写过俩篇文章积德篇如何少写烂代码举枪消灭烂代码的实战案例感觉文章中对的操作没有一个规范性的调用及编写。可以选择不声明方法。 showImg(https://segmentfault.com/img/bVbfwa7?w=1076&h=690); 前言 以往写过俩篇文章[积德篇] 如何少写PHP 烂代码 https://segmentfault.com/a/11...举枪消灭烂代码...

    mj 评论0 收藏0
  • [积德篇] 如何少写PHP ""代码

    摘要:但还是不如人意,如果把所有的业务及全部写在中,那只不过是将的臃肿转移到了那就没有什么存在意义了。所以我们需要继续分割,将对数据库的操作独立出来,因为的操作基本是一贯不变的,而操作根据业务的复杂度则变的多姿多彩。 showImg(https://segmentfault.com/img/bVbchg0?w=700&h=267); 写给初生牛犊不怕虎的童鞋们,大佬可随意摘看本章基于PHP ...

    fireflow 评论0 收藏0
  • 使用matplotlib绘制并排柱状图实战案例

      小编写这篇文章的一个主要目的,主要是给大家介绍的内容是使用matplotlib去进行绘制并排柱状图,那么,一个具体的操作实例是什么呢?下面就给大家详细解答下。  一、概念说明  柱状图(bar chart),从相同的横坐标出发,以不同的数值大小来设定柱子的高度,进而表示无序或有序的定性数据间某个定量指标的大小关系。  示意图如下:  (1)在无序的横坐标情景下,我们常常根据数值大小降序排布。 ...

    89542767 评论0 收藏0
  • 漫话:如何给女朋友解释灭霸指响并不是真随机"消灭"半数宇宙人口

    摘要:软件实现的是伪随机数。有限状态机不能产生真正的随机数的。复联中,灭霸打了指响之后,复仇者联盟中存活和死亡的名单其实并不是随机的。可见,灭霸的指响抹除过程并不是随机的。综上,灭霸的指响抹除过程不符合随机性不可预测性以及不可复现性。showImg(https://user-gold-cdn.xitu.io/2019/5/7/16a91fc63239db4d);周末,陪女朋友去电影院看了《复仇者联...

    WalkerXu 评论0 收藏0
  • 如何"有计划,高效率,优简历"应对面试

    摘要:虽然有了十全的计划,但如何高效率去记住上面那么多东西是一个大问题,看看我是怎么做的。 前言 前一篇文章讲述了我在三月份毫无准备就去面试的后果,一开始心态真的爆炸,但是又不服气,一想到每次回来后家人朋友问我面试结果的期待脸,越觉得必须付出的行动来证明自己了。 面经传送门:一个1年工作经验的PHP程序员是如何被面试官虐的? 下面是我花费两个星期做的准备,主要分三部分: 有计划——计划好...

    gyl_coder 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<