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

Everything-as-code. Polyglotte Entwicklung in der Praxis. #OOP2017

Everything-as-code. Polyglotte Entwicklung in der Praxis. #OOP2017

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! #qaware #OOP2017 @LeanderReimer

M.-Leander Reimer

January 31, 2017
Tweet

More Decks by M.-Leander Reimer

Other Decks in Programming

Transcript

  1. Everything-as-code. Polyglotte Entwicklung in der Praxis. // OOP 2017 //

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

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

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

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

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

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

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

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

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

    http://spectrum.ieee.org/computing/software/ the-2016-top-programming-languages 4 https://www.sitepoint.com/whats-best- programming-language-learn-2015/ // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 10
  11. Die beste Programmiersprache gibt es nicht! Auf den Kontext kommt

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

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

    Arbeitskraft zu tun! 4 Hoher Automatisiersgrad von arbeitsintensiven und wiederkehrenden Arbeitsschritten 4 Höhere Software-Qualität durch abgestimmte Tool-Chain 4 Mehr Produktivität und Zufriedenheit der Teams 4 Bessere Kosten-Effizienz und Wettbewerbsfähigkeit // OOP 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() // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 14
  15. The Quest for an ideal Polyglot Project Archetype 4 Welche

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

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

    Software Entwicklungs Umgebung 4 Nutzung von Gradle als Build-Tool für das Setup und die Aktualisierung unserer Entwicklungsumgebungen 4 Software-Pakete werden als Dependencies ausgedrückt 4 Gradle Tasks and Groovy Skripte statt Shell-Scripting 4 Versionskontrolle der SEU Definition und Skripte // OOP 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' } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 18
  19. Build-as-code // OOP 2017 // Everything-as-code -> { created with

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

    vielseitig einsetzbar. 4 Einfache Unterstützung für Polyglotte Projekte. 4 Build Skripte sind maximal kurz und prägnant. 4 Drastisch reduzierte Build-Zeiten durch Incremental Builds. 4 Zahlreiche neue Features: Composite Builds, Kotlin-basierte Build-Skripte, Performance Verbesserungen, ... 4 Regelmäßige Releases. Stabil und ausgereift. // OOP 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.163' // and many more ... } task everythingAsCode() << { println 'Everything-as-code @ OOP 2017.' } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 21
  22. Main-as-code // OOP 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! // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 23
  24. Für die Mutigen: Kotlin als ernsthafte Alternative zu Java. //

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

    Entwickler sehr schnell zu erlernen. 4 Sehr ausgewogene Universalsprache. 4 Null Safety + jede Menge andere nützliche Features. 4 JDK6 kompatibel. Kleine Library-Größe. 4 Sehr guter IDE Support. 4 Wishful Greenfield Thinking. // OOP 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) } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 26
  27. Willkommen in der JavaScript Wunderwelt. 4 Ein Universum für sich!

    4 Klarer Trend: Single Page Webapplikationen. 4 HTML5 + CSS3 + ? 4 ? = TypeScript oder 4 ? = ECMAScript2015 + Babel 4 Rückgrat des Builds: node + npm + webpack // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 28
  28. Test-as-code // OOP 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" } } // OOP 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) } // OOP 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' } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 33
  32. Gradle und Docker to start Jenkins task createJenkinsHome() { mkdir("${System.getProperty('user.home')}/Jenkins")

    } task createJenkins(type: Exec, group: 'jenkinsci', dependsOn: createJenkinsHome, description: 'Create Jenkins') { commandLine 'docker', 'run', '--name', 'jenkinsci', '-p', '8080:8080', '-p', '50000:50000', '-v', "${System.getProperty('user.home')}/Jenkins:/var/jenkins_home", 'jenkinsci/jenkins' } task startJenkins(type: Exec, group: 'jenkinsci', description: 'Start Jenkins') { commandLine 'docker', 'start', 'jenkinsci' } task stopJenkins(type: Exec, group: 'jenkinsci', description: 'Stop Jenkins') { commandLine 'docker', 'stop', 'jenkinsci' } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 34
  33. Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/debian8-jre8 MAINTAINER M.-Leander Reimer <[email protected]>

    RUN mkdir -p /app ADD build/distributions/everything-as-code-1.0.0.tar /app WORKDIR /app/everything-as-code-1.0.0 RUN chmod 755 bin/everything-as-code EXPOSE 18080 CMD ./bin/everything-as-code // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 36
  34. 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 // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 37
  35. 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 // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 38
  36. 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.0.0" ports: - containerPort: 18080 env: - name: PORT value: 18080 // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 39
  37. Ja, wir brauchen Dokumentation! 4 Und nein. Der Quellcode ist

    nicht genug! 4 Technische Dokumente mit Word sind ! " # 4 Dokumentation sollte neben dem Quellcode liegen: change code, change docs. 4 Schnell und einfach zu schreiben. 4 Unterstützung für Code, Bilder, Diagramme // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 41
  38. // 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 // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 42
  39. 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' } // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 43
  40. 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. --- // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 45
  41. Heutige Projekte sind vielsprachig. // OOP 2017 // Everything-as-code ->

    { created with ❤ and ☕ by @LeanderReimer @qaware } 46
  42. Zeitgemäße Entwickler müssen vielsprachig sein! // OOP 2017 // Everything-as-code

    -> { created with ❤ and ☕ by @LeanderReimer @qaware } 47
  43. Wir alle müssen unsere Hausaufgaben machen. 4 Entwickler: Be polyglot,

    keep learning! 4 Architekten: Die richtige Sprache ist stark abhängig vom jeweiligen Projekt-Kontext. Choose wisely! 4 Project Managers: Give your techies freedom! 4 Universities: Unterrichtet vielsprachig! // OOP 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 48
  44. We are hiring. http://www.qaware.de/karriere/#jobs // OOP 2017 // Everything-as-code ->

    { created with ❤ and ☕ by @LeanderReimer @qaware } 50
  45. Q & A // OOP 2017 // Everything-as-code -> {

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