SlideShare une entreprise Scribd logo
1  sur  61
Télécharger pour lire hors ligne
Beyond Design Principles & Patterns
Writing good OO code
Matthias Noback
@matthiasnoback
Writing good OO code
Without relying on design principles and patterns
Matthias Noback
@matthiasnoback
Design patterns
● Abstract factory
● Mediator
● Proxy
● Builder
● Composite
● Chain of responsibility
● Adapter
● Strategy
● Façade
● Bridge
● Observer
● Singleton
● Factory method
● Command
Design principles, and more patterns
● Class principles (SOLID)
● Package design principles
● Tactical DDD patterns
● Testing patterns
● Architectural patterns
All this stuff!
Education
● Refer to books (but nobody reads them)
● In interviews: “Do you know SOLID?”
● Knowing is one thing, applying it is something
else.
Back to basics
Any class can serve as the blueprint of an object,
but not every object will be a Good Objecttm
Objects introduce meaning
By wrapping primitive values
Class name = Type
Strings
Email
addresses
Floats
Latitude
If not every string counts as an email address,
introduce a dedicated type: EmailAddress.
If not every integer counts as an age, introduce a
dedicated type: Age.
And so on!
Objects keep together what belongs
together
Latitude and Longitude
X and Y
Amount and Currency
Distance and Unit
...
Cohesion
What is together belongs together.
Cohesion
What belongs together, gets together.
Objects attract related data and behavior.
Objects bring together meaningful
behaviors
Coordinates.distanceTo(Coordinates other): Distance
Money.convertTo(Currency other): Money
Map.set(String key, T item): void
Map.get(String key): T
Array.push(T item): void
Array.pop(): T
Objects
State & Behavior
final class Coordinates
{
private Latitude latitude;
private Longitude longitude;
public function halfwayTo(
Coordinates other
): Coordinates {
// ...
}
}
State
Behavior
Primitive
values Entities
Value
objects
Services
Anemic
domain
objects
For all objects
Make sure they can't exist in an incoherent or
inconsistent state
At construction time
● Provide the right data (values, value objects)
● Provide the right services (collaborating objects)
// no setter injection
service = new Service();
service.setLogger(...);
// no setter party
object = new Object();
object.setFoo(...);
object.setBar(...);
At modification time
● Provide the right data (values, value objects)
What's the “right” data?
● Valid (correct types, correct number of things,
etc.)
● Meaningful (within an allowed range, pattern,
etc.)
What's the “right” data?
Only allow transitions that make sense
final class Order
{
public function cancel(...): void
{
if (wasShipped) {
throw new LogicException(...);
}
}
}
When implementing behavior: follow
this recipe
public function someMethod(int $value)
{
// check pre-conditions
Assertion::greaterThan($value, 0);
// fail early
if (...) {
throw new RuntimeException(...);
}
// happy path: at "0" indent
// check post-conditions
return ...;
}
Command/Query Separation
Every method is either
a command or a query method.
public function commandMethod(...): void
{
/*
* Changes observable state of the system
*
* May have side effects:
* - network calls
* - filesystem changes
*
* Returns nothing.
* May throw an exception.
*/
}
public function queryMethod(...): [specific type]
{
/*
* Returns something, doesn't change
* anything.
*
* May throw an exception.
*/
}
CQS principle
Asking for information doesn’t
change observable state.
Return single-type values
● Object of specific type, or an exception
● List with values of specific type, or an empty list
public function queryMethod(...): [specific type]
{
if (...) {
throw new RuntimeException(...);
}
return objectOfSpecificType;
}
public function queryMethod(...): List
{
if (...) {
return List::empty();
}
return List::of(...);
}
At failure time
Throw useful and detailed exceptions
Defensive programming
Recover from failure?
No, usually: scream about it!
Offensive programming
Add lots of sanity checks and throw exceptions.
Assert::greaterThan(...);
Assert::count(...);
...
Offensive programming
Run static analysis tools
DateTime::createFromFormat() returns bool|DateTime
Offensive programming
Introduce strictly typed alternatives to PHP's
weakly typed functions.
public static function createFromFormat(
string $format,
string $date
): DateTimeImmutable {
$result = DateTimeImmutable::createFromFormat(
$format,
$date
);
if ($result === false) {
throw new RuntimeException(...);
}
return $result;
}
State versus behavior, revisited
Objects have state and behavior
But they hide data and implementation details
State versus behavior, revisited
Expose more behavior, less state
Treat your objects as black boxes
When writing tests for them
Don't test constructors by calling
getters
Give the object a good reason to remember
something, and describe that reason in a test.
public function it_can_be_constructed(): void
{
money = new Money(1000, new Currency('EUR'));
assertEquals(
1000,
money.amount()
);
assertEquals(
'EUR',
money.currency().asString()
);
}
Getters just
for testing!
public function it_can_be_converted(): void
{
money = new Money(1000, new Currency('EUR'));
rate = new ExchangeRate(
new Currency('EUR'),
new Currency('USD'),
1.23456
);
converted = money.convert(rate);
assertEquals(
new Money(
1235, // rounded to the second digit
new Currency('USD')
)
converted
);
}
No getters!
Nor testing them!
Guiding experiment
Only add a getter if
something other than a test needs it.
final class Money
{
public function convert(ExchangeRate rate): Money
{
Assertion::true(rate.fromCurrency()
.equals(this.currency));
return new Money(
this.amount * (1 / rate.rate()),
rate.toCurrency()
);
}
}
ExchangeRate needs
to expose all its
data
final class ExchangeRate
{
public function convert(Money money): Money
{
Assertion::true(money.currency()
.equals(this.fromCurrency));
return new Money(
money.amount() * (1 / this.rate),
rate.toCurrency
);
}
} Money needs
to expose all its
dataExchangeRate
has intimate
knowledge about
creating Moneys
Changing the behavior of an object
Always aim to do it without touching the code of its class
(let it remain a black box!)
class Game
{
public function move(): void
{
steps = this.roll();
}
private function roll(): int
{
return randomInt(1, 6);
}
}
How to use a
hard-coded value
for testing?
class Game
{
public function move(): void
{
steps = this.roll();
}
protected function roll(): int
{
return randomInt(1, 6);
}
}
class GameWithFixedRoll extends Game
{
protected function roll(): int
{
return 6;
}
}
final class Game
{
private Die die;
public function __construct(Die die)
{
this.die = die;
}
public function move(): void
{
steps = this.die.roll();
}
}
interface Die
{
public function roll(): int;
}
Dependency injection!
Composition instead of
inheritance
Final classes!
final RandomDie implements Die
{
public function roll(): int
{
return randomInt(1, 6);
}
}
final FixedDie implements Die
{
public function __construct(value)
{
this.value = value;
}
public function roll(): int
{
return this.value;
}
}
Technically a test double
called “stub”
Behavior can be modified
without touching the code
“Composition over inheritance”
Changing the behavior of objects by composing
them in different ways
(as opposed to using inheritance to override
behavior)
Guiding experiment
Make all classes final
Create better objects
● Introduce more types.
● Be more strict about them.
● Design objects that only accept valid data.
● Design objects that can only be used in valid
ways.
● Use composition instead of inheritance to
change an object's behavior.
Well designed objects lead to an application that
almost clicks together
Questions?
Matthias Noback
@matthiasnoback
Feedback:
https://joind.in/talk/d0880
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO code

Contenu connexe

Tendances

C# Starter L03-Utilities
C# Starter L03-UtilitiesC# Starter L03-Utilities
C# Starter L03-Utilities
Mohammad Shaker
 
Introduction to csharp
Introduction to csharpIntroduction to csharp
Introduction to csharp
singhadarsh
 
Introduction to csharp
Introduction to csharpIntroduction to csharp
Introduction to csharp
Raga Vahini
 
Introduction to CSharp
Introduction to CSharpIntroduction to CSharp
Introduction to CSharp
Mody Farouk
 
Introduction To Csharp
Introduction To CsharpIntroduction To Csharp
Introduction To Csharp
g_hemanth17
 

Tendances (17)

Session 12 - Exception Handling - Part 1
Session 12 - Exception Handling - Part 1Session 12 - Exception Handling - Part 1
Session 12 - Exception Handling - Part 1
 
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCECONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
CONSTRUCTORS IN C++ +2 COMPUTER SCIENCE
 
INHERITANCE IN C++ +2 COMPUTER SCIENCE CBSE AND STATE SYLLABUS
INHERITANCE IN C++ +2 COMPUTER SCIENCE CBSE AND STATE SYLLABUSINHERITANCE IN C++ +2 COMPUTER SCIENCE CBSE AND STATE SYLLABUS
INHERITANCE IN C++ +2 COMPUTER SCIENCE CBSE AND STATE SYLLABUS
 
C# Starter L03-Utilities
C# Starter L03-UtilitiesC# Starter L03-Utilities
C# Starter L03-Utilities
 
Introduction to csharp
Introduction to csharpIntroduction to csharp
Introduction to csharp
 
Introduction to csharp
Introduction to csharpIntroduction to csharp
Introduction to csharp
 
Introduction to CSharp
Introduction to CSharpIntroduction to CSharp
Introduction to CSharp
 
Introduction To Csharp
Introduction To CsharpIntroduction To Csharp
Introduction To Csharp
 
Session 08 - OOP with Java - continued
Session 08 - OOP with Java - continuedSession 08 - OOP with Java - continued
Session 08 - OOP with Java - continued
 
Android Development Course in HSE lecture #2
Android Development Course in HSE lecture #2Android Development Course in HSE lecture #2
Android Development Course in HSE lecture #2
 
Developing Applications for Android - Lecture#2
Developing Applications for Android - Lecture#2Developing Applications for Android - Lecture#2
Developing Applications for Android - Lecture#2
 
Class object method constructors in java
Class object method constructors in javaClass object method constructors in java
Class object method constructors in java
 
Generic Types in Java (for ArtClub @ArtBrains Software)
Generic Types in Java (for ArtClub @ArtBrains Software)Generic Types in Java (for ArtClub @ArtBrains Software)
Generic Types in Java (for ArtClub @ArtBrains Software)
 
Session 09 - OOPS
Session 09 - OOPSSession 09 - OOPS
Session 09 - OOPS
 
The Ring programming language version 1.5.4 book - Part 37 of 185
The Ring programming language version 1.5.4 book - Part 37 of 185The Ring programming language version 1.5.4 book - Part 37 of 185
The Ring programming language version 1.5.4 book - Part 37 of 185
 
Pythia Reloaded: An Intelligent Unit Testing-Based Code Grader for Education
Pythia Reloaded: An Intelligent Unit Testing-Based Code Grader for EducationPythia Reloaded: An Intelligent Unit Testing-Based Code Grader for Education
Pythia Reloaded: An Intelligent Unit Testing-Based Code Grader for Education
 
JavaScript Data Types
JavaScript Data TypesJavaScript Data Types
JavaScript Data Types
 

Similaire à DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO code

33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
Tomek Kaczanowski
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
ShriKant Vashishtha
 
Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"
Victor_Cr
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
ShashikantSathe3
 

Similaire à DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO code (20)

Beyond Design Principles and Patterns
Beyond Design Principles and PatternsBeyond Design Principles and Patterns
Beyond Design Principles and Patterns
 
Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)
 
JDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit TestsJDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
JDD 2016 - Sebastian Malaca - You Dont Need Unit Tests
 
#pugMi - DDD - Value objects
#pugMi - DDD - Value objects#pugMi - DDD - Value objects
#pugMi - DDD - Value objects
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Unit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDDUnit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDD
 
Pragmatic unittestingwithj unit
Pragmatic unittestingwithj unitPragmatic unittestingwithj unit
Pragmatic unittestingwithj unit
 
Presentacion clean code
Presentacion clean codePresentacion clean code
Presentacion clean code
 
Iterative architecture
Iterative architectureIterative architecture
Iterative architecture
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
Writing Good Tests
Writing Good TestsWriting Good Tests
Writing Good Tests
 
Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"
 
Template Method Design Pattern
Template Method Design PatternTemplate Method Design Pattern
Template Method Design Pattern
 
SOLID Java Code
SOLID Java CodeSOLID Java Code
SOLID Java Code
 
Neo4 J
Neo4 J Neo4 J
Neo4 J
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
 

Plus de Matthias Noback

Advanced web application architecture - PHP Barcelona
Advanced web application architecture  - PHP BarcelonaAdvanced web application architecture  - PHP Barcelona
Advanced web application architecture - PHP Barcelona
Matthias Noback
 
A testing strategy for hexagonal applications
A testing strategy for hexagonal applicationsA testing strategy for hexagonal applications
A testing strategy for hexagonal applications
Matthias Noback
 

Plus de Matthias Noback (20)

Rector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetupRector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetup
 
Service abstractions - Part 1: Queries
Service abstractions - Part 1: QueriesService abstractions - Part 1: Queries
Service abstractions - Part 1: Queries
 
Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019
 
Advanced web application architecture - PHP Barcelona
Advanced web application architecture  - PHP BarcelonaAdvanced web application architecture  - PHP Barcelona
Advanced web application architecture - PHP Barcelona
 
A testing strategy for hexagonal applications
A testing strategy for hexagonal applicationsA testing strategy for hexagonal applications
A testing strategy for hexagonal applications
 
Advanced web application architecture - Talk
Advanced web application architecture - TalkAdvanced web application architecture - Talk
Advanced web application architecture - Talk
 
Layers, ports and adapters
Layers, ports and adaptersLayers, ports and adapters
Layers, ports and adapters
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
 
Advanced web application architecture Way2Web
Advanced web application architecture Way2WebAdvanced web application architecture Way2Web
Advanced web application architecture Way2Web
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
 
Building Autonomous Services
Building Autonomous ServicesBuilding Autonomous Services
Building Autonomous Services
 
Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018
 
Designing for Autonomy
Designing for AutonomyDesigning for Autonomy
Designing for Autonomy
 
Docker workshop
Docker workshopDocker workshop
Docker workshop
 
Docker swarm workshop
Docker swarm workshopDocker swarm workshop
Docker swarm workshop
 
Docker compose workshop
Docker compose workshopDocker compose workshop
Docker compose workshop
 
Building autonomous services
Building autonomous servicesBuilding autonomous services
Building autonomous services
 
Designing for autonomy
Designing for autonomyDesigning for autonomy
Designing for autonomy
 
Advanced application architecture
Advanced application architectureAdvanced application architecture
Advanced application architecture
 
Continously delivering containerized microservices
Continously delivering containerized microservicesContinously delivering containerized microservices
Continously delivering containerized microservices
 

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

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
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
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 🔝✔️✔️
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
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...
 
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
 
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
 
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
 
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
 
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
 
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
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.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
 
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
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
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
 
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
 
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
 
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
 

DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO code