Skip to main content
Tweeted twitter.com/StackSoftEng/status/1323233401151827968
some links added, formatting improved, final question more focussed
Source Link
Doc Brown
  • 214k
  • 34
  • 394
  • 603

I'm currently developing an application using SFMLSFML. My biggest concern at the moment is making a layer of abstraction over the library, so I can easily change it to something else if needed. What I'm struggling with is designing an abstraction that's intuitive and not leakyleaky.

An example: drawing in SFML is done using drawable objects (implementing sf::Drawablesf::Drawable) and objects capable of rendering them (sf::RenderTargetsf::RenderTarget).

Say I want to wrap those and create my own IDrawableIDrawable:

class IDrawable {
public:
    virtual void draw(IRenderTarget& target) const = 0;
};

Even though it looks nice, in order for the concrete classes to achieve their goal, they somehow still need to exchange information specific to SFML, i.e. IRenderTargetIRenderTarget has to declare an abstraction breaking method, such as

virtual sf::RenderTarget& impl() = 0;

The only solution I can think of is creating concrete classes that require all library-specific parts to be passed via constructor, so there's no cross-class communication of library-specific data. This way, IDrawableIDrawable would change to:

class IDrawable {
public:
    virtual void draw() = 0;
}; 

Another solution would be abusing the friending mechanism, but I guess that's not great, either.

In other words -- areis there any general guidelinesan approach for wrapping a 3rd party library, so that the created abstraction is not leaky (doesn't require public accessor methods that break the encapsulation)?

I'm currently developing an application using SFML. My biggest concern at the moment is making a layer of abstraction over the library, so I can easily change it to something else if needed. What I'm struggling with is designing an abstraction that's intuitive and not leaky.

An example: drawing in SFML is done using drawable objects (implementing sf::Drawable) and objects capable of rendering them (sf::RenderTarget).

Say I want to wrap those and create my own IDrawable:

class IDrawable {
public:
    virtual void draw(IRenderTarget& target) const = 0;
};

Even though it looks nice, in order for the concrete classes to achieve their goal, they somehow still need to exchange information specific to SFML, i.e. IRenderTarget has to declare an abstraction breaking method, such as

virtual sf::RenderTarget& impl() = 0;

The only solution I can think of is creating concrete classes that require all library-specific parts to be passed via constructor, so there's no cross-class communication of library-specific data. This way, IDrawable would change to:

class IDrawable {
public:
    virtual void draw() = 0;
}; 

Another solution would be abusing the friending mechanism, but I guess that's not great, either.

In other words -- are there any general guidelines for wrapping a 3rd party library, so that the created abstraction is not leaky (doesn't require public accessor methods that break the encapsulation)?

I'm currently developing an application using SFML. My biggest concern at the moment is making a layer of abstraction over the library, so I can easily change it to something else if needed. What I'm struggling with is designing an abstraction that's intuitive and not leaky.

An example: drawing in SFML is done using drawable objects (implementing sf::Drawable) and objects capable of rendering them (sf::RenderTarget).

Say I want to wrap those and create my own IDrawable:

class IDrawable {
public:
    virtual void draw(IRenderTarget& target) const = 0;
};

Even though it looks nice, in order for the concrete classes to achieve their goal, they somehow still need to exchange information specific to SFML, i.e. IRenderTarget has to declare an abstraction breaking method, such as

virtual sf::RenderTarget& impl() = 0;

The only solution I can think of is creating concrete classes that require all library-specific parts to be passed via constructor, so there's no cross-class communication of library-specific data. This way, IDrawable would change to:

class IDrawable {
public:
    virtual void draw() = 0;
}; 

Another solution would be abusing the friending mechanism, but I guess that's not great, either.

In other words -- is there an approach for wrapping a 3rd party library, so that the created abstraction is not leaky (doesn't require public accessor methods that break the encapsulation)?

Source Link
mdx
  • 213
  • 1
  • 4

Wrapping 3rd party library - avoiding leaking abstraction

I'm currently developing an application using SFML. My biggest concern at the moment is making a layer of abstraction over the library, so I can easily change it to something else if needed. What I'm struggling with is designing an abstraction that's intuitive and not leaky.

An example: drawing in SFML is done using drawable objects (implementing sf::Drawable) and objects capable of rendering them (sf::RenderTarget).

Say I want to wrap those and create my own IDrawable:

class IDrawable {
public:
    virtual void draw(IRenderTarget& target) const = 0;
};

Even though it looks nice, in order for the concrete classes to achieve their goal, they somehow still need to exchange information specific to SFML, i.e. IRenderTarget has to declare an abstraction breaking method, such as

virtual sf::RenderTarget& impl() = 0;

The only solution I can think of is creating concrete classes that require all library-specific parts to be passed via constructor, so there's no cross-class communication of library-specific data. This way, IDrawable would change to:

class IDrawable {
public:
    virtual void draw() = 0;
}; 

Another solution would be abusing the friending mechanism, but I guess that's not great, either.

In other words -- are there any general guidelines for wrapping a 3rd party library, so that the created abstraction is not leaky (doesn't require public accessor methods that break the encapsulation)?