• 回忆初学编程的糗事:愚蠢的代码也是宝贵的学习经验



    在这里插入图片描述

    每日一句正能量

    需做白日梦。你要清楚地知道你到底是谁,要去哪里。要成为一个什么样的人,很多人浑浑噩噩,得过且过。你能清楚地意识到,或者梦想去到达彼岸,有时候,人生境遇就是如此,轻而易举滴到达你的彼岸。

    前言

    学习编程是一件充满挑战和收获的事情,尤其是在刚刚开始学习的时候,总是会犯下一些奇怪、愚蠢的错误。回过头来看自己当初写的代码,或许会觉得很无语,但这些错误也是我们成长进步的一部分。因此,本文将分享我在刚开始学编程时所犯下的一些错误和愚蠢的代码,以及我如何从中吸取经验教训,进一步提高自己的编程技能。

    常见的错误

    这个在之前的博客里面也写过了一些,没看过的可以先看看:

    在刚开始学习编写代码的时候,我写过不少自己觉得非常愚蠢的代码,但是这些代码也是我的成长之路上的一部分。通过这些错误,我不断地学习并提高自己的编程技能。

    回忆起自己最初写的代码,最让我觉得愚蠢的应该是一个简单的加法程序。当时我还没有掌握如何从用户输入中获取数据,于是我的机智的做法是将变量名设置为“input”并赋值为用户输入的值。这个做法虽然可以让程序运行,但是完全没有任何意义,而且后来发现这样做还会引起其他问题,因为“input”是Python的内置函数。

    下面是那个愚蠢的代码片段:

    input = input("请输入一个数字:")
    input = int(input)
    
    num1 = input
    num2 = 5
    sum = num1 + num2
    
    print("结果为:", sum)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    此外,还有一次我写的一个求阶乘的程序,程序中有一个无限循环,每次执行循环体时都会重复计算一遍阶乘,最后导致程序一直无法结束,我只能通过强制结束程序才能停止循环。

    代码片段如下:

    num = int(input("请输入一个数字:"))
    result = 1
    
    while True:
        for i in range(1, num+1):
            result = result * i
            
        print("结果为:", result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这些错误让我意识到了自己需要更加仔细地思考和规划代码,以避免出现这样的错误。同时,也让我更加珍惜正确的编程思路和规范的编码习惯。

    除此之外,我还通过制作流程图和使用其他调试工具提高了自己的技能水平。例如,使用PyCharm等集成开发环境来调试代码,以及使用Python中的pdb模块来进行代码调试。

    下面就列举出一些常见的简单错误。

    1. 拼写错误

    拼写错误似乎是最简单的错误,但是在代码中这种错误往往会导致程序运行失败。比如,我曾经在Python中写下这样的代码:

    pront("Hello World!")
    
    • 1

    这里面的错误就是拼写错误,正确的函数名是print,而不是pront。这个错误导致代码无法正确执行。

    1. 语法错误

    语法错误是指程序中的语句结构违反了编程语言规定的语法规则。这种错误也很容易发生,比如,我曾经在Java中写下这样的代码:

    if (i = 10) {
        System.out.println("i = 10");
    }
    
    • 1
    • 2
    • 3

    这里面的错误就是在if语句中使用了赋值语句,应该使用比较操作符来进行比较。因此,正确的代码应该是:

    if (i == 10) {
        System.out.println("i = 10");
    }
    
    • 1
    • 2
    • 3
    1. 变量错误

    变量错误是指程序中变量的命名或使用不当。这种错误往往会导致程序执行失败或者是程序执行结果与预期不一致。比如,我曾经在C++中写下这样的代码:

    int x = 10;
    int y = 5;
    int z = x * x + y * y;
    cout << "z = " << x * x + y * y << endl;
    
    • 1
    • 2
    • 3
    • 4

    这里面的错误就是输出时使用了x * x + y * y,而没有使用变量z,因此输出的结果与预期不一致。

    1. 算法错误

    算法错误是指程序中算法的设计不够合理,导致程序出现错误或者效率低下。比如,我曾经在Python中写下这样的代码:

    n = 10
    fact = 1
    for i in range(n):
        fact = fact * i
    print("10! = ", fact)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里面的错误就是计算10!的时候,没有将n的值修改为10,因此计算结果是0。

    还有一些离奇的其他的错误,例如:
    在这里插入图片描述

    总之,我的编程之路是充满挑战和收获的,尽管曾经也写过愚蠢的代码,但这些错误让我更好地了解编程,也让我不断地成长和进步。

    总结

    一般来说,创作一篇高质量的文章不易,因为它需要反复推敲研究,而高质量的代码也不例外。

    编写高质量代码是这样一个流程:思考、调研、规划、编写、验证、修改。(貌似没办法编成一个好记的顺口溜)

    按照这样的思路走,你会逐渐形成良好的编程习惯。

    新手最大的错误之一就是太急于写代码,而缺乏足够的规划和研究。虽然对于编写小程序而言是没多大问题的,但对于大项目的开发,这样做是很不利的。

    为了防止代码写完之后发现重大问题,写之前的深思熟虑是必不可少的。代码只是你想法的流露。

    以下是一些错误的做法,通常会使代码变得更糟糕(只举了一部分例子):

    • 复制代码。如果你贪图省事而复制代码,那么,只会让代码更加混乱。就好比,要在混乱的房间中,添加一把新椅子,而不是调整现有椅子的高度。因此,头脑中始终要有抽象的概念,并尽可能地去使用它。

    • 不使用配置文件。如果你的某个值在不同时间、不同环境下是不一样的,则该值应写入配置文件中。或者,你需要在代码中的多个位置使用某值,也应将它写入配置文件。这样的话,当你引入一个新的值时,只需要问自己:该值是否已经存在于配置文件?答案很可能是肯定的。

    • 使用不必要的条件语句或临时变量。每个if语句都包含逻辑上的分支,需要进行双重测试。因此,在不影响可读性的情况下,尽量避免使用条件语句。与之相关的一个错误就是,使用分支逻辑来扩展函数,而不去引入新函数。每当你认为你需要一个if语句或一个新的函数变量时,先问问自己:是否在将代码往正确的方向推进?有没有站在更高的层面去思考问题?

    不写测试

    我认同这一点:如果你自认为是专家,且有信心在不测试的情况下编写代码,那么在我看来,你就是个新手。

    如果不编写测试代码,而用手动方式测试程序,比如你正在构建一个Web应用,在每写几行代码后就刷新并与应用程序交互的话,我也这样做过,这没什么问题。

    但是,手动测试代码,是为了更明确如何在之后进行自动测试。如果成功测试了与应用的交互,那就应该返回到代码编辑页,编写自动测试代码,以便下次向项目添加更多代码时,自动执行完全相同的测试。

    毕竟,作为人类,每次更改代码后,难免会有忘记去重新测试曾经成功过的代码,所以,还是把它交给计算机完成吧!

    如果可以,就在编写代码之前,先猜测或设计测试的过程。测试驱动开发(TDD)这种方法不仅仅是流行,它还能使你对功能的看法发生积极的变化,以及为它们提供更好的设计方案。

    TDD并不适合每个人,每个项目,但是,至少要会用它。

    沉迷于性能优化

    在编程中过早优化是万恶之源(至少大部分是)。——Donald Knuth (1974年)

    自从Donald Knuth发表了以上观点之后,编程就发生了很大的变化,至今为止,我认为这个观点都是有价值的。

    记住一条好的规则:如果你不能有效地量化代码中的问题,那就别试图去优化它。

    如果在执行代码前已经在优化了,那么你很可能过早的进行了优化,这是完全没必要的,只是在浪费时间。

    当然在你写新代码之前一些明显需要优化的内容还是要考虑优化的。例如,在Node.js中,你要确保你的代码中没有泛滥的使用循环或阻止调用堆栈,这些是非常重要的,这是你必须牢记要提前优化的一个例子。所以在编写过程中,可以时常问问自己:我准备写的代码会阻止调用堆栈吗?

    应该避免对任何不能量化的代码进行任何不明显的优化,否则反而会不利。可能你认为你这样做会带来性能上的提升,但事实上这会成为新的不可预料的bug来源。

    因此,不要浪费时间去优化那些不能量化的性能问题。

    不以最终的用户体验为目标

    在应用程序中添加特性最简单的方法是什么?从你自己的角度看,或许是看它如何适应当前的用户界面,对吧?如果这个功能是要捕获用户输入的,那么把它加到已有的那些表单中。如果这个功能是要添加一个页面链接,那就把它加到已有的嵌套链接菜单中。

    不要自以为是。要站在终端用户角度来开发,这样才是真正的专业人员。这样的开发者才会去思考有这个功能诉求的用户需要什么,用户又会如何操作。而且他们会考虑如何能让用户更便捷地找到和使用这个功能,而不是只考虑如何在应用程序中添加这个功能,而不考虑这个功能的可发现性和可用性。

    工作时没有选对适合的工具

    每个人在完成编程的相关活动中,都有一套自己喜欢使用的工具。其中有一些很好用,也有一些不好用,但是大多数工具只是对某一项特定任务很棒,而对其他任务来说都没有那么好。

    如果要把钉子钉在墙上,锤子确实是把好工具,但如果要用锤子来旋螺丝钉,那就是很糟糕的工具了。不能只是因为你“喜欢”锤子,就用它来旋螺丝钉。也不能因为锤子是亚马逊中最受欢迎的工具,用户评价得分5.0,就用它来旋螺丝钉。

    根据受欢迎程度来选择工具,而不是针对问题的适用性来选择工具是新手的一个标志。

    对于新手而言,另一个问题是:你也许根本不知道对一项特定工作来说什么工具“更好”。在你当前的认知范围内,也许某一种工具就是你所知道的最好的工具。但是,跟其他工具相比时,它并不是首选。你需要熟悉所有可用的工具,并且对刚开始使用的新工具保持开放的心态。
    一些程序员是拒绝使用新工具的,他们对于现有的工具很满意,而且他们可能也不想去学习任何新的工具。我明白,我也能理解,但是这显然是不对的。

    工欲善其事,必先利其器。你可以用原始工具建造一个小屋,并享受你的甜蜜时光;你也可以投入时间和资金去获得好工具,这样你就可以更快地建造一座更好的房子。工具是不断更新的,而你也需要习惯去不断学习并使用它们。

    不理解代码问题会造成数据问题

    一个程序非常重要的一方面就是某种格式数据的管理,该程序将是添加新记录、删除旧记录和修改其他记录的界面。

    程序的代码即使有一点点的小问题,都会给其管理的数据带来不可预估的后果,尤其当你所有的数据验证都是通过那个漏洞程序完成时,则更是如此。

    当涉及到代码和数据的关系时,初学者可能不会立即将这些点联系起来。他们可能觉得在生产中继续使用一些错误代码也是可以的,因为特征X是不用运行的,它没那么重要。但问题是错误代码可能会不断地导致数据完整性问题,虽然这些问题在一开始的时候并不明显。

    更糟糕的是,在修复漏洞时,并没有修复漏洞所导致的细微的数据问题,就这样交付代码只会积累更多的数据问题,且这样的问题会被贴上“不可修复”的标签。

    那么如何避免让自己发生这些问题呢?你可以简单地使用多层次的数据完整性验证,不只依赖于单个用户界面,应该在前端、后端、网络通信和数据库中都创建验证。如果你不想这么做,那么请至少使用数据库级别的约束。

    要熟练掌握数据库约束,并学会在数据库中添加新列或新表时使用它们:

    • NOT NULL是对列的空值约束,表示该列不允许使用空值。如果你的应用程序中设定某个字段必须有值,那么在数据库中它的源数据就应该定义为not null。

    • UNIQUE是对列的单一约束,表示在整个表中该列不允许有重复值。比如,用户信息表的用户姓名或者电子邮件字段,就适合使用这个约束。

    • CHECK约束是一个自定义表达式,对于满足条件的数据,计算结果为True。例如,如果有一列值必须是介于0到100之间的百分比,则可以使用CHECK约束来强制执行。

    • PRINARY KEY(主键)约束表示某一列的值必须不为空,且不重复。你可能一直在用这个约束,数据库中的每个表都必须有一个主键来识别不同的记录。

    • FOREIGN KEY(外键)约束表示某一列的值必须与另一个表的某一列值相匹配,通常来说外键约束也会是主键约束。

    对于新手来说,另一个与数据完整性相关的问题是缺乏对事务处理(transactions)的思考。如果多个操作需要更改同一个数据源,且它们相互依赖时,则必须把它们包装在一个事务当中,这样当其中一个操作失败时就可以进行回滚。

    等等。

    后记

    回顾自己刚开始学编程时写下的愚蠢代码,我不禁感慨:成长之路总是充满坎坷和困难。然而,这些代码的存在也正是我不断学习和进步的重要标志。通过反思自己的错误,找出问题所在,并将其改正,我逐渐成为了更加熟练的编程人员。因此,我希望我的故事能够给那些刚开始学习编程的人一些启示,即使出现困难或是写下了愚蠢的代码也不要气馁,要坚持练习和学习,成为一名优秀的程序员。

    转载自:https://blog.csdn.net/u014727709/article/details/133361764
    欢迎start,欢迎评论,欢迎指正

  • 相关阅读:
    深度详解Java序列化
    recaf反编译 java jar包
    49 - 多态的概念和意义
    MySQL-3(9000字详解)
    带你了解极具弹性的Spark架构的原理
    Unity自定义属性面板Inspector面板和userData数据保存
    备战数学建模41-蒙特卡罗模拟(攻坚战5)
    花好月圆│以代码寄相思,绘嫦娥之奔月
    前端知识案例103-javascript基础语法-throw抛出日常
    Mysql 45讲学习笔记(三十四)join
  • 原文地址:https://blog.csdn.net/u014727709/article/details/133361764