IT-Tage 2017, Frankfurt am Main: Vortrag von Mario-Leander Reimer (@LeanderReimer, Cheftechnologe bei QAware)
Abstract:
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. Dieser Vortrag führt durch die einzelnen Entwicklungs-Phasen eines 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.
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Everything-as-code – Polyglotte Entwicklung in der Praxis
1.
2. #whoami
Mario-Leander Reimer
Cheftechnologe, QAware GmbH
- Senior Developer && Architect
- 20+ Jahre Erfahrung
- #CloudNativeNerd
- Open Source Enthusiast
mario-leander.reimer@qaware.de
http://github.com/lreimer
http://speakerdeck.com/lreimer
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
3. Software Industrialization
ist eine Schlüsselanforderung
für erfolgreiches DevOps und
Continuous Delivery.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
4. Ein Software-Fließband produziert
und liefert die fertige Software an.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
5. Software Industrialisierung bedeutet ...
• 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
6.
7. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
8. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
9. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
10.
11. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
12. val softwareIndustrialization = everythingAsCode()
open fun everythingAsCode() =
everythingIsMadeFromCode()
&& everythingIsMadeByCode()
private fun everythingIsMadeFromCode() = true
private fun everythingIsMadeByCode() = true
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
13. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
14. Auf die Domäne kommt es an!
Eine beste Programmiersprache gibt es nicht.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
15. Die Queste nach dem idealen 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!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
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
• Open Source. http://seu-as-code.io
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
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'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
20.
21. # language: en
Functionality: Authentication and Authorization
Scenario Outline: Check proper login behaviour
Given the username "<USERNAME>"
And the password "<PASSWORD>"
When the user logs into the system
Then the login result is "<RESULT>"
Examples: Login data
| USERNAME | PASSWORD | RESULT |
| mario-leander.reimer | invalidpwd | failure |
| unknown | somepwd | failure |
| mario-leander.reimer | correctpwd | success |
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
22. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
23.
24. Maven ist gut. Gradle ist 100x schneller.
• Sehr flexibel und vielseitig einsetzbar.
• Einfache Unterstützung für polyglotte Projekte.
• Build Skripte sind maximal kurz und prägnant.
• Deutlich reduzierte Build-Zeiten durch inkrementelle
Builds und Caching
• Zahlreiche neue Features: Composite Builds, Kotlin-
basierte Build-Skripte, Performance Verbesserungen, ...
• Regelmäßige Releases. Stabil und ausgereift.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
25. 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 using Gradle @ ContinuousLifecycle 2017.'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
26.
27. Java ist nach wie vor unsere
primäre Implementierungssprache!
Und das ist gut so!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
28. Aber:
Kotlin als Alternative zu
Java ist einen Blick wert!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
29. 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.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
30. @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)
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
31.
32. 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
33.
34. Grovy + Spock eignen sich für Unit,
Integration, Acceptance und UI-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"
}
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
35. Scala und Gatling für lesbare und
performante 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)
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
36.
37. Definition einer Build-Pipeline per
Jenkinsfile und Groovy
#!/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'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
38. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
39.
40. Architektur-Definition und Prüfung
mit QAvalidator für wartbaren Code.
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"
}
}
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
41.
42. Docker, Docker, Docker, ...
FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121
MAINTAINER M.-Leander Reimer <mario-leander.reimer@qaware.de>
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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
43. Cluster Orchestration mit K8s et.al.
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: everything-as-code
spec:
replicas: 2
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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
44. Einfache Provisionierung mit Ansible.
---
# 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
45. 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
46.
47. 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
48. // 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
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
49. Mit AsciidoctorJ und Gradle zum fertigen Dokument.
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', 'pdf']
options doctype: 'article'
attributes 'source-highlighter': 'coderay'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
50. 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]")
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
51. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
52.
53. 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.
---
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
57. Alles mit Augenmaß!
Der richtige Technologie-Stack hängt vom Team,
dem Projekt-Kontext und unseren Kunden ab.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
58. Fork me on GitHub.
https://github.com/lreimer/everything-as-code
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
59. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }