热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[译]软件的复杂性:定名的艺术

软件的复杂性:定名的艺术在计算机科学中只要两件难题的事变:缓存失效和定名范例。——PhilKarlton媒介编写优良代码本身是一件很难题的事变,为何这么说?由于优越的编码作风是为了

软件的复杂性:定名的艺术

在计算机科学中只要两件难题的事变:缓存失效和定名范例。
—— Phil Karlton

媒介

编写优良代码本身是一件很难题的事变,为何这么说?由于优越的编码作风是为了能更好的邃晓与浏览。平常我们会只注意前者,而疏忽了后者的重要性。我们的代码虽然只编写一次,然则在浏览复审时会浏览许屡次。

优越的编码习气能够进步我们的浏览质量,比写作本身要轻松很多,我们能够站在宏观角度对待题目,远观大局,而不失细节。起首我们须要邃晓、剖析清楚某个题目,然后用特有的,高效的,一针见血的体式格局让更多人邃晓。对我来讲,应当明白的把软件工程归属到社会科学领域。我们为谁编写代码,岂非不是为了人类吗?(觉得原文作者装的有点过)

向其他人通报我们的主意以及编程头脑,这就是我们在编码时要做的。

定名组织

为了申明我们的第一个看法,起首来做一个游戏,游戏名为 “我们住在哪一个房间?”,以下会为你供应一张图片,请你说说看这是什么房间。

题目 1/3

《[译]软件的复杂性:定名的艺术》

从上面的图片不难看出,这肯定是客堂。基于一件物品,我们能够联想到一个房间的称号,这很简朴,那末请看下图。

题目 2/3

《[译]软件的复杂性:定名的艺术》

基于这张图片,我们能够肯定的说,这是茅厕。
经由过程上面两张图片,不难发明,房间的称号只是一个标签属性,有了这个标签,以至我们不须要看它内里有什么东西。如许我们便能够竖立第一个推论:

推论1:容器(函数)的称号应包括其内部一切元素

能够将这个推论邃晓为 鸭子范例。假如有一张床?那末它就是寝室。我们也能够反过来举行剖析。

题目:基于一个容器称号,我们能够揣摸出它的构成部分。假如我们以寝室为例,那末很有能够这个房间有一张床。如许我们便能够竖立第二个推论:

推论2:依据容器(函数)的称号揣摸其内部构成元素

如今我们有了两条推论,据此我们试着看下面这张图片。

题目 3/3

《[译]软件的复杂性:定名的艺术》

好吧,床和马桶在统一个房间?依据我们的推论,如上图片使我们很难马上做出推断,假如依旧运用上述两条推论来给它下定义的话,那末我会称它为:怪物的房间。

这个题目并不在于统一个房间的物品数目上,而是完整不相关的物品被认作为具有一样的标签属性。在家中,我们平常会把有关联的,企图以及功用邻近的东西放在一同,以防止混淆黑白,所以如今我们有了第三条推论:

推论3:容器(函数)的明白度与其内部组件的亲昵水平成正比

这能够比较难邃晓,所以我们用下面这一张图来做申明:

《[译]软件的复杂性:定名的艺术》

假如容器内部元素属性关联性很强,那末我们更轻易找到一个用来讲明它的名字。反之,元素之间的无关性越强,越难以描述申明。属性维度能够会关系到他们的功用、目的、计谋,范例等等。关于定名规范,须要关联到元素本身属性才有实际意义。随着我的思绪,我们将很快邃晓这一点。

在软件工程方面,这个看法也一样实用。比方我们熟知的 组件函数要领效劳运用。罗伯特·德拉奈曾说过:“我们的邃晓能力很大水平与我们的认知相关联”,那末在这类手艺背景下,我们的代码是不是能够使浏览者以最简朴的体式格局感知到营业需求以及相关诉求?

Example 1:HTTP 域与汽车

HTTP 本身是一个域环境,它包括着我们的收集要求与相应状况。假如我们把一个 Car 的组件放入它的内部,那末我们不能再称它为 HTTP了,在这类情况下,它会变得让人疑心。

public interface WhatIsAGoodNameForThis {
/* methods for a car */
public void gas();
public void brake(); /* methods for an HTTP client */
public Response makeGetRequest(String param);
}

《[译]软件的复杂性:定名的艺术》

Example 2:单词的耦合

有一种罕见的定名形式,在称号时后缀附加上 Builder 或 er 一类的完毕词,比方:SomethingBuilderUserBuilderAccountCreatorUserHelperJobPerformer 等等。

《[译]软件的复杂性:定名的艺术》

比方上图中的名字,我们能够揣摸出三件事变。第一,在类名中运用动词 Build 意味着它是具有功用性的。第二,它由两部分构成,一个是 User 用户,另一个的 Builder 组织者,这意味着它们之间能够在封装、维度归类上存在歧义。第三,Builder 组织者 能够在类内部接见 User 用户 的相关逻辑、数据,由于他们在统一纬度空间内。

这一点与工场形式很相似,有本身的运用场景,当它在我们的工程中众多运用时,这将会是一个很贫苦的题目。别的,须要提示人人,在工场形式中,并不肯定须要有一个类,经由过程一个 createUser 的要领足矣很好的完成工场形式的功用。

Example 3: 基类

让我们先看几个生涯中实在的例子。起首是 i18n Ruby gem(它的类与要领称号都是异常精练)。

class Base
def config
def translate
def locale_available?(locale)
def transliterate
end

这里,Base 这个定名本身并没有转达太多寄义,个中内部结构包括了设置、翻译,地区设置,音译。它们能够看似无关的聚合在一同。

Example 4: 定名与构建

一个合理的定名能够指导我们构建出越发严瑾的组件容器。以下例所示。

class PostAlerter
def notify_post_users
def notify_group_summary
def notify_non_pm_users
def create_notification
def unread_posts
def unread_count
def group_stats
end

PostAlerter 从这个名字本身能够发明,它意味着在内部会做一些相似提示关照的功用。然则,个中 unread_postsunread_countgroup_status 并不在这个功用的重要领域内,从这一点来看,这个类的称号并非很抱负。我们能够将这个三个要领移动到一个名为 PostStatistics 的类中,如许解耦后,事宜功用会变得越发清楚,更可展望。

class PostAlerter
def notify_post_users
def notify_group_summary
def notify_non_pm_users
def create_notification
end
class PostsStatistics
def unread_posts
def unread_count
def group_stats
end

Example 5: 新鲜的定名

在 Spring 框架中有一些例子,组件做的事变太多,其称号都异常冗杂新鲜。这里只举一个例子(由于实在太多了):

class SimpleBeanFactoryAwareAspectInstanceFactory {
public ClassLoader getAspectClassLoader()
public Object getAspectInstance()
public int getOrder()
public void setAspectBeanName(String aspectBeanName)
public void setBeanFactory(BeanFactory beanFactory)
}

Example 6: 说说好的称号

我们聊了很多不太合理的定名,在 D3 的 arc 中就有很多不错的定名定义,比方:

export default function() {
/* ... */
arc.centroid = function() { /* ... */ }
arc.innerRadius = function() { /* ... */ }
arc.outerRadius = function() { /* ... */ }
arc.cornerRadius = function() { /* ... */ }
arc.padRadius = function() { /* ... */ }
arc.startAngle = function() { /* ... */ }
arc.endAngle = function() { /* ... */ }
arc.padAngle = function() { /* ... */ }
return arc;
}

上面这个例子中,每一个要领都是完整有意义的:他们都是以 arc 开首。而且他定名作风就像绘制下面的图片一样精练,使人欢欣。

《[译]软件的复杂性:定名的艺术》

要领 1: 拆解

《[译]软件的复杂性:定名的艺术》

运用场景:当你不能为类或要领找到一个适宜的定名,然则你晓得怎样拆解它们,而且希冀给他们的组合找到一个好的称号。

重要有两个步骤:

  1. 分辨出他们之间的特性和看法

  2. 将它们拆离开

在床和马桶这类特定耦合的场景下,为了拆解他们的差别之处,我们将床移动到左边,将马桶移动到右边。如许我们便将两个差别的事物星散开了。

当你不能为某个事物找到一个好的称号时,或许是由于你所面对的不止一件事物。不过如今我们已晓得,对多个事物举行定名是一件异常难题的事变,当我们碰到这类题目时,无妨确认一下组织这个事物的构成部分,以及行动行动。

事例:

我们现有一个未定名的类,个中包括了 requestreponseheadersURLsbodycachingtimeout,把一切这些从类中拉取出来,我们剩下如许一些组件:RequestResponeHeadersURLsReponseBodyCacheTimeout 等。假如我们已知这些类的称号,那末我们能够肯定这个类是用于处置惩罚 Web 要求的,HTTPClient 是一个不错的 Web 要求组件的定名。

当我们编码碰到难题时,先不要想着团体,先考虑一下部分细节。

要领 2: 发明新看法

《[译]软件的复杂性:定名的艺术》

运用场景:当一个类并不简朴或许内容并不相关。

发明新的看法须要大批营业领域的学问,当软件的定名和营业保持一致时,一个广泛的言语便竖立起来,它许可来自差别专业领域的人来运用雷同的言语。

要领 3: 分组规范

运用场景:当有一个好的定名,然则他们他们之间并不合适。

组件元素之前能够经由过程种种规范举行分组,比如组件元素的物理性质,经济性,情感性,社会性以及软件中最经常使用的功用。

在软件工程中,我们倾向于按功用对组件元素举行分组。假如列出你的项目文件,你能够会看到像 controller/models/adapters/templates/ 等等目次称号,然后,有些时刻,这些称号组合在一同并肯定合适,这也是从新评价模块,从新定义,计划定名的时刻。

每一个运用程序都有本身差别的上下文环境,每一个模块、每一个类、每一个要领也一样都有。User 这个词所代表的寄义能够是操纵系统用户,或是一张数据表,也能够是一个第三方的效劳凭据,差别的上下文环境,它所示意的寄义不尽雷同。

《[译]软件的复杂性:定名的艺术》

无意义的词与新词

多年以来,定名范例的演化上变得更具有意义,有更多的人来弥补这个陈腐的空白。

Helperhelpers 是一个支撑运用程序完成的重要体式格局。运用程序完成与定义的规范是什么呢?运用程序中的一切内容都应当支撑并完成其重要目的。

在实践中,它们被击中在一个非自然的分组中,为一写其他经常使用的操纵供应可重用性。平常情况下,helpers 须要另一个组件元素的内部数据的依靠。这类定名平常会在找不到适宜的称号时折衷运用。

Base,好久之前,在 C# 中有须要继续类的定名体式格局都是以 Base 定名。比方:汽车和自行车的父类都是 Base 而不是 Vehicle。只管微软提出发起去防止这类定名体式格局,但他依旧影响了 Ruby 这门言语,个中最具代表性的是 ActiveRecord 类的继续。到现在为止,我们依旧将 Base 看做为开发人员找不到适宜定名的一种替换体式格局。

更改调解后的 Base 含括了 CommonUtils,比方,JSON Ruby gem 的 Common 类具有 parsegenerateload 以及 jj 等要领,但这里 Common 真的具有它的寄义吗?

Tasks,在 Javascript 社区兴起了一种经由过程异步挪用函数的体式格局,这类体式格局起源于 task.js,纵然现在这个开源库很少再被提运用,然则这个术语撒布了下来。

假如团队中一切人都能清楚的邃晓它的寄义,那是可喜的。但假如有新人到场团队,而且他碰到了被扬弃在垃圾堆中的 60 年代便存在的离奇定名,那又怎么办呢?

在我之前的项目工作中,曾碰到过如许的一个类的定名,你们猜猜看,Atlanta,是的,亚特兰大,操蛋的亚特兰大。没人晓得或许能够告诉我为何要起这么个名字,以及寄义是什么。

参考资料

Cwalina,Krzysztof.2009,框架设想指南:可重用 .NET 库的商定、惯用语和形式,第二版。 Boston: Pearson Education, Inc. 206。

Evans, Eric. 2003。域驱动设想:处理软件中心复杂性。Boston: Addison-Wesley Professional。

原文链接:https://medium.com/hacker-dai…


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了在Java中gt、gtgt、gtgtgt和lt之间的区别。通过解释符号的含义和使用例子,帮助读者理解这些符号在二进制表示和移位操作中的作用。同时,文章还提到了负数的补码表示和移位操作的限制。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有