PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.cplus > Library design opinions...
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Library design opinions...

Réponse
 
LinkBack Outils de la discussion
Vieux 27/06/2008, 08h09   #1
rep_movsd
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Library design opinions...

Hi

I have developed a simple free library that is used for creating and
managing Directshow filter graphs, that I (and possibly several
others ) have been using for more than a year now...

Recently I thought of rewriting it with a more "intuitive" usage style
( mostly to satisfy my desire to play with template metaprogramming ),
and gain a bit of static error checking ( and making the user code
look like magic )

Heres some equivalent code for the old and new libraries ( its a bit
specific to the dshow framework, but it is fairly obvious what the
code does, also all the includes etc have been omitted )

Old library usage :
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void BuildGraph(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERER");
g.Connect(L"TEE", L"RENDERER2", 1, 0); // connect 2nd output pin
of tee to renderer2's first pin
}

void BuildGraphBad(CGraph &g)
{
g.Connect(L"SOURCE", L"TEE");
g.Connect(L"TEE", L"RENDERERER"); // Runtime error "filter
not found "
g.Connect(L"TEE", L"RENDERER2", 1, 0);
}

int main(int argc, char **argv)
{
CGraph g;
g.AddSourceFilter(argv[1], L"SOURCE"); // Create a source
filter based on filename
g.AddFilter(CLSID_InfTee, L"TEE"); // Create a Tee
g.AddFilter(CLSID_VideoRenderer, L"RENDERER"); // Create
renderers
g.AddFilter(CLSID_VideoRenderer, L"RENDERER2");
BuildGraph(g);
BuildGraphBad(g);
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////


New library usage:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DECLARE_FILTER(SOURCE);
DECLARE_FILTER(TEE);
DECLARE_FILTER(RENDERER);
DECLARE_FILTER(RENDERER2);

void BuildGraph()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);

SOURCE >> TEE >> RENDERER; // Chain the filters
TEE >> RENDERER2; // Add an extra renderer
}

void BuildGraphBad()
{
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERERER); // Misspelling - compile error

SOURCE >> TEE >> RENDERER; // Compile error
}

int main(int argc, char **argv)
{
CGraf g;
FILTER(SOURCE);
FILTER(TEE);
FILTER(RENDERER);
FILTER(RENDERER2);

SOURCE = argv[1]; // Create a source filter
based on filename
TEE = CLSID_InfTee; // Create filters based on
CLSIDs
RENDERER = CLSID_VideoRenderer;
RENDERER2 = CLSID_VideoRenderer;

g += SOURCE, TEE, RENDERER, RENDERER2; // FIlters get added to the
graph
BuildGraph();
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Some of the advantages of the new style are :
1) FIlter names are identifiers, so u get intellisense and compile
time checking
2) A filter with a given name always refers to the same object, so
there is no need to store a bunch of pointers to filter objects and
pass them around various functions ( or worse yet keep them global as
most directshow code does )
3) The operator overloading makes the code very readable,

The only disadvantage I see is that the implementation is complex and
I am not 100% confident that my code is perfect.

I was wondering to overload the unary minus operator to remove
filters from the graph and the divide by operator to disconnect
filters. I would also add some manipulator stuff ( like in iostreams)
to control the way filters are
connected with >> e.g.

// Remove renderer2 from graph
g -= RENDERER2;

// Connect the first audio pin of the source to the renderer
SOURCE >> pinType(MEDIATYPE_Audio) >> AUDIORENDER;

// Disconnect any connection betwen these 2 filters
SOURCE / AUDIORENDER;

Any opinions, suggestions?

Vivek
  Réponse avec citation
Vieux 27/06/2008, 08h12   #2
Alf P. Steinbach
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

* rep_movsd:
> Hi
>
> Any opinions, suggestions?


Please don't shout[1].


Cheers,

- Alf


Notes:
[1] That means, the all uppercase. Are those really macros? If so, get rid of them.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
  Réponse avec citation
Vieux 27/06/2008, 08h16   #3
rep_movsd
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

> Notes:
> [1] That means, the all uppercase. Are those really macros? If so, get rid of them.


FILTER and DECLARE_FILTER are macros...
The rest are identifiers....

  Réponse avec citation
Vieux 27/06/2008, 11h06   #4
Boris
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

On Fri, 27 Jun 2008 09:09:18 +0200, rep_movsd <rep.movsd@gmail.com> wrote:

> [...]Recently I thought of rewriting it with a more "intuitive" usage
> style
> ( mostly to satisfy my desire to play with template metaprogramming ),
> and gain a bit of static error checking ( and making the user code
> look like magic )


Your new code doesn't look like magic to me - it looks more like it has
been deliberately obfuscated. Once you start using the library in another
use case where you don't do exactly what is explained in the documentation
you have to fiddle around with all the macros trying to understand what's
going on there in detail. It's more useful to know what is a class, a
function, an object etc. as every C++ programmer understands then
immediately what they can do.

Boris

> [...]

  Réponse avec citation
Vieux 27/06/2008, 12h08   #5
rep_movsd
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

On Jun 27, 1:06pm, Boris <bor...@web.de> wrote:

> Your new code doesn't look like magic to me - it looks more like it has
> been deliberately obfuscated. Once you start using the library in another
> use case where you don't do exactly what is explained in the documentation
> you have to fiddle around with all the macros trying to understand what's
> going on there in detail. It's more useful to know what is a class, a
> function, an object etc. as every C++ programmer understands then
> immediately what they can do.
>
> Boris


Yes, I agree that the declaration macros have quite complex
implementations and are opaque, But what about the use of overloaded
operators to make the connections etc?
Does that look bad too?

Vivek
  Réponse avec citation
Vieux 27/06/2008, 13h05   #6
Boris
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

On Fri, 27 Jun 2008 13:08:01 +0200, rep_movsd <rep.movsd@gmail.com> wrote:

> [...]Yes, I agree that the declaration macros have quite complex
> implementations and are opaque, But what about the use of overloaded
> operators to make the connections etc?
> Does that look bad too?


I try either to reuse an idea from the standard (for example everybody has
an idea what operator<< and operator>> do because of streams) or make sure
that the usage of operators feels natural (which might be more difficult
as what is natural for me might not be natural for someone else). Your
library seems to use operator>> to chain filters and operator+= to add
filters? I probably wouldn't use overloaded operators here: operator>>
makes me think that there is a data flow while in fact it's just a
chaining of filters (if it was a lambda function it would make more sense
maybe . And when operator+= is overloaded you wonder if and how
operator+ fits into the schema.

Boris
  Réponse avec citation
Vieux 27/06/2008, 13h45   #7
Looney
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

On Jun 27, 5:09 pm, rep_movsd <rep.mo...@gmail.com> wrote:
> Hi
>
> I have developed a simple free library that is used for creating and
> managing Directshow filter graphs, that I (and possibly several
> others ) have been using for more than a year now...
>
> Recently I thought of rewriting it with a more "intuitive" usage style
> ( mostly to satisfy my desire to play with template metaprogramming ),
> and gain a bit of static error checking ( and making the user code
> look like magic )
>
> Heres some equivalent code for the old and new libraries ( its a bit
> specific to the dshow framework, but it is fairly obvious what the
> code does, also all the includes etc have been omitted )
>
> Old library usage :
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
>
> void BuildGraph(CGraph &g)
> {
> g.Connect(L"SOURCE", L"TEE");
> g.Connect(L"TEE", L"RENDERER");
> g.Connect(L"TEE", L"RENDERER2", 1, 0); // connect 2nd output pin
> of tee to renderer2's first pin
>
> }
>
> void BuildGraphBad(CGraph &g)
> {
> g.Connect(L"SOURCE", L"TEE");
> g.Connect(L"TEE", L"RENDERERER"); // Runtime error "filter
> not found "
> g.Connect(L"TEE", L"RENDERER2", 1, 0);
>
> }
>
> int main(int argc, char **argv)
> {
> CGraph g;
> g.AddSourceFilter(argv[1], L"SOURCE"); // Create a source
> filter based on filename
> g.AddFilter(CLSID_InfTee, L"TEE"); // Create a Tee
> g.AddFilter(CLSID_VideoRenderer, L"RENDERER"); // Create
> renderers
> g.AddFilter(CLSID_VideoRenderer, L"RENDERER2");
> BuildGraph(g);
> BuildGraphBad(g);
>
> };
>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
>
> New library usage:
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
>
> DECLARE_FILTER(SOURCE);
> DECLARE_FILTER(TEE);
> DECLARE_FILTER(RENDERER);
> DECLARE_FILTER(RENDERER2);
>
> void BuildGraph()
> {
> FILTER(SOURCE);
> FILTER(TEE);
> FILTER(RENDERER);
> FILTER(RENDERER2);
>
> SOURCE >> TEE >> RENDERER; // Chain the filters
> TEE >> RENDERER2; // Add an extra renderer
>
> }
>
> void BuildGraphBad()
> {
> FILTER(SOURCE);
> FILTER(TEE);
> FILTER(RENDERERER); // Misspelling - compile error
>
> SOURCE >> TEE >> RENDERER; // Compile error
>
> }
>
> int main(int argc, char **argv)
> {
> CGraf g;
> FILTER(SOURCE);
> FILTER(TEE);
> FILTER(RENDERER);
> FILTER(RENDERER2);
>
> SOURCE = argv[1]; // Create a source filter
> based on filename
> TEE = CLSID_InfTee; // Create filters based on
> CLSIDs
> RENDERER = CLSID_VideoRenderer;
> RENDERER2 = CLSID_VideoRenderer;
>
> g += SOURCE, TEE, RENDERER, RENDERER2; // FIlters get added to the
> graph
> BuildGraph();
>
> };
>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
>
> Some of the advantages of the new style are :
> 1) FIlter names are identifiers, so u get intellisense and compile
> time checking
> 2) A filter with a given name always refers to the same object, so
> there is no need to store a bunch of pointers to filter objects and
> pass them around various functions ( or worse yet keep them global as
> most directshow code does )
> 3) The operator overloading makes the code very readable,
>
> The only disadvantage I see is that the implementation is complex and
> I am not 100% confident that my code is perfect.
>
> I was wondering to overload the unary minus operator to remove
> filters from the graph and the divide by operator to disconnect
> filters. I would also add some manipulator stuff ( like in iostreams)
> to control the way filters are
> connected with >> e.g.
>
> // Remove renderer2 from graph
> g -= RENDERER2;
>
> // Connect the first audio pin of the source to the renderer
> SOURCE >> pinType(MEDIATYPE_Audio) >> AUDIORENDER;
>
> // Disconnect any connection betwen these 2 filters
> SOURCE / AUDIORENDER;
>
> Any opinions, suggestions?
>
> Vivek


Hi Vivek,
I would advice that only overload operators which your library's users
would find intuitive, also while following the normal semantics of
those operators. Remember the goal of your rewrite is to make a more
user friendly library, your library's users all ready know that you
can write nifty code, so do not just overload operators because u can.

Also I am a big fan of c++ Meta programming, though i do not
necessarily see that you can well use a lot of it for the task at
hand . You might be able to create cool types which know at compile
time what filters to add, but u still need to make runtime calls to
Direct show library to actually setup the filter graph. Meta
programming usually is more usefull when all or majority of the info
is available at compile time and you can get compiler to evaluate
expressions, inline calls and un-roll loops etc to generate faster
code. In your case say even if you had a types to represent a filter
at compile time, you still actually do need to setup the filter graph
at runtime with DS library, also consider what happens if the user of
your library wants to iterate over all the available filter types at
runtime and decide which ones to actually add to the filter graph. A
Meta programming solution is set out in stone and would fall short to
meet the user's needs.

Please do not be offended as i do not intend to offend, but i too like
others prefer the first code snippet over the second as upon a quick
glance, it's much clearer to me what the code is doing. The second
code snippet just seems to create unnecessary confusion.
My 2 cents
  Réponse avec citation
Vieux 27/06/2008, 13h48   #8
rep_movsd
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Library design opinions...

>
> I try either to reuse an idea from the standard (for example everybody has
> an idea what operator<< and operator>> do because of streams) or make sure
> that the usage of operators feels natural (which might be more difficult
> as what is natural for me might not be natural for someone else). Your
> library seems to use operator>> to chain filters and operator+= to add
> filters? I probably wouldn't use overloaded operators here: operator>>
> makes me think that there is a data flow while in fact it's just a
> chaining of filters (if it was a lambda function it would make more sense
> maybe . And when operator+= is overloaded you wonder if and how
> operator+ fits into the schema.
>
> Boris


Well in dshow architecture, a graph is a bag of filters and the
connections will have data flow through them ( in the direction of the
'>>' ). Filters are more like digital ICs with input and output pins
( the term filter isnt so fitting in fact )

Graphs are always directed, so i thought using >> to hook up filters
together would be intuitive.

The fact that you saw it as a "data flow" is actually a good thing

Yes, now that you mention it, the meaning of + is vague if += adds
filters to the graph.

Vivek


  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 00h25.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,20343 seconds with 16 queries