thoughtworks笔试题FizzBuzzWhizz

这次thoughtworks放出来的笔试题并不难,可以说大家都会做,不过给TW交作业,更需要注意代码的质量,具备测试代码和代码良好的可读性是必要的。

下面是我的作答,使用c#语言,没看过题目的同学请见这里。

一开始我写出了下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FizzBuzzWhizz {
    public class Game {
        private readonly int _Fizz;
        private readonly int _Buzz;
        private readonly int _Whizz;

        public Game(int fizz, int buzz, int whizz) {
            _Fizz = fizz;
            _Buzz = buzz;
            _Whizz = whizz;
        }

        private bool ContainsFizzChar(int number) {
            return number.ToString().Contains(_Fizz.ToString());
        }

        public IEnumerable<string> Count() {
            for (var n = 1; n <= 100; n++) {
                if (ContainsFizzChar(n))
                    yield return "Fizz";
                else {
                    var s = new StringBuilder();
                    if (n % _Fizz == 0)
                        s.Append("Fizz");
                    if (n % _Buzz == 0)
                        s.Append("Buzz");
                    if (n % _Whizz == 0)
                        s.Append("Whizz");
                    if (s.Length == 0)
                        s.Append(n);

                    yield return s.ToString();
                }
            }
        }
    }
}

搞定,简单、直接,用若干if else去判断每种分支条件,代码就像把题目中的要求翻译成英语,逻辑清晰,代码可读性也不错,但是代码太普通、太平淡了,然后我开始追求更短、更花哨的代码,用工厂模式取代本题中if else判断显然小题大做,然后想到了用Func,写出了下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;

namespace FizzBuzzWhizz {
    public class Game {
        private readonly int _Fizz;
        private readonly int _Buzz;
        private readonly int _Whizz;

        public Game(int fizz, int buzz, int whizz) {
            _Fizz = fizz;
            _Buzz = buzz;
            _Whizz = whizz;
        }

        public IEnumerable<string> Count() {
            var specialNumbers = new Dictionary<int, string> {
                        {_Fizz, "Fizz"},
                        {_Buzz, "Buzz"},
                        {_Whizz, "Whizz"}
                    };

            for (var n = 1; n <= 100; n++) {
                Func<string> containsFizzFunc = () => n.ToString().Contains(_Fizz.ToString()) ? "Fizz" : null;

                Func<string> matchedSpecialNumbersFunc =
                    () => string.Join(string.Empty, specialNumbers.Where(_ => n%_.Key == 0).Select(_ => _.Value));

                Func<string> toStringFunc = () => n.ToString();

                yield return new[] {containsFizzFunc, matchedSpecialNumbersFunc, toStringFunc}
                    .Select(func => func.Invoke())
                    .First(result => !string.IsNullOrWhiteSpace(result));
            }
        }
    }
}

回过头来对比发现,代码行数确实更少了,但我认为可读性、可维护性反而更差,这就是现实中的权衡,用最直接、最简单的方法解决问题,斟酌变量、方法命名,让代码本身成为注释,保持类、方法的职责单一,并不是卖弄代码技巧或滥用设计模式。

如果让我交作业,我会用第一个版本,你呢?

你可能感兴趣的:(C#,笔试题,Thoughtworks,FizzBuzzWhizz)