【问题标题】:Tiered Design With Analytical Widgets - Is This Code Smell? [closed]带有分析小部件的分层设计 - 这段代码有异味吗? [关闭]
【发布时间】:2011-02-02 05:43:40
【问题描述】:

我现在正在使用的想法是拥有一个多层次的分析对象“层”系统,它对一个公共对象执行特定的计算,然后根据它们的结果创建一组新的分析对象。然后,新创建的分析对象将轮到自己运行,并可选择创建更多分析对象,依此类推。关键是子分析对象将始终在创建它们的对象之后执行,这是相对重要的。整个设备将由单个线程调用,因此我目前不关心线程安全。只要满足某个基本条件,我不认为这是一个不稳定的设计,但我还是有点反感。

这是一些严重的代码异味还是我应该继续以这种方式实现它?有没有更好的办法?

这是一个示例实现:

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();
        }
    }
}

【问题讨论】:

    标签: c# .net algorithm collections


    【解决方案1】:

    是的,我称之为代码异味:

            _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++; 
            } 
    

    您正在迭代一个正在变化的集合。我的意思是第一次迭代,而不是第二次。您显然正在考虑这种变化(因此&lt; _tierCount而不是标准foreach)但它仍然是一种气味,IMO。

    我会让它进入生产代码吗?可能。取决于场景。但我会为此感到肮脏。

    另外:您的_tiers 成员也可以很容易地成为List&lt;List&lt;Widget&gt;&gt;

    【讨论】:

      【解决方案2】:

      这里最大的潜在问题是 Sweep 方法正在迭代一个集合 (_tiers),这可能会在调用 Widget.DoMyThing() 时发生变化。

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

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

      【讨论】:

      • _tiers 不会随着迭代而改变;每次调用 Widget.DoMyThing() 都会在 next teir 中添加一个 Widget
      【解决方案3】:

      +1 对 Randolpho 和 LBushkin。

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

      链接:

      Builder Pattern

      Composite Pattern

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        • 1970-01-01
        相关资源
        最近更新 更多