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

Everything-as-code. Eine vielsprachige Reise. @JUG_DA

Everything-as-code. Eine vielsprachige Reise. @JUG_DA

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 oder sogar 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. Willkommen in Babel! Hallo Software-Industrialisierung!

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 einzusetzen ist sicher nicht die Lösung. Genau das versuchen wir mit dieser Session zu vermitteln. Stattdessen braucht es eine gut integrierte und abgestimmte Tool-Chain. Wir berichten aus der Praxis.

M.-Leander Reimer

September 21, 2017
Tweet

More Decks by M.-Leander Reimer

Other Decks in Programming

Transcript

  1. Everything-as-code. Eine vielsprachige Reise. // JUG Darmastadt 2017 // Everything-as-code

    -> { created with ❤ and ☕ by @LeanderReimer @qaware } 1
  2. #whoami Mario-Leander Reimer Chief Technologist, QAware GmbH - Senior Developer

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

    ❤ and ☕ by @LeanderReimer @qaware } 3
  4. Welche Sprache verwenden echte Programmierer? // JUG Darmastadt 2017 //

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

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

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

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

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

    http://spectrum.ieee.org/computing/software/ the-2016-top-programming-languages • http://redmonk.com/sogrady/2017/06/08/language- rankings-6-17/ • https://jaxenter.de/programmiersprachen-rankings- q1-2017-54308 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 9
  10. Eine beste Programmiersprache gibt es nicht! Auf die Domäne kommt

    es an. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 10
  11. We are software craftsmen. The IDE is our workbench. //

    JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 11
  12. Unsere Definition von Software Industrialisierung • Hat nichts mit billiger

    Arbeitskraft zu tun! • Hoher Automatisiersgrad von arbeitsintensiven und wiederkehrenden Arbeitsschritten • Bessere Software-Qualität durch eine abgestimmte Tool-Chain • Mehr Produktivität und Zufriedenheit der Teams • Kosten-Effizienz und Wettbewerbsfähigkeit // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 12
  13. Software Industrialization ist eine Schlüsselanforderung für erfolgreiches DevOps und Continuous

    Delivery. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 13
  14. val softwareIndustrialization = everythingAsCode() open fun everythingAsCode() = everythingIsMadeFromCode() &&

    everythingIsMadeByCode() private fun everythingIsMadeFromCode() = true private fun everythingIsMadeByCode() = true // JUG Darmastadt 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 in welchen Domänen verwendet? • Welche Tools verwenden wir für Setup, Build, Code, Test, CI, Infrastructure, Documentation? • Was davon hat sich bewährt und was eher nicht? • Gibt es bereits Best Practices oder Anti-Patterns? + Wishful Greenfield Thinking! // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 15
  16. Eine vielsprachige Reise beginnt ... // JUG Darmastadt 2017 //

    Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 16
  17. SEU-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 17
  18. 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 definiert • Gradle Tasks und Groovy Code statt Shell-Scripting • Versionskontrolle der SEU Definition und Skripte // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 18
  19. 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' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 19
  20. Build-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 20
  21. 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 (40x) durch Incremental Builds. • Zahlreiche neue Features: Composite Builds, Kotlin- basierte Build-Skripte, Performance Verbesserungen, ... • Regelmäßige Releases. Stabil und ausgereift. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 21
  22. 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 @ JUG Darmstadt 2017.' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 22
  23. Main-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

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

    ist gut so! // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 24
  25. Aber: Kotlin als Alternative für Java ist einen Blick wert.

    // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 25
  26. 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. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 26
  27. @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) } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 27
  28. Frontend-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 28
  29. 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 29
  30. Test-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 30
  31. 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" } } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 31
  32. 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) } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 32
  33. Pipeline-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created

    with ❤ and ☕ by @LeanderReimer @qaware } 33
  34. 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' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 34
  35. 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.3.tar /app WORKDIR /app/everything-as-code-1.2.3 RUN chmod 755 bin/everything-as-code EXPOSE 18080 CMD ./bin/everything-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 36
  36. 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 37
  37. 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 38
  38. 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.3" ports: - containerPort: 18080 env: - name: PORT value: 18080 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 39
  39. 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 41
  40. // 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 42
  41. 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' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 43
  42. Architectur-Dokumentation mit Structurizr def workspace = new Workspace("Everything-as-code", "The system

    context of Everything-as-code.") def model = workspace.model // create a model and the software system we want to describe def bookApp = model.addSoftwareSystem("Book Application", "The best source to get info on books.") // create the various types of people (roles) that use the software system def anonymousUser = model.addPerson("Anonymous User", "Anybody on the web.") anonymousUser.uses(bookApp, "Searches for books and views details.") def browser = bookApp.addContainer("Web Browser", "Allows users to view information about books", "Edge, Chrome, Firefox") anonymousUser.uses(browser, "Views information from and makes requests to") def webApp = bookApp.addContainer("Web Application", "Hosts the browser-based web application and services", "Payara Fish") browser.uses(webApp, "uses [JSON/HTTPS]") // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 45
  43. Architektur-Validierung mit dem QAvalidator architecture(name: "Mail Example", prefix: "tview", reflexMLversion:

    "1.0") { excludes "java.lang.*" api "JavaMail" : "javax.mail.*" component "Mail" { api "IMail" : "de.qaware.mail.*" impl ["de.qaware.mail.impl.*", "de.qaware.mail.impl2.*"] uses "JavaMail" component "MailSender" { api ["de.qaware.mail.sender.*", "javax.mail.*"] impl "de.qaware.mail.impl.javamail.JavaMailSender" uses "JavaMail" } } } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 46
  44. 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. --- // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 48
  45. Heutige Projekte sind polyglot. // JUG Darmastadt 2017 // Everything-as-code

    -> { created with ❤ and ☕ by @LeanderReimer @qaware } 49
  46. // JUG Darmastadt 2017 // Everything-as-code -> { created with

    ❤ and ☕ by @LeanderReimer @qaware } 50
  47. Use the right tool for the job! // JUG Darmastadt

    2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 51
  48. Alles mit Augenmaß! Der richtige Technologie-Stack hängt ab vom Team,

    dem Projekt-Kontext und unseren Kunden. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 52
  49. Fork me on GitHub. https://github.com/lreimer/everything-as-code // JUG Darmastadt 2017 //

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

    created with ❤ and ☕ by @LeanderReimer @qaware } 55