The Essence of Software.Chapter.12.要记住的问题
在结尾,我想回顾一下本书的核心思想,并建议不同角色的读者如何应用它们。这些建议围绕一系列问题展开。
对于战略家、分析师和顾问
对于那些为一个产品及其演进制定战略的人来说,识别概念及其价值是主要任务,而单个概念的设计细节则退居次要地位。
核心概念是什么?
思考将要构建的——或者已经存在的——系统、服务或应用程序,并问问自己它的核心概念是什么。通过构建一个概念清单,你将鸟瞰其功能,在这个全景图中思考你的战略举措。将这些概念排列在一个依赖图(dependence diagram)中,看看它们之间是如何相互关联的,以及哪些概念处于核心地位。
你的概念有多老?
当你审视现有系统中的概念时,确定每个概念是何时引入的,并调查它随着时间的推移是发生了变化还是保持稳定。是否有概念发生了戏剧性的变形(如Facebook的 post(帖子)——见注释48),标志着整个系统的重大转变,或者在演变过程中成为了新的概念?是否有概念在引入后又被废弃了?哪些概念最成功地经受住了时间的考验?
你最有价值的概念是什么?
你是否有一个杀手级概念(如Photoshop的 layer(图层)或万维网的 url),它是你产品成功和竞争优势的源泉?是否有些概念(如Gmail的 label(标签))是你产品的关键枢纽,没有它产品几乎无法运作?是否有些概念对收入至关重要,可能是因为它们定义了你产品的高级版本,或者因为它们为你的客户带来了最大的价值?
你有成问题的概念吗?
你的产品是否包含让用户感到困惑的概念(频繁的帮助请求证明了这一点),或者其复杂性导致了不成比例的缺陷或系统停机?如果是这样,这些成问题的概念是与你的竞争对手共有的,还是自找的麻烦?
哪些共享概念定义了这个产品家族?
如果你将你的几个产品视为一个单一家族(如Adobe Creative Suite或Microsoft Office)的成员,你能否识别出它们之间共享的核心概念?这些共享概念是使用通用基础设施实现的,还是在每个产品中重新实现的?一个共享概念的各个实例之间是否一致,还是它们之间存在微小且可能随意的差异?当用户从一个产品移动到另一个产品时,这些差异是否会造成问题?它们是否会导致集成和数据共享问题?
也许属于该家族的产品目前没有共享概念,但如果未来出现在多个产品中的概念被统一,它们可能会共享。这种统一不仅会给整个家族带来好处,还会给单个产品带来好处吗?
每个概念的目的是什么?
对于你清单中的每个概念,你能给出一个简单而引人注目的目的吗?这些目的是否有助于产品的更大目标以及你组织的愿景?
每个概念服务于谁的目的?该目的是否符合你的客户的利益?如果是,它服务于哪些客户——用户还是广告商?如果它符合你组织的利益,它是否向客户索取了不必要的成本?旨在服务于客户利益的目的,是否有效地传达给了他们,并且是否与他们的真实需求相一致?
是否有缺失的概念?
你能否识别出一个未被满足的目的,该目的暗示了一个缺失的概念(例如电子邮件客户端中缺失的 correspondent(通信者)概念)?如果你能识别出这样的概念,是否有机会将其添加到你的产品中,从而获得竞争优势?
你竞争对手的概念是什么?
看看同一领域的竞争产品,并盘点它们的核心概念。它们与你的不同吗?你拥有而你的竞争对手缺乏的概念是否重要?它们是否给了你的产品优势,或者它们是否是不必要复杂性的来源?你的竞争对手拥有而你缺乏的概念是否对你产品的未来构成威胁?你是否采用了全行业通用的概念?如果是这样,它们是否使新客户更容易开始使用你的产品?或者这些概念是否让你陷入了过去产品有缺陷的假设中?
对于交互设计师和产品经理
许多适用于战略家和顾问的问题也适用于交互设计师和产品经理,但还有一些新问题集中在单个概念的设计和映射上,以及将可用性问题追溯到概念上。
概念是否一致地传达给了用户?
你的产品是否成功地(通过其界面、用户手册或帮助页面、培训和营销材料)投射出了一个与实际概念模型相匹配的心理模型(mental model)?回顾一下你的产品功能在用户界面和所有支持材料中的描述方式。这些是否都呈现了产品概念的一致形象?是否有一个用于概念及其目的的通用词汇表?
概念是如何解释的?
产品及其相关的支持材料是否围绕概念进行了系统的组织?在你的支持材料中,你是否解释了每个概念的目的?你是否有时会陷入详细解释概念的作用(does),而不解释它是为了什么(for)的陷阱中?你是否提供了引人注目的使用场景,并且它们是否突出了操作原理(operational principles),令人信服地展示了每个概念的设计是如何实现其目的的?
你面临什么样的可用性问题?
回顾用户的反馈和技术支持请求,你能否识别出产品中的主要可用性问题?然后,对于每个问题,你能否确定它属于哪种 类型 的问题,将其分配到交互设计的三个层次中的一个或多个层次上?
哪些概念让你高兴或悲伤?
作为一名设计师,你无疑对产品及其品质有着深刻的理解。为设计中成功的、有问题的或介于两者之间的方面制作一个表格。当你填满这个表格后,回顾每一个条目,将其分配到一个设计层次,对于所有最终被证明是概念性的条目,命名出负责的概念。
你是否有任何冗余的概念?
你能否找到冗余的概念(如Gmail的 category(类别)概念),它们与产品中其他概念的目的是相同的,这让你有可能通过消除一个概念来简化和澄清设计,并扩展另一个概念(如果需要的话)以涵盖被消除概念的功能?
你是否有任何过载的概念?
你是否有(如以前版本的Photoshop中的 cropping(裁剪)概念——见注释101)似乎服务于多个目的的概念?如果是这样,这些可能是可用性问题的原因。你能否找到一个概念的不同目的相互冲突的场景?如果没有,你能否制定一个连贯而引人注目的目的,将那些表面上截然不同的目的涵盖其中,从而论证该概念实际上并没有过载?
你的某些概念可以被拆分吗?
看看你那些比较复杂的概念,特别是那些过载的概念,考虑你是否可以将它们拆分(就像我们对Facebook的 like(点赞)概念所做的那样)成多个概念,每个概念都有一个更简单、更引人注目的目的。
这样做是否会给你一个机会在你的产品中更广泛、更一致地使用某个概念?
例如,如果你分离出一个 notification(通知)概念,你能否提供更广泛类型事件的通知,并让用户控制发生哪些通知?
熟悉的概念被有效地使用了吗?
对于你产品中的每个概念,问问自己是否有一个更熟悉的概念可以取代它。你的任何概念(如Microsoft PowerPoint的 section(节)概念)在目的上是否接近现有的、更熟悉的概念?如果是这样,用更熟悉的对应物替换它们会失去什么吗?如果你确定你使用不熟悉的概念是合理的,那么它与更熟悉概念不同的方式是否清楚并且能够被用户理解?
概念是如何组合的?
哪些概念被同步(synchronizations)捆绑在一起?你能否画出同步图(synchronization diagrams)来显示哪些动作被捆绑在一起?你的同步实现了什么类型的组合(compositions):自由的、协作的还是协同的(free, collaborative or synergistic)?你设计的威力有多少来自于同步,有多少来自于概念本身?
你是否有同步不足(under-synchronizations)?
是否存在这样的情况:你可以通过增加概念之间的同步来省去用户的一些手动工作,以便自动执行某些动作?这样的同步可以作为新手用户的默认设置,并以更可定制的形式提供给专家吗?
你是否有过度同步(over-synchronizations)?
是否存在概念同步过于紧密,从而从用户那里夺走过多控制权的情况?概念之间更多的正交性(orthogonality)(也就是更松散的同步)是否会给用户更精细的控制,使得你的概念中已经存在的功能变得可用?
你正在利用协同作用(synergy)吗?
你现有的概念组合是否创造了协同作用(就像 trash(垃圾桶)/folder(文件夹)的例子一样),其中一个概念放大了另一个概念的威力?你能否找到额外的协同机会?思考这个问题的一种方法是:你能否调整一个概念的行为,也许稍微泛化它,使其能够包含另一个概念的部分行为,但更一致、更广泛地提供这种行为?
概念是否有效地映射到了用户界面?
你的用户界面是透明地向用户展示概念,还是概念被埋在一层复杂的控件之下,使得很难看到它们并保持它们的分离?用户是否很容易发现如何选择动作及其参数?每个概念的状态对用户可见吗?你的用户界面是否不仅提供单独的概念动作,还提供用户可能需要的更复杂的动作序列?
你分析过你概念的依赖关系吗?
为你产品中的所有概念构建一个依赖图。根据它所依赖的概念,每个概念的理由是否成立?该图是否暗示了你没有考虑过的子集,也许可以用来简化产品?
概念的组装是否具有完整性?
每个概念孤立地看可能是合理的,但当与产品中作为一个整体的其他概念结合时,它可能会被削弱。该设计是否保留了每个概念的完整性?还是存在一些微妙的方式,用户对概念的理解由于另一个概念的干扰而必须被修改?
你的概念智慧被安全地记录下来了吗?
一个概念设计可能会演进很多年,积累了来自多代设计师的大量修复和改进。如果这些知识只被捕获在代码中,那么——正如Apple Numbers中 range(范围)概念的命运所表明的那样——当新程序员没有意识到这些微妙之处,并做出了在几秒钟内抹去多年洞察的修改时,它可能会丢失。出于这个原因,对于一个产品,维护一本追踪其每个概念发展的设计日志(design journal)是很重要的。一本更简短的概念目录(concept catalog)或手册(handbook),记录下公司设计的每个概念的精炼智慧,可以促进产品之间的共享,并帮助新设计师快速上手。
对于技术作家、培训师和营销人员
一些额外的问题适用于那些提供用户用来熟悉产品和在遇到困难时解决问题的关键材料的人。
支持材料是围绕概念组织的吗?
用户手册、帮助功能和技术支持文章是否围绕核心概念组织?一个概念的动作是否被放在一起以连贯的方式进行了解释?
你是否为概念给出了清晰的目的?
在介绍一个概念时,你是否解释了该概念 为什么 存在,它是 为了什么?你给出的目的是否满足形式良好(well formed)目的的标准(令人信服、关注需求、具体、可评估)?你是否避免了误导性的隐喻?
你是否解释了每个概念的操作原理?
为了解释如何使用一个概念,你是否给出了一个引人注目的操作原理,还是仅仅列出了动作,留给用户去弄清楚原型使用场景(archetypal usage scenario)是什么?
概念是否以合理的顺序进行解释?
如果你的一些材料(例如用户手册)是顺序的,它们呈现概念的顺序是否与依赖图一致,以便在引入每个概念时就可以说明其动机,而不需要向前引用尚未解释的概念?
对于程序员和架构师
上述关于概念、它们的目的以及它们之间关系的问题对于实现者也是基础。依赖图可用于分阶段进行增量开发,并规划部分发布。
什么样的一组概念构成了一个最小可行产品(minimum viable product)?
对于战略家来说,这当然也是一个至关重要的问题,但它对实现者具有特殊的意义,因为他们可以更容易地评估构建这些概念的成本。
哪些概念在实现上具有挑战性?
你能否识别出哪些概念在实现上最具挑战性?哪些概念拥有最复杂的状态,或者因为它们将包含的数据量而带来性能挑战?任何概念的操作原理是否暗示了可能需要分布式共识算法的一致性问题?如果是这样,最终一致性(eventual consistency)是否足够?
你能避免重新发明轮子吗?
如果你正在实现一个熟悉的概念,你能否在自己的组织或其他地方找到该概念的实现,从而为你提供指导并帮助你避免已知问题?
是否在适当的地方使用了标准库概念?
当标准库或插件可能同样出色时,你的设计师是否发明了一个需要非标准库或插件的概念?是否现有的实现与提议的概念足够接近,以至于值得调整设计来适应它?
概念是否尽可能通用?
设计中的概念是否不必要地专门针对特定的数据类型,或者它们可以被通用地表达?例如,如果设计包含一个 comment(评论)概念,那么评论的目标是任何条目,还是设计(更糟糕的是,实现)假定目标始终是 post(帖子)或 article(文章)?
你能将概念实现为独立的模块吗?
如果你的实现将概念纠缠在一起,这种缺乏模块化的情况真的合理吗?或者你正在积累最终必须偿还的技术债务?如果你成功地将概念模块化了,它们之间是否存在可以消除的代码依赖关系,以便它们可以更容易地被修改和重用?
概念之间是否存在复杂的同步?
如果产品依赖于以丰富方式同步的概念,这种同步是否会在代码中产生复杂性?如果是这样,是否有一种更好的方法来组织它,例如使用事件总线(event bus)或隐式调用(implicit invocation)架构,或者通过使用回调(callbacks)和依赖注入(dependency injection)?
某些概念动作是否涉及复杂的条件语句?
你的一些概念动作是否对其参数执行了复杂的检查,或者具有复杂的条件控制流?如果是这样,这可能是成问题的概念的症状。这样的动作是否在同一个概念内代表了多个动作(取决于呈现的参数)?拆分成几个截然不同的概念是否可以简化这些动作?概念之间缺乏同步是否导致了不应该需要处理的不一致状态?
对于研究人员和软件哲学家
我不断发展的概念理论仍有许多重要问题无法解决。也许你们中的一些人会受到启发,接受挑战,帮助建立一个更完整的概念设计理论和方法。考虑到这一点,以下是一些开放的问题。
概念目录应如何结构化?
一个概念目录或手册将允许设计师汇编他们的知识,使新手更容易获得专业知识,并将鼓励更大程度的概念重用,帮助设计师避免已知陷阱。这样的目录应该如何结构化?目录应该是特定于领域的(例如,社交媒体应用程序的目录和银行业的目录),还是目录应该强调跨领域的概念?
是否存在复合概念(composite concepts)?
我已经解释了概念如何可以被组合在一起,以及有时过度概念的补救措施是将其分解成多个概念。当一个概念被分解成更小的概念时,那个更大的实体是否仍然作为它自身的概念存在,并具有自己的目的?
是否有不同种类的目的?
我已经给出了构成良好目的的标准,以及用于识别目的何时是复合目的的连贯性测试。但我忽略了关于目的所扮演角色的一些重要区别。正如我所解释的,一个概念的目的,构成了在设计中包含它的动机。但包含意味着两件不同的事情。一是与概念带来的普遍好处相关;另一是与其他原本可能使用的概念相比,它所带来的特定好处。
例如,label(标签)和 folder(文件夹)概念都实现了组织条目的目的,而这个目的将成为包含它们其中任何一个的动机;但只有 label 实现了将条目组织到重叠类别中的目的。我不太清楚概念之间这种更细粒度的区别是否算是一种目的;也许这只是一个区分具有相同目的的概念的品质。
通用概念实例化时会出现什么问题?
我认为,概念在可能的情况下应该以通用形式陈述。这样做能让你触及设计的本质,消除可能导致不必要、非传统和不熟悉概念的领域特定的并发症。当通用概念被组合时,它们被实例化;例如,当 trash(垃圾桶)概念与 email(电子邮件)概念组合时,trash 的 items(条目)变成了 messages(消息)。是否有一种方法可以系统地将领域特定的概念(和目的)抽象成通用的概念?
通用概念的实例化可能伴随着与领域特定概念的组合。在一个餐厅预订系统中,仅知道资源的通用 reservation(预订)概念可以与知道餐厅餐桌的 table(餐桌)概念组合。Google Maps预订API正是施加了这样的结构,它要求餐厅将一张可以容纳四到六人的桌子转换成三个不同的抽象资源。这是它自己的一类组合吗?其背后是否存在一般原则?
动作同步足够吗?
概念的组合(在本书中)完全依赖于动作同步。是否应该允许概念也在状态上同步?例如,trash(垃圾桶)和 folder(文件夹)的协同组合(synergistic composition),可以表示为一个将垃圾桶中的条目与作为垃圾桶文件夹后代的那些文件和文件夹联系起来的不变量(invariant)。(见注释71。)
可以明确阐述映射原理吗?
是否存在评估映射的一般原则?这些原则大概会建立在众所周知的用户界面设计原则的基础上,但会更直接地解决与概念的联系。例如,研究人员探索了状态可见性的概念(特别是关于隐藏模式(hidden modes)),但通常是在单状态机更简单的设置下。什么样的可见性规则可能适用于由概念组成的应用程序?
对用户行为的假设在概念设计中扮演什么角色?
有些概念只有在用户以某种方式行为时才能实现其目的。例如,password(密码)概念,只有在用户选择了不可猜测的密码、记住他们的密码并且不分享密码时,才能提供有效的身份验证。这样的假设可以被表达为操作原理的先决条件吗?
概念实现可以完全模块化吗?
概念设计提出了一种新的编程惯用语(programming idiom)。我解释过(在注释81中)为什么传统的面向对象编程风格通常会导致不受欢迎的耦合,常常产生一种依赖关系指向完全错误方向的结构。将概念作为模块直接实现可能会产生一个更灵活和解耦的代码库(见注释32)。什么样的模块化机制将允许灵活的同步和组合?
微服务架构可能是概念实现的有用基础,其中每个微服务代表一个单一概念,因此它或许应被称为“纳米服务(nanoservice)”。纳米服务与微服务有何不同?它们能以我描述的方式同步,而不需要通常的、一个服务的内部调用另一个服务的API那样的依赖关系吗?
能在代码中检测到概念设计缺陷吗?
结构不良的概念不仅困扰用户,也困扰程序员。当在应用程序中试验一个概念设计问题时,我经常发现应用程序崩溃或表现出与当前设计问题没有直接关系的其他故障。我怀疑,当概念不清晰时,代码反映了这种混乱,且缺陷率会上升;在编写代码时,这无疑是我个人的经验。通过将代码库中的文件映射到概念上,源代码挖掘或静态分析可以利用这种联系吗?设计层次上的概念混淆能否通过代码中更高的缺陷率来预测?概念设计缺陷是否暗示了代码中值得更仔细审查的地方?
概念能应用于内部API设计吗?
根据定义,概念是面向用户的。但是当程序内部使用一个服务或API时,出现的许多问题与用户面临的问题相似。从概念设计的角度来看,实现栈某一层中的程序,可以被视为较低层概念的“用户”吗?如果可以,概念设计原则能否应用于代码设计?
对于我们所有人
除了所有这些工作场所的情况,我希望本书的思想在那种最常见的场景中能有所帮助——当我们正在努力弄懂另一个不那么容易理解的应用程序或功能时。也许稍微做一些概念分析就能揭示发生了什么。至少,它可能会让我们关于所使用的技术的日常讨论变得更接地气、更有实质内容,并帮助我们更清晰地看到通往更好设计的道路。