0 Bewertungen0% fanden dieses Dokument nützlich (0 Abstimmungen)
13 Ansichten207 Seiten
Ken kocienda, principal engineer, iOS Apps and frameworks, talks about writing easy-to-change code. "People think that I can teach them style. What stuff it all is! Have something to say, and say it as clearly as you can," he says. Clear writing is easier to understand 26 clear code is easier to change 27 Elements of a clear coding style?
Ken kocienda, principal engineer, iOS Apps and frameworks, talks about writing easy-to-change code. "People think that I can teach them style. What stuff it all is! Have something to say, and say it as clearly as you can," he says. Clear writing is easier to understand 26 clear code is easier to change 27 Elements of a clear coding style?
Ken kocienda, principal engineer, iOS Apps and frameworks, talks about writing easy-to-change code. "People think that I can teach them style. What stuff it all is! Have something to say, and say it as clearly as you can," he says. Clear writing is easier to understand 26 clear code is easier to change 27 Elements of a clear coding style?
These are confidential sessionsplease refrain from streaming, blogging, or taking pictures
Your second-most important goal as a developer
Session 112 Writing Easy-To-Change Code Ken Kocienda Principal Engineer, iOS Apps and Frameworks 1 This is a talk about writing code 2 Easy to read learn understand maintain change 3 Easy to change software 4 Your second-most important goal 5 What is your most important goal? 6 Ship products! 7 This is how we think at Apple 8 Over 30 iOS releases since 2007 9 Releases are complicated Legal Marketing Bug fixes New app features Improving existing features Changing priorities Competition Tight schedules Too few people Testing New hardware New OS features Work with other companies Too many people App Store submission 10 Help you make change easier 11 You always change your software 12 What Kinds of Change? Bug fixes Adding new features Enhancing existing features Changing code someone else wrote Changing code you wrote six months ago 13 General conventions 14 Mac and iOS conventions 15 Things to think about Topics 16 Style Stories Laziness Hygiene Notifications Topics Optimization Dependencies Mixing Expectations Wrap up 17 More than skin deep Style 18 Coding conventions 19 Coding Conventions Brace style for if-else Parenthesis Style Leading underscores Code indenting CapitalizationStyle (i.e. capitalization_style) 20 Local consistency is important 21 The beginnings of style 22 Style goes deeper 23 People think that I can teach them style. What stuff it all is! Have something to say, and say it as clearly as you can. That is the only secret of style. Matthew Arnold 24 Clarity 25 Clear writing is easier to understand 26 Clear code is easier to change 27 Elements of a clear coding style? 28 ! ! Good names Common idioms 29 ! ! Good names Common idioms 30 Good Names Are Descriptive NSString *searchString = [self _searchString]; BOOL searchStringIsNotEmpty = [searchString length] != 0; if (searchStringIsNotEmpty) { [self _findBanner]->findString(searchString, shouldBeep ? BeepOnFailure : DoNotBeepOnFailure); } 31 Good Names Are Descriptive NSString *searchString = [self _searchString]; BOOL searchStringIsNotEmpty = [searchString length] != 0; if (searchStringIsNotEmpty) { [self _findBanner]->findString(searchString, shouldBeep ? YES : NO); } 32 Descriptive Names You can go overboard @interface YesYouCanMakeNamesForClassesWhichAreTooLong { id _aReallyVerboseNameJustToBePerfectlyClear; } @end 33 Bad Names? Boolean Arguments Hard to know what they mean [magnifier stopMagnifying:NO]; 34 Bad Names? Boolean Arguments Hard to know what they mean - (void)stopMagnifying:(BOOL)animated; 35 Bad Names? Boolean Arguments Hard to know what they mean - (void)stopMagnifyingAnimated:(BOOL)animated; 36 Good names are descriptive 37 ! ! Good names Common idioms 38 ! ! Good names Common idioms 39 Workhorse Lines of Code Hard to know what they mean [_rightView setAlpha:![[_temporary text] length] ? 1.0 : 0.0]; 40 Count square brackets? 41 Workhorse Lines of Code Hard to know what they mean [_rightView setAlpha:![[_temporary text] length] ? 1.0 : 0.0]; 42 Rewrite Workhorse Lines of Code Be clear! BOOL textIsEmpty = [_temporary.text length] == 0; float alpha = textIsEmpty ? 1.0 : 0.0; [_rightView setAlpha:alpha]; 43 Read and understand quickly 44 Design patterns 45 Design Patterns Very common patterns Singleton Observer Prototype Chain of responsibility Command 46 Design Patterns Patterns used in Apple frameworks MVC Target-action Delegation Autorelease View controller 47 Idioms communicate at a high level 48 Shared vocabulary 49 ! ! Good names Common idioms 50 More than skin deep Style 51 Now I understand Stories 52 Bug. Why? 53 Did not anticipate Did not understand 54 Debug 55 Everyone knows that debugging is twice as hard as writing a program in the first place. So if you are as clever as you can be when you write it, how will you ever debug it? Brian Kernighan 56 Step 1: Debugger 57 What are you really looking for? 58 Step 1: Debugger T h i n k 59 How could this bug happen? 60 The most effective debugging tool is still careful thought, coupled with judiciously placed print statements. Brian Kernighan 61 Debugging is understanding 62 Debugging is not jiggling code 63 -performSelector:withObject:afterDelay: Rarely right! 64 Why? [self foo]; [self bar]; 65 Each bug fix should tell a story 66 Investigate. Eureka! Tell someone before you code the fix 67 Tell the story during code review 68 Write the story into your bug tracker 69 Anticipate more Understand better 70 Now I understand Stories 71 Wake me when it is over Laziness 72 Lazy initialization 73 It is good 74 It is not magic 75 Singleton Objects Lazy initialization is common FooController *controller = [FooController sharedInstance]; 76 Singleton Objects Lazy initialization is common @implementation FooController + (FooController *)sharedInstance { static dispatch_once_t once; static FooController *instance; dispatch_once(&once, ^{ instance = [[FooController alloc] init]; }); return instance; } @end 77 Singleton Objects Lazy initialization is common @implementation FooController (Continued) - (id)init { ... BarController *barController = [BarController sharedInstance]; ... } @end 78 Singleton Objects Lazy initialization is common @implementation BarController - (id)init { ... FooController *fooController = [FooController sharedInstance]; ... } @end 79 Init storm 80 Several problems 81 Long pause 82 Order of initialization 83 Singleton Objects How many do you have? @implementation FooController + (FooController *)sharedInstance { static dispatch_once_t once; static FooController *instance; dispatch_once(&once, ^{ instance = [[FooController alloc] init]; }); return instance; } @end 84 Singleton Objects How many do you have? @implementation FooController + (FooController *)sharedInstance { static FooController *instance; if (!instance) instance = [[FooController alloc] init]; return instance; } @end 85 Multiple instantiation of singleton 86 Mess 87 Think through lazy initialization 88 No silver bullets 89 Lightweight alloc at program start Better singleton decomposition 90 Alternative accessor patterns 91 Alternative Accessor Patterns Create or not? @interface FooController + (FooController *)sharedInstance; // will create + (FooController *)activeInstance; // wont create + (FooController *)sharedInstance createIfNeeded:(BOOL)createIfNeeded; @end 92 Wake me when it is over Laziness 93 You make the mess you clean it up! Hygiene 94 Good hygiene takes effort 95 The best writing is rewriting. E.B. White 96 Do not throw away code 97 Conflict? 98 Changes are part of a process 99 Your top priority should be to ship 100 Do not rewrite refactor 101 Refactoring Keep functionality, but change form 102 What about cruft? 103 Cruft is not code you do not understand code you did not write code you do not like 104 What is genuine cruft? 105 What Is Genuine Cruft? Dead code Comments which no longer apply There is no number three 106 Use compiler for dead code checks 107 Delete or check old comments 108 Accumulated knowledge 109 Size of change is important 110 Small: clean up as you go 111 Medium: need coordination 112 Large: need real planning 113 Beware of regressions 114 Test! 115 You make the mess you clean it up! Hygiene 116 Open the window and holler! Notifications 117 goto 118 Notifications are a glorified goto 119 You do not even say where to go! 120 You can go to more than one place! 121 Frustrate code inspection You can not see what code will run 122 Non-deterministic behavior Callbacks are unordered 123 Notifications can complicate change 124 Not all bad 125 Notifications promote loose coupling 126 Model/View/Controller (MVC) CoreData 127 will/did 128 You should know about endpoints 129 Think twice about other uses 130 Code can be too loosely coupled 131 Consider protocols or delegates 132 goto NextTopic; 133 The 3% solution Optimization 134 We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Donald Knuth 97% of the time 135 97% of the time 100% - 97% = 3% 136 Which 3% to worry about? 137 Things Which Can Be Slow Memory allocation View creation Drawing Questionable algorithms Questionable data structures I/O Blocking on information Unnecessary work New work you just added 138 Optimize when you have measured 139 Use Instruments 140 Optimize when you understand 141 Optimize code with clearest role 142 Optimize slowest and oldest 3% 143 Keep new code easiest to change 144 Trades are OK! Never make the program slower 145 Change, test, measure, optimize 146 The 3% solution Optimization 147 Dont call us well call you Dependencies 148 Implications of change 149 Limit collateral damage 150 ! ! Inheritance trees Call graphs 151 ! ! Inheritance trees Call graphs 152 Shallow is better 153 Avoid layers of overridden methods 154 Use delegation 155 Delegation Customize by calling another object Keeps conceptual overhead small Vary customization at runtime as needed 156 ! ! Inheritance trees Call graphs 157 Smaller is better 158 Limit includes 159 You get faster compile times 160 Strive for unidirectional calling 161 Bidirectional Call Graph We are all friends here Foo @interface { Bar *_b; } - (void)foo; @end @implementation [_b bar]; @end Bar @interface { Foo *_f; } - (void)bar; @end @implementation [_f foo]; @end 162 Bidirectional Call Graph We are all friends here Foo @interface { Bar *_b; } - (void)foo:(id)arg; @end @implementation [_b bar]; @end Bar @interface { Foo *_f; } - (void)bar; @end @implementation [_f foo]; @end 163 Bidirectional Call Graph We are all friends here Foo @interface { Bar *_b; } - (void)foo:(id)arg; @end @implementation [_b bar]; @end Bar @interface { Foo *_f; } - (void)bar; @end @implementation [_f foo:arg]; @end 164 Unidirectional Call Graph Rethink relationship Master @interface { Slave *_s; } - (void)changed; @end @implementation [_s update:arg]; @end Slave @interface { } - (void)update:(id)arg; @end @implementation @end 165 Unidirectional Call Graph Rethink relationship Master @interface { Slave *_s; } - (void)dataReceived; - (void)processData; @end @implementation [_s update:arg]; @end Slave @interface { } - (void)update:(id)arg; @end @implementation @end 166 ! ! Inheritance trees Call graphs 167 Dont call us well call you Dependencies 168 Purity of essence (OPE) Mixing 169 Model/View/Controller (MVC) 170 Do not mix model and view changes 171 Do not mix different things 172 Computation and I/O 173 Algorithms and data sources 174 UI and a specific screen resolution 175 UX and an interface paradigm 176 Conflicted About Animation Arguments Is this mixing too much? - (void)setEditing:(BOOL)editing animated:(BOOL)animated; 177 Hard-code animations? 178 Multitasking gestures 179 We change how the system works 180 App launch without animating hard 181 Do not mix different things 182 Purity of essence (OPE) Mixing 183 How do I work this thing? Expectations 184 Bugs are often disappointments 185 I expected A, you did B 186 Be conservative in what you send; be liberal in what you accept. Jon Postel 187 Hard to use wrong 188 Method arguments Assertions and early returns 189 Assertions This will never work // UIActionSheet.m - (void)showInView:(UIView *)view { NSParameterAssert(view != nil);
... } 190 Early Returns The method will not run right now - (void)beginWork { if (AlreadyBusy()) return; ... } 191 What about ivars? 192 Global variables are bad, right? 193 Scope is too broad 194 ivar scope also can be too broad 195 Rules of Thumb for ivars As few as possible Simple life-cycles Avoid tight relationships Avoid letting non-setter methods change ivars 196 Hard to manage ivar state? 197 Use a state machine 198 UIGestureRecognizers 199 Multitasking gestures 200 State Machines How do they help? States help to think things through States help to limit possibilities States help to make assertions Need to add a feature? ! Add a state ! Handle the transitions 201 Hard to use wrong 202 How do I work this thing? Expectations 203 Ten things to think about Wrap Up 204 Easy To Change Code Ten things to think about 1. Write clear code 2. Bug fixes should tell a story 3. Keep control of lazy initialization 4. Refactor instead of rewriting 5. Use notifications for the right things 205 Easy To Change Code, (Cont.) Ten things to think about 6. Keep new code easy to change 7. Optimize slowest and oldest code 8. Limit dependencies 9. Do not mix different things 10. Make code that is hard to use wrong 206 207