100
Stop wasting time through clean code #phpnw11 Volker Dusch / @__edorian

Stop wasting-time-by-applying-clean-code-principles

  • Upload
    edorian

  • View
    13.049

  • Download
    0

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Stop wasting-time-by-applying-clean-code-principles

Stop wasting time through clean code#phpnw11

Volker Dusch / @__edorian

Page 2: Stop wasting-time-by-applying-clean-code-principles

2

So stop wasting time!

Why are we here?

Introduction

Page 3: Stop wasting-time-by-applying-clean-code-principles

3

Why are we here

to talk code and coding!

Introduction

Page 4: Stop wasting-time-by-applying-clean-code-principles

4

});});});

Introduction

Page 5: Stop wasting-time-by-applying-clean-code-principles

5

Me?

Introduction

Page 6: Stop wasting-time-by-applying-clean-code-principles

6

Volker Dusch

@__edorian

Introduction

Page 7: Stop wasting-time-by-applying-clean-code-principles

7

PHP for around 9 years

Introduction

Page 8: Stop wasting-time-by-applying-clean-code-principles

8

I’m currently into TDD, CI, Clean Code and shipping

Introduction

…amongst other stuff

Page 9: Stop wasting-time-by-applying-clean-code-principles

9

Just go and buy those

Introduction

*Book covers used under fair use

Page 10: Stop wasting-time-by-applying-clean-code-principles

10

Get in touch

Twitter: @__edorianXing / G+: Volker DuschStackoverflow:(visit us at http://chat.stackoverflow.com/rooms/11/php

IRC: edorianMail: [email protected]

Introduction

Page 11: Stop wasting-time-by-applying-clean-code-principles

11

Ask questions at any time!

Introduction

First question gets an elePHPant

Another question gets one too!

Page 12: Stop wasting-time-by-applying-clean-code-principles

12

Why try to save time?

Motivation

Page 13: Stop wasting-time-by-applying-clean-code-principles

13

Because we are

professionals

Motivation

Page 14: Stop wasting-time-by-applying-clean-code-principles

14

Even so our field is

quite young

Motivation

Page 15: Stop wasting-time-by-applying-clean-code-principles

15

Do you know how expensive it is to have

you people around?

Motivation

Page 16: Stop wasting-time-by-applying-clean-code-principles

16 Motivation

German numbers, ymmv

You get around 50k a year

Adding non-wage labor costs of around 60%

50.000 / Year

80.000 / Year

Office space, water, hardware, coffee, plants, cleaning, drugs, travels, training

100.000 / Year

250 Days without weekends and holidays and your 30 holidays => 220 days

455 / Day

€, £, Approx.. values

When working 8 hours a day 55 Bucks per Hour!

Your employer expects you to contribute

over 100.000 Bucks in business value per year!

Page 17: Stop wasting-time-by-applying-clean-code-principles

17

Wait

why are we here again?

Motivation

Page 18: Stop wasting-time-by-applying-clean-code-principles

18

To get things done, fast!

Delivering is fun!

Motivation

Page 19: Stop wasting-time-by-applying-clean-code-principles

19

Coding!

Motivation

Not:• Requirement engineering, • Scrum, • Kanban, • Organizational structures• Sane hardware• Sane working environments• Tools

Page 20: Stop wasting-time-by-applying-clean-code-principles

20

What do we spent time on?

Time! It matters!

Page 21: Stop wasting-time-by-applying-clean-code-principles

21 Time! It matters!

Thinking

Asking

Changing

Reviewing Reading

Typing

Not programming

Growing/BuildingCreating

Planning

Page 22: Stop wasting-time-by-applying-clean-code-principles

22

We spent time:

Time! It matters!

• Planning

• Reading

• Processing

• Writing

• Going to 10

• Actual typing? Not that much

Page 23: Stop wasting-time-by-applying-clean-code-principles

23

Your codebase is just likethe database of a website

Time! It matters!

Read:Write Ratio - 10:1

and brains suck as caches

Page 24: Stop wasting-time-by-applying-clean-code-principles

24

Goals:

Time! It matters!

• Cheap writes

The ability to change your software quickly

• Cheap reads

The ability to understand your software

quickly

• Writes require reads

Page 25: Stop wasting-time-by-applying-clean-code-principles

25

Cheap reads

Time! It matters!

People will read your code!

again and again and again and again

Does it take 5 minutes or 2 hours to

understand a module?

Page 26: Stop wasting-time-by-applying-clean-code-principles

26

Why is our code hard to understand?

Clean code?

• Management?

• Unclear requirements?

• Customers?

• Schedules?

• Requirement changes?

Page 27: Stop wasting-time-by-applying-clean-code-principles

27

Because WE wrote it like that!

We had our reasons but it still is our responsibility!

Clean code?

Page 28: Stop wasting-time-by-applying-clean-code-principles

28

Rushing out stuff to make people happy

“Well I’d go back and fix it but I can’t because $x”

Is that comfortable?

Clean Code?

Page 29: Stop wasting-time-by-applying-clean-code-principles

29

What we need:

Clean Code?

A way to WRITE to our codebase so that we

are able to keep our READ costs low!

• Fearing we might break something leads

to us not making necessary changes

• If we don‘t fix stuff we won‘t have a

readable, maintainable codebase

Page 30: Stop wasting-time-by-applying-clean-code-principles

30

We need a “Pragmatic” approach for cheap writes

Pragmatic!

Page 31: Stop wasting-time-by-applying-clean-code-principles

31

Pragmatic?

Pragmatic?

• Fast

• Simple

• Just get it done as fast as possible

• Nobody cares how you do it

• Micromanagement?

Page 32: Stop wasting-time-by-applying-clean-code-principles

32

‘Pragmatic’ === ‘TDD’

Pragmatic!

• My boss should NOT have to care about

the fact that I’m writing unit tests!

• If you can go faster when writing tests it

is your responsibility to do that!

• When not writing tests means “getting it

done slower” nobody is asking you to do

it!

Page 33: Stop wasting-time-by-applying-clean-code-principles

33

I don’t have time to sharpen my axe!

There are so many trees that I need to cut down

Pragmatic!

Page 34: Stop wasting-time-by-applying-clean-code-principles

34

This is not a TDD session

TDD! It saves kittens!

A small TDD checklist:

• Write unit tests! TDD is just the fastest

way.

• Just do it. It’s not magic, don’t fear doing

it!

• Practice before you do it at work!

• Tools? You don‘t need tools to get started!

• watch –n1 'phpunit' and ¼ of a screen

is ALL you need!

Page 35: Stop wasting-time-by-applying-clean-code-principles

35

Get the basics right

TDD! It saves kittens!

A small TDD checklist (continued):

• Aim for 100% test coverage

• Your tests should run REALLY fast

• If you can‘t do that now use --filter

• „You“ means everyone in your team!

Page 36: Stop wasting-time-by-applying-clean-code-principles

36

Writing unit tests is a SKILL

TDD! It saves kittens!

• You need to acquire it

• You need to practice

• It‘s just like any other tool and concept

• Actually – Unit testing is really easy…

• Writing testable code can be hard and

NEEDS practice!

Page 37: Stop wasting-time-by-applying-clean-code-principles

37

Enough! Code! Now!

Enough! Code! Now!

Page 38: Stop wasting-time-by-applying-clean-code-principles

38

What to focus on?

Is there anything we can base our decisions on?

Enough! Code! Now!

Page 39: Stop wasting-time-by-applying-clean-code-principles

39 I <2 off by one errors

"There are only two hard problems in Computer Science: cache invalidation, naming things, and off-by-one errors.“

- Phil Karlton

Page 40: Stop wasting-time-by-applying-clean-code-principles

40 Naming things!

Page 41: Stop wasting-time-by-applying-clean-code-principles

41

We name everything

We might want to get that right

Naming matters

Page 42: Stop wasting-time-by-applying-clean-code-principles

42

The purpose of a name

is to reveal intent

Naming matters

Page 43: Stop wasting-time-by-applying-clean-code-principles

43

A good name tells you everything you need to know!

Examples!

class User {public function getId() {…}public function getName() {…}

/** Calculate Body-Mass-Index @link … */public function getBMI() {…}

/** @param float $kg Weight in Kilogramm */public function setWeight($kg) {…}

Page 44: Stop wasting-time-by-applying-clean-code-principles

44

You shouldn’t need comments

Code! Finally!

class User {public function getUserId() {…}public function getFirst/Last/DisplayName() {…}

/** @link … */public function getBodyMassIndex() {…}

/** @param float $kilogramm */public function setWeight($kilogramm) {…}

Page 45: Stop wasting-time-by-applying-clean-code-principles

45

Names already are

compliable documentation

Naming matters

Page 46: Stop wasting-time-by-applying-clean-code-principles

46

Another example

Code!

class Calendar {public function getMonth($shortened = false) {…}

}

class Calendar {public function getMonthNames() {…}public function getShortendMonthNames() {…}

}

Page 47: Stop wasting-time-by-applying-clean-code-principles

47

Proper naming is important and easily neglectable

Names matter! A lot!

• Descriptive names communicate intent

• They enable us to understand what‘s up

• Misleading names can make it nearly

impossible to navigate in a codebase

Page 48: Stop wasting-time-by-applying-clean-code-principles

48

It is easy to write code that a machine understands

Names matter! A lot!

Writing code that ANOTHER human can understand is

A LOT harder

Page 49: Stop wasting-time-by-applying-clean-code-principles

49

Before we start

naming things

Let’s go!

Page 50: Stop wasting-time-by-applying-clean-code-principles

50

Hungarian Notation?

$pszError = &“E_FATAL\0“;

$aArray; $sString; $fFloat; $cCount;

interface IUser {} class CUser {}

• For classes and interfaces we have IDEs

• If you have long methods you might be

interested in types 100 lines later

• But that isn‘t the issue we want to adress

Page 51: Stop wasting-time-by-applying-clean-code-principles

51

Let’s name things!

Name everything!

• Namespaces

• Classes

• Functions

• Variables

Page 52: Stop wasting-time-by-applying-clean-code-principles

52

Namespaces

Name Namespaces!

• The things that come before the last

underscore of your class name

• Namespaces gave us the ability to get

pretty class names• “User” vs “Framework_Util_Stuff_Foo_Auth_User”

Page 53: Stop wasting-time-by-applying-clean-code-principles

53

Namespaces

PSR-0

• The PHP world has mostly agreed that

Namespaces Directory structure

• Is that a good idea?

• Harder to change folder structure

• Duplicate information

• Just do it anyways. It’s the expected

layout

• It also pushes you to create modules!

Page 54: Stop wasting-time-by-applying-clean-code-principles

54

Classes

Classy class names

• The class name is the single most

important definition of what fits into that

class

• Using generic names throws that away!

• ApplicationManager,

FrameworkDataInformationProvider,

UtilityDataProcessor

Page 55: Stop wasting-time-by-applying-clean-code-principles

55

One class, one purpose

Putting the “S” in “SOLID”

• Name it after its purpose

• Single responsibility principle!

• There should be only one reason to

change a class

Page 56: Stop wasting-time-by-applying-clean-code-principles

56

Proper class namesrelate to good methods

It’s good if it doesn’t fit!

• Think of the real world

$user->getStoreDiscount() ?

$userManager->getStoreDiscount(); ?

• Do we ask your customers how much

they owe us or do we keep track of that?

Page 57: Stop wasting-time-by-applying-clean-code-principles

57

Proper class nameslead to smaller classes

Focus!

• Should we let our Email class figure out

attachment mime types?

• By always asking if stuff fits we can

‘discover’ new classes in our

applications

• EmailAttachment,

ImageEmailAttachment?

Page 58: Stop wasting-time-by-applying-clean-code-principles

58

And we care because?• Big classes rob you of all OO benefits

• You depend on way to much other stuff

• Usually tightly coupled

• You can extend from those classes and

chances are you can’t swap out ether

• You don’t get nice interfaces as well

OOP is there to help us!

Page 59: Stop wasting-time-by-applying-clean-code-principles

59

A logger interfaceinterface Logger {

public function log($message);

}

Loggers log!

Page 60: Stop wasting-time-by-applying-clean-code-principles

Another logger interface

60

interface 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);

}

Composite?

Page 61: Stop wasting-time-by-applying-clean-code-principles

61

All those rules! I want to get things done!

Rule 1: Segmentation fault

• These are just guidelines

• They exist to act as early warning signs

• Not running into trouble two hours later

can save an amazing amount of time

Page 62: Stop wasting-time-by-applying-clean-code-principles

62 ‘Util’ is the new ‘Manager’

Util Because naming is harddjango/core/files/utils.py

django/core/mail/utils.py

django/db/backends/util.py

django/db/utils.py

django/forms/util.py

django/http/utils.py

django/test/utils.py

django/utils/... (django still rocks btw.)

Page 63: Stop wasting-time-by-applying-clean-code-principles

63

Reserved class names

Name everything!

• Some names already have meaning

• If you name stuff like a design pattern

you’d better implement that pattern!

• Factory, DataMapper, Visitor,

Composite, Strategy, Builder

• A Logger without a log function?

Page 64: Stop wasting-time-by-applying-clean-code-principles

64

Functions!

Best thing since LJMP

• First unit of organization

• Functions are where the action is

• For a long time functions where all we

had!

• Calling one got A LOT faster over the

years

Page 65: Stop wasting-time-by-applying-clean-code-principles

65

Function naming

Starting off easy

• Does it return a boolean?

• Call it hasX or isX

Page 66: Stop wasting-time-by-applying-clean-code-principles

66

Hidden booleans

Implementation details

$status = $user->getStatus();

if($status == $user::STATUS_BANNED) {

}

if($user->isBanned()) {

}

Page 67: Stop wasting-time-by-applying-clean-code-principles

67

Getters and Setters

setTitle($this);

• Getter retrieve internal state

• Setters modify internal state

• Both should not modify anything else

• Don’t make your setters into liars

Page 68: Stop wasting-time-by-applying-clean-code-principles

68

Setters return null!

setTitle($this);

• Or maybe $this but nothing else!

• Return codes for ugly IFs onto

consumers

if(!$config->set("key", "value")) {

}

if(!$config->has("key")) {

$config->set("key", "value");

}

Page 69: Stop wasting-time-by-applying-clean-code-principles

69

No boolean parameters

$user->setInactive(false);

If you don’t have a very good reason!

$user->setAdminStatus(false);

$user->setAdminStatus(true);

vs

$user->revokeAdminRights();

$user->grantAdminRights();

Page 70: Stop wasting-time-by-applying-clean-code-principles

70

Classes are nounsFunctions start with verbs!

$title->show();

->createStuff(); ->deleteStuff()

->dispatchCall(); ->subscribeUser();

But never

$user->admin(); or $user->bag();

$list->subscription();

Page 71: Stop wasting-time-by-applying-clean-code-principles

71

Agree on verbs for actions

Don’t $dir->expunge();

Can you tell me the difference between

$directory->delete($entry);

And

$directory->remove($entry);

$router->dispatch/delegate($call);

$list->add/append($user);

Page 72: Stop wasting-time-by-applying-clean-code-principles

72

Different actions need distinguishable names!

Name everything!

• Even if that makes function names

longer

• Usually those functions get created for

“doing the same thing with different

side effects but not wanting to call it

that”

• If you can agree upon terms with your

team that’s even better!

Page 73: Stop wasting-time-by-applying-clean-code-principles

73

Always favor longfunction names? NO!

Bigger is not always better

• A short an precise public API is

important

• But you want long privates

$user->setUserNameOrThrowAn\

ExceptionIfNotPossible();

$logger->logMessageButDontDoAnything\

IfYouCantWriteToTheBackend($message);

Not even: $logger->logMessage($message);

Page 74: Stop wasting-time-by-applying-clean-code-principles

74

Public functions will be called from many places

Bigger is not always better

• They should do one thing and maybe

throw an exception if they can’t do that

• Precise names help a lot to create

readable client code

• Interally used functions can be named

as verbosely as needed to communicate

their intent and behavior

Page 75: Stop wasting-time-by-applying-clean-code-principles

75

Readable classes

implements humanReadable

• Some state

• Lots of small descripte methods

• Best arranged in order of interest

Page 76: Stop wasting-time-by-applying-clean-code-principles

76

Readable classes?

sort($this) stuff out

class Log {

private function writeToLogfile() {}

private function flushCurrentLogfileBuffer(){}

public function log($message) {}

private isLogfileWriteable {}

public function __construct(

SplFileInfo $logfile) {}

private createLogfileIfNecaccary() {}

}

Page 77: Stop wasting-time-by-applying-clean-code-principles

77

Method ordering

usort

• First you build it

• Then you call it

• Then it does work

• Most work happens in private methods

Page 78: Stop wasting-time-by-applying-clean-code-principles

78

Readable classes?

sorted($this)

class Log {

public function __construct(

SplFileInfo $logfile) {}

public function log {}

private function isLogfileWriteable {}

private function createLogfileIfNecaccary() {}

private function writeToLogfile() {}

private function flushCurrentLogfileBuffer(){}

}

Page 79: Stop wasting-time-by-applying-clean-code-principles

79

Maximum function length?

Name everything!

• LOC of the function body?

• Do you like reading functions that are:

• Over 100?

• Over 20?

• Over 7?

Page 80: Stop wasting-time-by-applying-clean-code-principles

80

6 Lines ought to be enough for everybody?

Reading > Writing

• Doing only one thing shouldn’t take much

space

• Can you split it into 2 functions? Then do!

Page 81: Stop wasting-time-by-applying-clean-code-principles

81

Why long function bodies?

main::doEverything();

• It’s very easy to create

• You just have to worry about

functionality

Page 82: Stop wasting-time-by-applying-clean-code-principles

82

What is in a long function?

Implements unreadable

Local 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(!fwrite($this->log)) {

$errors[] = 'Write E'; }

return $errros;

} // I'm really 12 lines long

Page 83: Stop wasting-time-by-applying-clean-code-principles

83

State and operations?

We shall name it Timmy

• It’s a class!

• Long functions are where classes hide!

• Even in the small example we could

separate Log and LogFileWriter

Page 84: Stop wasting-time-by-applying-clean-code-principles

84

Function overflow?

Methods everywhere!

• Good thing they have nice names

• And we wrapped them in classes

• That’s good for read/write access!

• Calling overhead just doesn’t matter

Page 85: Stop wasting-time-by-applying-clean-code-principles

85

Smaller is harder to write

Wrapping up functions

• Writing ONLY small functions is a SKILL

• It is _easy_ to write big functions!

• But the first change makes it all worth!

• If everything is small it can even impact

your coding standard ;)

Page 86: Stop wasting-time-by-applying-clean-code-principles

86

Last thing to nameVariables

We shall name it Timmy

• Rules of thumb:

• Descriptive function parameters

• Big scope: long name

• Short scope: short name

Page 87: Stop wasting-time-by-applying-clean-code-principles

87

Example

We shall name it Timmy

for($i = 7; $i; --$i) {

$this->doStuffToListItem($i);

}

vs

for($currentlistItemId = 7;

$this->listItemIdIsValid($currentlistItemId);

--$currentlistItemId

) {

$this->doStuffToListItem($currentlistItemId);

}

Page 88: Stop wasting-time-by-applying-clean-code-principles

88

Descriptive members!

Class scope is big scope!

• Members are accessed from many

places. They should communicate

intent!

• Local variables in small classes are only

used twice or thrice

Page 89: Stop wasting-time-by-applying-clean-code-principles

89

Wrapping up naming

Names matter

"A name, like an honorable human, should say what it means and mean what it says”

Names are the basis of our

communication!

They can speed up things immensely!

Page 90: Stop wasting-time-by-applying-clean-code-principles

90

Arrays

Hash maps everywhere!

• PHP is hash-map-based programming

• Our constants are in hash maps

• Our variables are stored in hash maps

• Our arrays are hash maps

• We’d like to foreach over EVERYTHING!

• PHP Arrays let us create amazing data

structures without much hassle

Page 91: Stop wasting-time-by-applying-clean-code-principles

91

Arrays

Hash maps everywhere!

PHP Arrays also let us create amazingly

complex and unmaintainable data structures$config['user'][$user['id']]['languages']['native'] ='en';

But arrays are too way cool to not use them.

Maybe we need OOP arrays?

Page 92: Stop wasting-time-by-applying-clean-code-principles

92

Value objects!

New them everywhere!

• OOP Data structure

• You can create them everywhere, no DI!

• Identitiy is based on state! Think dates

• Lots of getters and setters. If you really

miss arrays you can implement

ArrayAccess too• http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/

• Implement IteratorAggregate and you get foreach back!

Page 93: Stop wasting-time-by-applying-clean-code-principles

93

Value objects!

New them everywhere!

class List implements IteratorAggregate, Countable {

protected $list = array();

public function add($item) { $this->list[] = $item; }

public function count() { return count($this->list); }

public function remove($index) {

if(!isset($this->list[$index])) {/* throw ... */ }

unset($this->list[$index]);

$this->list = array_merge($this->list); }

public function getIterator {

return new ArrayIterator($this->list); }

}

Page 94: Stop wasting-time-by-applying-clean-code-principles

94

Value objects!

New them everywhere!

class MonthlyValues implements IteratorAggregate {

protected $values = array();

public function __construct(array $values) {

if(count($values) != 12) {

thrown new InvalidArgumentException('...');

}

$this->values = $values;

}

public function get($monthNumber) {

return $this->values[$monthNumber];

} // ... public function getIterator() ...

Page 95: Stop wasting-time-by-applying-clean-code-principles

95

Comments

New them everywhere!

• I’ve spend a lot of time ranting about

comments. Name things properly!

• Additional Resources:• http://edorian.posterous.com/they-told-you-to-

document-everything-they-lie

• http://www.slideshare.net/Edorian/php-unconference-

europa-clean-code-stop-wasting-my-time

Page 96: Stop wasting-time-by-applying-clean-code-principles

96 Find the method body

abstract class xyzRequest { /** * Initializes this xyzRequest. * * Available options: * * * logging: Whether to enable logging or not (false by default) * * @param xyzEventDispatcher $dispatcher An xyzEventDispatcher instance * @param array $parameters An associative array of initialization parameters * @param array $attributes An associative array of initialization attributes * @param array $options An associative array of options * * @return bool true, if initialization completes successfully, otherwise false * * @throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest */ public function initialize(xyzEventDispatcher $dispatcher, $parameters = array(), $attributes = array(), $options = array()) {

Page 97: Stop wasting-time-by-applying-clean-code-principles

97

Error handling

Name everything!

• Is a big topic that requires a whole

session

• Just use exceptions in favor of return

codes

• Don‘t force IF statements in client code

$stuff = $factory->create('unkownStuff');

$stuff->doWork(); // E_FATAL?

• Enable consumers to handle errors at a

point of their choosing!

Page 98: Stop wasting-time-by-applying-clean-code-principles

Wrapping up

98 Professionals deliver!

• Testing makes you FASTER!

• Creating small functions saves time!

• Only tested code can stay clean

• You can only fix what you can reproduce!

• JUST – DO – IT! YOU – ARE – IN –

CHARGE!

Page 99: Stop wasting-time-by-applying-clean-code-principles

99 Thanks a lot!

Thank you for your time!

Slides will be at: http://joind.in/3600the link will be at @__edorian too ;)

Please leave me feedback!

Page 100: Stop wasting-time-by-applying-clean-code-principles

100

Recommended Reads

Rate my talk please!

*Book covers used under fair use

Clean Code Management Professionalism

^ Best book in 2011 ^In my humble opinion

https://www.google.com/bookmarks/l#!threadID=GU46RJYjEsMU%2FBDcqV3woQ8eH4sOcl

More: