You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Justin Ross <ju...@gmail.com> on 2015/09/11 13:24:42 UTC

C++ proton API and namespaces

I wasn't subscribed before, so I'll have to address Alan's notes in a new
thread.

My reading of the internet suggests that "using namespace" is awfully
common.  Is it really anathema?

Here's the upside of using namespaces:

  - https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton

    ^ A small list of understandable top-level categories

  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/core

    ^ A core set of concepts that users will find frequent occasion to use

  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/reactor

    ^ A set of tools for using the core concepts in a reactive programming
style

  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/util
  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/codec
  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/types
  -
https://github.com/ssorj/stutter/tree/master/output/include/qpid/proton/extras

    ^ Things that are indeed useful, but they are useful less frequently or
they are less central to the API

The namespace handling in the examples remains reasonable, imo:

  - https://github.com/ssorj/stutter/blob/master/src/broker.cpp
  - https://github.com/ssorj/stutter/blob/master/src/client.cpp
  - https://github.com/ssorj/stutter/blob/master/src/helloworld.cpp

I'm not trying to say this is the layout we need to end up at.  It could
use some improvement.

But having a plan, with understandable grouping, and positiioning by user
priority, is to me a big win.  It helps the API user to focus on the most
important things first.

Justin

Re: C++ proton API and namespaces

Posted by Justin Ross <ju...@gmail.com>.
On Fri, Sep 11, 2015 at 11:23 AM, aconway <ac...@redhat.com> wrote:

> Those are fine. You need to write some header files for a library based
> on proton to appreciate where the pain lies.
>
>     namespace mynamespace {
>     #include <proton/core/message.hpp> // Need messge_value decl.
>
>     // Forward declare receiver, we only pass by reference
>     namespace qpid{ namspace::proton { namespace:core {
>     class receiver;
>     }}}
>
>     // Finally my function
>     qpid::proton::core::message_value
> get_message(qpid::proton::core::receiver&)
>     }
>
> The forward declaration is important, minimizing unnecessary #includes
> is key to keeping C++ build times manageable in a large code base.
>
> We can't use "using" in this header file without aliasing proton types
> directly into "mynamespace" for everyone who #includes the file, which
> defeats the purpose of having a separate namespace.
>

Wouldn't some well chosen namespace aliases reduce the typing for library
developers?

http://en.cppreference.com/w/cpp/language/namespace_alias

The layout is logical and useful. I think it makes sense to organize
> documentation for all bindings like this, and it maps directly to java
> and python without unusual pain.
>
> However it does not map well in C, C++ or Go *programming* constructs.
> C and C++ do not do well with deeply nested namespaces. Go does not do
> well with generic package names like "core" or "types" that are
> meaningless out of context. Programmers in any of these languages will
> be suspicious of a "simple, ligthweight protocol library" that has to
> be split into 7 or 8 namespaces in order to be comprehensible.
>
>
The proposal doesn't have deeply nested namespaces.  It is a flat array of
namespaces at one level, qpid::proton::*.  Some languages, for legacy
reasons, have mapped qpid::proton::core to qpid::proton::


> The entire C++ std or boost libraries go in a single namespace and
> nobody's head explodes - the documentation for those libraries *does*
> use a layout like you propose, but it is not imposed on the programmer
> coding time. Programmers will (hopefully) spend more time writing
> proton code than learning how to use proton so the coding overhead is
> important.
>

I think you're saying that the library symbols are all mapped into one
namespace from their respective sub namespaces.  They are not, however, all
*defined* in one namespace.  At least not in boost where I looked.

The notion that you should *add back* the structure using some
extra-language facility such as doxygen groups is silly.  We have to do
that for C, but languages with namespaces are already giving us the right
tool.  It's a lot of extra work to map on the groups with external
metadata, and since it's not integral to the APIs structure, it will get
out of sync.

For instance, people writing patches or improvements will likely forget to
add the extra categorization on.  Since the program structure is not in
place to direct their contribution, it will end up just tacked on to the
already long list.

I have poked around in various popular C++ libraries, and I am not seeing
the disdain for namespaces.  I also don't object to the notion that for
convenience sake we alias some or all proton modules to a single namespace.


> Go is a fan of small but *self-contained* packages with very clear
> dependencies. My Go binding currently has 3 packages (all under the
> qpid.apache.org/proton prefix):
>
> amqp: AMQP types and conversions, independently useful if you want to
> encode/decode AMQP data, and a dependency for the other two packages.
>
> reactor: the proton core and reactive API, all you need to build event
> -driven AMQP applications. Depends on amqp.
>
> messaging: procedural, blocking AMQP messaging API, depends on AMQP.
> Internally implemented in terms of reactor but does not require the
> user to use reactor at all.


I haven't looked at the go work yet, so I won't comment on that
specifically.  Generally, however, I like the split between amqp for codec
and reactor for the higher-level API.

Even in python and Java it is instructive to note *why* it is ok to
> impose the layout at programming time. Java programmers will never
> *use* the namespaces, their IDE's will automtically insert import
> statements and they will use unqualified class names.
>

Well, this just ain't so.  Plenty of folks write java without IDEs.  I did
for a long time.  Indeed the java language has made the import syntax more
convenient for the IDE-allergic over time.

Proton is not a simple, five-concept API.  There are a lot of first-order
Things, and it contains multiple API models for using them.

Justin

Re: C++ proton API and namespaces

Posted by aconway <ac...@redhat.com>.
On Fri, 2015-09-11 at 07:24 -0400, Justin Ross wrote:
> I wasn't subscribed before, so I'll have to address Alan's notes in a
> new
> thread.
> 
> My reading of the internet suggests that "using namespace" is awfully
> common.  Is it really anathema?

It is common, and normal in .cpp files, exactly as in your example, and
it works very nicely.

It is useless in header files unless you intend to alias the
definitions into a different namespace for everyone who includes that
header file - in which case why didn't you just put them there in the
first place?

C++ templates, inline functions and now constant-expressiona encourage
writing code (not just delcarations) in header files. The boost and std
libraries are almost exclusively header files. In a large codebase with
a mix of header and .cpp code it becomes a mental drag to remember
whether you are in a context where you can say "boost::shared_ptr" or
just "shared_ptr" so you end up just qualifying everything.

So in short, deeply nested namespaces are possible in principle in C++
but a bad idea in practice.

> Here's the upside of using namespaces:
[snip]

> The namespace handling in the examples remains reasonable, imo:
> 
>   - https://github.com/ssorj/stutter/blob/master/src/broker.cpp
>   - https://github.com/ssorj/stutter/blob/master/src/client.cpp
>   - https://github.com/ssorj/stutter/blob/master/src/helloworld.cpp

Those are fine. You need to write some header files for a library based
on proton to appreciate where the pain lies.

    namespace mynamespace {
    #include <proton/core/message.hpp> // Need messge_value decl.

    // Forward declare receiver, we only pass by reference
    namespace qpid{ namspace::proton { namespace:core {
    class receiver;
    }}}

    // Finally my function
    qpid::proton::core::message_value get_message(qpid::proton::core::receiver&)
    }

The forward declaration is important, minimizing unnecessary #includes
is key to keeping C++ build times manageable in a large code base.

We can't use "using" in this header file without aliasing proton types
directly into "mynamespace" for everyone who #includes the file, which
defeats the purpose of having a separate namespace.

> I'm not trying to say this is the layout we need to end up at.  It
> could
> use some improvement.
> 
> But having a plan, with understandable grouping, and positiioning by
> user
> priority, is to me a big win.  It helps the API user to focus on the
> most
> important things first.

The layout is logical and useful. I think it makes sense to organize
documentation for all bindings like this, and it maps directly to java
and python without unusual pain.

However it does not map well in C, C++ or Go *programming* constructs.
C and C++ do not do well with deeply nested namespaces. Go does not do
well with generic package names like "core" or "types" that are
meaningless out of context. Programmers in any of these languages will
be suspicious of a "simple, ligthweight protocol library" that has to
be split into 7 or 8 namespaces in order to be comprehensible. 

The entire C++ std or boost libraries go in a single namespace and
nobody's head explodes - the documentation for those libraries *does*
use a layout like you propose, but it is not imposed on the programmer
coding time. Programmers will (hopefully) spend more time writing
proton code than learning how to use proton so the coding overhead is
important.

Go is a fan of small but *self-contained* packages with very clear
dependencies. My Go binding currently has 3 packages (all under the
qpid.apache.org/proton prefix):

amqp: AMQP types and conversions, independently useful if you want to
encode/decode AMQP data, and a dependency for the other two packages.

reactor: the proton core and reactive API, all you need to build event
-driven AMQP applications. Depends on amqp.

messaging: procedural, blocking AMQP messaging API, depends on AMQP.
Internally implemented in terms of reactor but does not require the
user to use reactor at all.

Even in python and Java it is instructive to note *why* it is ok to
impose the layout at programming time. Java programmers will never
*use* the namespaces, their IDE's will automtically insert import
statements and they will use unqualified class names.

Python doesn't care what you import or alias where. The reactor module
in python already imports the entire python module as a convenience,
python programmers will import and alias at will and also never use the
qualified names.

So I think the layout is good, what we are missing are some guidelines
for package naming in languages where deep trees and numerous
namespaces are not the norm.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org