|
Objective-C 的 API 设计(二)
8 |
[tileController displayMenuCenteredOnPoint:loc inView:self.view]; |
Rule 7: 臃肿的demo通常意味着组件是糟糕的 另一个推论:您的demo的大小是衡量你component质量的标准,其值越小越好。Demo/Code 应该尽可能的小巧而又精简(用于演示,旨在描述所有组件的定制或功能)。 核心思想是当你的代码从你的空的Xcode项目模板到你的demo中应该保持最小化的修改。这并不是一个好的借口当你需要复制粘贴demo来让你的component运行。 Rule 8:分析特定的场景 我对于apps的准则就是:不要让用户去做选择。选择满足多数人的人性化的默认设置,略去参数设置窗口。毕竟,好的软件都是有倾向性的。 由于运用场景不是那么的清晰明确,所以不同的组件面对的情况也有些不同。你当然可以做一个只满足某种特定情况的组件,但是,通常我们都希望有些灵活性。你绝不会准确的知道另一个开发者将会怎样使用你的组件,所以你必须做到有一定的通用性。 认真的选择你的定制点是很重要的。考虑依赖关系更加的重要――不是对编译/链接的理解,而是定制类型之间的逻辑关系。我的方法就是尽量从“方面”的层次上考虑而不是实例变量的层次上。你希望你的组件的那些方面允许被定制化?那么你就知道哪些特定的属性需要暴露。 通过不暴露足够的的配置点,就可以很容易的弱化某个特定的定制类型。例如: 1.如果没有考虑圆角半径,就不要暴露宽度和高度。 2.如果没有高亮的背景颜色,就不要暴露背景颜色。 3.如果没有空间,就不要暴露大小。 具体的情况取决于具体的组件,但是需要从外观或者功能角度来考虑属性之间的关系。学会理解开发者。不要禁止组件的个性化,让它灵活些。
1 |
@property (nonatomic) BOOLdismissAfterTileActivated; |
2 |
@property (nonatomic) BOOLrightHanded; |
4 |
@property (nonatomic) NSInteger tileSide; |
5 |
@property (nonatomic) NSInteger tileGap; |
6 |
@property (nonatomic) CGFloat cornerRadius; |
让常识来指导你。确定那些能够满足70%左右你所能想到的使用场景的选项,然后提供这些选项。剩下的就让你的授权方法和代码架构来满足吧。 Rule 9: 多点属性,少点方法 有一个特定的模式持续出现在我所喜欢的一些来自标准库、开源的第三方以及我自己的一些代码组件。它是一个组件中属性(或者访问器,定制点)个数与方法(也就是所有其它的,从初始化到状态更新)个数的比率。 多属性少方法(再申明一次,方法不是指在Interface Builder中的那些)。MGTileMenu有一个初始化函数和四个实际上供公共使用的愿意非常(每一个都很方便调用另一个方法)。对定制点而言,它的比率有4倍之多。我认为这是一个非常好的比率,使组件不但在功能上变得简洁,而且在定制时更加灵活。
1 |
- (id)initWithDelegate:(id
)theDelegate;
|
2 |
- (CGPoint)displayMenuPage:(NSInteger)pageNum centeredOnPoint:(CGPoint)centerPt inView:(UIView *)parentView; |
4 |
- (void)switchToPage:(NSInteger)pageNum; |
Rule 10: 在你的控件中使用控件 一个同时简化组件API和实现的好方法就是在你的实现中使用己有的控件。具有统一的外在并不意味着你不可以使用已经存在的组件(确实,这是软件工程当中的一个基本原则)。 考虑是什么让UITableViewCell和UIButton拥有简单的API接口,发现这是因为它们使用诸如UIImageView和UILabel这样的子控件。你也可以,并且该这样去做,并且如果可行的话使用相应的子控件来使你的类接口保持简单不变。 举个例子,在MGTileMenu中,它的外表是常规的UIButtons(不只是子类)。跟在一个的view中自定义去画它的样式、处理输入事件和支持访问而言,极大地简化了它的实现。 Rule 11: 于人方便就是于己方便 你会很自然地在实现的过程中加入合适的方法并下意识地将其设置为私有的。相反,应该考虑是否可以公开这些方法,使这些组件能被集成到别人的应用程序。 对你而言那些如何简单方便地加入一个方法或函数的方式,对开发者而言同样如此。 举例来说,在MGTileMenu中,我创建了这些合适的函数:
1 |
CGRect MGMinimallyOverlapRects(CGRect inner, CGRect outer, CGFloat padding); |
3 |
CGGradientRef MGCreateGradientWithColors(UIColor *topColorRGB, UIColor *bottomColorRGB); |
第一个函数可以帮助我移动tile menu使它在父View完全可见(如果它们对菜单提供辅助的用户接口,便可以方便地让其它的开发者使用),第二个返回一个渐变Core Graphics给UIColors,它被我用来设置tiles的默认的背景(同时 当实现MGTileMenu的代理协议 时,其它的开发者们发现可以很方便的给tiles配置渐变色)。 Rule 12:魅力可以,魔数却不行。 你迟早都会在你的component中加入一些魅力。人人都希望有大量的Steve Jobs式的直观、宜人、富于掌控力的魅力,但是我所说的却是代码中的一些东西,诸如拥有特殊含义的数字或者值。例如,-1在某项设置或者某个特殊场景中,就有着某个特定的意义。 很好,那样做真的挺好的。不爽的是你的代码中充满一些莫名其妙的原始值,更不爽的是还将它们暴露在API中。如果你正在暴露一些魔数,那么为了便 |