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

Everything-as-code. Ein polyglottes Abenteuer. ...

Everything-as-code. Ein polyglottes Abenteuer. #jax2017

Als zeitgemäßer Entwickler muss man eine Vielzahl an Sprachen sicher beherrschen. Wir definieren unsere Entwicklungsumgebung mit Gradle, wir bauen unsere Software in Java, Kotlin und JavaScript. Wir verwenden Groovy und Scala um unsere Software zu testen. Die Build-Pipeline wird per DSL und JSON definiert. Mit YAML und Python beschreiben wir die Infrastruktur und das Deployment unserer Anwendungen. Die Dokumentation unserer Architekturen erledigen wir mit AsciiDoc und JRuby.

Use the right tool for the job! Das ist das Motto dieser Session. Jede Sprache hat Stärken in einer bestimmten Domäne. Diese Stärken gilt es zu nutzen. Aber einfach blind jede gerade angesagte Sprache oder Technologie einzusetzen ist sicher nicht die Lösung. Diese Session führt durch die einzelnen Entwicklungs-Phasen eines einfachen JEE Microservice und zeigt dabei einen in der Praxis erprobten, stabilen und gut integrierten polyglotten Technologie-Stack um moderne Enterprise Applikationen schnell und einfach zu entwickeln.

#qaware #CloudNativeNerd #jax2017 @LeanderReimer

M.-Leander Reimer

May 10, 2017
Tweet

More Decks by M.-Leander Reimer

Other Decks in Programming

Transcript

  1. Everything-as-code. Ein polyglottes Abenteuer. // JAX 2017 // Everything-as-code ->

    { created with ❤ and ☕ by @LeanderReimer @qaware } 1
  2. #whoami Mario-Leander Reimer Cheftechnologe, QAware GmbH • Vollblut Entwickler &&

    Architekt • #CloudNativeNerd • Open Source Enthusiast [email protected] http://github.com/lreimer http://speakerdeck.com/lreimer // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 2
  3. // JAX 2017 // Everything-as-code -> { created with ❤

    and ☕ by @LeanderReimer @qaware } 3
  4. Welche Sprache verwenden echte Programmierer? // JAX 2017 // Everything-as-code

    -> { created with ❤ and ☕ by @LeanderReimer @qaware } 4
  5. Meine #FirstSevenLanguages • Pascal • Basic • C / C++

    • Assembler • PHP • Java • C# // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 5
  6. Meine #LastSevenLanguages • Java • Groovy • TypeScript • Ruby

    • Kotlin • Scala • Go // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 6
  7. // JAX 2017 // Everything-as-code -> { created with ❤

    and ☕ by @LeanderReimer @qaware } 7
  8. // JAX 2017 // Everything-as-code -> { created with ❤

    and ☕ by @LeanderReimer @qaware } 8
  9. // JAX 2017 // Everything-as-code -> { created with ❤

    and ☕ by @LeanderReimer @qaware } 9
  10. Es gibt keine einstimmige Meinung ... • http://spectrum.ieee.org/computing/software/ the-2016-top-programming-languages •

    https://www.sitepoint.com/whats-best- programming-language-learn-2015/ • https://jaxenter.de/programmiersprachen- rankings-q1-2017-54308 // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 10
  11. Die beste Programmiersprache gibt es nicht! Auf den Kontext kommt

    es an. // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 11
  12. Die IDE ist unsere Werkbank. // JAX 2017 // Everything-as-code

    -> { created with ❤ and ☕ by @LeanderReimer @qaware } 12
  13. Unsere Definition von Software Industrialisierung • Hat nichts mit billiger

    Arbeitskraft zu tun! • Hoher Automatisiersgrad von arbeitsintensiven und wiederkehrenden Arbeitsschritten • Höhere Software-Qualität durch abgestimmte Tool- Chain • Mehr Produktivität und Zufriedenheit der Teams • Bessere Kosten-Effizienz und Wettbewerbsfähigkeit // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 13
  14. Wäre es nicht cool wenn ... open fun everythingAsCode() :

    Boolean { everytingIsMadeFromCode() && everythingIsMadeByCode() } val softwareIndustrialization = everythingAsCode() // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 14
  15. The Quest for an ideal Polyglot Project Archetype • Welche

    Sprachen werden in unseren Projekten verwendet? • Welche Tools verwenden wir für Setup, Build, Code, Test, CI, Infrastructure und Dokumentation? • Was davon hat sich bewährt und was eher nicht? • Gibt es bereits Best Practices für den Einsatz in der Praxis? + Wishful Greenfield Thinking! // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 15
  16. SEU-as-code // JAX 2017 // Everything-as-code -> { created with

    ❤ and ☕ by @LeanderReimer @qaware } 16
  17. Lightweight Developer Provisioning mit Gradle • [ SEU ] ->

    Software Entwicklungs Umgebung • Nutzung von Gradle als Build-Tool für das Setup und die Aktualisierung unserer Entwicklungsumgebungen • Software-Pakete werden als Dependencies ausgedrückt • Gradle Tasks and Groovy Skripte statt Shell- Scripting • Versionskontrolle der SEU Definition und Skripte // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 17
  18. plugins { id 'de.qaware.seu.as.code.base' version '2.4.0' } import static de.qaware.seu.as.code.plugins.base.Platform.isMac

    seuAsCode { seuHome = { if (isMac()) '/Volumes/Everything-as-code' else 'Y:' } projectName = 'Everything-as-code' } dependencies { // list of software dependencies ... software 'org.groovy-lang:groovy:2.4.7' software 'org.scala-lang:scala:2.11.8' software 'org.jruby:jruby:9.1.4.0' } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 18
  19. Build-as-code // JAX 2017 // Everything-as-code -> { created with

    ❤ and ☕ by @LeanderReimer @qaware } 19
  20. Maven ist gut. Gradle ist besser. • Sehr flexibel und

    vielseitig einsetzbar. • Einfache Unterstützung für Polyglotte Projekte. • Build Skripte sind maximal kurz und prägnant. • Drastisch reduzierte Build-Zeiten durch Incremental Builds. • Zahlreiche neue Features: Composite Builds, Kotlin- basierte Build-Skripte, Performance Verbesserungen, ... • Regelmäßige Releases. Stabil und ausgereift. // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 20
  21. apply plugin: 'application' apply plugin: 'war' apply plugin: 'kotlin' apply

    plugin: 'groovy' repositories { jcenter() } dependencies { providedCompile 'fish.payara.extras:payara-micro:4.1.1.164' // and many more ... } task everythingAsCode() << { println 'Everything-as-code @ JAX 2017.' } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 21
  22. Main-as-code // JAX 2017 // Everything-as-code -> { created with

    ❤ and ☕ by @LeanderReimer @qaware } 22
  23. Java ist nach wie vor die primäre Implementierungssprache! Und das

    ist gut so! // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 23
  24. Für die Mutigen: Kotlin als ernsthafte Alternative zu Java. //

    JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 24
  25. Warum Kotlin? Und nicht Scala, Clojure, ... • Für Java

    Entwickler sehr schnell zu erlernen. • Sehr ausgewogene Universalsprache. • Null Safety + Synatctic Sugar + jede Menge andere nützliche Features. • JDK6 kompatibel. Kleine Library-Größe. • Sehr guter IDE und Tool Support. • Wishful Greenfield Thinking. // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 25
  26. @JsonIgnoreProperties(ignoreUnknown = true) data class Book(val title: String, val isbn:

    String, val author: String) @ApplicationScoped open class Bookshelf { private val books = listOf(Book("The Hitchhiker's Guide to the Galaxy", "0345391802")) open fun byIsbn(isbn: String): Book? = books.find { it.isbn == isbn } } @Path("books") @Produces(MediaType.APPLICATION_JSON) open class BookResource @Inject constructor(private val bookshelf: Bookshelf) { @GET @Path("/{isbn}") open fun byIsbn(@PathParam("isbn") isbn: String): Response { val book = bookshelf.byIsbn(isbn) return if (book != null) Response.ok(book).build() else Response.status(Status.NOT_FOUND).build() } } @ApplicationPath("api") class BookstoreAPI : Application() { override fun getClasses() = hashSetOf(JacksonFeature::class.java, BookResource::class.java) } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 26
  27. Willkommen in der JavaScript Wunderwelt. • Ein Universum für sich!

    • Klarer Trend: Single Page Webapplikationen. • HTML5 + CSS3 + ? • ? = TypeScript oder • ? = ECMAScript2015 + Babel • Rückgrat des Builds: node + npm + webpack // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 28
  28. Test-as-code // JAX 2017 // Everything-as-code -> { created with

    ❤ and ☕ by @LeanderReimer @qaware } 29
  29. Groovy und Spock für Unit & Integration Tests class BookshelfSpec

    extends Specification { @Subject def bookshelf = new Bookshelf() @Unroll def "Find book #title by ISBN #isbn"() { when: 'we search a book by ISBN' def book = bookshelf.byIsbn(isbn) then: 'the title and author are correct' book?.title == title book?.author == author where: isbn || title | author "0345391802" || "The Hitchhiker's Guide to the Galaxy" | "Douglas Adams" "0345391829" || "Life, the Universe and Everything" | "Douglas Adams" } } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 30
  30. Scala und Gatling für Last-Tests class BooksPerformanceTest extends Simulation {

    val conf = http.baseURL("http://localhost:18080").acceptHeader("application/json") val feeder = csv("books.csv").random val scn = scenario("Book Search") .exec(http("Get all books").get("/api/books")) .during(30 seconds) { feed(feeder) .exec(http("Get book by title ${Title}").get("/api/books?title=${Title}")) .pause(1 second) .exec(http("Get book with ISBN ${ISBN}").get("/api/books/${ISBN}")) } setUp(scn.inject(atOnceUsers(10), rampUsers(50) over (30 seconds))) .assertions(global.responseTime.max.lessThan(5000)) .protocols(conf) } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 31
  31. Definition der Build-Pipeline per Jenkinsfile #!/usr/bin/env groovy node { stage

    'Checkout SCM' checkout scm stage 'Build/Analyse/Test' sh './gradlew clean build' archiveUnitTestResults() archiveDistributions() stage 'Dockerize' sh './gradlew buildDockerImage' stage 'Generate Documentation' sh './gradlew asciidoctor' } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 33
  32. Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121 MAINTAINER M.-Leander Reimer <[email protected]>

    RUN mkdir -p /app ADD build/distributions/everything-as-code-1.2.1.tar /app WORKDIR /app/everything-as-code-1.2.1 RUN chmod 755 bin/everything-as-code EXPOSE 18080 CMD ./bin/everything-as-code // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 35
  33. Vagrant und Ruby zum Setup lokaler VMs require 'yaml' $setup

    = <<SCRIPT sudo apt-add-repository ppa:ansible/ansible sudo apt-get update sudo apt-get install -y ansible sshpass SCRIPT Vagrant.configure("2") do |config| config.vm.box = "ubuntu/trusty32" settings = YAML.load_file 'src/vagrant/vagrant.yml' config.vm.provider "virtualbox" do |vb| vb.name = settings['vm']['name'] vb.gui = false vb.memory = "512" end config.vm.provision "shell", inline: $setup end // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 36
  34. Provisionierung mit Ansible (und Python) --- # file: jenkinsci.yml -

    hosts: jenkinsci remote_user: root tasks: - debug: msg="Creating a Jenkins pipeline job on {{ inventory_hostname }}" - jenkins_job: name: Everything-as-code Pipeline config: "{{ lookup('file', 'templates/pipeline-job.xml') }}" url: "http://{{ inventory_hostname }}" user: admin password: admin // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 37
  35. Cluster Orchestration mit Kubernetes --- apiVersion: extensions/v1beta1 kind: Deployment metadata:

    name: everything-as-code spec: replicas: 3 template: metadata: labels: tier: backend spec: containers: - name: everything-as-code image: "qaware-oss-docker-registry.bintray.io/lreimer/everything-as-code:1.2.1" ports: - containerPort: 18080 env: - name: PORT value: 18080 // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 38
  36. Ja, wir brauchen Dokumentation! • Und nein. Der Quellcode ist

    nicht genug! • Technische Dokumente mit Word sind ! " # • Dokumentation sollte neben dem Quellcode liegen: change code, change docs. • Schnell und einfach zu schreiben. • Unterstützung für Code, Bilder, Diagramme // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 40
  37. // Beispiel Architektur-Dokumentation mit arc42 (https://arc42.github.io) :imagesdir: ./images = image:qaware-logo.png[QAware

    GmbH,2016] Everything-as-code :toc-title: Table of Contents :toc: [[section-introduction-and-goals]] == Introduction and Goals The introduction to the architecture documentation should list the driving forces that software architects must consider in their decisions. === Requirements Overview === Quality Goals === Stakeholders <<<< include::02_architecture_constraints.adoc[] // further includes for the remaining sections // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 41
  38. AsciidoctorJ und Gradle to the Rescue plugins { id "org.asciidoctor.convert"

    version "1.5.3" } asciidoctorj { version = '1.5.4.1' } asciidoctor { sourceDir 'src/docs/architecture' resources { from('src/docs/architecture') { include 'images/**/*.png' include 'images/**/*.jpg' } } backends 'html5' options doctype: 'article' attributes 'source-highlighter': 'coderay' } // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 42
  39. These slides were written in Markdown. --- ## [fit] These

    slides were written in Markdown. - This is for real programmers! :smiley: - Several open source projects available - Use HTML and JavaScript alternatively. --- // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 44
  40. Heutige Projekte sind polyglot. // JAX 2017 // Everything-as-code ->

    { created with ❤ and ☕ by @LeanderReimer @qaware } 45
  41. Use the right tool for the job! // JAX 2017

    // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 46
  42. Wir alle müssen unsere Hausaufgaben machen. • Entwickler: Be polyglot,

    keep learning! • Architekten: Choose wisely! Die richtige Sprache ist stark abhängig vom jeweiligen Projekt-Kontext, Kundenumfeld und Team. • Project Managers: Give your techies freedom! • Universities: Unterrichtet vielsprachig! // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 47
  43. Cloud Native Night Meetup Termine [{ topic: 'Wolkenschieber - Operations

    in der Cloud', speakers: ['Timo Derstappen, Giant Swarm'], datum: 'Dienstag, 16. Mai 2017 um 18:30', wo: 'QAware Office Mainz', url: 'https://www.meetup.com/de-DE/Cloud-Native-Night/events/238824503/' }, { topic: 'Tracing and Monitoring of Cloud-Native Applications', speakers: ['Juraci Paixão Kröhling, Red Hat', 'Alois Mayr, Dynatrace'], datum: 'Dienstag, 25. Mai 2017 um 18:30', wo: 'QAware Office München', url: 'https://www.meetup.com/de-DE/cloud-native-muc/events/239505785/' }] // JAX 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 49
  44. We are hiring. http://www.qaware.de/karriere/#jobs // JAX 2017 // Everything-as-code ->

    { created with ❤ and ☕ by @LeanderReimer @qaware } 50
  45. Thanks! Questions? // JAX 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 51