SlideShare ist ein Scribd-Unternehmen logo
1 von 37
Interface Versioning in C++
Steve Love
ACCU London October 2010
Interface Versioning in C++
The problem
One library, many clients
Recompilation causes redeployment
Synchronising release cycles is painful
Quarantined release environments are prone to error
Copyright (c) Steve Love 2010 Interface Versioning in C++
The goal
Design a library that:
1 Can grow as requirements arise
2 Doesn’t force redeployment of clients every
upgrade
3 Is easy to use without undue effort
Dependency Management
Requires a loosening of the coupling between the
library and its clients
Copyright (c) Steve Love 2010 Interface Versioning in C++
Cause and effect
Changes to a class cause clients to recompile when:
Public member functions change
Base class list is changed
Data members change
Protected and Private member functions change
#pragma once
namespace inventory
{
class part
{
public:
unsigned id() const;
private:
unsigned num;
};
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Solution
Hide changes behind an interface
#pragma once
namespace inventory
{
class part
{
public:
virtual ~part();
virtual int id() const = 0;
};
part * create_part();
}
#include "part.h"
namespace
{
class realpart : public inventory::part
{
public:
realpart();
int id() const;
private:
int num;
};
}
namespace inventory
{
part * create_part()
{
return new realpart;
}
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Indirectly
Interfaces are only part of the solution...
Public member functions change
Base class list is changed
Data members change
Protected and Private member functions change
Copyright (c) Steve Love 2010 Interface Versioning in C++
A false hope
Necessity and sufficiency
Interfaces are vital
...but not sufficient on their own
Padding interfaces at the bottom
...is common.
But wrong.
Copyright (c) Steve Love 2010 Interface Versioning in C++
Why not?
class properties
{
public:
virtual int integer() const { return 0; }
virtual double floatingpoint() const { return 0; }
};
int main()
{
properties p;
}
cl /EHsc /FAs test.cpp
??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’
DD FLAT:?integer@properties@@UBEHXZ
DD FLAT:?floatingpoint@properties@@UAENXZ
; Function compile flags: /Odtp
Copyright (c) Steve Love 2010 Interface Versioning in C++
Changed interface
class properties
{
public:
virtual int integer() const { return 0; }
virtual double floatingpoint() const { return 0; }
virtual void integer( int ) { }
virtual void floatingpoint( double ) { }
};
int main()
{
properties p;
}
cl /EHsc /FAs test.cpp
Copyright (c) Steve Love 2010 Interface Versioning in C++
The result
Old:
??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’
DD FLAT:?integer@properties@@UBEHXZ
DD FLAT:?floatingpoint@properties@@UAENXZ
; Function compile flags: /Odtp
New:
??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’
DD FLAT:?integer@properties@@UAEXH@Z
DD FLAT:?integer@properties@@UBEHXZ
DD FLAT:?floatingpoint@properties@@UAEXN@Z
DD FLAT:?floatingpoint@properties@@UAENXZ
; Function compile flags: /Odtp
Copyright (c) Steve Love 2010 Interface Versioning in C++
The true path
Old new thing
Adding a method to an interface is bad.
Adding a new interface to a library is benign.
Copyright (c) Steve Love 2010 Interface Versioning in C++
Simple interfaces
#pragma once
#include <string>
namespace inventory
{
class part
{
public:
virtual ~part();
virtual unsigned id() const = 0;
virtual const std::string & name()
const = 0;
};
part * create_part();
}
#include <part.h>
#include <iostream>
#include <memory>
// Also link to inventory.lib
int main()
{
using namespace std;
using namespace inventory;
unique_ptr< part > p( create_part() );
cout << p->id() << endl;
cout << p->name() << endl;
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Extended interface
#pragma once
#include <string>
namespace inventory
{
class part
{
public:
virtual ~part();
virtual unsigned id() const = 0;
virtual const std::string & name()
const = 0;
};
class part_v2 : public part
{
public:
using part::id;
using part::name;
virtual void id( unsigned val ) = 0;
virtual void name( const std::string
& val ) = 0;
};
part * create_part();
}
#include <part.h>
#include <iostream>
#include <memory>
// Also link to inventory.lib
int main()
{
using namespace std;
using namespace inventory;
unique_ptr< part_v2 > p( dynamic_cast<
part_v2* >( create_part() ) );
p->id( 100 );
p->name( "wingnut" );
cout << p->id() << endl;
cout << p->name() << endl;
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Implementing part_v2
#include "part.h"
namespace
{
class realpart : public inventory::part_v2
{
public:
realpart();
unsigned id() const;
const std::string & name() const;
void id( unsigned val );
void name( const std::string & val );
private:
unsigned num;
std::string namestr;
};
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Wrong turn!
#include <string>
class part
{
public:
virtual int id() const = 0;
virtual const std::string & name() const = 0;
};
class part_v2 : public part
{
public:
virtual void id( int val ) = 0;
virtual void name( const std::string & val ) = 0;
};
It’s not the interface that’s the problem...
Copyright (c) Steve Love 2010 Interface Versioning in C++
v1 and v2 side-by-side
...it’s the implementation.
class realpart : public part
{
public:
int id() const { return num; }
const std::string & name() const { return namestr; }
private:
int num;
std::string namestr;
};
class realpart_v2 : public part_v2
{
public:
int id() const { return num; }
const std::string & name() const { return namestr; }
void id( int val ) { }
void name( const std::string & val ) { }
private:
int num;
std::string namestr;
};
Copyright (c) Steve Love 2010 Interface Versioning in C++
More vtables
??_7realpart@@6B@ DD FLAT:??_R4realpart@@6B@ ; realpart::‘vftable’
DD FLAT:?id@realpart@@UBEHXZ
DD FLAT:?
name@realpart@@UBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ
; Function compile flags: /Odtp
??_7realpart_v2@@6B@ DD FLAT:??_R4realpart_v2@@6B@ ; realpart_v2::‘vftable’
DD FLAT:?id@realpart_v2@@UBEHXZ
DD FLAT:?
name@realpart_v2@@UBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ
DD FLAT:?id@realpart_v2@@UAEXH@Z
DD FLAT:?
name@realpart_v2@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
; Function compile flags: /Odtp
DANGER!
This will appear to work, but depends on the
implementation
Copyright (c) Steve Love 2010 Interface Versioning in C++
Split the implementations
#include "part.h"
namespace
{
class realpart : public inventory::part
{
public:
realpart();
unsigned id() const;
const std::string & name() const;
protected:
unsigned num;
std::string namestr;
};
class realpart_v2 : public inventory::part_v2, public
realpart
{
public:
using part::id;
using part::name;
void id( unsigned val );
void name( const std::string & val );
};
namespace inventory
{
part::~part()
{
}
part * create_part()
{
return new realpart_v2;
}
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Split the implementations
#include "part.h"
namespace
{
class realpart : public inventory::part
{
public:
realpart();
unsigned id() const;
const std::string & name() const;
protected:
unsigned num;
std::string namestr;
};
class realpart_v2 : public inventory::part_v2, public
realpart
{
public:
using part::id;
using part::name;
void id( unsigned val );
void name( const std::string & val );
};
namespace inventory
{
part::~part()
{
}
part * create_part()
{
return new realpart_v2;
}
}
...except...
it doesn’t compile!
Copyright (c) Steve Love 2010 Interface Versioning in C++
Ambiguity
Copyright (c) Steve Love 2010 Interface Versioning in C++
Resolved
#pragma once
#include <string>
namespace inventory
{
class part
{
};
class part_v2 : public virtual part
{
};
}
#include "part.h"
namespace
{
class realpart : public virtual inventory::part
{
};
class realpart_v2 : public virtual inventory::part_v2, public realpart
{
};
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Finishing polish
Names have power
namespace inventory
{
class part
{
};
class part_v2 : public virtual part
{
};
part * create_part();
}
The factory returns a part.
Changing this breaks the ABI (ODR).
Clients of part_v2 must now find all references to
“part”, and use the factory like this:
unique_ptr< part_v2 > p( dynamic_cast< part_v2* >( create_part() ) );
Copyright (c) Steve Love 2010 Interface Versioning in C++
Called by a common name
Class part becomes class part_v1
typedef part_v1 * part;
Copyright (c) Steve Love 2010 Interface Versioning in C++
Called by a common name
Class part becomes class part_v1
typedef part_v1 * part;
Or, even better....
#include "part_v1.h"
#include <memory>
namespace inventory
{
typedef part_v1 part_current;
typedef std::unique_ptr< part_current > part;
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
No more casts
namespace inventory
{
INVENTORY_LIB part_v1 * create_part_ptr();
template< typename type_version >
part create_part()
{
return part( static_cast< type_version * >( create_part_ptr() ) );
}
}
#include <part_factory.h>
#include <iostream>
int main()
{
using namespace std;
using namespace inventory;
part p = create_part< part_current >();
cout << p->number() << endl;
cout << p->name() << endl;
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Version up!
New interface
namespace inventory
{
class INVENTORY_LIB part_v2 : public virtual part_v1
{
};
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
The real thing
New implementation
#include <part_v2.h>
namespace inventory_impl
{
class realpart_v2 : public virtual inventory::part_v2, public realpart_v1
{
};
}
Update factory
namespace inventory
{
using namespace inventory_impl;
INVENTORY_LIB part_v1 * create_part_ptr()
{
return new realpart_v2;
}
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Status quo
Update the typedef
namespace inventory
{
typedef part_v2 part_current;
typedef std::unique_ptr< part_current > part;
}
The template factory stays the same
#include <part.h>
namespace inventory
{
INVENTORY_LIB part_v1 * create_part_ptr();
template< typename type_version >
part create_part()
{
return part( static_cast< type_version * >( create_part_ptr() ) );
}
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
The client
V1
#include <part_factory.h>
#include <iostream>
int main()
{
using namespace std;
using namespace inventory;
part p = create_part< part_current >();
cout << p->number() << endl;
cout << p->name() << endl;
}
v2
#include <part_factory.h>
#include <iostream>
int main()
{
using namespace std;
using namespace inventory;
part p = create_part< part_current >();
p->number( 100 );
p->name( "steve" );
cout << p->number() << endl;
cout << p->name() << endl;
}
Copyright (c) Steve Love 2010 Interface Versioning in C++
Dependency management
Code that has objects passed to it
(i.e. does not need to create objects)
should have no dependency on the factory.
Paramaterize from Above
and all that
Copyright (c) Steve Love 2010 Interface Versioning in C++
Divide and conquer
IINVENTORY.DLL
Headers for part_v1/v2
Implementation file for
part_v1
The part type and
part_current typedef
INVENTORY_IMPL.DLL
Headers and
implementation of
realpart
The factory
Copyright (c) Steve Love 2010 Interface Versioning in C++
In other words...
Copyright (c) Steve Love 2010 Interface Versioning in C++
Justifying the means
The means
An extensible, safe and conforming way of extending
interfaces without causing clients to redeploy.
The end
Loosening the coupling between the library and its
clients.
Copyright (c) Steve Love 2010 Interface Versioning in C++

Weitere ähnliche Inhalte

Was ist angesagt?

NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
tcaesvk
 
3150 Chapter 2 Part 1
3150 Chapter 2 Part 13150 Chapter 2 Part 1
3150 Chapter 2 Part 1
Mole Wong
 
OOP in C - Before GObject (Chinese Version)
OOP in C - Before GObject (Chinese Version)OOP in C - Before GObject (Chinese Version)
OOP in C - Before GObject (Chinese Version)
Kai-Feng Chou
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009
Deepak Singh
 
OOP in C - Inherit (Chinese Version)
OOP in C - Inherit (Chinese Version)OOP in C - Inherit (Chinese Version)
OOP in C - Inherit (Chinese Version)
Kai-Feng Chou
 
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
Olve Maudal
 

Was ist angesagt? (20)

Analyzing FreeCAD's Source Code and Its "Sick" Dependencies
Analyzing FreeCAD's Source Code and Its "Sick" DependenciesAnalyzing FreeCAD's Source Code and Its "Sick" Dependencies
Analyzing FreeCAD's Source Code and Its "Sick" Dependencies
 
NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
 
Solid C++ by Example
Solid C++ by ExampleSolid C++ by Example
Solid C++ by Example
 
Open source report writing tools for IBM i Vienna 2012
Open source report writing tools for IBM i  Vienna 2012Open source report writing tools for IBM i  Vienna 2012
Open source report writing tools for IBM i Vienna 2012
 
Log4 J
Log4 JLog4 J
Log4 J
 
Automatically Documenting Program Changes
Automatically Documenting Program ChangesAutomatically Documenting Program Changes
Automatically Documenting Program Changes
 
It's complicated, but it doesn't have to be: a Dagger journey
It's complicated, but it doesn't have to be: a Dagger journeyIt's complicated, but it doesn't have to be: a Dagger journey
It's complicated, but it doesn't have to be: a Dagger journey
 
Insecure coding in C (and C++)
Insecure coding in C (and C++)Insecure coding in C (and C++)
Insecure coding in C (and C++)
 
3150 Chapter 2 Part 1
3150 Chapter 2 Part 13150 Chapter 2 Part 1
3150 Chapter 2 Part 1
 
C# Variables and Operators
C# Variables and OperatorsC# Variables and Operators
C# Variables and Operators
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
introduction of c langauge(I unit)
introduction of c langauge(I unit)introduction of c langauge(I unit)
introduction of c langauge(I unit)
 
OOP in C - Before GObject (Chinese Version)
OOP in C - Before GObject (Chinese Version)OOP in C - Before GObject (Chinese Version)
OOP in C - Before GObject (Chinese Version)
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009
 
OOP in C - Inherit (Chinese Version)
OOP in C - Inherit (Chinese Version)OOP in C - Inherit (Chinese Version)
OOP in C - Inherit (Chinese Version)
 
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
 
P/Invoke - Interoperability of C++ and C#
P/Invoke - Interoperability of C++ and C#P/Invoke - Interoperability of C++ and C#
P/Invoke - Interoperability of C++ and C#
 
Qno1
Qno1Qno1
Qno1
 

Andere mochten auch (10)

An Introduction To Palomino
An Introduction To PalominoAn Introduction To Palomino
An Introduction To Palomino
 
Martin Strýček - Ako začať s MongoDB
Martin Strýček - Ako začať s MongoDBMartin Strýček - Ako začať s MongoDB
Martin Strýček - Ako začať s MongoDB
 
C++: Interface as Concept
C++: Interface as ConceptC++: Interface as Concept
C++: Interface as Concept
 
XAMPP
XAMPPXAMPP
XAMPP
 
Recruiting for diversity in tech
Recruiting for diversity in techRecruiting for diversity in tech
Recruiting for diversity in tech
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
 
Intro to C++ - language
Intro to C++ - languageIntro to C++ - language
Intro to C++ - language
 
Moved to Speakerdeck
Moved to SpeakerdeckMoved to Speakerdeck
Moved to Speakerdeck
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operator
 
C++ Inheritance
C++ InheritanceC++ Inheritance
C++ Inheritance
 

Ähnlich wie C++ Interface Versioning

Visual studio 2008
Visual studio 2008Visual studio 2008
Visual studio 2008
Luis Enrique
 
Chapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-classChapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-class
Deepak Singh
 
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
Thomas Conté
 
Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your code
vmandrychenko
 

Ähnlich wie C++ Interface Versioning (20)

Visual studio 2008
Visual studio 2008Visual studio 2008
Visual studio 2008
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 
1z0 804 exam-java se 7 programmer ii
1z0 804 exam-java se 7 programmer ii1z0 804 exam-java se 7 programmer ii
1z0 804 exam-java se 7 programmer ii
 
Chapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-classChapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-class
 
C# Tutorial MSM_Murach chapter-14-slides
C# Tutorial MSM_Murach chapter-14-slidesC# Tutorial MSM_Murach chapter-14-slides
C# Tutorial MSM_Murach chapter-14-slides
 
CAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptxCAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptx
 
Virtual Function and Polymorphism.ppt
Virtual Function and Polymorphism.pptVirtual Function and Polymorphism.ppt
Virtual Function and Polymorphism.ppt
 
Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)
 
C++ Overview PPT
C++ Overview PPTC++ Overview PPT
C++ Overview PPT
 
C++
C++C++
C++
 
Cleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsCleaning your architecture with android architecture components
Cleaning your architecture with android architecture components
 
Oops lecture 1
Oops lecture 1Oops lecture 1
Oops lecture 1
 
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
MS Day EPITA 2010: Visual Studio 2010 et Framework .NET 4.0
 
2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta
 
High performance web programming with C++14
High performance web programming with C++14High performance web programming with C++14
High performance web programming with C++14
 
C++ Programming
C++ ProgrammingC++ Programming
C++ Programming
 
Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your code
 
C++ 11 Features
C++ 11 FeaturesC++ 11 Features
C++ 11 Features
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projects
 
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
 

Mehr von Skills Matter

Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheim
Skills Matter
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
Skills Matter
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_t
Skills Matter
 

Mehr von Skills Matter (20)

5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmScala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
 
Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheim
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlCukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberl
 
Cukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsCukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.js
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldProgressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source world
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
 
Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#
 
A poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingA poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testing
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
 
Serendipity-neo4j
Serendipity-neo4jSerendipity-neo4j
Serendipity-neo4j
 
Simon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSimon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelism
 
Plug 20110217
Plug   20110217Plug   20110217
Plug 20110217
 
Lug presentation
Lug presentationLug presentation
Lug presentation
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_t
 
Plug saiku
Plug   saikuPlug   saiku
Plug saiku
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

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...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
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...
 
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
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
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
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
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...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
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...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 

C++ Interface Versioning

  • 1. Interface Versioning in C++ Steve Love ACCU London October 2010 Interface Versioning in C++
  • 3. One library, many clients Recompilation causes redeployment Synchronising release cycles is painful Quarantined release environments are prone to error Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 4. The goal Design a library that: 1 Can grow as requirements arise 2 Doesn’t force redeployment of clients every upgrade 3 Is easy to use without undue effort Dependency Management Requires a loosening of the coupling between the library and its clients Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 5. Cause and effect Changes to a class cause clients to recompile when: Public member functions change Base class list is changed Data members change Protected and Private member functions change #pragma once namespace inventory { class part { public: unsigned id() const; private: unsigned num; }; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 6. Solution Hide changes behind an interface #pragma once namespace inventory { class part { public: virtual ~part(); virtual int id() const = 0; }; part * create_part(); } #include "part.h" namespace { class realpart : public inventory::part { public: realpart(); int id() const; private: int num; }; } namespace inventory { part * create_part() { return new realpart; } } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 7. Indirectly Interfaces are only part of the solution... Public member functions change Base class list is changed Data members change Protected and Private member functions change Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 9. Necessity and sufficiency Interfaces are vital ...but not sufficient on their own Padding interfaces at the bottom ...is common. But wrong. Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 10. Why not? class properties { public: virtual int integer() const { return 0; } virtual double floatingpoint() const { return 0; } }; int main() { properties p; } cl /EHsc /FAs test.cpp ??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’ DD FLAT:?integer@properties@@UBEHXZ DD FLAT:?floatingpoint@properties@@UAENXZ ; Function compile flags: /Odtp Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 11. Changed interface class properties { public: virtual int integer() const { return 0; } virtual double floatingpoint() const { return 0; } virtual void integer( int ) { } virtual void floatingpoint( double ) { } }; int main() { properties p; } cl /EHsc /FAs test.cpp Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 12. The result Old: ??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’ DD FLAT:?integer@properties@@UBEHXZ DD FLAT:?floatingpoint@properties@@UAENXZ ; Function compile flags: /Odtp New: ??_7properties@@6B@ DD FLAT:??_R4properties@@6B@ ; properties::‘vftable’ DD FLAT:?integer@properties@@UAEXH@Z DD FLAT:?integer@properties@@UBEHXZ DD FLAT:?floatingpoint@properties@@UAEXN@Z DD FLAT:?floatingpoint@properties@@UAENXZ ; Function compile flags: /Odtp Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 14. Old new thing Adding a method to an interface is bad. Adding a new interface to a library is benign. Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 15. Simple interfaces #pragma once #include <string> namespace inventory { class part { public: virtual ~part(); virtual unsigned id() const = 0; virtual const std::string & name() const = 0; }; part * create_part(); } #include <part.h> #include <iostream> #include <memory> // Also link to inventory.lib int main() { using namespace std; using namespace inventory; unique_ptr< part > p( create_part() ); cout << p->id() << endl; cout << p->name() << endl; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 16. Extended interface #pragma once #include <string> namespace inventory { class part { public: virtual ~part(); virtual unsigned id() const = 0; virtual const std::string & name() const = 0; }; class part_v2 : public part { public: using part::id; using part::name; virtual void id( unsigned val ) = 0; virtual void name( const std::string & val ) = 0; }; part * create_part(); } #include <part.h> #include <iostream> #include <memory> // Also link to inventory.lib int main() { using namespace std; using namespace inventory; unique_ptr< part_v2 > p( dynamic_cast< part_v2* >( create_part() ) ); p->id( 100 ); p->name( "wingnut" ); cout << p->id() << endl; cout << p->name() << endl; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 17. Implementing part_v2 #include "part.h" namespace { class realpart : public inventory::part_v2 { public: realpart(); unsigned id() const; const std::string & name() const; void id( unsigned val ); void name( const std::string & val ); private: unsigned num; std::string namestr; }; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 18. Wrong turn! #include <string> class part { public: virtual int id() const = 0; virtual const std::string & name() const = 0; }; class part_v2 : public part { public: virtual void id( int val ) = 0; virtual void name( const std::string & val ) = 0; }; It’s not the interface that’s the problem... Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 19. v1 and v2 side-by-side ...it’s the implementation. class realpart : public part { public: int id() const { return num; } const std::string & name() const { return namestr; } private: int num; std::string namestr; }; class realpart_v2 : public part_v2 { public: int id() const { return num; } const std::string & name() const { return namestr; } void id( int val ) { } void name( const std::string & val ) { } private: int num; std::string namestr; }; Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 20. More vtables ??_7realpart@@6B@ DD FLAT:??_R4realpart@@6B@ ; realpart::‘vftable’ DD FLAT:?id@realpart@@UBEHXZ DD FLAT:? name@realpart@@UBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ ; Function compile flags: /Odtp ??_7realpart_v2@@6B@ DD FLAT:??_R4realpart_v2@@6B@ ; realpart_v2::‘vftable’ DD FLAT:?id@realpart_v2@@UBEHXZ DD FLAT:? name@realpart_v2@@UBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ DD FLAT:?id@realpart_v2@@UAEXH@Z DD FLAT:? name@realpart_v2@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z ; Function compile flags: /Odtp DANGER! This will appear to work, but depends on the implementation Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 21. Split the implementations #include "part.h" namespace { class realpart : public inventory::part { public: realpart(); unsigned id() const; const std::string & name() const; protected: unsigned num; std::string namestr; }; class realpart_v2 : public inventory::part_v2, public realpart { public: using part::id; using part::name; void id( unsigned val ); void name( const std::string & val ); }; namespace inventory { part::~part() { } part * create_part() { return new realpart_v2; } } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 22. Split the implementations #include "part.h" namespace { class realpart : public inventory::part { public: realpart(); unsigned id() const; const std::string & name() const; protected: unsigned num; std::string namestr; }; class realpart_v2 : public inventory::part_v2, public realpart { public: using part::id; using part::name; void id( unsigned val ); void name( const std::string & val ); }; namespace inventory { part::~part() { } part * create_part() { return new realpart_v2; } } ...except... it doesn’t compile! Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 23. Ambiguity Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 24. Resolved #pragma once #include <string> namespace inventory { class part { }; class part_v2 : public virtual part { }; } #include "part.h" namespace { class realpart : public virtual inventory::part { }; class realpart_v2 : public virtual inventory::part_v2, public realpart { }; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 26. Names have power namespace inventory { class part { }; class part_v2 : public virtual part { }; part * create_part(); } The factory returns a part. Changing this breaks the ABI (ODR). Clients of part_v2 must now find all references to “part”, and use the factory like this: unique_ptr< part_v2 > p( dynamic_cast< part_v2* >( create_part() ) ); Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 27. Called by a common name Class part becomes class part_v1 typedef part_v1 * part; Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 28. Called by a common name Class part becomes class part_v1 typedef part_v1 * part; Or, even better.... #include "part_v1.h" #include <memory> namespace inventory { typedef part_v1 part_current; typedef std::unique_ptr< part_current > part; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 29. No more casts namespace inventory { INVENTORY_LIB part_v1 * create_part_ptr(); template< typename type_version > part create_part() { return part( static_cast< type_version * >( create_part_ptr() ) ); } } #include <part_factory.h> #include <iostream> int main() { using namespace std; using namespace inventory; part p = create_part< part_current >(); cout << p->number() << endl; cout << p->name() << endl; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 30. Version up! New interface namespace inventory { class INVENTORY_LIB part_v2 : public virtual part_v1 { }; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 31. The real thing New implementation #include <part_v2.h> namespace inventory_impl { class realpart_v2 : public virtual inventory::part_v2, public realpart_v1 { }; } Update factory namespace inventory { using namespace inventory_impl; INVENTORY_LIB part_v1 * create_part_ptr() { return new realpart_v2; } } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 32. Status quo Update the typedef namespace inventory { typedef part_v2 part_current; typedef std::unique_ptr< part_current > part; } The template factory stays the same #include <part.h> namespace inventory { INVENTORY_LIB part_v1 * create_part_ptr(); template< typename type_version > part create_part() { return part( static_cast< type_version * >( create_part_ptr() ) ); } } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 33. The client V1 #include <part_factory.h> #include <iostream> int main() { using namespace std; using namespace inventory; part p = create_part< part_current >(); cout << p->number() << endl; cout << p->name() << endl; } v2 #include <part_factory.h> #include <iostream> int main() { using namespace std; using namespace inventory; part p = create_part< part_current >(); p->number( 100 ); p->name( "steve" ); cout << p->number() << endl; cout << p->name() << endl; } Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 34. Dependency management Code that has objects passed to it (i.e. does not need to create objects) should have no dependency on the factory. Paramaterize from Above and all that Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 35. Divide and conquer IINVENTORY.DLL Headers for part_v1/v2 Implementation file for part_v1 The part type and part_current typedef INVENTORY_IMPL.DLL Headers and implementation of realpart The factory Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 36. In other words... Copyright (c) Steve Love 2010 Interface Versioning in C++
  • 37. Justifying the means The means An extensible, safe and conforming way of extending interfaces without causing clients to redeploy. The end Loosening the coupling between the library and its clients. Copyright (c) Steve Love 2010 Interface Versioning in C++