【问题标题】:Where should methods() be placed?方法()应该放在哪里?
【发布时间】:2012-07-18 17:02:09
【问题描述】:

我有一个演示脚本,可以很好地显示问题,所以我会显示脚本,然后提问。

class Program
{
    static void Main(string[] args)
    {
        Dog dog = new Dog() { Age = 4 };

        //This approach (version A)
        dog.DisplayDogYears();

        //Or this approach (version B)
        displayDogYears(dog);

        Console.ReadKey();
    }

    private static void displayDogYears(Dog d)
    {
        Console.WriteLine("The dog is {0} years old in human years.", d.Age * 7);
    }
}

public class Dog
{
    public int Age { get; set; }

    public void DisplayDogYears()
    {
        Console.WriteLine("The dog is {0} years old in human years.", Age * 7);
    }
}

有两种方法可以做同样的事情(方法 A 和 B)。就可扩展性和可读代码而言,是否有任何理由更喜欢一种方法而不是另一种方法。我可以看到方法 A 的一个优点是该方法可用于 Dog 类的所有实例(非常好、可扩展、可重用和可维护,但是,在调试时它确实意味着我必须在不同的类之间移动(而 VS 有跳转到不同的文件等),而不是只在一个文件中查看所有内容。

有什么想法吗?

戴夫

【问题讨论】:

  • 我将用户视图输出放入视图层。虽然,对于控制台应用程序来说,好处大部分会丢失。

标签: c# function methods


【解决方案1】:

这确实是一个偏好问题。

我可能会在其余部分措辞不好,但不要太深入:

有几个因素需要考虑:

  • 可读性
  • 代码重用
  • 可怜的维护程序员不得不维护它。 (但这可能是可读性)

在这个例子中,我认为所有因素都指向在 Dog 类中。

代码中的类应该反映现实生活中的对象。

  • 可读性:对我来说,狗的年龄以年为单位,以狗年为单位,因此它应该是狗的财产。 (这是选项 C - 在您的问题中未显示)而不是调用程序中的方法。
  • 代码重用:如果您编写的另一个应用程序需要使用 Dog 类,并且需要获取 Dog Years 中的年龄,则必须重写代码。

简而言之,现实生活到代码对象的映射是狗年是狗的一部分,而不是调用程序。

【讨论】:

    【解决方案2】:

    视情况而定,

    您是否需要能够在不同的类中调用该方法,即您希望它可重用?选择A。

    是否仅在一个类/方法中调用 B.

    【讨论】:

      【解决方案3】:

      Dog 类与Console 分离,但仍允许Dog 类显示自己的年龄。

      public class Dog
      {
          public int Age { get; set; }
          private int dogYears { get { return Age * 7; } }
      
          public void DisplayDogYears(TextWriter writer)
          {
              writer.WriteLine(
                  "The dog is {0} years old in human years.", 
                  dogYears);
          }
      }
      

      然后您可以将狗年显示给任何TextWriter

      static void Main(string[] args)
      {
          var dog = new Dog { Age = 4 };
      
          // This will output to the console
          dog.DisplayDogYears(Console.Out);
      
          // This will output to the 'sb' StringBuilder
          var sb = new StringBuilder();
          dog.DisplayDogYears(new StringWriter(sb));
      }
      

      【讨论】:

        【解决方案4】:

        最佳实践还说让每个类都独立,因此 Dog 类不会与应用程序的主要部分一起使用,而是保持独立。按照这种逻辑,最好将与该类相关的每个方法都放在该类中。例如,假设您有 20 个班级,20 只动物,每个班级都有不同的年龄计算方式,您是否希望将所有 20 个班级和所有 20 种方法随机放在同一页面上?是的?那么你有问题!

        您希望保持代码干净且易于访问,每个类都独立,每个方法都专门针对其中的该类。例如 Dog 类不需要知道 Cat 年数是如何计算的,它与自身无关,所以 cat 类中 cat 年,dog 类中 dog 年,

        这更整洁,易于使用和阅读,并且可重用性更好!假设您现在想在另一个项目中使用您的 dog 类,您将不得不先切出该类,然后在代码行中寻找该类所需的所有方法。如果它们在其中,都在一个地方,它将加快您的编码速度并让您继续迎接更大的挑战!

        我什至不会提及您希望重用的类应该位于共享库中以便于重用。

        【讨论】:

          【解决方案5】:

          戴夫,这是一个隔离问题。如果你要添加一个 Cat 类怎么办?你会添加一个新方法说 DisplayCatYears 吗?如果您在 Dog 类中拥有它 - 您可以为此提取通用接口,并通过利用多态性让一个方法编写动物年龄作为参数传递。

          更重要的是,当您的程序超过几个屏幕长度并且将所有内容都放在一个文件中时,我认为您会感到不舒服。

          【讨论】:

          • 天哪 - 我已经发布了 X 篇关于为什么要使用接口的帖子,而且您一口气回答了我的问题,还解释了接口的用途。谢谢
          【解决方案6】:

          在调试时确实意味着我必须在不同的类之间移动(并且 VS 必须跳转到不同的文件等),而不是只在一个文件中查看所有内容

          你所有的钥匙都在一个巨大的钥匙圈上吗?你的所有纸质文件都堆在你的桌子上吗?

          将方法分离到它们所属的类中。也许您实际上需要一个 third 类来将 Dog 年(或通常的 Animal 年)转换为 Human 年。将所有内容都放在一个(或几个)类中会限制重用性、可维护性(您必须在调试器中运行程序才能弄清楚它在做什么)和可扩展性。

          【讨论】:

          • +1 以获得良好的日常参考,例如一大叠纸!
          • 我从没想过这一点,(我们是无纸化的,但我想这意味着我错过了重点:)) - 是的,我当然把所有东西都归档到它所属的地方。谢谢。
          【解决方案7】:

          在这种情况下,该方法应该在类 (Dog) 上,因为它是特定于 Dog 对象的功能。

          顺便说一句,狗 -> 人类年不是简单的几何乘法 - 随着狗年龄的增长曲线开始平滑,因此乘数减小。

          Dog Years

          【讨论】:

            【解决方案8】:

            这种方法会更好。因为你的班级没有直接输出任何东西。所以一切仍然由main 类控制。它使我更容易阅读代码正在做什么。

            class Program
            {
                static void Main(string[] args)
                {
                    Dog dog = new Dog() { Age = 4 };
            
                    //This approach (version A)
                    Console.WriteLine(dog.DisplayDogYears());
            
                    Console.ReadKey();
                }
            
            
            }
            
            public class Dog
            {
                public int Age { get; set; }
            
                public String DisplayDogYears()
                {
                    return("The dog is {0} years old in human years.", Age * 7);
                }
            }
            

            【讨论】:

            • 这很棒。漂亮且可维护。同样,就像 Felice 的回答一样,您赞成选项 A!感谢您花时间回答。
            • 选项 A 肯定是更传统的.. 选项 B 在较大的项目中往往变得不利。
            • @DaveRook:还要注意,调试时在各种类/文件之间跳转不会成为实际项目中的问题。无论如何,它们实际上由几十个类/文件组成,您的堆栈跟踪几乎总是会跨越其中的多个。
            【解决方案9】:

            我希望在 Dog 类中有一个方法:

            public int GetAgeInHumanYears()
            {
                return Age*7;
            }
            

            并使用您喜欢的格式字符串从 main 调用此方法。

            【讨论】:

            • 糟糕,错误地点击了“无用 (-1)” - 我确实尝试添加 1(我现在已经这样做了),非常抱歉!这是一种更好的方法,因为我可以决定如何处理这个数字。我想如果我一直想把它写成一个控制台,那么原始帖子会更好,但如果我想控制我对结果的处理,那么你的方法 FTW!谢谢
            • +1 这是要走的路。 Dog 类与控制台有什么关系?什么都没有,所以它不应该知道控制台是什么,也不应该使用它。如果我想在 Windows 应用程序中使用它怎么办。长话短说,将框架或 ui 功能排除在“模型”类之外。
            猜你喜欢
            • 1970-01-01
            • 2011-12-11
            • 1970-01-01
            • 1970-01-01
            • 2012-02-17
            • 2018-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多