/craftmanship/functions/index.html
HTML | 467 lines | 382 code | 79 blank | 6 comment | 0 complexity | 2d805fa7cece0c9ccfa164cc7fd9e384 MD5 | raw file
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>Clean functions</title>
- <meta name="description" content="How to create clean functions">
- <meta name="author" content="Jeroen De Dauw">
- <meta name="apple-mobile-web-app-capable" content="yes" />
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
- <link rel="stylesheet" href="css/reveal.min.css">
- <link rel="stylesheet" href="css/theme/default.css" id="theme">
- <!-- For syntax highlighting -->
- <link rel="stylesheet" href="lib/css/zenburn.css">
- <!-- If the query includes 'print-pdf', use the PDF print sheet -->
- <script>
- document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
- </script>
- <!--[if lt IE 9]>
- <script src="lib/js/html5shiv.js"></script>
- <![endif]-->
- </head>
- <body>
- <div class="reveal">
- <!-- Any section element inside of this container is displayed as a slide -->
- <div class="slides">
- <section>
- <h2>Clean functions</h2>
- <p>
- Caturday will not be stopped!<br />
- <img src="img/Willnotbestopped.gif" alt="Y U NO LOAD">
- </p>
- </section>
- <section>
- <h2>Clean functions</h2>
- <p>
- Presentation by <a href="https://twitter.com/JeroenDeDauw">@JeroenDeDauw</a><br /><br />
- bit.ly/clean-functions
- </p>
- </section>
- <section data-state="blackout">
- <h2>Function size and naming</h2>
- </section>
- <section>
- <h3>How big should a function be?</h3>
- <ol>
- <li class="fragment">It should be SMALL</li>
- <li class="fragment">It should be SMALLER than that</li>
- </ol>
- <br /><br />
- <blockquote class="fragment">
- A function should do one thing.<br />
- It should do it well, and it should do it only.
- </blockquote>
- </section>
- <section>
- <p>4 - 5 lines</p>
- </section>
- <section>
- <h3>What is "one thing"?</h3>
- <p class="fragment">
- One level of abstraction
- </p>
- <pre class="fragment"><code contenteditable class="PHP">
- function onFirstPost() {
- $messageText = $this->getWelcomeMessageBody();
- if ($this->addFooter()) $messageText.=$this->getWelcomeMessageFooter();
- $this->emailer->send( $messageText );
- foreach ( $this->getReviewers() as $reviewer ) {
- $this->reviewerNotifier->notify( $reviewer );
- }
- }
- </code></pre>
- <pre class="fragment"><code contenteditable class="PHP">
- function onFirstPost() {
- $this->sendWelcomeMessage();
- $this->notifyReviewers();
- }
- </code></pre>
- </section>
- <section>
- <p>
- Predicates of if and while statements
- </p>
- <pre><code contenteditable class="PHP">
- if ( $foo === 'bar' && ( $user->isAllowed( '' ) || $baz )
- && $this->bah() ) {
- $this->sendWelcomeMessage();
- }
- </code></pre>
- <pre class="fragment"><code contenteditable class="PHP">
- if ( $this->isFirstPost() ) {
- $this->sendWelcomeMessage();
- }
- </code></pre>
- </section>
- <section>
- <p>
- Bodies of control structures
- </p>
- <pre><code contenteditable class="PHP">
- if ( $this->isFirstPost() ) {
- $this->sendWelcomeMessage();
- }
- </code></pre>
- <pre><code contenteditable class="PHP">
- foreach ( $this->getReviewers() as $reviewer ) {
- $this->notifyReviewer( $reviewer );
- }
- </code></pre>
- </section>
- <section>
- <p>
- How much indenting / nesting?
- </p>
- </section>
- <section>
- <p>
- Name length rule
- </p>
- <pre><code contenteditable class="PHP">
- $user->remove();
- function remove() {
- // ...
- $this->removePostsFromDatabase();
- // ...
- }
- </code></pre>
- </section>
- <section>
- <p>
- Well written prose
- </p>
- <pre><code contenteditable class="PHP">
- if ( $this->isFirstPost() ) {
- $this->sendWelcomeMessage();
- $this->notifyReviewers();
- }
- </code></pre>
- <pre class="fragment"><code contenteditable class="PHP">
- function notifyReviewers() {
- foreach ( $this->reviewers as $reviewer ) {
- $reviewer->notify( $this->post );
- }
- }
- </code></pre>
- </section>
- <section>
- <h3>Big functions</h3>
- <ul>
- <li>Have multiple functional areas</li>
- <li class="fragment">Functions define scopes</li>
- <li class="fragment">Have variables used throughout</li>
- <li class="fragment">That is what classes are for</li>
- <li class="fragment">Group of functions that use a common set of variables</li>
- </ul>
- </section>
- <section>
- <h3>Panic! Lots of small functions!</h3>
- <ul>
- <li class="fragment">Function call overhead</li>
- <li class="fragment">Long time to write all those functions</li>
- </ul>
- </section>
- <section>
- <h3>Silly!</h3>
- <p>
- Well named methods, classes and namespaces act like signposts
- </p>
- </section>
- <section>
- <p>
- So what makes small functions unsettling?
- </p>
- </section>
- <section>
- <p>
- The landscape metaphor
- </p>
- </section>
- <section>
- <p>
- Long functions are familiar.<br />
- Like landscapes, we recognize the landmarks
- </p>
- </section>
- <section>
- <h3>New people</h3>
- <ul>
- <li class="fragment">Do not recognize anything</li>
- <li class="fragment">Can only start wandering around aimlessly</li>
- </ul>
- </section>
- <section>
- <h3>New people + signposts</h3>
- <ul>
- <li>Establish themselves quickly</li>
- <li>Start being productive fast</li>
- </ul>
- </section>
- <section>
- <h3>The bedroom metaphor</h3>
- <ul>
- <li class="fragment">Everything lying around at some place well known to you</li>
- <li class="fragment">Mom gets upset and forces you to clean room</li>
- <li class="fragment">You rebel and put things back</li>
- <li class="fragment">Part of growing up is realizing this does not work in teams</li>
- </ul>
- </section>
- <section>
- <h3>Call time overhead</h3>
- <ul>
- <li class="fragment">Nanosecond</li>
- <li class="fragment">Compilers are good at optimizing</li>
- <li class="fragment">Time better spend on real performance issues</li>
- </ul>
- </section>
- <section>
- <blockquote>
- I'm sorry I had to write you such a long letter,<br />
- but I did not have time to write you a short one
- </blockquote>
- <p>-- Blaise Pascal</p>
- <br />
- <ul>
- <li class="fragment">Takes time and effort</li>
- <li class="fragment">Places burden of breaking down on ALL readers</li>
- <li class="fragment">You are a reader as well</li>
- </ul>
- </section>
- <section>
- <h3>Example from gerrit</h3>
- <ul>
- <li><a href="https://gerrit.wikimedia.org/r/#/c/78365/2/lib/resources/jquery.wikibase/jquery.wikibase.entityselector.js">Step 0, wrong direction</a></li>
- <li><a href="https://gerrit.wikimedia.org/r/#/c/78365/3/lib/resources/jquery.wikibase/jquery.wikibase.entityselector.js">Step 1, first split</a></li>
- <li><a href="https://gerrit.wikimedia.org/r/#/c/78365/4/lib/resources/jquery.wikibase/jquery.wikibase.entityselector.js">Step 2, second split</a></li>
- </ul>
- </section>
- <section data-state="blackout">
- <h2>Function arguments</h2>
- </section>
- <section>
- <h3>How many?</h3>
- <ul>
- <li class="fragment">Ideally none, the fewer the better</li>
- <li class="fragment">Arguments are hard to understand</li>
- <li class="fragment">More then 3 requires very special justification</li>
- </ul>
- </section>
- <section>
- <section>
- <h3>Flag arguments</h3>
- <p class="fragment">
- Make functions do multiple things!
- </p>
- <pre class="fragment"><code contenteditable class="PHP">
- renderHtml( true );
- </code></pre>
- </section>
- <section>
- <pre><code contenteditable class="PHP">
- function renderHtml( $userIsLoggedIn ) {
- // ...
- if ( $userIsLoggedIn ) {
- // ...
- }
- // ...
- }
- </code></pre>
- <pre class="fragment"><code contenteditable class="PHP">
- function renderHtmlForLoggedInUser() {
- }
- function renderHtmlForAnonUser() {
- }
- </code></pre>
- <pre class="fragment"><code contenteditable class="PHP">
- renderHtmlForLoggedInUser();
- </code></pre>
- </section>
- </section>
- <section>
- <h3>Argument objects</h3>
- <pre><code contenteditable class="PHP">
- function drawCircle( $x, $y, $radius ) {}
- </code></pre>
- <pre><code contenteditable class="PHP">
- function drawCircle( Point $center, $radius ) {}
- </code></pre>
- </section>
- <section>
- <h3>Output arguments</h3>
- <pre><code contenteditable class="PHP">
- appendFooter( $report );
- </code></pre>
- <pre><code contenteditable class="PHP">
- $report->appendFooter();
- </code></pre>
- </section>
- <section data-state="blackout">
- <h2>Side effects</h2>
- </section>
- <section>
- <p>Either do something OR answer something, not both!</p>
- </section>
- <section>
- <pre><code contenteditable class="Java">
- public boolean set( String attributeName, String value );
- </code></pre>
- <pre class="fragment"><code contenteditable class="Java">
- if ( set( "username", "NyanCat" ) )
- </code></pre>
- </section>
- <section>
- <p>Same for returning error codes. Error handling is one thing.</p>
- </section>
- <section data-transition="linear">
- <h3>Conclusion</h3>
- <ul>
- <li>Small!</li>
- <li class="fragment">Small well named functions act like signposts</li>
- <li class="fragment">Classes hide in big functions</li>
- <li class="fragment">Functions do one thing, extract till you drop</li>
- <li class="fragment">Minimize arguments</li>
- <li class="fragment">Command query separation</li>
- </ul>
- </section>
- <section data-state="blackout" data-transition="linear">
- <h3>These slides</h3>
- <p>CC BY-SA 3.0, <a href="https://twitter.com/#!/JeroenDeDauw">Jeroen De Dauw</a></p>
- <p>
- <a href="https://github.com/JeroenDeDauw/slides/">Clone from GitHub</a>
- or view at <a href="http://bit.ly/clean-functions">bit.ly/clean-functions</a>
- </p>
- <div class="fragment">
- <br />
- <h3>Attribution</h3>
- <p>Slide engine: <a href="http://lab.hakim.se/reveal-js/">reveal.js</a>, Copyright (C) 2014 Hakim El Hattab</p>
- <small>
- <br />
- A lot of the material in these slides is based on works by Robert C. Martin.<br />
- In particular his book
- <a href="http://www.goodreads.com/book/show/3735293-clean-code">Clean Code</a>
- , and
- <a href="http://www.cleancoders.com/">Clean Coders</a>
- video series.
- </small>
- </div>
- </section>
- <section data-state="blackout" data-transition="linear">
- <h3>Instead of me</h3>
- <img height="290px" src="img/clean-code.jpg" />
- <img height="290px" src="img/clean-coder.jpg" />
- <img height="290px" src="img/fowler-enterprise.jpg" />
- <img height="290px" src="img/legacy-code.jpg" />
- </section>
- <section data-state="blackout">
- <img src="img/i-has-question-lolcat.jpg" />
- </section>
- </div>
- </div>
- <script src="lib/js/head.min.js"></script>
- <script src="js/reveal.min.js"></script>
- <script>
- // Full list of configuration options available here:
- // https://github.com/hakimel/reveal.js#configuration
- Reveal.initialize({
- controls: true,
- progress: true,
- history: true,
- center: true,
- theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
- transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
- // Optional libraries used to extend on reveal.js
- dependencies: [
- { src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
- { src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
- { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
- { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
- { src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
- { src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
- // { src: 'plugin/leap/leap.js', async: true }
- // { src: 'plugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }
- // { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
- ]
- });
- </script>
- </body>
- </html>