成就/徽章的架构
Posted
技术标签:
【中文标题】成就/徽章的架构【英文标题】:Architecture for achievements / badges 【发布时间】:2012-12-05 06:21:32 【问题描述】:已经有很多关于编写类似于 SO 的徽章系统的问题,我的问题有所不同。假设我有一个网页系统、徽章/成就,在数据库中存储为一行,其中包含成就密钥 (id)、用户 ID 和任何其他数据。
我的简单问题是,我应该将徽章 ID 存储在哪里?每个成就我都有一个课程,其中包含所有数据和方法来测试它是否已经获得。我想我可能有几十个或几百个。我希望这些 ID 只使用一次硬编码,并且在一个简洁的地方,所以我不会意外更改它们或混淆它们。
我可以在课堂上对它们进行硬编码,比如
public int Key get return 15; // I'm calling it Key, not ID
但是,如果我将我的成就拆分到多个文件中,我不想在添加新的时候到处寻找最高的密钥并冒着出错的风险。
我可以把它们放在另一个类的字典里...
public class AchievementSet
private Dictionary<int, Achievement> _achievements;
public AchievementSet()
_achievements = new Dictionary<int, Achievement>()
1, new SomethingAchievement()
;
但是现在类本身不知道它自己的密钥,它需要(或者是吗?)如果我现在将它传递给构造函数,我冒着数字不匹配的风险。
有什么建议吗?
【问题讨论】:
为什么不将徽章存储在数据库中? 我想,因为每个徽章都有关联的代码,您仍然需要将该代码与徽章 ID 匹配。所以它基本上不会解决任何问题。 【参考方案1】:在 Stack Overflow 的上下文中,我想每个徽章都具有以下属性: ID、姓名、等级(青铜、白银或黄金)和描述等。
您提到您目前为每个徽章/成就都有一个班级,每个班级都对授予它的条件进行了适当的检查。
我建议您放弃您现在正在查看的模型(每个成就一个课程)的原因是因为当您在 200 种不同的环境中导航时,您将继续面临巨大的问题寻找你记不起的那个 ID 的类。
通过将您的徽章存储在表格中,您的数据都在一个逻辑位置,而不是分散在您的应用程序中。
在回答问题时:您是否不同意接受的回答:***.com/questions/3162446/
不一定,我更喜欢这个想法,而不是我之前提出的一个单一班级的提议,该班级将根据他们的 ID 检查所有徽章。
尽管有它的名字,但我相信 RexM 并没有在该文件中定义 CommenterBadge
本身,应该将其命名为 CommenterBadgeJob
。 (您会注意到它没有我在答案中定义的任何特征,并且继承自 BadgeJob
)。显而易见的问题是“每个徽章作业如何知道它对应于哪个 BadgeId?”
我会在我的Badge
中添加一个名为BadgeJob
的唯一字段,您可以通过它查找徽章。
enum BadgeClass Bronze, Silver, Gold
//This class would be inherited from the database.
public class Badge
public int Key get;set;
public string Name get;set;
public BadgeClass Class get;set;
public string BadgeJob get;set;
public string Description get;set
我会修改他的代码如下:
public class CommenterBadgeJob : BadgeJob
public Badge commenter_badge get;set;
public CommenterBadgeJob() : base()
//Lookup badge
string badge_job_name = this.GetType().Name;
commenter_badge = db.Badges.Where(n=>n.BadgeJob == badge_job_name).Single();
protected override void AwardBadges()
//select all users who have more than x comments
//and dont have the commenter badge
//add badges
//run every 10 minutes
protected override TimeSpan Interval
get return new TimeSpan(0,10,0);
【讨论】:
那么您不同意***.com/questions/3162446/… 接受的答案吗? 我已经更新了我的答案。如果我不清楚,请告诉我,我会尝试修改我的答案。 我已经将所有数据放入数据库中,这很有效,因为我的大部分成就都具有简单的条件,例如某些字段 >= 阈值。谢谢!【参考方案2】:使用枚举怎么样?
public enum BadgeTypes
GoodAnswer = 1,
Commenter = 2,
Teacher = 3,
//...
每个 BadgeJob 都可以有一个 BadgeType
属性,该属性将用于在 AwardBadges()
期间插入成就时填充徽章 ID(枚举值可以保留为整数)。
我认为没有必要为每个成就设置一门课程。 BadgeJob
包含所有徽章归属逻辑,BadgeTypes
足以代表不同的徽章。
【讨论】:
但是每个成就不是有一个Job
类吗?这似乎是一回事……我不想要一个长达数千行的“逻辑”类。
是的,每个成就都有一个工作类别(“BadgeJob 的包含...”是复数形式)。抱歉,如果不清楚。
或者,您的意思是,您不希望每个成就有一个工作类别?我看不出这会更短:/
我确实想要一个,因为我不想要一个庞大的班级。但是,如果逻辑在单独的类中,它们的数据(名称、描述)也可以放在那里。
枚举值不能包含空格或标点符号。但我知道你要去哪里。链接也不错。以上是关于成就/徽章的架构的主要内容,如果未能解决你的问题,请参考以下文章
如何在对系统的影响最小的情况下为您的 APP 处理成就/徽章/奖励?