SlideShare a Scribd company logo
1 of 45
700 Tons of Code Later
When Your IDE Will Not Cut It You Need a Spoon
Alexander Shopov @TEQnation 2019
[ashopov@ashmac ~]$ whoami
By day: Software Engineer at Uber
By night: OSS contributor
Overall: father of 2, husband of 1
Coordinator of Bulgarian GNOME TP
Git, bash, Sentry, Jenkins speak Bulgarian
South Slavic language in Cyrillic
[ashopov@ashmac ~]$ whoami
Contacts:
E-mail: ash@kambanaria.org
LinkedIn: https://www.linkedin.com/in/alshopov
SlideShare: https://www.slideshare.net/al_shopov
GitHub: https://github.com/alshopov
Web: Just search “al_shopov”
Please Learn and Share
License: Creative Commons
Attribution 4.0 International
(CC-BY v4.0)
When We All Know How To Do Stuff
● Files
– small or few - text editor
– big or many - sed, awk, perl
● Data
– small, single table - spreadsheet
– many, interrelated, large tables - database
● Explore the data
– quick check - ad hoc interactive session
– large, long, transform and change - SQL/ETL/script job
When We Only We Think We Do
● 1 module - use editor/IDE
● 10 modules - use editor/IDE
● 100 modules - use editor/IDE
When We Only We Think We Do
● 1 module - use editor/IDE
● 10 modules - use editor/IDE
● 100 modules - use editor/IDE
Really?
● 700 modules - use what?
So What Can We Do?
● Don’t work on 700 modules
● Curse at ℙ{IDE, CPU, memory} when trying to open 700
modules
● Work, work, work
– Work in sequence - need time
– Work in parallel - need people
– Work in in sequence/parallel - need time, people and management
Is It Realistic?
● Microservices
● Growth
● Monrepos
Lather, Rinse, Repeat
● Files - put a single FS
● Data - put in a single DB
● Source - put in a single SCCS
● Eggs - put in a single basket
IDEs Work Great Until They Don't
● Text tools – inadequate
● Lexer, parser – hard
● Use good and tested solution
Spoon
Spoon At a Glance
● Site: http://spoon.gforge.inria.fr
● Development: https://github.com/INRIA/spoon
● License: MIT/CeCILL-C
● Distributed via maven, thin/fat (library/utility) versions
● Started in 2005, currently at v7.4, going to v7.5
● Developed at INRIA (Lille), part of OW2, used in academia
and industry
Two Sides of The Polyhedron
Code analysis
– Static checks
– Get metrics
– Architecture
Code generation
– Annotation
processing
– Instrumentation
– Reflection
substitute
When You Do That:
Code
Transformation
AKA Most of Programming
● Refactor
● Upgrade dependencies
● Replace dependencies
● Bug fixing
● Maintenance
● Most mundane things
Spoon’s Metamodel - AST For Java
Developers
● Based on the Java LANGUAGE
● More complicated than bytecode
● Programmers ≠ compilers, reflection
– nested classes - synthetic members
– covariant return, type erasure - bridge methods
Legion
● Structure (declarations,
roughly what can be
outside methods)
● Code (executable statements and
expressions, roughly inside
methods)
● References (names, roughly cross-
references, may
shortcut/terminate)
Everything is CtElement
● Ct = Compile Time
● Presents tree model on top of source (DOM for Java)
– children, parents, siblings
– queries
– paths
● Instances are CtVisitable-able - accept(CtVisitor) that
can visitCtSomeThing (CtSomeThing<?> thing)
The Fab Four
● Elements are created via Factory-s
● Elements are searched via Query-es
● Analyses are done via Processor-s
● Transformations are done via Template-s
Let’s Do a Realistic Example
● Many modules that have lots of unit tests (hooray!) (jUnit 4.x)
● For every one of the modules - introduce a common base class for
unit tests
● Inconsistent naming – there are TestFooBar, FooBarTest, even
Bug123BeGone – whatever people liked
● Some of the above names represent utility classes
● Some of the test classes already extend others
● There are inner classes as well
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism readClasses() {
// Command line launcher,
// others for maven,…
spoonUniverse = new Launcher();
// call it many times if needed
spoonUniverse.addInputResource(IN_DIR);
// build and wait
spoonUniverse.buildModel();
return this;
}
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism display() {
// ↓ bad
// System.out.println(spoonUniverse);
// ↓ moderately good
SpoonModelTree tree = new SpoonModelTree(
spoonUniverse.getFactory());
/* Get the same via command line:
java -jar spoon-core-…—with-dependencies.jar -g -i DIR
*/
return this;
}
package org.kambanaria.spoonerism;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class Bug123BeGone {
@Test
public void test() {
assertEquals(123, 12 * 10 + 3);
}
}
assertEquals(123, 12 * 10 + 3);
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
TypeFilter<CtClass> isClass =
new TypeFilter<CtClass>(CtClass.class);
Factory factory = spoonUniverse.getFactory();
CtTypeReference<?> juTestRef =
factory.Type().createReference("org.junit.Test");
// can also use class literal
// factory.Type().createReference(org.junit.Test.class);
TypeFilter<CtClass> isWithTestAnnotatedMethods =
new TypeFilter<CtClass>(CtClass.class) {
@Override
public boolean matches(CtClass ctClass) {
return super.matches(ctClass) &&
!ctClass
.getMethodsAnnotatedWith(juTestRef)
.isEmpty();
}
};
TypeFilter<CtClass> isRealTestingClass = new TypeFilter<CtClass>(CtClass.class) {
@Override
public boolean matches(CtClass ctClass) {
if (!super.matches(ctClass)) {
return false;
}
CtTypeReference<?> current = ctClass.getReference();
do {
if (!current.getTypeDeclaration()
.getMethodsAnnotatedWith(juTestRef).isEmpty()) {
return true;
}
} while ((current = current.getSuperclass()) != null);
return false;
}
};
testingClasses = new HashSet<>(spoonUniverse.getModel().getRootPackage()
.getElements(isRealTestingClass));
if (!super.matches(ctClass)) {
return false;
}
CtTypeReference<?> current = ctClass.getReference();
do {
if (!current.getTypeDeclaration()
.getMethodsAnnotatedWith(juTestRef).isEmpty()) {
return true;
}
} while ((current = current.getSuperclass()) !=null);
return false;
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism determineBaseTestingClassPackage(){
// What is the name of the new superclass? BaseTest
// What is the package of the new superclass?
CtClass firstClass = testingClasses.iterator().next();
String qualifiedName = firstClass.getPackage().getQualifiedName();
List<String> commonComponents = Arrays.asList(
qualifiedName.split("[.]"));
for (CtClass ctClass:testingClasses) {
List<String> currentComponents = Arrays.asList(
ctClass.getPackage().getQualifiedName().split("[.]"));
int max = Math.min(currentComponents.size(), commonComponents.size());
for (int i = 0; i < max; i++ ) {
if (!currentComponents.get(i).equals(commonComponents.get(i))) {
commonComponents = commonComponents.subList(0, i);
break;
}
}
}
baseTestingClassPackage = String.join(".", commonComponents);
return this;
}
A.B.C.D.E
A.B.F.G
A.B.H
A.B.I.J.K
A.B.L
A.B.M.N
—————————
A.B
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism createBaseTestingClass() {
String baseClassFqn =
baseTestingClassPackage + ".BaseTest";
BaseTestingClass =
spoonUniverse.getFactory().createClass(baseClassFqn);
return this;
}
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism extendTestingClasses() {
CtTypeReference<?> baseTestingClassRef =
baseTestingClass.getReference();
for (CtClass ctClass: testingClasses) {
CtTypeReference<?> superClass =
ctClass.getSuperclass();
if (ctClass.getSuperclass() == null) {
ctClass.setSuperclass(baseTestingClassRef);
}
}
return this;
}
new
Spoonerism()
.readClasses()
.display()
.enumerateTestingClasses()
.determineBaseTestingClassPackage()
.createBaseTestingClass()
.extendTestingClasses()
.writeTransformedClasses();
Spoonerism writeTransformedClasses () {
Environment env = spoonUniverse.getEnvironment();
env.setAutoImports(true);
env.setCommentEnabled(true);
spoonUniverse.setSourceOutputDirectory(OUT_DIR);
spoonUniverse.prettyprint();
return this;
}
Spoon Me Further
● 2016, Gérard Paligot, slides
● 2017, Benjamin Danglot, YouTube, slides
● 2018, Simon Urli, YouTube, slides
Fork Off
● Eclipse JDT (Java Development Tools)
● IntelliJ PSI (Program Structure Interface)
Try with Spoon first:
– It is for Java, based on Java and in Java
– Roots in academy yet targeting industry and
practitioners
Why Such Title And Names
● Peter J. Landin —
The Next 700 Programming Languages
● Bessey, et.al —
A few billion lines of code later: using
static analysis to find bugs in the real world
● Spoonerism — changing sounds between words,
“Is it kisstomary to cuss the bride?”

More Related Content

What's hot

ITT 2015 - Simon Stewart - Building Android Apps at Speed and Scale
ITT 2015 - Simon Stewart - Building Android Apps at Speed and ScaleITT 2015 - Simon Stewart - Building Android Apps at Speed and Scale
ITT 2015 - Simon Stewart - Building Android Apps at Speed and ScaleIstanbul Tech Talks
 
Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integralfukamachi
 
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)Ozh
 
Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Metosin Oy
 
Building a Testable Data Access Layer
Building a Testable Data Access LayerBuilding a Testable Data Access Layer
Building a Testable Data Access LayerTodd Anglin
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launchedMat Schaffer
 
Golang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war storyGolang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war storyAerospike
 
PostgreSQL, your NoSQL database
PostgreSQL, your NoSQL databasePostgreSQL, your NoSQL database
PostgreSQL, your NoSQL databaseReuven Lerner
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignLightbend
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Baruch Sadogursky
 
SecLists @ BlackHat Arsenal 2015
SecLists @ BlackHat Arsenal 2015SecLists @ BlackHat Arsenal 2015
SecLists @ BlackHat Arsenal 2015Daniel Miessler
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Anton Arhipov
 
The story and tech of Read the Docs
The story and tech of Read the DocsThe story and tech of Read the Docs
The story and tech of Read the Docsericholscher
 
“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.Graham Dumpleton
 
CPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolscharsbar
 
Velocity 2011 Chef OpenStack Workshop
Velocity 2011 Chef OpenStack WorkshopVelocity 2011 Chef OpenStack Workshop
Velocity 2011 Chef OpenStack WorkshopChef Software, Inc.
 

What's hot (20)

ITT 2015 - Simon Stewart - Building Android Apps at Speed and Scale
ITT 2015 - Simon Stewart - Building Android Apps at Speed and ScaleITT 2015 - Simon Stewart - Building Android Apps at Speed and Scale
ITT 2015 - Simon Stewart - Building Android Apps at Speed and Scale
 
Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integral
 
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)
WordPress Plugin Unit Tests (FR - WordCamp Paris 2015)
 
Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014
 
Building a Testable Data Access Layer
Building a Testable Data Access LayerBuilding a Testable Data Access Layer
Building a Testable Data Access Layer
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
ORMs in Golang
ORMs in GolangORMs in Golang
ORMs in Golang
 
Golang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war storyGolang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war story
 
PostgreSQL, your NoSQL database
PostgreSQL, your NoSQL databasePostgreSQL, your NoSQL database
PostgreSQL, your NoSQL database
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
SecLists @ BlackHat Arsenal 2015
SecLists @ BlackHat Arsenal 2015SecLists @ BlackHat Arsenal 2015
SecLists @ BlackHat Arsenal 2015
 
Advanced I/O in browser
Advanced I/O in browserAdvanced I/O in browser
Advanced I/O in browser
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012
 
The story and tech of Read the Docs
The story and tech of Read the DocsThe story and tech of Read the Docs
The story and tech of Read the Docs
 
“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.
 
CPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its tools
 
Velocity 2011 Chef OpenStack Workshop
Velocity 2011 Chef OpenStack WorkshopVelocity 2011 Chef OpenStack Workshop
Velocity 2011 Chef OpenStack Workshop
 

Similar to 700 Tons of Code Later

More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)Jen Wong
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Chris Weldon
 
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongJDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongPROIDEA
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHPvinaikopp
 
Practical Chaos Engineering
Practical Chaos EngineeringPractical Chaos Engineering
Practical Chaos EngineeringSIGHUP
 
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018Mike Harris
 
Powershell Training
Powershell TrainingPowershell Training
Powershell TrainingFahad Noaman
 
The Many Ways to Test Your React App
The Many Ways to Test Your React AppThe Many Ways to Test Your React App
The Many Ways to Test Your React AppAll Things Open
 
Monitoring your Python with Prometheus (Python Ireland April 2015)
Monitoring your Python with Prometheus (Python Ireland April 2015)Monitoring your Python with Prometheus (Python Ireland April 2015)
Monitoring your Python with Prometheus (Python Ireland April 2015)Brian Brazil
 
Automated Unit Testing
Automated Unit TestingAutomated Unit Testing
Automated Unit TestingMike Lively
 
Agile Data Science: Hadoop Analytics Applications
Agile Data Science: Hadoop Analytics ApplicationsAgile Data Science: Hadoop Analytics Applications
Agile Data Science: Hadoop Analytics ApplicationsRussell Jurney
 
Code transformation With Spoon
Code transformation With SpoonCode transformation With Spoon
Code transformation With SpoonGérard Paligot
 
Java script at backend nodejs
Java script at backend   nodejsJava script at backend   nodejs
Java script at backend nodejsAmit Thakkar
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShellBoulos Dib
 
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014The Hive
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
Agile Data Science: Building Hadoop Analytics Applications
Agile Data Science: Building Hadoop Analytics ApplicationsAgile Data Science: Building Hadoop Analytics Applications
Agile Data Science: Building Hadoop Analytics ApplicationsRussell Jurney
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenchesIsmail Mayat
 
Getting started-php unit
Getting started-php unitGetting started-php unit
Getting started-php unitmfrost503
 

Similar to 700 Tons of Code Later (20)

More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010
 
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go WrongJDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
JDD 2016 - Grzegorz Rozniecki - Java 8 What Could Possibly Go Wrong
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHP
 
Practical Chaos Engineering
Practical Chaos EngineeringPractical Chaos Engineering
Practical Chaos Engineering
 
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
 
Powershell Training
Powershell TrainingPowershell Training
Powershell Training
 
The Many Ways to Test Your React App
The Many Ways to Test Your React AppThe Many Ways to Test Your React App
The Many Ways to Test Your React App
 
Monitoring your Python with Prometheus (Python Ireland April 2015)
Monitoring your Python with Prometheus (Python Ireland April 2015)Monitoring your Python with Prometheus (Python Ireland April 2015)
Monitoring your Python with Prometheus (Python Ireland April 2015)
 
Automated Unit Testing
Automated Unit TestingAutomated Unit Testing
Automated Unit Testing
 
Continuous feature-development
Continuous feature-developmentContinuous feature-development
Continuous feature-development
 
Agile Data Science: Hadoop Analytics Applications
Agile Data Science: Hadoop Analytics ApplicationsAgile Data Science: Hadoop Analytics Applications
Agile Data Science: Hadoop Analytics Applications
 
Code transformation With Spoon
Code transformation With SpoonCode transformation With Spoon
Code transformation With Spoon
 
Java script at backend nodejs
Java script at backend   nodejsJava script at backend   nodejs
Java script at backend nodejs
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShell
 
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014
Agile Data Science by Russell Jurney_ The Hive_Janruary 29 2014
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Agile Data Science: Building Hadoop Analytics Applications
Agile Data Science: Building Hadoop Analytics ApplicationsAgile Data Science: Building Hadoop Analytics Applications
Agile Data Science: Building Hadoop Analytics Applications
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenches
 
Getting started-php unit
Getting started-php unitGetting started-php unit
Getting started-php unit
 

More from Alexander Shopov

Knots - the Lazy Data Transfer Objects for Dealing with the Microservices Craze
Knots - the Lazy Data Transfer Objects for Dealing with the Microservices CrazeKnots - the Lazy Data Transfer Objects for Dealing with the Microservices Craze
Knots - the Lazy Data Transfer Objects for Dealing with the Microservices CrazeAlexander Shopov
 
Нови приключения на преводачите
Нови приключения на преводачитеНови приключения на преводачите
Нови приключения на преводачитеAlexander Shopov
 
Bundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPMBundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPMAlexander Shopov
 
Beyond the Final Frontier of jQuery Selectors
Beyond the Final Frontier of jQuery SelectorsBeyond the Final Frontier of jQuery Selectors
Beyond the Final Frontier of jQuery SelectorsAlexander Shopov
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeAlexander Shopov
 
Lifting The Veil - Reading Java Bytecode During Lunchtime
Lifting The Veil - Reading Java Bytecode During LunchtimeLifting The Veil - Reading Java Bytecode During Lunchtime
Lifting The Veil - Reading Java Bytecode During LunchtimeAlexander Shopov
 
Lifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeLifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeAlexander Shopov
 

More from Alexander Shopov (10)

Knots - the Lazy Data Transfer Objects for Dealing with the Microservices Craze
Knots - the Lazy Data Transfer Objects for Dealing with the Microservices CrazeKnots - the Lazy Data Transfer Objects for Dealing with the Microservices Craze
Knots - the Lazy Data Transfer Objects for Dealing with the Microservices Craze
 
Нови приключения на преводачите
Нови приключения на преводачитеНови приключения на преводачите
Нови приключения на преводачите
 
In Vogue Dynamic
In Vogue DynamicIn Vogue Dynamic
In Vogue Dynamic
 
Bundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPMBundling Packages and Deploying Applications with RPM
Bundling Packages and Deploying Applications with RPM
 
Beyond the Final Frontier of jQuery Selectors
Beyond the Final Frontier of jQuery SelectorsBeyond the Final Frontier of jQuery Selectors
Beyond the Final Frontier of jQuery Selectors
 
Oracle's Take On NoSQL
Oracle's Take On NoSQLOracle's Take On NoSQL
Oracle's Take On NoSQL
 
I Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java BytecodeI Know Kung Fu - Juggling Java Bytecode
I Know Kung Fu - Juggling Java Bytecode
 
Lifting The Veil - Reading Java Bytecode During Lunchtime
Lifting The Veil - Reading Java Bytecode During LunchtimeLifting The Veil - Reading Java Bytecode During Lunchtime
Lifting The Veil - Reading Java Bytecode During Lunchtime
 
Caching in HTTP
Caching in HTTPCaching in HTTP
Caching in HTTP
 
Lifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java BytecodeLifting The Veil - Reading Java Bytecode
Lifting The Veil - Reading Java Bytecode
 

Recently uploaded

Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 

Recently uploaded (20)

Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 

700 Tons of Code Later