也许是因为我现在已经编写了大约两个学期的编码,但是我现在遇到的主要绊脚石是将教授的项目描述和要求转换为实际的代码。由于我目前在算法101,我基本上做一个自下而上的过程,从空白白板开始,绘制对象和方法的交互,然后将其转换为类和代码。
但是现在教授已经将接口和抽象类混合在了一起。从理智上讲,我可以认识到它们是如何工作的,但我正在弄清楚如何在当前项目中使用这些新工具(模拟Web服务器)。
在我的教授自己的话中,将抽象描述映射到Java代码是真正的伎俩。那么从英语(或任何语言)到计算机代码最常用的步骤是什么?您如何决定创建界面的位置和时间,或使用抽象类?
那么从英语(或任何语言)到计算机代码最常用的步骤是什么?
经验教你如何做到这一点。如果它还没有自然而然地出现(如果没有,那就不要感觉不好,因为它需要很长时间!),你可以问自己一些问题:
该系统的主要概念是什么?它们如何相互关联?如果我向别人描述这个,我会用什么词和短语?这些想法将帮助您确定哪些类是有用的思考。
这些东西有什么样的行为?它们之间是否存在天然的依赖关系? (例如,a LineItem
没有背景,没有相关性或意义 Order
,也不是 Engine
很多没用的东西 Car
。)行为如何影响其他对象的状态?他们是否相互沟通,如果是,以何种方式沟通?这些想法将帮助您开发类的公共接口。
当然,那只是冰山一角。有关这个思想过程的更多信息,请参阅Eric Evans的优秀书籍, 领域驱动设计。
您如何决定创建界面的位置和时间,或使用抽象类?
没有硬性和快速的处方;再次,经验是这里最好的指南。也就是说,你可以遵循一些经验法则:
如果几个不相关或明显不同的对象类型都提供相同类型的功能,请使用接口。例如,如果 Steerable
界面有一个 Steer(Vector bearing)
方法,可能有很多不同的东西可以引导: Boat
S, Airplane
S, CargoShip
S, Car
等等。这些是完全无关的事情。但它们都共享能够被引导的共同界面。
通常,尝试使用接口而不是抽象基类。这样您就可以定义一个实现N个接口的实现。对于Java,您只能拥有一个抽象基类,因此一旦您说某个类继承自另一个类,您就会被锁定到特定的继承层次结构中。
每当你不需要从基类实现时,肯定喜欢一个抽象基类的接口。如果您使用的语言不适用继承,这也很方便。例如,在C#中,你不能拥有 struct
从基类继承。
那么从英语(或任何语言)到计算机代码最常用的步骤是什么?
经验教你如何做到这一点。如果它还没有自然而然地出现(如果没有,那就不要感觉不好,因为它需要很长时间!),你可以问自己一些问题:
该系统的主要概念是什么?它们如何相互关联?如果我向别人描述这个,我会用什么词和短语?这些想法将帮助您确定哪些类是有用的思考。
这些东西有什么样的行为?它们之间是否存在天然的依赖关系? (例如,a LineItem
没有背景,没有相关性或意义 Order
,也不是 Engine
很多没用的东西 Car
。)行为如何影响其他对象的状态?他们是否相互沟通,如果是,以何种方式沟通?这些想法将帮助您开发类的公共接口。
当然,那只是冰山一角。有关这个思想过程的更多信息,请参阅Eric Evans的优秀书籍, 领域驱动设计。
您如何决定创建界面的位置和时间,或使用抽象类?
没有硬性和快速的处方;再次,经验是这里最好的指南。也就是说,你可以遵循一些经验法则:
如果几个不相关或明显不同的对象类型都提供相同类型的功能,请使用接口。例如,如果 Steerable
界面有一个 Steer(Vector bearing)
方法,可能有很多不同的东西可以引导: Boat
S, Airplane
S, CargoShip
S, Car
等等。这些是完全无关的事情。但它们都共享能够被引导的共同界面。
通常,尝试使用接口而不是抽象基类。这样您就可以定义一个实现N个接口的实现。对于Java,您只能拥有一个抽象基类,因此一旦您说某个类继承自另一个类,您就会被锁定到特定的继承层次结构中。
每当你不需要从基类实现时,肯定喜欢一个抽象基类的接口。如果您使用的语言不适用继承,这也很方便。例如,在C#中,你不能拥有 struct
从基类继承。
一般来说...
- 阅读很多其他人的代码。开源项目非常适合。尽管尊重他们的许可证。
- 你永远不会完美。这是一个迭代过程。如果你没有把它弄好,不要气馁。
- 实践。实践。实践。
- 经常研究。继续处理越来越具有挑战性的项目/设计。即使周围有简单的人。
对于良好的设计,没有灵丹妙药或算法。
如今,我加入了一个我认为很体面的设计并从中开始工作。
当时机成熟时,我将实现理解结果必须尽快重构(重写)。
给这个项目你最好的机会,留意你的错误,以及在你取回你的结果后应该怎么做。
继续这样做,你会没事的。
你应该做的是 代码来自自上而下,而不是自下而上。尽可能清楚简明地编写主要功能,使用尚未创建的API,就好像它们已经存在一样。然后,您可以以类似的方式实现这些API,直到您拥有只有几行的函数。如果你自下而上编码,你可能会创建一些你实际上并不需要的东西。
在何时创建界面方面......几乎所有东西都应该是一个界面。当您使用尚不存在的API时,假设每个具体类都是某个接口的实现,并使用指示该接口的声明类型。您的继承应该只使用接口完成。在提供实现时,只在最底层创建具体类。我建议避免使用抽象类,只使用委托,尽管抽象类在两个不同的实现略有不同并且具有多个具有共同实现的函数时也是合理的。例如,如果您的接口允许迭代元素并且还提供求和函数,则求和函数在迭代函数方面实现是微不足道的,因此这将合理地使用抽象类。另一种方法是在这种情况下使用装饰器模式。
您可能还会发现Google Techtalk“如何设计一个好的API及其重要性“在这方面有所帮助。你可能也有兴趣阅读我自己的一些 软件设计观察。
此外,对于未来的未来,您可以继续阅读基础知识 域驱动设计 使自己与现实世界的场景保持一致 - 它为需求映射到真实类提供了坚实的基础。