首先来看YuShuBook。之所以YuShuBook会出现大量的classmathod,他的原因就在于:YuShuBook并不会保存数据,而是把所有数据都返回给了调用方去;换句话说YuShuBook是个伪面向对象(伪类),因为他只是包装了一系列的方法,而没有存储这个类的特征,数据。
YuShuBook关键词缀在Book中,依此可以知道,我们这个类是用来描述书籍的,而search_by_isbn,search_by_key这些方法返回的就是关于书籍的数据,所以我们完全可以用这个方法所返回的数据来描述类本身,把他存储到类的内部,而不是返回到外部去(保持类的内聚性)
class YuShuBook:
search_by_isbn_url = "http://t.yushu.im/v2/book/isbn/{}"
search_by_key_url = "http://t.yushu.im/v2/book/search?q={}&count={}&start={}"
def __init__(self):
self.total = 0
self.books = []
def search_by_isbn(self, isbn):
url = self.search_by_isbn_url.format(isbn)
result = HTTP.get(url)
self.__fill_single(result)
def search_by_key(self, q, page=1):
url = self.search_by_key_url.format(q, current_app.config["PRE_PAGE"],
self.calculate_start(page))
result = HTTP.get(url)
self.__fill_collection(result)
def __fill_single(self, data):
if data:
self.books = [data]
self.total = 1
def __fill_collection(self, data):
self.books = data['books']
self.total = data['total']
def calculate_start(self, page):
return (page-1) * current_app.config["PRE_PAGE"]
# 具体的单一数据处理封装在BookViewModel里
class BookViewModel:
def __init__(self, book):
self.title = book['title'],
self.publisher = book['publisher'],
self.pages = book['pages'],
self.author = book['author'],
self.price = book['price'],
self.summary = book['summary'],
self.image = book['image']
# BookCollection只负责集合的处理
class BookCollection:
def __init__(self):
self.keyword = ''
self.total = 0
self.books = []
def fill(self, yushu_book, keyword):
self.keyword = keyword
self.total = yushu_book.total
self.books = [BookViewModel(book) for book in yushu_book.books]
在重构的时候,我们没有在类中保存查询参数,如果保存了查询参数,在代码层面是没有问题的,但是存在一个问题就是:YuShuBook的作用是隐藏了数据的具体获取方式,也就是说YuShuBook足够的抽象,他不需要我们去关心数据具体是怎么来的,但是如果我们把查询参数也加入到类里面来之后,他就会使得这个类更加的具体化,因为我们保持的数据更多,更加精准,甚至描述了使如何获取数据的,一般一个类太具体化就会存在一个扩展和修改的问题,加入YuShuBook有一天内部的数据来源改成从数据库里获取信息,那么这样的情况下面,我们把查询参数放在YuShuBook中反而不好了,他减少了YuShuBook的灵活性