Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby & Java 8 - The Reunion

Ruby & Java 8 - The Reunion

Java.

Just hear speak of this language we feel chill. Several complaints: too verbose, tons of XML, difficult to create applications because configuration is hard: look at old guy called Struts and the mastodon Spring to all occasions. A corporate language, with corporate soul, to corporate people.

Look you, so accustomed with Rails / Sinatra facility, template mechanisms and other features, try to venture into this inhospitale world: will want to distance. However, believe if you want, a lot ot things has changed.

With Java 8, doors opened much more warmly to rubyist programmers. Think of being able to create Java applications having features that until recently were unimaginable on the platform. Would not be more productive - and fun too - programming in a elegant and efficient way? This became possible with Java 8.

Come with me to rediscover a land once unfriendly and bureaucrat years ago and see that, with Ruby and their way, Java is no longer that bogeyman to avoid.

Marcelo Pinheiro

September 23, 2016
Tweet

More Decks by Marcelo Pinheiro

Other Decks in Technology

Transcript

  1. $ whoami • Fireman / Problem Solver / Programmer since

    2000 • Ruby, Python, Golang, Java, C#, Classic ASP, PHP, Coldfusion, Erlang and others • Fought, made coffee, negotiated deadlines • Software & DevOps Engineer
  2. Java? • Probably most of us already worked with it

    • Mainly terrible experiences • Highly verbose • Tons of XML to configure • Old-fashioned documentation • Bureaucratic
  3. Java 8: new stuff • Lambda • Method Reference •

    Stream API • java.util.stream • Date / Time • java.time • Optional • java.util.Optional • Improvements on Collections and Concurrent packages
  4. Java 8: Lambda • After years, finally • As other

    languages, adding functional paradigm features • Package java.util.function offers a lot of useful interfaces: • BiFunction, IntBinaryOperator, IntConsumer and others
  5. Java 8: Lambda sum = ->(s, i) { s +

    i } range = (1..ARGV[0].to_i) puts range.reduce(0, &sum) import java.util.function.IntBinaryOperator; import java.util.stream.IntStream; public class Lambda { public static void main(String[] args) { IntBinaryOperator sum = (s, i) -> s + i; IntStream range = IntStream .rangeClosed(1, Integer.valueOf(args[0])); System.out.println(range.reduce(0, sum)); } }
  6. Java 8: Method Reference • Another functional feature • Instead

    of explicitly call a method, you can use <Class>::<methodName> when possible • You can call instance / class methods here, since not passing any argument
  7. Java 8: Method Reference a = %w(a bc def) a.map(&:size).each

    { |a| puts a.inspect } import java.util.List; import java.util.Arrays; public class MethodReference { public static void main(String[] args) { List<String> a = Arrays.asList("a", "bc", "def"); a.stream() .map(String::length) .forEach(System.out::println); } }
  8. Java 8: Stream API • Provides functional-style to manipulate stream

    of objects • Awesome benefits with Collections API core library • Map/Reduce • Easy as Ruby does • Sequential / Parallel transformations
  9. Java 8: Stream API populate = ->(_) { Array.new(5) {

    Random.rand(9) + 1 } } arrays = 5.times.map(&populate) arrays.each { |a| puts a.inspect } import java.util.function.Supplier; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.Arrays; public class StreamExample { public static void main(String[] args) { Supplier<List<Integer>> populate = () -> new Random() .ints(5, 1, 10) .map((i) -> Integer.valueOf(i)) .boxed() .collect(Collectors.toList()); Stream<List<Integer>> arrays = Stream.generate(populate).limit(5); arrays .map((a) -> a.toArray()) .map(Arrays::toString) .forEach(System.out::println); } }
  10. Java 8: Date / Time • Current java.date package is

    non thread-safe • java.util.time is totally new package • Good interface • Thread-safe obviously • Date / Time operations (plus, minus etc)
  11. Java 8: Date / Time format = '%Y-%M-%d %H:%M:%S %z'

    now = Time.now.utc.localtime('-03:00') puts now.strftime(format) today = Time.new(2016, 9, 23, 12, 30, 00, "-03:00") puts today.strftime(format) import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.ZoneOffset; import java.time.ZoneId; import java.time.format.DateTimeFormatter; public class LocalDateTimeExample { public static void main(String[] args) { String pattern = "yyyy-MM-dd HH:mm:ss Z"; DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern); ZoneOffset offset = ZoneOffset.of("-03:00"); ZonedDateTime zonedNow = ZonedDateTime .of(LocalDateTime.now(), ZoneId.systemDefault()) .withZoneSameInstant(offset); System.out.println(fmt.format(zonedNow)); ZonedDateTime zonedToday = LocalDateTime .of(2016, 9, 23, 12, 30, 15) .atOffset(offset).toZonedDateTime(); System.out.println(fmt.format(zonedToday)); } }
  12. Java 8: Optional • Remember java.lang.NullPointerException? • Optionals solves in

    a good way • Integrated with Lambdas • Offer secure checks
  13. Java 8: Optional numbers = 5.times.map { 10 + Random.rand(10)

    }.sort puts numbers.inspect found = numbers.select { |n| n % 17 == 0 }.first puts("Number 17 #{found.nil? ? 'not found' : 'found'}") import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.Optional; import java.util.Arrays; public class OptionalExample { public static void main(String[] args) { List<Integer> numbers = new Random() .ints(5, 10, 20) .map((i) -> Integer.valueOf(i)) .boxed().collect(Collectors.toList()); System.out.println(Arrays.toString(numbers.toArray())); Optional<Integer> found = numbers .stream() .filter((n) -> n % 17 == 0) .findFirst(); System.out.println("Number 17 " + (!found.isPresent() ? "not found" : "found")); } }
  14. Java 8: Libraries • Web frameworks • Apollo - http://spotify.github.io

    • Jooby - http://jooby.org • Spark - http://sparkjava.com • Ratpack - https://ratpack.io • Persistence • Speedment - http://speedment.org • Tests • Lambda Behave - http://richardwarburton.github.io/lambda-behave
  15. Java 8 Libraries: Apollo • Provides a common set of

    libraries to write microservices • Routing / Response / Middleware • Application Lifecycle (loading, start & stop) • Specialised HTTP service using api and core libraries • Jetty as HTTP server import com.spotify.apollo.AppInit; import com.spotify.apollo.Environment; import com.spotify.apollo.route.Route; import com.spotify.apollo.httpservice.LoadingException; import com.spotify.apollo.httpservice.HttpService; public final class Ping { public static void main(String... args) throws Exception { HttpService.boot(Ping::init, "ping", args); } static void init(Environment environment) { environment.routingEngine().registerAutoRoute( Route.sync("GET", "/ping", requestContext -> "pong")); } }
  16. Java 8 Libraries: Jooby • Focused on developer productivity •

    Java DSL for routes • Simple; you can use Reflection, Dependency Injection and Annotations but at most cases is optional or not necessary • Jackson for JSON • Supports Jetty / Netty / Undertow as HTTP servers import org.jooby.Jooby; public class App extends Jooby { { get("/", req -> "Hello " + req.param("name").value("World") + "!"); } public static void main(String[] args) throws Exception { new App().start(args); } }
  17. Java 8 Libraries: Spark • Sounds familiar? • Good support

    to template engines • Embedded Jetty • No annotations import static spark.Spark.*; public class HelloWorld { public static void main(String[] args) { get("/hello", (req, res) -> "Hello World"); } }
  18. Java 8 Libraries: Ratpack • Based on Netty (non-blocking IO)

    • Just a HTTP server, no additional features • DIY business layer on it • Spring Boot to start as a service import ratpack.server.RatpackServer; public class Main { public static void main(String... args) throws Exception { RatpackServer.start(server -> server.handlers(chain -> chain .get(ctx -> ctx.render("Hello World!")) .get(":name", ctx -> ctx.render( "Hello " + ctx.getPathTokens().get("name") + "!" )))); } }
  19. Java 8 Libraries: Speedment • Stream ORM toolkit • Kinda

    ActiveRecord • Support for most famous SQL databases • Multi-thread • Key-Value Cache on search HaresApplication haresApplication = new HaresApplicationBuilder() .withPassword("myPwd") .withSchema("hares") .build(); HareManager hares = haresApplication.getOrThrow(HareManager.class); List<Hare> oldHares = hares.stream() .filter(h -> h.getAge() > 8) .collect(toList());
  20. Java 8 Libraries: Lamba Behave • Sounds familiar? • BDD

    unit to test Java applications • JUnit integration import com.insightfullogic.lambdabehave.JunitSuiteRunner; import org.junit.runner.RunWith; import java.util.Stack; import static com.insightfullogic.lambdabehave.Suite.describe; @RunWith(JunitSuiteRunner.class) public class StackSpec {{ Stack<Integer> stack = new Stack<>(); describe("a stack", it -> { it.isSetupWith(stack::clear); it.isConcludedWith(stack::clear); it.should("be empty when created", expect -> { expect.that(stack).isEmpty(); }); it.should("pop the last element pushed onto the stack", expect -> { expect.that(stack).isEmpty(); stack.push(2); stack.push(1); expect.that(stack.pop()).isEqualTo(1); }); }); }}
  21. Java: Good Stuff • SQL • JDBI - http://jdbi.org •

    Database Migration • Flyway - https://flywaydb.org • Lightweight Dependency Injection • Guice - https://github.com/google/guice • Template Engine • FreeMarker - http://freemarker.org • Immutability • Immutables - https://immutables.github.io • Read-Print-Loop • Java REPL - http://www.javarepl.com/console.html
  22. Java Good Stuff: JDBI • Fluent SQL library • Object

    serialisation • Queries • Batch operations // using in-memory H2 database DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test", "username", "password"); DBI dbi = new DBI(ds); Handle h = dbi.open(); h.execute("create table something (id int primary key, name varchar(100))"); h.execute("insert into something (id, name) values (?, ?)", 1, "Brian"); String name = h.createQuery("select name from something where id = :id") .bind("id", 1) .map(StringMapper.FIRST) .first(); assertThat(name, equalTo("Brian")); h.close();
  23. Java Good Stuff: Flyway • Command-line tool to apply migrations

    on a database • Supports MySQL, Postgres, RDS, SQL Azure and others • Similar to AR migrations, but: • You write SQL queries to be executed • Be careful (Captain Obvious)
  24. Java Good Stuff: Guice • Lightweight Dependency Injection toolkit •

    Alternative to Spring • No need to write XML with DI mapping class BillingService { private final CreditCardProcessor processor; private final TransactionLog transactionLog; @Inject BillingService(CreditCardProcessor processor, TransactionLog transactionLog) { this.processor = processor; this.transactionLog = transactionLog; } } public class BillingModule extends AbstractModule { @Override protected void configure() { bind(TransactionLog.class).to(DatabaseTransactionLog.class); bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class); } } public static void main(String[] args) { Injector injector = Guice.createInjector(new BillingModule()); BillingService bs = injector.getInstance(BillingService.class); ... }
  25. Java Good Stuff: FreeMarker <!doctype html> <html lang="en"> <head> <title>${pageTitle}</title>

    </head> <body> <div class="example-page"> <h1>Hello, world!</h1> <p>If your UTF-8 encoding is set up properly, these elements should be the same:</p> <ul> <li>© | &copy; | &#169;</li> <li>® | &reg; | &#174;</li> <li>¥ | &yen; | &#165;</li> </ul> </div> </body> </html> import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorld { @RequestMapping("/") public String loadExample(Model model) { model.addAttribute("pageTitle", "Example Freemarker Page"); return "hello-world"; } }
  26. Java Good Stuff: Immutables • Annotation processor to generate immutable

    classes • Ready to JSON serialise • Generates classic getter/setters AND methods based on attribute name import org.immutables.value.Value; @Value.Immutable public interface ValueObject { String name(); List<Integer> counts(); Optional<String> description(); } ValueObject valueObject = ImmutableValueObject.builder() .name("My value") .addCounts(1) .addCounts(2) .build(); @Value.Immutable abstract class AbstractItem { abstract String getName(); abstract Set<String> getTags(); abstract Optional<String> getDescription(); } // Use generated immutable implementation ValueObject valueObject = ImmutableValueObject.builder() .name("My value") .addCounts(1) .addCounts(2) .build(); // Use generated value object Item namelessItem = Item.builder() .setName("Nameless") .addTags("important", "relevant") .setDescription("Description provided") .build(); Item namedValue = namelessItem.withName("Named");
  27. Java Good Stuff: REPL • Yes, exists! • Good for

    basic interactions • Remember to import classes / packages first • Available on site and JAR download to run as command-line
  28. Java 8: still Java • Maven • XML to infinity

    and beyond • Still verbose as hell • Dependency Injection / Design Patterns when possible • More modern, but not so in average • Spring thinking prevails • Hard to find polyglot programmers
  29. Java 8: still Java • My impressions • Much more

    friendly than 8 years ago • Functional Features on Ruby gave to me a smooth transition to Java 8 • Culture shock is a opportunity to develop good tools and change thinking