Clean Code Days 2016

The Lone Stranger

Why you can't establish Clean Code on your own

Carsten Windler, HolidayPirates GmbH

if ( is_array($fields ) ) {
	if ( isset($fields['blog_id']) ) {
		$blog_id = $fields['blog_id'];
	} elseif ( isset($fields['domain']) && isset($fields['path']) ) {
		$key = md5( $fields['domain'] . $fields['path'] );
		$blog = wp_cache_get($key, 'blog-lookup');
		if ( false !== $blog )
			return $blog;
		if ( substr( $fields['domain'], 0, 4 ) == 'www.' ) {
			$nowww = substr( $fields['domain'], 4 );
			$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain IN (%s,%s) AND path = %s ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'], $fields['path'] ) );
		} else {
			$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s AND path = %s", $fields['domain'], $fields['path'] ) );
		}
		if ( $blog ) {
			wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
			$blog_id = $blog->blog_id;
		} else {
			return false;
		}
	} elseif ( isset($fields['domain']) && is_subdomain_install() ) {
		$key = md5( $fields['domain'] );
		$blog = wp_cache_get($key, 'blog-lookup');
		if ( false !== $blog )
			return $blog;
		if ( substr( $fields['domain'], 0, 4 ) == 'www.' ) {
			$nowww = substr( $fields['domain'], 4 );
			$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain IN (%s,%s) ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'] ) );
		} else {
			$blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s", $fields['domain'] ) );
		}
		if ( $blog ) {
			wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
			$blog_id = $blog->blog_id;
		} else {
			return false;
		}
	} else {
		return false;
	}
} else {
	if ( ! $fields )
		$blog_id = get_current_blog_id();
	elseif ( ! is_numeric( $fields ) )
		$blog_id = get_id_from_blogname( $fields );
	else
		$blog_id = $fields;
}

$blog_id = (int) $blog_id;

$all = $get_all == true ? '' : 'short';
$details = wp_cache_get( $blog_id . $all, 'blog-details' );

if ( $details ) {
	if ( ! is_object( $details ) ) {
		if ( $details == -1 ) {
			return false;
		} else {
			// Clear old pre-serialized objects. Cache clients do better with that.
			wp_cache_delete( $blog_id . $all, 'blog-details' );
			unset($details);
		}
	} else {
		return $details;
	}
}

// Try the other cache.
if ( $get_all ) {
	$details = wp_cache_get( $blog_id . 'short', 'blog-details' );
} else {
	$details = wp_cache_get( $blog_id, 'blog-details' );
	// If short was requested and full cache is set, we can return.
	if ( $details ) {
		if ( ! is_object( $details ) ) {
			if ( $details == -1 ) {
				return false;
			} else {
				// Clear old pre-serialized objects. Cache clients do better with that.
				wp_cache_delete( $blog_id, 'blog-details' );
				unset($details);
			}
		} else {
			return $details;
		}
	}
}

if ( empty($details) ) {
	$details = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE blog_id = %d /* get_blog_details */", $blog_id ) );
	if ( ! $details ) {
		// Set the full cache.
		wp_cache_set( $blog_id, -1, 'blog-details' );
		return false;
	}
}

if ( ! $get_all ) {
	wp_cache_set( $blog_id . $all, $details, 'blog-details' );
	return $details;
}

switch_to_blog( $blog_id );
$details->blogname		= get_option( 'blogname' );
$details->siteurl		= get_option( 'siteurl' );
$details->post_count	= get_option( 'post_count' );
restore_current_blog();

/**
 * Filter a blog's details.
 *
 * @since MU
 *
 * @param object $details The blog details.
 */
$details = apply_filters( 'blog_details', $details );

wp_cache_set( $blog_id . $all, $details, 'blog-details' );

$key = md5( $details->domain . $details->path );
wp_cache_set( $key, $details, 'blog-lookup' );

return $details;
  • unprofessional
  • will make you unhappy
  • a.k.a. Sisyphos™
  • other developers will keep the code rotting
  • will introduce new bugs
  • leads to trouble with other developers

So the answer is

not really surprisingly

Clean Code!

... but how?

So you decided to introduce Clean Code

to your

project

Sorry...

Introducing Clean Code to an existing project

  • takes time
  • is painful
  • is cumbersome
  • ...is totally worth it

Management

Customer

Co-Worker

 

Other departments

 

People you might need to convince:

#1 - The Arguments

The Management

Now you have to explain why you want to spent more time on doing the same stuff as before.

The Business likes charts.

Let's give them some charts.

Project without Clean Code*

Life

  • Technology change
  • Requirements change
  • Personnel change

*simplification; not necessarily related to any real project

Technology change

  • Framework update
  • Language update
  • Infrastructure change because of technical need

Requirements change

  • New top prio feature requires many changes

Personnel change

  • Truck factor hits you

Truck Factor explained

your former lead dev

(yes, under the truck)

Project as a rollercoaster

Project with Clean Code

Projects compared

Sloppiness Short Term

Boost (SSTB)

Clean Code Long Term Benefit (CCLTB)

Time considerations

t 0

t1

t2

Startup

Phase

Consolidation Phase

Credit

Interest

\int_{t_0}^{t_1} \! f({x_s}) \, \mathrm{d}x < \int_{t_0}^{t_1} \! f(x_c) \, \mathrm{d}x
t0t1f(xs)dx<t0t1f(xc)dx\int_{t_0}^{t_1} \! f({x_s}) \, \mathrm{d}x < \int_{t_0}^{t_1} \! f(x_c) \, \mathrm{d}x

fewer backlog items are left when doing sloppy programming instead of clean code in the startup phase 

t 0

t 1

f({x_s})
f(xs)f({x_s})
f({x_c})
f(xc)f({x_c})
\int_{t_0}^{t_2} \! f({x_s}) \, \mathrm{d}x > \int_{t_0}^{t_2} \! f(x_c) \, \mathrm{d}x
t0t2f(xs)dx>t0t2f(xc)dx\int_{t_0}^{t_2} \! f({x_s}) \, \mathrm{d}x > \int_{t_0}^{t_2} \! f(x_c) \, \mathrm{d}x

more backlog items left when doing sloppy programming instead of Clean Code over project lifetime

t 0

t 2

f({x_c})
f(xc)f({x_c})
f({x_s})
f(xs)f({x_s})

Sometimes it's a Business decision to make debts

StartupMan

Sometimes it's ignorance

???

Wait, wait, wait... it's for the

Management, so keep it simple!

\int_{t_0}^{t_2} \! f({x_s}) \, \mathrm{d}x > \int_{t_0}^{t_2} \! f(x_c) \, \mathrm{d}x
t0t2f(xs)dx>t0t2f(xc)dx\int_{t_0}^{t_2} \! f({x_s}) \, \mathrm{d}x > \int_{t_0}^{t_2} \! f(x_c) \, \mathrm{d}x

Quality is an investment

Developer scalability

Lower per-bug-costs

Customer satisfaction

Why Clean Code matters

Quality as an investment

  • don't think short term 
  • future changes on platform or requirements will be easier
  • avoid piling up technical debt

Developer scalability

  • new developers can be added to a project easier
  • gathered experience and techniques can be transferred to other projects

Lower per-bug-costs

  • catching a bug on development stage is much cheaper than on Live
  • preventing regressions with live outage

Customer Satisfaction

  • Customer experiences more stable product
  • better reputation

The Customer

...ouch...

Leave it up to the Management, if you can!

Now you have to explain why you want them to spent more money on getting the same results as before.

Quality is an investment

End-Customer satisfaction

Develop agile

Why Clean Code matters for your customer

Quality is an investment

  • don't think short term
  • future changes on platform or requirements will be easier
  • Customer is lesser depending on your company*

*you probably don't want to tell that though

End-Customer satisfaction

  • more stable product
  • happier customers
  • better reputation
  • lesser outages

Develop agile

  • Introduce and evaluate new features faster

Co-Workers

Now you have to explain why you want them to spent more time on doing the same stuff than before

Yes, once again!

Happy refactoring

Saves development time

Ego

Lesser stress during deploys

Developer scalability

Happy refactoring

  • tests give you a much more confidence when refactoring
  • thus it will encourage to refactor if needed

Saves time

  • automated tests can save a lot of time
  • you don't need to click through half of the application to test a single small feature
  • bugs are usually easier to solve when you just worked on a topic than weeks after

Ego

  • bugs discovered by others are often a bit embarassing
  • overall project / developer reputation increases

Lesser stress during deploys

  • deploy with confidence

Developer scalability

  • easier to integrate new colleagues

Turn developers from this...

... into this

How to get developers on your side

  • live what you mean
  • provide good examples on the project
  • inhouse workshops
  • find allies
  • provide THE TOOLS

#2 The Tools

Code Style Guides

  • Improve readability
  • A matter of professionalism
  • Very easy to introduce

Code Style Guides

  • best use existing code standards
  • sniffers help you check and reformat automatically
  • run e.g. on pre-commit on changed files only

Software Metrics

What can you do with these numbers?

Hey Bob, how is your project going?

Awesome! During last the Refactoring Sprint we managed to drop the overall cyclomatic complexity by ~5 points (which is great). However we still have a maintenability index of 64.32 on the Middleware which we will change ASAP.

Nice

Your project on a T-Shirt

REFACTORING TIME!!

Why is my code so bad?

Software

Metrics

  • easy to introduce
  • will show you how good / how bad your codebase actually is
  • make developers aware of software quality
  • helps identifying problem areas

Source Code Analyzer

  • easy to introduce
  • will give you direct hints where in your code things go wrong
  • Copy & Paste detectors will not allow lazyness
  • prevents bad code from getting added to the codebase

Putting the finger where it hurts

However no tool will make you a better programmer 

Never stop learning!

Code Reviews

  • fairly easy it introduce*
  • actually a must have
    • can prevent really nasty bugs
    • great for sharing knowledge
  • be careful - don't be arrogant
  • some devs prefer eye-to-eye reviews, others are ok with comments in the Merge Request

*assuming you use Version Control Systems

Tests

KISS

Keep It teSted, Stupid!

Tests are not optional, they are mandatory.

Period.

We mean it.

Seriously.

Write / Refactor

Automated Tests

Ideal world

But what if we have no Unit Tests yet??

Write / Refactor

Bugs

Harsh reality

Writing Tests for untested classes usually requires refactoring

  • refactoring without tests == risky!
  • chicken-egg-problem
  • concentrate on Unit Tests for new classes
  • for legacy code, try to find simple classes to start with

Manual Tests

E2E

Unit Tests

The Almighty Test Pyramid

E2E

not (yet) available

not an option

- slow

- a bit fragile

- require test mode

E2E Tests

your way to go before you start with refactoring

+ require no refactoring

+ require no deep code knowledge

+ can be done in a sane amount of time

Workflows

  • tools are nothing without control
  • setup clearly documented workflows
  • be stubborn, otherwise sloppiness will come back
  • just like animals, some developers will SMELL any fear or weakness
  • so it's a good idea to automize

Continuous Integration

  • Fail build immediately
    • Code Sniffer
    • Source Code Analyzer
    • Unit Tests
    • Acceptance Tests
  • Reports
    • Software Metrics
    • Test coverage

What

is

left?

Clean Code is NOT about being the best coder in the world.

(although you have to be pretty good)

Clean Code is about professionalism.

Clean Code is about knowing that sloppy code will cost a lot of money.

And:

Clean Code is about being proud of your code!

And your job.

It's probably the best job in the world.

Thank you.

Image credits

Office work business
https://stocksnap.io/photo/HZCASACP3N

 

Top view of phone, earphones pen and diary

https://www.pexels.com/photo/top-view-of-phone-earphones-pen-and-diary-6662/

 

Guy working man
https://stocksnap.io/photo/GDAGX2JKI4

 

Red fire truck
https://stocksnap.io/photo/I2W591P4EV

 

Man wearing black and red checkered long sleeve...
https://www.pexels.com/photo/man-wearing-black-and-red-checkered-long-sleeve-shirt-wearing-black-wayfarer-sunglasses-sitting-on-white-wooden-chair-69212/
        

Man in white shirt using Macbook
https://www.pexels.com/photo/man-in-white-shirt-using-macbook-pro-52608/

 

Bow tie fashion man person

https://www.pexels.com/photo/bow-tie-fashion-man-person-5198/

 

All above images are licensed under CC0. Thank you very much for making this great work available freely!

The Lone Stranger

By carstenwindler

The Lone Stranger

  • 244
Loading comments...