国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

8次嘗試,帶你走進(jìn)iOS 精益編程

移動(dòng)開發(fā) iOS
Copy-Paste是大部分程序員最容易犯的毛病,為此引入了大量的重復(fù)代碼。

[[153315]]

開場(chǎng)

今天, 我們將從一個(gè)小功能開始, 先去不假思索的實(shí)現(xiàn)它

Product Repository: Filtering Operation

Code start

有一個(gè)產(chǎn)品庫(kù), 我們要對(duì)它做過(guò)濾操作.

***個(gè)需求并不復(fù)雜.

需求1:在倉(cāng)庫(kù)中查找所有顏色為紅色的產(chǎn)品

First Attempt: Hard Code

我們先用最簡(jiǎn)單的方式去實(shí)現(xiàn)它, 硬編碼

  1. - (NSArray *)findAllRedProducts:(NSArray *)products 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if (product.color == RED) { 
  5. [list addObject:product]; 
  6. return list; 

 

如果這個(gè)世界是永恒靜止的,這樣的實(shí)現(xiàn)無(wú)可厚非,但世界往往并非如此。

緊接著,第二個(gè)需求來(lái)了

需求2:在倉(cāng)庫(kù)中查找所有顏色為綠色的產(chǎn)品

Second Attempt: Parameterizing

Copy-Paste是大部分程序員最容易犯的毛病,為此引入了大量的重復(fù)代碼。

  1. - (NSArray *)findAllGreenProducts:(NSArray *)products 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if (product.color == GREEN) { 
  5. [list addObject:product]; 
  6. return list; 

為了消滅硬編碼,得到可重用的代碼,可以引入簡(jiǎn)單的參數(shù)化設(shè)計(jì)。

  1. - (NSArray *)findProducts:(NSArray *)products byColor:(ProductColor)color 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if (product.color == color) { 
  5. [list addObject:product]; 
  6. return list; 

終于可以放心了, 這個(gè)時(shí)候我們的產(chǎn)品經(jīng)理怎么可能讓你舒服呢,需求3又來(lái)了

需求3:查找所有重量小于10的所有產(chǎn)品

Third Attempt: Parameterizing with Every Attribute You Can Think Of

大部分程序員依然會(huì)使用Copy-Paste解決這個(gè)問(wèn)題,拒絕Copy-Paste的陋習(xí),***實(shí)效的一個(gè)反饋就是讓這個(gè)快捷鍵失效,從而在每次嘗試Copy-Paste時(shí)提醒自己做更好的設(shè)計(jì)

  1. - (NSArray *)findProducts:(NSArray *)products byWeith:(float)weight 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if (product.weight < weight) { 
  5. [list addObject:product]; 
  6. return list; 

為了消除兩者重復(fù)的代碼,通過(guò)簡(jiǎn)單的參數(shù)化往往不能***解決這類問(wèn)題,相反地會(huì)引入過(guò)度的復(fù)雜度和偶發(fā)成本。

  1. - (NSArray *)findProducts:(NSArray *)products byColor:(ProductColor)color byWeith:(float)weight type:(int)type 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if ((type == 1) && product.color == color) { 
  5. [list addObject:product]; 
  6. continue
  7. else if ((type == 2) && (product.weight < weight)) 
  8. [list addObject:product]; 
  9. continue
  10. return list; 

日常工作中,這樣的實(shí)現(xiàn)手法非常普遍,函數(shù)的參數(shù)列表隨著需求增加不斷增加,函數(shù)邏輯承擔(dān)的職責(zé)越來(lái)越多,邏輯也變得越來(lái)越難以控制。

通過(guò)參數(shù)配置應(yīng)對(duì)變化的設(shè)計(jì)往往都是失敗的設(shè)計(jì)

易于導(dǎo)致復(fù)雜的邏輯控制,引發(fā)額外的偶發(fā)復(fù)雜度

Forth Attempt: Abstracting over Criteria

為此需要抽象,使其遍歷的算法與查找的標(biāo)準(zhǔn)能夠獨(dú)立地變化,互不影響。

  1. @interface ProductSpec : NSObject 
  2. - (BOOL)satisfy:(Product *)product; 
  3. @end 

此刻filter的算法邏輯得到封閉,當(dāng)然函數(shù)名需要重命名,使其算法實(shí)現(xiàn)更加具有普遍性。

  1. - (NSArray *)findProducts:(NSArray *)products bySpec:(ProductSpec *)spec 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if ([spec satisfy:product]) { 
  5. [list addObject:product]; 
  6. return list; 

通過(guò)可復(fù)用的類來(lái)封裝各種變化,讓變化的因素控制在最小的范圍內(nèi)。

  1. @interface ColorSpec() 
  2. @property (nonatomic, assign) ProductColor color; 
  3. @end 
  4. @implementation ColorSpec 
  5. + (instancetype)specWithColor:(ProductColor)color 
  6. ColorSpec *spec = [[ColorSpec alloc] init]; 
  7. spec.color = color; 
  8. return spec; 
  9. - (BOOL)satisfy:(Product *)product 
  10. return product.color == RED; 
  11. @end 
  12. @interface BelowWeightSpec() 
  13. @property (nonatomic, assign) float limit; 
  14. @end 
  15. @implementation BelowWeightSpec 
  16. + (instancetype)specWithBelowWeight:(float)limit 
  17. BelowWeightSpec *spec = [[BelowWeightSpec alloc] init]; 
  18. spec.limit = limit; 
  19. return spec; 
  20. - (BOOL)satisfy:(Product *)product 
  21. return (product.weight < _limit); 
  22. @end 

用戶的接口也變得簡(jiǎn)單多了,而且富有表現(xiàn)力。

  1. [self findProducts:_products bySpec:[ColorSpec specWithColor:RED]]; 

這是經(jīng)典的OO設(shè)計(jì),如果熟悉設(shè)計(jì)模式的讀者對(duì)此已經(jīng)習(xí)以為常了。設(shè)計(jì)模式是好東西,但往往被濫用。為此不能依葫蘆畫瓢,死板照抄,而是為了得到更簡(jiǎn)單的設(shè)計(jì)而引入設(shè)計(jì)模式的,這個(gè)過(guò)程是很自然的。

與大師們交流,問(wèn)究此處為何引入設(shè)計(jì)模式,得到的答案:直覺(jué)。忘記所有設(shè)計(jì)模式吧,管它是不是模式,如果設(shè)計(jì)是簡(jiǎn)單的,這就是模式。

另外還有一個(gè)明顯的壞味道,ColorSpec和BelowWeightSpec都需要繼承ProductSpec,都需要定義一個(gè)構(gòu)造函數(shù)和一個(gè)私有的字段,并重寫satisfy方法,這些都充斥著重復(fù)的結(jié)構(gòu)。

是不是覺(jué)得目前的寫法已經(jīng)夠用了? 莫急, 讓我們來(lái)看看下個(gè)需求

需求4:查找所有顏色為紅色,并且重量小于10的所有產(chǎn)品

 

  1. Firth Attempt: Composite Criteria 
  2.  
  3. 按照既有的代碼結(jié)構(gòu),往往易于設(shè)計(jì)出類似ColorAndBelowWeightSpec的實(shí)現(xiàn)。 
  4. @interface ColorAndBelowWeigthSpec() 
  5. @property (nonatomic, assign) ProductColor color; 
  6. @property (nonatomic, assign) float limit; 
  7. @end 
  8. @implementation ColorAndBelowWeigthSpec 
  9. + (instancetype)specWithColor:(ProductColor)color beloWeigth:(float)limit 
  10. ColorAndBelowWeigthSpec *spec = [[ColorAndBelowWeigthSpec alloc] init]; 
  11. spec.color = color; 
  12. spec.limit = limit; 
  13. return spec; 
  14. - (BOOL)satisfy:(Product *)product 
  15. return product.color == _color || (product.weight < _limit); 
  16. @end 

 

存在兩個(gè)明顯的壞味道:

包含and的命名往往是違背單一職責(zé)的信號(hào)燈

ColorAndBelowWeightSpec的實(shí)現(xiàn)與ColorSpec,BelowWeightSpec之間存在明顯的重復(fù)

此刻,需要尋找更本質(zhì)的抽象來(lái)表達(dá)設(shè)計(jì),and/or/not語(yǔ)義可以***解決這類問(wèn)題。

Composite Spec: AndSpec, OrSpec, NotSpec

Atomic Spec:ColorSpec, BeblowWeightSpec

  1. @interface AndSpec() 
  2. @property (nonatomic, strong) NSArray *specs; 
  3. @end 
  4. @implementation AndSpec 
  5. + (instancetype)spec:(ProductSpec *)spec, ... NS_REQUIRES_NIL_TERMINATION 
  6. va_list args; 
  7. va_start( args, spec ); 
  8. NSMutableArray *mArray = [@[spec] mutableCopy]; 
  9. for ( ;; ) 
  10. id tempSpec = va_arg( args, id ); 
  11. if (tempSpec == nil) 
  12. break
  13. [mArray addObject:tempSpec]; 
  14. va_end( args ); 
  15. AndSpec *andSpec = [[AndSpec alloc] init]; 
  16. andSpec.specs = [mArray copy]; 
  17. return andSpec; 
  18. - (BOOL)satisfy:(Product *)product 
  19. for (ProductSpec *spec in _specs) { 
  20. if (![spec satisfy:product]) { 
  21. return NO; 
  22. return YES; 
  23. @end 
  24. @interface OrSpec () 
  25. @property (nonatomic, strong) NSArray *specs; 
  26. @end 
  27. @implementation OrSpec 
  28. + (instancetype)spec:(ProductSpec *)spec, ... NS_REQUIRES_NIL_TERMINATION 
  29. va_list args; 
  30. va_start( args, spec ); 
  31. NSMutableArray *mArray = [@[spec] mutableCopy]; 
  32. for ( ;; ) 
  33. id tempSpec = va_arg( args, id ); 
  34. if (tempSpec == nil) 
  35. break
  36. [mArray addObject:tempSpec]; 
  37. va_end( args ); 
  38. OrSpec *orSpec = [[OrSpec alloc] init]; 
  39. orSpec.specs = [mArray copy]; 
  40. return orSpec; 
  41. - (BOOL)satisfy:(Product *)product 
  42. for (ProductSpec *spec in _specs) { 
  43. if ([spec satisfy:product]) { 
  44. return YES; 
  45. return NO; 
  46. @end 
  47. @interface NotSpec () 
  48. @property (nonatomic, strong) ProductSpec *spec; 
  49. @end 
  50. @implementation NotSpec 
  51. + (instancetype)spec:(ProductSpec *)spec 
  52. NotSpec *notSpec = [[NotSpec alloc] init]; 
  53. notSpec.spec = spec; 
  54. return notSpec; 
  55. - (BOOL)satisfy:(Product *)product 
  56. if (![_spec satisfy:product]) { 
  57. return YES; 
  58. return NO; 
  59. @end 

可以通過(guò)AndSpec組合ColorSpec, BelowWeightSpec來(lái)實(shí)現(xiàn)需求,簡(jiǎn)單漂亮,并且富有表達(dá)力。

  1. [self findProducts:_products bySpec:[AndSpec spec:[ColorSpec specWithColor:RED], [BelowWeightSpec specWithBelowWeight:10], nil]]; 

但這樣的設(shè)計(jì)存在兩個(gè)嚴(yán)重的壞問(wèn)道:

AndSpec與OrSpec存在明顯的代碼重復(fù),OO設(shè)計(jì)的***個(gè)直覺(jué)就是通過(guò)抽取基類來(lái)消除重復(fù)。

  1. @interface CombinableSpec () 
  2. @property (nonatomic, strong) NSArray *specs; 
  3. @end 
  4. @implementation CombinableSpec 
  5. + (instancetype)spec:(CombinableSpec *)spec, ... NS_REQUIRES_NIL_TERMINATION 
  6. va_list args; 
  7. va_start( args, spec ); 
  8. NSMutableArray *mArray = [@[spec] mutableCopy]; 
  9. for ( ;; ) 
  10. id tempSpec = va_arg( args, id ); 
  11. if (tempSpec == nil) 
  12. break
  13. [mArray addObject:tempSpec]; 
  14. va_end( args ); 
  15. CombinableSpec *combinableSpec = [[CombinableSpec alloc] init]; 
  16. combinableSpec.specs = [mArray copy]; 
  17. return combinableSpec; 
  18. - (BOOL)satisfy:(Product *)product 
  19. for (ProductSpec *spec in _specs) { 
  20. if ([spec satisfy:product] == _shortcut) { 
  21. return _shortcut; 
  22. return !_shortcut; 
  23. @end 
  24. @implementation AndSpec 
  25. - (instancetype)init 
  26. self = [super init]; 
  27. if (self) { 
  28. self.shortcut = NO; 
  29. return self; 
  30. @end 
  31. @implementation OrSpec 
  32. - (instancetype)init 
  33. self = [super init]; 
  34. if (self) { 
  35. self.shortcut = YES; 
  36. return self; 
  37. @end 

大堆的初始化方法讓人眼花繚亂

  1. [self findProducts:_products bySpec:[NotSpec spec:[AndSpec spec:[ColorSpec specWithColor:RED], [BelowWeightSpec specWithBelowWeight:10], nil]]]; 
  2.  
  3. Sixth Attempt: Using DSL 

 

可以引入DSL改善程序的可讀性,讓代碼更具表達(dá)力。

我們先添加一些DSL:

  1. static ProductSpec *COLOR(ProductColor color) 
  2. return [ColorSpec specWithColor:RED]; 
  3. static ProductSpec *BELOWWEIGHT(float limit) 
  4. return [BelowWeightSpec specWithBelowWeight:limit]; 
  5. static ProductSpec *AND(ProductSpec *spec1, ProductSpec *spec2) 
  6. return [AndSpec spec:spec1, spec2, nil]; 
  7. static ProductSpec *OR(ProductSpec *spec1, ProductSpec *spec2) 
  8. return [OrSpec spec:spec1, spec2, nil]; 
  9. static ProductSpec *NOT(ProductSpec *spec) 
  10. return [NotSpec spec:spec]; 

這樣我們的代碼表現(xiàn)起來(lái)就是這樣的

  1. [self findProducts:_products bySpec:NOT(AND(COLOR(RED), BELOWWEIGHT(10)))]; 
  2.  
  3. Seventh Attempt: Using a Lambda Expression 

 

可以使用Block改善設(shè)計(jì),增強(qiáng)表達(dá)力。

  1. - (NSArray *)findProducts:(NSArray *)products byBlock:(BOOL (^)())block 
  2. NSMutableArray *list = [@[] mutableCopy]; 
  3. for (Product *product in products) { 
  4. if (block(product)) { 
  5. [list addObject:product]; 
  6. return list; 

代碼現(xiàn)在開起來(lái)是這個(gè)樣子

  1. [self findProducts:_products byBlock:^BOOL(id p) {return [p color] == RED;}]; 

構(gòu)造DSL,復(fù)用這些Block

  1. ProductSpecBlock color(ProductColor color) 
  2. return ^BOOL(id p) {return [p color] == color;}; 
  3. ProductSpecBlock weightBelow(float limit) 
  4. return ^BOOL(id p) {return [p weight] < limit;}; 
  5. - (void)test7_2 
  6. [self findProducts:_products byBlock:color(RED)]; 
  7.  
  8. Eighth attempt: Using NSPredicate 

 

還可以使用標(biāo)準(zhǔn)庫(kù)
 

  1. [self.products filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weight > 10"]]; 

結(jié)束

今天的編碼就到此為止了, 這篇文章本是Horance所寫, 筆者將用OC實(shí)現(xiàn)了一遍.如果咱們不是iOS Developer的話, 還是有其他attempt的, 如泛型.

責(zé)任編輯:chenqingxiang 來(lái)源: 曉月的專欄
相關(guān)推薦

2017-05-16 15:27:32

精益敏捷代碼

2010-03-16 17:30:14

Java多線程編程

2016-07-18 16:09:40

精益生產(chǎn)Testin質(zhì)量控制

2016-02-24 16:09:24

并行科技軟件交付

2009-12-09 13:41:50

PHP Zend框架

2011-10-08 14:38:21

精益掃描儀

2017-09-21 10:34:38

留存分析數(shù)據(jù)分析留存

2013-08-14 13:35:32

設(shè)計(jì)

2011-10-06 17:10:24

精益掃描儀

2010-09-14 10:15:24

2020-07-03 09:41:20

華為∑co時(shí)間醫(yī)療

2011-03-16 14:20:30

2020-08-11 09:47:30

JS閉包代碼

2012-06-04 15:26:29

精益掃描儀

2011-07-27 17:05:59

精益掃描儀

2015-07-22 10:25:09

NEC

2015-11-03 11:08:01

IT高性能運(yùn)維

2011-09-14 17:21:28

精益掃描儀

2014-03-27 17:20:02

金蝶

2021-01-21 15:40:45

VRARVR眼鏡
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

人人干在线视频| 国产女主播视频一区二区| 成年人国产精品| 日韩一区二区三区av| 成品人视频ww入口| 青青草免费在线视频| 在线观看wwwxxxx| 丁香久久综合| 亚洲一二三四| 成人网18免费网站| 亚洲天堂影视av| 成人av午夜电影| 欧美精选在线播放| 亚洲欧美日韩区| 真不卡电影网| 久久久久久久久97黄色工厂| 国产欧美在线一区二区| 久久草在线视频| 中文字幕无线精品亚洲乱码一区 | 日韩中文欧美| 丝袜美腿精品国产二区| 超碰免费在线播放| 欧美日韩国产中文精品字幕自在自线| av观看免费在线| 国产剧情一区二区| 亚洲精品二区| 香蕉亚洲视频| 高清一区二区三区视频| 欧美偷窥清纯综合图区| 色av中文字幕一区| 黑人巨大精品| 亚洲第一区第二区| 福利在线观看| 一本大道久久a久久精品综合| 国产日韩在线| 亚洲精品综合在线| 免费99热在线观看| 国产欧美1区2区3区| 91免费观看| 成人av免费在线播放| 久久久精品综合| 国产最新视频在线| 欧美激情性做爰免费视频| 中文在线中文字幕| 亚洲曰韩产成在线| 亚洲国产另类 国产精品国产免费| 能在线观看av网站| 中文字幕一区二区三区不卡在线| 成熟老妇女视频| 99麻豆久久久国产精品免费| www.国产在线视频| 成人国产精品视频| 在线观看成人免费| 国产激情视频一区二区在线观看| 欧美日韩亚洲国产成人| 国产丶欧美丶日本不卡视频| 女女百合国产免费网站| 丰满亚洲少妇av| 午夜精品久久久内射近拍高清 | 欧美日韩在线一二三| 久久www免费人成看片高清| 成人小视频在线观看免费| 欧美激情中文字幕一区二区| 少妇性bbb搡bbb爽爽爽欧美| 精品国产百合女同互慰| 一区二区三区高清在线观看| 国产精品一区二区三区四区五区 | 国产最新在线| 最近2019中文字幕大全第二页| 久久99国产精一区二区三区| 欧美精品久久久| 久久九九久久九九| 免费在线看a| 欧美精品videossex88| 一区免费在线| 国产午夜福利视频在线观看| 欧美天堂一区二区三区| 九九久久国产| 国产高清不卡av| 91亚洲永久精品| 日本在线视频站| 久久久久日韩精品久久久男男 | 亚洲xxxxx电影| 成人综合在线视频| 精品视频一二三| 欧美特黄a级高清免费大片a级| 91社在线播放| 粉嫩老牛aⅴ一区二区三区| 超薄肉色丝袜脚交一区二区| 51午夜精品| 国产精品伦理一区二区| 成人ssswww在线播放| 国产一区视频在线播放| 91亚洲国产成人精品一区二区三| 成人福利在线观看视频| 国产精品露脸自拍| 久久综合一区二区| 999福利在线视频| 99re视频在线| 中文字幕一区二区三| 91av一区| 视频一区二区三区免费观看| 色妞www精品视频| 日本不卡二三区| 亚洲黄色a v| 这里只有精品在线观看| 麻豆91在线观看| 欧美性video| 国产欧美日韩综合一区在线观看| 亚洲一级二级三级| 亚洲制服欧美另类| 美女在线视频一区二区| 精品国产视频在线| 美女视频黄免费的久久 | 国产亚洲精品自在久久| 亚洲综合色在线| 超碰精品在线| 日本一道本久久| 亚洲欧美综合v| 韩国理伦片一区二区三区在线播放| 黄网站app在线观看| 国产精品看片你懂得| 日韩av首页| 白白操在线视频| 亚洲欧美另类国产| 精品在线一区二区三区| 欧洲在线视频| 一区二区在线观| 亚洲欧美一区二区三区情侣bbw| 水野朝阳av一区二区三区| 毛片在线不卡| 日本午夜精品电影| 精品1区2区在线观看| 日本视频中文字幕一区二区三区| 国产欧美va欧美va香蕉在线| 亚洲欧洲精品一区二区三区不卡| 超碰97久久| 成人在线看片网站| 日本精品视频网站| 亚洲人123区| 久久人人88| 成人高清在线| 日韩欧美在线电影| 亚洲久久久久久久久久久| 国产成人综合自拍| 久久久久伊人| 天天色综合天天色| 国产精品三级网站| 色偷偷一区二区三区| 亚洲国产激情| 国产激情在线播放| 又粗又黑又大的吊av| 孩xxxx性bbbb欧美| 亚洲乱码国产乱码精品精的特点| 欧美一区2区| 香蕉视频在线播放| 久久精品国产精品亚洲精品色| 亚洲天堂日韩电影| 国产精品护士白丝一区av| 久久国产亚洲| 99爱在线视频| 欧美日韩亚洲高清一区二区| 美国十次了思思久久精品导航| 欧美日韩卡一| 黄色高清在线观看| 欧美裸体网站| 欧美成人激情图片网| 天天影视涩香欲综合网| 免费日韩视频| 中文字幕日韩在线| yiren22综合网成人| 黄色三级中文字幕| 国产精品99一区| 精品国产一区二区国模嫣然| 久久噜噜亚洲综合| 中文字幕免费一区二区三区| 在线观看网站免费入口在线观看国内| 国产福利视频在线播放| 91免费版网站入口| 国产视频精品xxxx| 一区二区三区影院| 日本视频免费一区| 精品三级av在线导航| 韩国av网站在线| 国产喷水theporn| 蜜桃av色综合| 久久久免费在线观看| 91麻豆精品国产自产在线观看一区| 丁香婷婷综合激情五月色| 精品久久电影| gay欧美网站| 中文字幕在线视频观看| 成人av在线播放观看| 亚洲综合最新在线| 北条麻妃99精品青青久久| 91福利在线免费观看| 国产午夜一区二区三区| 亚洲欧美高清| 国产日韩欧美一区二区三区| 国产精品毛片久久久久久久久久99999999|