class: title # Code Is Communication .col.col-4.about.left.centered[ ## Steven Hicks ###
[@pepopowitz](http://twitter.com/pepopowitz) ###
steven.hicks@centare.com ###
[bit.ly/code-is-communication](http://bit.ly/code-is-communication) ] ??? **Contact Info** **Thanks:** * conference * organizers * you! --- class: bg-cover background-image: url(images/dev-up-sponsors.png) ??? * sponsors --- class: middle .col.col-5.profile[ ![Me](images/steve-by-lila-square.jpg) ] .col.col-5[ # Steven Hicks ] --- class: middle .col.col-5.profile[ ![Me](images/steve-by-lila-square.jpg) ] .col.col-5[ # Steven Hicks .centare-logo[ ![Centare](images/centare.png) ] ] ??? * Agile coaching * Consulting * Product development consulting --- class: middle .col.col-5.profile[ ![Me](images/steve-by-lila-square.jpg) ] .col.col-5[ # Steven Hicks .centare-logo[ ![Centare](images/centare.png) ] ## Spreadsheets -> Web Apps ] --- class: middle .col.col-5.profile[ ![Me](images/steve-by-lila-square.jpg) ] .col.col-5[ # Steven Hicks .centare-logo[ ![Centare](images/centare.png) ] ## Spreadsheets -> Web Apps ## Web developer for ~20 years ] ??? I've seen a lot of code. --- ```javascript var o=n=>n+(!/1.$/.test(--n)&&'snr'[n%=10]+'tdd'[n]||'th') ``` ??? I want to start with some code. I'll giveyou all about 1:00. Raise your hand when you think you understand what this code does. --- class: small ```javascript function getOrdinalForNumber(number) { var suffix = getSuffix(number); return `${number}${suffix}`; } function getSuffix(number) { if (numberEndsInElevenTwelveOrThirteen(number)) { return "th"; } var lastDigit = number % 10; switch (lastDigit) { case 1: return "st"; case 2: return "nd"; case 3: return "rd"; default: return "th"; } } function numberEndsInElevenTwelveOrThirteen(number) { var asString = number.toString(); return ( asString.endsWith("11") || asString.endsWith("12") || asString.endsWith("13") ); } ``` ??? Do it again. --- ```javascript getOrdinalForNumber(3); ``` ``` 3rd ``` .footnote[ https://codegolf.stackexchange.com/questions/4707/outputting-ordinal-numbers-1st-2nd-3rd ] ??? Both of them do the same thing. ... But we aren't here to play code golf. We're here to talk about .... --- class: title # Communication ??? Which I will say in front of you all, is pretty funny, because as someone who is extremely uncomfortable in social situations, I would say that my general advice about communication with others is --- class: title, small # Avoid it and go for a bike ride instead. ??? I am a pretty active guy, I usually prefer to go for a run or bike ride by myself than to talk to people. ... but I know a person. And so here's another introduction slide. --- class: middle .col.col-5.profile[ ![Me](images/stephanie-hicks-1.jpg) ] .col.col-5[ # Stephanie Hicks ] --- class: middle .col.col-5.profile[ ![Me](images/stephanie-hicks-1.jpg) ] .col.col-5[ # Stephanie Hicks ## Thinks I'm neat ] --- class: middle .col.col-5.profile[ ![Me](images/stephanie-hicks-1.jpg) ] .col.col-5[ # Stephanie Hicks ## Thinks I'm neat ## Teaches English & creative writing ] --- class: middle .col.col-5.profile[ ![Me](images/stephanie-hicks-1.jpg) ] .col.col-5[ # Stephanie Hicks ## Thinks I'm neat ## Teaches English & creative writing ## Helps me feel comfortable speaking to others ] ??? I lean on her a lot in social situations because she's great at communicating. So I had the idea for this talk And I said Steph, I have this idea, but I kind of stink at communication. --- class: title # How can I be better at communication? ??? And she said for starters... --- class: new-section # Be direct. ## Stop leaving room for misinterpretation. ??? And at first I got mad --- background-image: url(images/kids/liv_sad2.jpg) class: bg-cover ??? Because I tend to take this kind of feedback personally. But then I started to think about it. When I write code, I try to be direct. --- class: sub-section # Be Direct ## Single Responsibility Principle (SRP) ??? I try to follow the SRP I try to follow it with classes And I try to follow it with functions --- class: double-wide, secondary # Be Direct ## SRP .leftest.small[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] ??? If my function here does several things, I'll try to identify them (identify!) --- class: double-wide, secondary # Be Direct ## SRP .leftest.small.dim-1.dim-2.dim-4.dim-5.dim-6.dim-7.dim-8.dim-9.dim-10.dim-11.dim-12.dim-13.dim-14.dim-15.dim-16.dim-17.dim-18.dim-19.dim-20.dim-21[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] --- class: double-wide, secondary # Be Direct ## SRP .leftest.small.dim-1.dim-2.dim-3.dim-4.dim-12.dim-13.dim-14.dim-15.dim-16.dim-17.dim-18.dim-19.dim-20.dim-21[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] --- class: double-wide, secondary # Be Direct ## SRP .leftest.small.dim-1.dim-2.dim-3.dim-4.dim-5.dim-6.dim-7.dim-8.dim-9.dim-10.dim-11.dim-21[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] --- class: double-wide, secondary # Be Direct ## SRP .leftest.small[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] .rightest.small[ ```javascript function loadSomeData(){ setLoadingState(); var dataRequest = buildDataRequest(); dataService.loadData( dataRequest, handleResponse ); } ``` ] .rightest.small[ ```javascript function setLoadingState(){ me.loading = true; } function buildDataRequest(){ //... } function handleResponse(data){ //... } ``` ] ??? and extract them to more focused methods, So I can read through them one abstraction at a time. --- class: sub-section # Be Direct ## Cohesion ??? I try to write cohesive code --- class: double-wide, tertiary # Be Direct ## Cohesion ### Group Related Elements ??? I try to group related elements. ... -- ```csharp public Player GetPlayer() public void AddPlayer(Player player) public void UpdatePlayer(Player player) public Team GetTeam() public void AddTeam(Team team) public void UpdateTeam(Team team) ``` ??? This helps me identify patterns and repetition easily And find areas of code that might be suitable for extracting methods or classes. --- class: double-wide, medium, tertiary # Be Direct ## Cohesion ### Organize By Feature ??? I prefer to organize my code by feature, rather than type. ... -- .leftest[ ```json app/ App.js actions/ calendar.js speakers.js user-profile.js containers/ CalendarContainer.js SpeakerListContainer.js UserProfileContainer.js components/ Calendar.js Session.js Speaker.js SpeakerList.js UserProfile.js reducers/ root.js calendar.js speakers.js user-profile.js ``` ] ??? On the left, is a pretty standard react app. I have my code organized by object type. The problem with this approach is that when my system changes, it's not all the containers that change. --- class: double-wide, medium, tertiary # Be Direct ## Cohesion ### Organize By Feature .leftest.dim-1.dim-2.dim-3.dim-4.dim-6.dim-7.dim-8.dim-10.dim-11.dim-12.dim-13.dim-16.dim-17.dim-18.dim-19.dim-21[ ```json app/ App.js actions/ calendar.js speakers.js user-profile.js containers/ CalendarContainer.js SpeakerListContainer.js UserProfileContainer.js components/ Calendar.js Session.js Speaker.js SpeakerList.js UserProfile.js reducers/ root.js calendar.js speakers.js user-profile.js ``` ] ??? It's "something to do with speakers". I need to bounce around all these folders to find all of the speaker files. --- class: double-wide, medium, tertiary # Be Direct ## Cohesion ### Organize By Feature .leftest[ ```json app/ App.js actions/ calendar.js speakers.js user-profile.js containers/ CalendarContainer.js SpeakerListContainer.js UserProfileContainer.js components/ Calendar.js Session.js Speaker.js SpeakerList.js UserProfile.js reducers/ root.js calendar.js speakers.js user-profile.js ``` ] .rightest[ ```json app/ App.js calendar/ calendar.actions.js calendar.reducer.js Calendar.container.js Calendar.component.js Session.component.js speakers/ speakers.actions.js speakers.reducer.js SpeakerList.container.js SpeakerList.component.js Speaker.component.js attendees/ user-profile.actions.js user-profile.reducer.js UserProfile.container.js UserProfile.component.js ``` ] ??? When I organize by feature, All of my speaker things are in one folder. This structure, to me, is more cohesive. --- class: bg-cover background-image:url(images/horizontal-slices.jpg) ??? we have a history of putting things in buckets that are based on horizontal slices --- class: bg-cover background-image: url(images/vertical-slices.jpg) ??? but it's the vertical slices - the features - that put "code that changes together" in the same place. this is applicable on both server side and client there are variations of this slide that have been used to argue for technologies like css-in-js but it is appropriate everywhere. ... It's kind of like packing your clothes. Underwear, pants, shirts, all separated, it's kind of a mess when you want to get dressed the next day. I've never tried it...but what if we all just started packing by outfits instead? That way we just have to grab a whole outfit and go. No digging. (if we changed our clothes, anyway) --- class: sub-section # Be Direct ## Be Explicit ??? Another way to be direct with code is to be explicit, rather than implicit. --- class: double-stack, tertiary # Be Direct ## Be Explicit ### Use Parentheses ??? When I have a mathematical expression, I am explicit with parentheses, so that the reader doesn't have to remember the order of operations. ... -- ```csharp var overallIndex = pageSize * pageNumber + indexOnPage; ``` ??? If I look at this statement for a bit, I can deduce the order of operations. ... -- ```csharp var overallIndex = (pageSize * pageNumber) + indexOnPage; ``` ??? Or, I can throw parentheses in so that I don't have to spend any time at all identifying the OOO. ... So I look back at my wife and I say --- background-image: url(images/kids/lila_happy2.jpg) class: bg-cover # Be Direct ??? You're right. I can be more direct. What else you got for me? And she says --- class: new-section # Be Clear ## Say exactly what you mean ??? ... And I realized, I totally get this I've got kids. I want to introduce you to one of them. You've been seeing photos of my daughters Lila and Olivia. But I want to talk specifically about... --- background-image: url(images/supercat.jpg) class: bg-cover ??? Olivia. This is Supercat. (sidetrack) Olivia will do anything for a laugh. But she's not great at making decisions. and so I have this conversation daily. --- class: title, conversation .alt-brand[ > ## Daaad! I'm hungry! ] -- > ## Okay, Liv. Want some yogurt? -- .alt-brand[ > ## No! I hate yogurt! ] -- > ## Okay. How about an apple? -- .alt-brand[ > ## Dad I said I wanted yogurt!!!! ] ??? Olivia has trouble communicating clearly what she wants So I understand the importance of clarity. And I feel pretty strongly about the **importance of being clear in my code** ... especially when it comes to naming things. --- class: sub-section # Be Clear ## Name things clearly ??? Naming is the hardest thing in development. Here are some rules I like to follow. --- class: double-wide, tertiary, medium # Be Clear ## Name Clearly ### Name With Intention -- .leftest[ ```javascript function calculateOnBasePercentage( a, b, c, d, e){ var top = a + b + c; var bottom = b + c + d + e; return top / bottom } ``` ] ??? On the left, you see code where the variables don’t really mean anything. And in fact, in order to know what the variables mean, I need to know the formula for obp. And this is the opposite of how it should be. ... -- .rightest[ ```javascript function calculateOnBasePercentage( hits, walks, hitByPitch, atBats, sacrificeFlies){ var top = hits + walks + hitByPitch; var bottom = walks + hitByPitch + atBats + sacrificeFlies; return top / bottom } ``` ] ??? On the right, the variable names mean something, making it easier to tell what the function is doing. When you don't name with intention, you force readers to have to think. --- class: double-wide, tertiary # Be Clear ## Name Clearly ### Name Thoroughly ??? If the function does multiple things, all of those things should be identified in the name. If there are side effects, the name should mention that. -- ```csharp public void _____(ShoppingCart cart) { this.ShoppingCartRepository.Add(cart); this.ClearCart(); } ``` -- .leftest[ ```csharp public void SaveCart(...) // Doesn't tell the whole story ``` ] -- .rightest[ ```csharp public void SaveAndClearCart(...) // Tells the whole story ``` ] ??? ... And you'll notice that the function name got a little bit longer, but... --- class: double-wide, tertiary # Be Clear ## Name Clearly ### Use Long Names ??? As developers, we spend a lot of time trying to make things small. The length of a name should not be one of those things. ... -- .leftest[ ```javascript //ambiguous name function process(request) { } ``` ] ??? Short names are generally ambiguous. ... -- .rightest[ ```javascript //unambiguous name function saveUserProfile(request) { } ``` ] ??? Longer names are generally more clear. ... --- class: double-wide, tertiary # Be Clear ## Name Clearly ### Avoid Encodings ??? Encoded names are also unclear. As a general rule, if you can’t pronounce the name out loud, it is probably encoded. ... -- .leftest[ ```javascript //encoded names //hungarian notation var dblPrice; //abbreviations var flNmWoExt; //scoping var m_Title; ``` ] ??? Some examples of encoding are Hungarian notation, abbreviations, and scoping prefixes. ... -- .rightest[ ```javascript //not encoded var price; var fileNameWithoutExtension; var title; ``` ] ??? Encoding forces the reader to __decipher code__ as it’s read. --- class: double-wide, tertiary # Be Clear ## Name Clearly ### Use Constants ??? Sometimes we forget to name things altogether. **magic numbers and strings** are easier to understand when they are constants with a descriptive name -- .leftest[ ```javascript return seconds / 86400; ``` ] ??? ... who can tell me what this number represents? -- .rightest[ ```javascript const secondsInADay = 86400; return seconds / secondsInADay; ``` ] ??? ... who can tell me now? ... There's something else I think about when I think about being clear with my code. --- class: sub-section, secondary # Be Clear ## Comments ??? and that's comments. --- background-image: url(images/comments-lie.jpg) class: bg-cover, square ??? This tweet summarizes a lot of what I think about comments. --- class: title # Comments Lie. ??? Your IDE doesn’t keep comments up to date like it does variable names. And chances are, you don’t either. Once you understand the code, you stop reading the comments. --- class: double-wide, tertiary # Be Clear ## Comments ### Lie ```javascript function isHallOfFameWorthy(player){ //a player is considered HOF worthy if // he played for 18 seasons //<------- 18 return player.seasonsPlayed > 20; //<------- 20 } ``` ??? In this example, you can see that a comment says one thing, but the code says another. --- class: double-wide, small, tertiary # Be Clear ## Comments ### Don't Excuse Confusing Code ??? Comments don’t excuse confusing code, which is too often how we use them. ... -- .leftest[ ```javascript function inductPlayer(player) { //induct a player if he is awesome. // a player is considered awesome if // he played for the brewers, // won a world series, // or was named steve. if (player.teams['brewers'] || player.worldSeriesTitleCount > 0 || player.firstName == 'Steve') { hallOfFame.induct(player); } } ``` ] ??? We write code that isn’t clear, and then we write lengthy comments summarizing the code. ... -- .rightest[ ```javascript function inductPlayer(player) { if (isAwesome(player)) { hallOfFame.induct(player); } } ``` ] ??? But instead of 5 lines of comments and 3 lines of code, wouldn’t you rather see one line of code? --- class: double-wide, tertiary # Be Clear ## Comments ### Apologize ```javascript // ________________ // | |_____ __ // | I'm Sorry | |__| |_________ // |________________| |::| | / // /\**/\ | \.____|::|__| < // ( o_o )_ | \::/ \._______\ // (u--u \_) | // (||___ )==\ // ,dP"/b/=( /P"/b\ // |8 || 8\=== || 8 // `b, ,P `b, ,P // """` """` ``` ??? Comments are often an apology For not being able to express ourselves in the code clearly. If you are apologizing, you'll want to include the "i'm sorry" kitten on a bicycle so i'll leave that here for you. --- background-image: url(images/comments-redundant.jpg) class: bg-cover, square ??? Here's another thing I think about comments --- class: double-wide, tertiary # Be Clear ## Comments ### Can Be Redundant ??? I remember being taught in college to comment every line. -- .leftest[ ```csharp public void SavePlayer() { //open the file this.OpenFile(); var player = { //the name of the player Name = "Jim Gantner", //the player's position Position = "2B" } //save the player to file this.SavePlayerToFile(player); } ``` ] ??? These comments just echo the code. They are just noise. If I'm writing code that is clear, I don't need them. --- class: double-wide, tertiary # Be Clear ## Comments ### Can Be Misused ??? as in unused code, a scenario which is better served by source control. -- ```javascript function isAwesome(player) { //return player.yearsExperience > 8 //return player.yearsExperience > 15 //return player.yearsExperience > 12 return player.yearsExperience > 10 && player.hits > 3000 && player.ops > .850; } ``` ??? --- class: sub-section # Comments ## Can also be good ??? This isn't to say all comments are bad. The right comment in the right situation can be helpful --- class: double-wide, medium, tertiary # Be Clear ## Comments ### Can Explain Intention -- .leftest[ ```javascript function mapPlayer(players) { //in: // [ // { // playerId: 1, // name: 'Jim Gantner', // position: '2B' // }, // ... // ] //out: // [ // 'Jim Gantner' // ] return _.chain(players) .where({ position: '2B' }) .pluck('name') .value(); } ``` ] ??? In this case, telling me the expected input and output of this function. These types of comments are especially useful when doing functional-style filter, map, reduce operations where you're mapping things from one shape to another --- class: double-wide, tertiary # Be Clear ## Comments ### Can Simplify ??? Comments can also simplify something like a regex ... -- ```javascript function validateTime(time) { //valid formats: HH:MM, // where HH is in 24 hour format var regex = new RegExp( "^([0-1][0-9]|[2][0-3]):([0-5][0-9])$"); return regex.test(time); } ``` ??? It takes time to decipher a regular expression. A comment can help you understand the code faster. With the caveat that if you aren't keeping it up to date, it's not doing any good. --- class: double-wide, tertiary # Be Clear ## Comments ### Can Warn The Reader ??? advise the reader why an unexpected line needs to be there. -- ```javascript function getMiddleInfielders(players) { return _.filter(players, function(player) { return player.position == '2B' || player.position == 'SS' // we have to include third basemen, // because sometimes the shift is on. || player.position == '3B' }); } ``` ??? ... So after all of this thinking about how to make my code more clear, I start to get excited --- background-image: url(images/kids/liv_happy1.jpg) class: bg-cover # Be Clear ??? and I ramble a whole bunch about names and comments and regular expressions and she says whoa whoa whoa, slow down. Next rule for good communication. --- class: new-section # Be Concise ??? And again, I was a little hurt by this ... --- background-image: url(images/kids/lila_sad2.jpg) class: bg-cover ??? But then I started to bring it back to code again. I can think of some ways my code is concise, especially when it comes to functions I have this theory that... --- background-image: url(images/war-and-peace.jpg) class: bg-cover ??? Functions should read less like war & peace --- background-image: url(images/cyoa.jpg) class: bg-cover square ??? And more like a choose your own adventure book --- class: double-wide, secondary # Be Concise ## Small Units ??? And we can accomplish this with small units of code. -- .leftest.small[ ```javascript function loadSomeData(){ me.loading = true; var dataRequest = {}; dataRequest.ids = _.pluck(me.items, 'id'); dataRequest.startDate = formatDate(me.startDate); dataRequest.endDate = formatDate(me.endDate); dataService.loadData( dataRequest, function (result) { me.fieldA = result.fieldA; me.fieldB = result.fieldB; notify('Data loaded!'); } ); } ``` ] ??? This is my example from before Where I identified all of the different things happening And extracted them ... -- .rightest.small[ ```javascript function loadSomeData(){ setLoadingState(); var dataRequest = buildDataRequest(); dataService.loadData( dataRequest, handleResponse ); } ``` ```javascript function setLoadingState(){ me.loading = true; } function buildDataRequest(){ //... } function handleResponse(data){ //... } ``` ] ??? I want to read a small excerpt, and from its contents, identify where I need to read next. Through this process, I can understand the code one small bit at a time. --- class: double-wide, secondary # Be Concise ## Eliminate Indentation ??? Here's a hint that your units of code are too large - You have a lot of indentation. -- .small[ ```javascript function searchPlayers(team, position, searchText) { var results = []; players.forEach(function(player) { if (player.team == team) { player.positions.forEach(function(playerPosition) { if (playerPosition == position) { if (player.firstName.startsWith(searchText)) { results.push({ playerId: player.playerId, fullname: `${player.firstName} ${player.lastName}` }); } else if (player.lastName.startsWith(searchText)) { results.push({ playerId: player.playerId, fullname: `${player.firstName} ${player.lastName}` }); } } }); } }); return results; } ``` ] ??? ... Indented code is confusing. --- class: double-wide, secondary # Be Concise ## Eliminate Indentation .small[ ```javascript function searchPlayers(team, position, searchText) { return players .filter(p => p.team == team) .filter(p => positionMatches(p, position)) .filter(p => playerNameMatches(p, searchText)) .map(mapMatchingPlayers); } function positionMatches(player, position) { return player.positions .filter(pos => pos == position).length > 0; } function playerNameMatches(player, searchText) { return ( player.firstName.startsWith(searchText) || player.lastName.startsWith(searchText) ); } function mapMatchingPlayers(player) { return { playerId: player.playerId, fullname: `${player.firstName} ${player.lastName}` }; } ``` ] ??? When possible, you can avoid it by extracting functions. --- class: double-wide, small, secondary # Be Concise ## Avoid Regions ??? Another way to identify if your function could be more concise is if it has regions ... -- .leftest[ ```csharp public void GetCurrentGameScenario( RequestModel request) { #region Get Player Info var playerFromDb = GetPlayerById( request.PlayerId); var playerResult = MapPlayer(playerFromDb); #endregion #region Get Game Info var gameFromDb = GetGameById( request.GameId); var gameResult = MapGame(gameFromDb); #endregion } ``` ] ??? In this example, you can see I’ve got sections of code indicated by regions. ... -- .rightest[ ```csharp public void GetCurrentGameScenario( RequestModel request) { var playerResult = GetPlayerInfo( request.PlayerId); var gameResult = GetGameInfo( request.GameId); } ``` ] .rightest[ ```csharp public PlayerViewModel GetPlayerInfo( int playerId) { //... } public GameViewModel GetGameInfo( int gameId) { //... } ``` ] ??? If I extract those blocks into separate methods, my top level method becomes a nice concise outline. ... This rule for regions also extends to classes. If you can find commonality between a bunch of functions in a class, enough to create a region, that region could probably be its own class. --- class: double-wide, secondary # Be Concise ## Pass Few Arguments ??? The more arguments you have, the more mental mapping the reader has to do, to keep the sequence straight. ... -- .leftest[ ```javascript function buildTeam( sp, c, _1b, _2b, _3b, ss, lf, cf, rf) { //... } } ``` ] ??? There are no hard limits, but fewer is better, 3 is a lot, and that is way too many. There are a couple of ways out of this. First, we can look at our method and decide if it is doing too much. If so, break it up. ... -- .rightest[ ```javascript function buildTeam( battery, infield, outfield) { //... } } ``` ] ??? Second, it's possible that the arguments you're passing are conceptually related. In this case, you can combine arguments into objects. --- class: double-wide, secondary # Be Concise ## But Be Complete ```javascript (w,g,c,m)=>(b=(`G`[r=`repeat`](w)+` `)[r](g))+(`C`[r](w)+` `)[r](c)+(`M`[r](w)+` `)[r](m)+b ``` ??? there is a balancing act between being concise and being complete. you don't want to be so concise that you've written code golf But just like communicating verbally Unnecessary words are noise. ... So after all of this thinking about how to make my code more concise, I told my wife --- background-image: url(images/kids/liv_happy2.jpg) class: bg-cover # Be Concise ??? Yeah. I recognize the value of being concise. What did she have for me next? She said, --- class: new-section # Stop repeating yourself ??? When you repeat yourself, I stop listening. And this made me kind of mad... --- background-image: url(images/kids/liv_sad1.jpg) class: bg-cover ??? But again I brought it back in my head to code. One of my favorite rules to follow is the --- class: sub-section # Don't repeat yourself ## DRY Principle ??? Repetition in code is a bug in waiting. You change things in 4 places, but forget about the 5th. --- class: double-wide, small, tertiary # Don't repeat yourself ## Stay DRY ### Extract Method ??? One of the best ways to eliminate duplication is by extracting methods. ... -- .leftest[ ```javascript function loadPlayerStats(players) { var _1b = players['cecil cooper']; var _1bStatsRequest = { playerId: _1b.id }; statsService .loadStats(_1bStatsRequest) .then(function (result){ _1b.stats = result; }); var _2b = players['jim gantner']; var _2bStatsRequest = { playerId: _2b.id }; statsService .loadStats(_2bStatsRequest) .then(function (result){ _2b.stats = result; }); var _3b = players['paul molitor']; var _3bStatsRequest = { playerId: _3b.id }; statsService .loadStats(_3bStatsRequest) .then(function (result){ _3b.stats = result; }); } ``` ] ??? Here, you can see I’m repeating about 9 lines of code for several different players. --- class: double-wide, small, tertiary # Don't repeat yourself ## Stay DRY ### Extract Method .leftest.dim-1.dim-2.dim-12.dim-13.dim-14.dim-15.dim-16.dim-17.dim-18.dim-19.dim-20.dim-21.dim-22.dim-23.dim-24.dim-25.dim-26.dim-27.dim-28.dim-29.dim-30[ ```javascript function loadPlayerStats(players) { var _1b = players['cecil cooper']; var _1bStatsRequest = { playerId: _1b.id }; statsService .loadStats(_1bStatsRequest) .then(function (result){ _1b.stats = result; }); var _2b = players['jim gantner']; var _2bStatsRequest = { playerId: _2b.id }; statsService .loadStats(_2bStatsRequest) .then(function (result){ _2b.stats = result; }); var _3b = players['paul molitor']; var _3bStatsRequest = { playerId: _3b.id }; statsService .loadStats(_3bStatsRequest) .then(function (result){ _3b.stats = result; }); } ``` ] ??? One thing that's interesting about repeated code is often you can see it in the shape of the code. --- class: double-wide, small, tertiary # Don't repeat yourself ## Stay DRY ### Extract Method .leftest.dim-1.dim-2.dim-3.dim-4.dim-5.dim-6.dim-7.dim-8.dim-9.dim-10.dim-11.dim-12.dim-23.dim-24.dim-25.dim-26.dim-27.dim-28.dim-29.dim-30[ ```javascript function loadPlayerStats(players) { var _1b = players['cecil cooper']; var _1bStatsRequest = { playerId: _1b.id }; statsService .loadStats(_1bStatsRequest) .then(function (result){ _1b.stats = result; }); var _2b = players['jim gantner']; var _2bStatsRequest = { playerId: _2b.id }; statsService .loadStats(_2bStatsRequest) .then(function (result){ _2b.stats = result; }); var _3b = players['paul molitor']; var _3bStatsRequest = { playerId: _3b.id }; statsService .loadStats(_3bStatsRequest) .then(function (result){ _3b.stats = result; }); } ``` ] ??? One thing that's interesting about repeated code is often you can see it in the shape of the code. --- class: double-wide, small, tertiary # Don't repeat yourself ## Stay DRY ### Extract Method .leftest[ ```javascript function loadPlayerStats(players) { var _1b = players['cecil cooper']; var _1bStatsRequest = { playerId: _1b.id }; statsService .loadStats(_1bStatsRequest) .then(function (result){ _1b.stats = result; }); var _2b = players['jim gantner']; var _2bStatsRequest = { playerId: _2b.id }; statsService .loadStats(_2bStatsRequest) .then(function (result){ _2b.stats = result; }); var _3b = players['paul molitor']; var _3bStatsRequest = { playerId: _3b.id }; statsService .loadStats(_3bStatsRequest) .then(function (result){ _3b.stats = result; }); } ``` ] .rightest[ ```javascript function loadPlayerStats(players) { var _1b = players['cecil cooper']; loadStatsForPlayer(_1b); var _2b = players['jim gantner']; loadStatsForPlayer(_2b); var _3b = players['paul molitor']; loadStatsForPlayer(_3b); }; ``` ```javascript function loadStatsForPlayer(player) { var statsRequest = { playerId: player.id }; statsService .loadStats(statsRequest) .then(function (result){ player.stats = result; }); }; ``` ] ??? On the right, I’ve extracted the duplication into one method, improving readability. And now I've only got one place that I need to change, instead of many. --- class: title ## Stay DRY # But not too DRY ??? Dry is a recommendation, not a hard rule. When I first learned about DRY, everything seemed like duplication. Now I find myself asking **"is this duplication"?** What's the **reason for these things changing?** If it seems like they would all change together, then yes, it's repetition. If they might change for different reasons, they might just be similar code. This is an important distinction because you don't want to end up with the wrong abstraction. --- background-image: url(images/kids/lila_happy3.jpg) class: bg-cover # Stop repeating yourself ??? So again, I said to my wife, I get it. I can stop repeating myself. No matter how many times I tell you about the amazing dream I had last night.... you don't care. And she said exactly. And we moved on to the next lesson. --- class: new-section # Pace Yourself ??? Sometimes you talk too fast, and I can't keep up. --- background-image: url(images/coping-2.jpg) class: bg-cover, square ??? I had to remind myself of some coping strategies I've learned (from booklets my daughter has brought home from school) ... About the pacing - I know I talk fast when I am trying to make a point So I think I see where she's coming from And then I thought about the ways I pace my code, to make it more readable. --- class: sub-section # Pace Yourself ## Use Whitespace ??? The first thing I like to do for pacing is use whitespace effectively --- class: double-wide, medium, tertiary # Pace Yourself ## Whitespace ### Separate Concepts Visually ??? I find that vertical whitespace helps keep concepts separate, and therefore more readable. ... -- .leftest[ ```javascript function loadStatisticsForPlayers() { me.loading = true; var statsRequest = buildStatisticsRequest(); playerService.loadStatistics( statisticsRequest, onStatisticsLoaded); } ``` ] ??? On the left, I have no vertical whitespace, so my code appears cluttered. ... -- .rightest[ ```javascript function loadStatisticsForPlayers() { me.loading = true; var statsRequest = buildStatisticsRequest(); playerService.loadStatistics( statisticsRequest, onStatisticsLoaded); } ``` ] ??? On the right, I’ve separated concepts with vertical whitespace. This allows me to quickly identify the different things happening in the method. --- class: double-stack, medium, tertiary # Pace Yourself ## Whitespace ### Reduce Concepts Per Line ??? Another way we can use vertical spacing is to give concepts their own line. ... -- ```javascript function getSecondBaseman(players) { return _.chain(players).where({ position: '2B'}).pluck('lastname').value(); } ``` ??? Here again, I’ve got a line of code that chains together several clauses, and it reads like a __runon sentence__. ... -- ```javascript function getSecondBaseman(players) { return _.chain(players) .where({ position: '2B'}) .pluck('lastname') .value(); } ``` ??? By giving each clause its own line, I can more easily identify important concepts. --- class: double-stack, tertiary # Pace Yourself ## Whitespace ### Reduce Concepts Per Line ??? Aside from readability, another great reason to reduce the concepts per line is how easy it is to see your changes in Git, or whatever other source control you're using. -- ![Me](images/codesamples/git-diff-bad.png) -- ![Me](images/codesamples/git-diff-good.png) --- background-image: url(images/kids/liv_happy3.jpg) class: bg-cover # Pace Yourself ??? So at this point, I got really excited and started telling her all about whitespace and Git and beep boop beep boop And she said UGH, this is what I'm talking about. ... Sometimes it just seems like you are speaking a different language. --- class: new-section # Speak My Language ??? If you want to communicate with me, speak my language. And this made me sad --- background-image: url(images/kids/liv_sad3.jpg) class: bg-cover ??? But I realized, using the right language is also one of my rules for writing readable code. --- class: double-wide, tertiary # Speak My Language ## Names ### Language Constructs ??? Especially when it comes to naming things It's important to use appropriate language constructs. ... -- ```javascript var stats = statisticsForPlayers; ``` ??? This code seems all fantastic. Just assigning one variable to another. ... -- ```javascript function statisticsForPlayers() { me.loading = true; var statsRequest = buildStatisticsRequest(); playerService.loadStatistics( statisticsRequest, onStatisticsLoaded); } ``` ??? Until you discover that statisticsForPlayers is a method, not an object. Code is easier to read when you use **nouns for classes**, and **verbs for functions**. When you use the wrong language constructs, you have to think harder about what something is. --- class: double-wide, tertiary # Speak My Language ## Names ### Spell Correctly ??? Misspelled names are confusing When you mis-spell a word, you are in the minority (except accommodation. no one knows how to spell that. we should get rid of it.) Everything else...You can be certain that a majority of those reading your code can spell correctly. ... -- .leftest[ ```javascript function geenrateRandomNumber(){ } ``` ] ??? So when I misspell the word generate, whether it's a typo or I think that's how it's spelled, It makes things harder for others to read. ... -- .rightest[ ```javascript function generateRandomNumber(){ } ``` ] ??? It also has the unfortunate side-effect of preventing my IDE from auto-completing when I type "gen". --- class: double-wide, tertiary # Speak My Language ## Names ### Be Consistent ??? Inconsistent language also forces the reader to think when they read your code. ... -- .leftest[ ```javascript //inconsistent names for lists var playerList; var teams; var listOfSeasons; ``` ] ??? If I am inconsistent with naming lists of things, I spend more time trying to identify what something is. ... -- .rightest[ ```javascript //consistent names for lists var playerList; var teamList; var seasonList; ``` ] ??? When you use consistent language, reading your code requires less thought. In this case, I can quickly identify if something is a list of things. --- class: double-wide, tertiary # Speak My Language ## Names ### Be Symmetrical ??? There's also something to be said for symmetry in naming ... -- .leftest[ ```csharp //asymmetrical names public void FileOpen(...) public void CloseFile(...) ``` ] ??? Asymmetry can show itself a couple ways. 1- Ordering of terms in the name We're naturally drawn to symmetry so this throws us off. ... --- class: double-wide, tertiary # Speak My Language ## Names ### Be Symmetrical .leftest[ ```csharp //asymmetrical names public void FileOpen(...) public void CloseFile(...) ``` ```csharp //asymmetrical names public void UnpackFile(...) public void CloseFile(...) ``` ] ??? There's also something to be said for symmetry in naming ... Asymmetry can show itself a couple ways. 1- Ordering of terms in the name ... 2- unnatural opposites There is a specific book I remember reading to my kids A tab-flappy book, and on the front of each flap was one word, behind the flap was the opposite. Up, down. In, out. Open, Close. These words are natural opposites, and we understand them from a very young age. ... -- .rightest[ ```csharp //symmetrical names public void OpenFile(...) public void CloseFile(...) ``` ] ??? Symmetrical names are easier to read because you understand them without thinking. --- class: double-wide, tertiary # Speak My Language ## Names ### Metaphors Are Tricky ??? And the idea of unnatural opposites brings me to metaphors. Metaphors are high-risk high-reward. A good metaphor can be really helpful for readability. It provides the reader a shortcut to understanding the code. But you really have to nail the metaphor. ... -- .leftest[ ```csharp // cuz metronomes "keep time". public interface IMetronome { DateTime Now { get; } } ``` ] ??? If you use one that isn't quite right, it can make things more confusing. And in this case, you can tell it's not right, because I have to add a cute comment. I got too cute with this. ... -- .leftest[ ```csharp public interface IClock { DateTime Now { get; } } ``` ] ??? My Clock interface doesn't need a cute comment because it is the right metaphor. --- background-image: url(images/kids/lila_happy1.jpg) class: bg-cover, inverse-text # Speak My Language ??? I get it, I told her. And we looked back at the list of things we'd talked about --- class: summary-list, center # Be Direct # Be Clear # Be Concise # Stop Repeating Yourself # Pace Yourself # Speak My Language ??? To be better at communication (read em) And looking at this, and comparing it to all the ways I try to do all these things in code, I said think I can sum it all up by saying, the key to good communication is... --- class: new-section # Don't Make Me Think ??? Above all else, Don't make me think! --- background-image: url(images/reactions/hi-five.jpg) class: bg-cover, square ??? And she said "exactly!" ... And this is the most important thing for code, too. Code should not make the reader think. --- name: development-is-hard background-image: url(images/legos_thumb.gif) animated-background: images/legos_single.gif class: bg-cover, inverse-text # Development Is Hard Enough ??? When you're writing or reading code, you're building a mental model in your head. **a lego spaceship** in your head It takes a lot of thought and effort to build this model up , and even more to keep from losing it. ... The more we have to think about the code we're reading, the less effort we are able to put toward maintaining that model. ... Development is already Hard Don't Make it harder on yourself, and your teammates, with code that communicates poorly. --- class: title # THANK YOU! .col.col-4.about.left.centered[ ## Steven Hicks ###
[@pepopowitz](http://twitter.com/pepopowitz) ###
steven.hicks@centare.com ###
[bit.ly/code-is-communication](http://bit.ly/code-is-communication) ] --- # Resources ## Further Reading * [_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) * [_Refactoring_](https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) * [_Code Complete_](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670)