Re[2]: Вариант 0K
От: xpalex  
Дата: 01.09.10 06:09
Оценка:
Здравствуйте, 0K, Вы писали:

0K>Здравствуйте, 0K, Вы писали:


0K>Для порядка размещу и свой вариант. В конкурсе я специально не стал учавствовать (конкурс закончился сегодня 1 сентября) из-за неадекватного поведения некоторых товарищей.


0K>Собственно вариант и несколько комментариев:


0K>
0K>using System;
0K>using System.Globalization;
0K>using System.IO;
0K>using System.Runtime.Serialization;
0K>using System.Security;

0K>namespace ConsoleApplication1
0K>{
0K>    [Serializable]
0K>    public class CounterException : Exception
0K>    {
0K>        public CounterException() { }
0K>        public CounterException(string message) : base(message) { }
0K>        public CounterException(string message, Exception innerException) : base(message, innerException) { }
0K>        protected CounterException(SerializationInfo info, StreamingContext context)
0K>            : base(info, context) { }
0K>    }

0K>    public class Counter
0K>    {
0K>        private string _path;

0K>        public string Alias { get; protected set; }
0K>        public int Count { get; protected set; }

0K>        protected Counter() { }

0K>        /// <exception cref="ArgumentNullException">alias is null.</exception>
0K>        /// <exception cref="ArgumentOutOfRangeException">alias is empty</exception>
0K>        /// <exception cref="ArgumentException">Invalid character</exception>
0K>        public Counter(string alias)
0K>        {
0K>            if (null == alias)
0K>                throw new ArgumentNullException("alias");

0K>            if (string.IsNullOrEmpty(alias))
0K>                throw new ArgumentOutOfRangeException("alias");

0K>            if (alias.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
0K>                throw new ArgumentException("Invalid character.");

0K>            Alias = alias;
0K>            _path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Alias);
0K>        }

0K>        public static Counter TryParse(string alias)
0K>        {
0K>            try { return new Counter(alias); }
0K>            catch (ArgumentException)
0K>            {
0K>                return null;
0K>            }
0K>        }

0K>        /// <exception cref="CounterException"></exception>
0K>        public void Load()
0K>        {
0K>            int count;

0K>            if (File.Exists(_path))
0K>            {
0K>                try
0K>                {
0K>                    string text = File.ReadAllText(_path);

0K>                    if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out count))
0K>                        count = 0;
0K>                }
0K>                catch (PathTooLongException exception)
0K>                {
0K>                    throw new CounterException(exception.Message, exception);
0K>                }
0K>                catch (UnauthorizedAccessException exception)
0K>                {
0K>                    throw new CounterException(exception.Message, exception);
0K>                }
0K>                catch (FileNotFoundException)
0K>                {
0K>                    count = 0;
0K>                }
0K>                catch (SecurityException exception)
0K>                {
0K>                    throw new CounterException(exception.Message, exception);
0K>                }
0K>                catch (IOException exception)
0K>                {
0K>                    throw new CounterException(exception.Message, exception);
0K>                }
0K>            }
0K>            else
0K>                count = 0;

0K>            Count = count;
0K>        }

0K>        public void Increment()
0K>        {
0K>            Count++;
0K>        }

0K>        /// <exception cref="CounterException"></exception>
0K>        public void Save()
0K>        {
0K>            try
0K>            {
0K>                File.WriteAllText(_path, Count.ToString(CultureInfo.InvariantCulture.NumberFormat));
0K>            }
0K>            catch (PathTooLongException exception)
0K>            {
0K>                throw new CounterException(exception.Message, exception);
0K>            }
0K>            catch (UnauthorizedAccessException exception)
0K>            {
0K>                throw new CounterException(exception.Message, exception);
0K>            }
0K>            catch (FileNotFoundException exception)
0K>            {
0K>                throw new CounterException(exception.Message, exception);
0K>            }
0K>            catch (SecurityException exception)
0K>            {
0K>                throw new CounterException(exception.Message, exception);
0K>            }
0K>            catch (IOException exception)
0K>            {
0K>                throw new CounterException(exception.Message, exception);
0K>            }
0K>        }
0K>    }

0K>    public class Program
0K>    {
0K>        static void Main(string[] args)
0K>        {
0K>            const string YES_SYMBOLS = "YyДд";

0K>            bool first = true;
0K>            Counter counter;

0K>            while (true)
0K>            {
0K>                if (!first)
0K>                {
0K>                    Console.WriteLine("Повторить?");

0K>                    if (!YES_SYMBOLS.Contains(Console.ReadLine()))
0K>                        break;

0K>                    Console.Clear();
0K>                }
0K>                else
0K>                    first = false;

0K>                Console.WriteLine("Введите имя счетчика:");
0K>                string alias = Console.ReadLine();

0K>                counter = Counter.TryParse(alias);

0K>                if (null == counter)
0K>                {
0K>                    Console.WriteLine("Некорректное имя счетчика (пояснение каким должно быть правильное имя).");
0K>                    continue;
0K>                }

0K>                try
0K>                {
0K>                    counter.Load();
0K>                }
0K>                catch (CounterException exception)
0K>                {
0K>                    Console.WriteLine("Ошибка при получении значения счетчика." + Environment.NewLine + exception.Message);
0K>                    continue;
0K>                }

0K>                Console.WriteLine("Текущее значение счетчика {0}: {1}.", counter.Alias, counter.Count);

0K>                counter.Increment();

0K>                try
0K>                {
0K>                    counter.Save();
0K>                }
0K>                catch (CounterException exception)
0K>                {
0K>                    Console.WriteLine("Ошибка при сохранении нового значения счетчика." + Environment.NewLine + exception.Message);
0K>                    continue;
0K>                }
0K>            }
0K>        }
0K>    }
0K>}
0K>


0K>Главная загвоздка в данном задании -- целая гармошка возможных исключений при работе с файлами. И по идее (которую даже сами MS не выполняют)

0K> -- нельзя использовать Exception. Я решил так и оставить эту гармошку (5 исключений) в 2-х местах, т.к. в .Net нет вменяемых средств для устранения дублирования и повышения читаемости такого кода.

0K>Весь смысл кода -- обернуть эту гармошку в одно простое исключение, ясно отражающее причину ошибки и содержащее всю необходимую информацию.


0K>Если кто-то сможет покритиковать по делу или добавить свой вариант -- буду благодарен.


Про поведение:
1. После инкремента значения 2147483647 в файле оказывается отрицательно число.
2. При указании имени счетчика ".." пишет "Текущее значение счетчика ..: 0"

Я понимаю, что ТЗ ваше, и, наверное, так требовалось по ТЗ.

Про код:
1. Зачем метод Counter.TryParse, если вы на том же уровне (из Program.Main) делаете обернутый counter.Load и counter.Save? Что мешало сделать такой же обернутый new Counter(alias)? Как-то непоследовательно...

2. Не описана ответственность класса Counter. Можно-ли дергать за .Increment() до .Load() ? Можно-ли дергать за .Increment() после .Save()? Тут явное нарушение SRP: класс отвечает как за инкремнтирование счетчика, так и за работу с файловым хранилищем.

3. Counter.Increment() гаранитрует успешеное выполнение ?

4. Console.ReadLine() тоже может бросать исключения.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.