8

如果您正在构建一个 eshop 或任何其他使用会话在请求之间存储一些数据的应用程序,这并不重要。如果您不想通过要求他注册来惹恼用户,您需要允许他在可能的情况下匿名执行某些任务(用户确实必须有注册的理由)。

有一个问题 - 如果用户决定使用他现有的配置文件登录,他可能已经在他的“匿名”会话中拥有一些数据。

合并这些数据的最佳实践是什么?我猜应用程序应该在可能的情况下自动合并它,或者让用户决定在哪里不可能。

但我要问的更多是是否有任何关于如何有效地在数据库(通常存储会话数据的地方)中发挥魔力的资源。

我有两个基本的解决方案:

  1. 保留匿名会话数据并添加另一个“关系”,说明实际使用的内容在何处以及如何合并
  2. 物理合并这些数据

我们可以说第一个解决方案可能会更有效,因为关于任何关系的信息可能意味着比关于用户的数据更少的数据。但这也意味着在读取数据时需要付出更多的努力(因为我们首先需要读取关系以获取实际的用户数据)。

是否有任何文章/资源可用于为此特定用例(匿名 + 用户数据)设计数据结构?

4

2 回答 2

9

任何使用用户数据的应用程序开发人员都应该问的一个很好的问题,遗憾的是,很少有人这样做:(

实际上,这里有两个完全独立的问题:

  • 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 离线同步来“一枪杀死两只苍蝇” ,其解决方案同时提供数据库和用户管理功能,从而减轻了开发人员的痛苦。在搜索数据并发、冲突解决等时,肯定会找到更多信息。

最后,我必须添加强制性免责声明,这里写的只是我自己的想法和建议,每个人都应该自担风险,如果你突然有太多快乐的用户导致你的系统崩溃,请不要追究我的责任: )

由于我自己正在开发一个应用程序,我正在实现所有这些方面,我当然很想听听其他意见以及人们对这个主题还有什么看法。

于 2013-08-26T11:44:06.250 回答
7

根据我的经验——无论是作为需要登录的网站的用户,还是作为与登录用户一起工作的开发人员——我认为我从未见过一个网站以这种方式运行。

常见的模式是让用户匿名,当他们第一次做需要保存状态的事情时,会提示他们登录。然后记住之前的操作,用户可以继续。例如,如果他们尝试在购物车中添加东西,系统会提示他们登录,然后在登录后,该商品就在他们的购物车中。

我想有些地方可以让您装满购物车,然后登录,此时购物车与具体用户相关联。

我将创建一个 SessionUser 对象,该对象具有站点交互的状态和一个名为 UserId 的字段,该字段用于检索名称、地址等其他内容。

对于匿名用户,我将使用 UserId 的空引用创建 SessionUser 对象。这意味着我们无法解析名称或地址,但我们仍然可以保存状态。他们正在执行的操作,他们正在查看的页面等。

一旦他们登录,我们就不必合并两个对象,我们只需在 SessionUser 中填充 UserId 字段,现在我们可以遍历对象图以获取姓名、电子邮件、地址或其他任何内容。

于 2013-08-22T16:17:26.000 回答