背景:SICP读到第三章节,我印象最深刻的就是用数据驱动设计来实现一个带有通用型操作的系统。简单来说就是,这套系统支持这种功能,不管你的数据类型是什么,有理数,复数,常规算术,支持一套同样的操作。比如加法。都支持(add x y),不管你x,y 是什么类型的数据。你不用管细节。具体看《计算机程序的构造和解释》第128页。不过最好从115页的2.4节开始看。因为经过前面的常规方法,你更能体会数据驱动设计的优势。
今天我们看一个常规的问题。如果我们做的项目,用国际化的,当用户注册信息的时候,我们需要根据不同的情况向他们发送不同的信息,比如它来自中国,向它发送中文,是美国的,发送英文。
下面是常规的新手会写出的代码。基本就是通过if,else逻辑不断的判断:
from User import User
from EmailService import EmailService
#
# main function
#
def main():
#
# Fetch the current user
#
new_user = User()
new_user.load_from_session()
#
# Welcome email
#
if new_user.country == "fr":
subject = "Bonjour et bienvenue sur notre site"
content = "Bonjour et Bienvenue sur notre tout nouveau site. Contactez l'équipe de support si vous avez des..."
EmailService.send(new_user.email, subject, content)
elif new_user.country == "us" or new_user.country == "ca":
subject = "Welcome to our site"
content = "Hello and Welcome to our brand new site. Contact support team if you have any questions."
EmailService.send(new_user.email, subject, content)
#
# run main
#
if __name__ == "__main__":
main()
这段代码的问题在于,现在只有几个国家,当我们市场越来越大,需要不断地加入新的国家,假以时日,代码维护和扩展都不好做。为了解决这个问题,下面是数据驱动设计的做法:
from User import User
from EmailService import EmailService
rule = [
{
"country": ["fr"],
"subject": "Bonjour et bienvenue sur notre site",
"content": "Bonjour et Bienvenue sur notre tout nouveau site. Contactez l'équipe de support si vous avez des..."
},
{
"country": ["us", "ca"],
"subject": "Welcome to our site",
"content": "Hello and Welcome to our brand new site. Contact support team if you have any questions."
}
]
def main():
user = User()
user.load_from_session()
for rule in rule_set:
# 处理规则
if "country" in rule and user.country in rule["country"]:
EmailService.send(user.email, rule["subject"], rule["content"])
if __name__ == "__main__":
main()
这段代码以后就好扩展了,如果有新的国家,只要往列表里加入数据就行了。这样的代码更解耦,更灵活,方便扩展。其实《代码大全》也有一章讲这种设计思想的,有兴趣的可以去翻翻。