任何使用用户数据的应用程序开发人员都应该问的一个很好的问题,遗憾的是,很少有人这样做:(
实际上,这里有两个完全独立的问题:
Q1 - 在什么阶段需要用户登录/注册?
Q2 - 数据并发和冲突解决(见下文)。
在这里对每个问题进行一些分析。请原谅我的额外热情来自我自己的“沮丧的用户”体验。:)
Q1 是一个纯粹的可用性问题。答案实际上是显而易见的:
即使需要保存状态本身也不足以成为理由。如果我作为用户对保存该状态不感兴趣,那么不要强迫我签名!请!
您(作为网站)证明强迫我签名的唯一原因是当我(作为用户)想要保存我的数据以供以后使用时。在这里,我以用户的身份发言,他们在签名上浪费了时间,却发现该网站毫无用处。如果你想摆脱太多的用户,那是正确的方法。在任何其他情况下 - 请尽可能延迟!
为什么这么多网站完全无视如此明显的规则?我可以看到的可能原因:
R1 - 开发人员友好与用户友好。是的,要求立即登录是开发人员友好的,因此我们不需要为并发(Q2)而烦恼。所以我们可以节省开发人员的成本、时间等。但每次节省都是有代价的!在这种情况下称为用户体验。这不一定是您要寻找储蓄的地方。特别是,因为解决方案不应该那么难(见下文)。
R2 - 做出决定的设计师或经理是“室内爱好者” :) 她过着幸福的生活,周围有超快的电脑和超快的互联网连接,无法想象唱歌对任何用户来说都那么难。那么为什么它这么重要呢?这么多原因:
它破坏了应用程序流程。生活在上个世纪的网站仍然以有时相当长的形式取代了整个屏幕。有些表格设计糟糕,有些指令不稳定,有些根本不起作用。有些提交按钮由于某种原因在所使用的浏览器中被禁用。一些表单设计师有天才的想法,可以锁定某些几乎没有明显变化或颜色的字段。如果您不想让我填写,请不要向我展示该字段!
如果网站对用户数据是认真的,它必须请求电子邮件并且必须验证它!为什么?我还能如何回到忘记所有其他凭据的用户那里?为什么要验证?如果用户输入错误的电子邮件怎么办?如果我不验证,下次用户尝试使用正确的电子邮件恢复密码时,恢复失败并且所有数据都丢失了!很明显,但仍有一些网站没有这样做。然后我需要等到收到验证电子邮件并单击,希望格式正确且唯一可识别的链接不会在我的浏览器中中断,也不会由于编码检测损坏而得到一些有趣的字符,从而使整个链接无法使用。
互联网连接可能很慢或中断,使每一个额外的步骤都变得痛苦。即使有良好的连接,它也会在各处发生,页面突然需要更长的时间才能加载。此外,电子邮件可能不会立即到达。然后不耐烦的用户开始疯狂地点击“重新发送验证”链接。在这种情况下,90% 的网站会重新发送带有新令牌的链接,但也会禁用所有以前的令牌。然后几封电子邮件以不可预测的顺序到达,可怜的用户不得不徒劳地猜测,哪一封(并且只有一封)仍然有效。现在,为什么这些网站很难保持几个令牌处于活动状态,仅针对这种情况,我无法理解。
最后,网站坚持使用所谓的“用户名”的习惯仍然很难改掉。所以现在,除了我的电子邮件,我必须努力想出这个独特的用户名,不同于以前的任何用户!非常感谢你让它变得又甜又简单!我自己的处理方式是使用我的电子邮件作为用户名。可悲的是,仍然有网站不接受它!那么如果某个有趣的类型使用我的电子邮件作为他的用户名呢?如果您的电子邮件是 bill@gates.com,那也不是那么不切实际。但是为什么不使用电子邮件和密码来避免所有这些混乱呢?
这里有一些可能的指导来减轻用户的痛苦:
仅在您绝对需要时才强制我登录/注册,并给我一个选择不注册的机会!
让它成为一页表单,这样我就知道我在做什么,而且不用说,尽可能少地使用输入字段。理想情况下只有电子邮件和密码(可能两次),没有用户名!
将您的登录表单显示为页面顶部的小窗口,无需重新加载,并允许我在该窗口之外单击即可摆脱它。不要强迫我寻找“关闭”按钮,或者更糟糕的是,我可能会混淆其他东西的图标!
帐户让用户单击后退/前进和重新加载按钮。重新加载时不要清除表格!根本不要放清除按钮!太容易误点击了。您要求我填写的数据首先不应该太长,以至于我无法在不需要“协助”清除的情况下重新输入。
现在问Q2。在这里,我们有一个众所周知的冲突解决问题,每当需要合并两个数据时就会发生这种问题。比如匿名数据和注册用户数据,还包括两个用户修改同一个数据,或者同一个用户在不同时间从不同设备修改数据,或者本地存储的数据与服务器数据冲突等等。
但无论来源是什么,问题总是一样的。我们有两个数据,比如两个对象 $obj1 和 $obj2,您需要生成单个合并对象 $obj3。逻辑可以很简单,比如服务器的对象总是获胜,或者最后修改的对象总是获胜,或者最后修改的对象键总是获胜,或者任何更复杂的逻辑。这实际上取决于您的应用程序的性质。但在每种情况下,您需要做的就是编写带有返回 $obj3 的参数 $obj1、$obj2 的逻辑函数。
在许多情况下可能可行的解决方案是在每个对象属性(键)上存储时间戳,并让最新更改的键在同步时获胜。这说明了例如同一用户在不同设备匿名时修改不同属性的情况。
想象一下,我昨天在设备 AA 上修改了密钥 A 和 B,然后今天从设备 BB 登录以输入另一个 B 并将其保存到服务器,然后切换回我的设备 AA,我是匿名的,在不更改的情况下输入另一个 A昨天的老B,然后意识到我要登录并同步。然后我的本地 B 显然是旧的,显然不应该覆盖我最近在设备 BB 上更改的 B 的值。在这个看似复杂的情况下,上述解决方案可以无缝且有效地工作。相反,仅将时间戳放在整个对象上是错误的。
现在在某些情况下,保留两个对象可能是有意义的,例如,通过添加额外的属性来区分它们,就像在 Radek 的问题中建议的案例 1 一样。例如,Dropbox 在文件末尾添加了诸如“用户 X 的冲突副本”之类的内容。就像在 Dropbox 的情况下,这在协作应用程序的情况下是明智的,用户喜欢有一些版本控制。但是,在这些情况下,您作为开发人员只需保存两个副本并让用户处理该问题。
另一方面,如果您必须根据用户的数据编写复杂的逻辑,那么拥有两个不同的副本可能是一场噩梦。在这种情况下,我会将数据分成两组(例如,从一个对象中创建两个对象)。第一组具有代表整个应用程序状态的数据,这对于保持唯一性很重要。对于该数据,我将使用上述或类似的冲突解决方案。然后第二组是特定于用户的,我会将这两个数据作为两个单独的条目存储在数据库中,正确标记它们(就像 Dropbox 一样),然后让用户处理他们项目的两个(或更多)条目的列表.
最后,如果数据库管理的额外复杂性让开发人员感到不安,并且由于 Radek 要求提供资源参考,我想通过提到博客条目StackMob 离线同步来“一枪杀死两只苍蝇” ,其解决方案同时提供数据库和用户管理功能,从而减轻了开发人员的痛苦。在搜索数据并发、冲突解决等时,肯定会找到更多信息。
最后,我必须添加强制性免责声明,这里写的只是我自己的想法和建议,每个人都应该自担风险,如果你突然有太多快乐的用户导致你的系统崩溃,请不要追究我的责任: )
由于我自己正在开发一个应用程序,我正在实现所有这些方面,我当然很想听听其他意见以及人们对这个主题还有什么看法。