务实 创业_成功软件开发人员的基本务实

务实 创业

每位软件开发人员经过实践检验的实用技巧列表

塞缪尔·克拉拉Samuel Clara)在《 Unsplash 》上写道: “一个人在高高的锯齿状岩石的边缘上高高举起双手

介绍

创造优秀,成功的软件非常困难。 很难!

因此,对于每个程序员而言,重要的是了解,理解和应用基本的软件开发实用程序-实践证明和规则,这些实践和建议已证明了其实用性,并有助于我们在最短的时间内创建最佳的软件。

在本文中,我尝试组装了一组我认为最相关的基本语用学。 如果您是一位经验丰富的程序员,那么您可能对大多数/全部都很熟悉。 如果您错过了一些建议,请留下评论与我们分享。

请注意:

  • 本文的语用是关于设计和编写代码的 。 要使软件开发项目成功,还有其他重要方面(例如良好的用户界面,与人打交道等),但它们不在本文档的范围之内。
  • 以下语用学仅涵盖一般适用的 基本原理。 没有针对特定编程环境(编程语言,库,工具和体系结构)的建议。
  • 如果您着急的话,可以在本文结尾处找到所有语用学的摘要。

提示分为三类:

  • 一般准则
  • 资料设计
  • 编写代码

让我们开始吧。

一般准则
一切都应该尽可能简单,但不要简单! - 艾尔伯特爱因斯坦

简单的工具和概念可以快速理解,易于使用,不易出错,并提高我们的生产力。

我们都喜欢简单。 简约使工作和生活更加愉快。

但是,我们必须意识到过于简单化,正如爱因斯坦美丽的名言结尾所指出的那样。

因此:保持简单,但不要简单!

许多著名人士主张朴素。 这里有一些例子:

“简单性是可靠性的前提。 简洁和清晰...决定成功与失败。 -Edsger W. Dijkstra; 荷兰计算机科学家; “发表声明被认为有害”的作者
“简单是最终的复杂程度。” —未知
“简单将普通变成惊人。” -斯科特·亚当斯; 迪尔伯特的创造者
“如果您不能简单地解释它,那么您将无法理解得足够。” - 艾尔伯特爱因斯坦; 物理学家; 天才
“真理总是在简单中找到,而不是事物的多重性和混乱性。” - 艾萨克·牛顿; 数学家 天文学家; 神学家; 作者兼物理学家
如果注定要失败,那就“快速失败!”

大多数软件项目失败。 这是一个令人遗憾和不可否认的事实。

如果一个项目被认为失败了,那么它应该尽可能快地失败,以限制损失并为(希望)不会失败的其他项目腾出时间和资源。

在这种情况下, 快速失败意味着应该尽快发现并处理问题 。 我们等待解决问题的时间越长,就会浪费更多的时间,精力和资源。 累积损耗随时间呈指数增长。

例如,在设计阶段纠正设计缺陷既容易又便宜。 但是一旦该软件投入生产并为许多人所使用,修复该错误通常非常昂贵且令人沮丧。

“我们'失败'越早,学习越快,成功的机会就越大。 早日失败可以节省您的时间和金钱。” -Demian Borba; Adobe产品经理
“快速测试,快速失败,快速调整。” —汤姆·彼得斯; 畅销书《追求卓越》的作者
力争“足够好”,而不是“完美”。 然后释放!

除非我们正在做一个非常小的项目,否则创建完美的软件(没有错误,完全实现所有功能,优化用户界面,出色的文档等)非常耗时且昂贵。 在大多数情况下,由于实际限制,无法实现完美。

即使是软件行业中拥有最佳开发人员和梦想预算的主要参与者,也无法编写完美的软件。 这就是为什么他们不断提供补丁程序和新版本的原因。

因此,请按照以下步骤操作:

  • 设定目标和优先事项
  • 创建一个原型
  • 提供“足够好”的软件
  • 持续改进(见下一项)
“您不能编写100%完美的代码。 即使您这样做,也不会在6个月内完美。” 克里斯·麦德 CodeProject的联合创始人
“在计算机的简要历史中,没有人编写过一款完美的软件。” -安迪·亨特(Andy Hunt)作家; 《实用程序员》的合著者
“现在交付的功能的90%比从未交付的功能的100%要好。” 布莱恩·W·克尼根(Brian W. 计算机科学家和作家; Unix的共同开发者
寻找完美的解决方案通常会导致停滞和沮丧。 毅力,对完美的包容,对改进的追求以及对竭尽所能的承诺,这些都是健康的,并且最有可能产生最佳结果。” —艾伯特·埃利斯(Albert Ellis); 心理治疗师
听用户的话!

实践表明:

  • 软件开发人员无法预期用户真正想要的一切。
  • 用户通常不确切知道他们想要什么,除非他们使用该软件已有一段时间。
  • 用户的满意度是软件成功的决定因素。

我们希望用户满意。 因此,最好的方法是这样的迭代方法:

“在花了很多时间尝试一些营销技巧之后,他(Stack Exchange的共同创始人,Joel Spolsky)得出结论(5年后):没有什么比改善产品更好的了。 制作人们想要的出色软件,并不断对其进行改进。 与您的客户(用户)交谈并倾听。 找出他们的需求。” -预订“编码员在工作”
“……我们为每个主要产品功能构建原型。 我们很早就在实施之前先与预发布用户和主要客户进行了测试。 是的,我们经常“失败”,这太好了! 太好了,因为我们在此过程中学到了很多东西,从长远来看将失败的风险降到最低。 最后,我们以创新的方式同理心地满足实际客户需求。” -Demian Borba; Adobe产品经理
“提早发布,经常发布。” — 维基百科
“程序的最重要属性是它是否达到了用户的意图。” —托尼·霍尔(Tony Hoare); 电脑科学家; 1980年ACM图灵奖
资料设计
在编写代码之前,请仔细设计数据!

每当您创建应用程序时,首先要仔细设计数据结构及其关系。 在编写代码之前执行此操作。

精心设计的数据结构可导致代码更简单,更可维护,错误更少,性能更高且内存消耗更少。

差异可能是惊人的。

“研究后的研究表明,最优秀的设计师可以更快,更小,更简单,更清晰地创建[数据]结构,并且花费更少的精力。 伟大与一般之间的差异接近一个数量级。” —弗雷德·布鲁克斯; 书“没有银弹”
“告诉我您的流程图(代码)并隐藏表(数据结构),我将继续感到困惑。 给我看你的表(数据结构),我通常不需要你的流程图(代码)。 他们将很明显。” —弗雷德·布鲁克斯; 本书“神话中的月人”
“表示规则:将知识整合到数据中,因此程序逻辑可以是愚蠢且健壮的。 数据占主导。 如果您选择了正确的数据结构并组织得当,那么这些算法几乎总是不言而喻的。 数据结构而不是算法是编程的核心” — Unix编程的艺术
“我非常支持围绕数据设计代码,而不是相反地设计代码。 糟糕的程序员会担心代码。 好的程序员担心数据结构及其关系。” 莱纳斯·托瓦尔兹 Linux的创造者
“如果正确地使用了数据结构及其不变式,那么大多数代码将自行编写。” -彼得·德意志(Peter Deutsch); 本书“编码员在工作”
除非有充分的理由使它们可变,否则请使所有数据结构不可变!

不可变的数据结构更易于理解,使用更简单且更不易出错,因为:

  • 创建后,状态将不再更改。 没有状态转换,没有临时无效状态,也不需要同步,锁定或防御性复制。
  • 不变的数据可以在并发/并行计算环境中自由共享-不存在损坏数据,死锁或其他很难解决和修复的棘手问题的风险。
  • 基于不可变数据的计算结果可以轻松地缓存以提高性能。

但是,不可变的数据结构并不总是最佳选择。 例如,为每个更改克隆整个结构可能会非常昂贵(在时间和空间上)。 在某些情况下(例如游戏或GUI应用程序),可变数据结构更适合。

此外,如果两个对象需要直接相互引用,则这些对象(其中至少一个)必须是可变的。 例如,树中的父子节点直接相互引用,共同的朋友(A指向B,B指向A)等。如果在这种情况下必须保留不变性,则可能的解决方案是具有描述这些关系的附加数据结构,例如一组表示彼此相关的对象的元组。

将允许值的集合限制为最小的值!

限制数据类型的允许值集:

  • 文档并帮助理解数据类型
  • 消除了由于错误的值而导致的行为不当或严重故障的风险
  • 简化了必须处理数据的代码

例如,考虑数据类型为employeename字段的情况。 通过允许将任何字符串存储在name ,可能发生以下情况:

  • 长字符串可能导致缓冲区溢出(取决于编程语言),内存耗尽或其他软件故障。
  • 名称中无效但在Javascript和SQL中用作有效符号的字符(例如<>" )可以为诸如SQL和/或脚本注入之类的攻击打开大门。
  • 如果代码未明确正确处理这些值,则null字符串或null字符串可能会导致错误。

为避免这些风险,应限制name字段。 例如,以下简单的正则表达式消除了上述所有问题:

[a-zA-Z ]{1,70}

此正则表达式将名称限制为最多70个字符,至少需要一个字符,并且只能使用字母和空格。 但是,请注意,上述正则表达式将过分简化,不适用于必须允许名称包含连字符,撇号和其他符号的现实生活中。

保护数据免受无效值影响(尤其是从外部源读取数据时)是编写安全软件的最重要规则。 (例如,请参阅OWASP十大关键Web应用程序漏洞十大安全编码实践

尝试以数据输入形式进行SQL注入的示例:

JavaScript注入尝试的示例:

大多数情况下,默认值应该是允许值集中最严格的值。

通过选择尽可能严格的值作为默认值,我们始终处于安全状态。

应该(在代码中,在配置文件中等)明确声明更多允许值。

例如:

  • 默认情况下,写入文件的功能不应覆盖现有文件。
  • 默认情况下,应启用所有编译器警告。
  • 如果在多用户应用程序中添加了新用户,则默认情况下应授予最低特权。

最后一个示例说明严格的默认值并不总是最佳选择。 他们可能很烦人。 如果多用户应用程序仅由一个人在其PC上使用,则该用户显然希望默认具有完全权限。 因此,最佳默认值有时取决于几个因素。

GUI中严格的默认值示例:

避免数据冗余!

将可变数据的副本存储在不同位置容易出错,费力且昂贵,因为:

  • 在数据更改的情况下,由于健忘,技术问题,安全问题等,存在无法更新所有位置的风险。这可能导致数据不一致和损坏,并最终导致严重的软件故障。
  • 有时需要为每次数据修改(创建,更新和删除操作)实现并激活锁定/同步机制,以避免在数据修改过程中访问无效数据。 实施这些机制可能非常棘手且容易出错。
  • 需要额外的内存来存储副本。

普通的例子:推销员错过了重要的约会。 原因:他将约会输入到PC上的日程中,但忘记了将数据与手机上的另一个日程同步。 如果两个议程的数据都存储在一个地方(例如,存储在云中),那么他将不会错过他的约会。

考虑使用通用的标准化格式将数据存储在简单的文本文件中!

使用文本文件作为存储媒体有很多优点:

  • 所有操作系统均完全支持文本文件。 无需安装和配置其他软件,例如数据库服务器。
  • 文本文件可以很容易地被人阅读和操纵。 这对于调试目的非常方便。
  • 许多第三方应用程序(以任何编程语言编写)和工具也可以轻松读取和操作它们。 例如,Unix提供了许多有用的文本处理工具,例如grep,awk,sed等。
  • 使用JSON,XML和CSV等标准格式,可以由许多现有应用程序查询,排序,过滤,搜索,打印和转换数据。 例如,可以在电子表格应用程序中轻松使用CSV文件。

但是,文本文件也有严格的限制,特别是在大数据的情况下。 复杂的查询(带有过滤器和联接),更新和删除操作,事务处理,数据加密和其他功能可能需要手动实现,并且效率很低。 当涉及大数据时,将其存储在数据库中通常是唯一可行的选择。

此外,将数据存储为字符(而不是位)会消耗更多的空间和时间。 因此,二进制数据有时是不可避免的。

使用文本表示图形的一个很好的例子是SVG (标量矢量图形)。

这是SVG文件( SVG_example.svg )的简单示例:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
width="140"
height="140" >
    <circle cx="70" cy="70" r="40" stroke="red" stroke-width="4" fill="yellow" />
</svg>

打开文件(例如,使用Web浏览器)将显示以下图像:

“编写程序来处理文本流,因为这是一个通用接口。” -道格·麦克罗伊; Unix管道的发明者
“ Unix传统强烈鼓励编写程序来读写简单的,文本的,面向流的,与设备无关的格式。” 埃里克·史蒂文·雷蒙德 Unix编程的艺术
编写代码
编写漂亮的代码!

漂亮的代码简短,简单,易于理解,模块化,可扩展,可靠且可维护。

漂亮的代码很少需要注释,并且像散文一样读起来。

开发人员喜欢查看并使用漂亮的代码。 这使他们感觉良好

编写精美的代码是一门艺术 ,需要热情,坚定的承诺和多年的实践。

“出色的软件需要对美丽的狂热奉献。 如果您查看好的软件,就会发现没人能看到的部件也很漂亮。” -Paul Graham, 黑客和画家
“当前的开发速度取决于过去的开发质量。” —布赖恩·麦卡利斯特(Brian McCallister)
“应该编写程序供人们阅读,而只是为了使机器能够执行。” -阿伯森和萨斯曼; 《计算机程序的结构和解释》一书
“由于维护是如此重要且昂贵,因此编写程序就好像它们进行的最重要的通信不是与执行它们的计算机,而是与将来将要阅读和维护源代码的人(包括您自己)进行的通信。” — Unix编程的艺术
“始终编写代码,好像最终维护您的代码的人将是一个暴力的精神病患者,知道您的住所。” 约翰·伍兹
“您始终可以通过真理的美丽和朴素来认识真理。” -理查德·费曼(Richard P. Feynman); 物理学家
尽可能使用现有软件!

不要重新发明轮子!

在编写新代码之前,请确保所需的功能尚不存在。

查看现有的库和框架(可能以不同的语言编写),工具,其他应用程序和云服务,以找到所需的内容,或者获得想法并获得启发。

例如,Unix提供了许多强大,可靠和灵活的即用型工具(也可在Windows上使用)来进行文本操作。 如果合适,请在您的应用程序中使用它们。

“…库代码可能比您自己编写的代码更好,并且随着时间的推移可能会有所改进。 ......库代码受到的关注远远超出了大多数开发人员能够致力于相同功能的程度。'' —约书亚·布洛赫(Joshua Bloch); 本书“有效的Java”
“您应该研究您的库,并努力避免无故重新发明它们,以使您的代码简短易读,使您的生活愉快而富有成效。” 亨利·斯宾塞; C程序员的十诫
“最好的代码就是根本没有代码。” —杰夫·阿特伍德
“如果我比别人看到的更多,那就是站在巨人的肩膀上。” - 艾萨克·牛顿; 数学家 天文学家; 神学家; 作者兼物理学家
失败而喧闹!

尽早发现并修复问题!

这有助于最小化开发时间和成本,并降低生产模式下的故障和损坏风险。

应自动检测最大数量的错误。 这可以通过智能IDE,编译器,静态代码分析器,模糊测试器等来实现。自动检测到的错误很容易被发现,并且不会投入生产并引起故障。

编写好的单元测试。

在运行应用程序之前未发现的错误以及所有种类的运行时问题(例如,找不到文件,无效的输入数据等)应在运行时尽早检测到。

因此,请检查所有输入的有效值(函数自变量,用户输入,资源输入等)。 检查所有返回值以了解错误情况。

如果无法很好地处理运行时问题,则应用程序应通过以适当的方式报告问题(即,使用有助于解决问题的最大信息)来持续应用“ 快速失败”原则,然后立即中止操作。 这很重要,因为:

  • 在开发模式下,它可以帮助调试,因为一旦出现问题,应用程序就会发出严重的崩溃
  • 在生产模式下,它导致应用程序崩溃,通常比静默继续运行更糟糕,并导致更糟糕的结果,例如错误的数据,错误的决策等。

这是错误HTML代码可能发生的情况的示例,因为应用快速失败原理:

而不是显示以下救生警告...

…显示一条危及生命的消息:

有关上述结果的解释(以及有关如何快速失败的更多建议),请阅读“快速失败!简介”。 软件开发中的原理 (提示:HTML代码中只是缺少的>字符)。

最终, 故障快速原则有助于在更短的时间内编写更可靠,更安全的代码

因此,更喜欢支持Fail-fast原理的编程语言,库,框架和工具。

“修复您所能做的-但是当您必须失败时,请尽量避免嘈杂。” — Unix哲学; 维修规则
“如果通告某个函数在遇到困难时返回错误代码,那么您应该检查该代码,是的,即使检查代码的大小是您的代码的三倍并在您的打字手指上产生疼痛,因为如果您认为“不可能发生在我身上”,诸神必因你的傲慢而惩罚你。 亨利·斯宾塞; C程序员的十诫
“您在编写新代码之前会修复错误吗?” 乔尔·斯波斯基(Joel Spolsky); Joel测试:改进代码的12个步骤
每个软件组件都应该很小,并负有单一责任。

小型,单一职责的组件对组件的作者和用户都有好处。

  • 对作者的好处:它们更易于编写,测试和维护。 它们不太容易出错,并降低了可靠性(耦合)。
  • 对用户的好处:它们更易于理解和使用。 它们可以更灵活地与其他组件结合。 如果需要,可以更轻松地用其他实现替换或扩展它们。

整体的力量是许多简单的组件无缝地协同工作的结果。

“编写通过干净接口连接的简单零件。 让每个程序都做好一件事。” — Unix编程的艺术
“我养成了编写非常小的函数的习惯。” —马丁·福勒(Martin Fowler); 功能长度
不要过度设计!

抵制增加将来可能使用的功能的诱惑。

每个功能都会增加复杂性,并增加发生故障的风险。 每个功能都需要时间来创建,测试和维护。

而且,通常很难预见到以后会真正需要的功能,尤其是在需求频繁变化的项目中。 添加永远不会使用的功能是没有意义的。

记住:保持小巧简单!

在思考“我们还能添加什么?”之前,问自己“我们能去除什么吗?”

“如有疑问,请排除在外。 如果有API设计的基本定理,就是这样。 它同样适用于功能,类,方法和参数。 API的每个方面都应尽可能小,但不能更小。 您以后总是可以添加东西,但不能将它们拿走。” —约书亚·布洛赫(Joshua Bloch); 如何设计好的API以及为何如此重要
“实现完美,不是在没有其他可添加的东西时,而是在没有其他东西可取的时候。” —圣艾修伯里安托万
为了获得知识,每天都要增加东西。 为了获得智慧,请每天清除事物。” —老子
“ YAGNI:您将不需要它。” —极限编程原理 维基百科
仅在必要时进行优化!

与其编写“运行速度更快的智能代码”,不如编写运行速度足够快的简单,正确且可维护的代码。

该方法应为:

  • 编写完成任务的简单代码
  • 如果 (且仅 )存在性能问题,则:
  • 衡量性能以可靠地找到瓶颈(不要猜测!)
  • 优化需要更快运行的代码

别忘了:不良的性能通常仅是不良的数据结构,不良的代码和/或不良的体系结构的结果。

“过早的优化是万恶之源。” —唐纳德·克努斯(Donald Knuth); 《计算机编程艺术》的作者
“使其运行,然后使其正确,然后使其快速。” 肯特·贝克 极限编程的创造者
急于在发现瓶颈之前进行优化可能是唯一破坏了更多特征而不是特征蠕变的错误。 从折磨的代码到难以理解的数据布局,到处都是以透​​明和简单为代价的对速度,内存或磁盘使用的迷恋。 它们产生了无数的错误,并耗费了数百万个工时,通常只是为了获得使用某些资源的边际收益,而这些资源的花费远低于调试时间。” — Eric Steven Raymond Unix编程的艺术
自动执行重复任务!

一次又一次地执行相同操作容易出错,适得其反,令人厌烦,并增加了不执行重要任务(例如单元/集成测试,备份等)的风险。

使用您可以获得的最佳工具来执行常见任务,例如编写/编辑代码,处理文件等。

力求执行一次单击或什至更好地自动运行的计划任务。

自动执行任务通常很容易。 创建小型脚本(以您的首选语言编写或使用OS脚本编写),使用诸如AutoitSelenium之类的自动化工具,或使用任何其他最合适的工具来快速自动化您或您的用户的重复任务。

“优先使用工具而不是非熟练的帮助来减轻编程任务,即使您不得不绕开构建工具并希望在使用完毕后将其中的一些工具丢弃。” -道格·麦克罗伊; Unix管道的发明者
“经济规则:程序员的时间很昂贵; 优先考虑节省机器时间。” — Unix编程的艺术
“您能一步一步完成吗?” 乔尔·斯波斯基(Joel Spolsky); Joel测试:改进代码的12个步骤
乐在其中!

流程(心理学)在Wikipedia中描述如下:

“流……是一种精神状态,在这种状态下,执行一项活动的人会完全沉浸在活动过程中充满活力的专注,全神贯注和享受的感觉中。 从本质上讲,流动的特征是完全吸收了自己的行为,并因此而丧失了空间和时间感。”

处于流程中(也称为在区域中以hack模式 )可能导致幸福感状态,需要体验才能理解。 流可能是程序员曾经在一个论坛上写道的原因:“我想编写代码,编写代码,直到死亡。”

对于程序员而言,最好在以下条件下实现流程:

  • 没有干扰 ,例如打来的电话,电子邮件,任何其他类型的通知,噪音等。
  • 手头的编程任务是值得且具有挑战性的,但并不是太困难
  • 在开始编码之前,您必须清楚地看到

“清楚看”是什么意思? 闭上你的眼睛。 您能看到整体情况,数据结构及其关系,功能及其相互作用吗? 必须首先消除疑虑-通过使用纸和铅笔,搜索网络,寻求帮助,编写小的测试代码片段或进行其他适当的操作来消除疑虑。

现在可以看清楚了吗? 然后开始编码并充分享受吧!

摘要

以下是所有语用学的摘要:

一般准则
  • 一切都应该尽可能简单,但不要简单! - 艾尔伯特爱因斯坦
  • 如果注定要失败,那就“快速失败!”
  • 力争“足够好”,而不是“完美”。 然后释放!
  • 听用户的话!
资料设计
  • 在编写代码之前,请仔细设计数据!
  • 除非有充分的理由使它们可变,否则请使所有数据结构不可变!
  • 将允许值的集合限制为最小的值!
  • 大多数情况下,默认值应该是允许值集中最严格的值。
  • 避免数据冗余!
  • 考虑使用通用的标准化格式将数据存储在简单的文本文件中!
编写代码
  • 编写漂亮的代码!
  • 尽可能使用现有软件!
  • 失败而喧闹!
  • 每个软件组件都应该很小,并负有单一责任。
  • 不要过度设计!
  • 仅在必要时进行优化!
  • 自动执行重复任务!
  • 乐在其中!

翻译自: https://hackernoon.com/fundamental-pragmatics-for-successful-software-developers-79a9d327f430

务实 创业

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值