users
表需要记录每个用户的状态。例如:
这里至少有两个选项。一种是简单地使用一个元组(或其他一些数据结构),其中包含在类模块中定义的所有可用状态变体。像这样:
user_status = ("NO_ACCOUNT",
"ACCOUNT_CREATED",
"NOT_VERIFIED",
"VERIFICATION_FAILED_SMS",
"VERIFIED")
另一个是拥有一个与users
表具有一对多关系的数据库表:
id status
0 "NO_ACCOUNT"
1 "ACCOUNT_CREATED"
2 "NOT_VERIFIED"
3 "VERIFICATION_FAILED_SMS"
4 "VERIFIED"
现在,有趣的是,在这两种情况下,users
表的status
字段将存储与编码到数据结构或数据库表中的预定义状态相对应的整数。在任一解决方案中,users
表都与其他表无法区分。
数据库版本将确保查找表中存在状态值。从理论上讲,代码版本可以分配任何值,但是,实际上,每个状态评估和对users
表的更改都是通过类方法实现的,除非编码错误,否则会很难制作错误。
在大多数情况下,我认为两种解决方案都是等效的。
但是,当编写代码来处理各种状态时,事情变得有趣。假设我想根据用户的状态采取行动。假设已经检索了值并将其分配给类中某处的self.user_status
,我可能会这样做:
if self.user_status == 0:
print "NO_ACCOUNT: do something relevant"
elif self.user_status == 1:
print "ACCOUNT_CREATED: do something relevant"
...
etc
换句话说,我们在代码中有不受欢迎的幻数。不好的主意。
我真正想要的是这样的:
if self.user_status == NO_ACCOUNT:
print "NO_ACCOUNT: do something relevant"
elif self.user_status == ACCOUNT_CREATED:
print "ACCOUNT_CREATED: do something relevant"
...
etc
这意味着定义一组变量来捕获值(在C中这些将是#define
但在Python中没有这样的东西:
NO_ACCOUNT = 0
ACCOUNT_CREATED = 1
NOT_VERIFIED = 2
VERIFICATION_FAILED_SMS = 3
VERIFIED = 4
现在我们有一套看起来很干净的条件,但我们仍在处理必须每次更改时都要维护这些变量 - 查找表解决方案。也许我们添加一个新的状态代码或删除旧的状态代码。
使用查找表时的情况与此没有太大区别。如果我们没有定义上面的变量,我们最终会使用带有幻数的条件,并且没有任何意义:
# This means nothing without a comment
# Prone to errors
if self.user_status == 0:
字典可能是更好的解决方案,而不是创建一堆变量。条件仍有意义:
if self.user_status == status_codes["NO_ACCOUNT"]:
最后,即将完整循环,可以在类初始化期间通过从数据库中读取查找表来加载此字典,以便建立键值对。在这种情况下,如果修改了查找表中的值,则代码可能变得“脆弱”。例如,如果我决定将“NO_ACCOUNT”更改为“ACCOUNT_MISSING”,则代码会中断,我们必须重构才能修复。
我理解规范化并使用DBMS来强制执行完整性等。我在这里思考的部分是决定在哪里存储这种查找表的行:在代码中?在db?或两者都加倍维护?
我不是在寻找意见,而是在制作这些选择时使用各种算法。也许基于DB理论对这个问题有一个非常强烈的答案。好多了。