使用“单一责任原则”迫使我的容器拥有公共制定者

我正在努力按照SOLID原则进行设计。 我发现当你使用“单一责任原则”(SOLID的S)时,你通常必须在数据容器和数据处理器之间拆分类。 例如,如果我有一个具有5个属性的类人员从DB读取而不是将所有内容放在一个类中,我创建一个带有属性的Person类和另一个从数据库中读取该信息并创建Person的PersonReader类。

如果我这样做,我必须打开Person属性,以便PersonReader可以访问它们,但是我的封装比将所有内容放在黑盒子中并使属性只能读取更少。

我错过了什么或这是这个原则的缺点吗?

提前致谢

编辑:我已经将人作家改为一个人读者,因为没有必要在开始时公开财产制定者。

大多数数据访问策略(ORM技术)涉及您所描述类型的妥协。 最少侵入性的使用reflection(或内省等)在需要时填充您的实体(例如,当没有公共设置者时)。

话虽如此,如果你的实体只是数据容器(如在贫血域模型中 ),单一责任原则不应该真正关心你,因为你的对象没有复杂的逻辑会被破坏(或干扰)数据访问代码。

也许我错过了什么,但你为什么不为Person类编写一个接受它所有属性的构造函数呢? 通过这种方式,PersonReader将能够在不打开人员属性的情况下创建人员。

另一种选择是将人员属性的setter标记为内部(并使组件内部对PersonReader的程序集可见,如果它在不同的程序集中)。 这将允许您访问人员属性,但会阻止任何人在程序集之外更改它们。

我绝对同意你的意见,有时你会遇到这个问题。 我经历过序列化,它类似于ORM。 在我的情况下,我需要将对象的状态写入(二进制)文件。

在某些情况下,可以创建一个接口,通过该接口可以写入和读取内部状态。 因此,您的人员课程将获得两个“保存”和“加载”(或“写入”和“阅读”或您认为合适的任何内容)。 这些方法分别通过“IPropertyWriter”和“IPropertyReader”。 (在我的例子中,我称他们为InStream和OutStream)。

然后,Person :: save(IPropertyWriter writer)会这样做

writer.writeProperty("name", this.name); writer.writeProperty("age", this.age); 

你可以说你仍在违反单一责任原则,但我认为没有其他人应该知道人的内部。 (特别是在我的序列化的情况下,我不得不存储部分无法通过getter访问的内部状态)。 重点是Person没有耦合到任何数据库代码。 您的IPropertyWriter可以是一切。 此外,“了解自己的属性”的责任并不是真正的新属性,而是附加到每个对象上。

你可能也会问这个人改变的可能性有多大。 如果它不太可能,我认为C ++中的friend类是一种好方法,但是如果它可能会改变,我宁愿在声明属性的地方使用序列化方法,所以你不要忘记更新依赖代码。

你太精细了。 特定的类应该读取数据库 – 但是您不需要一个唯一的工作就是创建Person的类。 那太浪费了。 单个数据库阅读器应该能够创建通过数据库的任何类 – 因为这是它的工作。 从数据库中读取。

打开Person的属性没有封装问题,因此DatabaseReader可以访问它们,因为如果没有类能够创建它,则Person是多余的。 任何类别的责任都是可创造和可破坏的固有部分。