SlideShare a Scribd company logo
1 of 91
Download to read offline
VALUES
Ben Eddy
@ClashingPlaids
ROADMAP
Why our brains like object-orientation
Examples of value objects
ActiveRecord tips
RUBY IS AN OBJECT-ORIENTED
PROGRAMMING LANGUAGE
WHAT IS AN OBJECT?
OBJECTS ARE USEFUL
→
class Car
# car stuff
end
class ShippingContainer
# container stuff
end
class Person
# person stuff
end
OBJECTS HAVE ATTRIBUTES
class Person
attr_accessor :age
end
person = Person.new
person.age = 0
while true do
sleep 31536000
person.age += 1
end
person_1 = Person.new
person_1.age = 40
person_2 = Person.new
person_2.age = 40
hostage = Person.new
hostage.age = 40
captor = Person.new
captor.age = 40
OBJECTS HAVE IDENTITY
hostage = Person.new
hostage.age = 40
captor = Person.new
captor.age = 40
hostage == captor
# => false
hostage = Person.new
hostage.age = 40
captor = Person.new
captor.age = 40
hostage.object_id
# => 70122276807860
captor.object_id
# => 70122276712780
IDENTITY IS IMPORTANT
EXCEPT WHEN IT ISN'T
string_1 = "ABC"
string_2 = "ABC"
string_1 = "ABC"
string_2 = "ABC"
string_1.object_id
# => 70122276804530
string_2.object_id
# => 70122276104871
string_1 == string_2
# => true
string_1 = "ABC"
string_2 = "ABC"
string_1.==(string_2)
# => true
IDENTITY VS. VALUE
VALUE OBJECTS
Immutable
Easier to reason about
Easier to test
Easier to share
Enable easier method and class naming
Make systems more robust
Enrich semantics
class Person
end
class Person
attr_accessor :name
end
alice = Person.new
alice.name = "Alice Cranston"
class Person
def take_last_name(last_name)
self.name = first_and_middle_names.push(last_name).join(" ")
end
def first_and_middle_names
name.split(" ")[0..-2]
end
end
NAMING IS HARD
Avoid names which are too common
Avoid infamous names
class Person
# ...
COMMON_NAMES = %w( Ben Eric Jane )
def name_common?
COMMON_NAMES.include?(first_name)
end
def first_name
name.split(" ").first
end
end
class Person
def name_similiar_to?(other_name)
FuzzyMatch.matches?(name, other_name)
end
end
dictators = ["Adolf Hitler", "Genghis Khan", "Josef Stalin"]
person = Person.new
["Eric Jones", "Mingus Kan", "Timion Lowry"].reject do |name|
person.name = name
person.name_common? ||
dictators.any? { |dictator| person.name_similiar_to?(dictator) }
end
class Person
COMMON_NAMES = []
def take_last_name
# ..
end
def name_common?
# ...
end
def name_similiar_to?(other_name)
# ...
end
end
class Name
def initialize(@name)
@name = name
end
def ==(other_name)
name == other_name.name
end
protected
attr_reader :name
end
Name.new("Ben Eddy") == Name.new("Ben Eddy")
# => true
class Name
def initialize(name)
@name = name
end
def merge_with(other_name, patronymic: true); end
def common?; end
def similiar_to?(other_name); end
def mononym?; end
def ==(other_name); end
protected
attr_reader :name
end
class Name
def first_and_middle
# ...
end
def last
# ...
end
def merge_with(other_name)
Name.new [first_and_middle, other_name.last].join(" ")
end
end
husband = Person.new
husband.name = Name.new("Melvin Cartwright")
wife = Person.new
wife.name = Name.new("Alice Cranston")
# marriage
wife.name = wife.name.merge_with(husband.name)
VALUES ARE IMMUTABLE
dictators = [
Name.new("Adolf Hitler"),
Name.new("Genghis Khan"),
Name.new("Josef Stalin")
]
[
Name.new("Eric Jones"),
Name.new("Mingus Kan"),
Name.new("Timion Lowry")
].reject do |name|
name.common? || dictators.any?(&name.method(:similar_to?))
end
name.common?
name.similar_to?(other_name)
name.merge_with(other_name)
MAKING THE IMPLICIT EXPLICIT
DRAW ON ESTABLISHED
FORMALISMS
NOUN AN·THRO·PON·Y·MY
SPECIFIC
GENERAL
SPECIFIC
GENERAL
class Payment
attr_reader :card_number
def initialize(card_number)
@card_number = card_number
end
end
class Payment
# ...
def charge
PaymentProcessor.charge(card_number)
end
end
4321 5678 9012 1234
4321 5678 9012 1234
4321 5678 9012 1234
class Payment
# ...
def charge
# Add some card number validations
PaymentProcessor.charge(card_number)
end
end
class CreditCardNumber
def initialize(number)
# ...
end
def issuer
# ...
end
def valid?
# validations
end
end
class Payment
def credit_card_number
CreditCardNumber.new(@card_number)
end
end
TEST IN ISOLATION
4321 5678 9012 1234
4321-5678-9012-1234
4321567890121234
Be conservative in what you do, be liberal
in what you accept from others.
class Payment
def credit_card_number
CreditCardNumber.new(@card_number.gsub(/D/, ''))
end
end
class CreditCardNumber
def self.coerce(number)
return number if number.is_a?(CreditCardNumber)
new(number.to_s.gsub(/D/, ''))
end
end
class Payment
def credit_card_number
CreditCardNumber.coerce(@card_number)
end
end
COERCE AT THE BOUNDARY
COERCE AT THE BOUNDARY
Money.coerce(10)
Money.coerce(10.0)
Money.coerce("10")
Money.coerce("$10.00")
Money.coerce(:vegetables)
# => TypeError
payments = [
Payment.new(CreditCardNumber.new("371449635398431")),
Payment.new(CreditCardNumber.new("4012888888881881")),
Payment.new(CreditCardNumber.new("4012888888881881"))
]
payments.group_by(&:credit_card_number)
payments.group_by(&:credit_card_number)
# => {
CreditCardNumber.new("371449635398431") => [payment]
CreditCardNumber.new("4012888888881881") => [payment]
CreditCardNumber.new("4012888888881881") => [payment]
}
class CreditCardNumber
def eql?(other)
number == other.number
end
end
payments.group_by(&:credit_card_number)
# => {
CreditCardNumber.new("371449635398431") => [payment]
CreditCardNumber.new("4012888888881881") => [payment, payment]
}
payments = [
Payment.new(CreditCardNumber.new("371449635398431")),
Payment.new(CreditCardNumber.new("4012888888881881")),
Payment.new(CreditCardNumber.new("4012888888881881"))
]
grouped = payments.group_by(&:credit_card_number)
# => {
CreditCardNumber.new("371449635398431") => [payment]
CreditCardNumber.new("4012888888881881") => [payment, payment]
}
grouped[CreditCardNumber.new("4012888888881881")]
# => nil
class CreditCardNumber
def hash
number.hash
end
end
payments = [
Payment.new(CreditCardNumber.new("371449635398431")),
Payment.new(CreditCardNumber.new("4012888888881881")),
Payment.new(CreditCardNumber.new("4012888888881881"))
]
grouped = payments.group_by(&:credit_card_number)
# => {
CreditCardNumber.new("371449635398431") => [payment]
CreditCardNumber.new("4012888888881881") => [payment, payment]
}
grouped[CreditCardNumber.new("4012888888881881")]
# => [payment, payment]
RECAP
==
eql?
hash
# optionally
<=>
class User
def active?
status == "invited" || status == "email_confirmed"
end
end
class User
def active?
status.active?
end
def status
Status.new(@status)
end
end
dangerous_symptoms = Symptoms.new(
Symptom.new(:coughing),
Symptom.new(:fever)
)
patients.each do |patient|
if patient.symptoms.match?(dangerous_symptoms)
raise "OUTBREAK DETECTED"
end
end
duration_1 = Duration.new(60)
duration_2 = Duration.from_minutes(1)
duration_1 == duration_2
# => true
duration_1.longer_than?(Duration.new(120))
# => false
query = "SELECT * FROM users"
query += " WHERE last_name = 'Williams'"
query = SqlQuery.new("SELECT * FROM users")
query = query.where(last_name: "Williams")
THE VIRTUES OF VALUES
Make the implicit explicit
Segregate domain generality from specificity
Segregate imperative code from functional code
Easy and safe to share
Simplify transactions
Few dependencies
Easier to test
ACTIVERECORD AND VALUE
OBJECTS
DATABASES CAN ONLY STORE
PRIMITIVES
READING/WRITING
class Payment < ActiveRecord::Base
def credit_card_number
CreditCardNumber.new(super)
end
def credit_card_number=(number)
super CreditCardNumber.coerce(number).to_s
end
end
READING/WRITING
class Person < ActiveRecord::Base
def address
Address.new({
street: street,
city: city,
state: state
})
end
def address=(attributes)
Address.coerce(attributes).tap do |address|
self.street = address.street
self.city = address.city
self.state = address.state
end
end
end
FORMS
<%= form_for @person do |f| %>
<%= f.fields_for :address, f.object.address do |ff| %>
<%= ff.input :street %>
<%= ff.input :city %>
<%= ff.input :statee %>
<% end %>
<% end %>
{
person: {
address: {
street: "123 Main",
city: "Boulder",
state: "CO"
}
}
}
FORMS
<%= simple_form_for @person do |f| %>
<%= f.input :address, as: :address %>
<% end %>
QUERYING
class Payment < ActiveRecord::Base
def self.with_credit_card_number(number)
where(card_number: number)
end
end
number = CreditCardNumber.new("4012888888881881")
Payment.with_credit_card_number(number)
# => TypeError: Cannot visit CreditCardNumber
QUERYING
class Payment < ActiveRecord::Base
def self.with_credit_card_number(number)
where(card_number: number.to_s)
end
end
number = CreditCardNumber.new("4012888888881881")
Payment.with_credit_card_number(number)
QUERYING
handler = proc do |column, credit_card_number|
column.eq(credit_card_number.to_s)
end
ActiveRecord::PredicateBuilder.register_handler(
CreditCardNumber, handler)
class Payment < ActiveRecord::Base
def self.with_credit_card_number(number)
where(card_number: number)
end
end
number = CreditCardNumber.new("4012888888881881")
Payment.with_credit_card_number(number)
GETTING STARTED
Wrap primitives
Use internally
Get help
Values
Good
FURTHER READING
Domain Driven Design - Eric Evans
Are We There Yet? - Rich Hickey
Value of Values - Rich Hickey
Boundaries - Gary Bernhardt

More Related Content

What's hot

Improving RDF Search Performance with Lucene and SIREN
Improving RDF Search Performance with Lucene and SIRENImproving RDF Search Performance with Lucene and SIREN
Improving RDF Search Performance with Lucene and SIREN
Mike Hugo
 
Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
Andre Foeken
 
PHP Unit 4 arrays
PHP Unit 4 arraysPHP Unit 4 arrays
PHP Unit 4 arrays
Kumar
 

What's hot (20)

Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
ZIO Prelude - ZIO World 2021
ZIO Prelude - ZIO World 2021ZIO Prelude - ZIO World 2021
ZIO Prelude - ZIO World 2021
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Lab 4
Lab 4Lab 4
Lab 4
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
GDI Seattle - Intro to JavaScript Class 2
GDI Seattle - Intro to JavaScript Class 2GDI Seattle - Intro to JavaScript Class 2
GDI Seattle - Intro to JavaScript Class 2
 
tutorial7
tutorial7tutorial7
tutorial7
 
Improving RDF Search Performance with Lucene and SIREN
Improving RDF Search Performance with Lucene and SIRENImproving RDF Search Performance with Lucene and SIREN
Improving RDF Search Performance with Lucene and SIREN
 
A limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyA limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced Ruby
 
Indexing thousands of writes per second with redis
Indexing thousands of writes per second with redisIndexing thousands of writes per second with redis
Indexing thousands of writes per second with redis
 
The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181The Ring programming language version 1.5.2 book - Part 6 of 181
The Ring programming language version 1.5.2 book - Part 6 of 181
 
Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
 
Python programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphismPython programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphism
 
Dart - en ny platform til webudvikling af Rico Wind, Google
Dart - en ny platform til webudvikling af Rico Wind, GoogleDart - en ny platform til webudvikling af Rico Wind, Google
Dart - en ny platform til webudvikling af Rico Wind, Google
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Rails workshop for Java people (September 2015)
Rails workshop for Java people (September 2015)Rails workshop for Java people (September 2015)
Rails workshop for Java people (September 2015)
 
PHP Unit 4 arrays
PHP Unit 4 arraysPHP Unit 4 arrays
PHP Unit 4 arrays
 
Handout - Introduction to Programming
Handout - Introduction to ProgrammingHandout - Introduction to Programming
Handout - Introduction to Programming
 

Viewers also liked

Viewers also liked (8)

Value Objects
Value ObjectsValue Objects
Value Objects
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara Hacopian
 
#pugMi - DDD - Value objects
#pugMi - DDD - Value objects#pugMi - DDD - Value objects
#pugMi - DDD - Value objects
 
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
 
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progressValue objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progress
 
Persisting Value Objects
Persisting Value ObjectsPersisting Value Objects
Persisting Value Objects
 
A System Is Not a Tree
A System Is Not a TreeA System Is Not a Tree
A System Is Not a Tree
 
Aggregates, Entities and Value objects - Devnology 2010 community day
Aggregates, Entities and Value objects - Devnology 2010 community dayAggregates, Entities and Value objects - Devnology 2010 community day
Aggregates, Entities and Value objects - Devnology 2010 community day
 

Similar to Values

Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101
Nando Vieira
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
Edgar Suarez
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
Wen-Tien Chang
 
Coffeescript a z
Coffeescript a zCoffeescript a z
Coffeescript a z
Starbuildr
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
intelliyole
 

Similar to Values (20)

Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
Language supports it
Language supports itLanguage supports it
Language supports it
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Coffeescript a z
Coffeescript a zCoffeescript a z
Coffeescript a z
 
Elegant objects
Elegant objectsElegant objects
Elegant objects
 
Ruby basic3
Ruby basic3Ruby basic3
Ruby basic3
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
Fog City Ruby - Triple Equals Black Magic
Fog City Ruby - Triple Equals Black MagicFog City Ruby - Triple Equals Black Magic
Fog City Ruby - Triple Equals Black Magic
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby Basics
 
Lecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of Twente
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

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
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
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
 
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
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
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
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 

Values