如何在登录后合并用户数据



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

有一个问题——如果用户决定用他现有的个人资料登录,他可能已经在他的"匿名"会话中有一些数据。

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

但是我更想问的是,是否有任何关于如何在数据库(通常存储会话数据的地方)中有效地执行魔术的资源。

在我的脑海中有两个基本的解决方案:

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

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

是否有关于为这个特殊用例设计数据结构的文章/资源(匿名+用户数据)?

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

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

  • Q1 -在哪个阶段需要用户登录/注册?

  • Q2 -数据并发性和冲突解决(见下文)。

这里是对每个问题的一些分析。请原谅我因为自己的"受挫用户"经历而产生的额外热情。:)


Q1是一个纯粹的可用性问题。答案其实很明显:

  • 尽量避免或延迟强制用户登录!

即使需要保存状态本身也不足以成为一个理由。如果我作为用户对保存状态不感兴趣,那么不要强迫我签名!拜托!

你(作为网站)证明强迫我签名的唯一原因是当我(作为用户)想要保存我的数据以供以后使用。在这里,我以用户的身份发言,浪费了时间在签名上,却发现这个网站毫无用处。如果你想摆脱太多的用户,这是正确的方法。在任何其他情况下,请尽可能推迟!

为什么这么多的网站完全无视这样一个明显的规则?我能看到可能的原因:

  • R1-开发人员友好vs用户友好。是的,要求立即登录是开发人员友好的,所以我们不需要为并发性而烦恼(Q2)。所以我们可以节省开发者的成本和时间。但是每一次节约都是有代价的!在这种情况下叫做用户体验。这并不一定是你想要节省的地方。特别是,因为解决方案不应该那么难(见下文)。

  • R2 -做决定的设计师或经理是一个"室内爱好者":)她过着快乐的生活,周围都是超高速的电脑和超高速的互联网连接,无法想象唱歌对任何用户来说都是那么困难。那么,这有什么大不了的呢?So many reasons:

  • 它破坏了应用程序流。生活在上个世纪的网站仍然用有时相当长的形式取代整个屏幕。有些表单设计得很糟糕,有些表单的说明不稳定,有些表单根本不起作用。有些浏览器的提交按钮由于某种原因在使用的浏览器中被禁用。一些表单设计师有天才的想法,用几乎不明显的变化或颜色锁定某些字段。如果你不想让我填,就别给我看!

  • 如果网站是认真对待用户的数据,它必须请求电子邮件,必须验证它!为什么?我还应该如何回到忘记了所有其他凭据的用户?为什么验证?如果用户打错了邮件怎么办?如果我不验证它,下次用户试图用她正确的电子邮件恢复密码时,恢复失败,所有数据都丢失了!很明显,但仍然有一些网站没有这样做。然后我需要等到收到验证电子邮件并点击,希望,格式良好且唯一可识别的链接不会在我的浏览器中中断,也不会因为编码检测中断而得到一些有趣的字符,使整个链接不可用。

  • 互联网连接可能很慢或中断,使每多走一步都是痛苦的。即使有良好的连接,有时也会出现页面加载时间突然变长的情况。此外,邮件可能不会马上到达。然后不耐烦的用户开始疯狂地点击"重新发送验证"链接。在这种情况下,90%的网站用新的令牌重新发送他们的链接,但也禁用所有以前的令牌。然后几封邮件以不可预测的顺序到达,可怜的用户不得不徒劳地猜测,哪一封(而且只有一封)仍然有效。现在,为什么这些网站很难保持几个令牌的活动,就在这种情况下,我无法理解。

  • 最后,网站仍然坚持所谓的"用户名",这是一个很难改掉的习惯。所以现在,除了我的电子邮件,我必须努力思考想出这个唯一的用户名,不同于任何以前的用户!非常感谢你让它变得甜蜜和简单!我自己的处理方法是使用我的电子邮件作为用户名。遗憾的是,仍然有网站不接受它!那要是某个有趣的人用我的邮箱作为他的用户名呢?如果你的邮箱地址是bill@gates.com,这也不太现实。但是为什么不直接使用电子邮件和密码来避免这些混乱呢?


这里有一些可能的指导方针来减轻用户的痛苦:

  • 只有在你绝对需要的时候才强迫我注册,并给我一个选择不注册的机会!

  • 让它成为一个页面的形式,所以我知道我在做什么,不用说,使用尽可能少的输入字段。理想情况下,只有电子邮件和密码(可能两次),没有用户名!

  • 显示您的签名形式的小窗口在您的页面顶部没有重新加载,并允许我摆脱它与单一点击离开该窗口。不要强迫我寻找"关闭"按钮,或者更糟糕的是,我可能会混淆的图标!

  • 用户点击后退和重新加载按钮的帐号。重载时不要清除表单!不要放清除按钮!它很容易被意外点击。您要求我填写的数据首先不应该太长,否则我无法在不需要"协助"的情况下重新输入。


现在问Q2。在这里,我们遇到了众所周知的冲突解决问题,每当需要合并两个数据时都会发生冲突解决问题。例如,匿名数据和注册用户数据,但也包括两个用户修改相同的数据,或者同一用户在不同时间从不同设备修改数据,或者本地存储的数据与服务器数据冲突,等等。

但无论来源是什么,问题总是一样的。我们有两个数据,比如说两个对象$obj1和$obj2,你需要生成一个合并对象$obj3。逻辑可以很简单,比如服务器的对象总是获胜,或者最后修改的对象总是获胜,或者最后修改的对象键总是获胜,或者任何更复杂的逻辑。这实际上取决于应用程序的性质。但在每种情况下,你所需要做的就是用$obj1, $obj2参数编写逻辑函数,返回$obj3。

一个可能在许多情况下工作的解决方案是在每个对象属性(键)上存储时间戳,并让最新更改的键在同步时刻获胜。例如,当同一用户在不同设备上匿名时,会修改不同的属性。

想象一下,我昨天在设备AA上修改了密钥A和B,然后今天从设备BB登录进入另一个B并将其保存到服务器,然后切换回我的设备AA,在那里我是匿名的,在不更改昨天的旧B的情况下输入另一个A,然后意识到我想登录和同步。那么我的本地B显然是旧的,显然不应该覆盖我最近在BB设备上更改的B值。在这个看似复杂的情况下,上述解决方案可以无缝有效地工作。相反,将时间戳只放在整个对象上是错误的。

现在在某些情况下,保留两个对象是有意义的,并且,例如,通过添加额外的属性来区分它们,就像Radek的问题中建议的情况1。例如,Dropbox在文件末尾添加了"用户X的冲突副本"之类的内容。就像Dropbox的情况一样,这对于协作应用来说是明智的,因为用户喜欢有一些版本控制。然而,在这种情况下,作为开发人员,您只需保存两个副本,让用户处理这个问题。

另一方面,如果您必须根据用户数据编写复杂的逻辑,那么有两个不同的副本可能是一场噩梦。在这种情况下,我会将数据分成两组(例如,从一个对象中创建两个对象)。第一组具有表示应用程序整体状态的数据,重要的是要保持唯一。对于这些数据,我将使用上述或类似的冲突解决方案。然后第二组是用户特定的,我将这两个数据作为两个单独的条目存储在数据库中,适当地标记它们(像Dropbox一样),然后让用户处理他们项目的两个(或更多)条目列表。

最后,如果数据库管理的额外复杂性使开发人员感到不安,并且由于Radek要求提供资源参考,我想通过提到博客条目StackMob离线同步来"一举两得",其解决方案提供了数据库和用户管理功能,因此减轻了开发人员的痛苦。当然,在搜索数据并发、冲突解决和类似的东西时,可以找到更多的信息。

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

因为我自己正在开发一个应用程序,在那里我实现了所有这些方面,我当然非常有兴趣听到其他人的意见和其他人对这个主题的看法。

根据我的经验——无论是作为一个需要登录的网站的用户,还是作为一个与登录用户打交道的开发人员——我认为我从未见过这样的网站。

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

我想有些地方会允许您填写购物车,然后登录,此时购物车与具体用户相关联。

我将创建一个SessionUser对象,其中包含站点交互状态和一个名为UserId的字段,用于检索其他内容,如名称,地址等

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

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

相关内容