代码之家  ›  专栏  ›  技术社区  ›  Jacobs Data Solutions

带有分析小部件的分层设计-这是代码的味道吗?

  •  2
  • Jacobs Data Solutions  · 技术社区  · 15 年前

    我现在的想法是有一个多层次的“层”分析对象系统,它对一个公共对象执行一定的计算,然后根据结果创建一组新的分析对象。然后,新创建的分析对象将自己运行,并可以选择创建更多的分析对象,依此类推。关键是子分析对象总是在创建它们的对象之后执行,这是相对重要的。整个装置将被一个线程调用,所以我现在不关心线程安全性。只要满足一定的基本条件,我不认为这是一个不稳定的设计,但我仍然有点反胃。

    这是一种严重的代码味道吗?还是我应该这样去实现它?有更好的办法吗?

    下面是一个示例实现:

    namespace WidgetTier
    {
        public class Widget
        {
            private string _name;
    
            public string Name
            {
                get { return _name; }
            }
    
            private TierManager _tm;
            private static readonly Random random = new Random();
    
            static Widget()
            {
            }
    
            public Widget(string name, TierManager tm)
            {
                _name = name;
                _tm = tm;
            }
    
            public void DoMyThing()
            {
                if (random.Next(1000) > 1)
                {
                    _tm.Add();
                }
            }
        }
    
        //NOT thread-safe!
        public class TierManager
        {
            private Dictionary<int, List<Widget>> _tiers;
            private int _tierCount = 0;
            private int _currentTier = -1;
            private int _childCount = 0;
    
            public TierManager()
            {
                _tiers = new Dictionary<int, List<Widget>>();
            }
    
            public void Add()
            {
                if (_currentTier + 1 >= _tierCount)
                {
                    _tierCount++;
                    _tiers.Add(_currentTier + 1, new List<Widget>());
                }
                _tiers[_currentTier + 1].Add(new Widget(string.Format("({0})", _childCount), this));
                _childCount++;
            }
    
            //Dangerous?
            public void Sweep()
            {
                _currentTier = 0;
                while (_currentTier < _tierCount)  //_tierCount will start at 1 but keep increasing because child objects will keep adding more tiers.
                {
                    foreach (Widget w in _tiers[_currentTier])
                    {
                        w.DoMyThing();
                    }
                    _currentTier++;
                }
            }
    
            public void PrintAll()
            {
                for (int t = 0; t < _tierCount; t++)
                {
                    Console.Write("Tier #{0}: ", t);
                    foreach (Widget w in _tiers[t])
                    {
                        Console.Write(w.Name + "  ");
                    }
                    Console.WriteLine();
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                TierManager tm = new TierManager();
    
                for (int c = 0; c < 10; c++)
                {
                    tm.Add();   //create base widgets;
                }
    
                tm.Sweep();
                tm.PrintAll();
    
                Console.ReadLine();
            }
        }
    }
    
    3 回复  |  直到 15 年前
        1
  •  2
  •   Randolpho    15 年前

    是的,我称之为以下代码气味:

            _currentTier = 0; 
            while (_currentTier < _tierCount)  //_tierCount will start at 1 but keep increasing because child objects will keep adding more tiers. 
            { 
                foreach (Widget w in _tiers[_currentTier]) 
                { 
                    w.DoMyThing(); 
                } 
                _currentTier++; 
            } 
    

    当集合正在更改时,您正在对其进行迭代。我是说第一次迭代,不是第二次。很明显你在考虑变化(因此 < _tierCount 而不是标准 foreach )但我还是觉得有味道。

    我可以让它进入生产代码吗?可能。视情况而定。但我会觉得很肮脏。

    还有:你的 _tiers 成员可以很容易地成为 List<List<Widget>> .

        2
  •  1
  •   LBushkin    15 年前

    这里最大的潜在问题是 Sweep 方法正在迭代集合( _tiers )可能会改变 Widget.DoMyThing() .

    .NET BCL类不允许在迭代时更改集合。代码的结构方式暴露了这种情况可能发生的风险。

    除此之外,另一个问题是程序的结构使得很难理解按什么顺序发生的事情。也许您可以将递归组装模型的程序阶段与访问模型并执行计算的部分分开。

        3
  •  0
  •   Jacobs Data Solutions    15 年前

    +一个给兰多尔夫和尔布什金。

    不过,我想了想,我知道为什么会有这种味道。我所实现的模式似乎是对构建器模式的某种歪曲。更好的方法是用一系列分析步骤创建一个组合,这些步骤作为一个整体,代表某种有意义的状态。分析过程(行为)的每个步骤都应该不同于输出组合(状态)。我在上面实现的将状态和行为结合在一起。由于国家所有者和国家分析者是同一客体,这也违反了单一责任原则。使用复合“构建自身”的方法打开了创建恶性循环的可能性,尽管我上面的原型已经确定完成。

    链接:

    Builder Pattern

    Composite Pattern

    推荐文章