代码之家  ›  专栏  ›  技术社区  ›  Coding Monkey

施工设计

  •  7
  • Coding Monkey  · 技术社区  · 15 年前

    我有一个类,你在一个文件夹中传递它,然后它关闭并处理指定文件夹中的大量数据。

    例如:

    MyClass myClass = new MyClass(@"C:\temp");
    

    现在,它会关闭并读取数千个文件,并用数据填充类。

    我是否应该将此数据从构造函数中移出并将其作为单独的方法,如下面的方法?

    MyClass myClass = new MyClass();
    myClass.LoadFromDirectory(@"C:\temp");
    
    9 回复  |  直到 6 年前
        1
  •  22
  •   Tom Anderson    15 年前

    也许您应该用一个返回对象实例的静态方法来尝试这种方法。

    var myClass = MyClass.LoadFromDirectory(@"C:\temp");
    

    这将使初始化代码保持在构造函数之外,并为您提供所需的“一行”声明。


    从下面的海报中继续评论,通过添加状态,实现可以是这样的:

    public class MyClass
    {
    
    #region Constructors 
    
        public MyClass(string directory)
        {
            this.Directory = directory;
        }
    
    #endregion
    
    #region Properties
    
        public MyClassState State {get;private set;}
    
        private string _directory;
    
        public string Directory 
        {
            get { return _directory;} 
            private set 
            {
                _directory = value; 
                if (string.IsNullOrEmpty(value)) 
                    this.State = MyClassState.Unknown; 
                else 
                    this.State = MyClassState.Initialized;
            }
        }
    
    #endregion
    
    
    
        public void LoadFromDirectory()
        {
            if (this.State != MyClassState.Initialized || this.State != MyClassState.Loaded)
                throw new InvalidStateException();
    
            // Do loading
    
            this.State = MyClassState.Loaded;
        }
    
    }
    
    public class InvalidStateException : Exception {}
    
    
    public enum MyClassState
    {
        Unknown,
        Initialized,
        Loaded
    }
    
        2
  •  5
  •   Cerebrus    15 年前

    这要看情况而定。你应该评估课程的基本目的。它执行什么功能?

    我通常喜欢让一个类构造函数为类的运行做必要的初始化。然后我调用类上的方法,这样可以安全地假定已经完成了必要的初始化。

    通常,初始化阶段不应该太密集。执行上述操作的另一种方法可能是:

    // Instantiate the class and get ready to load data from files.
    MyClass myClass = new MyClass(@"C:\temp");
    
    // Parse the file collection and load necessary data.
    myClass.PopulateData();
    
        3
  •  1
  •   Robert Harvey    15 年前

    这就是你们班的全部工作吗?如果是这样的话,我会说这并不重要。但很可能你的课实际上做的比你所展示的要多。例如,它是否有任何错误处理?

    构造函数的目的是构造一个对象。方法的目的是执行操作。所以我投票赞成这个形式:

    MyClass myClass = new MyClass();
    myClass.LoadFromDirectory(@"C:\temp");
    
        4
  •  1
  •   Jason Williams    15 年前

    我同意阿里和其他人的看法——把他们分开。

    一个构造函数应该真正完成最少的工作量(只需初始化准备好使用的对象,然后就可以使用了)。通过使用单独的方法完成工作:

    • 对调用者来说,工作函数可能需要很长时间。
    • 很容易提供几个构造函数来用不同的信息初始化对象(例如,您可能能够传入自己的类(而不是字符串),该类可以提供路径名。或者,您可以传递一个额外的参数,该参数指定要匹配的通配符文件名,或者传递一个标志来指定搜索是否应循环到子文件夹中)。
    • 您可以避免与构造函数有关的任何问题。在构造函数中,对象没有完全形成,因此进行工作可能很危险——例如,在构造函数中调用虚函数是一个非常糟糕的主意。你在构造器中输入的代码越少,你就越不可能意外地做一些“坏”的事情。
    • 将不同的行为/功能分为不同的方法是一种更清晰的编码方式。保持初始化和工作分离
    • 拆分类在将来更容易维护和重构。
        5
  •  0
  •   Noam Gal    15 年前

    我认为您应该根据是否计划重用同一对象在不同的输入上执行相同的操作来决定上述两种方法(“先初始化,然后执行”vs“empty init,perform with params”)。
    如果类仅用于在固定参数上运行任务,我将在构造函数中初始化它(使其为只读),然后在其他方法上执行任务。
    如果您想继续在不同的参数上执行任务,我将把它放在task方法本身中。

    如果所有的类都是这个任务,我也会考虑将其全部更改为静态类/方法-它不需要保持其内部状态。

    无论如何,我永远不会将任务本身放在构造函数中。如小脑所说,初始化应该很快。

        6
  •  0
  •   finnw    15 年前

    除非类的主要目的是执行I/O,否则您可能不应该在构造函数中执行I/O(可能引发IOException)。

    考虑将类分成两部分:

    interface IMyDataSource
    {
       // ...
    }
    
    class FileDataSource: IMyDataSource
    {
        public FileDataSource(string path)
        {
            // ...
        }
    }
    
    class MyClass
    {
        public MyClass(IMyDataSource source)
        {
             // ...
        }
    }
    
    IMyDataSource myDS = new FileDataSource(@"C:\temp");
    MyClass myClass = new MyClass(myDS);
    

    这样,主类可以专注于管理自己的状态,而数据源则从文件内容构建初始状态。

        7
  •  0
  •   Serge    15 年前

    如果这是类所使用的唯一资源,那么最好将路径传递给构造函数。否则,它将是类成员的参数。

        8
  •  0
  •   richardtallent    15 年前

    我个人的偏好是使用C 3.0初始值设定项。

    class MyClass {
        public string directory;
        public void Load() {
          // Load files from the current directory
          }
      }
    
    MyClass myClass = new MyClass{ directory = @"C:\temp" };
    myClass.Load();
    

    这有几个优点:

    • 对象实例化将没有 自动文件系统副作用。
    • 所有参数都已命名。
    • 所有参数都是可选的(但是, 当然,可以扔一个 加载()中的异常(如果未定义)
    • 可以初始化尽可能多的属性 在实例化调用中需要 无需超载 构造函数。例如,选项 对于是否重复使用目录, 或用于文件规范搜索的通配符 为了。
    • 你还是可以有一些逻辑的 在要执行的目录的setter中 一些东西,但同样的,副作用 通常不是好事。
    • 通过在 单独程序调用,避免 不能 在中引用MyClass实例 异常处理程序。
        9
  •  0
  •   Ari Roth    15 年前

    我要回应这里的“分裂他们”。如果有帮助,请尝试以下操作:

    1. 问问自己,“这个方法/属性/字段是什么?
    2. 让它这样做,不多不少。

    在这里应用,你会得到:

    1. 构造函数应该创建对象。
    2. 您的方法应该从文件系统加载它的数据。

    在我看来,这比“构造函数应该创建对象”更合乎逻辑。 从文件系统加载数据。