幽默轻松小知识,一起来看看老弟第一次写的后端代码,你觉得如何?

大家好,我是鱼皮,今天分享我的老弟第一次写后端代码时出现的囧事,希望大家引以为戒。

孽起

我的老弟小阿巴,目前大一,自学编程有一段时间了,之前主要以学前端为主,比较好上手。

但这货最近不知道咋回事,一直嚷嚷着要写写后端代码。

我说:你前端才刚学没多久呢,急什么?

小阿巴说:没人比我更懂前端!

好家伙,没想到几日不见,这家伙现在这么骄傲了!那必须得杀杀他的锐气,让他领略一下后端的恐怖。

于是我说:成,正好我最近在开发一个新功能【删除消息】,功能很简单,允许用户删除自己已经阅读过的消息。前端后端都交给你来做,时间也不急,给你两周,拿去练练手,熟悉下项目吧~

没想到小阿巴这狗说:两周?瞧不起谁呢,就这么一个小功能,我 3 天给你搞定!

我大惊:现在的年轻人都这么强了么?行,我等你!

没想到,不到 3 天,小阿巴真的提交了代码,让我们一起来看看他的实现思路和代码吧。

实现思路

功能实现包括前端和后端两部分,分别来思考一下。

前端

要实现用户已读消息删除功能,前端的工作比较简单,添加一个删除按钮,并且给按钮添加一个点击事件,点击后调用后端 消息删除 接口即可。

前端界面

小阿巴写的前端代码:

<!-- 伪代码 -->
<button onClick={doDelete(消息)}>删除</button>
<script>// 删除消息function doDelete(msg) {// 消息 id 存在且为已读if(msg.id && msg.isRead) {// 调用后端接口service.deleteMsgById(msg.id);}}
</script>

看着好像没啥问题吧,写的还挺工整的,代码规范好评!

再看看后端怎么样。

后端

后端要做的事情就是接受前端发过来的请求,操作数据库,将数据库中指定 id 的消息删除,再返回是否删除成功给前端。

存放消息的数据库

很多编程语言都可以拿来写后端,比如 Java、Go 语言等。但由于小阿巴是第一次做后端,我心疼他,所以让它使用 NodeJS(JavaScript 语法)来写。

看看小阿巴写的后端代码:

// 删除消息接口
// @params msgId 消息 id
function deleteMsgById(msgId) {// 调用数据库删除函数,得到结果const res = db.deleteById(msgId);return res;
}

总共就这么几行代码,简洁清晰,也难怪小阿巴花了 3 天的时间就写出来了。

不知道大家觉得这段代码怎么样,像不像自己第一次写的代码呢?

请大家思考一下,他写的代码有没有什么问题?

分析问题

其实,小阿巴这段代码问题非常大!一旦上线了,后果不堪设想!

主要有三个问题,我把小阿巴叫了过来,要根据问题的严重性从大到小给他盘一盘。

1. 未做校验

我对小阿巴说:再仔细看看你的代码,是不是少了校验逻辑?

小阿巴疑惑:我不是在前端判断消息 id 是否存在、消息是否已读了么?

我:那如果用户不在浏览器里点删除按钮,而是直接请求接口,随便传消息 id 呢?

小阿巴陷入了沉思。

这是第一次写后台的同学经常犯的错误,尤其是前后端都一个人写的时候,以为在前端判断参数是否合法就够了。但其实,恶意用户可不管这么多,他们可以直接用各种工具在浏览器外向你的后端发送请求,随便传一些消息 id,甚至直接遍历可能的 id。如果后端不做校验,一上线,正常用户的消息可能就被删光了!绝对的 最高级事故

小阿巴:没想到这么严重,那我在后台补上对消息状态的校验,好像也不太行吧?毕竟用户可以任意传递请求参数。

我:挺聪明嘛,的确如此,所以我们还要补上对当前登录用户的校验。

完善的代码大致是这样的:

// 删除消息接口
// @params msgId 消息 id
function deleteMsgById(msgId) {// 校验参数合法性if (!mgsId) {return false;}// 从数据库查消息最新状态const msg = db.getMsgById(msgId);// 从 session 或中间件获取当前用户信息const user = getCurrentUser();// 消息未读或不是该用户的消息if (!msg.isRead || !user || msg.userId !== user.id) {return false;}// 调用数据库删除函数,得到结果return db.deleteById(msgId);
}

小阿巴:我记住啦,后端接口是业务核心,一定要加强校验!

我:不错,来看看其他的问题吧。

2. 硬删除

我:在你的代码中,直接调用了 delete 函数直接删除数据,你知道这会有什么问题么?

小阿巴:有啥问题?

我:直接删除数据,会导致管理员在需要排查问题时缺少线索。比如用户发送过违规消息,一段之间后把消息自己删掉了,那管理员也不能查出他的违规记录了。

小阿巴:还真是,那咋办?这数据不能删?

我:一般会采用 软删除,给数据表添加一个额外的字段来表示删除状态,比如 isDelete,状态为 0 表示未删除,为 1 表示已删除。正常情况下,只给用户展示 isDelete = 0 的数据,删除时,将该字段的值从 0 更新为 1 即可。

所以上述代码的最后那部分,可以略作修改:

// 原代码,真实删除
db.deleteById(msgId)
// 新代码,软删除(更新)
db.updateById(msgId, {isDelete: 1})

这样后端代码就基本完善了。

当然,也不是所有的数据表都需要软删除,要根据业务场景来决定。

3. 无防误触

最后还有一个产品体验上的小问题,建议在用户点击删除时,出一个二次确认的弹框,否则用户不小心点错了,想找却又找不回消息,那就会感到愤怒了!

确认删除

前端开发做的越多,就会越注重这些小细节,提升用户体验非常重要!


小阿巴:学到了,学到了!我好菜啊 555。

我:没事,这是很正常的,知错能改,就还是好阿巴。

很多正在阅读文章的朋友们,是否也犯过这些小错误呢?请养成良好的编程习惯,多多检查自己的代码吧!

对了,听说点个 在看,印象更深刻!

往期推荐

被攻击了!

在车上偶遇一位阿里大佬!

刷了 1000 多道算法题,一点心得

前端老弟第一次写后端,崩了!相关推荐

  1. 前端工程师怎么写后端?试试 koa.js + Apache APISIX 吧~

    前言 两年前,我还是一个小白开发者.当时为了上线我开发的一个网站购买了一个学生服务器,并且安装了 linux 服务器的小白之友 宝塔面板 ,相信现在还有很多朋友买到服务器了第一件事就是装个宝塔.在宝塔 ...

  2. 写给刚入门的前端工程师的前后端交互指南

    转自原文 写给刚入门的前端工程师的前后端交互指南 作为刚接触前端的不久的童鞋,大家都会兴奋于CSS和JS所带来漂亮界面,然而,前端工程师除了UI重构外,还有非常重要的职责在正确的区域渲染出服务端的数据 ...

  3. java前端接口怎么写_如何写出优雅的后端API接口?

    目录前言 接口交互 返回格式 控制层Controller 美观优化 优雅优化 实现方案 总结 前言 在移动互联网,分布式.微服务盛行的今天,现在项目绝大部分都采用的微服务框架,前后端分离方式,(题外话 ...

  4. python写网页前端交易rsa加密_Flask框架实现的前端RSA加密与后端Python解密功能详解!...

    本文实例讲述了Flask框架实现的前端RSA加密与后端Python解密功能.分享给大家供大家参考,具体如下: 前言 在使用 Flask 开发用户登录API的时候,我之前都是明文传输 username ...

  5. 关于第一次写项目的总结

    关于第一次写项目的总结 这一周和往常一样,我是在写项目,我想说,我想承认,我写项目的状态是真的不好,所有这次博客,我想反思我自己. 自从写项目以来,我就有各种事情缠身,不能好好的完成项目,不仅每天基本 ...

  6. 【小程序】【Tips】【前端】交互【后端】从Json对象数组里面获取数据的方法 - PHP - JS 的原生方法

    小程序后端和前端之间是通过,json的格式来传数据的,那么,数据如何获取呢?这就分两个部分 1 就是后端到前端 后端我们考虑是PHP环境,前端是JS, 那么在JS里面,很简单: 比如,小程序一般在前端 ...

  7. Web开发之二:什么是前端、什么是后端

    从去年做空间开始,这一年来,一直在提前端和后端这样两个概念,同时,也在小组内推行着技术上的分工,并在开发模式上尝试着创新.在学习了Spring.IBatis之后,对于前端后分工的需求也越来越强烈,所以 ...

  8. 新手须知,前端该如何与后端合作?

    1.前后端分离 前端与后端的分离,能使前端的开发脱离后端的开发模式,拥有更大的自由度,以此便可做前端工程化.组件化.单页面应用等. 2.尽量避免后端模板渲染 web 应用的渲染方式分为服务器端渲染和客 ...

  9. 【spring-boot】前端传图像到后端

    spring-boot+thymeleaf+ajax前端传图像到后端 注意: 前端html 前端js(ajax) 后端controller层 配置文件application.yml 注意: 本文总体上 ...

最新文章

  1. mac怎么用python3.0_怎么在mac中使用python
  2. python 利用正则构建一个计算器
  3. 带有下标的赋值维度不匹配_不稳定的期权时间价值
  4. 虚拟机系列 | JVM类加载机制
  5. python 类函数 实例函数_python_30期【实例函数 类里面的函数】
  6. dbscan和谱聚类_R 无监督聚类算法(1)K-means和层次聚类
  7. Log4Cpp 使用实例
  8. matlab中累乘,numpy中的裁剪、压缩和累乘
  9. 单细胞测序技术(single cell sequencing)
  10. 华为公司内部控制手册(干货)
  11. 惠普HP LaserJet Pro M405d 打印机驱动
  12. Java锁的种类以及辨析(四):可重入锁
  13. 码元携带多少比特信息?波特率和比特率的关系?
  14. 使用Python对excel中的数据进行处理
  15. 读《筚路蓝缕——世纪工程决策建设记述》II
  16. Linux配置JDK环境——步骤详解
  17. RK系列SDK -- dummy codec虚拟声卡注册
  18. ASM Disk Discovery 最佳实践
  19. [小脚本] 基于opencv 的绿幕抠图
  20. 市场28款主流同步整流DCDC芯片横向测评预告---引用嘉立创商城的文章

热门文章

  1. [导入]ASP.NET MVC的WebSite模式(with mvc membership)
  2. WPF DataGrid根据内容设置行颜色
  3. Django之 RESTful规范
  4. Spring实战Day2
  5. 解决 display 和 transition 冲突的问题
  6. Newtonsoft.Json Deserialize Type 或者 同类型 变量 反序列化
  7. JAVA多线程之先行发生原则
  8. effective C++ 条款 3:尽可能使用const
  9. applecare多少钱?_否,AppleCare +无法覆盖丢失或被盗的iPhone
  10. Javascript中数组去重的六种方法