首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有宏定义的可伸缩API开发

具有宏定义的可伸缩API开发
EN

Code Review用户
提问于 2015-12-25 14:06:34
回答 1查看 107关注 0票数 4

几个月后,我将成为一个大型(Ish)项目的一部分,我的团队很有可能会更大,至少有2名程序员(可能有3名)和大约3到5名或更多的API用户(我们正在构建一个游戏,他们将使用我们尚未选择的脚本语言编写高级逻辑)。

现在,我在上一个项目中使用了下面提到的技术,在生成用于映射配置文件的结构时取得了“很大”的成功。问题是,这将是我第一次与几个开发人员和多个使用者一起构建API,我不知道它的扩展效果如何。

tl;dr:

  1. 这个系统是否有足够的直觉和规模,让一个人(你!),在没有预先存在的系统知识的情况下,能够在没有太多问题的情况下捡起并扩展它?
  2. 如果不是的话,我应该如何去构建一个既能达到同样的目的,又能让我跳过所有重复巡航的东西呢?
  3. 你能看到我忽略的任何_gotcha_s吗?

这些示例使用python2.7和pybind11 (用于将结构绑定到python)。当正确地链接到python时,它们是可构建的和可运行的。

代码语言:javascript
复制
#include <pybind11/pybind11.h>

namespace py = pybind11;

#define PLUGIN PYBIND11_PLUGIN

#define PLUGIN_BEGIN(TYPE, NAME, DESCR)         \
    PLUGIN(TYPE)                                \
    {                                           \
        typedef TYPE Type;                      \
        py::module Module (NAME, DESCR);        \
        py::class_<Type> Binding(Module, #NAME);\

#define PLUGIN_END                              \
        return Module.ptr();                    \
    }                                           \

#define PLUGIN_MAP_FIELD(NAME)                \
    Binding.def_readwrite(#NAME, &Type::NAME);\

#define PLUGIN_MAP_PROPERTY(NAME)                                   \
    Binding.def_property(#NAME, &Type::get##NAME, &Type::set##NAME);\

然后你就这样使用它:

代码语言:javascript
复制
#include <string>

struct SPerson
{
    unsigned int Age;

    std::string getName( void ) { return m_Name; }
    void setName( const std::string name ) { m_Name = name; }

private:
    std::string m_Name;
};

PLUGIN_BEGIN(SPerson, "Person", "A person descriptor")
    PLUGIN_MAP_FIELD(Age)
    PLUGIN_MAP_PROPERTY(Name)
PLUGIN_END
EN

回答 1

Code Review用户

发布于 2015-12-25 21:28:45

您目前得到的内容扩展到了这样的内容:

代码语言:javascript
复制
PYBIND11_PLUGIN(SPerson)
{
    typedef SPerson Type;
    py::module Module("Person", "A person descriptor")
    py::class_<SPerson> Binding(Module, "\"Person\"");
    Binding.def_readwrite("Age", &Type::Age);
    Binding.def_property("Name", &Type::getName, &Type::setName);
    return Module.ptr();
}

我想你在一个地方有一个流浪的#NAME前面。

无论如何,是否有技术原因需要SPersonPerson作为不同的标识符?这似乎会增加混淆(同一实体的两个名称,取决于您正在编写的语言),而不是减少。

字符串"A person descriptor"只是内部文档,对吗?它对代码的语义不重要,也就是说,它只是一个注释?如果是这样的话,几乎可以肯定的是,最好忽略它。请记住,这段代码的目标是那些将代码剪切粘贴并更改所需内容以使其工作的人;我预见到

代码语言:javascript
复制
PLUGIN_BEGIN(SPerson, "Person", "A person descriptor")
PLUGIN_BEGIN(SDog, "Dog", "A dog descriptor")
PLUGIN_BEGIN(SVehicle, "Vehicle", "A vehicledescriptor")
PLUGIN_BEGIN(SWeapon, "Weapan", "A person descriptor")
PLUGIN_BEGIN(SEnemy, "Enemy", "A person descriptor")

在你的未来,除非你现在采取措施消除这些多余的字段。记住墨菲定律:任何可能出错的事情,都会出错。所以,如果你不想出任何问题,你应该努力消除系统中任何可能出错的元素。

代码语言:javascript
复制
PLUGIN_BEGIN(Person)
    PLUGIN_MAP_FIELD(Age)
    PLUGIN_MAP_PROPERTY(Name)
PLUGIN_END

如果你的用户可能表现出任何个人主动性--如果他们想理解你给他们的工具,而不是被动地使用它和/或问你他们是否有问题--那么我也会建议不要用pybind11 11‘S的名字来掩饰事情。如果你的意思是FIELD,不要说READWRITE。这将帮助用户-程序员,当一些不可避免的故障,他必须谷歌的东西的名称;这会有帮助,因为将有一个名字(readwrite),而不是两个(ReadW区和字段),这意味着他的googling可以有两倍的效率在相同的时间。

当扩展库的时候,这也会帮助你,库作者。在当前系统中,用户如何将const数据成员公开给pybind11?他不能。你需要一个新的宏来处理const字段。pybind11已经有了这样的东西的名称(只读),但是你还没有为它们编出你自己的名字。您是使用FIELD_READONLY,还是CONST_FIELD,还是使用READONLY,即使您最初没有使用READWRITE.?有点乱。然而,如果你在设计上决定坚持用pybind11 11‘S的名字来描述刚开始的事情,你就再也不用浪费自己的时间在这样的问题上了;答案总是“按照pybind11的说法去做”。

宏系统将每个Python模块限制为一个Python类。没关系,对吧?

句法上的挑剔:有一天那些后面的反斜杠会咬你的。(我甚至不知道是否正确定义了将反斜杠作为源文件的最后一个字符!)而不是

代码语言:javascript
复制
#define FOO \
        bar \
        baz \
/* warning: this blank line is semantically significant */

我强烈建议

代码语言:javascript
复制
#define FOO \
        bar \
        baz
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/115043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档