【问题标题】:Need concept for a particular type apps in c#在 c# 中需要特定类型应用程序的概念
【发布时间】:2011-06-15 17:02:21
【问题描述】:

我开发了一个 Windows 应用程序,其中一个按钮位于窗体上,当单击按钮时,几个系列的功能将一个接一个地运行,如下面的一个

Button_Click()

{

function1();

function2();

function3();

function4();

function5();

function6();

function7();

function8();

function9();

function101();

function1();

function12();

function13();

} 

每个函数都有一些工作。所以我的应用程序运行良好,但我需要知道如何以更结构化的方式设计这类工作。所以请指导我如何构造方式我可以一个接一个地调用所有函数。经验丰富的专家开发人员将如何处理这项工作,或者他们如何一个接一个地调用函数。谢谢

【问题讨论】:

    标签: c# architecture


    【解决方案1】:
    • 给你的实体起有意义的名字
    • 给你的实体起有意义的名字
    • 给你的实体起有意义的名字
    • 给你的实体起有意义的名字
    • 为常用代码提取函数
    • 可能信号/插槽/侦听器/观察者概念适合您。

    编辑:重构示例:

    假设你的代码是:

    void Button1_Click() {
        function1();
        function2();
        function3();
        function4();
        function5();
    }    
    void Button2_Checked(int variable0) {
        if (variable0) {
            function1();
            function2();
        } else {
            function1();
            function2();
            function3();     
            function4();
            function5();
        }
    }
    

    步骤 0-10 是为所有按钮、功能、 变量,参数(一次只重命名一个实体;为了发帖,我跳过了这个):

    void orderPizzaButton_Click() {
        requestSalamis();
        requestAnchovis();        
        requestShitake();        
        requestCheese();
        requestGroundMeat();
    }    
    void lasagnePervesityLevel_Changed(int newValue) {
        if (newValue <= 0) {
            requestCheese();
            requestGroundMeat();
        } else {
            requestSalamis();
            requestAnchovis();        
            requestShitake();
            requestCheese();
            requestGroundMeat();
        }
    }
    

    第 11 步是在这些函数中找到共同点,并提取一个新的、可重用的函数 来自他们:

    void orderPizzaButton_Click() {
        requestStrangeIngredientCombination();
    }    
    void lasagnePervesityLevel_Changed(int newValue) {
        if (newValue <= 0) {
            requestCheese();
            requestGroundMeat();
        } else {
            requestStrangeIngredientCombination();
        }
    }
    
    void requestStrangeIngredientCombination() {
        requestSalamis();
        requestAnchovis();        
        requestShitake();
        requestCheese();
        requestGroundMeat();
    }
    

    第 12 步是优化您对公共代码的搜索(将其视为一种规范化):

    void orderPizzaButton_Click() {
        requestStrangeIngredientCombination();
    }
    void lasagnePervesityLevel_Changed(int newValue) {
        if (newValue <= 0) {
            requestStandardComponents();
        } else {
            requestStrangeIngredientCombination();
        }
    }
    
    void requestStandardComponents() {
        requestCheese();
        requestGroundMeat();
    }
    void requestStrangeIngredientCombination() {
        requestSalamis();
        requestAnchovis();        
        requestShitake();
        requestStandardComponents();
    }   
    

    虽然在此示例中您似乎没有保存代码,但实际上它通常。此外,节省代码行在这里不是重要的事情,重要的是减少冗余,因为一旦你决定你的不正常的千层面和奇怪的披萨也应该放辣椒和西尔维斯特史泰龙的形象,你不仅会有代码重复,但是工作重复;最重要的是,有可能忘记代码中某些地方的新功能。当然,这非常糟糕,甚至对业务至关重要。假设您的客户希望他们的千层面上出现西尔维斯特·史泰龙的形象,正如您的营销活动所承诺的那样,然后没有人订购比萨饼,而只有那些订购千层面的人。

    存在更多重构和设计,具体取决于实际代码。我真的 建议入手以下书籍。此外,最重要的经验法则:一次一步。只做一次小的重构、编译、测试。

    • 重构 - 改进现有代码的设计 由 Addison-Wesley 的 Martin Fowler 撰写
    • C++ 编码标准:101 条规则、指南和 C++ 最佳实践,作者:Herb Sutter、Andrei Alexandrescu(C++ 深度系列),Addison-Wesley
    • Design Patterns: Elements of Reusable Object-Oriented Software 作者 Gamma、Helm、Johnson、Vlissides(通常称为 GoF,代表四人组),再次在 Addison-Wesley 发表

    【讨论】:

    • 我应该遵循哪种设计模式来处理这种情况。你能显示示例代码来处理这种情况吗?
    • 我不确定这是否真的值得一个设计模式。有意义地命名事物并将重复的东西放入单独的、可重用的实体中应该是程序员的常识。我举个例子吧。
    【解决方案2】:

    这完全取决于是否需要按特定顺序调用函数。

    如果不是:使用发布/订阅模式。

    如果需要特定订单:

    不要使用函数,将函数添加到类中并使用如下所示的管道。

    public interface IPipeline
    {
        void AddLast(IPipelineHandler handler);
        void AddFirst(IPipelineHandler handler);
    
        void Invoke(IPipelineContext context);
    }
    
    public interface IPipelineContext
    {
       Form SourceForm {get; }
    
       // The result that the pipeline should produce.  (change from object to a specific type)
       object Result {get; }
    
       //and other properties that each handler will need.
    }
    
    public interface IPipelineHandler
    {
        string Name {get; }
        void Process(IPipelineContext context);
    }
    

    在管道实现中,调用具有相同上下文的每个处理程序:

    public void Invoke(IPipelineContext context)
    {
         foreach (handler in _handlers)
         {
            try
            {
                 handler.Process(context);
            }
            catch (Exception err)
            {
                //abort or continue with the next handler?
            }
         }
    }
    

    【讨论】:

    • 您的代码很好,但我无法理解如何在我的场景中使用它。基本上我不是很高级的用户。如果你给我完整的代码会更好,我所有的function1(),function2()等等都将用你上面的代码一个接一个地调用。谢谢。我只需要看看我的函数如何用你的实现来调用。请帮助我。谢谢
    【解决方案3】:

    如果您正在创建的功能需要按顺序执行这些功能,那么为什么不将这些调用封装在一个方法中呢?这将为您提供更高级别的封装,并意味着可以在其他地方调用此函数,例如从菜单工具栏调用,而不必担心是否所有函数都以正确的顺序调用。

    为您的函数分配更有意义的名称也是值得的,但我确信您将它们命名为 functionX() 只是出于示例目的。

    所以,例如:

    Button_Click()
    {
       Print()
    }
    
    private void Print()
    {
      function1();
      function2();
      function3();
      function4();
      function5();
      function6();
      function7();
      function8();
      function9();
      function10();
      function11();
      function12();
      function13();
    }
    

    【讨论】:

    • 并且抽象层次更高,可以提高代码的可读性。如果此功能在其他地方执行,那么您正在拨打一个电话,而不是 14 次。这也可以通过模拟进行更好的单元测试。 ---编辑--- 嗯,我回复的人似乎删除了他们的评论。
    • 可能Button_Click已经封装了这些功能?所以你写了同样的东西。
    • 当然,这是真的。使用这样的示例代码,很难知道完整的域。 Button_Click() 向我表明了 .NET 点击处理模式,因此得到了响应。因此,如果 Button_Click() 是一个封装级别,那么我对更有意义的函数名称的评论具有更大的相关性。感谢您指出这一点!
    • 这里我给你伪代码,这就是为什么我没有指定有意义的名字。
    • 我以为是这样 :) 希望我的回答对您有所帮助!
    【解决方案4】:

    你期待什么答案?在不知道这些功能如何相互关联的情况下,没有人可以回答这个问题。

    这些功能是否相互依赖?下一个功能是否必须等待前一个功能完成?或者它们可以并行运行?这些功能总是相同还是可以改变?也许您想配置它们,从而使按钮执行的调用是动态的。甚至在运行时?

    如果您没有任何这些要求,我认为您当前的代码没有问题。

    你应该看看像命令模式或管道和过滤器模式这样的设计模式,也许这对你有帮助。

    【讨论】:

    • 我只想知道如何使用正确的设计模式来处理我的情况。功能不相互依赖。是的,下一个功能将在上一个完成之前等待。功能将始终相同。所以现在用小代码告诉我用正确的设计模式来实现这种情况。谢谢
    • 在这种情况下,您当前的代码没问题。您的代码是否有任何问题,是什么让您认为您的代码有问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多