Marathon Based Development
Who I Am
Boaz Berman
Developer
3.5 years in Shavit
"The future is already here- it's just not evenly distributed", William Gibson
Agenda
- Bullet One
- Bullet Two
- Bullet Three
Those methods are not a swiss knife, fit for every situation.
Those methods are an operation room, full of expensive machines.
Source Control System
Git
Dominates the market.
Fast, lightweight, has wide indestry support.
Repository, Branch, Commit
Squashing Commits
git reset --soft HEAD~3
git commit -m "New message for the combined commit"
git push --force
Merge vs Rebase
Git Workflow
Short Lived Feature Branches
Trunk Based Development
origin
local
Database Migrations
(Go) Migrate
mongodb-migrations
Never rename.
Add column, n versions later remove old column.
Clean Code
Do'nt Repeat Yourself
You Ain't Gonna Need It
SOLID
Keep It Simple Stupid
Occam's razor
-
Single Responsibility
-
Open/Closed Principle
-
Liskov Substitution
-
Interface Segregation
-
Dependency Inversion
Feature Toogles & Experiments
function reticulateSplines(){
// current implementation lives here
}
function reticulateSplines(){
var useNewAlgorithm = false;
// useNewAlgorithm = true; // UNCOMMENT IF YOU ARE WORKING
// ON THE NEW SR ALGORITHM
if( useNewAlgorithm ){
return enhancedSplineReticulation();
}else{
return oldFashionedSplineReticulation();
}
}
function oldFashionedSplineReticulation(){
// current implementation lives here
}
function enhancedSplineReticulation(){
// TODO: implement better SR algorithm
}
How do I introduce change?
Experiments
A/B Testing
Canary Release
QA In Production?
Using Feature Flags & Gradual Rollout to Testers
Stateless
Push state to the boundaries (Databases)
Server must sustain:
- No Session
- No User Info
- No Multi-phase processes
- No side-effects
Each session is carried out as if it was the first time and responses are not dependent upon data from a previous session.
Testing
End To End (E2E)
- Slowest
- Focus on making sure no major breaks
- No edge cases
- Close to business language
public class GoogleSearch {
static WebDriver driver = new FirefoxDriver();
static Wait<WebDriver> wait = new WebDriverWait(driver, MAX_30_SECONDS);
public static void main(String[] args) {
boolean result;
driver.get("http://www.google.com/");
try {
result = firstPageContainsQAANet();
} catch(Exception e) {
result = false;
} finally {
driver.close();
}
System.out.println("Test " + (result? "passed." : "failed."));
}
private static boolean firstPageContainsQAANet() {
//type search query
driver.findElement(By.name("q")).sendKeys("qa automation\n");
// click search
driver.findElement(By.name("btnG")).click();
// Wait for search to complete
wait.until(webDriver -> {
System.out.println("Searching ...");
return webDriver.findElement(By.id("resultStats")) != null;
});
// Look for QAAutomation.net in the results
return driver.findElement(By.tagName("body")).getText().contains("qaautomation.net");
}
}
Integration (Black-Box)
- Slower
- Focus on validation correctness of single service at a time
- Validate correctness, not code quality
- Boost confident while preserving test isolation and speed
@Test
public class SomeKeyGoogleService {
public SearchServiceConnection searchService;
@Before
public void init() {
// Initialize service
searchService = ...;
}
@After
public void clean() {
// Do some cleaning
}
@Describe("Given Youtube service has results and there are existing indexed pages " +
"When a phrase searched Then return Youtube with indexed results")
public void usuallyThisWillBeAMeaningfullName() {
// given
youtubeMock.when("/searchResults?search=my%20search%20phrase")
.thenReturn("{video: \"http://youtube.com/v?asd123@!ASd2134=\"}");
db.insert(new IndexedPage("Welcome to my search phrase"));
// when
var returnContent = searchService.call("/search?s=my%20search%20phrase").result().asJson();
// then
expect(returnContent).toConsistOf(youtubeVideo("http://youtube.com/v?asd123@!ASd2134="),
pageInfo("Welcome to my search phrase"));
}
}
Unit
- Fastest
- Focus on validation correctness of single [public] function at a time
- Validate mostly code quality, but also correctness as a side effect*
- Encourage clean code (SOLID, YAGNI etc..)
- Easiest to write (purpose wise)
public class AlertAdderTest
{
public SlackAlertAdder slackAlertAdder = mock(SlackAlertAdder.class);
public FacebookAlertAdder facebookAlertAdder = mock(FacebookAlertAdder.class);
public AlertAdder alertAdder = new AlertAdder(slackAlertAdder, facebookAlertAdder);
@Test
public void whatAnAlertIsAddedThenSlackAlertIsAdded()
{
Alert anAlert = new Info("Holy shit, watch out");
alertAdder.add(anAlert);
verify(slackAlertAdder).add(anAlert);
}
}
Also
Consumer Driven Contract
(PACT)
Component Testing
Mutation Testing
(PIT)
Test Driven Development
Single artifact & Environment configuration
Central Logging
Logs are the stream of aggregated, time-ordered events collected from the output streams of all running services
Produce -> Collect -> Index -> Use
Service-wise
Fluentd/ Logstash
Elasticsearch
Kibana
12Factor: Logs
Also: Correlation Ids, Schema
Kibana Example
Tracing
Using correlation Ids we can create a flow of the data:
Monitoring
Counter counter = Counter
.builder("instance")
.description("indicates instance count of the object")
.tags("dev", "performance")
.register(registry);
counter.increment(2.0);
assertTrue(counter.count() == 2);
counter.increment(-1);
assertTrue(counter.count() == 2);
SimpleMeterRegistry registry = new SimpleMeterRegistry();
Timer timer = registry.timer("app.event");
timer.record(() -> {
try {
TimeUnit.MILLISECONDS.sleep(1500);
} catch (InterruptedException ignored) { }
});
timer.record(3000, MILLISECONDS);
assertTrue(2 == timer.count());
assertTrue(4510 > timer.totalTime(MILLISECONDS)
&& 4500 <= timer.totalTime(MILLISECONDS));
Micrometer
What to monitor?
A Key Performance Indicator (KPI) is a measurable value that demonstrates how effectively a company is achieving key business objectives.
Business Metrics are used to track all areas of business.
Mean time to failure (MTTF) is the length of time a device or other product is expected to last in operation. MTTF is one of many ways to evaluate the reliability of pieces of hardware or other technology.
Mean Time to Repair (MTTR) is a measure of how long it takes to get a product or subsystem up and running after a failure.
Continues Integration, Deployment & Delivery
Continues Integration
Continues Deployment
Continues Delivery
Practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.
Designed to ensure that code can be deployed to production by delivering every change to a production-like environment and ensuring business applications and services function as expected.
Every change that passes the automated tests is deployed to production automatically.
Automation Server (Jenkins)
pipeline {
agent any
tools {
maven 'Maven 3.3.9'
jdk 'jdk8'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'mvn -Dmaven.test.failure.ignore=true install'
}
post {
success {
junit 'target/surefire-reports/**/*.xml'
}
}
}
}
}
Automation Server (CircleCI)
version: 2
jobs:
build:
docker:
- image: circleci/<language>:<version TAG>
steps:
- checkout
- run: echo "hello world"
deploy:
docker:
- image: java:8-jre-alpine
steps:
- run: java -jar my-app-*.jar
Containers & Orchestrators
A container image is a lightweight, stand-alone, executable package of a piece of software that includes everything needed to run it: code, runtime, system tools, system libraries, settings. Available for both Linux and Windows based apps, containerized software will always run the same, regardless of the environment. Containers isolate software from its surroundings, for example differences between development and staging environments and help reduce conflicts between teams running different software on the same infrastructure.
FROM alpine/git
WORKDIR /app
RUN git clone https://github.com/spring-projects/spring-petclinic.git
FROM maven:3.5-jdk-8-alpine
WORKDIR /app
COPY --from=0 /app/spring-petclinic /app
RUN mvn install
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=1 /app/target/spring-petclinic-1.5.1.jar /app
CMD ["java -jar spring-petclinic-1.5.1.jar"]
Docker
Kubernetes
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.
Microservices
An approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deploy-able by fully automated deployment machinery.
N-Tier Architecture
Microservices
Tips:
Separate database per service
Collaborate on api with consumers
Past & Future compatible api (Objects)
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.
-- Melvyn Conway, 1967
Domain Driven Design
How do I "built around business capabilities"
Is about designing software based on models of the underlying domain. A model acts as a Ubiquitous Language to help communication between software developers and domain experts. It also acts as the conceptual foundation for the design of the software itself - how it's broken down into objects or functions. To be effective, a model needs to be unified - that is to be internally consistent so that there are no contradictions within it.
Bounded Context
Value objects, which represent a value that might have sub-parts (for example, a date may have a day, month and year)
Entities, which are objects with identity. For example, each Customer object has its own identity, so we know that two customers with the same name are not the same customer
Aggregate roots are objects that own other objects. This is a complex concept and works on the basis that there are some objects that don't make sense unless they have an owner.
Ubiquitous Language
DevOps
Code - code development and review, source code management tools, code merging
Build - continuous integration tools, build status
Test - continuous testing tools that provide feedback on business risks
Package - artifact repository, application pre-deployment staging
Release - change management, release approvals, release automation
Configure - infrastructure configuration and management, Infrastructure as Code tools
Monitor - applications performance monitoring, end–user experience
DevOps aims at shorter development cycles, increased deployment frequency, more dependable releases, in close alignment with business objectives.
Lean Development
shifted the focus from individual machines and their utilization, to the flow of the product through the total process. Toyota concluded that by right-sizing machines for the actual volume needed, introducing self-monitoring machines to ensure quality, lining the machines up in process sequence, pioneering quick setups so each machine could make small volumes of many part numbers, and having each process step notify the previous step of its current needs for materials, it would be possible to obtain low cost, high variety, high quality, and very rapid throughput times to respond to changing customer desires.
Lean Principles
Eliminate Waste
Unnecessary code or functionality
Starting more than can be completed
Delay in the software development process: Delays time to customer, slows down feedback loops
Unclear or constantly changing requirements
Bureaucracy
Slow or ineffective communication
Partially done work
Defects and quality issues
Task switching
Build Quality In
Pair programming: Avoid quality issues by combining the skills and experience of two developers instead of one
Test-driven development: Writing criteria for code before writing the code to ensure it meets business requirements
Incremental development and constant feedback
Minimize wait states: Reduce context switching, knowledge gaps, and lack of focus
Automation: Automate any tedious, manual process or any process prone to human error
Create Knowledge
Pair Programming
Code reviews
Documentation
Wiki – to let the knowledge base build up incrementally
Thoroughly commented code
Knowledge sharing sessions
Training
Use tools to manage requirements or user stories
Defer Commitment
This Lean principle encourages team to demonstrate responsibility by keeping their options open and continuously collecting information, rather than making decisions without the necessary data.
Deliver Fast
Build a simple solution, put it in front of customers, enhance incrementally based on customer feedback.
Common culprits
- Thinking too far in advance about future requirements
- Blockers that aren’t responded to with urgency
- Over-engineering solutions and business requirements
Respect People
Optimize the Whole
"If you don't have the time to do it right, when will you have time to do it again?", John Wooden
Resources
- Clean Code, Robert C. Martin
- Growing Object Oriented Software, guided by tests- Steve Freeman & Nat Pryce
- The Twelve Factor App- https://12factor.net/
- Domain Driven Design- Eric Evans
- Building Microservices- Sam Newman
- The Pheonix Project- Gene Kim, Kevin Behr, George Spafford
- Continues Delivery- Jez Humble & David Farley
- Medium- https://medium.com/
- StackShare.io- https://stackshare.io/
- Newsletters- SWLW, Alligator.io, DevOpsLinks
Marathon Based Development
By Boaz Berman
Marathon Based Development
- 394