Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Your Code is Terrible (I Love It!)

Patrick Seda
October 21, 2016

Your Code is Terrible (I Love It!)

Patrick Seda

October 21, 2016
Tweet

More Decks by Patrick Seda

Other Decks in Programming

Transcript

  1. Patrick Seda @pxtrick - CTO of Colligo Vox - Mobile/Technology

    Solutions Consulting - 25+ Years as a Software Professional - Apps: Enterprise to Children’s games
  2. rename method // Calculate the payment for given loan terms.

    function getResult(...) { // ... } var payment = getResult({...}); // Calculate the payment for given loan terms. function getPayment(...) { // ... } var payment = getPayment({...}); // Calculate the payment for given loan terms. function paymentFor(...) { // ... } var payment = paymentFor({...}); better better OK
  3. named parameters // Calculate mortgage APR. function getAPR(loanAmount, feesAmount, monthlyPayment,

    paidInFullMonth, balanceInLastMonth) { // Perform calculation ... } // Usage: With ordered parameters. var apr = getAPR(200000, 5000, 1500, 40, 20000);
  4. named parameters // Calculate mortgage APR. function getAPR(params) { //

    Perform calculation ... } // Usage: With named parameters. var apr = getAPR({ loanAmount: 200000, feesAmount: 5000, monthlyPayment: 1500, paidInFullMonth: 40, balanceInLastMonth: 20000 });
  5. compose method Scenario: 1.  Fetch the number of viewers of

    a video every second, and update the UI. 2.  If no manual interaction with the app has happened within 5 minutes, log out.
  6. compose method // UI interaction monitoring. var timeoutThresholdMs = 300000;

    // 5 mins var lastUITouch = Date.now(); // Start the fetching. var timer = setInterval(function() { fetchViewerCount({ onLoad: updateViewerCount }); }, 1000); // Update the number of viewers watching. function updateViewerCount(num) { if ((Date.now() - lastUITouch) < timeoutThresholdMs) { viewerCountLabel.value = num; } else { alert(‘You are being logged out.’); clearInterval(timer); loginWindow.open(); activeWindow.close(); } }
  7. compose method // UI interaction monitoring. var timeoutThresholdMs = 300000;

    // 5 mins var lastUITouch = Date.now(); // Start the fetching. var timer = setInterval(function() { fetchViewerCount({ onLoad: updateViewerCount }); }, 1000); // Update the number of viewers watching. function updateViewerCount(num) { if ((Date.now() - lastUITouch) < timeoutThreshouldMs) { viewerCountLabel.value = num; } else { alert(‘You are being logged out.’); clearInterval(timer); loginWindow.open(); activeWindow.close(); } }
  8. compose method function loggedIn() { activeWindow = countWindow.open(); loginWindow.close(); session.start();

    viewerCountFetcher.start() { onLoad: updateViewerCount }; } function logout() { viewerCountFetcher.stop(); session.end(); loginWindow.open(); activeWindow.close(); } // Update the number of viewers watching. function updateViewerCount(num) { if (session.isLive()) { viewerCountLabel.value = num; } else { alert(‘Session expired, you will be logged out.’); logout(); } }
  9. compose method function loggedIn() { activeWindow = countWindow.open(); loginWindow.close(); session.start();

    viewerCountFetcher.start() { onLoad: updateViewerCount }; } function logout() { viewerCountFetcher.stop(); session.end(); loginWindow.open(); activeWindow.close(); } // Update the number of viewers watching. function updateViewerCount(num) { if (session.isLive()) { viewerCountLabel.value = num; } else { alert(‘Session expired, you will be logged out.’); logout(); } }
  10. compose method function loggedIn() { activeWindow = countWindow.open(); // Starts

    session & fetch loginWindow.close(); } function logout() { loginWindow.open(); activeWindow.close(); // Stops session & fetch } // Update the number of viewers watching. function updateViewerCount(num) { if (session.isLive()) { viewerCountLabel.value = num; } else { alert(‘Session expired, you will be logged out.’); logout(); } }
  11. create with factory var Menu = require(‘Menu’); // Create a

    Radio button menu. var radioMenu = new Menu({ type: ‘radio’, buttons: [{ name: ‘Red’, onClick: openRedPage }, { name: ‘White’, onClick: openWhitePage }] });
  12. Headwear Shirts Shoes Headwear Shirts Shoes create with factory Women’s

    Men’s Red White Dessert Radio Menu Expandable Menu
  13. create with factory var Menu = require(‘Menu’); // Create an

    expandable menu. var expandableMenu = new Menu({ type: ‘expandable’, sections: [{ title: ‘Women\’s’, buttons: [{ name: ‘Headwear’, onClick: openWomenHeadwearPage }, { name: ‘Shoes’, onClick: openWomenShoePage }] }] });
  14. create with factory var Menus = require(‘Menus’); // Create a

    Radio button menu. var radioMenu = Menus.createRadioMenu({ buttons: [{ name: ‘Red’, onClick: openRedPage }, { name: ‘White’, onClick: openWhitePage }] });
  15. create with factory var Menus = require(‘Menus’); // Create an

    expandable menu. var expandableMenu = Menus.createExpandable({ sections: [{ title: ‘Women\’s’, buttons: [{ name: ‘Headwear’, onClick: openWomenHeadwearPage }, { name: ‘Shoes’, onClick: openWomenShoePage }] }] });
  16. conditionals become strategy function initAnalytics(params) { require(‘google’).initialize(params); } function logEvent(params)

    { require(‘google’).logEvent(params); } function logException(params) { require(‘google’).logException(params); } logEvent({ name: ‘failedLoginAttempts’, value: 3 }); logException({ name: ‘JSONParse’, value: inputString // e.g. ‘{first: “1”, second:}’ });
  17. conditionals become strategy function logEvent(params) { switch (analyticsProvider) { case

    ‘GOOGLE’: require(‘google’).logEvent(params); break; case ‘FLURRY’: require(‘flurry’).logEvent(params); break; } }
  18. conditionals become strategy function logException(params) { switch (analyticsProvider) { case

    ‘GOOGLE’: require(‘google’).logException(params); break; case ‘FLURRY’: require(‘flurry’).logException(params); break; } } var analyticsProvider = ‘FLURRY’; logEvent({ name: ‘failedLoginAttempts’, value: 3 }); logException({ name: ‘JSONParse’, value: inputString });
  19. conditionals become strategy function logEvent(params) { switch (analyticsProvider) { case

    ‘GOOGLE’: require(‘google’).logEvent(params); break; case ‘FLURRY’: require(‘flurry’).logEvent(params); break; case ‘CRASHLYTICS’: require(‘crashlytics’).logEvent(params); break; case ‘NEWRELIC’: require(‘newRelic’).logEvent(params); break; } }
  20. conditionals become strategy function logException(params) { switch (analyticsProvider) { case

    ‘GOOGLE’: require(‘google’).logException(params); break; case ‘FLURRY’: require(‘flurry’).logException(params); break; case ‘CRASHLYTICS’: require(‘crashlytics’).logException(params); break; case ‘NEWRELIC’: require(‘newRelic’).logException(params); break; } } var analyticsProvider = ‘NEWRELIC’; logEvent({ name: ‘failedLoginAttempts’, value: 3 });
  21. conditionals become strategy What is Strategy? •  Separates interface from

    implementation •  Enables interchangeable algorithms Context   Strategy   Strategy  A   Strategy  B   initialize()   logEvent()   logException()   initialize()   logEvent()   logException()   initialize()   logEvent()   logException()  
  22. conditionals become strategy var analyticsStrategies = { GOOGLE: require(‘google’), FLURRY:

    require(‘flurry’), CRASHLYTICS: require(‘crashlytics’), NEWRELIC: require(‘newRelic’) }; var analyticsProvider = ‘NEWRELIC’; var analytics = analyticsStrategies[analyticsProvider]; function logEvent(params) { analytics.logEvent(params); } function logException(params) { analytics.logException(params); } logEvent({ name: ‘failedLoginAttempts’, value: 3 });
  23. state machine // Handle asynchronous hardware events. function handleEvent(eventName) {

    switch (eventName) { case 'start': if (isTimerSet && isDoorClosed && !isCooking) { startCooking(); } break; case 'stop': if (isCooking) { stopCooking(); } clearTimer(); break; case 'openDoor': if (isCooking) { stopCooking(); } isDoorClosed = false; break; case 'closeDoor': isDoorClosed = true; break; case 'setTime': if (!isCooking && !isTimerSet) { isTimerSet = true; } break; case 'doneCooking': if (isCooking) { stopCooking(); clearTimer(); } } }
  24. state machine DoorClosed   Idle   NoTimer   DoorOpen  

    NoTimer   DoorClosed   Idle   TimerSet   DoorOpen   TimerSet   DoorClosed   Cooking   openDoor   closeDoor   openDoor   closeDoor   setTimer   stop   setTimer   stop   openDoor   stop   doneCooking   start  
  25. state machine // Handle asynchronous hardware events. function handleEvent(eventName) {

    // Attempt to transition states. if (stateMachine.handleEvent(eventName)) { // Delegate execution to the state object. stateMachine.currentState.execute(); } }
  26. We have a dilemma! •  Refactoring is necessary (to improve

    quality) •  Refactoring is done later-on (after a crushing deadline) •  Hard to get approval (“non-essential” work) getting it done