简体   繁体   English

OOP,强制方法调用顺序

[英]OOP, enforcing method call order

Question: 题:

This is a question about OOP practice. 这是有关OOP实践的问题。 I've run into a situation while working with an API where there are a series of methods that need to be called in a specific order. 我在使用API​​时遇到了一种情况,其中需要按特定的顺序调用一系列方法。

Case: 案件:

Controlling the operation of a smart sensor. 控制智能传感器的操作。

A simplified version of the interaction goes like this: first the API must be configured to interface with the sensor over TCP, the next command starts the scanning process, followed by receiving input for multiple items until the command to stop is given. 交互的简化版本是这样的:首先必须将API配置为通过TCP与传感器连接,然后下一条命令开始扫描过程,然后接收多个项目的输入,直到给出停止命令为止。 At that time a similar series of disconnect commands must be given. 那时必须给出一系列类似的断开命令。 If these are executed out of order an exception is thrown. 如果这些命令无序执行,则会引发异常。

I see a conflict between the concepts of modularization and encapsulation here. 我在这里看到了模块化和封装概念之间的冲突。 Each of the steps is a discrete operation and thus should be encapsulated in separate methods, but they are also dependent on proper order of execution. 每个步骤都是离散操作,因此应封装在单独的方法中,但它们也取决于正确的执行顺序。

I'm thinking from the perspective of a later developer working on this code. 我是从后来开发此代码的开发人员的角度考虑的。 It seems like someone would have to have a high level of understanding of this system before they could work on this code and that makes it feel fragile. 似乎有些人必须对此系统有较高的了解,然后才能使用此代码,这会使它感到脆弱。 I can add warning comments about this call order, but I'm hoping there's some principle or design pattern that might fit my situation. 我可以添加有关此呼叫顺序的警告注释,但我希望有一些适合我情况的原理或设计模式。

Here's an example: 这是一个例子:

class RemoteTool
{
    public void Config();
    public void StartProcess();
    public void BeginListen();

    public void StopProcess();
    public void StopListening();
}

class Program
{
    static void Main(string[] args)
    {
        RemoteTool MyRemoteTool = new RemoteTool();

        MyRemoteTool.Config();
        MyRemoteTool.StartProcess();
        MyRemoteTool.BeginListen();

        // Do some stuff

        MyRemoteTool.StopListening();
        MyRemoteTool.StopProcess();
    }
}

The closest thing I can think of is to use boolean flags and check them in in each function to assure that the prerequisite functions have already been called, but I guess I'm hoping for a better way. 我能想到的最接近的方法是使用布尔标志并在每个函数中检入它们,以确保先决条件函数已被调用,但我想我希望有一种更好的方法。

Here's a method I found while looking for an answer. 这是我在寻找答案时发现的一种方法。 It's pretty simple, it helps, but doesn't solve my issue. 这很简单,有帮助,但不能解决我的问题。

Essentially the class is created exactly in the question, but the dependant functions are created as protected and a public member is created to keep them in order like so: 从本质上讲,该类是完全在问题中创建的,但是从属函数是按受保护的方式创建的,并且创建了一个公共成员以使其保持顺序,如下所示:

class RemoteTool
{
    public bool Running = false;
    public void Run()
    {
        Config();
        StartProcess();
        BeginListen();

        Running = true;
    }

    public void Stop() {
        StopListening();
        StopProcess();

        Running = false;
    }

    protected void Config();
    protected void StartProcess();
    protected void BeginListen();

    protected void StopProcess();
    protected void StopListening();
}

The trouble is that you still have to call Stop() and Run() in the right order, but they're easier to manage and the modularization is higher. 问题在于您仍然必须以正确的顺序调用Stop()和Run(),但是它们更易于管理并且模块化程度更高。

I think the problem is related to the fact that the RemoteTool class has a contract that requires some pre-condition. 我认为问题与RemoteTool类具有需要某些前提条件的合同有关。 eg : method b() has to execute() after method a(). 例如:方法b()必须在方法a()之后执行()。

If your language does not provide a mechanism to define these kinds of pre-conditions, you need to implement one yourself. 如果您的语言没有提供定义此类前提条件的机制,则您需要自己实现。

I agree with you that to implement this extra functionality (or these specific class contract features) inside RemoteTool() class could degrade your current design. 我同意您的观点,即在RemoteTool()类中实现此额外功能(或这些特定的类合同功能)可能会降低当前的设计水平。 A simple solution could be use another class with the responsibility of enforce the needed pre-condition before call the specific method of RemoteClass.(RemoteToolProxy() can be a suitable name) 一个简单的解决方案是使用另一个类,该类负责在调用RemoteClass的特定方法之前强制执行所需的前提条件。(RemoteToolProxy()可以是一个合适的名称)

This way you will decouple the concrete functionality and the contract that says how to use it. 这样,您将使具体功能与说明如何使用它的契约脱钩。

There are other alternatives provided by a software design approach called Design by Contract that can give you other ways of improving your class contract. 软件设计方法还提供了其他替代方法,称为按合同设计 ,可以为您提供改善类合同的其他方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM