Slide 1

Slide 1 text

Everything-as-code. A polyglot adventure. M.-Leander Reimer QAware GmbH

Slide 2

Slide 2 text

#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

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Which programming language do real developers use?

Slide 5

Slide 5 text

My #FirstSevenLanguages • Pascal • Basic • C / C++ • Assembler • PHP • Java • C#

Slide 6

Slide 6 text

My #LastSevenLanguages • Java • Groovy • TypeScript • Ruby • Kotlin • Scala • Go

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

There is no unanimous opinion ... • 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

Slide 10

Slide 10 text

There is no best programming language! Every language is strong in a specific domain.

Slide 11

Slide 11 text

We are software craftsmen. The IDE is our workbench.

Slide 12

Slide 12 text

Definition of Software Industrialization • This has nothing to do with cheap labor! • Automation of repetitive and laborious tasks • Better software quality through a standardized and streamlined tool chain • A well integrated tool chain leads to a higher productivity and happiness of your team • Better cost efficiency and competitiveness

Slide 13

Slide 13 text

Software Industrialization is a key requirement for DevOps and Continuous Delivery.

Slide 14

Slide 14 text

val softwareIndustrialization = everythingAsCode() open fun everythingAsCode() = everythingIsMadeFromCode() && everythingIsMadeByCode() private fun everythingIsMadeFromCode() = true private fun everythingIsMadeByCode() = true

Slide 15

Slide 15 text

The Quest for an ideal project archetype • Which languages are used for the specific domains in our projects? • Which tools are used for Setup, Build, Code, Test, CI, Infrastructure, Documentation? • What are the the dos and don'ts of using a specific language or technology? + some Wishful Greenfield Thinking!

Slide 16

Slide 16 text

So the polyglot adventure begins.

Slide 17

Slide 17 text

SEU-as-code

Slide 18

Slide 18 text

Lightweight Developer Provisioning • [ SEU ] German acronym; Software Entwicklungs-Umgebung • Use a build tool for the automated creation and update of a software development environment • Software packages are expressed as dependencies • Gradle tasks and Groovy are used instead of shell scripting • The SEU definition is version controlled just like ordinary source code • Available open source at http://seu-as-code.io

Slide 19

Slide 19 text

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' }

Slide 20

Slide 20 text

Build-as-code

Slide 21

Slide 21 text

Maven is good. Gradle is 100x faster. • Very flexible. Gradle can build everything. • Polyglot builds are supported easily. • Succinct build scripts. Default conventions over configuration. • Incremental builds, reduced build times. • New features: Kotlin build scripts, Composite Builds, Parallel Downloads, ... • Frequent releases. Mature and stable.

Slide 22

Slide 22 text

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 with Gradle @ DevoxxPL 2017.' }

Slide 23

Slide 23 text

Main-as-code

Slide 24

Slide 24 text

There is nothing wrong with Java as primary language!

Slide 25

Slide 25 text

But Kotlin is a serious alternative worth considering as primary language.

Slide 26

Slide 26 text

But why Kotlin? And not Scala, Clojure, et.al. • Easy to learn for Java developers. • Well-balanced universal language. • Inbuilt Null safety & Syntactic sugar & Excellent interoperability. • JDK6 compatible. Small library size. • Good IDE and tool support.

Slide 27

Slide 27 text

@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) }

Slide 28

Slide 28 text

Frontend-as-code

Slide 29

Slide 29 text

Welcome to JavaScript wonderland. • A strange universe on its own! • Clear trend towards Single Page Web Applications • Some fancy JavaScript UI framework. • HTML5 + CSS3 + ? • ? = TypeScript or • ? = ECMAScript2015 + Babel • Build Backbone: node + npm + webpack

Slide 30

Slide 30 text

Test-as-code

Slide 31

Slide 31 text

Groovy and Spock for 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" } }

Slide 32

Slide 32 text

Scala and Gatling for Load Testing 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) }

Slide 33

Slide 33 text

Pipeline-as-code

Slide 34

Slide 34 text

Build Pipeline Definition via 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' }

Slide 35

Slide 35 text

Infrastructure-as-code

Slide 36

Slide 36 text

Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121 MAINTAINER M.-Leander Reimer 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

Slide 37

Slide 37 text

Vagrant and Ruby for local VM setup require 'yaml' $setup = <

Slide 38

Slide 38 text

Provisioning with Ansible (and 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

Slide 39

Slide 39 text

Cluster Orchestration with 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

Slide 40

Slide 40 text

Documentation-as-code

Slide 41

Slide 41 text

Yes, we need documentation! • And no, the source code is not enough. • Writing technical docs with Word is ! " # • Documentation should be located next to the source code: change code, change docs. • It should be easy, quick and fun to write. • Support for code, images, UML diagrams, ...

Slide 42

Slide 42 text

// 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

Slide 43

Slide 43 text

AsciidoctorJ and 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' }

Slide 44

Slide 44 text

Architecture-as-code

Slide 45

Slide 45 text

Architecture documentation using 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]")

Slide 46

Slide 46 text

Architecture validation using 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" } } }

Slide 47

Slide 47 text

Presentation-as-code

Slide 48

Slide 48 text

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. ---

Slide 49

Slide 49 text

State of the art software projects are polyglot.

Slide 50

Slide 50 text

Use the right tool for the job!

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Use common sense! The right language and tool depends on your team, the project context and your customer.

Slide 53

Slide 53 text

Fork me on GitHub. https://github.com/lreimer/everything-as-code

Slide 54

Slide 54 text

Please vote for this ! talk.

Slide 55

Slide 55 text

Thanks! Questions?