SlideShare une entreprise Scribd logo
1  sur  72
Télécharger pour lire hors ligne
SOLIDMARTIJN DASHORST
topicus
AGENDA
INTRODUCTIE
SOLID
CONCLUSIE & DISCUSSIE
INTRO
Acroniemen
TCP
IP XP
SOLID
JAVA EE
JSP JPA
SOAP
SMTP
SNMP
OSI
HTTP
HATEOAS
POM
PINO
JAREAR
EJB
C#
JAX-B JAX-P
JAX-WS
JAX-RS
SAAJ
k8sl10n
i18n
GRASPKISS
STAVAZA
MOSCOW
YAGNI
SOLID
Robert C. Martin
"Uncle Bob"
SOLID
Robert C. Martin Copyright (c) 2000 by Robert C. Martin. All Rights Reserved.
www.objectmentor.com
1
Design Principles and
Design Patterns
Robert C. Martinwww.objectmentor.com
What is software architecture? The answer is multitiered. At the highest level, there
are the architecture patterns that define the overall shape and structure of software
applications1
. Down a level is the architecture that is specifically related to the pur-
pose of the software application. Yet another level down resides the architecture of
the modules and their interconnections. This is the domain of design patterns2
, pack-
akges, components, and classes. It is this level that we will concern ourselves with in
this chapter.
Our scope in this chapter is quite limitted. There is much more to be said about the
principles and patterns that are exposed here. Interested readers are referred to
[Martin99].
Architecture and DependenciesWhat goes wrong with software? The design of many software applications begins as
a vital image in the minds of its designers. At this stage it is clean, elegant, and com-
pelling. It has a simple beauty that makes the designers and implementers itch to see it
working. Some of these applications manage to maintain this purity of design through
the initial development and into the first release.But then something begins to happen. The software starts to rot. At first it isn’t so
bad. An ugly wart here, a clumsy hack there, but the beauty of the design still shows
through. Yet, over time as the rotting continues, the ugly festering sores and boils
accumulate until they dominate the design of the application. The program becomes a
festering mass of code that the developers find increasingly hard to maintain. Eventu-1. [Shaw96]
2. [GOF96]
SOLID
Single Responsibility Principle

Open Closed Principle

Lishkov Substitution Principle


Interface Segregation Principle

Dependency Inversion Principle
SOLID
SOLID
A class should only have a single
responsibility, that is, only changes to one
part of the software's specification should
be able to affect the specification of the
class.
wikipedia.org
Één verantwoordelijkheid per klasse: 

één reden om te wijzigen.
public static void main(String[] args) {
    Person user = new Person();
    user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
    user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    Person user = new Person();
    user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
    user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    Person user = new Person();
    user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
    user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    Person user = new Person();
    user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
    user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    Person user = new Person();
    user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
    user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public class PersonDataCapture {
    public Person getUserData() {
        Person user = new Person();
        user.setVoornaam(System.console().readLine("Wat is je voornaam? "));
        user.setAchternaam(System.console().readLine("Wat is je achternaam? "));
        return user;
    }
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
        console().printf("Je hebt geen geldige voornaam opgegeven");
        return;
    }
    if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
        console().printf("Je hebt geen geldige achternaam opgegeven");
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public class PersonValidator {
    public boolean isValidUser(Person user) {
        if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {
            console().printf("Je hebt geen geldige voornaam opgegeven");
            return false;
        }
        if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {
            console().printf("Je hebt geen geldige achternaam opgegeven");
            return false;
        }
        return true;
    }
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    PersonValidator validator = new PersonValidator();
    if (!validator.isValidUser(user)) {
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    PersonValidator validator = new PersonValidator();
    if (!validator.isValidUser(user)) {
        return;
    }
    console().printf("Je accountnaam is: %snn",
            user.getVoornaam().substring(0, 1) + user.getAchternaam());
}
public class AccountGenerator {
    public String generateAccountFor(Person user) {
        return user.getVoornaam().substring(0, 1) + user.getAchternaam();
    }
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    PersonValidator validator = new PersonValidator();
    if (!validator.isValidUser(user)) {
        return;
    }
    AccountGenerator generator = new AccountGenerator();
    String accountnaam = generator.generateAccountFor(user);
    System.console().printf("Je accountnaam is: %snn", accountnaam);
}
public static void main(String[] args) {
    PersonDataCapture input = new PersonDataCapture();
    Person user = input.getUserData();
    PersonValidator validator = new PersonValidator();
    if (!validator.isValidUser(user)) {
        return;
    }
    AccountGenerator generator = new AccountGenerator();
    String accountnaam = generator.generateAccountFor(user);
    System.console().printf("Je accountnaam is: %snn", 

        accountnaam);
}
public class AccountGenerator {
    public String generateAccountFor(Person user) {
        return user.getVoornaam().substring(0, 1) + user.getA
    }
}
public class PersonValidator {
    public boolean isValidUser(Person user) {
        if (user.getVoornaam() == null || user.getVoornaam().isBlan
            console().printf("Je hebt geen geldige voornaam opgegev
            return false;
        }
        if (user.getAchternaam() == null || user.getAchternaam().is
            console().printf("Je hebt geen geldige achternaam opgeg
            return false;
        }
        return true;
    }
}
public class PersonDataCapture {
    public Person getUserData() {
        Person user = new Person();
        user.setVoornaam(console().readLine("Wat is je voorna
        user.setAchternaam(console().readLine("Wat is je acht
        return user;
    }
}
SOLID
open for extension
closed for modification
class Rectangle {
    int width;
    int height;
}
class AreaCalculator {
    public double area(Rectangle... rectangles) {
        double area = 0;
        for (var r : rectangles) {
            area += r.height * r.width;
        }
        return area;
    }
}
Rectangle r1 = new Rectangle();
r1.width = 2;
r1.height = 3;
var calc = new AreaCalculator();
System.out.println(calc.area(r1));
class Rectangle {
    int width;
    int height;
}
class Circle {
    int radius;
}
class AreaCalculator {
    public double area(Object... shapes) {
        double area = 0;
        for (var s : shapes) {
            if (s instanceof Rectangle) {
                var r = (Rectangle) s;
                area += r.height * r.width;
            } else if (s instanceof Circle) {
                var c = (Circle) s;
                area += c.radius * c.radius * Math.PI;
            }
        }
        return area;
    }
}
var rect = new Rectangle();
rect.width = 2;
rect.height = 3;
var circle = new Circle();
circle.radius = 2;
System.out.println(new AreaCalculator().area(rect, circle));
abstract class Shape {
    public abstract double area();
}
class Rectangle extends Shape {
    int height, width;
    public double area() {
        return width * height;
    }
}
class Circle extends Shape {
    int radius;
    public double area() {
        return radius * radius * Math.PI;
    }
}
class AreaCalculator {
    public double area(Shape... shapes) {
        double area = 0;
        for (var s : shapes) {
            area += s.area();
        }
        return area;
    }
}
SOLID
...in a computer program, if S is a
subtype of T, then objects of type T
may be replaced with objects of
type S without altering any of the
desirable properties of the program
(correctness, task performed, etc.)
wikipedia.org
Liskov substitution principle
Objecten moeten zich netjes
gedragen...
TLDR; principe
Waar een A verwacht
wordt, moet een B zich
gelijksoortig gedragen B
A
interface Sender {
    void send(String s);
}
class SmtpSender implements Sender {
    @Override
    public void send(String s) {
    }
}
class FtpSender implements Sender {
    @Override
    public void send(String s) {
    }
}
interface Sender {
    void send(String s);
}
class SmtpSender implements Sender {
    @Override
    public void send(String s) {
        if (s.startsWith("banaan"))
            throw new IllegalStateException();
    }
}
class FtpSender implements Sender {
    @Override
    public void send(String s) {
    }
}
interface Sender {
    void send(String s);
}
class SmtpSender implements Sender {
    @Override
    public boolean send(String s) {
    }
}
class FtpSender implements Sender {
    @Override
    public void send(Integer s) {
    }
}
class Filer {
    public boolean file(String x) throws FileAlreadyExistsException {
        return false;
    }
}
class Filer {
    public boolean file(String x) throws FileAlreadyExistsException {
        return false;
    }
}
class NetworkFiler extends Filer {
    public boolean file(String x)
            throws FileAlreadyExistsException, SocketException {
        return false;
    }
}
class Rectangle {
    private int width, height;
    public void setHeight(int h) {}
    public void setWidth(int w) {}
    public int getHeight() {}
    public int getWidth() {}
}
static void fillRect(Rectangle r) {
    r.setHeight(50);
    r.setWidth(150);
    assert (r.getHeight() == 50);
    assert (r.getWidth() == 150);
}
Rectangle r = new Rectangle();
fillRect(r);
class Rectangle {
    private int width, height;
    public void setHeight(int h) {}
    public void setWidth(int w) {}
    public int getHeight() {}
    public int getWidth() {}
}
class Square extends Rectangle {
    public void setHeight(int h) {
        super.setHeight(h);
        super.setWidth(h);
    }
    public void setWidth(int w) {
        super.setWidth(w);
        super.setHeight(w);
    }
}

static void fillRect(Rectangle r) {
    r.setHeight(50);
    r.setWidth(150);
    assert (r.getHeight() == 50);
    assert (r.getWidth() == 150);
}
Square s = new Square();
s.setHeight(100);
fillRect(s);
SOLID
No client should be forced to depend on
methods it does not use
wikipedia.org
Interface Segregation Principle
interface Shape {
    public double getArea();
    boolean isCongruentWith(Shape other);
    void draw();
}
interface Shape {
    public double getArea();
    boolean isCongruentWith(Shape other);
    void draw();
}
class Rectangle implements Shape {
    private int width, height;
    public double getArea() {
        return width * height;
    }
    boolean isCongruentWith(Shape othe
    public void draw() {}
}
interface Shape {
    public double getArea();
    boolean isCongruentWith(Shape other);
    void draw();
}
class Rectangle implements Shape {
    private int width, height;
    public double getArea() {
        return width * height;
    }
    boolean isCongruentWith(Shape othe
    public void draw() {}
}
class Circle implements Shape {
    private int radius;
    public double getArea() {
        return radius * radius * Math.PI;
    }
    boolean isCongruentWith(Shape other)
   public void draw() {}
}
interface Shape {
    public double getArea();
    boolean isCongruentWith(Shape other);
    void draw();
}
class Rectangle implements Shape {
    private int width, height;
    public double getArea() {
        return width * height;
    }
    boolean isCongruentWith(Shape othe
    public void draw() {}
}
class Circle implements Shape {
    private int radius;
    public double getArea() {
        return radius * radius * Math.PI;
    }
    boolean isCongruentWith(Shape other)
   public void draw() {}
}
class Point implements Shape {
    private int x, y;
    public void draw() {}
    boolean isCongruentWith(Shape other)
}
interface Drawable {
    void draw();
}
interface Shape {
    boolean congruentWith(Shape other);
}
interface Area extends Shape {
    double area();
}
interface Drawable {
    void draw();
}
interface Shape {
    boolean isCongruentWith(Shape other);
}
interface Area extends Shape {
    double area();
}
class Rectangle implements Drawable,
Area, Shape {
    private int height, width;
    public void draw() {
}
    public boolean isCongruentWith(Shape
}
    public double area() {
}
}

interface Drawable {
    void draw();
}
interface Shape {
    boolean isCongruentWith(Shape other);
}
interface Area extends Shape {
    double area();
}
class Circle implements Drawable,
Area, Shape {
    private int radius;
    public void draw() {
}
    public boolean congruentWith(Shape ot
}
    public double area() {
}
}
interface Drawable {
    void draw();
}
interface Shape {
    boolean isCongruentWith(Shape other);
}
interface Area extends Shape {
    double area();
}
class Point implements Drawable, Shape {
    private int x, y;
    public void draw() {
}
    public boolean congruentWith(Shape ot
}
}
• Java Collections
• Java IO streams
SOLID
Depend upon abstractions, 

not concretions
Dependency Inversion Principle
1. High-level modules should not depend
on low-level modules. Both should
depend on abstractions.
2. Abstractions should not depend on
details. Details should depend on
abstractions.
1. High-level modules should not depend
on low-level modules. Both should
depend on abstractions.
2. Abstractions should not depend on
details. Details should depend on
abstractions.
LeerlingDAO RapportService
LeerlingDAOImpl RapportService
LeerlingDAO
Wanneer je het Open/Closed Principle
toepast, volgt "automatisch" 

Dependency Inversion
iemand op internet
CONC

LUSIE
SOLID
Single Responsibility Principle

Open Closed Principle

Lishkov Substitution Principle
Interface Segregation Principle

Dependency Inversion Principle
SOLID
Single Responsibility Principle

Open Closed Principle

Lishkov Substitution Principle
Interface Segregation Principle

Dependency Inversion Principle
GRASP
General
Responsibility
Assignment
Software
Patterns
SOLID GRASP
Het *wat* Het *hoe* en waarom
Refactoring
Code Ownership
Continuous Delivery
SOLID
DRY
YAGNI
GRASP
PATTERNS
REFACTORING
Meer lezen/zien?
• GRASP

(wikipedia)
• Refactoring (2nd Edition) 

Martin Fowler (boek)
• Clean Code

Robert C. Martin (boek)
• Readable code - and the long
lost secret of how to achieve it

Christin Gorman (video, 10min)
Discussie

Contenu connexe

Similaire à SOLID principles

Secrets of going codeless - How to build enterprise apps without coding
Secrets of going codeless - How to build enterprise apps without codingSecrets of going codeless - How to build enterprise apps without coding
Secrets of going codeless - How to build enterprise apps without coding
Newton Day Uploads
 
"Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
 "Up-Down Development & DSL-first approach", Владимир Мельник, DataArt "Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
"Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
DataArt
 
Software Development in 21st Century
Software Development in 21st CenturySoftware Development in 21st Century
Software Development in 21st Century
Henry Jacob
 

Similaire à SOLID principles (20)

What Web Framework To Use?
What Web Framework To Use?What Web Framework To Use?
What Web Framework To Use?
 
Solid design principles
Solid design principlesSolid design principles
Solid design principles
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Secrets of going codeless - How to build enterprise apps without coding
Secrets of going codeless - How to build enterprise apps without codingSecrets of going codeless - How to build enterprise apps without coding
Secrets of going codeless - How to build enterprise apps without coding
 
Micro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJS
Micro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJSMicro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJS
Micro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJS
 
An overview of the architecture of electron.js
An overview of the architecture of electron.jsAn overview of the architecture of electron.js
An overview of the architecture of electron.js
 
The dependency inversion principle
The dependency inversion principleThe dependency inversion principle
The dependency inversion principle
 
Are You a SOLID Coder?
Are You a SOLID Coder?Are You a SOLID Coder?
Are You a SOLID Coder?
 
"Micro-frontends: Scalable and Modular Frontend in Parimatch Tech", Kyrylo Ai...
"Micro-frontends: Scalable and Modular Frontend in Parimatch Tech", Kyrylo Ai..."Micro-frontends: Scalable and Modular Frontend in Parimatch Tech", Kyrylo Ai...
"Micro-frontends: Scalable and Modular Frontend in Parimatch Tech", Kyrylo Ai...
 
Elements of Java Language
Elements of Java Language Elements of Java Language
Elements of Java Language
 
Software Architecture Erosion and Modernization
Software Architecture Erosion and ModernizationSoftware Architecture Erosion and Modernization
Software Architecture Erosion and Modernization
 
"Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
 "Up-Down Development & DSL-first approach", Владимир Мельник, DataArt "Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
"Up-Down Development & DSL-first approach", Владимир Мельник, DataArt
 
bGenius kennissessie_20120510
bGenius kennissessie_20120510bGenius kennissessie_20120510
bGenius kennissessie_20120510
 
Professional practises craftsmanship trainings - part 2
Professional practises   craftsmanship trainings - part 2Professional practises   craftsmanship trainings - part 2
Professional practises craftsmanship trainings - part 2
 
Lecture1422914635
Lecture1422914635Lecture1422914635
Lecture1422914635
 
Software Development in 21st Century
Software Development in 21st CenturySoftware Development in 21st Century
Software Development in 21st Century
 
7 Redux challenges
7 Redux challenges7 Redux challenges
7 Redux challenges
 
ABSE and AtomWeaver : A Quantum Leap in Software Development
ABSE and AtomWeaver : A Quantum Leap in Software DevelopmentABSE and AtomWeaver : A Quantum Leap in Software Development
ABSE and AtomWeaver : A Quantum Leap in Software Development
 
FRONTEND DEVELOPMENT WITH REACT.JS
FRONTEND DEVELOPMENT WITH REACT.JSFRONTEND DEVELOPMENT WITH REACT.JS
FRONTEND DEVELOPMENT WITH REACT.JS
 
SE2_Lec 19_Design Principles and Design Patterns
SE2_Lec 19_Design Principles and Design PatternsSE2_Lec 19_Design Principles and Design Patterns
SE2_Lec 19_Design Principles and Design Patterns
 

Plus de Martijn Dashorst

Keep your Wicket application in production
Keep your Wicket application in productionKeep your Wicket application in production
Keep your Wicket application in production
Martijn Dashorst
 

Plus de Martijn Dashorst (20)

HTMX: Web 1.0 with the benefits of Web 2.0 without the grift of Web 3.0
HTMX: Web 1.0 with the benefits of Web 2.0 without the grift of Web 3.0HTMX: Web 1.0 with the benefits of Web 2.0 without the grift of Web 3.0
HTMX: Web 1.0 with the benefits of Web 2.0 without the grift of Web 3.0
 
From Floppy Disks to Cloud Deployments
From Floppy Disks to Cloud DeploymentsFrom Floppy Disks to Cloud Deployments
From Floppy Disks to Cloud Deployments
 
Converting 85% of Dutch Primary Schools from Oracle to PostgreSQL
Converting 85% of Dutch Primary Schools from Oracle to PostgreSQLConverting 85% of Dutch Primary Schools from Oracle to PostgreSQL
Converting 85% of Dutch Primary Schools from Oracle to PostgreSQL
 
Solutions for when documentation fails
Solutions for when documentation fails Solutions for when documentation fails
Solutions for when documentation fails
 
Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8
 
Code review drinking game
Code review drinking gameCode review drinking game
Code review drinking game
 
Java Serialization Deep Dive
Java Serialization Deep DiveJava Serialization Deep Dive
Java Serialization Deep Dive
 
Code review drinking game
Code review drinking gameCode review drinking game
Code review drinking game
 
Scrum: van praktijk naar onderwijs
Scrum: van praktijk naar onderwijsScrum: van praktijk naar onderwijs
Scrum: van praktijk naar onderwijs
 
Who Automates the Automators? (Quis Automatiet Ipsos Automates?)
Who Automates the Automators? (Quis Automatiet Ipsos Automates?)Who Automates the Automators? (Quis Automatiet Ipsos Automates?)
Who Automates the Automators? (Quis Automatiet Ipsos Automates?)
 
De schone coder
De schone coderDe schone coder
De schone coder
 
Wicket 10 years and beyond
Wicket   10 years and beyond Wicket   10 years and beyond
Wicket 10 years and beyond
 
Apache Wicket and Java EE sitting in a tree
Apache Wicket and Java EE sitting in a treeApache Wicket and Java EE sitting in a tree
Apache Wicket and Java EE sitting in a tree
 
The State of Wicket
The State of WicketThe State of Wicket
The State of Wicket
 
Wicket 2010
Wicket 2010Wicket 2010
Wicket 2010
 
Vakmanschap is meesterschap
Vakmanschap is meesterschapVakmanschap is meesterschap
Vakmanschap is meesterschap
 
Keep your Wicket application in production
Keep your Wicket application in productionKeep your Wicket application in production
Keep your Wicket application in production
 
Wicket In Action - oredev2008
Wicket In Action - oredev2008Wicket In Action - oredev2008
Wicket In Action - oredev2008
 
Guide To Successful Graduation at Apache
Guide To Successful Graduation at ApacheGuide To Successful Graduation at Apache
Guide To Successful Graduation at Apache
 
Wicket In Action
Wicket In ActionWicket In Action
Wicket In Action
 

Dernier

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
VictorSzoltysek
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
+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
 

Dernier (20)

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
 
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
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
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 🔝✔️✔️
 
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
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
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
 
+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...
 
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
 
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 🔝✔️✔️
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
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
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
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
 
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
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 

SOLID principles