by Martin Fowler
在Ruby群体中徘徊了一段时间,我发现”人性化接口“这个词多次被提及。这个词描述了部分Ruby人对于写类接口的看法,我认为这也在两种API的设计想法之间建立起一个有趣的对比(另一种是”最小化接口“)。
人性化接口的本质在于找出人们想做什么,然后设计出接口,这样可以非常方便的实现基本功能。
它和最小化接口有一个显著的差异,那就是人性化接口倾向于做的很庞大,的确,人性化接口的设计者对于接口会变得过于庞大一点都不担心。这并不是说拥有人性化接口的类一定要象它所表现出的那么庞大。事实上,两种设计的基本功能通常是非常相似的。
这儿有个好办法可以清楚看出人性化接口和最小化接口的不同──比较Java和Ruby的list组件。Java有一个声明了25个静态方法的接口(java.util.List),而Ruby则拥有一个定义了78个方法的Array类(这是个list而不是数组)。两者在大小上的差异在于它们的线索拥有不同的风格(虽说有很多原因可以用来解释这个不同)。两者的组件都提供了相同的基本服务,然而,Ruby的数组包含了许多额外的功能。这些功能都是些相对来说比较小的东西,而它们同样也可以在Java的最小化接口上建立起来。
我们来通过一个小例子来表现这种不同:获取一个线性表的最后一个元素。
用Java我们可以这样做:
aList.get(aList.size - 1)
用Ruby我们这样做:
anArray.last
事实上更令人吃惊的是:Ruby的数据还有个first方法,于是,与其用anArray[0]表示数组首元素,还不如用anArray.first表示。
其实还有更加多变的功能。Ruby的数组有个flatten方法,可以将嵌套数组转换成为一元数组:
irb> [1,2,[3,4,[5,6],7],8].flatten
=> [1, 2, 3, 4, 5, 6, 7, 8]
这儿的要点在于,所有这些功能,不论是简单如last,还是复杂如flatten,都可以由使用者自己写,而不必增加list类的长度。最低限要求者倾向于把注意力集中在通过必要方法的最小化集合来支持这些行为,而人性化接口的设计者们则试着加入尽可能多的用的着的方法。通常这些额外的方法都被归类为辅助方法,而在最低限要求者们看来,这些功能不值得他们去补充。
现在引出了一个问题:如何决定某个方法是否应该被加入到人性化接口中去?如果你把什么都放进去,那么你将得到一个非常复杂的类。人性化接口的设计者们尝试着判别哪些最常用的功能,然后根据这些判断来设计接口,使它们更方便使用。
这些原则不仅规定了你将加入哪些方法,同时它也影响到你对于这些方法的命名。在RubyConf大会上,Tanaka Akira先生提出了为普通方法命以简短名称的意义。用的越多,你就对它们越熟悉──要记得一个简单的名字非常方便,而且也保证了代码的读写的流畅性。例如,从语法上来看,DateTime是默认的对于日期的格式化方法,而更加灵活的strptime方法能够将时间以任意形式表现出来,但这个方法并不常用。
这个命名原则与最低限要求者的方法并不冲突。确实,在Java的List接口出现时,它改变了遗留元素在方法上的获取。
Ruby的人性化接口哲学造就的另一个有趣的结果就是别名的使用。当你想获得一个线表的长度时,你应该使用length还是size?有些库使用其中一个,有些使用另一个,而Ruby的数组两种都用,互为别名,而且两者都能够生成相同的代码。Ruby人的观点是:与其告诉方法库的用户去记住应该使用哪一个,不如两者都可用。
你可能会对哪一种接口设计风格更好这个问题感到厌烦。下面,我试着概括一下人性化接口的好处(如果你想要了解最小化接口,反过来看就行了)。
大多数对象的能力取决于它的行为,而非数据。如果你只是试着提供最小化实现,那么你将为了实现一些普通的功能而针对不同用户写大量重复的代码。万一遇到象flatten这样复杂的功能,用户大概只能够自己去写递归函数了,虽然并不难,但为什么要用这么个不是问题的问题去烦扰用户呢?
即使对于像last一样简单的方法,用户都需要学习一门“方言”。为什么一个简单可读的方法,用户却不能直观的看清它们呢?好的软件总是优先考虑用户的感受,让它们绝对生活很简单。人性化接口就遵从这些原则。
人性化接口做了很多事,当然这些事用不着用户操心了。尤其是API的调用,这就像是普通工作一样简单——不论是读还是写。
其实两种风格都各有好的方面。我个人比较倾向于人性化接口,虽然我也知道它实现起来更加困难。
补充:
这个问题引发过一阵轰动,也因此有了一些有趣和有用的讨论。在之前的一些时候,我可以把链接放出来并写一些评论来帮助阅读,但现在我仅仅把它们列出来而不做评论。争论大多是由Elliotte Harold的一篇对于人性化实现途径的简短而火药味十足的批评文章,以及James Robertson对这篇文章的回复引起的(最好还是亲自去看看Robertson的帖子)。接下来争论就像洪水一样泛滥开来:| Cees de Groot | Antonio Vieiro | David Hoefler | James Higgs | Peter Williams | Cedric Beust | John D. Mitchell | Stuart Roebuck | Elliotte Harold (2) | Jon Tirsen | Hitesh Jasani | Blaine Buxton | Ramnivas Laddad | Anders Noras | James Robertson (2) | Kieth Ray | James Robertson (3) | Elliotte Harold (3) | Charles Miller | Rob Lally | Bernard Notarianni | David Crow | Jim Weirich | Jim Weirich (2) | Ian Bicking | Brian Foote | Justin Gehtland | Tom Moertel | Antonio Vieiro (2) | Kris Wehner | The Server Side | Ravi Mohan | Danny Lagrouw | Piers Cawley | Peter Williams | Florian Frank | Chris Siebenmann。
其实还有更多,我并没有把它们的观点全部整理起来,我只是把我认为有意思的观点放进辩论中,而不希望出现谩骂的现象。讨论中,有人过于关注Ruby Array对Java List的例子,而忽略了根本的原则,当然,这也是很自然的。讨论有许多不错的方向,如果有机会的化我会试着引导其中的一二。
或者你也可疑读读Joey deVilla的文章,他的文章囊括了以上大多数的观点。
原文:
http://martinfowler.com/bliki/HumaneInterface.html
HumaneInterface
by Martin Fowler
5 December 2005 Reactions
(Updated [frequently] with links at end.)
Hanging around the ruby crowd for a while, I've come across the term 'Humane Interface' quite a bit. It describes part of the rubyist attitude to writing class interfaces, I think it also sets up an interesting contrast between two schools of thought in designing APIs (the other is the MinimalInterface).
The essence of the humane interface is to find out what people want to do and design the interface so that it's really easy to do the common case.
The obvious contrast to a minimal interface is that humane interfaces tend to be much larger, and indeed humane interface designers don't worry too much about the interface being big. This isn't to say that classes with humane interfaces need be larger in terms of implementation. The fundamental functionality of the two is often quite similar.
A good way of looking at the difference between humane and minimal interfaces is to compare the list components in Java and Ruby. Java has an interface (java.util.List) which declares 25 instance methods. Ruby has an Array class (which is a list not an array) that has 78 methods. That difference in size is something of a clue of that there's a different style here (although there's more reasons for that difference). Both components offer the basic same service, but Ruby's array includes a lot of additional functionality. This functionality is all relatively small things that can be built on Java's minimal interface.
Let's take a small example to help show the difference: getting the last item on the list. To do this in Java you do:
aList.get(aList.size -1)
in Ruby you do
anArray.last
In fact it's even more startling than that: Ruby's Array has a first method too, so rather than going anArray[0] you can go anArray.first.
There's larger elements of functionality as well. Ruby's Array has a flatten method that takes nested arrays and turns them into a single level.
irb> [1,2,[3,4,[5,6],7],8].flatten
=> [1, 2, 3, 4, 5, 6, 7, 8]
The point here is all of this functionality, whether as simple as last or as complex as flatten, can be written by clients themselves without increasing the size of the list class. Minimalists tend to focus on the minimal set of necessary methods to support these behaviors, humane designers try to add methods that are needed. Often these extra methods are referred to as convenience methods, a term that minimalists do not consider to be a complement.
This begs the question: "what's the basis for deciding what should be added to a humane interface?" If you put in everything anyone might want you'll get a very complex class. Humane interface designers try to identify what are the most common uses of a class, and design the interface to make these uses easy.
Not just does this principle inspire the methods you add, it also affects how you name them. At RubyConf, Tanaka Akira pointed out the value of preferring short names for common methods. Since these are used more often you get familiar with them - it's easy to remember brief names if you use them a lot, also it's more useful since it saves typing and reading. An example of this is the parse method on DateTime that does a default parse of common date formats and the more flexible strptime that can take any format, but you use less often.
This principle of naming isn't in conflict with the minimalist approach. Indeed when Java's List interface appeared it changed the legacy Vector's elementAt method to get.
Another interesting consequence of ruby's humane interface philosophy is the aliasing method names. When you want the length of a list, should you use length or size? Some libraries use one, some the other, Ruby's Array has both, marked as aliases so that either name calls the same code. The rubyist view being that it's easier for the library to have both than to ask the users of a library to remember which one it is.
You can get long and tiresome threads about which style of interface design is best. Here I'll try to summarize the arguments in favor of the humane interface (see MinimalInterface for the other side).
Much of an object's strength lies in its behavior, not its data. If you only try to provide the minimum, you end up with multiple clients duplicating code for common cases. In cases like flatten you end up with a bunch of people writing their own recursive functions. It's not hard, but why should they bother when it's not that rare a case?
Even for simple cases like last, readers have to learn an idiom. Why should they have to see something indirect, when a simple method reads directly? Good software thinks of the users first and makes life easy for them. Humane interfaces follow that principle.
Humane interfaces do more work so that clients don't have to. In particular the human users of the API need things so that their common tasks are easy to do - both for reading and writing.
There are good arguments on both sides. Personally I lean to the Humane Interface approach, although I do think it's harder.
Follow Ups
This one caused a bit of stir, which has led to some interesting and useful discussion. At some point I might put some narrative over the links to help you read them, until then I'll just list them. The debate was mostly triggerred by Elliotte Harold's short but robust criticism of the humane approach and James Robertson's reply (make sure you check the comments on Robertson's posts). Then came the deluge | Cees de Groot | Antonio Vieiro | David Hoefler | James Higgs | Peter Williams | Cedric Beust | John D. Mitchell | Stuart Roebuck | Elliotte Harold (2) | Jon Tirsen | Hitesh Jasani | Blaine Buxton | Ramnivas Laddad | Anders Noras | James Robertson (2) | Kieth Ray | James Robertson (3) | Elliotte Harold (3) | Charles Miller | Rob Lally | Bernard Notarianni | David Crow | Jim Weirich | Jim Weirich (2) | Ian Bicking | Brian Foote | Justin Gehtland | Tom Moertel | Antonio Vieiro (2) | Kris Wehner | The Server Side | Ravi Mohan | Danny Lagrouw | Piers Cawley | Peter Williams | Florian Frank | Chris Siebenmann .
There's more too, I haven't spotted them all and I've only gone for those that I think add something interesting to the debate and avoid invective. There's been a tendency to over-focus on the Ruby Array vs Java List example rather than the underlying principles, but that's natural. There have been a number of good directions the discussion is going, if I get chance I'll try to develop one or two of them.
Or you could just read Joey deVilla - who includes excerpts from most of the above.
---------爱与和平的分割线---------
第一次翻译,所以...很囧
orz
分享到:
相关推荐
因此,具有人性化接口的报警系统成为了解决这一问题的关键。这样的系统不仅包含了基础的安全功能,如防火、防盗、煤气泄漏检测以及紧急求助,还引入了微机管理和智能控制网络技术,能够自动对多种意外情况进行快速...
5. **人性化接口**: 这意味着库的设计考虑到了开发者的使用体验,提供了直观且易于理解的API。例如,可能有链表或树状结构来表示JSON对象,以及易于操作的函数接口。 6. **错误处理**: ezJSON库应当提供良好的错误...
然而市场上出现的各类家庭安全报警系统功能虽较齐全,但并不完善,明显的不足之处就是报警号码都是预先存入,而且没有提供人机交互功能,用户如因特殊情况需更换报警电话号码时往往无能为力,其设计显然不够人性化,...
总结来说,"USB 之人性化介面裝置的報告描述元"涉及的主题涵盖了USB接口如何支持人机交互设备的工作,特别是通过报告描述符来定义设备行为和功能。研究这些文档可以帮助我们更深入地理解USB技术,尤其是对于HID设备...
平台的设计还体现了结构简单、成本低的优点,并具有人性化接口,便于操作和功能的进一步开发。通过采用FPGA,智能吸尘平台的集成度被降低,开发者可以在现有基础上增加更多功能,如环境感知、路径规划和数据通信等。...
传统的监控系统通常依赖于PLC,但随着微处理器技术的进步,尤其是嵌入式技术的广泛应用,现在可以设计出集本地监控、人性化接口、无线通信和GPS定位于一体的移动设备监控系统。 系统的核心是ARM微处理器,这里选用...
此外,机器人设计中还采用了人性化接口设计,所有接口都可以通过端子接线引出,使用方便。 2. 喷泉系统水泵控制技术: 喷泉系统通过水泵电机的转动产生能量差值,推动水柱连续不断地压入和流出,形成稳定的流量。...
3. **用户接口设计**:人性化设计不仅关乎硬件,还涉及软件界面,如APP的设计应直观易用,符合用户的操作习惯。 4. **安全性与隐私保护**:在电子政务中,信息安全是关键,包括防止数据泄露,确保用户个人信息的...
"USB之人性化介面装置的报告描述元123"的标题和描述暗示了我们主要探讨的是USB HID设备的报告描述符。 报告描述符是HID设备的核心组件,它是设备向主机描述其输入、输出和特征报告结构的蓝图。理解报告描述符对于...
人性化自助式计算机实验室管理系统本文对高校开放式计算机实验室管理进行了深入细致的探究、探索和实践,提出了人性化智能网络管理模式,研制成功了自助式人性化计算机实验室群管理系统。系统基于校园卡,属于用户端...
USB之人性化介面裝置(Human Interface Devices, 简称HID)是USB设备类规范中的一个重要组成部分,主要用于连接人机交互设备,如键盘、鼠标、游戏控制器、触摸屏等。USB HID设备开发涉及了硬件接口设计、驱动程序...
这需要用到ActionListener接口,通过实现它的actionPerformed()方法来响应用户的操作。按钮的实例添加监听器,使得每次点击都会执行相应的统计逻辑。 6. 异常处理: 在处理用户输入时,可能会遇到空输入或者非英文...
### 2020年的人性化人机交换:核心知识点解析 #### 一、概述与背景 《2020年的人性化人机交换》是一本专注于探讨未来人机交互技术及其对人类社会影响的专业书籍。该书由Richard Harper、Tom Rodden、Yvonne Rogers...
标题中的“USB之人性化介面装置”指的是USB Human Interface Device(HID),这是一种常见的USB设备类别,主要用于连接各种输入和输出设备,如键盘、鼠标、游戏控制器、扫描仪等。这些设备通过USB接口与计算机通信,...
【人性化电视遥控器】的发展与应用 随着科技的进步,电视遥控器的设计也在不断进化,力求更加人性化和便捷。本文以“人性化”的电视遥控器为切入点,探讨了Wiimote(Wii摇杆)如何引领人机交互界面的革命。Wiimote...
此外,考虑到设备的可扩展性,人性化开放式天文圆顶可能还配备了接口,以便连接各种天文仪器,如望远镜、赤道仪、跟踪系统等,以满足不同层次的观测需求。这不仅增强了设备的多功能性,也为未来技术升级留出了空间。...
为了改善这种情况,"人性化的shell"概念应运而生,其中的代表便是"nushell",它旨在提供一种更加直观和易用的命令行交互体验。 nushell(简称Nu)是一个创新的开源shell项目,它的设计目标是让命令行操作变得更加...
### 基于MINIGUI系统灌溉控制人性化计算机界面设计 #### 摘要与背景 随着技术的进步,人性化计算机界面越来越成为嵌入式系统的关键组成部分。为了使嵌入式系统的操作更加简单高效,研究人员致力于开发各类嵌入式...
Avago Technologies提供最先进的特性和功能,让世界级顶尖手机制造商为智能手机用户提供丰富体验。Avago的产品不仅直接影响人性化接口和用户体验,而且能够实现新款小尺寸集成型移动智能手机。
在本文中,我们将深入探讨城市轨道交通公共广播系统的人性化设计及其在重庆轨道交通3号线一期工程中的应用。 首先,广播系统的人性化设计应考虑声场的均匀分布,确保每个区域的乘客都能清晰听到广播内容,避免声场...