构建框架时需要考虑的事项

jai*_*jai 10 java frameworks

我们正计划构建一个框架:一个成本估算框架,将在我们组织的各个领域中使用.

高级要求是这样的:如果我开发某种产品,我会花多少钱?生成的成本将用于与供应商引用的成本进行比较,并决定选择哪个供应商.

现在,我的问题是: 在开发框架时需要考虑哪些事项?

我很少想到:

  1. 通过抽象类和接口实现高级需求
  2. 提供可能对Framework用户有用的实用程序类.
  3. 考虑应该是什么内部 - 一种元数据 - 不应该向框架用户显示.
  4. 设计模式使用像模板一样.
  5. 输入类的属性和方法.

Jon*_*eet 13

一些想法:

  • 稍后添加有用功能比删除已被证明设计糟糕或有害的功能更容易.
  • 设计继承或禁止它:继承引入了额外的复杂层,因为您需要计算超类和子类之间的交互.这并不是说这是邪恶的,但应非常仔细地考虑.
  • 在我的经验中,接口通常比抽象类更清晰,因为它们促进了继承的组合.
  • 对于接口,记录调用者应该期望的内容以及实现者应该期望的内容.基本上从双方想出合同,并记录下来.特别是,文档无效约束 - 方法是否应该接受null?他们应该保证他们永远不会归零吗?
  • 使用框架设计可测试性,包括框架和其他框架.框架的哪些位可以合理地用在测试代码中,哪些应该被嘲笑?
  • 从一开始就使用您自己的框架.构建一个其他人可以用来理解框架的示例应用程序.

  • 只是提出一个反驳论点.对于快速发展的框架(以及因此大多数新的框架),接口的使用经常被放弃.请参阅"接口被高估" - http://www.artima.com/weblogs/viewpost.jsp?thread=142428 (2认同)

LBu*_*kin 6

下面的一些建议取决于您是否构建一个框架,严格由一个小团队在一组有限的项目中内部使用,或者您是否正在构建供许多匿名开发人员使用的东西.另外,请记住,很大程度上取决于框架的大小以及范围的宽度或范围.我的一些建议实际上只适用于更大的多用途框架.

一般建议

  • 花些时间与将要使用您的框架的一些开发人员交谈.确保你真正理解什么是有用的,什么不会.
  • 花点时间确保您创建的抽象对您的未来用户来说是可理解和直观的.
  • 除非您正在构建独特且具有革命性的内容,否则请花时间查看域中存在的其他框架.避免他们的错误,但不要害怕借用成功的概念......不是一切都必须由你发明.
  • 以正式的API文档和示例代码的形式生成文档.如果人们无法理解如何应用您的框架,那么它将无法成功.
  • 简明扼要地命名.这可能是框架开发人员最难的任务之一 - 尤其是在实现抽象概念或通用概念时.在确定名称之前与人交谈.某些名称具有多种含义,可能与您的预期不同.
  • 考虑使您的框架与其他低级框架(如用于日志记录,模拟和依赖注入的框架)兼容.这将使您的用户满意并减少采用的障碍.
  • 投资良好的单元测试.框架通常具有大的表面区域,用户可以与...交互......许多类,许多方法,派生,接口实现.如果没有快速回归测试的能力,框架可以快速增长到可以维持的水平.
  • 保持您的公共接口狭窄和小.在框架中设计功能时,请牢记单一责任原则......在这个层面上真的很重要.

设计咨询

  • 并行性的设计和测试.如今,大多数框架都用于构建具有一些(通常很多)并行处理活动的应用程序.特别是在Web应用程序中使用的框架需要仔细考虑多线程访问将如何影响它们.我遵循的一些一般原则是:
    • 尽可能避免锁定.如果不可能,请使用显式锁定对象而不是.NET lock(...)语句.
    • 对读取频率高于写入的共享对象使用读/写锁.
  • 将功能设计到图层中.对于大型框架,这不仅有助于保持功能解耦,还允许用户更容易地使用他们实际需要的框架部分.
  • 对于打算与.NET 2.0及更高版本一起使用的框架,请使用泛型集合!很难推断出存储在object [],ArrayList或Hashtable中的内容......尤其是在内部传递此类集合的大型框架中.
  • 避免在公共接口中使用对象或对象[]这在框架中是邪恶的,并且是导致错误和可维护性问题的主要原因.您几乎总能找到一个界面或使用泛型来代替这一点.在极少数情况下,你不能,准确记录你希望传入或传出的内容......并断言它.
  • 首选聚合到继承.虽然继承是一个有用且强大的概念,但框架作者经常过度使用或滥用它.仔细考虑继承是否真的是解决设计问题的正确工具.
  • 尽可能避免使用类型转换和运行时类型检查.根据我的经验,这些通常是一种设计气味.Lot的铸造表明您没有有效地利用接口,泛型或通用约束.这可能会导致开发人员对如何使用框架的错误和混淆.
  • 允许调用者尽可能使用策略注入功能.对于某些专业化来说,继承是过度的.随着支持功能级别成为.NET生态中的公民,您应该使用它们(以lambdas或委托的形式)来允许消费者专门化您提供的功能.

实施建议

  • 避免吸气剂产生副作用的物质.有时这是不可避免的(例如执行内部缓存的getter,或懒惰实例化对象).但是,根据我的经验,带有副作用的getter(特别是在框架级代码中)是引入heisenbugs并让你的用户在调试时诅咒你名字的最快方法.
  • 如果可能,使小的瞬态对象不可变.使用该语言中的readonly(或等效)关键字强制执行此操作.不可变性的好处是巨大的 - 在.NET中(分配成本降低),它并不像你想象的那么昂贵.
  • 尽可能使用自封装.此技术通过避免内部与外部调用者的数据的不同访问语义,有助于避免错误并简化重构.
  • 避免使用魔术数字和硬编码常量.框架是一种代码,很难预测用户的确切需求.通过使用配置而不是编译常量来保留一些灵活性.
  • 保持方法的参数数量很小(小于7).当您需要传入许多参数时,请考虑创建一个轻量级数据对象来支持该方法.
  • 优先考虑不同类型的多个方法重载的泛型方法.让语言和编译器尽可能地完成工作.这也使您的代码更加灵活和有用.检查LINQ的设计,了解它在实践中的工作原理.