SlideShare une entreprise Scribd logo
1  sur  77
Télécharger pour lire hors ligne
MMaakkee iitt 
SSOOLLIIDD!! 
LLuuííss OOttáávviioo CCoobbuuccccii OObblloonncczzyykk 
@@llccoobbuuccccii
LLuuííss OOttáávviioo 
CCoobbuuccccii OObblloonncczzyykk 
@@llccoobbuuccccii
PPrriinnccííppiiooss 
ee vvaalloorreess
“Working software is the primary 
measure of progress.” 
PPrriinnccííppiiooss 
ee vvaalloorreess
“Welcome changing requirements, 
even late in development.” 
PPrriinnccííppiiooss 
ee vvaalloorreess
“Continuous attention to technical excellence 
and good design enhances agility.” 
PPrriinnccííppiiooss 
ee vvaalloorreess
NNoossssaass 
rreessppoonnssaabbiilliiddaaddeess??
NNoossssaass 
Traduzir desejos 
rreessppoonnssaabbiilliiddaaddeess??
NNoossssaass 
Traduzir desejos 
Escolher linguagem 
rreessppoonnssaabbiilliiddaaddeess??
Traduzir desejos 
Escolher linguagem Libs/frameworks 
NNoossssaass 
rreessppoonnssaabbiilliiddaaddeess??
Libs/frameworks 
NNoossssaass 
Traduzir desejos 
Escolher linguagem 
Definir arquitetura 
rreessppoonnssaabbiilliiddaaddeess??
Garantir qualidade 
Libs/frameworks 
NNoossssaass 
Traduzir desejos 
Escolher linguagem 
Definir arquitetura 
rreessppoonnssaabbiilliiddaaddeess??
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé??
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
Precisamos criar um 
Usuário com nome e idade
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
class UserCreator 
{ 
public function create($name, $age) { /*... */ } 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
public function __construct() { 
$this->conn = new PDO( 
'mysql:host=127.0.0.1;dbname=awesome', 
'root', 
'ImAGenius' 
); 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
public function create($name, $age) { 
$stm = $this->conn->prepare('...'); 
$stm->execute([$name, $age]); 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
Agora, temos que logar no 
arquivo /tmp/users.log, adicionando 
o responsável pelo cadastro
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
class UserCreator 
{ 
public function create($name, $age, $responsible) { /*... */ } 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
public function __construct() { 
// (…) 
$this->logger = new FileLogger(); 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
public function create($name, $age, $responsible) { 
$stm = $this->conn->prepare('...'); 
$stm->execute([$name, $age]); 
$this->logger->log(/* … */); 
}
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
Meu, num dá pra imprimir 
o último usuário criado?
CCooiissaass qquuee nnuunnccaa 
ooccoorrrreemm...... nnéé?? 
class UserCreator 
{ 
public function create($name, $age, $responsible) { /*... */ } 
public function print() { /* … */ } 
}
RReessuullttaaddoo
RReessuullttaaddoo 
Será que “APENAS 
funcionar” é suficiente?
RReessuullttaaddoo 
((rreeaall))
BBaadd ssmmeellllss
BBaadd ssmmeellllss 
Rigidez
BBaadd ssmmeellllss 
Rigidez 
Fragilidade
BBaadd ssmmeellllss 
Rigidez 
Fragilidade 
Imobilidade
BBaadd ssmmeellllss 
Rigidez 
Fragilidade 
Imobilidade 
Complexidade 
desnecessária
PPrriinncciipplleess ooff OOOODD
PPrriinncciipplleess ooff OOOODD 
Class design
PPrriinncciipplleess ooff OOOODD 
Class design 
Package cohesion
PPrriinncciipplleess ooff OOOODD 
Class design 
Package cohesion 
Package coupling
PPrriinncciipplleess ooff OOOODD 
Class design 
Package cohesion 
Package coupling 
SS..OO..LL..II..DD..
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
SSiinnggllee RReessppoonnssiibbiilliittyy 
One does not simply 
have more than a reason 
to modify a class...
SSiinnggllee RReessppoonnssiibbiilliittyy 
A class should have one, 
and only one, reason 
to change.
SSiinnggllee RReessppoonnssiibbiilliittyy 
class UserRepository 
{}
SSiinnggllee RReessppoonnssiibbiilliittyy 
class UserRepository 
{ 
public function findByAge($age) { /* … */ } 
public function findByName($name) { /* … */ } 
}
SSiinnggllee RReessppoonnssiibbiilliittyy 
class UserRepository 
{ 
public function findByAge($age) { /* … */ } 
public function findByName($name) { /* … */ } 
public function pdfReport() { /* … */ } 
}
SSiinnggllee RReessppoonnssiibbiilliittyy 
class UserRepository 
{ 
public function findByAge($age) { /* … */ } 
public function findByName($name) { /* … */ } 
} 
class UserReport 
{ 
public function generate() { /* … */ } 
}
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
OOppeenn//cclloosseedd 
Should be able to extend 
behaviors, without modifying 
the class
OOppeenn//cclloosseedd 
class Authenticator 
{}
OOppeenn//cclloosseedd 
class Authenticator 
{ 
public function authenticate($login, $passwd) { /* … */ } 
}
OOppeenn//cclloosseedd 
class Authenticator 
{ 
public function authenticate($login, $passwd) { /* … */ } 
private function findUser($login) { /* finds on DB */ } 
private function matchPasswd(User $user, $passwd) { /* … */ } 
}
OOppeenn//cclloosseedd 
class Authenticator 
{ 
public function authenticate($login, $passwd) { /* … */ } 
private function findUser($login) { /* finds on DB */ } 
private function matchPasswd(User $user, $passwd) { /* … */ } 
} 
E se precisarmos buscar 
em outro lugar?
OOppeenn//cclloosseedd 
class Authenticator 
{ 
public function authenticate($login, $passwd) { /* … */ } 
protected function findUser($login) { /* finds on DB */ } 
private function matchPasswd(User $user, $passwd) { /* … */ } 
} 
Assim podemos sobrescrever 
o método de busca...
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
LLiisskkoovv ssuubbssttiittuuttiioonn 
Derived classes must be 
substitutable for their base 
classes
LLiisskkoovv ssuubbssttiittuuttiioonn 
class Rectangle 
{ 
public function setX($x) { /* … */ } 
public function setY($y) { /* … */ } 
public function getArea() { /* … */ } 
}
LLiisskkoovv ssuubbssttiittuuttiioonn 
function getArea($x, $y, Rectangle $object) 
{ 
$object->setX($x); 
$object->setY($y); 
return $object->getArea(); 
} 
getArea(5, 10, new Rectangle());
LLiisskkoovv ssuubbssttiittuuttiioonn 
class Square extends Rectangle 
{ 
public function setX($x) { /* also setY() */ } 
public function setY($y) { /* also setX() */ } 
}
LLiisskkoovv ssuubbssttiittuuttiioonn 
function getArea($x, $y, Rectangle $object) 
{ 
$object->setX($x); 
$object->setY($y); 
return $object->getArea(); 
} 
getArea(5, 10, new Square());
LLiisskkoovv ssuubbssttiittuuttiioonn 
Contravariance of method arguments in subtypes 
Covariance of return types in subtypes
LLiisskkoovv ssuubbssttiittuuttiioonn 
Contravariance of method arguments in subtypes 
Covariance of return types in subtypes 
Preconditions cannot be strengthened in subtypes 
Postconditions cannot be weakened in subtypes
LLiisskkoovv ssuubbssttiittuuttiioonn 
Contravariance of method arguments in subtypes 
Covariance of return types in subtypes 
Preconditions cannot be strengthened in subtypes 
Postconditions cannot be weakened in subtypes 
No new exceptions! Don't violate history constraint
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
IInntteerrffaaccee sseeggrreeggaattiioonn 
Make fine grained interfaces 
that are client specific
IInntteerrffaaccee sseeggrreeggaattiioonn 
interface UserManager 
{}
IInntteerrffaaccee sseeggrreeggaattiioonn 
interface UserManager 
{ 
public function create($name, $email); 
public function remove($id); 
public function find($id); 
public function findByName($name); 
}
IInntteerrffaaccee sseeggrreeggaattiioonn 
class UserController 
{ 
public function find($id) { /* … */ } 
/** @return UserManager */ 
public function getManager(); 
}
IInntteerrffaaccee sseeggrreeggaattiioonn 
interface UserManager 
{ 
public function create($name, $email); 
public function remove($id); 
} 
interface UserLocator 
{ 
public function find($id); 
public function findByName($name); 
}
SS..OO..LL..II..DD.. pprriinncciipplleess 
Single Responsibility principle 
Open/Closed principle 
Liskov substitution principle 
Interface segregation principle 
Dependency inversion principle
DDeeppeennddeennccyy IInnvveerrssiioonn 
Depend on abstractions, 
not on concretions
DDeeppeennddeennccyy IInnvveerrssiioonn 
public function __construct( 
DatabasePersister $persister, 
FileNotifier $notifier 
) { 
$this->persister = $persister; 
$this->notifier = $notifier; 
}
DDeeppeennddeennccyy IInnvveerrssiioonn 
public function __construct(Persister $persister, Notifier $notifier) 
{ 
$this->persister = $persister; 
$this->notifier = $notifier; 
}
SSOOLLIIDD pprriinncciipplleess
SSOOLLIIDD pprriinncciipplleess 
Classes mais coesas
SSOOLLIIDD pprriinncciipplleess 
Classes mais coesas 
Menos acoplamento
SSOOLLIIDD pprriinncciipplleess 
Classes mais coesas 
Menos acoplamento 
Menos mudanças 
em código estável
SSOOLLIIDD pprriinncciipplleess 
Classes mais coesas 
Menos acoplamento 
Menos mudanças 
em código estável 
Testes mais fáceis
DDúúvviiddaass??
OObbrriiggaaddoo!! 
@@llccoobbuuccccii

Contenu connexe

Tendances

Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
Phpで作るmovable typeプラグイン
Phpで作るmovable typeプラグインPhpで作るmovable typeプラグイン
Phpで作るmovable typeプラグイン
Yuji Takayama
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Acquia
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
Rebecca Murphey
 

Tendances (20)

Jquery plugin development
Jquery plugin developmentJquery plugin development
Jquery plugin development
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
jQuery UI Widgets, Drag and Drop, Drupal 7 JavascriptjQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
NodeJS The edge of Reason - Lille fp#6
NodeJS The edge of Reason - Lille fp#6NodeJS The edge of Reason - Lille fp#6
NodeJS The edge of Reason - Lille fp#6
 
ES6 at PayPal
ES6 at PayPalES6 at PayPal
ES6 at PayPal
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
PhoneGap: Local Storage
PhoneGap: Local StoragePhoneGap: Local Storage
PhoneGap: Local Storage
 
BVJS
BVJSBVJS
BVJS
 
Phpで作るmovable typeプラグイン
Phpで作るmovable typeプラグインPhpで作るmovable typeプラグイン
Phpで作るmovable typeプラグイン
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1Drupal Step-by-Step: How We Built Our Training Site, Part 1
Drupal Step-by-Step: How We Built Our Training Site, Part 1
 
Sins Against Drupal 2
Sins Against Drupal 2Sins Against Drupal 2
Sins Against Drupal 2
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
 
Real Time App with Node.js
Real Time App with Node.jsReal Time App with Node.js
Real Time App with Node.js
 
Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.
 
TDC 2014 - JavaScript de qualidade: hoje, amanhã e sempre!
TDC 2014 - JavaScript de qualidade: hoje, amanhã e sempre!TDC 2014 - JavaScript de qualidade: hoje, amanhã e sempre!
TDC 2014 - JavaScript de qualidade: hoje, amanhã e sempre!
 
API Design
API DesignAPI Design
API Design
 
えっ、なにそれこわい
えっ、なにそれこわいえっ、なにそれこわい
えっ、なにそれこわい
 

Similaire à Make it SOLID!

Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
Alexei Gorobets
 

Similaire à Make it SOLID! (20)

Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Demystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPDemystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHP
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Introduction to Domain-Driven Design
Introduction to Domain-Driven DesignIntroduction to Domain-Driven Design
Introduction to Domain-Driven Design
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data Model
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Demystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPDemystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHP
 
Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016
 
Solid principles
Solid principlesSolid principles
Solid principles
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
What is DDD and how could it help you
What is DDD and how could it help youWhat is DDD and how could it help you
What is DDD and how could it help you
 
OOP in PHP
OOP in PHPOOP in PHP
OOP in PHP
 
So S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeSo S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better Code
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 

Dernier

Dernier (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 

Make it SOLID!