与AI对话 --- 软件层级
Q:我们来讨论一个具体的层级关系。假设有一个DisplayObject 层级。然后我们有一个层级,专门封装了一些方法,关于如何画displayobject。 这个层级是服务于display object ,可以看作是display object的extension 部分。 还有一个层级,关于如何从display object里面 query 得到信息的。这个层,也可以看作是display object层级的扩展。 从宏观上看, 似乎display object依赖于 画层级 和 query 层级。 但是从微观上看,query 层级的输入参数,是需要display object的。似乎,query 层依赖于displayobject. 这就使得宏观得到的层级关系与微观上,产生了矛盾。 为什么这样? 哪个错了?
Q:
No, I think we make the wrong thinking. The question occur when a layer is too big and we want to seperate it. for example, in the past, the display object level may have the responsbility of draw things. Now we seperate the respobisility and make draw a thin layer that works for the dispaly object. So from macro view, the dispaly object level use the draw level things.
AI:
I understand your point. When a layer becomes too large and you decide to separate its responsibilities into smaller, more manageable layers, it can create a situation where the original layer (now split) appears to have dependencies on the new layers. This can lead to confusion about the direction of dependencies.
Clarifying the Separation of Responsibilities
In your example, the DisplayObject layer originally had the responsibility of drawing itself. To improve modularity and maintainability, you decided to separate the drawing functionality into its own layer. This separation can indeed create a situation where the DisplayObject layer depends on the drawing layer for rendering.
Macro and Micro View of Dependencies
[*]Macro View:
[*]From a macro perspective, the DisplayObject layer uses the drawing layer to render itself. This makes it seem like the DisplayObject layer depends on the drawing layer.
[*]Similarly, if you have a query layer to extract information from DisplayObject, the DisplayObject layer might seem to depend on the query layer for querying.
[*]Micro View:
[*]From a micro perspective, the drawing layer and query layer need instances of DisplayObject to perform their operations. This makes it seem like the drawing and query layers depend on DisplayObject.
Resolving the Perceived Contradiction
To resolve this perceived contradiction, it's important to clearly define the roles and responsibilities of each layer and ensure that dependencies are managed in a way that maintains the integrity of the layered architecture.
Example: DisplayObject, Drawing Layer, and Query Layer
Let's consider the following example:
[*]DisplayObject: Represents the object to be drawn and queried.
[*]Drawing Layer: Provides methods to draw DisplayObject.
[*]Query Layer: Provides methods to query information from DisplayObject.
Refactoring for Clarity
To maintain a clear separation of concerns and manage dependencies effectively, you can use interfaces and dependency injection. This approach ensures that each layer depends on abstractions rather than concrete implementations.
Example Code
Here is an example demonstrating how to refactor the code to maintain clear dependencies:
#include #include // Define IDrawable interfaceclass IDrawable {public: virtual void draw() const = 0; virtual ~IDrawable() = default;};// Define IQuery interfaceclass IQuery {public: virtual std::string query() const = 0; virtual ~IQuery() = default;};// DisplayObject implements IDrawable and IQuery interfacesclass DisplayObject : public IDrawable, public IQuery {public: void draw() const override { std::cout
页:
[1]