序列化代码的最佳位置。被序列化的类的内部,还是每种格式的外部类?
我经常发现自己陷入了在哪里放置类的序列化代码的困境,并且想知道其他人对此主题的想法是什么。
Bog 标准序列化是理所当然的。只需装饰相关类即可。
我的问题更多是针对通过各种协议或不同格式序列化的类,并且需要对过程进行一些思考/优化,而不是盲目地序列化装饰属性。
我经常觉得将所有与一种格式相关的代码放在自己的类中会更干净。它还允许您通过添加新类来添加更多格式。 例如。
class MyClass
{
}
Class JSONWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class BinaryWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class DataBaseSerialiser
{
public void Save(MyClass o);
public MyClass Load();
}
//etc
然而,这通常意味着 MyClass 必须向外界公开更多的内部结构,以便其他类能够有效地序列化。这感觉是错误的,并且违背了封装。有办法解决这个问题。例如,在 C++ 中,您可以使序列化程序成为朋友,或者在 C# 中,您可以将某些成员公开为显式接口,但感觉仍然不太好。
当然,另一个选择是让 MyClass 知道如何将自身序列化为各种格式或从各种格式序列化自身:
class MyClass
{
public void LoadFromJSON(Stream stream);
public void LoadFromBinary(Stream stream);
public void SaveToJSON(Stream stream);
public void SaveToBinary(Stream stream);
//etc
}
这感觉更加封装和正确,但它将格式与对象耦合起来。如果某些外部类由于 MyClass 不了解某些上下文而知道如何更有效地序列化怎么办? (也许一大堆 MyClass 对象引用同一个内部对象,因此外部序列化程序可以通过仅序列化一次来进行优化)。此外,如果您想要一种新格式,则必须在所有对象中添加支持,而不仅仅是编写一个新类。
有什么想法吗?就我个人而言,我根据项目的具体需求使用了这两种方法,但我只是想知道是否有人有支持或反对特定方法的强有力的理由?
I often find myself in a quandary in where to put serialisation code for a class, and was wondering what others' thoughts on the subject were.
Bog standard serialisation is a no brainer. Just decorate the class in question.
My question is more for classes that get serialised over a variety of protocols or to different formats and require some thought/optimisation to the process rather than just blindly serialising decorated properties.
I often feel it's cleaner to keep all code to do with one format in its own class. It also allows you to add more formats just by adding a new class.
eg.
class MyClass
{
}
Class JSONWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class BinaryWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class DataBaseSerialiser
{
public void Save(MyClass o);
public MyClass Load();
}
//etc
However, this often means that MyClass has to expose a lot more of its internals to the outside world in order for other classes to serialise effectively. This feels wrong, and goes against encapsulation. There are ways around it. eg in C++ you could make the serialiser a friend, or in C# you could expose certain members as an explicit interface, but it still doesn't feel great.
The other option of course, is to have MyClass know how to serialize itself to/from various formats:
class MyClass
{
public void LoadFromJSON(Stream stream);
public void LoadFromBinary(Stream stream);
public void SaveToJSON(Stream stream);
public void SaveToBinary(Stream stream);
//etc
}
This feels more encapsulated and correct, but it couples the formatting to the object. What if some external class knows how to serialise more efficiently because of some context that MyClass doesn't know about? (Maybe a whole bunch of MyClass objects are referencing the same internal object, so an external serialiser could optimise by only serialising that once). Additionally if you want a new format, you have to add support in all your objects, rather than just writing a new class.
Any thoughts? Personally I have used both methods depending on the exact needs of the project, but I just wondered if anyone had some strong reasons for or against a particular method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最灵活的模式是保持对象轻量级,并为特定类型的序列化使用单独的类。
想象一下如果您需要添加另外 3 种数据序列化的情况。你的类很快就会因为他们不关心的代码而变得臃肿。 “对象不应该知道它们是如何被消耗的”
The most flexible pattern is to keep the objects lightweight and use separate classes for specific types of serialization.
Imagine the situation if you were required to add another 3 types of data serialization. Your classes would become quickly bloated with code they do not care about. "Objects should not know how they are consumed"
我想这实际上取决于使用序列化的上下文以及使用序列化的系统的限制。例如,由于 Silverlight 反射限制,需要公开一些类属性才能使序列化器正常工作。另一种情况是,WCF 序列化程序要求您临时了解可能的运行时类型。
除了您指出的之外,将序列化逻辑放入类中违反了 SRP。为什么类需要知道如何将自身“翻译”为另一种格式?
不同的情况需要不同的解决方案,但我大多看到单独的序列化器类来完成这项工作。当然,它需要暴露类内部的某些部分,但在某些情况下你无论如何都必须这样做。
I guess it really depends on the context in which serialization will be used and also on limitations of systems using it. For example due to Silverlight reflection limitations some class properties need to be exposed in order for serializers to work. Another one, WCF serializers require you to know possible runtime types ad-hoc.
Apart from what you pointed out, putting serialization logic into the class violates SRP. Why would a class need to know how to "translate" itself to another format?
Different solutions are required in different situations, but I've mostly seen separated serializers classes doing the work. Sure it required exposing some parts of class internals, but in some cases you'll have to do it anyways.