Code Stinkers Anonymous

download Code Stinkers Anonymous

If you can't read please download the document

description

2011 NOTE: Some links in this presentation are no longer valid. Sorry about that. As a professional developer, especially one who works in Ruby, you hear about code quality all the time. You learn that testing your code and making it easy to maintain are the path to success. You know about TDD, BDD, TATFT and LMNOP. You learn to cycle from red to green to refactoring. We all do our best to write quality, maintainable, reusable code. We're all human, though; some of us slip, and some of us have had to work hard at preventing code smells. In this talk, I'll talk about how I learned to program, how going pro exposed flaws in my coding style, and how I'm working to improve my code quality, sharing some of my old stinky code, the better, refactored versions, and the lessons I've learned in honing my craft.

Transcript of Code Stinkers Anonymous

  • 1.Code StinkersAnonymous Mark Cornick Viget Labs RubyNation June 12, 2009 Friday, June 12, 2009

2. Hello Friday, June 12, 2009 3. My name is Mark, and I am a code stinker. Friday, June 12, 2009 4. How I got here Friday, June 12, 2009 5. 10 years in sysadmin before becoming a developer Friday, June 12, 2009 6. Mostly self-taught; almost never used my CS degree Friday, June 12, 2009 7. A very Brief Introduction ToEdsger W. Dijkstra who wiquot; be quoted a few times in the next few slides Friday, June 12, 2009 8. Edsger W.Dijkstra(1930-2002)Notable for: Shortest path algorithm Reverse Polish notation Being a curmudgeon Friday, June 12, 2009 9. How Do We Tell Truths That Might Hurt? Friday, June 12, 2009 10. My Back Pages Or, I was so much lamer then;Im less lame than that now Friday, June 12, 2009 11. BASIC Friday, June 12, 2009 12. 10 TEXT:HOME20 GOSUB 10030 END100 ?YES I JUST GOSUBBED FORNO REASON WHATSOEVER110 RETURN Friday, June 12, 2009 13. It is practicaquot;y impossible to teach good programming style to students that have had prior exposure to BASIC: as potential programmers they are mentaquot;y mutilated beyond hope of regeneration. Edsger W. DijkstraFriday, June 12, 2009 14. COBOL Friday, June 12, 2009 15. IDENTIFICATION DIVISION.PROGRAM-ID. COBOL-EXAMPLE.PROCEDURE DIVISION.MAIN.IF YEAR [:xxxx] xxx xxxx xxxxxx.xxxxxx(:xx_xxx_xxxxxxx) xxxxxx[:xxxxxx] ||= Xxxxxxx::XXXXXX_XXXXXX @xxxxxxx_xxxxxxx = xxxxxx.xxxxxx(:xxxxxxx_xxxxxxx) xx xxxxxx[:xxxxxxxx_xxxx_xxxxxxx].xxx? @xxxx_xxxxxxxxxx_xxx_xxxxxxx = xxxx xxxx @xxxx_xxxxxxxxxx_xxx_xxxxxxx = xxxxxx[:xxxxxxxx_xxxx_xxxxxxx].xxxxxxx?(quot;xxxx_xxxxxxxxxxquot;) xx @xxxx_xxxxxxxxxx_xxx_xxxxxxxxxxxxx[:xxxxxxxx_xxxx_xxxxxxx].xxxxxx(quot;xxxx_xxxxxxxxxxquot;)xxxxxxxx_xxxxxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxxxxxx_xxxx_xxxxx']]xx xxxxxxxx_xxxxxx.xxxxxx > 9xxxxxxxx_xxxxxx.xxxx{|x,x| x[1] x[1]}[9..-1].xxxx xx |x|xxxxxx[:xxxxxxxx_xxxx_xxxxxxx] 19xxxx_xxxxxx.xxxx{|x,x| x[1] x[1]}[19..-1].xxxx xx |x|xxxxxx[:xxxx_xxxxxxx] xxxxxx[:xxxxxx], :xxxxxx_xxx => xxxxxx[:xxxxxx_xxx], :xx_xxxxxxxx => xxxxxx[:xx_xxxxxxxx], :xxxxx => xxxx, :xxxxxx => xxxxxx[:xxxxxx].xx_x) xxxx xxxxx[:xxxxxx] = quot;Xxxxxxx xxxxxxxx, xxxxxx xxx xxxx xxxxxx xxxxx.quot; @xxxxxxxx = [].xxxxxxxx(:xxxx => 1) xxx @xxxx_xxxxxxx = @xxxxxxxx[0,3] @xxxxxxxxxx_xxxxxxx = (@xxxxxxxx[3,(Xxxxxxx.xxx_xxxx - 3)] || []) @xxxxxxxx = @xxxxxxxx.xxxxxx xx @xxxxxxxx.xxxxxxx_xx?(:xxxxxx) && [email protected]? && [email protected]? @xxxxx_xxxxxx = Xxxx[*@xxxxxxxx.xxxxxx['xxxxx_xxxxx']] @xxxx_xxxxxx = Xxxx[*@xxxxxxxx.xxxxxx['xxxx_xxxxx']] @xxxxxxxx_xxxx_xxxxxx = Xxxx[*@xxxxxxxx.xxxxxx['xxxxxxxx_xxxx_xxxxx']] xxxxxx_xxxxx_xxxxxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxxx_xxxxx']]xxxxxx_xxxx_xxxxxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxx_xxxxx']]xxxxxx_xxxxxxxx_xxxx_xxxxxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxxxxxx_xxxx_xxxxx']]xxxxxx_xxxxx_xxxxxx.xxxx xx |x,x|@xxxxx_xxxxxx[x] = 0 xxxxxx @xxxxx_xxxxxx.xxx_xxx?(x)xxxxxxxxx_xxxx_xxxxxx.xxxx xx |x,x|@xxxx_xxxxxx[x] = 0 xxxxxx @xxxx_xxxxxx.xxx_xxx?(x)xxxxxxxxx_xxxxxxxx_xxxx_xxxxxx.xxxx xx |x,x|@xxxxxxxx_xxxx_xxxxxx[x] = 0 xxxxxx @xxxxxxxx_xxxx_xxxxxx.xxx_xxx?(x)xxx@xxxxx_xxxxxx = @xxxxx_xxxxxx.xxxx# OPTIMIZE: this is ugly@xxxx_xxxxxx = @xxxx_xxxxxx.xxxx{|x,x| quot;#{xxxxxxx('%09x',xxxxxx_xxxx_xxxxxx[x[0]])} #{x[0]}quot; quot;#{xxxxxxx('%09x',xxxxxx_xxxx_xxxxxx[x[0]])} #{x[0]}quot;}@xxxxxxxx_xxxx_xxxxxx = @xxxxxxxx_xxxx_xxxxxx.xxxx{|x,x| quot;#{xxxxxxx('%09x',xxxxxx_xxxxxxxx_xxxx_xxxxxx[x[0]])} #{x[0]}quot; quot;#{xxxxxxx('%09x',xxxxxx_xxxxxxxx_xxxx_xxxxxx[x[0]])} #{x[0]}quot;}@xxxxxxxx_xxxxxx = @xxxxxxxx.xxxxxxxxxxxxxx_xxx = [] xxxxxxxx_xxx = [] xxxxxx xxxxxxx[:xxxxxx]['xxxxxxxx_xxxxx_xxxxx'].xxx?xxxxxxxx_xxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxxxxxx_xxxxx_xxxxx']].xxxxxx_xx{|x,x| x.xxxxx?}.xxxxxxx{|x,x| x.xx_x} xxx xxxxxx xxxxxxx[:xxxxxx]['xxxxxxxx_xxxxx_xxxxx'].xxx?xxxxxxxx_xxx = Xxxx[*xxxxxxx[:xxxxxx]['xxxxxxxx_xxxxx_xxxxx']].xxxxxx_xx{|x,x| x.xxxxx?}.xxxxxxx{|x,x| x.xx_x} xxx xxxxxxx_xxxxxxx = [] (xxxxxxxx_xxx+xxxxxxxx_xxx).xxxx xx |xxx|xxxxxxxxxxxx_xxxxxxx user_agent)if @response.header['location']current = URI.parse(@response.header['location'])path = current.query.nil? ? current.path : quot;#{current.path}?#{current.query}quot;else@final_response = trueendendendend@responseend Friday, June 12, 2009 102. Small Pieces, Loosely JoinedFriday, June 12, 2009 103. RememberUNIX? Small tools doing one job well smallmethods doing onejob well Friday, June 12, 2009 104. Name Methods ToCommunicate Intent thing.expires_at < Time.nowthing.expired?user.has_accepted_terms &&!user.suspended user.can_sign_in?Friday, June 12, 2009 105. Dont Do Too MuchIn A Method When you see a method getting toolong, break it into smaquot;er methods. Hint: look for excessive indentationand nested ifs. Hint: a method shouldnt come closeto lling your editor window.Friday, June 12, 2009 106. def self.user_agentquot;Awesome App Ruby/#{RUBY_VERSION}quot;end def self.maximum_redirects4end def initialize(url)@url = urlend def endpoint_for(uri)endpoint = uri.path.sub(/^/?$/, '/')endpoint += quot;?#{uri.query}quot; unless uri.query.blank?endpointend def fetch(url, redirects_remaining)return if redirects_remaining == 0beginuri = URI.parse(url)response = Net::HTTP.start(uri.host, uri.port) do |http|http.get(endpoint_for(uri), {'User-Agent' => self.class.user_agent})endif response.is_a?(Net::HTTPRedirection)response = fetch(response['location'], redirects_remaining - 1)endrescue URI::InvalidURIErrorRAILS_DEFAULT_LOGGER.warn quot;Error parsing URL: '#{url}'quot;endresponseend def response@response ||= fetch(@url, self.class.maximum_redirects)endFriday, June 12, 2009 107. Self-Review Dont check it in if the tests fail. Use continuous integration to keepyourself honest. (more on this later) Look over all your changes before youcommit. If you miss something and youre usingGit, x it and git commit --amendFriday, June 12, 2009 108. Peer Review Pair-program whenever you can. Pairprogramming comes with built-in peerreview. Do regular code reviews with your peers.During active development, weekly isgood. Listen to criticism. Dont take it personaquot;y.No ones perfect.Friday, June 12, 2009 109. Quality TakesTime By law, straight bourbon must be aged in new, charred oak barrels for at least two years. Anything less yieldsjust whiskey, not bourbon.Friday, June 12, 2009 110. Sysadmins are used to ghting res Friday, June 12, 2009 111. Fireghting is notthe way to lasting codequality.Friday, June 12, 2009 112. Fireghting results in code that isjust whiskey (and maybe not even that) Friday, June 12, 2009 113. You may not have two to four years, but you stiquot;shouldnt rush Friday, June 12, 2009 114. Working In A Vacuum Most of us dont. No one should. Friday, June 12, 2009 115. Ethic of Reciprocity Friday, June 12, 2009 116. The GoldenRule Friday, June 12, 2009 117. Code unto others as you would have themcode unto you.Friday, June 12, 2009 118. You hate xing other peoples bad code.Friday, June 12, 2009 119. Dont make otherpeople x yours!Friday, June 12, 2009 120. One more tool: Continuous Integration Friday, June 12, 2009 121. Every time the code changes,run the tests. Friday, June 12, 2009 122. Know where a build broke and who was responsible. Friday, June 12, 2009 123. CI is a good idea even if you work alone. Friday, June 12, 2009 124. Some CI Options CruiseControl.rb,cruisecontrolrb.thoughtworks.com Integrity, integrityapp.com RunCodeRun (hosted!),runcoderun.com runcoderun.com/mcornick Friday, June 12, 2009 125. Lets Wrap This Up Or, I Hope You Know This Wiquot; Go Down On Your Permanent Record Friday, June 12, 2009 126. Where we come from inuences where we go. Friday, June 12, 2009 127. Theres still time to changethe road youre on. Friday, June 12, 2009 128. Test. No matter how, just do it. Friday, June 12, 2009 129. Use tools to help you, not to do work for you. Friday, June 12, 2009 130. Recognize anti-patterns.Avoid them. Friday, June 12, 2009 131. Play well with others. Friday, June 12, 2009 132. Take pride in your work. Appeal to your own ego. Friday, June 12, 2009 133. Learn from mistakes. Learn from refactoring. Friday, June 12, 2009 134. Put it all together and you will write better code. Friday, June 12, 2009 135. The End. This has been Code Stinkers Anonymousby Mark Cornick. Thank you!http://objectsinmirrors.com/http://twitter.com/mcornick Please rate this talk on SpeakerRate! http://speakerrate.com/talks/1170 Friday, June 12, 2009