Slide 1

Slide 1 text

33 THINGS YOU WANT TO DO BETTER TOM BUJOK JUG ZURICH 11th of MARCH 2014

Slide 2

Slide 2 text

33 THINGS YOU WANT TO DO BETTER ABOUT ME Tom BUJOk SBB, BERN, CH @TOMBUJOK WWW.REFICIO.ORG

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

THE CODE WE PRODUCE IS BAD

Slide 5

Slide 5 text

http://images.fineartamerica.com/images-medium-large/big-ball-from-a-cable-twisted-pair-aleksandr-volkov.jpg SPAGHETTI CODE JUNGLE

Slide 6

Slide 6 text

http://us.cdn282.fansshare.com/photos/rowanatkinson/mr-bean-rowan-atkinson-actor-brunette-jacket-mr-bean-1209381970.jpg JOHN - THE DEVELOPER

Slide 7

Slide 7 text

http://s1.cdn.autoevolution.com/images/news/gallery/mr-bean-s-classic-mini-showcased-at-european-rally-photo-gallery_8.jpg

Slide 8

Slide 8 text

! http://s1.cdn.autoevolution.com/images/news/gallery/mr-bean-s-classic-mini-showcased-at-european-rally-photo-gallery_8

Slide 9

Slide 9 text

?

Slide 10

Slide 10 text

WELL-DEFINED STANDARDS

Slide 11

Slide 11 text

(TIME | BUSINESS)+ PRESSURE

Slide 12

Slide 12 text

WHAT ABOUT OUR SKILLS?

Slide 13

Slide 13 text

http://i1.mirror.co.uk/incoming/article1867031.ece/ALTERNATES/s2197/Cristiano-Ronaldo-1867031.jpg PRACTICE MAKES PERFECT

Slide 14

Slide 14 text

DEPLOYING OUR SKILLS IS MUTUALLY EXCLUSIVE FROM MASTERING THEM!

Slide 15

Slide 15 text

http://thetrymovement.com/wp-content/uploads/2013/09/aristotle-wallpaper.jpg

Slide 16

Slide 16 text

Wikipedia: "Habits are routines of behavior that are repeated regularly and tend to occur subconsciously." WHAT IS a HABIT?

Slide 17

Slide 17 text

undesirable behavior pattern

Slide 18

Slide 18 text

BAD HABITS - ELIMINATE ASAP Bad Habits - Katherine Murdock “The Psychology of Habit”: - Recognise bad habits and eliminate them ASAP - The older you get the more difficult it is to remove a bad habit - Each repetition leaves its mark! Turning bad habits into good ones - Dr. Michael Roussell, PhD.: - You can’t erase a habit, you can only overwrite one. - Insert the new habits into the current habit loops

Slide 19

Slide 19 text

LET’S RECAP

Slide 20

Slide 20 text

LOMBOK

Slide 21

Slide 21 text

public class Person { ! private final Integer age; private final String name; private final String surname; ! }

Slide 22

Slide 22 text

@ToString @EqualsAndHashCode @RequiredArgsConstructor @Getter @Setter public class Person { ! private final Integer age; private final String name; private final String surname; ! }

Slide 23

Slide 23 text

@Data public class Person { ! private final Integer age; private final String name; private final String surname; ! }

Slide 24

Slide 24 text

! @Builder public class Person { ! @NonNull private final Integer age; @NonNull private final String name; @NonNull private final String surname; ! } Person.builder() .name("James").surname("Bond").age(33) .build();

Slide 25

Slide 25 text

@Log4j public class CleanupLombokExample { ! public void read(String input, String output) throws { @Cleanup InputStream in = new FileInputStream(input); @Cleanup OutputStream out = new FileOutputStream(output); byte[] b = new byte[1024]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } log.info("Finished!"); } }

Slide 26

Slide 26 text

@Log4j public class CleanupLombokExample { ! public void read(String input, String output) throws { @Cleanup InputStream in = new FileInputStream(input); @Cleanup OutputStream out = new FileOutputStream(output); byte[] b = new byte[1024]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } log.info("Finished!"); } }

Slide 27

Slide 27 text

GUAVA

Slide 28

Slide 28 text

@Test public void exampleOptionalPresent() { ! Optional possible = Optional.of(5); possible.isPresent(); // returns true possible.get(); // returns 5 } ! @Test(expected = IllegalStateException.class) public void exampleOptionalEmpty() { ! Optional empty = Optional.absent(); empty.isPresent(); // returns false empty.get(); // throws IllegalStateException } !

Slide 29

Slide 29 text

@Test public void validationExample() { Preconditions.checkState(initialized); Preconditions.checkArgument("IDLE".equals(status), "!IDLE"); Preconditions.checkPositionIndexes(start, end, data.length); String currentUser = Preconditions.checkNotNull(userId); }

Slide 30

Slide 30 text

@Test public void exampleCollections() { // Map> Multimap ml = ArrayListMultimap.create(); // Map> Multimap ms = HashMultimap.create(); // Map> Table tab = HashBasedTable.create(); }

Slide 31

Slide 31 text

LAMBDAJ

Slide 32

Slide 32 text

@Test public void filteringComplexShowcase() { Person me = new Person("Mario", "Fusco", 35); Person luca = new Person("Luca", "Marrocco", 29); Person biagio = new Person("Biagio", "Beatrice", 39); List list = asList(me, luca, biagio); filter(having( on(Person.class).getAge(), greaterThan(30)), list); }

Slide 33

Slide 33 text

@Test public void closureSimpleShowcase() { ! Closure println = closure(); { of(System.out).println(var(String.class)); } ! println.apply("one"); println.each("one", "two", "three"); }

Slide 34

Slide 34 text

LOGGING

Slide 35

Slide 35 text

try { throw new RuntimeException("Dev oops"); } catch (Exception ex) { log.error(ex); } ! ! try { throw new RuntimeException("Dev oops"); } catch (Exception ex) { log.error("Caught you bastard!", ex); } LOG4j

Slide 36

Slide 36 text

try { throw new RuntimeException("Dev oops"); } catch (Exception ex) { // does not compile // log.error(ex); } ! ! String id = "1231-4935-2314"; try { throw new RuntimeException("Dev oops"); } catch (Exception ex) { log.error("Caught you bastard! {}", id, ex); } SLF4j

Slide 37

Slide 37 text

BAD DEFAULTS

Slide 38

Slide 38 text

@Test public void autoGeneratedCatchExample_BAD() { try { stockService.buy("AAPL", 10); } catch (Exception ex) { ex.printStackTrace(); } }

Slide 39

Slide 39 text

@Test public void autoGeneratedCatchExample_GOOD() { try { stockService.buy("AAPL", 10); } catch (Exception ex) { throw new RuntimeException(ex.getMessage(), ex); } }

Slide 40

Slide 40 text

@Test public void insaneExceptionHandling() { try { stockService.buy("AAPL", 10); } catch (Exception ex) { // ignored as it will never happen } }

Slide 41

Slide 41 text

@Test public void insaneExceptionHandlingTrick() { try { stockService.buy("AAPL", 10); } catch (Exception ex) { // ignored as it will never happen System.exit(-1); // } }

Slide 42

Slide 42 text

! ! public final class QueryUtil { ! public static String extractTableName(String query) { // (...) return tableName; } ! public static String removeParameters(String query) { // (...) return queryNoParams; } ! public static String formatQuery(String query) { // (...) return queryFormatted; } }

Slide 43

Slide 43 text

http://my-dedicated-server.com/product_images/4324_large_file_EffectiveJava_L.png http://www-fp.pearsonhighered.com/assets/hip/images/bigcovers/0132350882.jpg

Slide 44

Slide 44 text

SPOCK

Slide 45

Slide 45 text

class SpockSpecExample extends Specification { @Unroll def "should detect blank for [#input]"() { ! expect: StringUtils.isBlank(input) == result ! where: input | result null | true "" | true " " | true "\t\n" | true "." | false } }

Slide 46

Slide 46 text

! def "should send messages to all subscribers"() { ! setup: Subscriber john = Mock(), jim = Mock() String msg = "Jazoon 2013 rocks!" when: publisher.send(msg) then: 1 * john.receive(msg) 1 * jim.receive(msg) ! } }

Slide 47

Slide 47 text

UNITILS

Slide 48

Slide 48 text

! ! ! public class UnitilsIOExample extends UnitilsJUnit4 { ! @FileContent(value = "/input.txt", encoding = "UTF-8") private String data; ! @TempFile("output.txt") private File output; ! @Test public void exampleFileContent() { assertEquals("Jazoon 2013 rocks!", data); } ! }

Slide 49

Slide 49 text

! ! @Test public void exampleAssertion() { User user1 = new User(1, "John", "Doe"); User user2 = new User(1, "John", "Doe"); assertFalse(user1.equals(user2)); assertReflectionEquals(user1, user2); } ! @Test public void exampleListAssertion() { List l = asList(2, 1); assertReflectionEquals(asList(1, 2), l, LENIENT_ORDER); }

Slide 50

Slide 50 text

private Service service = new Service(); ! @InjectInto(target = "service", property = "dao") private Dao dao = new Dao(); ! ! ! @InjectIntoStatic(target = Dao.class, property = "INSTANCE") private Dao singletonOverridingDao = new Dao(); ! @Test public void testSingletonOverrideInjection() { assertSame(singletonOverridingDao, Dao.INSTANCE); } ! } ! !

Slide 51

Slide 51 text

JUNITPARAMS

Slide 52

Slide 52 text

! ! ! @RunWith(JUnitParamsRunner.class) public class HardcodedParamsExample { ! @Test @Parameters({ "17, false", "22, true"} ) public void personIsAdult(int age, boolean correct) { assertThat(new Person(age).isAdult(), is(correct)); } }

Slide 53

Slide 53 text

! ! public class PersonProvider { public static Object[] provideAdults() { return $( $(new Person(25), true), $(new Person(32), true) ); } ! public static Object[] provideTeens() { return $( $(new Person(12), false), $(new Person(17), false) ); } }

Slide 54

Slide 54 text

AWAITILITY

Slide 55

Slide 55 text

! @Test public void testWithAtomicPseudoClosure() { await() .atMost(10, SECONDS) .untilCall( to(userRepository).size(), equalTo(3)); } ! ! private AtomicInteger atomic = new AtomicInteger(0); ! @Test public void testWithAtomicNumber() { await() .untilAtomic(atomic, equalTo(1)); } ! }

Slide 56

Slide 56 text

BYTEMAN

Slide 57

Slide 57 text

@RunWith(BMUnitRunner.class) public class FalseInjectionTest { ! @Test(expected = RuntimeException.class) @BMRule(name = "Processor IOException", targetClass = "FalseInjectionTest$StockService", targetMethod = "getQuote", action = "throw new RuntimeException()") public void checkIfFaultInjected() { new StockService().getQuote("AAPL"); }

Slide 58

Slide 58 text

GROOVY

Slide 59

Slide 59 text

XML PARSING Citibank 100 1000 UBS 90 2000

Slide 60

Slide 60 text

JAVA ! DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(stocks); doc.getDocumentElement().normalize(); NodeList nodes = doc.getElementsByTagName("stock"); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element el = (Element) node; NodeList list = el.getElementsByTagName("symbol") NodeList children = list.item(0).getChildNodes(); System.out.println(children(0).getNodeValue()); } } }

Slide 61

Slide 61 text

def doc = new XmlSlurper().parse(stocks) doc.stock.each { println it.symbol.text() } GROOVY +

Slide 62

Slide 62 text

GRAPE

Slide 63

Slide 63 text

@Grapes([ @Grab(group='commons-lang', module='commons-lang', version='2.4') ]) ! def abbreviate(String s) { StringUtils.abbreviate( s, 10 ) } ! def strings = ['Hello', 'Groovy'] strings.each { String aString -> println "$aString: ${abbreviate(aString)}" }

Slide 64

Slide 64 text

GRADLE

Slide 65

Slide 65 text

4.0.0 org.demo demo 0.0.1-SNAPSHOT jar http://maven.apache.org UTF-8 junit junit 4.8.1 test org.mockito mockito-all 1.8.4 test maven-resources-plugin 2.6 copy-resources validate copy-resources ${basedir}/target/resources/copy src/test/resources true ! apply plugin: 'java' ! group='org.demo' artifactId='demo' version='0.1-SNAPSHOT' ! repositories { mavenCentral() } ! dependencies { testCompile 'junit:junit:4.8.1' testCompile 'org.mockito:mockito-all:1.8.4' } ! task copyTestResources(type: Copy, dependsOn: 'assemble') { from 'src/test/resources' into 'src/test/resources/copy' include('**/*.xml', '**/*.properties') } MAVEN GRADLE

Slide 66

Slide 66 text

TOOLS

Slide 67

Slide 67 text

git log git status git diff ! git add git checkout -- git reset HEAD ! git branch git branch git branch -d git checkout git commit -m "message" git commit --amend git merge ! git stash list git stash push git stash pop ! git push origin master git pull git reset HEAD git reset --hard GIT

Slide 68

Slide 68 text

find -regex .*\\.groovy -exec grep -Hn "import spock." {} \; ! find -regex .*\\.groovy -exec sed -i "s/@mrbean/@tom/g" {} \; ! ls -Al | awk '{ print $6 " " $10 }' | sort -r BASH

Slide 69

Slide 69 text

BABUN https://github.com/babun/babun/

Slide 70

Slide 70 text

IDE CTRL + ALT + B ⌘ + ⎇ + B

Slide 71

Slide 71 text

CODE REVIEWS

Slide 72

Slide 72 text

WRAP-UP

Slide 73

Slide 73 text

http://izquotes.com/quotes-pictures/quote-any-jackass-can-kick-down-a-barn-but-it-takes-a-good-carpenter-to-build-one-sam-rayburn-151527.jpg

Slide 74

Slide 74 text

ANY QUESTIONS?

Slide 75

Slide 75 text

THANK YOU TOM BUJOK JUG ZURICH 11th of MARCH 2014 @TOMBUJOK WWW.REFICIO.ORG http://gamedevwithoutacause.com/wp-content/uploads/2011/11/singleton-12yr.jpeg