adr*_*ndz 5 ruby architecture datetime design-patterns ruby-on-rails
我正在寻找有关如何为一个棘手的问题构建优雅解决方案的指导.虽然我使用的是Ruby(和Rails),但我认为我的问题主要是建筑问题,尽管我对语言的选择显然会对涉及图书馆等的建议产生影响,因此语言仍然具有相关性.
无论如何,简而言之:我的应用程序包含代表会员资格的对象,属于健身设施成员.会员资格包含一系列定期付款.有些会员资格会在学期结束时自动续约,而其他会员则不会.
因此,例如,您可能拥有初始期限为一年的成员资格,然后在此之后每月更新一次.在应用程序中,创建此类成员资格会导致创建12个定期付款.当上个月到期时,会员资格也会到期.每日cron任务负责导致成员资格根据已完成的付款到期.如果成员资格设置为自动续订,则相同的cron任务将续订成员资格.
您可能还拥有没有初始任期的会员资格,只需按月或按周运行.这些工作方式类似,减去最初的付款时间安排.
到现在为止还挺好.使事情变得复杂的是附加要求:
管理员可以"冻结"成员资格(暂停),持续特定的持续时间,之后他们会自动重新激活(例如代表在一段时间内去度假的人).我现在可以选择冻结成员资格并稍后重新激活,或者我可以选择通过在将来的某个时间点设置冻结日期来安排冻结,以及重新激活日期(注意:始终有重新激活日期,这让事情变得容易一些).
管理员可以立即取消会员资格,也可以在将来设置取消.(未来的取消尚未建成.)
管理员可以退还会员资格,这类似于取消,除非过去的付款都退还.
使这些难以处理的原因是对经常性支付的影响.冻结成员资格时,定期付款必须在冻结期间"延长",以便不支付代表冻结的时间段.这在概念上和编程上都难以处理.例如,付款可以延长不同时期(即,每隔一周付费的人的每次付款支付两周的会员资格),并且取消日期可以是付款所涵盖的期间内的任何地方.
对于冻结,我采用了成员资格对象包含一些日期的方法,即"freeze_on"和"thaw_on"来处理冻结期.然而,客户现在也希望将来取消,我注意到冻结功能的一些错误,这让我相信我需要重新考虑我的方法.
我正在考虑改变事情,以便可以安排未来的事件,但对应用程序的经常性付款部分没有影响.想法是排队特定事件.例如,未来的冻结将通过在特定日期排队冻结事件和在后续日期解冻事件来完成(这两个事件将从用户的角度连接到单个"预定冻结").未来取消将以类似方式处理.
这种方法有一些好处,例如,如果你想取消未来的取消(这是我正在谈论的那种烦人的,棘手的东西),你可以简单地从事件队列中删除预定的取消.
然而,我有一种唠叨的感觉,我可能只是从煎锅跳进火里.我想知道是否有人可以就此问题向我提供一些指导.我可以检查这类问题的设计模式或现有架构原则吗?
另外需要注意的是,对于具有预定条款的会员资格(即不是每月自动续订)的定期付款必须作为可编辑的数据库记录(及时移动,价格调整)存在,因此使用时间表达式(如Martin据我所知,福勒建议不适合这个问题.我意识到我提议的事件队列解决方案不会向用户显示任何现有定期付款会发生的变化,但我认为我可以接受这一点.
不是扫描生活条形码,它是一个二维码
多伦多,给我们你的创意人
编辑:回应下面两个很好的建议(评论框不允许几乎这个级别的细节):
克里斯罗宾逊:
是的,冻结期可以是任意长度,但实际上我认为它不到两周就很少见.但无论期间长短,任何解决方案都应该有效.
是的,更新日期会发生变化 - 它会被冻结的长度推进.因此,如果冻结时间为两周,则会将付款推迟两周.为了使事情变得特别棘手,在某些企业中,付款只能在特定日期提取 - 例如,某些俱乐部仅在每个月的1日和15日处理付款.因此,当日期被推迟时,对于这些俱乐部,他们必须"抓住"特定日期.
您能否更详细地解释为什么这些规则会影响事件排队而不影响订阅付款的管理?
我对您的摊销表概念感兴趣.这基本上就是我已经建立的 - 一个为期一年的会员每月支付创造了12个,每周创造了52个 - 并且每个都有与他们相关的金额,税收等,以及管理的状态机"待定","已付款","失败"和"退款"状态.
我正在努力的部分是这个表如何响应事件.现在,如果您设置冻结,它会立即通过更改付款日期来影响表格.在表格中间设置冻结,然后向前推送付款.这听起来很有效,但它实际上非常复杂且难以管理.您的摊销表如何改善这种情况?
Arsen7:
这听起来像我最初提出的事件队列.我很明显你以前曾经使用过这样的东西(我对你的处理日期的错误检查印象深刻,这是一个好主意,我打算尽快实施)所以我希望你能解释一下你的建议更详细一点.
具体来说,我想知道你的概念将如何处理我在原始问题中描述的经常性付款情况,以及我刚刚在Kris Robison的回答中留下的评论.如果我已经为特定购买设置了定期付款的时间表,并且在付款中间安排了冻结事件,那么付款时间表将保持不变,直到冻结日期变为当前日期为止.冻结的时间到了,付款会继续下去吗?
这对我来说可能是一种简化我的应用程序的好方法,但我想知道用户如何看待它.我如何向他们表明他们在安排冻结时所看到的付款时间表不再是准确的时间表,但一旦冻结就会改变?
是否可以采用银行使用的方案,即每天处理一次所有帐户操作?每个对象都可能有一组(未来的)操作,例如冻结期,并且每天该对象都必须做出一个简单的决定,例如:“我今天是否应该过期?”
好的方面是,这种日常处理的编程非常简单。另外,一个奇怪的续订规则(如果您需要它们)设计起来很简单:“是星期五吗?这是本月的最后一个吗?如果是,请将我标记为续订,在所需付款中添加一些金额,或执行任何操作”。
每次询问对象时动态计算状态的成本非常高(就计算能力而言)。如果你存储当前的“账户”,当你想要预测未来的状态时,你只需要更复杂的计算。
将其视为伪代码:
def process(day)
raise "Already processed or missed a day" unless day == last_processed_day + 1
check_expiration day
check_frozen day
check_anything day
#...
self.last_processed_day = day
self.save!
end
Run Code Online (Sandbox Code Playgroud)
回复:
具体来说,我想知道您的概念将如何处理我在最初的问题中以及我刚刚对克里斯·罗宾逊的答案留下的评论中描述的定期付款情况。如果我为特定购买设置了定期付款时间表,并且在付款中间安排了冻结事件,那么付款时间表是否会保持不变,直到冻结日期成为当前日期(此时)何时开始冻结并提前付款?
我觉得这可能是简化应用程序的好方法,但我想知道用户会如何看待它。我如何向他们表明,他们在安排冻结时查看的付款时间表不再是准确的时间表,而是在冻结发生后会发生变化?
“每日处理”方案可帮助您快速回答需要复杂计算的问题。
您有三个“组”:当前状态(经常询问)、历史(几乎从未改变,询问相对较少)和未来。
您的日常处理过程不仅限于更新“当前”状态。如果在处理的当天安排了某些事件,则该过程可能需要添加“历史”记录。
如果您的用户经常询问有关未来的问题(正如您所说,他们会的),“处理”也可能会为这些问题创建一种缓存。例如:查找(计算)下一个付款日期,并将其写入辅助表(时间表)中。
您需要做的主要事情是决定用户将提出哪些问题,以及您是否能够即时计算答案还是需要准备答案。
在银行(当然,情况有所不同),如果您询问当前余额,他们可能会给出当天开始时的答案。“更好”的银行会告诉你,早上你有X$,但现在还有Y$等待记账。
因此,如果您将冻结记录放入事件队列中,您可以调用一个方法,该方法将立即更新时间表。相同的过程(或非常相似的过程)将或可能在日常处理例程中被调用。
归档时间: |
|
查看次数: |
667 次 |
最近记录: |