程序员如何做事更细致?

最近在工作中老是犯一些小错误,哦,当然也不是最近了,其实我一直是个马虎的人,我很讨厌做一些细活,因为这会让我反复改动多次在会成功,而平时的代码由于有debug,即便出错了,再改回来即可,但是,很多时候并没有我们想的那么容易,趁着周末,我写下了这篇总结,希望也能帮助到大家。

文章目录

  • 1. 需求有没有问清楚?
    • 1.1 多做记录
  • 2. 反复太多
    • 2.1 单元测试
    • 2.2 自测-交叉验证
  • 3. 基础不牢
    • 3.1 常见错误
  • 4. 不守规矩
    • 4.1 事故
  • 5. 慢就是快

1. 需求有没有问清楚?

我们在开发过程中,一个大忌就是需求都没搞清楚,为了能够更快的完成任务,直接上手写代码,没准写到一半发现需求有问题,或者是之前自己没理解好,导致最终出了问题。
在这里插入图片描述

1.1 多做记录

我的建议是,养成记录工作的好习惯,我一般是以导图的形式做一个梳理,比如下图这样子,里面也包含了我周末想做的事,重点关注最后一条即可。

在这里插入图片描述

  • 需求地址:方便我们快速定位到这个需求具体要我们做什么。
  • 思路:大致写下思路,如果你的思路不清晰,写代码一定会被卡住。
  • 伪代码:先用伪代码的形式写一遍,很多东西可以精简下,这样的好处是,会提前碰到那些我们没考虑到的地方。
  • 问题:开发一定会遇到问题,可以在这里做个记录。
  • 代码位置:这是为了便于我们后期有了bug快速定位。
  • 接口请求:可以和下面的测试用例一起用,可以快速debug。
  • 提交记录:为了更快的追踪之前提交的记录,建议复制版本号,因为在idea中如果出现分支合并,很容易找不到提交的记录。

这里不仅包含了写代码前的一些准备工作,也包含了一些开发的小技巧,思路,总的来说就是多记录,当事物繁多时就能体会到好处了。

2. 反复太多

2.1 单元测试

这里的反复是指,明明开发完成了,测试或者上线又出bug了,我们自我测试是必不可少的,推荐自己的代码使用单元测试跑一下,但我知道很多情况下是做不到的,因为公司代码太繁杂了,测试不一定好跑,所以只是做个小小的推荐,这里推荐使用mocktio框架,它可以以插桩的形式将某些service注入进来,完成虚假的调用,我们只需关注自己想关注的部分即可。
在这里插入图片描述

代码示例如下。

service代码

public class UserRepository {
    public User findUserById(String userId) {
        // 数据库逻辑,这里为了简单省略
        return null;
    }
}

public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(String userId) {
        return userRepository.findUserById(userId);
    }
}

测试代码

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

public class UserServiceTest {

    @Test
    public void testGetUserById() {
        // 创建模拟对象
        UserRepository mockRepository = mock(UserRepository.class);

        // 设置模拟行为
        when(mockRepository.findUserById("123")).thenReturn(new User("123", "Test User"));

        // 使用模拟对象创建UserService实例
        UserService userService = new UserService(mockRepository);

        // 调用UserService的方法并断言结果
        User result = userService.getUserById("123");
        assertNotNull(result);
        assertEquals("123", result.getId());
        assertEquals("Test User", result.getName());

        // 验证模拟对象的方法是否被调用
        verify(mockRepository).findUserById("123");
    }
}

2.2 自测-交叉验证

上面的例子很简单,但很多情况下我们求快或者实在搞不了单元测试,那么只能自测了,如果之前写了伪代码,那么将会减少出错的可能性,但这还不够。

这里我是从吴军老师那学到的方法,就是交叉验证,即便我们debug跑下觉得没什么问题,我们也还是应该掌握逆向思维,通过结果,反推值,看是否没问题。

3. 基础不牢

很多时候我们犯错,其实是因为基础不牢导致的,比如下面一些例子,我们就应该警惕。

在这里插入图片描述

3.1 常见错误

  1. 空指针异常(NullPointerException):
    当试图使用一个未初始化(null)的对象时,就会抛出空指针异常。例如,尝试调用一个未实例化对象的方法或访问其属性。

  2. BigDecimal使用浮点数构造器:
    使用new BigDecimal(double)构造函数时,可能不会得到预期的精确值,因为double本身可能无法精确表示。正确的做法是使用字符串构造器,如new BigDecimal("0.1")

  3. 数组越界(ArrayIndexOutOfBoundsException):
    尝试访问数组中不存在的索引时,会抛出数组越界异常。例如,访问长度为5的数组的第6个元素。

  4. 类转换异常(ClassCastException):
    将对象强制类型转换为不兼容类型时,将抛出类转换异常。

  5. 并发修改异常(ConcurrentModificationException):
    在迭代集合时(如使用for-each循环),如果同时对集合进行结构性修改(添加、删除元素),则可能抛出此异常。

  6. String比较使用
    使用
    来比较字符串,这实际上比较的是对象引用,而不是字符串的内容。应该使用.equals()方法来比较字符串的内容。

  7. 忽视了基本类型和包装类之间的区别:
    例如,int和Integer的区别,其中Integer是可以为null的,而int是有默认值0的基本类型。

  8. 不正确的异常处理:
    异常处理不当,如使用空的catch块或仅打印堆栈跟踪而不进行适当处理。

  9. 忽视了Java集合框架中的线程安全问题:
    如在多线程环境下使用非线程安全的集合,如ArrayList和HashMap,而不是线程安全的版本,如Vector或ConcurrentHashMap。

  10. 资源泄露:
    在使用资源(如流、数据库连接等)后没有正确关闭,可能导致资源泄露。

4. 不守规矩

我们会因为自己的熟练,而过度自信,导致一些代码觉得太简单了,肯定不会出问题,最终出现了bug。
或者是自我觉得经验还可以,不听他人的劝告,做一些自认为对的事情,但最终却发现自己走入了一个误区,一开始自己想错了。

这里主要是想给大家提个醒,我们在深入专业的同时,也要保留一份怀疑,开放的态度去听取,挖掘更多的可能性。 下面是一些因为编程不规范导致的事故。

4.1 事故

在这里插入图片描述

  1. Knight Capital Group的交易系统故障(2012年):
    Knight Capital Group由于软件部署错误,导致其交易算法失控。一个旧的、未使用的软件功能被意外地激活,导致公司在不到一小时内损失了约4.4亿美元。这个事件突显了代码管理和部署过程中严格遵守规范的重要性。

  2. Ariane 5 Flight 501失败(1996年):
    欧洲空间局的Ariane 5火箭在首次飞行中因为软件异常而解体。问题源自于64位浮点数在转换为16位整数时未能适当处理溢出。这个错误表明了代码重用时需要考虑上下文的重要性,以及进行充分测试的必要性。

  3. Heartbleed漏洞(2014年):
    OpenSSL的一个严重漏洞,由于未正确检查网络输入的长度,导致攻击者可以读取内存中的敏感数据。这个漏洞凸显了输入验证的重要性以及在安全相关代码中遵守最佳实践的必要性。

  4. Therac-25事故(1985-1987年):
    Therac-25是一台辐射治疗机,由于软件错误,导致至少六名患者接受了过量的辐射。软件的设计和编码错误,包括竞争条件和不充分的安全检查,是导致这些事故的主要原因。

5. 慢就是快

这也是最近才感悟到的东西,很多需求急着上线,但因为没有经过充分的测试,或者是因为时间太赶,代码滥竽充数,cv大法,只为了完成某个功能,看似进度很快,后期又是不停的改bug。

另外一点是最近学习的感悟,我们很容易夸下海口,说我要在一个月完成什么什么事,比如学习完某个课程,或者在新一年的目标中,定下了许许多多想要完成的事,但大多都不了了之。

在这里插入图片描述

为什么会这样呢?

首先一点就是贪,人总是想要事情做的又快又好,想要知识到了我们脑中就能立刻转化为经验,技能,赚到钱。

但现实不是游戏,很多生活中的大改变往往是每日里的点滴努力汇聚而成的,所以不要有急于求成的心态,只想着每天做一点小改变,就像我前面导图中写到的,周末学一节操作系统,不需要多,平时忙的花就花个10分钟看下视频,即便是躺在床上也能完成,稍微做下笔记。

只要这件事情的进度在往前,那么总能够完成的,如果觉得事情太困难了,不仿切割成一个个的子任务,日积月累,总能够有所成效的。

生命中这些不经意的时刻,最后你付出的点点努力,就像遗失在生命中各个角落的弹珠,有一天突然来了一根线,这些弹珠都被连了起来,你突然发现原来它们不是散落的,它们是一条真正的银河。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/164464.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高效背单词——单词APP安利

大英赛,CET四六级,以及考研英语,都在不远的未来再度来临,年复一年的考试不曾停息,想要取得好成绩,需要我们的重视并赋予相应的努力。对于应试英语,词汇量是不可忽略的硬性要求。相比于传统默写&…

SOME/IP 协议介绍(六)接口设计的兼容性规则

接口设计的兼容性规则(信息性) 对于所有序列化格式而言,向较新的服务接口的迁移有一定的限制。使用一组兼容性规则,SOME / IP允许服务接口的演进。可以以非破坏性的方式进行以下添加和增强: • 向服务中添加新方法 …

Node.js环境配置级安装vue-cli脚手架

一、下载安装Node.js (略) 二、验证node.js并配置 1、下载安装后,cmd面板输入node -v查询版本、npm -v ,查看npm是否安装成功(有版本号就行了) 2、选择npm镜像(npm config set registry https://registry.npm.taobao.org&…

笔记55:长短期记忆网络 LSTM

本地笔记地址:D:\work_file\DeepLearning_Learning\03_个人笔记\3.循环神经网络\第9章:动手学深度学习~现代循环神经网络 a a a a a a a a a

如何解决msvcr100.dll丢失问题?5个实用的解决方法分享

在日常计算机操作过程中,相信不少小伙伴都经历过这样一种困扰,那便是某款应用程序或者游戏无法正常启动并弹出“找不到msvcr100.dll”的提示信息。这类问题让人头疼不已,严重影响到了我们的工作效率和休闲娱乐。接下来,就让小编带…

Amazon EC2的出现,是时代的选择了它,还是它选择了时代

目录 Amazon EC2简介 友商云服务器对比(Amazon VS Tencent) 友商云服务器对比(Amazon VS Alibaba) Amazon 云服务器的绝对优势 Amazon EC2功能 Amazon EC2 Linux 实例入门 启动实例 连接到的实例 清除的实例 终止的实例…

2 Redis的高级数据结构

1、Bitmaps 首先,最经典的应用场景就是用户日活的统计,比如说签到等。 字段串:“dbydc”,根据对应的ASCII表,最后可以得到对应的二进制,如图所示 一个字符占8位(bit),…

C/C++关于main函数参数问题

文章目录 前言不带参数的main带参数的main为什么会有带参数的main总结 前言 每次写C/C程序,基本上就是一个int main(){return 0;}。但是后来在linux里面涉及到很多带参数的main函数,我一直不太理解,这里就写篇博客记录一下。 不带参数的main…

浅谈滑动窗口

滑动窗口是什么? 滑动窗口其实是一个想象出来的数据结构。有左边界L和有边界R。 举例来说:数组 arr {3,1,5,7,6,5,8}; 其窗口就是我们规定的一个运动轨迹。 最开始时,边界LR都在数组的最左侧,此时没有包住任何数。 此时规定&…

米家竞品分析

一、项目描述 1. 竞品分析描述 分析市场直接竞品和潜在竞品,优化产品核心结构和页面布局,确立产品核心功能定位。了解目标用户核心需求,挖掘用户魅力型需求,以及市场现状为产品迭代做准备。 2. 产品测试环境 二、市场 1. 行业…

Python将已标注的两张图片进行上下拼接并修改、合并其对应的Labelme标注文件

Python将已标注的两张图片进行上下拼接并修改、合并其对应的Labelme标注文件 前言前提条件相关介绍实验环境上下拼接图片并修改、合并其对应的Labelme标注文件代码实现输出结果 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容&#xff…

【Leetcode合集】2342. 数位和相等数对的最大和

文章目录 2342. 数位和相等数对的最大和方案1方案2方案3方案4 2342. 数位和相等数对的最大和 2342. 数位和相等数对的最大和 代码仓库地址: https://github.com/slience-me/Leetcode 个人博客 :https://slienceme.xyz 给你一个下标从 0 开始的数组 nu…

Ubuntu(Linux)的基本操作

基本操作三步走 1、输入vim code.c点击i(出现insert)表示可以编辑代码编辑代码之后按下esc(退出编辑模式)按下shift:(冒号)wq(退出文件)2、输入gcc code.c(进行编译代码…

为什么求职者反感企业招聘用的人才测评?

为什么求职者会对人才测评的不满?大概率是认为性格测评不能完整的定义人的优势,也就是测不准! 这个想法是对的,性格测评并不能100%的展现一个完整的人,目前没有那个测评的信效度能达到如此理想,估计以后也…

⑩⑤【DB】详解MySQL存储过程:变量、游标、存储函数、循环,判断语句、参数传递..

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ MySQL存储过程 1. 介绍2. 使用3. 变量①系统变…

【kafka】使用docker启动kafka

1.环境准备 docker拉取zookeeper镜像 docker pull zookeeper:3.4.14 创建zookeeper容器,默认端口号为2181 docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14 拉取kafka镜像 docker pull wurstmeister/kafka:2.12-2.3.1 创键kafka容器&#xff…

Linux | C语言中volatile关键字的理解

目录 前言 一、代码引入 二、现象解释 三、具体引用 前言 本章主要讲解介绍volatile关键的作用与使用场合;深刻理解volatile关键字;本文你需要有信号相关的基础知识; Linux | 信号-CSDN博客 一、代码引入 首先,我们来查看下面…

【文末附资料链接】2023年第十三届亚太杯数学建模竞赛(APMCM)优秀参考论文思路指导(持续更新中ing)

一、赛事介绍 数学建模作为一门跨学科的科学,不仅需要对数学知识的熟练掌握,还需要对实际问题的深刻理解和解决问题的创新思维。亚太杯数学建模竞赛旨在激发青年学子的创造力和团队协作精神,培养其在实际问题中运用数学方法解决现实挑战的能力…

介绍交换空间概念以及如何设置交换空间

文章目录 什么交换空间新增交换空间 什么交换空间 交换空间(Swap space)是计算机内存的一种补充,位于硬盘驱动器上。当物理内存不足时,系统会将不活跃的页面移到交换空间中。 交换空间可以帮助系统在以下情况下运行&#xff1a…