我已经使用了几年的指针,但我最近才决定转换到C++ 11的智能指针(即唯一,共享和弱).我对它们做了很多研究,这些是我得出的结论:
因此,考虑到这些原则,我开始修改我的代码库以利用我们新的闪亮智能指针,完全打算清除尽可能多的原始指针.然而,我对如何最好地利用C++ 11智能指针感到困惑.
例如,让我们假设我们正在设计一个简单的游戏.我们认为将虚构的Texture数据类型加载到TextureManager类中是最佳的.这些纹理很复杂,因此按值传递它们是不可行的.此外,让我们假设游戏对象需要特定的纹理,具体取决于它们的对象类型(即汽车,船等).
之前,我会将纹理加载到矢量(或其他容器,如unordered_map)中,并在每个相应的游戏对象中存储指向这些纹理的指针,以便在需要渲染时可以引用它们.让我们假设纹理保证比指针寿命更长.
那么,我的问题是如何在这种情况下最好地利用智能指针.我看到几个选项:
将纹理直接存储在容器中,然后在每个游戏对象中构造unique_ptr.
class TextureManager {
public:
const Texture& texture(const std::string& key) const
{ return textures_.at(key); }
private:
std::unordered_map<std::string, Texture> textures_;
};
class GameObject {
public:
void set_texture(const Texture& texture)
{ texture_ = std::unique_ptr<Texture>(new Texture(texture)); }
private:
std::unique_ptr<Texture> texture_;
};
Run Code Online (Sandbox Code Playgroud)
然而,我对此的理解是,新的纹理将从传递的引用中复制构造,然后由unique_ptr拥有.这让我觉得非常不受欢迎,因为我会使用与使用它的游戏对象一样多的纹理副本 - 击败指针点(没有双关语意).
不直接存储纹理,而是存储容器中的共享指针.使用make_shared初始化共享指针.构造游戏对象中的弱指针.
class TextureManager {
public:
const std::shared_ptr<Texture>& texture(const std::string& key) const
{ return textures_.at(key); }
private:
std::unordered_map<std::string, std::shared_ptr<Texture>> textures_;
};
class GameObject {
public:
void set_texture(const std::shared_ptr<Texture>& …Run Code Online (Sandbox Code Playgroud)我有一些问题要弄清楚在Django中引入验证逻辑的最佳(读取:DRY和可维护),即模型,表单和DRF序列化器之间.
我已经与Django合作了几年,并且一直遵循处理模型,表单和REST API端点验证的各种约定.我已经尝试了很多变体来确保整体数据的完整性,但最近我遇到了一些绊脚石.以下是查看了许多文章,SO帖子和门票后我尝试过的简要列表:
在模型级别进行验证; 即,在myModel.save()通过覆盖调用之前确保所有自定义约束都匹配myModel.clean()(以及特定于字段和唯一的方法).为此,我确保myModel.full_clean()调用myForm.clean()(对于表单 - 而管理面板实际上已经这样做了)和mySerializer.validate()(对于DRF序列化程序)方法.
在表单和序列化程序级别进行验证,为可维护的DRY代码调用共享方法.
在表单和序列化程序级别进行验证,每种方法都有一个独特的方法,以确保最大的灵活性(即当表单和端点具有不同的约束时).
当表单和序列化器具有相同的约束时,方法一对我来说似乎最直观,但在实践中有点混乱; 首先,数据由表单或序列化程序自动清理和验证,然后实例化模型实体,并再次运行更多验证 - 这有点复杂并且可能变得复杂.
方法三是Django Rest Framework从3.0版开始推荐的; 他们消除了很多model.save()钩子,并且更愿意将验证留给应用程序面向用户的方面.这对我来说很有意义,因为Django的基本model.save()实现model.full_clean()无论如何都不会调用.
所以,方法二对我来说似乎是最好的整体推广结果; 验证生活在一个独特的地方 - 在触摸模型之前 - 由于共享验证逻辑,代码库不那么杂乱/更干.
不幸的是,我遇到的大多数麻烦都是让Django Rest Framework的序列化器合作.这三种方法都适用于表单,实际上适用于大多数HTTP方法(最值得注意的是在POST实体创建时) - 但是在更新现有实体(PUT,PATCH)时似乎没有好的方法.
简而言之,事实证明,当输入数据不完整时(或其他有效的 - 通常是PATCH的情况),验证输入数据相当困难.请求数据可能只包含一些字段 - 包含不同/新信息的字段 - 并且为所有其他字段维护模型实例的现有信息.事实上,DRF问题#4306完美地总结了这一特殊挑战.
我还考虑在视图集级别运行自定义模型验证(填充serializer.validated_data并且serializer.instance存在之后,但在调用serializer.save()之前),但我仍然在努力想出一个干净的,由于处理更新的复杂性,通用方法.
TL; DR Django Rest Framework使得在一个明显的位置编写干净,可维护的验证逻辑变得有点困难,特别是对于依赖于现有模型数据和传入请求数据的混合的部分更新.
我很想让一些Django大师权衡他们的工作,因为我没有看到任何方便的解决方案.
谢谢.
python django validation serialization django-rest-framework
我已经在他们的C++样式指南中使用谷歌的DISALLOW_COPY_AND_ASSIGN宏几个月了,但最近我发现,额外禁用移动构造函数和移动赋值会很有用.
我之前没有写过任何真正的宏(实际上,我一直试图尽可能远离它们),所以我想从其他人那里得到一些关于我是否实现它的反馈正确.
// Original Version
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// Modified Version (no move semantics)
#define DISALLOW_COPY_MOVE_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&); \
TypeName(TypeName&&); \
void operator=(const TypeName&&)
Run Code Online (Sandbox Code Playgroud)
建议和批评是非常受欢迎的.
谢谢你的时间!