轻松学模块化编程(三)
十九、创造神奇的用户体验
首先,要开始学习在设计应用程序时考虑用户体验,您应该知道以下缩写:
-
UX :用户体验。使用应用程序的总体体验
-
UI :用户界面。用户使用的网页或图形界面
-
吻:简单点,笨蛋。总体设计理念
-
RWD:响应式网页设计(一种允许网页在多种不同设备上呈现的网页设计方法)
应用程序层次
您应该根据以下特征从高到低排列 UX 的优先级:
-
功能:软件做它应该做的事情。
-
有用性:软件好用吗?
-
效率:用户能否高效工作?
-
神奇:体验神奇吗?
如果你的软件没有功能,你就不能专注于可用性。如果你的软件不可用,你就不能专注于提高效率。
在你掌握了所有的基础知识(功能性、可用性和效率)之后,你才可以尝试让你的 UI 变得神奇。
考虑你的观众
为你的软件考虑受众总是很重要的。你应该尽可能多地了解他们。
你们中熟悉哈利波特(或魔法)的人会认出这些词:巫师*/、女巫和麻瓜*。在波特的世界里,哑炮是知道魔法但不会使用魔法的人,麻瓜是不知道魔法的正常人。
我们可以将这个类比应用于软件。当设计你的软件时,你需要记住每一类可能使用它的人:
-
初始用户:麻瓜
-
熟练用户:哑炮
-
高度熟练用户:巫师/女巫
例如,如果你只为巫师和女巫设计,麻瓜会感到失落。如果你只为麻瓜设计,巫师们会觉得软件不完整而且太简单。
选择是一种幻觉
一个人的选择越多,就越需要思考。作为一名设计师,你应该做到以下几点:
-
限制选择。
-
为每一个可能的选择做好准备。
-
为你的观众量身定制选择。
-
验证用户输入,确保它符合预期。
你经常需要决定是给你的用户一个选择,还是替他们做出选择。
最简单的方法(对你来说)总是让用户决定,但是更好的方法通常是少给用户一个选择。这将使你的软件更简单,因此更容易使用。
方向
本能地工作——本能是你的朋友。动作是吸引用户注意力的一种微妙而有效的方式。然而,太多的运动会分散注意力,所以应该保持在最低限度。
另一种本能视觉是人脸。人脸首先被注意到。这就是为什么你总是在文本的左侧看到面孔(在从左向右阅读的语言中)。眼睛首先被吸引到脸部,然后是伴随的文字。
拟真
Skeuomorph 是现实生活中的东西,在软件中被模仿。
模拟现实生活中的特征,如边缘、斜面和按钮,对于交流可负担性(用户可以用某物做什么)是有用的。然而,如果你在模拟一个完整的物体(比如一本书),你必须 100%正确。这就是为什么 skeuomorphism 通常是一个坏主意。如果做得不完美,模仿真实世界的东西会被认为是假的。
你可以采取相反的方法,试图消除所有的隐喻。UI 可以是非常平坦和无边框的。然而,你可能把这个概念看得太远了。例如,什么是可点击的,应该仍然是显而易见的。
背景很重要
没有上下文的三颗星可能意味着任何事情。然而,给定上下文(3/5 颗星),其含义变得显而易见。
上下文对于导航也很重要。用户在软件中的位置以及如何导航到其他地方必须是显而易见的。否则,你的用户会感到失落,这不是一种舒服的感觉。
一个相关的概念是避免“模式”与软件交互的方式越多,它看起来就越复杂。
吻
最重要的是,保持简单——对用户来说简单。例如,一般来说,在软件中应该总是有一种方法来做一些事情。此外,作为一般规则,你的用户界面应该遵循现有软件/网站设置的惯例(例如,总是给链接加下划线)。
随着软件的增长,你必须不断地选择新的 UI 特性。除了其他考虑之外,您还应该考虑如何使它们变得更简单。
你不是用户
除非你只是为自己开发软件,否则绝大多数的可能性是你的用户和你非常不同。因此,你不仅要试着像你的用户一样思考,还要真正了解他或她。这意味着理想情况下,你坐下来看你的用户操作软件。
同样,在生产系统中,你应该监控你的用户在做什么。他们在使用这项新功能吗?他们在做什么意想不到的事吗?指标有助于分析用户的行为。
摘要
从本章中,您应该已经了解了以下内容:
-
你的 UI 应该是功能性的、可用的、高效的,按照这个顺序。
-
在设计的所有阶段,考虑谁是你的用户。
-
限制选择并处理所有情况。
-
本能是你的朋友,但不要模仿现实。
-
为用户保持简单,并倾听他们的意见。
关于可用性的更多信息,我强烈推荐史蒂夫·克鲁格的不要让我思考(新骑手,2014)。
二十、数据库
数据库是大多数软件项目极其重要的组成部分。简而言之,数据库是一个以标准格式存储数据的软件系统,根据数据库的不同,它可以实现以下一项或多项功能:快速存储和检索、执行复杂查询的能力、数据输入的验证以及对数据的计算。
可以追溯到几十年前的经典数据库被称为关系数据库。除了原始数据,它还存储数据库中表之间的关系。数据库通常由几个具有定义的约束的高度结构化的数据表组成。例如,表中的每一列都有一个类型,它是否可以为空,它是否必须是唯一的,以及其他约束。
有一种高度标准化的语言用于在数据库上执行操作和计算,称为 SQL (结构化查询语言)。SQL 已经存在很长时间了,可以很容易地保证它有自己的书,所以这本书将只涵盖基础知识。
自从所谓的大数据产品和网络应用(例如一个特定的“脸”主题社交网络)出现以来,第二类数据库已经出现: NoSQL 或非关系型数据库。通常,这些更像是键值或文档存储,而不是关系数据库。它们包括 Redis、MongoDB、Cassandra、DynamoDB 等数据库。
Note
SQL/NoSQL 分类过于简化,但它提供了比实际复杂现实更简单的叙述。换句话说,“这里有龙!”
SQL(关系)数据库
经典关系数据库的一部分是 ACID(原子性、一致性、隔离性、持久性)的概念。总结一下 ACID,它意味着数据库总是处于一致的状态(带有强制约束),即使系统在更新过程中崩溃。例如,如果表中的一列被标记为“not null”,它将永远不会为 null。它还支持事务,它们是工作的原子单位——要么全部发生,要么什么都不发生。乍一看,这似乎是一件简单的事情,但实际上这是一个非常复杂的问题。
在关系数据库中,数据的主要存储被称为表。一个表有列,它们是表模式(定义)的一部分,定义具体存储哪种数据。一个表有行,它是存储在表中的数据,每一行都有为每一列定义的值。
一些好的开源数据库包括 PostgreSQL、MySQL 和 H2。对于本节,您可以安装 PostgreSQL。在 Debian 或 Ubuntu Linux 上键入“sudo apt install postgresql”。对于其他系统,请参见网站 2 获取安装说明。DBeaver 是一个很好的连接和操作数据库的图形化工具。 3
结构化查询语言
关系数据库的基本语言是 SQL。它包括定义表和对这些表执行复杂查询的能力。
例如,创建一个表如下所示:
1 CREATE TABLE dragon(
2 dragon_id INTEGER,
3 dragon_name VARCHAR(100),
4 birth_date DATE NOT NULL,
5 PRIMARY KEY (dragon_id)
6 );
一个表总是需要有一个主键—它充当表中每一行的标识符,所以它在表中的每一行都必须是唯一的。这种情况下,主键是dragon_id。
接下来,您可以使用insert语句向表中添加数据。例如,在 PostgreSQL 中,您可以通过以下方式插入两行:
insert into dragon values (1, 'Smaug', current_date);
insert into dragon values (2, 'Drago', current_date);
数据库类型涵盖了基础知识,如INTEGER,但其他不熟悉的类型包括:
-
VARCHAR(长度)类似于String对象。它有一个给定的最大长度。 -
TIMESTAMP用于存储日期和时间。 -
NUMERIC(precision, scale)或DECIMAL(precision, scale)用于存储货币值等数字(例如,数字 123.45 的精度为 5,小数位数为 2)。 -
BLOB通常用于存储二进制数据。
select语句允许您指定要从一个或多个表中提取哪些列。您还可以在select语句中使用MIN、MAX或COUNT等聚合函数来执行更复杂的查询。例如,要查找最老的龙的生日,可以执行以下查询:
1 SELECT MIN(birth_date) FROM dragon;
可以使用一个where子句将查询限制在表中的某些行。要选择名称以 S 开头的所有龙(按字母顺序),运行以下命令:
1 SELECT dragon_id, dragon_name FROM dragon
2 WHERE dragon_name LIKE 'S%'
3 ORDER BY dragon_name;
order by子句用于对查询返回的结果进行排序。like关键字用于根据匹配表达式匹配varchar列,其中%匹配任何值。
外键
外键只是一个表中引用另一个表的主键的一列。
例如,假设你有一张wizard桌子,每个巫师都有多条他们作为宠物饲养的龙。
1 CREATE TABLE wizard(
2 wizard_id INTEGER,
3 wizard_name VARCHAR(100),
4 PRIMARY KEY (wizard_id)
5 );
如果wizard表的主键是wizard_id,那么dragon表可能会有如下带有所有者列和外键约束的新定义:
1 CREATE TABLE dragon(
2 dragon_id INTEGER,
3 dragon_name VARCHAR(100),
4 birth_date DATE NOT NULL,
5 PRIMARY KEY (dragon_id)
6 owner INTEGER,
7 FOREIGN KEY owner REFERENCES wizard (wizard_id)
8 );
虽然 SQL 关键字以大写形式显示,但这并不是 PostgreSQL 所要求的,只是为了便于说明。
连接
数据库系统通常作为一个单独的进程运行,您的代码以某种方式连接到它。
有许多不同的方法可以做到这一点。在 Java 中,连接数据库的最基本标准被称为 JDBC。
它允许您在数据库上运行 SQL 语句。您将需要一个特定的驱动程序——一个为您的数据库实现 JDBC 标准— 的库。
在实际应用程序中,您还应该使用 JDBC 连接池,比如 HikariCP。 4 连接池允许应用程序多次重用连接,这提高了应用程序的吞吐量和性能,因为连接启动需要时间。
还有对象关系映射 (ORM)框架,比如 Hibernate。 5 这些框架让你把 Java 对象映射到数据表。它们是在 JDBC 的基础上建造的。例如,Hibernate 有自己的查询语言,叫做 HQL,由 Hibernate 翻译成 SQL。我们前面讨论过的 GORM 默认使用 Hibernate。
或者,有代码生成框架允许您使用 DSL 进行查询。jOOQ 就是这样一个 Java 框架。 6 它允许你用本地语言编写类型安全的查询。例如:
1 create.selectFrom(DRAGON)
2 .where(DRAGON.NAME.like("S%"))
3 .orderBy(DRAGON.NAME)
NoSQL(非关系)数据库
大型网络项目(如维基百科)在使用关系数据库扩展到数百万用户时存在问题。他们必须将数据库划分到多台机器上(称为分片),这破坏了外键引用。关于这一点有一个定理,CAP 定理,它说你可以在一个数据库中拥有一致性、可用性和分区中的两个,但不是所有三个。因此,随着时间的推移,大数据项目转移到了 NoSQL 或非关系数据库,这做出了不同的权衡,因此它们可以更容易地扩大规模。很多时候,权衡是最终一致性而不是完全一致性。换句话说,在另一个用户输入新值后,一个用户可能会在短时间内读取旧值。
网飞、Reddit、Twitter、GitHub、Pinterest、易贝、eHarmony、craigslist 和许多其他网站都使用 NoSQL 数据库。
Note
我将在这里介绍一些 NoSQL 数据库,但还有许多其他的数据库。
使用心得
Redis 7 是键值存储。在 Redis 中,一切都以字符串形式存储,包括二进制数据。它是用 C 写的,有一长串命令。88
有多个客户端可以使用许多不同语言的 Redis,包括 Java、Node.js、Scala、Ruby、Python 和 Go。
MongoDB
MongoDB 9 是文档数据库。它存储 JSON 风格(JavaScript)的文档,并具有丰富的查询语法。它是用 C++写的,但是 JavaScript 可以用在查询和聚合函数中。
MongoDB 支持文档中任何字段的索引。它使用分片进行水平扩展,并使用复制提供高可用性和更高的吞吐量。最近,它增加了对 ACID 事务的支持。
MongoDB 也可以用作文件系统。
卡桑德拉
卡珊德拉 10 最初是在脸书开发的,并于 2008 年 7 月作为开源项目发布。它是用 Java 编写的,现在是一个成熟的顶级 Apache 项目。
Cassandra 是可伸缩的、分散的、容错的,并且具有可调的一致性。它还使用复制来提高容错能力和性能。
Cassandra 有一个类似 SQL 的替代方案,叫做 CQL (Cassandra 查询语言)。语言驱动程序可用于 Java (JDBC)、Python (DBAPI2)和 Node。JS(海莱纳斯)。
VoltDB
VoltDB 11 提供了 SQL/NoSQL 划分的反例。它是分布式的,内存中的,速度极快,但它也是一个关系数据库,并支持 SQL。
摘要
-
有两种主要类型的数据库:SQL 和 NoSQL 或关系和非关系。
-
关系(SQL)数据库是高度结构化的、一致的和持久的,但是难以扩展。
-
大数据项目倾向于使用非关系数据库,这就像键值存储,可以更容易地扩展。
https://en.wikipedia.org/wiki/ACID 。
2
3
4
https://github.com/brettwooldridge/HikariCP
5
6
7
8
9
10
11