平庸程序员的各种迹象

2023-11-07 07:30
文章标签 程序员 迹象 平庸

本文主要是介绍平庸程序员的各种迹象,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1.无法从集合的角度思考

从命令式编程过度到函数式和声明式编程,会立刻要求你思考将数据集合当作原语来操作,而不是作为标量值。无论你在关系型 数据库(并且不是作为一个对象仓库)中使用 SQL,还是设计规模会随多处理器线性变化的程序,亦或是你写的代码必须要在拥有 SIMD 能力的芯片(比如现代显卡和电子游戏机)上执行,都需要这种过渡。

特征

只有在带有声明式或函数式编程特性(程序猿应该知道这些特性)的平台上看到这些特征时,下面列出的才算数。

  1. 在 for 或 foreach 的循环里对集合中的每个元素执行原子操作。
  2. 写的 Map 或 Reduce 函数里包含自定义的循环,在循环里逐一重复执行数据集。
  3. 从服务器抓取大量数据集,并在客户端上计算和,而不是在查询里使用聚集函数。
  4. 函数作用于一个集合中的每个元素,并在函数开头通过执行一次新的数据库查询来抓取一个关联记录。
  5. 写的业务逻辑函数,例如更新一个用户界面或执行文件 I/O,很不幸地为了某种折衷而伴随有副作用。
  6. 在实体类打开专属的数据库连接或文件操作符,并且在每个对象的生命周期里都保持连接状态。

补救措施

非常有趣,想象着一个发牌的人通过手指在牌里翻转把一副牌切成两堆交叉洗牌,就能让大脑联想到集合,以及如何成批地操作集合。激发人联想的其他想象还有:

  • 高速公路上的车流通过一系列收费站(并行处理)。
  • 泉水汇聚成溪流,溪流又汇聚成小河,最后再汇聚成江河(并行分解/聚集函数)。
  • 一个报纸印刷机(协同程序、流水线)。
  • 夹克上的拉链头把拉链齿拉上(简单的联结)。
  • 转移 RNA 加上氨基酸,并在一个核蛋白中加入信使 RNA,就变成了蛋白质(多阶段函数驱动联结,详见 animation)。
  • 在一棵橘子树中,数以亿计的细胞里同时发生着上述的过程,不断地将空气、水和阳光转换成橘子汁(大型分布式集群上的 Map/Reduce)。

如果你正在写一个处理集合的程序,思考一下所有的附加数据和记录,你的函数需要操作它们的每一个元素。并且在 Reduce 函数应用到每对数据上之前,使用 Map 函数把它们成对地联结在一起。

2.缺乏批判性思维

除非你能批判自己的思维并从中找出缺陷,否则你会错过那些可以在敲代码之前就能解决的问题。如果你也无法评判自己曾经写过的代码,那你只能在不断摸索中以龟速学习。这个问题同时来源于思考怠惰和以自我为中心,因此,这个问题的特征似乎也来自两个不同的方向。

特征

  1. 自制“业务规则引擎”。
  2. 静态工具类很冗余且庞大,或者多学科的函数库只用一个命名空间。
  3. 把各种应用糅合在一起,或给当前的应用附加不相关的特性来避免启动新项目的开销。
  4. 程序架构开始需要建立 epicycle 模型。(译者: epicycle 模型是天文学上使用的模型,用来解释天体在运动过程中出现的偏差等异常行为。)
  5. 为了很不相关的数据向表中添加字段(比如:在通讯录的表中放置“# cars owned”字段)。(译者:通讯录的内容要记录是否有车干嘛,确实扯远了。)
  6. 前后矛盾的命名规范。
  7. 处于“拿着锤子看什么都是钉子”的心态,或者改变对问题的定义,这样所有问题都能用某个特定的技术来解决。
  8. 编写程序降低问题的复杂度。
  9. 从病理上冗余地防御式编程(“企业级代码”)。
  10. 用 XML 重新发明 LISP。

补救措施

从Paul 和 Elder 写的《批判性思维 | Critical Thinking》这样的书入手,控制自我意识,在向朋友或同事发表自己的想法以此寻求评论时,练习抵制为自己辩护的冲动。

一旦你习惯了别人来检验你的想法,你就会开始自我审视并练习想象这些想法的结果。另外,你也需要培养起区别轻重缓急的能 力(能直觉知道对这种规模的问题,需要花费多少精力比较合适)、用实践验证假设的习惯(这样你就不会高估问题的大小)和面对失败的健康心态(就算艾萨克. 牛顿的地心引力说是错的,但我们依然爱他并需要他去尝试)。

最后,你必须自律。意识到计划里有缺陷不会让你更高效,除非你有足够的意志力去改正缺陷,并重建手中正在进行的工作。

3.弹球式编程

如果你把面板倾斜得刚刚好,把曲柄拉回到刚好的距离,并且以正确的顺序击中那些凸起的按钮,那么程序就会像弹球一样运行无误:随着指令的执行流程,从条件语句返回,跳过未选中的指令,转向下一次的状态转换。

特征

  1. 用一个 try-catch 代码块包围 Main() 的整个函数体,并在 Catch 分句中重置整个程序(像弹球地沟,掉下去以后重新开始游戏)。
  2. 在强类型的语言中,用字符串或整型来存储那些拥有(可以用)更合适封装类型的值。
  3. 把复杂数据打包成带分隔符的字符串,然后在使用它的每个函数里解析一遍。
  4. 对输入有歧义的函数,不会用断言(assertion)或方法协定(method contract)。
  5. 使用 Sleep() 来等待另一个线程完成任务。
  6. 对非枚举类型的值使用 switch 语句,而且分支语句中没有“Otherwise”分句。
  7. 用 Automethods 或 Reflection 来调用在非法的用户输入中提到的方法。
  8. 在函数里通过设置全局变量来返回多个值。
  9. 类里有一个方法和几个字段,通过设置字段来为方法传递参数。
  10. 不用事务来更新多行数据库内容。
  11. 孤注一掷(比如,试图不用事务和 ROLLBACK 来恢复数据库的状态)。

补救措施

把程序的输入想象成水。它即将流过每一个缝隙,灌满每一个容器。那么你要想一想,如果它流过的地方并没有明确创建任何东西去呈接它的话,会造成什么后果。

你要让自己熟悉平台的机制,这有助于写出健壮且易扩展的程序。共有三种基础机制:

  1. 当某种意外发生时,能在产生任何破坏之前停止程序,然后帮助你识别出是哪里出错了(类型体系、断言、异常等)。
  2. 将程序的执行导向处理意外最佳的代码块( try-catch 模块、多重分发、基于事件驱动编程等)。
  3. 暂停线程直到一切就绪(WaitUntil 命令、互斥锁和信号量、同步锁等)。

还有第四条,单元测试,你可以在设计阶段使用。

使用这些机制应该成为你的第二天性,就像在句子里用逗号和句号一样。为了做到这些,每次浏览一遍上面介绍的机制(括号里 提到的那些),并重构你的旧程序,把提到的这些机制塞到任何能塞的地方,就算最后发现这么做并不合适(尤其是在它们看似不合适的时候,至少那时你也开始明 白其中的缘由)。

4.不熟悉安全原则

如果要说下述特征并不很严重,但它们几乎是大部分程序都存在的整体质量问题。意思是说,这些特征不会让你成为一名很糟糕的程序猿,只是意味着你不应该从事网络程序或安全系统的工作,直到你已经在这方面做了一些功课。

特征

  1. 以明文形式存储可利用信息(名字、卡号、密码等)。
  2. 用低效的加密术存储可利用信息(将密码编译在程序中的对称加密算法;简单密码;任何“解码环( decoder-ring )”、自创加密算法、专有的或未验证的加密算法)。
  3. 在接受网络连接或解释来自非置信源的输入信息之前,程序或设备没有限制它们的权限。
  4. 不进行边界检查或输入合法性验证,尤其是在使用非托管类的语言时。
  5. 把不合法或非转义的输入串接到字符串上来构建SQL查询。
  6. 调用用户输入中指定的程序。
  7. 试图通过搜索已知漏洞的签名(signature)来阻止漏洞被利用。
  8. 用不加盐的哈希值(unsalted hash)存储信用卡卡号或密码。

补救措施

下面只涵盖了基本原则,但遵照这些原则会避免绝大多数臭名昭著的错误,那些错误可以让整个系统大打折扣。对于任何处理或存储有价值信息的系统,无论是向你还是其用户,或是控制一个贵重资源的系统,它们通常都有一个安全专家来审查系统的设计与实现。

从审查程序开始,找出用数组或其他配置内存的容器来存储输入的代码,确保这部分代码检查了输入的大小不会超出分配给它的 内存大小。没有其他类型的 bug 能比缓冲区溢出更能导致可利用的安全漏洞。从某个层面来说,在写网络通信程序或任何安全第一的场合下,你应该认真考虑使用某种内存托管型的编程语言。

下一步,审查数据库查询操作。审查那些将未修改输入串接到 SQL 查询内容中的查询操作,并且,如果平台支持的话就切换为使用参数化查询,如果不支持就对输入进行过滤或转义。这么做是为了防止 SQL 注入攻击。

在你清除了这两类最臭名昭著的安全 bug 之后,你应该继续将所有的的程序输入视为完全不可靠,或是有潜在恶意。按有效的验证规则来定义程序的输入很重要,而且除非输入能通过验证,否则程序应该拒 绝它,这样你就能够通过修复验证方法并使其更加明确来修复可利用的漏洞,而不是通过扫描已知漏洞的签名来修复漏洞。

进一步说,你应该总是在开始设计程序之前,思考程序需要执行的操作以及这些操作需要从 host 获得什么样的权限,因为这个时候是想出怎么样能尽可能使用最少权限的最佳时机。这条建议背后的原则是,如果在你的代码中找到一个可利用的 bug ,限制这个bug可能对系统其他部分造成的损害。换言之:在你学会不信任输入之后,你也应该学会不要信任自己写的程序。

最后你要学会的是数据加密基础,从《Kerckhoff’s principle》开始。这一点亦可表达为“安全第一”,从中还衍伸出了一些有趣之处。

原则一,永远不要信任一个密码或其他加密原语,除非它已经被公开发表,并且已经由更高级别的安全社区对其进行了全面的分 析和测试。从密码学的发展来看,模糊晦涩的加密法、专有的加密法或是新出现的加密法都毫无安全可言。即使是可信的加密原语,其实现中也会存在缺陷,因此, 对于你不能确定其已经得到全面审查的加密算法(包括自己实现的版本),要避免使用。所有的新型加密系统都要经过一系列的详细审查,这个过程可能长达十年之 久,或更长,而你只要关注那些最后经受住了审查并且所有已知错误都已修复的加密系统。

原则二,如果密钥容易破解或存储失当,那这和完全不加密一样糟糕。如果程序要对数据加密,但不需要解密或很少需要解密,那就考虑只把对称加密密钥对的公钥给它,并让解密阶段和私钥分开运行,用户必须每次输入一个好的口令来确保密钥的安全。

越是处于危险之中,你需要做的功课越多,并且必须在程序的设计阶段投入更多精力。这都是因为一旦你的程序部署下去,就会有成堆、有时候可能是成千上万的不速之客试图去破坏它的安全性。

绝大部分可追溯到代码问题的安全故障都归因于一些很愚蠢的错误,其中大部分错误可以通过筛选输入、谨慎使用资源、利用常识、想清楚再写代码等方式来避免。

5. 代码一塌糊涂

特征

  1. 不遵循一贯的命名规范。
  2. 不使用缩进,或缩进不一致。
  3. 不使用空格,例如在方法之间不加空格(或表达式里不加空格,看“ANDY=NO”)。
  4. 有一大堆被注释掉的代码。

补救措施

程序猿在匆忙之下(或特殊情况下)犯了上述所有毛病的话,会在之后返回来清理,但一个糟糕的程序猿真的就只是粗心大意。 有时,利用可通过快捷键来修复缩进和空格(“美观的格式”)的 IDE 是很帮助的,但我发现程序猿总是把代码搞得一团糟,极大地违背 Visual Studio 对适当缩进的坚持。

转载于:https://my.oschina.net/u/2822116/blog/697366

这篇关于平庸程序员的各种迹象的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/362129

相关文章

LabVIEW程序员是怎样成长为大佬

成为一名LabVIEW编程领域的“大佬”需要时间、实践、学习和解决复杂问题的经验。尽管LabVIEW作为一种图形化编程语言在初期可能相对容易上手,但要真正成为精通者,需要在多个层面上深入理解。以下是LabVIEW程序员如何逐步成长为“大佬”的路径: 1. 打好基础 LabVIEW的大佬们通常在初期会打下非常坚实的基础,理解LabVIEW编程的核心概念,包括: 数据流编程模型:Lab

程序员必备心理学——心流

心理学之心流 前言一、“心流”是什么?二、心流的好处二、如何进入心流心流状态的四个阶段第一个阶段:挣扎第二个阶段:放松第三个阶段:心流第四个阶段:巩固 进入心流的技巧 总结题外话 前言 你是否常常感觉自己明明学习了一整天,但是就是感觉没有太多的收获。这个时候除了你的学习方向等问题之外,也可能是你的学习方法太低效了。作者本人就经常有这种情况,好在偶然间在b站刷到一个大佬的这个心

程序员都在使用的画图工具

大家好,我是袁庭新。 程序员都在使用的画图工具,你一定没用过这款画图工具吧!我教程中的架构图都是用它来画的。 比如我编写的RDB工作原理图就是用draw.io绘制的,如下图所示: 再例如Redis集群故障恢复原理图我也是通过draw.io工具绘制的,如下图所示: 是不是觉得draw.io绘制的图形特别简洁、美观。它的官网是: https://www.drawio.com dra

GitHub:代码是程序员沟通最直接的手段

如果不是 Andreessen horowitz 的投资,估计 GitHub 很难被福布斯、CNN、纽约时报等传统媒体注意到。普通大众之前不了解这个工具,是因为它距离记者的世界太远了——GitHub 是一个程序员所使用的托管项目的服务。 但在一些程序员眼里,它不仅是托管项目的地方,还是“开源”项目的大本营,而且是提高程序员“技术水平”和“技术品味”的地方,更是一个程序员社交的地方。

黑马程序员---银行业务调度系统

模拟实现银行业务调度系统逻辑 需求分析: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。 异步随机生成各种类型的客户,生成各类型用户的概率比例为:         VIP客户 :普通客户 :快速客户 =  1:6:3。 客户办理业务所

黑马程序员---空中网面试题

空中网4k/5k月薪挑选大四实习生的线程题     两年前,我们一个大四的学员去应聘空中网的实习生职位,空中网只给他出了三道线程题,拿回家做两天后再去给经理讲解,如果前两题做好了给4k月薪,第三道题也做出来的话就给5k的月薪。这样的实习薪水和招聘要求,不需要有工作经验的限制,纯粹是技术功底的比拼和考核,而不像许多其他公司非要招两年工作经验的人,逼得那些刚毕业和未毕业的大学生不得不去撒谎,不得不去做

黑马程序员---线程并发库

软件包 java.util.concurrent 在并发编程中很常用的实用工具类。 请参见:            描述 接口摘要BlockingDeque<E>支持两个附加操作的 Queue,这两个操作是:获取元素时等待双端队列变为非空;存储元素时等待双端队列中的空间变得可用。BlockingQueue<E>支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及

黑马程序员---多线程

TraditionalTread 传统线程技术回顾 创建线程的两种方式: thread3中,同时创建了Thread的子类和Runnable,那么会优先执行Thread的子类,因为Runnable的代码被当做参数传到了Thread类里,Thread子类的run方法又覆盖了父类的方法,所以会执行Thread子类的代码。 package cn.itcast.heima;public class T

黑马程序员---代理

分析代理类的作用与原理及AOP的概念 代理的概念与作用  1.已经写好一个类,现在要为这个类增加一些功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等,你准备如何做? 现在我们写一个代理类: 保持了原来那个类的功能,又增加了你现在需要的功能。 主函数调用的时候,直接调用代理类就行了。 这就是代理类的功能。   2.编写一个与目标类具有相同接口的代理类,代理

黑马程序员---类加载器

------- android培训、java培训、期待与您交流! ----------   简要介绍什么是类加载器和类加载器的作用 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader   类加载器也是Java类,因为其他是java类的类加载器本身也要被