【问题标题】:C# How to split the following large complex classC#如何拆分以下大型复杂类
【发布时间】:2009-09-30 02:10:10
【问题描述】:

我已经设法将以下 THWorkingMemory 类编程为反模式,即上帝对象。我计划它是一个相当小的类,大约有 20 个方法,但现在它包含了队列处理程序、计时器、线程、回调、powershell 队列回调、事件处理程序、锁处理程序和大约 50 多个方法,即很多。这个类已经变得太大而无法维护,我需要分成更小的类。但是怎么做呢?

THWorkingMemory 类从根本上定义了大约 8 个主要代码块,这将建议 8 个单独的类,但是写入 TreeDictionary 的所有方法都使用 ReaderWriterLockerWrapper。

这里是代码。

interface IWorkingMemory
{
protected CMemory CBase;
protected CMemory CCM { get { .. } 
public abtract event .. 
public abstract void ExecuteAction(Guid ExecutionGuid, string jim ... ...);
    ..
..20+ methods, events   
}

internal sealed class CMemory
{
    public CMemory()
    {
        CBase=new TreeDictionary<Guid, ExecutionState>(new comparer);
    }   ..
}


public sealed class ExecutionState 
{ // 20+ methods. that act against the treedictionary node  }

internal sealed class THWorkingMemory:IWorkingMemory
{   
    lockStrategy = new ReaderWriterLockerWrapper();

    public void ExecuteAction(Guid ExecutionGuid, string jim ... ...)
    {

        lockStrategy.AcquireWriteLock()
            CCM[ExecutionGuid].CreateExecutionState(jim);
        lockStrategy.ReleaseWriteLock()
    }

    2000 lines+ of methods, timers, threading, events, callbacks, 
        queues processing. powershell script callbacks from ExecutionState, etc.
}

private ReaderWriterLockerWrapper
{
    public void AcquireWriteLock(int timeout) {}\n
    public void ReleaseWriteLock() {}
}

我查看了有关部分课程的问题,但没有得到很好的记录。 这在这里是有意义的,因为 THWorkingMemory 类中的大多数方法都使用 ReaderWriterLockerWrapper。

拆分 THWorkingMemory 的最佳方式是什么,因此它保留了锁类的准确性,即确保写入树字典不会发生冲突,即写入被锁定。我还查看了嵌套类,它可以作为一种解决方案,但不能像现在一样使用储物柜。

有什么想法吗?

【问题讨论】:

  • Alfred,感谢您修复我的编辑。鲍勃。

标签: design-patterns oop c#-3.0


【解决方案1】:

我还研究了嵌套类,它可以作为一种解决方案,但不能像现在一样使用储物柜。

如果嵌套类是通过对包含类的引用进行实例化的,则它们可以使用锁定器,以便它们可以使用实例成员数据和/或调用包含类的实例方法。

例如,给定这样的骨架 ...

class THWorkingMemory
{
  class NestedClass
  {
    THWorkingMemory m_self;
    internal NestedClass(THWorkingMemory self)
    {
      m_self = self;
    }

    ... methods of NestedClass can invoke m_self.ExecuteAction
        and/or can access m_self.lockStrategy ...
  }

  NestedClass m_nestedClass;

  internal THWorkingMemory()
  {
    m_nestedClass = new NestedClass(this);
  }
}

...您可以将方法/功能移出 THWorkingMemory 类并移入 NestedClass。


或者,您可以仅将要共享的数据和方法包装到一个类中,并将对该类的引用(而不是对整个容器的引用)传递给您的嵌套类[es]。

class THWorkingMemory
{
  class SharedData
  {
    lockStrategy = new ReaderWriterLockerWrapper();

    public void ExecuteAction(Guid ExecutionGuid, string jim ... ...)
    {
      lockStrategy.AcquireWriteLock()
      CCM[ExecutionGuid].CreateExecutionState(jim);
      lockStrategy.ReleaseWriteLock()
    }
  }

  class NestedClass
  {
    SharedData m_sharedData;
    internal NestedClass(SharedData sharedData)
    {
      m_sharedData = sharedData;
    }

    ... methods of NestedClass can invoke m_sharedData.ExecuteAction
        and/or can access m_sharedData.lockStrategy ...
  }

  SharedData m_sharedData;
  NestedClass m_nestedClass;

  internal THWorkingMemory()
  {
    m_sharedData = new SharedData();
    m_nestedClass = new NestedClass(m_sharedData);
  }
}

编辑

嗯,THWorkingMemory 内存类实现了 IWorkingMemory 接口,这样接口可以传递给嵌套类吗?

我认为你会通过在主类中定义方法来实现主类中的接口,但通过委托给嵌套类中的相应方法来实现这些方法,例如:

interface IWorkingMemory
{
  void SomeMethod();
  void AnotherMethod();
  ... + 20 other methods ...
}

class THWorkingMemory : IWorkingMemory
{
  class NestedClass
  {
    public void SomeMethod()
    {
      ... some complicated implementation here ...
    }

    ... + plus private methods which help to implement the public method ...
  }

  class AnotherNestedClass
  {
    public void AnotherMethod()
    {
      ... some complicated implementation here ...
    }

    ... + plus private methods which help to implement the public method ...
  }

  SharedData m_sharedData;
  NestedClass m_nestedClass;
  AnotherNestedClass m_anotherNestedClass;

  internal THWorkingMemory()
  {
    m_sharedData = new SharedData();
    m_nestedClass = new NestedClass(m_sharedData);
    m_anotherNestedClass = new AnotherNestedClass(m_sharedData);
  }

  #region implement IWorkingMemory methods

  public void SomeMethod()
  {
    //implement by delegating to the implementation in the nested class
    m_nestedClass.SomeMethod();
  }

  public void AnotherMethod()
  {
    //implement by delegating to the implementation in the nested class
    m_anotherNestedClass.AnotherMethod();
  }

  ... + 20 other methods ...

  #endregion
}

注意:

  • 您的主类现在很简单/微不足道:所有复杂性都封装在嵌套类中
  • 每个嵌套类都可能有私有的实现细节,它对其他类隐藏了
  • 这些嵌套类可能不需要嵌套:您可以改为将它们设为“internal”类
  • 你的主类变成了Facade

【讨论】:

  • 嗨,克里斯,感谢您这么快回来。我今晚和明天看看。鲍勃。
  • 嗨,克里斯,我看过了,但是这些解决方案是否适用于来自 IWorkingMemory 的接口实现
  • 我不明白您的最新评论/问题。
  • 嗯,THWorkingMemory 内存类实现了IWorkingMemory 接口,这样接口可以传递给嵌套类吗?鲍勃
  • 太酷了。我什至没有想过这样做。 B
【解决方案2】:

我会研究SOLID 原则。特别是单一责任原则。我发现它们在分析一个类以确定如何拆分它时非常有用。我还使用了 Fowler 的重构 catalog。有时仅仅通过浏览它,我就会发现一个我没想过要使用的重构。

我在检查函数时使用的一些一般准则:

  • 它是否依赖于任何私有类字段?如果它不是移动到单独班级的自动候选者。
  • 函数可以很容易地泛化吗?换句话说,它的逻辑是否与它所操作的类数据的结构相关联,或者只要稍加修改,它就可以在其他地方使用。如果可以概括,请将其移至单独的类。

当然,如果您有一套良好的单元测试作为开始移动事物时的安全网,这将大有帮助。

您可能也对http://refactormycode.com/感兴趣

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 2023-02-09
    • 2021-08-29
    • 1970-01-01
    相关资源
    最近更新 更多