SlideShare une entreprise Scribd logo
1  sur  44
Télécharger pour lire hors ligne
API & Fluency
An introdcution to Internal DSL (for PHP)
Where it started...
In 2005 Eric Evans proposed a different style of defining an API excluding
the Setter concept in favor of Mutators with return value; this approach
was named Fluent Interface in an article by Martin Fowler.
https://www.martinfowler.com/bliki/FluentInterface.html
Why Fluent?
The fluent attribute comes out from the special syntax of the developed
API that, as prose, makes its use readable and explicit.
Java example
Fluent Interface & Builder
Fluent Interfaces find immediate application in those areas where the
Builder Design Pattern can be used, getting a powerful configuration
tool.
C# example
Fluent Interface & DSL
The concept of Fluent Interface can be related to that of Domain Specific
Language
<< ...In software engineering, a fluent interface is an object-oriented API
whose design relies extensively on method chaining. Its goal is to
increase code legibility by creating a Domain-Specific Language... >>
https://en.wikipedia.org/wiki/Fluent_interface
DSL: External, Internal (or Embedded)
DSLs are classified into: External and Internal
They are defined external when they arise from grammars, and they
involve sets of elements proper to the theory of programming languages
such as: parser, lexer, interpreter or compiler
They are defined internal when they arise as a syntax enrichment of a
general-purpose hosting language, focusing on a specific jargon.
External DSL Vs Internal DSL
An External DSL is a complex engineering work that leads to a project
with a long-term perspective that provides a powerful maintenance
equipment (tools & efforts) to obtain the maximum return on initial
investment
An Internal DSL is generally simpler to build, can be also defined by a
single developer, but has a shorted horizon, different target and
possibilities
External DSL (Resources)
https://tomassetti.me/ https://strumenta.com/ http://voelter.de/
Why Internal DSL ?
●
Using a known programming language to lead added value with:
●
Simplify repetitive tasks
●
Simplify/Encapsulate some existing API
●
Encapsulate boilerplate code
●
Abstract complex business problems
●
Provide an API that expresses the intent of the code clearly
●
Guide the developer in the domain with IDE autocomplete
Internal DSL : Artifacts & DSL Session
Deploying an Internal DSL can be done as a library.
Another possibility is to define script & macro definitions in a template
language
Using the artifact allows a developer to create several instances of the DSL
that can be named as DSL Session.
Internal DSL : logical schema
An internal DSL can be assimilated to the sequence of several fluent
objects so named because their different methods lead to a fluent
sequence of contexts of the jargon you are working on.
Internal DSL : What style? Example
Form::WithId("My-Form")→
Attributes()→
Action("/Work.php")→
Method(HttpMethod::POST())→
Target(FormTarget::SELF)→
End()→
Elements()→
Text( textAttributes()→
WithId("t001")→
Named("text1") )→
Text( textAttributes()→
WithId("t002")→
Named("text2") )→
CheckBox( checkboxAttributes()→
WithId("male")→
Named("gender")→
WithValue("male") )→
CheckBox( checkboxAttributes()
WithId("female")→
Named("gender)→
WithValue("female") )→
End()→
AsHTML();
Internal DSL : What style? Example
Form::With(
Form::Id("My-Form"),
Form::Attributes("/Work.php",
HttpMethod::POST(),
FormTarget::SELF()),
Form::Fields(
Text::Of("t001", "text1"),
Text::Of("t002", "text2"),
Checkbox::Of(Gender::MALE,
Gender::GENDER_LABEL,
Gender::MALE),
Checkbox::Of(Gender::FEMALE,
Gender::GENDER_LABEL,
Gender::FEMALE),
)
);
Internal DSL : What style? Example
Form()→
Attributes(function(FormId $form):FormAttributes{
return $form
→ WithId("My-Form")
→ Action("/Work.php")
→ Method(FormMethod::POST)
→ Target(FormTarget::SELF);
})→ Text(function( FormField $field):void{
$field
→ Id("t001")
→ Name("text1");
})→ Text(function(FormField $field):void{
$field
→ Id("t002")
→ Name("text2");
})→ Checkbox(function(FormField $field):void{
$field
→ Id("male")
→ Name("gender")
→ Value("male");
})→ Checkbox(function(FormField $field):void{
$field
→ Id("female")
→ Name("gender")
→ Value("female"); })
→ End()
→ asHTML();
Internal DSL : Design Guidelines
The fundamental guidelines are related to:
●
The limits imposed by the Hosting Language (syntax,
idioms, meta-prg support, ...)
●
Complete study of the elements of the domain to which
fluency is to be obtained
●
Definition of the grammar and resulting syntax fluent
objects
https://www.bottlecaps.de/rr/ui (EBNF Diagram Tool)
●
Objectives on quality, re-usability, maintenance, ... of the
DSL sought
Internal DSL : Design Guidelines
SCALA
val qux = value of method “someInternalMethod” of bar
public class SimpleProject extends Project {
public int defaultNumOfWindows(){ return 4;}
public void define(){
defineHouseProject("SimpleHouse")
.withWindows(defaultNumOfWindows())
.whereWallsAre()
.painted(WHITE)
.decoratedWith(decorationsPalette()
.<ManualExecution>use(
SPONGING,
manualExecution())
.withInk(YELLOW))
.done()
.roofMadeIn(WOOD)
.build();
}}
JAVA
from elasticsearch import Elasticsearch
client = Elasticsearch()
response = client.search(
index="my-index",
body={
"query": {
"bool": {
"must": [{"match": {"title": "python"}}],
"must_not": [{"match": {"description":
"beta"}}],
"filter": [{"term": {"category": "search"}}]
}
},
"aggs" : {
"per_tag": {
"terms": {"field": "tags"},
"aggs": {
"max_lines": {"max": {"field": "lines"}}
}
}
}
})
Python
Internal DSL : Design Patterns
The chaining of different methods on the fluent objects can
be defined considering some primitive design principles
that are classifiable in three families:
●
Context primitives
●
Pure primitives
●
Glues primitives
Internal DSL : Design Patterns
The primitive design included in the 3 families are:
●
Starter
●
Finisher
●
Transition
●
Action
●
Back-Track
●
Delegation
●
Scoper
Internal DSL : Context Primitives
Starter: It is the primitive that describes the method of the
fluent object that allows the start of a DSL session; The
invocation of the input method defines the input context
Finisher: It is the primitive that describes the method that
does not return any fluent object concluding the current DSL
session
Transition: It is the primitive that describes a method of a
fluent object that returns another fluent object leading to a
change of context.
Internal DSL : Pure Primitives
Action: It is the primitive that describes methods that
determines a side-effect in the context current and continuing
with the current fluent-object
Back-Track: It is the primitive that describes methods that
determine a possible side-effect in the current context and
lead to a previous fluent object.
Internal DSL : Glue Primitives
Delegation: It is the primitive that that describes a method
that receives a behavior that delegate an activity with respect
to the current fluent object. It may have returned as much as
the present context that a new context.
Scoper: It is a primitive that describes methods that are used
internally in the DSL for implement a binding between the
current context and supporting object of the DSL.
Internal DSL : How to implement
There may be one or more entry
points to the DSL; generally when
Builder nature prevails it will
highlight a single entrypoint
If there are several entry points, they
must be independent of each other
and lead to different contexts.
To define a precise initial context, the
entry point of the DSL can be access
extending a specific context object
Java example
Internal DSL : How to implement

The exit point is generally unique although, more rarely, there may be
several.

The exit point is will be the one that will produce the final result of the
DSL.
Java examples
Internal DSL : How to implement
Rules for the contextual transition:
●
a fluent object can have one or more methods
●
a fluent object has a contract defined by an interface
●
a fluent object that exposes a new context and is not preceded by
others is a Starter
●
a fluent object that is not followed by another fluent object is a
Finisher
●
a fluent object can have methods that return to the current context
(this) or that lead to a new fluent object (Transition)
Internal DSL : How to implement
●
A fluent object representing mandatory DSL terms will be defined by all
methods that represent these keywords. The methods lead to a new
fluent object or to the Finisher
●
A fluent object that represents a freely repeatable term will be defined by
an interface with a method that represents this keyword and returns to
the same interface and at the same time extending the interface of
following fluent object or that of the finisher.
Internal DSL : How to implement
●
A fluent object representing an optional keyword will be expressed by an
interface that extends that of a successor object or Finisher. There will be
a method that expresses the optional keyword and returns the interface
of the next fluent object.
●
A flowing object that triggers a sub-branch of the DSL will be defined by
an interface with methods whose parameters will be other fluent objects
allowing recursion in the DSL
Internal DSL : Using the rules - Example
Internal DSL : Using the rules - Example
Car()→ BaseProduct()→ Produce();
Car()→ WithPreset(Preset::MARINE())→ Produce();
Car()→ StandardPreset()→ FullOptionals()→ Produce();
Car()→ StandardPreset()→ Produce();
Car()→ AdvancedPreset()→ Luxury()→ Produce();
Car()→ AdvancedPreset()→ Sports()→ Produce();
Car()→ WithEquipement()→
Part("Engine001") →
Part("BrakeTX3") →
Part("WheelDDS7") →
Produce();
Internal DSL : Using the rules - Example
interface Car
{
// single keyword in DSL
public function BaseProduct():CarProducer;
// parametric keyword in DSL
public function WithPreset(Preset $presetId): CarProducer;
// single optional keyword in DLS
public function StandardPreset():CarConfigWithOptional;
// multi choice exclusive keyword in DSL
public function AdvancedPreset():CarConfigAdvanced;
// repeatable keyword in DSL
public function WithEquipement():VariableCarConfig;
}
Internal DSL : Using the rules - Example
public function StandardPreset():CarConfigWithOptional;
interface CarConfigWithOptional extends CarProducer
{
public function FullOptionals():CarProducer;
}
public function AdvancedPreset():CarConfigAdvanced;
interface CarConfigAdvanced
{
public function Luxury():CarProducer;
public function Sports():CarProducer;
}
Internal DSL : Using the rules - Example
public function WithEquipement():VariableCarConfig;
interface VariableCarConfig extends CarProducer
{
public function Part(string $partId):VariableCarConfig;
}
Internal DSL : Mutations vs Immutability
●
When is defined a Transition to the same context, especially with
the Action Pattern, a side-effect happen
●
It’s possible to choose a Transition to the same context, creating a
new fluent object of the same type or cloning the existing one
●
Can be adopted validation policies for each node of the DSL and
Immutable Value Object as parameters
Internal DSL : Eager vs Lazy
●
In a DSL session the operation defined by the method chaining
are immediately evaluated
●
It’s possible to choose a lazy evaluation by using lambda, closure,
anonymous classes or classes hosting these kind of elements, that
are chained or aggregated; the evaluation happen on the Finisher
or by the lazy element returned to the Finisher
Internal DSL : Fluent Lazy Builder - Example
interface NameBuilder
{
public function WithName(string $name): FamilyNameBuilder;
}
interface FamilyNameBuilder
{
public function WithFamilyName(string $name): AgeBuilder;
}
interface AgeBuilder
{
public function WithAge(int $age):Person;
}
Internal DSL : Fluent Lazy Builder - Example
public static final function Define():NameBuilder{
return new class() implements NameBuilder{
public function WithName(string $name): FamilyNameBuilder{
return new class($name) implements FamilyNameBuilder{
private string $name;
public function __construct(string $name){ $this->name=$name;}
public function WithFamilyName(string $familyName): AgeBuilder{
return new class($this->name,$familyName) implements AgeBuilder{
private string $name;
private string $familyName;
public function __construct(string $name,string $familyName){
$this->name=$name;
$this->familyName = $familyName;
}
public function WithAge(int $age):Person{
return new Person($this->name, $this->familyName, $age);
} };
}};
}};
Person::Define()
→ WithName("John")
→ WithFamilyName("Black")
→ WithAge(40);
Internal DSL : Fluent Lazy Builder
Cascading Closure
class Person{
…
public static final function PersonBuilder():Closure
{
return
fn(string $name):Closure=>
fn(string $familyName):Closure=>
fn(int $age):Person=> new Person(
$name,
$familyName,
$age);
}
… }
Person::PersonBuilder()("John")("Black")(40)
Internal DSL : Execute Around Pattern

Execute Around Pattern frees the user from certain actions that
should always be executed before and after the business method.
MailSender::Send(function(Mail $config):Mail{
return $config
→ From("john.black@kmail.com")
→ To("jack.white@jmail.com")
→ Subject("Test message from Netscape
Communicator 4.7")
→ Body("Hello World!");
});
Internal DSL : Execute Around Pattern
class MailSender{
...
public static final function Send(Closure $mailConfig):void{
$mailSender = new MailSender();
$connection = null;
try{
$connection = $mailSender->connectToServer();
$connection→ Open();
$mailSender→ mailProcessing($connection, $mailConfig);
}finally{
if(isset($connection))
{
$connection.close();
}
}
}
...
}
Internal DSL : Loan Pattern
$refill = function(ToyBox
$box):ToyBox{
return $box
→ addToy("lego")
→ addToy("mechano")
→ addToy("laser");
};
$play = function(ToyBox
$box):ToyBox{
return $box
→ nextToy()
→ nextToy()
→ nextToy();
};
$playSession =
ToyBox::play($refill, $play);
$playSession();
$playSession();
/**
*
* @param Closure(ToyBox):ToyBox $boxFillerPolicy
* @param Closure(ToyBox):ToyBox $playActions
* @return Closure():void
*/
public static final function play(
Closure $boxFillerPolicy,
Closure $playActions):Closure{
return
function()use(
$boxFillerPolicy,
$playActions):void{
$box = new ToyBox();
$box→ Open();
$box = $boxFillerPolicy($box);
$box = $playActions($box);
$box→ Close()
→ CleanUpToys();
};
}
Internal DSL : Typed Key Value Pair
$arr = entriesForValueClass(Foo::class,[
entry("a",new Foo()),
entry("b",new Foo()),
]);
$arr2 = entriesForStringValue([
entry("WW","1"),
entry("ss","2"),
]);
$arr3 = entriesForIntValue([
entry("WW",1),
entry("ss",2),
]);
Internal DSL : Typed Key Value Pair
/**
*
* @template T
*
**/
final class KeyValue
{ … }
/**
*
* @template T
* @param T $value
* @return KeyValue<T>
*/
function entry(string $key, $value):
KeyValue
{
return new KeyValue($key, $value);
}
/**
*
* @template R
* @param array<KeyValue<R>> $pairs
* @param class-string<R> $clazz
* @return array<string,R>
* @psalm-suppress UnusedParam
*/
function entriesForValueClass(string $clazz,
array $pairs): array
{
$result = array();
foreach ($pairs as $pair) {
$result[$pair→ key()] = $pair→
value();
}
return $result;
}
Internal DSL : Typed Key Value Pair
/**
*
* @param array<KeyValue<string>> $pairs
* @return array<string,string>
*/
function entriesForStringValue(array
$pairs): array
{
$result = array();
foreach ($pairs as $pair) {
$result[$pair → key()] = $pair → value();
}
return $result;
}
/**
* @param array<KeyValue<int>> $pairs
* @return array<string,int>
*/
function entriesForIntValue(array $pairs):
array
{
$result = array();
foreach ($pairs as $pair) {
$result[$pair → key()] = $pair → value();
}
return $result;
}
Internal DSL : Problems

Careful drafting of a DSL can require a major effort

It is not easy to find compromises with respect to principles and
good practices

Use of inheritance, generics, composition for decoration can be
difficult

The maintenance of large DSL can be a considerable effort: it is
always good to consider a DSL as a product and evaluate when it
is appropriate to invest in it
That All Folks
More PHP Code Examples:
https://github.com/stefanofago73/php_dsl

Contenu connexe

Tendances

Tendances (20)

Lecture4 corba
Lecture4   corbaLecture4   corba
Lecture4 corba
 
CORBA - Introduction and Details
CORBA - Introduction and DetailsCORBA - Introduction and Details
CORBA - Introduction and Details
 
A Field Guide to DSL Design in Scala
A Field Guide to DSL Design in ScalaA Field Guide to DSL Design in Scala
A Field Guide to DSL Design in Scala
 
Common Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBACommon Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBA
 
Chapter 17 corba
Chapter 17 corbaChapter 17 corba
Chapter 17 corba
 
Common Object Request Broker Architecture
Common Object Request Broker ArchitectureCommon Object Request Broker Architecture
Common Object Request Broker Architecture
 
Chapter10
Chapter10Chapter10
Chapter10
 
D1 from interfaces to solid
D1 from interfaces to solidD1 from interfaces to solid
D1 from interfaces to solid
 
Corba and-java
Corba and-javaCorba and-java
Corba and-java
 
Corba introduction and simple example
Corba introduction and simple example Corba introduction and simple example
Corba introduction and simple example
 
CORBA Basic and Deployment of CORBA
CORBA Basic and Deployment of CORBACORBA Basic and Deployment of CORBA
CORBA Basic and Deployment of CORBA
 
Corba
CorbaCorba
Corba
 
Language Integrated Query - LINQ
Language Integrated Query - LINQLanguage Integrated Query - LINQ
Language Integrated Query - LINQ
 
Corba
CorbaCorba
Corba
 
Corba concepts & corba architecture
Corba concepts & corba architectureCorba concepts & corba architecture
Corba concepts & corba architecture
 
CORBA
CORBACORBA
CORBA
 
CORBA Component Model
CORBA Component Model CORBA Component Model
CORBA Component Model
 
C O R B A Unit 4
C O R B A    Unit 4C O R B A    Unit 4
C O R B A Unit 4
 
Corba
CorbaCorba
Corba
 
Vb.net
Vb.netVb.net
Vb.net
 

Similaire à Api and Fluency

Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLsintelliyole
 
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022InfluxData
 
AestasIT - Internal DSLs in Scala
AestasIT - Internal DSLs in ScalaAestasIT - Internal DSLs in Scala
AestasIT - Internal DSLs in ScalaDmitry Buzdin
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)lennartkats
 
Linq 1224887336792847 9
Linq 1224887336792847 9Linq 1224887336792847 9
Linq 1224887336792847 9google
 
Building DSLs On CLR and DLR (Microsoft.NET)
Building DSLs On CLR and DLR (Microsoft.NET)Building DSLs On CLR and DLR (Microsoft.NET)
Building DSLs On CLR and DLR (Microsoft.NET)Vitaly Baum
 
Extending js codemotion warsaw 2016
Extending js codemotion warsaw 2016Extending js codemotion warsaw 2016
Extending js codemotion warsaw 2016Francis Bourre
 
Advanced SQL - Database Access from Programming Languages
Advanced SQL - Database Access  from Programming LanguagesAdvanced SQL - Database Access  from Programming Languages
Advanced SQL - Database Access from Programming LanguagesS.Shayan Daneshvar
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The EnterpriseDaniel Egan
 
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)Frank Scheffler
 
Framework engineering JCO 2011
Framework engineering JCO 2011Framework engineering JCO 2011
Framework engineering JCO 2011YoungSu Son
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practicesmanugoel2003
 
ALPHA Script - Presentation
ALPHA Script - PresentationALPHA Script - Presentation
ALPHA Script - PresentationPROBOTEK
 
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...Maarten Balliauw
 
How to build Sdk? Best practices
How to build Sdk? Best practicesHow to build Sdk? Best practices
How to build Sdk? Best practicesVitali Pekelis
 
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...Maarten Balliauw
 

Similaire à Api and Fluency (20)

Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022
Gary Fowler [InfluxData] | InfluxDB Scripting Languages | InfluxDays 2022
 
AestasIT - Internal DSLs in Scala
AestasIT - Internal DSLs in ScalaAestasIT - Internal DSLs in Scala
AestasIT - Internal DSLs in Scala
 
Analysis
AnalysisAnalysis
Analysis
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
Linq 1224887336792847 9
Linq 1224887336792847 9Linq 1224887336792847 9
Linq 1224887336792847 9
 
Building DSLs On CLR and DLR (Microsoft.NET)
Building DSLs On CLR and DLR (Microsoft.NET)Building DSLs On CLR and DLR (Microsoft.NET)
Building DSLs On CLR and DLR (Microsoft.NET)
 
Extending js codemotion warsaw 2016
Extending js codemotion warsaw 2016Extending js codemotion warsaw 2016
Extending js codemotion warsaw 2016
 
Advanced SQL - Database Access from Programming Languages
Advanced SQL - Database Access  from Programming LanguagesAdvanced SQL - Database Access  from Programming Languages
Advanced SQL - Database Access from Programming Languages
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
 
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)
Sprache als Werkzeug: DSLs mit Kotlin (JAX 2020)
 
Framework engineering JCO 2011
Framework engineering JCO 2011Framework engineering JCO 2011
Framework engineering JCO 2011
 
Getting Native with NDK
Getting Native with NDKGetting Native with NDK
Getting Native with NDK
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
 
oodb.ppt
oodb.pptoodb.ppt
oodb.ppt
 
ALPHA Script - Presentation
ALPHA Script - PresentationALPHA Script - Presentation
ALPHA Script - Presentation
 
LOD2: State of Play WP6 - LOD2 Stack Architecture
LOD2: State of Play WP6 - LOD2 Stack ArchitectureLOD2: State of Play WP6 - LOD2 Stack Architecture
LOD2: State of Play WP6 - LOD2 Stack Architecture
 
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
 
How to build Sdk? Best practices
How to build Sdk? Best practicesHow to build Sdk? Best practices
How to build Sdk? Best practices
 
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
 

Plus de Stefano Fago

Exploring Open Source Licensing
Exploring Open Source LicensingExploring Open Source Licensing
Exploring Open Source LicensingStefano Fago
 
Non solo Microservizi: API, Prodotti e Piattaforme
Non solo Microservizi: API, Prodotti e PiattaformeNon solo Microservizi: API, Prodotti e Piattaforme
Non solo Microservizi: API, Prodotti e PiattaformeStefano Fago
 
Don’t give up, You can... Cache!
Don’t give up, You can... Cache!Don’t give up, You can... Cache!
Don’t give up, You can... Cache!Stefano Fago
 
Resisting to The Shocks
Resisting to The ShocksResisting to The Shocks
Resisting to The ShocksStefano Fago
 
Gamification - Introduzione e Idee di un NON GIOCATORE
Gamification - Introduzione e Idee di un NON GIOCATOREGamification - Introduzione e Idee di un NON GIOCATORE
Gamification - Introduzione e Idee di un NON GIOCATOREStefano Fago
 
Quale IT nel futuro delle Banche?
Quale IT nel futuro delle Banche?Quale IT nel futuro delle Banche?
Quale IT nel futuro delle Banche?Stefano Fago
 
Microservices & Bento
Microservices & BentoMicroservices & Bento
Microservices & BentoStefano Fago
 
What drives Innovation? Innovations And Technological Solutions for the Distr...
What drives Innovation? Innovations And Technological Solutions for the Distr...What drives Innovation? Innovations And Technological Solutions for the Distr...
What drives Innovation? Innovations And Technological Solutions for the Distr...Stefano Fago
 
Reasoning about QRCode
Reasoning about QRCodeReasoning about QRCode
Reasoning about QRCodeStefano Fago
 
... thinking about Microformats!
... thinking about Microformats!... thinking about Microformats!
... thinking about Microformats!Stefano Fago
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design PatternsStefano Fago
 
Riuso Object Oriented
Riuso Object OrientedRiuso Object Oriented
Riuso Object OrientedStefano Fago
 

Plus de Stefano Fago (13)

Exploring Open Source Licensing
Exploring Open Source LicensingExploring Open Source Licensing
Exploring Open Source Licensing
 
Non solo Microservizi: API, Prodotti e Piattaforme
Non solo Microservizi: API, Prodotti e PiattaformeNon solo Microservizi: API, Prodotti e Piattaforme
Non solo Microservizi: API, Prodotti e Piattaforme
 
Don’t give up, You can... Cache!
Don’t give up, You can... Cache!Don’t give up, You can... Cache!
Don’t give up, You can... Cache!
 
Resisting to The Shocks
Resisting to The ShocksResisting to The Shocks
Resisting to The Shocks
 
Gamification - Introduzione e Idee di un NON GIOCATORE
Gamification - Introduzione e Idee di un NON GIOCATOREGamification - Introduzione e Idee di un NON GIOCATORE
Gamification - Introduzione e Idee di un NON GIOCATORE
 
Quale IT nel futuro delle Banche?
Quale IT nel futuro delle Banche?Quale IT nel futuro delle Banche?
Quale IT nel futuro delle Banche?
 
Microservices & Bento
Microservices & BentoMicroservices & Bento
Microservices & Bento
 
Giochi in Azienda
Giochi in AziendaGiochi in Azienda
Giochi in Azienda
 
What drives Innovation? Innovations And Technological Solutions for the Distr...
What drives Innovation? Innovations And Technological Solutions for the Distr...What drives Innovation? Innovations And Technological Solutions for the Distr...
What drives Innovation? Innovations And Technological Solutions for the Distr...
 
Reasoning about QRCode
Reasoning about QRCodeReasoning about QRCode
Reasoning about QRCode
 
... thinking about Microformats!
... thinking about Microformats!... thinking about Microformats!
... thinking about Microformats!
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design Patterns
 
Riuso Object Oriented
Riuso Object OrientedRiuso Object Oriented
Riuso Object Oriented
 

Dernier

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
Accelerating Enterprise Software Engineering with Platformless
Accelerating Enterprise Software Engineering with PlatformlessAccelerating Enterprise Software Engineering with Platformless
Accelerating Enterprise Software Engineering with PlatformlessWSO2
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
Français Patch Tuesday - Avril
Français Patch Tuesday - AvrilFrançais Patch Tuesday - Avril
Français Patch Tuesday - AvrilIvanti
 

Dernier (20)

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
Accelerating Enterprise Software Engineering with Platformless
Accelerating Enterprise Software Engineering with PlatformlessAccelerating Enterprise Software Engineering with Platformless
Accelerating Enterprise Software Engineering with Platformless
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
Français Patch Tuesday - Avril
Français Patch Tuesday - AvrilFrançais Patch Tuesday - Avril
Français Patch Tuesday - Avril
 

Api and Fluency

  • 1. API & Fluency An introdcution to Internal DSL (for PHP)
  • 2. Where it started... In 2005 Eric Evans proposed a different style of defining an API excluding the Setter concept in favor of Mutators with return value; this approach was named Fluent Interface in an article by Martin Fowler. https://www.martinfowler.com/bliki/FluentInterface.html
  • 3. Why Fluent? The fluent attribute comes out from the special syntax of the developed API that, as prose, makes its use readable and explicit. Java example
  • 4. Fluent Interface & Builder Fluent Interfaces find immediate application in those areas where the Builder Design Pattern can be used, getting a powerful configuration tool. C# example
  • 5. Fluent Interface & DSL The concept of Fluent Interface can be related to that of Domain Specific Language << ...In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a Domain-Specific Language... >> https://en.wikipedia.org/wiki/Fluent_interface
  • 6. DSL: External, Internal (or Embedded) DSLs are classified into: External and Internal They are defined external when they arise from grammars, and they involve sets of elements proper to the theory of programming languages such as: parser, lexer, interpreter or compiler They are defined internal when they arise as a syntax enrichment of a general-purpose hosting language, focusing on a specific jargon.
  • 7. External DSL Vs Internal DSL An External DSL is a complex engineering work that leads to a project with a long-term perspective that provides a powerful maintenance equipment (tools & efforts) to obtain the maximum return on initial investment An Internal DSL is generally simpler to build, can be also defined by a single developer, but has a shorted horizon, different target and possibilities
  • 8. External DSL (Resources) https://tomassetti.me/ https://strumenta.com/ http://voelter.de/
  • 9. Why Internal DSL ? ● Using a known programming language to lead added value with: ● Simplify repetitive tasks ● Simplify/Encapsulate some existing API ● Encapsulate boilerplate code ● Abstract complex business problems ● Provide an API that expresses the intent of the code clearly ● Guide the developer in the domain with IDE autocomplete
  • 10. Internal DSL : Artifacts & DSL Session Deploying an Internal DSL can be done as a library. Another possibility is to define script & macro definitions in a template language Using the artifact allows a developer to create several instances of the DSL that can be named as DSL Session.
  • 11. Internal DSL : logical schema An internal DSL can be assimilated to the sequence of several fluent objects so named because their different methods lead to a fluent sequence of contexts of the jargon you are working on.
  • 12. Internal DSL : What style? Example Form::WithId("My-Form")→ Attributes()→ Action("/Work.php")→ Method(HttpMethod::POST())→ Target(FormTarget::SELF)→ End()→ Elements()→ Text( textAttributes()→ WithId("t001")→ Named("text1") )→ Text( textAttributes()→ WithId("t002")→ Named("text2") )→ CheckBox( checkboxAttributes()→ WithId("male")→ Named("gender")→ WithValue("male") )→ CheckBox( checkboxAttributes() WithId("female")→ Named("gender)→ WithValue("female") )→ End()→ AsHTML();
  • 13. Internal DSL : What style? Example Form::With( Form::Id("My-Form"), Form::Attributes("/Work.php", HttpMethod::POST(), FormTarget::SELF()), Form::Fields( Text::Of("t001", "text1"), Text::Of("t002", "text2"), Checkbox::Of(Gender::MALE, Gender::GENDER_LABEL, Gender::MALE), Checkbox::Of(Gender::FEMALE, Gender::GENDER_LABEL, Gender::FEMALE), ) );
  • 14. Internal DSL : What style? Example Form()→ Attributes(function(FormId $form):FormAttributes{ return $form → WithId("My-Form") → Action("/Work.php") → Method(FormMethod::POST) → Target(FormTarget::SELF); })→ Text(function( FormField $field):void{ $field → Id("t001") → Name("text1"); })→ Text(function(FormField $field):void{ $field → Id("t002") → Name("text2"); })→ Checkbox(function(FormField $field):void{ $field → Id("male") → Name("gender") → Value("male"); })→ Checkbox(function(FormField $field):void{ $field → Id("female") → Name("gender") → Value("female"); }) → End() → asHTML();
  • 15. Internal DSL : Design Guidelines The fundamental guidelines are related to: ● The limits imposed by the Hosting Language (syntax, idioms, meta-prg support, ...) ● Complete study of the elements of the domain to which fluency is to be obtained ● Definition of the grammar and resulting syntax fluent objects https://www.bottlecaps.de/rr/ui (EBNF Diagram Tool) ● Objectives on quality, re-usability, maintenance, ... of the DSL sought
  • 16. Internal DSL : Design Guidelines SCALA val qux = value of method “someInternalMethod” of bar public class SimpleProject extends Project { public int defaultNumOfWindows(){ return 4;} public void define(){ defineHouseProject("SimpleHouse") .withWindows(defaultNumOfWindows()) .whereWallsAre() .painted(WHITE) .decoratedWith(decorationsPalette() .<ManualExecution>use( SPONGING, manualExecution()) .withInk(YELLOW)) .done() .roofMadeIn(WOOD) .build(); }} JAVA from elasticsearch import Elasticsearch client = Elasticsearch() response = client.search( index="my-index", body={ "query": { "bool": { "must": [{"match": {"title": "python"}}], "must_not": [{"match": {"description": "beta"}}], "filter": [{"term": {"category": "search"}}] } }, "aggs" : { "per_tag": { "terms": {"field": "tags"}, "aggs": { "max_lines": {"max": {"field": "lines"}} } } } }) Python
  • 17. Internal DSL : Design Patterns The chaining of different methods on the fluent objects can be defined considering some primitive design principles that are classifiable in three families: ● Context primitives ● Pure primitives ● Glues primitives
  • 18. Internal DSL : Design Patterns The primitive design included in the 3 families are: ● Starter ● Finisher ● Transition ● Action ● Back-Track ● Delegation ● Scoper
  • 19. Internal DSL : Context Primitives Starter: It is the primitive that describes the method of the fluent object that allows the start of a DSL session; The invocation of the input method defines the input context Finisher: It is the primitive that describes the method that does not return any fluent object concluding the current DSL session Transition: It is the primitive that describes a method of a fluent object that returns another fluent object leading to a change of context.
  • 20. Internal DSL : Pure Primitives Action: It is the primitive that describes methods that determines a side-effect in the context current and continuing with the current fluent-object Back-Track: It is the primitive that describes methods that determine a possible side-effect in the current context and lead to a previous fluent object.
  • 21. Internal DSL : Glue Primitives Delegation: It is the primitive that that describes a method that receives a behavior that delegate an activity with respect to the current fluent object. It may have returned as much as the present context that a new context. Scoper: It is a primitive that describes methods that are used internally in the DSL for implement a binding between the current context and supporting object of the DSL.
  • 22. Internal DSL : How to implement There may be one or more entry points to the DSL; generally when Builder nature prevails it will highlight a single entrypoint If there are several entry points, they must be independent of each other and lead to different contexts. To define a precise initial context, the entry point of the DSL can be access extending a specific context object Java example
  • 23. Internal DSL : How to implement  The exit point is generally unique although, more rarely, there may be several.  The exit point is will be the one that will produce the final result of the DSL. Java examples
  • 24. Internal DSL : How to implement Rules for the contextual transition: ● a fluent object can have one or more methods ● a fluent object has a contract defined by an interface ● a fluent object that exposes a new context and is not preceded by others is a Starter ● a fluent object that is not followed by another fluent object is a Finisher ● a fluent object can have methods that return to the current context (this) or that lead to a new fluent object (Transition)
  • 25. Internal DSL : How to implement ● A fluent object representing mandatory DSL terms will be defined by all methods that represent these keywords. The methods lead to a new fluent object or to the Finisher ● A fluent object that represents a freely repeatable term will be defined by an interface with a method that represents this keyword and returns to the same interface and at the same time extending the interface of following fluent object or that of the finisher.
  • 26. Internal DSL : How to implement ● A fluent object representing an optional keyword will be expressed by an interface that extends that of a successor object or Finisher. There will be a method that expresses the optional keyword and returns the interface of the next fluent object. ● A flowing object that triggers a sub-branch of the DSL will be defined by an interface with methods whose parameters will be other fluent objects allowing recursion in the DSL
  • 27. Internal DSL : Using the rules - Example
  • 28. Internal DSL : Using the rules - Example Car()→ BaseProduct()→ Produce(); Car()→ WithPreset(Preset::MARINE())→ Produce(); Car()→ StandardPreset()→ FullOptionals()→ Produce(); Car()→ StandardPreset()→ Produce(); Car()→ AdvancedPreset()→ Luxury()→ Produce(); Car()→ AdvancedPreset()→ Sports()→ Produce(); Car()→ WithEquipement()→ Part("Engine001") → Part("BrakeTX3") → Part("WheelDDS7") → Produce();
  • 29. Internal DSL : Using the rules - Example interface Car { // single keyword in DSL public function BaseProduct():CarProducer; // parametric keyword in DSL public function WithPreset(Preset $presetId): CarProducer; // single optional keyword in DLS public function StandardPreset():CarConfigWithOptional; // multi choice exclusive keyword in DSL public function AdvancedPreset():CarConfigAdvanced; // repeatable keyword in DSL public function WithEquipement():VariableCarConfig; }
  • 30. Internal DSL : Using the rules - Example public function StandardPreset():CarConfigWithOptional; interface CarConfigWithOptional extends CarProducer { public function FullOptionals():CarProducer; } public function AdvancedPreset():CarConfigAdvanced; interface CarConfigAdvanced { public function Luxury():CarProducer; public function Sports():CarProducer; }
  • 31. Internal DSL : Using the rules - Example public function WithEquipement():VariableCarConfig; interface VariableCarConfig extends CarProducer { public function Part(string $partId):VariableCarConfig; }
  • 32. Internal DSL : Mutations vs Immutability ● When is defined a Transition to the same context, especially with the Action Pattern, a side-effect happen ● It’s possible to choose a Transition to the same context, creating a new fluent object of the same type or cloning the existing one ● Can be adopted validation policies for each node of the DSL and Immutable Value Object as parameters
  • 33. Internal DSL : Eager vs Lazy ● In a DSL session the operation defined by the method chaining are immediately evaluated ● It’s possible to choose a lazy evaluation by using lambda, closure, anonymous classes or classes hosting these kind of elements, that are chained or aggregated; the evaluation happen on the Finisher or by the lazy element returned to the Finisher
  • 34. Internal DSL : Fluent Lazy Builder - Example interface NameBuilder { public function WithName(string $name): FamilyNameBuilder; } interface FamilyNameBuilder { public function WithFamilyName(string $name): AgeBuilder; } interface AgeBuilder { public function WithAge(int $age):Person; }
  • 35. Internal DSL : Fluent Lazy Builder - Example public static final function Define():NameBuilder{ return new class() implements NameBuilder{ public function WithName(string $name): FamilyNameBuilder{ return new class($name) implements FamilyNameBuilder{ private string $name; public function __construct(string $name){ $this->name=$name;} public function WithFamilyName(string $familyName): AgeBuilder{ return new class($this->name,$familyName) implements AgeBuilder{ private string $name; private string $familyName; public function __construct(string $name,string $familyName){ $this->name=$name; $this->familyName = $familyName; } public function WithAge(int $age):Person{ return new Person($this->name, $this->familyName, $age); } }; }}; }}; Person::Define() → WithName("John") → WithFamilyName("Black") → WithAge(40);
  • 36. Internal DSL : Fluent Lazy Builder Cascading Closure class Person{ … public static final function PersonBuilder():Closure { return fn(string $name):Closure=> fn(string $familyName):Closure=> fn(int $age):Person=> new Person( $name, $familyName, $age); } … } Person::PersonBuilder()("John")("Black")(40)
  • 37. Internal DSL : Execute Around Pattern  Execute Around Pattern frees the user from certain actions that should always be executed before and after the business method. MailSender::Send(function(Mail $config):Mail{ return $config → From("john.black@kmail.com") → To("jack.white@jmail.com") → Subject("Test message from Netscape Communicator 4.7") → Body("Hello World!"); });
  • 38. Internal DSL : Execute Around Pattern class MailSender{ ... public static final function Send(Closure $mailConfig):void{ $mailSender = new MailSender(); $connection = null; try{ $connection = $mailSender->connectToServer(); $connection→ Open(); $mailSender→ mailProcessing($connection, $mailConfig); }finally{ if(isset($connection)) { $connection.close(); } } } ... }
  • 39. Internal DSL : Loan Pattern $refill = function(ToyBox $box):ToyBox{ return $box → addToy("lego") → addToy("mechano") → addToy("laser"); }; $play = function(ToyBox $box):ToyBox{ return $box → nextToy() → nextToy() → nextToy(); }; $playSession = ToyBox::play($refill, $play); $playSession(); $playSession(); /** * * @param Closure(ToyBox):ToyBox $boxFillerPolicy * @param Closure(ToyBox):ToyBox $playActions * @return Closure():void */ public static final function play( Closure $boxFillerPolicy, Closure $playActions):Closure{ return function()use( $boxFillerPolicy, $playActions):void{ $box = new ToyBox(); $box→ Open(); $box = $boxFillerPolicy($box); $box = $playActions($box); $box→ Close() → CleanUpToys(); }; }
  • 40. Internal DSL : Typed Key Value Pair $arr = entriesForValueClass(Foo::class,[ entry("a",new Foo()), entry("b",new Foo()), ]); $arr2 = entriesForStringValue([ entry("WW","1"), entry("ss","2"), ]); $arr3 = entriesForIntValue([ entry("WW",1), entry("ss",2), ]);
  • 41. Internal DSL : Typed Key Value Pair /** * * @template T * **/ final class KeyValue { … } /** * * @template T * @param T $value * @return KeyValue<T> */ function entry(string $key, $value): KeyValue { return new KeyValue($key, $value); } /** * * @template R * @param array<KeyValue<R>> $pairs * @param class-string<R> $clazz * @return array<string,R> * @psalm-suppress UnusedParam */ function entriesForValueClass(string $clazz, array $pairs): array { $result = array(); foreach ($pairs as $pair) { $result[$pair→ key()] = $pair→ value(); } return $result; }
  • 42. Internal DSL : Typed Key Value Pair /** * * @param array<KeyValue<string>> $pairs * @return array<string,string> */ function entriesForStringValue(array $pairs): array { $result = array(); foreach ($pairs as $pair) { $result[$pair → key()] = $pair → value(); } return $result; } /** * @param array<KeyValue<int>> $pairs * @return array<string,int> */ function entriesForIntValue(array $pairs): array { $result = array(); foreach ($pairs as $pair) { $result[$pair → key()] = $pair → value(); } return $result; }
  • 43. Internal DSL : Problems  Careful drafting of a DSL can require a major effort  It is not easy to find compromises with respect to principles and good practices  Use of inheritance, generics, composition for decoration can be difficult  The maintenance of large DSL can be a considerable effort: it is always good to consider a DSL as a product and evaluate when it is appropriate to invest in it
  • 44. That All Folks More PHP Code Examples: https://github.com/stefanofago73/php_dsl