写出您的名词,动词,形容词是一种很好的方法,但是我更倾向于将类设计看作是询问应该隐藏哪些数据的问题?
假设您有一个Query
对象和一个Database
对象:
该Query
对象将帮助您创建和存储查询-存储是此处的关键,因为函数可以帮助您轻松创建一个查询。也许您可以留下:Query().select('Country').from_table('User').where('Country == "Brazil"')
。语法无关紧要-这就是您的工作!-关键是对象可以帮助您隐藏某些东西,在这种情况下,是存储和输出查询所必需的数据。对象的强大功能来自使用它的语法(在这种情况下,是一种巧妙的链接),并且不需要知道它存储了什么才能使其工作。如果操作正确,则该Query
对象可以输出对多个数据库的查询。它在内部将存储特定格式,但在输出时可以轻松转换为其他格式(Postgres,MySQL,MongoDB)。
现在让我们仔细考虑一下Database
对象。这个藏起来什么?显然,它不能存储数据库的全部内容,因为这就是我们拥有数据库的原因!那有什么意义呢?目的是向使用对象的人员隐藏数据库的工作方式Database
。好的类将在处理内部状态时简化推理。对于此Database
对象,您可以隐藏网络调用的工作方式,或批处理查询或更新,或提供缓存层。
问题是这个Database
对象很大。它代表了如何访问数据库,因此它可以做任何事情。显然,根据系统的不同,很难进行联网,缓存和批处理,因此将它们隐藏起来将非常有帮助。但是,正如许多人会注意到的那样,数据库异常复杂,而且与原始DB调用之间的距离越远,调整性能和理解事情的工作就越困难。
这是OOP的基本权衡。如果选择正确的抽象,它会使编码更简单(字符串,数组,字典),如果选择的抽象太大(数据库,EmailManager,NetworkingManager),则可能变得太复杂而无法真正了解其工作原理或如何处理。期望。目的是隐藏复杂性,但是一定要复杂。一个好的经验法则是从避免Manager
对象开始,而是创建类似的类structs
-它们所做的只是保存数据,并使用一些辅助方法来创建/处理数据,从而使您的生活更轻松。例如,在以EmailManager
调用sendEmail
一个Email
对象的函数开始的情况下。这是一个简单的起点,并且代码很容易理解。
对于您的示例,请考虑需要将哪些数据组合在一起以计算所需的内容。例如,如果您想知道一只动物走了多远,您可以拥有AnimalStep
和AnimalTrip
(收集AnimalSteps)类。既然每个Trip都具有所有Step数据,那么它应该能够弄清楚它的内容,也许AnimalTrip.calculateDistance()
是有道理的。