开发现代界面的主要问题

哈Ha! 我提请您注意丹·阿布拉莫夫(Dan Abramov )的 文章 “ UI工程的要素” ,其中涉及必须在一个良好的界面中解决的当代问题和任务。 作者研究了接口开发中的基本问题,仅在不使用现成的库和框架的情况下进行接口的解释和解决方案,就可以深入了解市场上存在的前端开发领域的解决方案。



译者注
文字以第一人称书写和翻译。 英文原著的作者是Dan Abramov ,他是用于构建复杂用户界面的React库的开发人员。

在我的上一份出版物中,我写到了认识到自己知识差距的重要性。 似乎我在为您提供借口以求平庸。 一点都不! 但是实际上,我们的知识是一个广泛的话题。

我坚信您可以“立即开始”学习知识,而无需按一定顺序学习技术(用于Web开发的技术堆栈-大约是翻译器)。 但我也认为,在所选领域积累经验和专业技能非常重要。 就个人而言,我一直对创建用户界面最感兴趣。

我想知道我的理解和发现的重要意义吗? 当然,我对Javascript和React等技术非常了解。 但是,经验带来的最重要的事情是难以捉摸的,并且在试图准确地表达它们时通常会消失。 我从没想过要把它们说出来。 这是我第一次系统化和描述其中的一些。



如今,有很多学习技术的方法。 在2019年押注哪个图书馆? 而在2020年呢? 我应该学习Vue还是React? 还是角? 那Redux或Rx呢? 我需要学习阿波罗吗? REST还是GraphQL? 在这里很容易迷路! 另外,作者也可能会误会。

我在认知上的最大成就与任何特定技术无关。 当我解决特定的UI(用户界面-大约翻译器)问题时,我开始了解更多。 同时,有时我发现其他人的库和模式可以帮助我解决问题。 有时他会写自己的决定(既好又糟)。
这种结合-包括理解问题 ,尝试工具和应用各种解决方案 -给了我最宝贵的经验和技能。 这篇文章仅关注我在用户界面开发中处理的问题。



如果您正在开发用户界面,则很可能直接或在使用库时遇到了其中一些问题。 在这两种情况下,我都建议您使用一个完全没有库的简单应用程序,尝试重现并解决这些问题。 没有一个真正的解决方案。 鉴于每个问题的长处和短处,了解这些问题并探索可能的解决方案都带来了经验。

一致性


您喜欢该帖子,并出现了题词:“您和另外3个朋友对此表示赞赏。” 您再次单击“赞”按钮,则题词消失了。 听起来很简单! 但是,可能会在屏幕上的多个位置出现这样的题词。 可能还有其他类似的视觉指示(例如,按钮的背景色),也应更改。 以前从服务器接收并在您将鼠标悬停时显示的“喜欢者”列表现在应包括您的姓名。 而且,如果您转到另一部分或单击“后退”按钮,则该帖子不应“忘记”自己喜欢的内容。 如您所见,即使单个用户的本地完整性也会产生许多困难的任务。 同时,其他用户也可以与您显示的数据进行交互(例如,您正在查看的帖子)。 如何在屏幕的不同部分保持数据同步? 我们应该如何以及何时使用服务器检查本地数据并接收/发送更改?

反应性


人们仅在非常有限的时间内允许其操作缺少视觉反馈。 对于连续的用户动作(例如滚动),仅在最短的时间内就可能缺乏应用程序的反应。 即使在16毫秒处跳过一帧,也看起来有问题并且没有完成。 根据一些研究,对于离散 (一次性)动作(例如单击),用户通常认为响应延迟少于100毫秒。 如果操作花费更多时间,则必须显示视觉指示器。 但是,有一些违反直觉的任务。 导致页面模板发生变化或经历多个交替阶段的指示器可能会使操作“感觉”的时间比实际花费的时间更长。 同样,通过跳过动画的一帧,应用程序在20毫秒内的响应可能会比30毫秒内的完整动画“慢”一些。 我们的意识不像基准。 我们如何保持应用程序的响应速度?

响应时间(延迟)


计算机计算和通过网络传输数据需要时间。 有时,如果计算时间不影响用户设备的响应能力,我们可以忽略该时间(但是,请确保已在旧设备和预算设备上测试了代码)。 但是,无法避免处理通过网络传输数据的时间-可以以秒为单位进行计算! 当我们等待数据或代码加载时,应用程序不能简单地“挂起”。 这意味着任何需要新数据,代码或资产的动作都可能是异步的,并且必须处理其加载状态。 这对于绝大多数屏幕和元素都是如此。 如何在不显示旋转纺丝器级联或界面中没有空“孔”的情况下正确处理数据传输的延迟? 如何避免页面布局移位? 以及如何更改异步依赖关系而无需不断重写代码?

导览


我们期望与该界面进行交互时该界面“稳定”。 元素不应突然消失。 在应用程序内部(例如,链接)和外部(例如,浏览器中的“后退”按钮)的导航也应遵守此原则。 例如,在用户部分中的/profile/likes/profile/follows following选项卡之间切换不应使该部分之外的搜索字段内容无效。 甚至切换到另一个屏幕都应该看起来像是步行到另一个房间。 人们期望,当他们回来时,会发现离开他们的所有事物(也许会对一些新事物感到满意)。 如果您位于磁带的中间,请单击配置文件选项卡,然后返回到磁带-那么,您绝对不希望从头开始重新滚动磁带,也不想等到磁带的过去状态被加载。 如何设计一个应用程序来处理任意用户导航而又不丢失重要上下文?

陈旧性


通过向应用程序添加本地缓存,我们可以使“后退”按钮的实现瞬间完成。 为此,我们将必要的数据存储在缓存中(来自先前状态的数据-大约是翻译器)。 从理论上讲,我们甚至可以更新缓存以使数据保持最新。 但是,缓存的实施带来了新的挑战。 缓存可能已过时。 如果我更改了头像,则应该对其进行更新,包括在缓存中。 如果我发布了新帖子,则它应立即显示在缓存中,否则缓存将无效。 这样的代码最终可能变得太复杂且难以维护。 如果发布过程失败了怎么办? 内存中的缓存多长时间? 重新获取数据集时,我们是将新数据与缓存数据更早地合并,还是要摆脱旧的缓存并再次缓存整个数据集? 分页和排序应如何在缓存中显示?

熵值


热力学第二定律大致如下:“随着时间的流逝,一切都会变成一团糟”(当然不是逐字逐句地)。 用户界面也是如此。 我们无法预测特定用户的操作及其顺序。 在任何给定时间,我们的应用程序可能处于大量(巨大!)不同状态之一。 我们会尽力使结果可预测且受设计限制。 我们不想看带有bug的屏幕截图,并自省:“这是怎么发生的?” 对于N个可能的状态,它们之间存在N×(N – 1)个可能的转换。 例如,如果一个按钮可能有五个不同的状态(正常,活动,悬停,突出显示和禁用),那么负责更改按钮的代码必须对5×4 = 20种可能的转换是正确的-或明确禁止其中的某些状态。 我们如何处理可能状态的组合增加并创建可预测的视觉输出?

优先权


有些事情比其他事情更重要。 可能您的对话界面应严格显示在调用该按钮的“上方”,并超出父容器。 或者,刚安排好的任务(即点击的结果)可能比已经开始的长期运行的任务更为重要。 随着应用程序的放大,由不同人员甚至团队编写的不同部分开始争夺有限的资源,例如处理器的计算能力,网络流量,屏幕空间或捆绑包大小。 有时,您可以按单一的“重要性”比例分配项目,类似于z-index CSS规则。 但是通常它不会以任何好的结尾而结束 。 任何开发人员都会真诚地认为自己的代码很重要。 但是,如果一切都同样重要,那就意味着-没有什么是重要的。 我们如何才能使应用程序的独立部分进行交互,而不是为有限的资源而战?

辅助功能


不适合残疾人使用的网站不是高度专业化的问题。 例如,在英格兰,每五分之一的用户都会遇到此问题( 这是一个视觉图表)。 我对自己有感觉。 尽管我只有26岁,但我很少使用字体稀疏且配色方案不透明的网站。 我尝试减少使用触控板的频率,但是担心有一天我不得不使用不合适的键盘键盘。 我们绝不能将我们的应用程序变成残疾人的噩梦-好消息是这并不那么困难。 您需要先探索解决方案和工具。 此外,我们必须使设计人员和开发人员做出正确的决定变得简单易懂。 我们如何确保默认情况下启用应用程序的可用性,而不是过时的版本?

国际化


我们的应用程序应在全球范围内运行。 是的,人们说不同的语言,但是除此之外,从右到左都需要对写作的支持,而开发人员只需付出很少的努力即可。 我们如何在不损失应用程序响应速度和响应时间的情况下支持不同的语言和脚本?

派送


我们必须将应用程序代码交付给最终用户计算机。 我们将使用哪种传输方式和格式? 在这个问题中,每个答案都将因其自身的优缺点而妥协。 例如,本机应用程序由于其庞大的规模而必须提前下载其所有代码。 虽然Web应用程序通常具有短得多的启动时间,但是在使用过程中被迫处理大量延迟和下载。 我们如何决定从这两个选项中选择哪种类型的延迟? 我们如何根据用户使用情况统计信息优化响应时间? 我们需要什么数据才能做出最佳决策?

灵活性(弹性)


没有人喜欢遇到自己程序中的错误。 但是,有些错误将不可避免地投入生产。 这非常重要-然后会发生什么。 一些错误会导致错误的行为,但严格定义和预定义的行为。 例如,您的代码针对给定条件显示了不合适的状态。 但是,如果由于错误而导致应用程序完全停止渲染怎么办? 在这种情况下,由于无法确定视觉输出,因此我们将无法继续有意义的程序执行。 从提要中渲染一个帖子时发生的错误不应“破坏”整个提要的渲染或将应用程序置于不稳定状态,否则将导致进一步的错误。 我们如何编写在某一部分中呈现或接收数据时隔离错误的代码,并继续执行应用程序其余部分的正确操作? 创建用户界面时,容错是什么意思?

抽象化


在小型应用程序中,我们可以在额头上硬编码并解决所有上述问题。 但是应用程序倾向于增长。 我们希望能够重用,合并和组合应用程序的不同部分,并与其他人一起完成。 我们希望在单个整体的各个部分之间定义可理解的边界,这些边界将为不同的人所接受,同时避免过于僵化的逻辑,因为逻辑经常在工作过程中发生变化和发展。 我们如何创建隐藏UI实现细节的抽象? 随着应用程序的增长,我们如何避免这些问题再次发生?



当然,还有许多我没有提到的问题。 此列表绝不是完整的或详尽的。 例如,我没有涉及设计与开发之间的协作,调试或测试。 也许我们会再回到这个时候。

尝试阅读这些问题很容易,请记住将显示数据的特定框架或用于接收数据的库作为解决方案。 但是我建议您想象这些解决方案不存在,然后尝试重读。 您将如何解决这些问题? 尝试在一个简单的应用程序上实现您的想法。 我很高兴看到您在Github上进行实验的结果。 (只需在Twitter上标记Dan Abramov,并将链接附加到存储库-大约是翻译器)。

在这些问题中特别有趣的是,它们中的大多数都以各种规模表现出来。 在使用小部件(例如工具提示)以及大型应用程序(例如Twitter或Facebook)时,您可能会遇到它们。

考虑一下您想使用的应用程序中的非平凡用户界面元素,然后再次遍历上述问题的列表。 您能描述一下开发人员的权衡吗? 尝试从头开始重现类似的行为!

我意识到了开发良好的用户界面,在小型应用程序中尝试这些问题而无需使用第三方库和框架的情况。 我向所有想要在开发复杂接口时深入了解解决方案和取舍的人推荐此方法。

Source: https://habr.com/ru/post/zh-CN435912/


All Articles