TIMTOWTDI and Java – (and not only Java!) – About me



TIMTOWTDI and Java – (and not only Java!) – About me

0 0


timtowtdi-java-jdd14


On Github Xaerxess / timtowtdi-java-jdd14

TIMTOWTDI and Java

(and not only Java!)

Grzegorz Rożniecki (@xaerxess)

About me

Java / Perl / JavaScript developer

Software reader / writer

xaerxess.pl

@xaerxess

Xaerxess

- Will this talk be about programming languages? Not really. - Java (obviously) - JavaScript (only good parts) - Perl (FTW!) - also: Python (and TIMTOWTDI?) - also: PHP (...) - A bit about good practices and how treat experience from other languages. - Something about good design (**IMO**).

About this talk

Slides | Source on GitHub

This work is licensed under a Creative Commons Attribution 4.0 International License.

TIMTOWTDI

There is more than one way to do it

Tim Toady

- Tim Toady - Larry Wall
- TIMTOWTDI == mess?
"The very fact that it's possible to write messy programs in Perl is also what makes it possible to write programs that are cleaner in Perl than they could ever be in a language that attempts to enforce cleanliness. The potential for greater good goes right along with the potential for greater evil." - Larry Wall, Perl creator - quite opposite in Java

Why?

Python Zen

There should be one - and preferably only one - obvious way to do it

- No shortcut for that and no fancy pronounciation - that'll be another way to say the phrase! - vs Perl?

Tim Toady in practice

What's goalkeeper for?

Tim Toady in practice

What's goalkeeper for? - Coach orders
"There are only two kinds of languages: the ones people complain about and the ones nobody uses" - Bjarne Stroustrup, C++ creator
"There are only 10 kinds of languages: the ones people complain about and the ones nobody uses" - Bjarne Stroustrup, C++ creator
- camel -> back to Perl

Perl doing for loop

for (my $i = 0; $i <= 3; ++$i) {
    print $i;
}
            
- Larry Wall -> linguist

Perl doing for loop

for my $i (0..3) {
    print $i;
}
            

Perl doing for loop

for (0..3) {
    print $_;
}
            

Perl doing for loop

for (0..3) {
    print;
}
            

Perl doing for loop

print for (0..3);
            
- Larry Wall -> linguist

Linguistic relativity

vs

Universal grammar

- **universal grammar hypothesis** says that the underlying structure of the human **brain determines (or at least constrains) the human capacity for language**, which is why all languages share a set of characteristics that are true of all languages (language aquisition device) - **linguistic relativity** suggests that **language itself limits (or at least influences) the ways in which language speakers conceptualize their world** and this affects their cognitive processes - Strong: language **determines** thought and linguistic categories limit and determine cognitive categories - Weak: linguistic categories and usage **influence** thought and behavior, both linguistic and non-linguistic - http://gallivananth1102.blogspot.com/2014/02/universal-grammar-or-linguistic.html

Sapir–Whorf hypothesis

Edward Sapir Benjamin Whorf linguistics theory Hopi - time & space - Edward Sapir - cognitive science basics (theory) - Benjamin Lee Whorf - research
Perl Java created in 1987 created in 1991 Perl 5 released in 1994 JDK 1.0 released in 1995 "get things done" "write once, run anywhere" OO support in Perl 5 OO support from the beginning

TIMTOWTDI

BSCINABTE

There’s more than one way to do itbut sometimes consistency is not a bad thing either

Tim Toady

Bicarbonate

OOP in Perl

package Foo;

sub new {
  my $class = shift;
  my $self = { }; # or [ ] or any arbitrary scalar value
  return bless $self, $class;
}

1;
            
- Perl community lesson: consistency

Standards

People like rules and guidelines. They like to agree with them, or to argue with them.
- http://programmers.stackexchange.com/questions/157277/indentation-is-there-any-evidence-to-show-whether-2-or-4-spaces-is-more-readabl - http://webcache.googleusercontent.com/search?q=cache:P5afiEgnEKwJ:www.cl.cam.ac.uk/teaching/1314/P201/ppig-book/ch1-5.pdf+&cd=5&hl=en&ct=clnk&gl=pl - http://blog.codinghorror.com/death-to-the-space-infidels/

Inconsistency

TIMTOWTDI?

Java and TIMTOWTDI

finally...

  • simple syntax
  • stable and battle tested
  • JVM
  • has coding standards
  • has best practices

but...

  • verbose syntax
  • backwards compatibility
  • JVM languages are not Java
  • has many coding standards
  • has some best practices

Java syntax

final class Person {

  private final String name;
  private final Integer age;

  public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public Integer getAge() {
    return age;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((age == null) ? 0 : age.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Person other = (Person) obj;
    if (age == null) {
      if (other.age != null)
        return false;
    } else if (!age.equals(other.age))
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
  }

}
            
vs
case class Person(name: String, age: Int)
            

Java 7+: Objects Java < 7 - Guava: Objects

  @Override
  public int hashCode() {
    return Objects.hash(name, age);
  }

  @Override
  public boolean equals(final Object obj) {
    if (!(obj instanceof Person))
      return false;
    final Person other = (Person) obj;
    return Objects.equals(this.name, other.name)
        && Objects.equals(this.age, other.age);
  }
            

Better?

Guava 18+: MoreObjects.toStringHelper Guava < 18: Objects.toStringHelper

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add("name", name)
        .add("age", age)
        .toString();
  }
            

Also better?

  @Override
  public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
  }
            

Lombok: @Value

@Value public class Person {
  String name;
  Integer age;
}
            

Lombok: black magic

Google AutoValue: @AutoValue

@AutoValue
abstract class Person {

  public static Person create(String name, Integer age) {
    return new AutoValue_Person(name, age);
  }

  public abstract String getName();
  public abstract int getAge();
}
            

Good trade-off?

Legacy

- Every language has some legacy code, API, etc.

You should prefer List<Foo> over Foo[] whenever possible.

  • A collection can be mutable or immutable. A nonempty array must always be mutable.
  • A collection can be thread-safe; even concurrent. An array is never safe to publish to multiple threads.
  • A collection can allow or disallow null elements. An array must always permit null elements.
  • A collection is type-safe; an array is not. Because arrays "fake" covariance, ArrayStoreException can result at runtime.
  • A collection can hold a non-reifiable type (e.g. List<Class<? extends E>> or List<Optional<T>>). With an array you get compilation warnings and confusing runtime exceptions.
  • A collection has a fully fleshed-out API; an array has only set-at-index, get-at-index and length.
  • A collection can have views (unmodifiable, subList, filter...). No such luck for an array.
  • A list or set's equals, hashCode and toString methods do what users expect; those methods on an array do anything but what you expect -- a common source of bugs.
  • Because of all the reasons above, third-party libraries like Guava won't bother adding much additional support for arrays, focusing only on collections, so there is a network effect.
- Kevin Bourrillion, lead Guava developer on StackOverflow

So, why would you ever use object arrays?

  • have to interact with an API that uses them, and you can't fix that API
    • convert to/from a List as close to that API as you can
  • have a reliable benchmark that shows you're actually getting better performance with them
    • benchmarks can lie, and often do
  • can't think of any other reasons
- Kevin Bourrillion, also there

JVM languages

  • JVM is great!
  • Scala, Clojure, Jython, JRuby
  • ...but employers don't trust them...
  • ...and there's big need for Java devs, not JVM-based devs
  • :-(
- Searching for the holy grail?

Coding standards

Be consistent in your team.

Ex. consistent IDE preferences

The "final" battle

Best practices

- Always override hashCode when you override equals - Minimize mutability - Design and document for inheritance or else prohibit it - Prefer lists to arrays - Know and use the libraries _Sounds familiar?_

Lambdas

"Closures feel to me like one of these design Black Holes. (...) So, should we just give in to the force of gravity and go the rest of the way? The debate's afoot. It's going to be an entertaining year." - James Gosling, Java creator - in 2006, on his blog
"Java has closures, it's just called 'anonymous inner classes' (...). [They] are the better and more 'java-way' to do closures. Adding an additional syntax for closures will only make the language more complex without solving even one real problem." - Karsten Wagner - in 2006, commenting Java closures proposal

...and in 2014 (finally) instead of this:

List<Album> favs = new ArrayList<>();
for (Album a : albums) {
    boolean hasFavorite = false;
    for (Track t : a.tracks) {
        if (t.rating >= 4) {
            hasFavorite = true;
            break;
        }
    }
    if (hasFavorite) {
        favs.add(a);
    }
}
Collections.sort(favs, new Comparator<Album>() {
    @Override public int compare(Album a1, Album a2) {
        return a1.name.compareTo(a2.name);
}});
            

...you can do this:

List<Album> sortedFavs =
  albums.stream()
        .filter(a -> a.tracks.anyMatch(t -> (t.rating >= 4)))
        .sorted(Comparator.comparing(a -> a.name))
        .collect(Collectors.toList());
            

There is more than one way to do it, finally!

THE END

Questions?

Please send me a feedback:@xaerxess or xaerxess at gmail dot com