寻求帮助将 SOLID 原则应用于文件 I/O 问题

Posted

技术标签:

【中文标题】寻求帮助将 SOLID 原则应用于文件 I/O 问题【英文标题】:Looking for help applying SOLID principles to a file I/O problem 【发布时间】:2020-07-16 14:48:17 【问题描述】:

我正在尝试更多地了解设计模式和原则。我通常在理论上理解它们,但在将它们应用于现实世界的问题时,我发现自己很难。这将是一个更长的问题,要给出所有相关的上下文,我非常感谢任何关于如何正确构建它的建议。

目前,我正在尝试在 Modern C++ 中为称为 TextGrid 的特定类型的结构化文件(从我没有编写的不同软件导出)实现文件管理器(读取和写入)。这个文件可以有三种不同的“风格”(它们都存储相同的信息,只是使用不同的格式):

短文本文件 长文本文件 二进制文件

所有口味都有相同的扩展名。用户通常不知道他们正在处理哪个文件,您必须阅读文件的开头才能分辨出区别。

现在我了解到,将表示存储在文件中的结构化数据的 TextGrid 类与 I/O 分开通常是有意义的。所以会有一个类TextGrid和一个(静态)类TextGridManager

这就是我迷路的地方。我应该在自己的课程中实现阅读和写作吗?我是否应该实现一个抽象类 BaseTextGridManager 然后派生专门的类(我认为这将是开放封闭原则所推荐的)?但如果是这样,用户如何知道要实例化哪个专用类,因为您必须先读取文件的前几个字节才能知道如何解析它?

我当然可以找到一种方法让它以某种方式工作,但我正在寻找有关如何优雅地完成它并遵循 SOLID 原则的建议。任何见解将不胜感激。

更新:

感谢这个问题下面的cmets,我目前的计划是按以下方式组织它:

class TextGrid:

  // The representation of the TextGrid data


class TextGridManager:

public:
   static TextGrid readTextGridFile(const std::string& filename);
   static bool writeTextGridFile(const TextGrid& tg, const std::string& filename, const std::string& format);

private:
   TextGridManager();
   static TextGrid BinaryTextGridFactory(std::istream& file);
   static TextGrid ShortTextGridFactory(std::istream& file);
   static TextGrid LongTextGridFactory(std::istream& file);

我欢迎任何建设性的批评和反馈。

【问题讨论】:

我希望有一个嗅探器函数(它可能有足够的部分和状态作为一个类)来确定文件类型,然后是三个不同的工厂函数(也可能有足够的声明保证是一个类)处理每种不同的文件格式。每个工厂函数的输出都是一个 TextGrid。 有趣。因此,嗅探器功能将与生成 TextGrid 的三个工厂一起位于 TextGridManager 中。并且界面会像TextGrid tg = TextGridManager::readTextGrid(filename) 这样工作,并且所有的嗅探和不同的解析都对用户隐藏?但这不会违反开闭原则吗?因为如果(无论出于何种原因)文件会有第四种格式,那么我无法派生新的管理器,但必须在旧类中添加另一个工厂。据我了解的原理,这正是应该避免的。 @Simon Parsing 其实应该隐藏起来。作为您 API 的用户,我不想对您的实现细节感到恼火。 “这是一个文件/文件名,请给我存储其中的数据。如果在读取/解析过程中发生了不好的事情,请让我知道(通过(明确定义的)异常或错误代码)”。***函数应该类似于TextGrid read_textgrid(std::string_view filename) 与其从原则的角度思考(由于它们的泛化性质,无论如何都会引起争议),而是考虑抽象的层/级别更有意义。 @Sebastian 我很欣赏这个观点,但这究竟意味着什么? 【参考方案1】:

对于新格式,您将添加新编写器并告知工厂。我不是 C++ 的人,但这并不重要。语法是 C# 的,省略了访问修饰符。

interface ITextGridReader 
    TextGrid read(filename);


class TextGridReader: ITextGridReader 
    // impl read(...);


interface ITextGridWriter 
    bool write(filename, textGrid);


class BinaryTextGridWriter: ITextGridWriter 
    // imp write(...);


class LongTextGridWriter: ITextGridWriter 
    // imp write(...);


// Calling code
ITextGridReader reader = new TextGridReader();
TextGrid textGrid = reader.read(...);
ITextGridWriter writer = Factory.CreateTextGridWriter(format);
writer.write(...);

【讨论】:

以上是关于寻求帮助将 SOLID 原则应用于文件 I/O 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何应用 SOLID 原则在 React 中整理代码之开闭原则

如何应用 SOLID 原则整理 React 代码之单一原则

如何应用 SOLID 原则整理 React 代码之单一原则

译浅谈SOLID原则

适用于Java开发人员的SOLID设计原则简介

依赖倒置原则|SOLID as a rock