Save time by applying clean code principles


Published on

Published in: Technology

Save time by applying clean code principles

  2. 2. ABOUT MESoftware EngineerPHP since 11 yearsCICleanCodeDevOpsTDDShippingBullet points
  3. 3. WORKING FORResearchGate gives science back to the people who make it happen.We help researchers build reputation and accelerate scientificprogress.On their terms.
  4. 4. GET IN TOUCHstackoverflow:Twitter: @_ _edorianG+ / Xing: Volker DuschIRC (freenode): edorianMail:
  5. 5. AGENDAMotivationBig pictureConcrete examples
  6. 6. WERE DEVELOPERSLets start with us!We get paid to do what we loveMost of us started because we where fascinated by programmingBut what is our job?
  7. 7. OUR JOB IS TO DELIVERGet things doneGive good estimatesAsk the right questionsKeep doing thatDont slow downKeep our promises
  8. 8. THE COST OF HAVING USFOLKSAROUNDGerman numbers, YMMV €, ApproximationsSalary: ~50k a year 50.000€ / Yearadding non-wage labor cost 80.000€ / Yearand office space, water, hardware,coffee, plants, cleaning, travels, training 100.000€ / YearWeekends, holidays, vacation, etc:We work 220 days a year. 455€ / day"Classic" 8 hour work day 55 Bucks per Hour!We are expected to contribute over 100.000 Bucks in business valueper year!
  9. 9. WHAT DO WE SPEND TIME ON?Planning a changeReading the codeActing on that planEvaluating the outcomeGOTO 10
  10. 10. OUR CODE LIKE OUR DATA STORAGEIt has a read:write ratio of 10:1...and our brains are really bad caches!
  11. 11. GOALSCheap writesThe ability to adapt our software to new requirements.Cheap readsThe ability to understand and reason about our software quickly.Writes require readsThere is no UPDATE. All we have is GET and PUT.
  12. 12. CHEAP READSYour coworkers will read your code again and again and againDoes it take them 2 hours or 5 minutes to understand a module?
  13. 13. SO HOW DO WE KEEP IT EASY?CHEAP WRITES!Fear to break something leads to not cleaning upNot cleaning up leads to expensive readsExpensive reads lead to expensive writesSo how do we reduce fear of breaking things?
  14. 14. TESTINGTDD is a pragmatic approach to maintainable code.Its not going to get easier than that ;)It doesnt even have to take longer
  15. 15. SHORT TDD INTERMISSIONWrite unit tests! TDD is just the fastest way, eventually.Tools? You dont need tools to get started!watch –n1 phpunitand ¼ of a screen is ALL you need!Aim for 100% test coverage but dont obsess. Test what breaks a lot.Have a fast test suite. Or use --filterif you cant.Writing tests can feel like extra work if you are rethinking an alreadysolved problem.TDD offers a way to first think about the problem, the interface andthe interactions and then filling in the details step by step until you aredone with the bigger picture.
  16. 16. TESTING ISNT HARDWriting proper code is hardThe harder it is to use the code in question, the harder is writing testsfor itComplex tests mean that the code is to complex. Break it down.If anything: Mocking is hard(-ish).Phake is your friend: Mocking for grown ups: PHPUnit mocking API is still good enough.
  17. 17. CODING GUIDELINESA collection for formatting and structure rules so that everyone caneasily find their way around and produce uniform code.Just create the rule set fitting your practicesAdapt when there is painDont over analyze. Just do itPHP CodeSniffer:
  18. 18. COMPLEXITYGUIDELINESSimilar to a coding standard but focusing on hunting down potentialproblems within your source codePossible bugsSuboptimal codeOvercomplicated expressionsUnused parameters, methods, propertiesPHP MessDetector
  19. 19. CODERules for structuring our source code that have proven to help withsustainability.
  20. 20. THE MOST BASIC THING:Separate the web-glue from the business logic.Keep templates stupidHave services owning the logic for manipulation of business entitiesHide the data access behind a layer that you can maintainindividually
  21. 21. SOLIDSingle responsibilityOpen-closedLiskov substitutionInterface segregationDependency inversion design)
  22. 22. COMPOSITION OVER INHERITANCEDont inherit from things if you can just use them.
  23. 23. DEPENDENCYINJECTIONThis goes for you code base as well as for your whole Company.Allows for quick and easy reuse of small componentsIf wiring is to hard people will copy/paste insteadCan be achieved in many ways. Pick one that works for you
  24. 24. REUSING CODEThe dependency manager for PHPAs easy as committing everything to your SCM.But with care free autoloading and updates!
  25. 25. CODE EXAMPLES!What to focus on?—Phil Karlton
  26. 26. NAMINGA good name tells you everything you need to know!class User {public function getId() {…}public function getName() {…}/*** Calculate Body-Mass-Index* @link ...wikipedia...* @return float*/public function getBMI() {…}/*** @param float $kg Weight in kilogramms*/public function setWeight($kg) {…}}
  27. 27. YOU SHOULDNT NEED COMMENTSNames are documentationclass User {public function getUserId() {…}public function getFirst/Last/Full/DisplayName() {…}/*** @return float*/public function getBodyMassIndex() {…}/*** @param float $kilogramm*/public function setWeight($kilogramms) {…}}
  28. 28. ANOTHER ONEclass Calendar {public function getMonth($shortened = false) {…}}class Calendar {public function getMonthNames() {…}public function getShortendMonthNames {…}}
  29. 29. NAMES ARE GUIDESDescriptive names communicate intentThey enable us to understand whats upMisleading names can make it nearly impossible to navigate in a codebaseIt is easy to write code that a machine understands.Writing code that another human can understand is A LOT harder.
  30. 30. CLASSY CLASS NAMESA class name is the single most important definition of what behaviorfits into that classUsing generic names throws that away!ApplicationManager, FrameworkDataInformationProvider,UtilityDataProcessor
  31. 31. ONE CLASS, ONE PURPOSEName it after its purposeThere should be only one reason to change a classA good class names makes inappropriate methods stand outDo we ask your customers how much they owe us or do we keep trackof that?$customer->getStoreDiscount(); // ?$customerManager->getStoreDiscount(); // ?$discountService->calculateDiscountForCustomer($customer); // ?
  32. 32. SMALLER MORE FOCUSED CLASSESShould we let our Email class figure out attachment mime types?By always asking if stuff fits we can "discover" new classes in ourapplicationsEmailAttachment, EmailImageAttachment?
  33. 33. WHY DO WE CARE AGAINBig inflexible classes rob us of all the OOP benefitsLots of dependenciesHarder to maintainHarder to reuseSwapping out a piece of the behavior gets way more complex
  34. 34. INTERFACES ARE FOR THE CONSUMERinterface Logger {public function log($logMessage);public function setOutputFormat($format);public function activate();public function deactivate();public function flush();public function setIncludeTimestamp($format);public function addLogger(Logger $logger);}
  35. 35. ONLY PUT IN THERE WHAT USERS NEEDinterface Logger {public function log($message);}
  36. 36. FUNCTION NAMINGCentralize implementation but exposing questions, not state$status = $user->getStatus();if ($status == $user::STATUS_BANNED) {}if ($user->isBanned()) {}
  37. 37. DONT USE BOOLEANS AS PARAMETERS EITHER$user->setAdminStatus(false);$user->setAdminStatus(true);$user->revokeAdminRights();$user->grantAdminRights();
  38. 38. FUNCTION LENGTHDo you like reading functions that are:100 lines?20 lines?7 lines?Functions tend to get big quickly because its very easy to write for thatone current specialized use case.
  39. 39. LONG FUNCTIONSLocal variables and code that operates on them? :)public function log($message) {$log = ;$errors = array();$log .= PHP_EOL . date(Y-m-d H:i:s) . : ;if (!$message) {$errrors[] = No Message;} else {$log .= $message;}if ($fp = !fopen(ERROR_LOG, w)) {$errors[] = Error log issue}if (!$fp || !fwrite($this->log)) {$errors[] = Write Error;}return $errros;}
  40. 40. ARRAYSArrays are great ad-hoc data structures but hard to read and maintain$monthlyUsers = array(124334, 123234141, // ...$monthlyUsers = array(1 => 124334, 2 => 123234141, // ...$monthlyUsers = array(jan => 124334, feb => 123234141, // ...
  41. 41. VALUE OBJECTSclass MonthlyValues implements IteratorAggregate {protected $values = array();public function __construct(array $values) {if(count($values) != 12) {thrown new InvalidArgumentException(...);}$this->values = $values;}/*** @param monthNumber See: Month::JANUARY ...*/public function getValueFor($monthNumber) {// error handling...return $this->values[$monthNumber];}public function getIterator() {return $this->values;}}
  42. 42. THANK YOU!
  43. 43. QUESTIONS?GET IN TOUCHstackoverflow:Twitter: @_ _edorianG+ / Xing: Volker DuschIRC (freenode): edorianMail: