Re[10]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 17.08.10 14:30
Оценка:
Здравствуйте, gandjustas, Вы писали:

0K>>Можно усложнить так, чтобы Settings было использовать не выгодно -- но потеряется наглядность.

G>Да не надо усложнять, просто приведи описание задачи, а не код, который её якобы решает. Код тебе тут напишут моментально.

Задача: продемонстрировать правильную работу с исключениями на примере простой программы, которая напрямую читает файл с числом, изменяет его и записывает обратно (см выше). Представьте что нет готовых классов для работы с пользовательскими настройками -- делайте прямым обращением к файлу. Иначе всегда можно найти готовую библиотеку. Почему стоит себя ограничивать именно библиотеками MS?
=сначала спроси у GPT=
Re[3]: Конкурс на умение работать с Exception
От: Neco  
Дата: 17.08.10 14:39
Оценка: 18 (3)
Здравствуйте, 0K, Вы писали:

0K>Ожидается максимальное удобно для среднестатистического пользователя. Вот ключ. А то попривыкли мозги отключать.

Что-то вы какой-то злой сёдня.
Среднестатический пользователь бывает разный. Есь пользователь-домохозяйка, пользователь-айтишник, пользователь-прогер (т.е. пользователь кода). Удобство у каждого своё.
Подход "думать за пользователя" он вообще неправильный. Думать имеет смысл, когда нет возможности спросить его или он сам не знает как точно надо — тогда и надо вводить все эти гибкости в коде, которые усложнят его создание, но упростят изменения.
А когда заказчик под боком и вопросы на поверхности — надо спрашивать и получать ответы.
Но понятно, что вам лень думать даже над простыми сценариями, так что я буду писать самый короткий и понятный код, взяв все свои предположения о требованиях за истину. И этот код после тестирования будем усложнять, лады?
Пока что вижу такие основные требования:
1. программа должна накидывать счётчик, показывая старое значение (почему-то) и записывая новое;
2. программа должна уметь выводить два типа сообщений;
3. программа после ошибки должна позволять вводить данные повторно;

заметьте, нет примеров ошибок и сообщений которые хотел бы получать пользователь. поэтому я их тоже сам додумаю.

0K>1. Ее будут использовать и совсем неопытные пользователи?

выше были среднестатические ))

0K>2. Нужен код, который легко перенести в Win/WPF-приложение.

код бизнес-логики или код вывода ошибок? вывод ошибок непереносим — он везде уникален. Точнее может он и переносим (можно и зайца научить курить), но смысл?

В общем, вот мой код на конкурс самых суперских программистов.

using System;
using System.IO;
using System.Reflection;

namespace ConsoleApplication1 {
    #region Presentation
    class Program {
        static void Main(string[] args) {
            bool exitProgram = false;

            do {
                try {
                    Console.WriteLine("Enter the name of a counter and press ENTER:");
                    string fileName = Console.ReadLine();
                    var incrementor = new Incrementor((new FileNameGenerator()).GenerateFileName(fileName));
                    var result = incrementor.PerformIncrement();
                    Console.WriteLine("Value of counter: {0}", result.PreviousValue);
                    exitProgram = true;
                    Console.WriteLine("Press enter for exit.");
                    Console.ReadLine();
                } catch (Exception ex) {
                    var myFriend = new FriendlyMessageGenerator();
                    var msg = myFriend.GetFriendly(ex);
                    Console.WriteLine("Friendly message: {0}", msg.Message);
                    Console.WriteLine("Error details: {0}", msg.Details);
                    
                    Console.WriteLine("Would you like to try again?");
                    if (Console.ReadLine().Equals("n", StringComparison.OrdinalIgnoreCase)) {
                        exitProgram = true;
                    }
                }
            } while (!exitProgram);

        }
    }
    #endregion

    #region SharedApplicationComponent
    public class FileNameGenerator {
        private const string EXTENSION = ".txt";
        public string GenerateFileName(string counterName) {
            return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + counterName + EXTENSION;
        }
    }
    public class FriendlyMessageGenerator {
        public FriendlyMessage GetFriendly(Exception ex) {
            string message;
            if (ex is IncrementorException) {
                message = (ex as IncrementorException).Message;
            } else {
                message = "Unexpected error has been happened during executing the task. Please, see the details.";
            }
            return new FriendlyMessage(message, ex);
        }
    }
    public class FriendlyMessage {
        public FriendlyMessage(string message, Exception exception) {
            Message = message;
            Details = exception;
        }
        public string Message { get; private set; }
        public Exception Details { get; private set; }
    }
    #endregion

    #region BusinessLogicComponent
    public class Incrementor {
        private string _counterFileName;
        private const int STARTUP_NUMBER = 0;
        
        public Incrementor(string counterFileName) {
            _counterFileName = counterFileName;
        }
        public Result PerformIncrement() {
            CreateFileIfItDoesNotExist();
            var oldValue = ReadCurrentValue();
            var newValue = oldValue + 1;
            WriteNewValue(newValue);
            return new Result(oldValue, newValue);
        }
        private int ReadCurrentValue() {
            try {
                return int.Parse(File.ReadAllText(_counterFileName));
            } catch (Exception ex) {
                throw new IncrementorException("Error during reading current value", ex);
            }
        }
        private void WriteNewValue(int newValue) {
            try {
                File.WriteAllText(_counterFileName, newValue.ToString());
            } catch (Exception ex) {
                throw new IncrementorException("Error during writing new value", ex);
            }
        }
        private void CreateFileIfItDoesNotExist() {
            if (!File.Exists(_counterFileName)) {
                try {
                    File.Create(_counterFileName).Close();
                    File.WriteAllText(_counterFileName, STARTUP_NUMBER.ToString());
                } catch (Exception ex) {
                    throw new IncrementorException("Error during file creating", ex);
                }
            }
        }
    }
    public class IncrementorException : Exception {
        public IncrementorException() { }
        public IncrementorException(string message) : base(message) { }
        public IncrementorException(string message, Exception inner) : base(message, inner) { }
        protected IncrementorException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }
    }
    public class Result {
        public Result(int previousValue, int newValue) {
            PreviousValue = previousValue;
            NewValue = newValue;
        }
        public int PreviousValue { get; private set; }
        public int NewValue { get; private set; }
    }
    #endregion
}


т.е. если в двух словах, то я за такой вид обработки ошибок:
        private void WriteNewValue(int newValue) {
            try {
                File.WriteAllText(_counterFileName, newValue.ToString());
            } catch (Exception ex) {
                throw new IncrementorException("Error during writing new value", ex);
            }
        }

это должно делаться на более-менее высоком уровне, чтобы не мельчить.

И реальный FriendlyMessageGenerator навороченней — он делает рекурсивный обход всех Inner сообщений и собирает информацию не только из моих собственных исключений (у которых надо просто Message прочитать), но и читает Message'ы оракловых исключений и позволяет выдавать дружественные ошибки типа "База данных недоступна" или "Нарушение целостности связки Работник-Отдел.". Это если сильно надо. А в большинстве случаев просто смотришь в детали и понимаешь в чём дело.

Кстати, в ответ попрошу и свой код выложить.
всю ночь не ем, весь день не сплю — устаю
Re[4]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 17.08.10 14:39
Оценка:
Здравствуйте, microcod, Вы писали:

M>Файл вполне доступен, только видимо слишком большой для программы. Ничего не "разжёвывается".


Плохой пример.

Вот PaintNet что выдал (стандартный диалог, кстати):

---------------------------
Open
---------------------------
File C:\#$# does not exist.

Verify that the correct file name was given.
---------------------------
OK
---------------------------


---------------------------
Open
---------------------------
8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
The above file name is invalid.
---------------------------
OK
---------------------------


А вот если файл заблокирован:


---------------------------
Paint.NET
---------------------------
An I/O error occurred when writing to the file.
---------------------------
OK
---------------------------


Я так понимаю это просто Message от IOException.

---------------------------
Paint.NET
---------------------------
There was an error reading the file from the media.
---------------------------
OK
---------------------------


А это просто Paint:

---------------------------
Paint
---------------------------
A sharing violation occurred while accessing C:\Untitled.png.
---------------------------
OK
---------------------------

Здесь даже детали есть.
=сначала спроси у GPT=
Re[3]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 17.08.10 15:02
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>1)WriteToFile не выкидывает эксепшн в случае неудачи

G>2)Не проверяется ACL, а только разрешения CAS
G>3)Не обрабатываются абсолютные пути
G>4)Не обрабатывается отсутствие каталога

Попробуйте не повторить его ошибок. Критиковать каждый может.

G>ЗЫ. Не тот уровень абстракции, чтобы такие задачи решать.


Т.е. вы хотите сказать, что простым чтением из файла и простой записью в файл эта задача не разрешима в принципе? Или вы просто не в состоянии этого сделать?
=сначала спроси у GPT=
Re[10]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 17.08.10 15:12
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

0K>>Можно усложнить так, чтобы Settings было использовать не выгодно -- но потеряется наглядность.

G>Да не надо усложнять, просто приведи описание задачи, а не код, который её якобы решает. Код тебе тут напишут моментально.

Кстати, придумал как вам объяснить.

Нужно чтобы код писал именно в файл (простой файл, внутри цифра), т.к. этот файл будут использовать из другой программы, которая не умеет работать с XML (и перекомпилить эту супер-мега программу нельзя, т.к. нет исходного кода и толком никто не знает как именно она работает -- единственный интерфейс -- этот файл со счетчиком).

Понятна теперь задача? Понятно почему нельзя Settings использовать?

А теперь покажите на практике, что вы действительно такой умный. Предидущие два ответа были с глобальным перехватом Exception. Вы против. Покажите нам как эту задачу решить правильно Или вы только на словах такой умный?
=сначала спроси у GPT=
Re[11]: Конкурс на умение работать с Exception
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 17.08.10 17:10
Оценка:
Здравствуйте, 0K, Вы писали:

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


0K>>>Можно усложнить так, чтобы Settings было использовать не выгодно -- но потеряется наглядность.

G>>Да не надо усложнять, просто приведи описание задачи, а не код, который её якобы решает. Код тебе тут напишут моментально.

0K>Задача: продемонстрировать правильную работу с исключениями на примере простой программы, которая напрямую читает файл с числом, изменяет его и записывает обратно (см выше).

Переведу на русский: продемонстрировать правильную работу с исключениями на примере неправильной программы.

Вообще-то я говорил про задачу с точки зрения пользователя.

0K>Представьте что нет готовых классов для работы с пользовательскими настройками -- делайте прямым обращением к файлу. Иначе всегда можно найти готовую библиотеку. Почему стоит себя ограничивать именно библиотеками MS?

1)Они идут в комплекте
2)Они решают задачи
Re[4]: Конкурс на умение работать с Exception
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 17.08.10 17:17
Оценка:
Здравствуйте, 0K, Вы писали:

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


G>>1)WriteToFile не выкидывает эксепшн в случае неудачи

G>>2)Не проверяется ACL, а только разрешения CAS
G>>3)Не обрабатываются абсолютные пути
G>>4)Не обрабатывается отсутствие каталога

0K>Попробуйте не повторить его ошибок. Критиковать каждый может.


не повторять ошибок — сделать на более высоком уровне абстракции. Обычный механизм сеттингов защитит от обработки отсутствия файла, проблем с доступом, именами файлов и неправильными значениями. Остальные ошибки и нет смысла обрабатывать ибо сделать все равно ничего не получится.

G>>ЗЫ. Не тот уровень абстракции, чтобы такие задачи решать.


0K>Т.е. вы хотите сказать, что простым чтением из файла и простой записью в файл эта задача не разрешима в принципе? Или вы просто не в состоянии этого сделать?

Вполне в состоянии, но полезный код погрязнет в обилии низкоуровневых, и вообще-то ненужных, деталей.

Единственный способ правильно решать такую задачу, отчасти повторить механизм сеттингов и использовать его в своем коде. Но этим сильно лень заниматься ибо есть стандартные средства.
Re[11]: Конкурс на умение работать с Exception
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 17.08.10 17:21
Оценка:
Здравствуйте, 0K, Вы писали:

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


0K>>>Можно усложнить так, чтобы Settings было использовать не выгодно -- но потеряется наглядность.

G>>Да не надо усложнять, просто приведи описание задачи, а не код, который её якобы решает. Код тебе тут напишут моментально.

0K>Кстати, придумал как вам объяснить.


0K>Нужно чтобы код писал именно в файл (простой файл, внутри цифра), т.к. этот файл будут использовать из другой программы, которая не умеет работать с XML (и перекомпилить эту супер-мега программу нельзя, т.к. нет исходного кода и толком никто не знает как именно она работает -- единственный интерфейс -- этот файл со счетчиком).


То есть
1)Файл гарантировано есть и заранее известен
2)Доступ к файлу гарантировано есть
3)Значение счетчика, записанного туда, обязательно корректно

0K>Понятна теперь задача? Понятно почему нельзя Settings использовать?

Конечно

0K>А теперь покажите на практике, что вы действительно такой умный.

Возьму код из первого поста и пропишу в нем путь к файлу.

0K>Предидущие два ответа были с глобальным перехватом Exception. Вы против.

Я не против.

0K>Покажите нам как эту задачу решить правильно

См выше.
Re[7]: Конкурс на умение работать с Exception
От: IT Россия linq2db.com
Дата: 17.08.10 18:13
Оценка: +3
Здравствуйте, 0K, Вы писали:

0K>Понятно. Вы кодер, который реальные задачи не решает. Вот если все по полочкам распишут, разжуют -- тогда смогу накодить чего-нибудь. Здесь задачка чуть сложнее: не только кодинг но и подумать нужно. Вероятно такие решает ваш босс.


Слудующий переход на личности или неуважительное отношение к посетителям форума закончится продолжительным баном.
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Конкурс на умение работать с Exception
От: Nikolay_P_I  
Дата: 17.08.10 18:32
Оценка:
Здравствуйте, 0K, Вы писали:


0K>А это просто Paint:


0K>---------------------------

0K>Paint
0K>---------------------------
0K>A sharing violation occurred while accessing C:\Untitled.png.
0K>---------------------------
0K>OK
0K>---------------------------

0K>Здесь даже детали есть.


Здесь правильно про сценарии использования говорили. У нас половина такого кода просто прокидывает исходное исключение дальше и выводит юзеру окно с требованием позвать администратора системы. В окне все аж со стектрейсом. Ибо не юзерское это дело — голову ломать над тем — каких прав на чтение какого файла почему не хватает и как это ему, юзеру, исправлять.
Re: И сбоку бантик
От: akasoft Россия  
Дата: 17.08.10 20:56
Оценка: 16 (2)
Здравствуйте, 0K, Вы писали:

0K>И придумал вот такой максимально простой тест (буквально 7 строчек кода внутри функции) для выявления человека, который действительно лучше всех умеет работать с исключениями. Не на словах а на деле. Вот сам код:


В отличие от темы "курицы и яйца" код однозначно вторичен, а первично описание или ТЗ или use case. Короче, любимое наше "что делать". (А потом, само собой, "кто виноват".)

А поскольку описания нет, а есть только код, значит, не будем фантазировать, а будем его читать. Я придерживаюсь мнения тех, кто считает, что код пишут, чтобы его читать.

Пронумеруем код для удобства анализа, только значащие строки.

0K>
0K>using System;
0K>using System.IO;

0K>namespace ConsoleApplication1
0K>{
0K>    class Program
0K>    {
0K>        static void Main(string[] args)
0K>        {
0K>01            Console.WriteLine("Введите имя счетчика и нажмите ENTER:");
            
0K>02            string fileName = Console.ReadLine();

0K>            // Если файла не существует -- нужно создать.
0K>            // Может не быть доступа к файлу
0K>            // Имя счетчика может быть некорректным -- с этим что-то нужно сделать
0K>03            string text = File.ReadAllText(fileName);

0K>04            int count = int.Parse(text);

0K>05            Console.WriteLine("Значение счетчика: ", count);

0K>06            count++;

0K>            // Может быть запрещена запись в файл
0K>07            File.WriteAllText(fileName, count.ToString());
0K>        }
0K>    }
0K>}
0K>


Что мы видим? В строке 01 вывод приглашения, если мы его вывести не сможем, то продолжать работу дальше бессмысленно. В строке 02 мы определяем переменную и пробуем ввести нечто, являющееся именем файла. Опять же, продолжение бессмысленно, если вылетит исключение. В строке 03 мы видим чтение файла, а перед этим три строчки комментария, которые и будут нашим руководством к действию. Если файла не существует, нам приедет FileNotFoundException, что приедет в случае отсутствия доступа или некорректного для FS имени — с лёта не скажу, а искать влом. Тем не менее, несколько минут отладки в среде и эмуляция проблем, либо запуск приложения в реальных пользовательских условиях с протоколируованием необработанных исключений — замечательно поймают названия исключений, на которые мы и будем довешивать свою реакцию, если она нужна и разумна. По аналогии с NotFoundException. Ещё есть вариант почитать описание вызываемых методов, там иногда бывает нужная нам информация об исключениях. Не всегда, конечно, документация поспевает за полётом мысли, но всё же. Я намеренно не стал читать, и реагировать на. Начинаем писать код:

Console.WriteLine("Введите имя счетчика и нажмите ENTER:");
string fileName = Console.ReadLine();
string text = "";
try
{
    text = File.ReadAllText(fileName);
}
catch (NotFoundException e)
{
    text = "-1"
}


Что мы имеем? Определение переменной text вынесено за блок try, реакция на NotFoundException одна — подавляем, ибо отсутствие файла не является основанием для аварийного завершения работы, плюс записываем в переменную text значение "-1".

Читаем дальше. В строке 04 видим разбор полученного на предыдущем шаге значения. Тут мы можем словить FormatException, если окажется, что то, что мы проситали — не число. Реагируем на из предположения (тут включилась Боевая Телепатия, в коде про это ничего нет!), что если там чёртичто, то должен быть сбоку бантик, т.е. "-1":

int count = 0;
try
{
    count = int.Parse(text);
}
catch (FormatException e)
{
    count = -1;
}


Опять же, определение переменной count уехало за блок try.
В строке 05 выводим значение, если не смогли, то опять всё бессмысленно. Аналогично и для строки 06. А вот со строкой 07 надо предусмотреть реакцию на SecurityException (тут опять лезет Боевая Телепатия и шепчет про UnauthorizedAccessException, но я её убедительно гоню указующим жестом.). Но какую реакцию? Читаемый нами код в строке 07 и комментарий над ней ничего не говорит нам о том, как же мы должны реагировать. Раз не говорит, то и реакции не будет. Тут Боевая Телепатия в третий раз закинула невод, и предлагает регировать выводом сообщения в консоль, а то мало перехватов исключений. И по аналогии добавить вывод в консоль сообщения об отсутствующем/существующем файле. Поскольку целью программы является инкремент счётчика, и именно этого мы сделать не можем из-за прилетевшего исключения, то мы не подавляем, а пробрасываем исключение в вызывающий код. Получаем:

static void Main(string[] args)
{
    Console.WriteLine("Введите имя счетчика и нажмите ENTER:");
    
    string fileName = Console.ReadLine();

    string text = "";
    try
    {
        text = File.ReadAllText(fileName);
        Console.WriteLine("Счётчик '{0}' найден.", text);
    }
    catch (NotFoundException e)
    {
        text = "-1"
        Console.WriteLine("Счётчик '{0}' не найден и будет создан.", text);
    }

    int count = 0;
    try
    {
        count = int.Parse(text);
    }
    catch (FormatException e)
    {
        count = -1;
    }

    Console.WriteLine("Значение счетчика: ", count);

    count++;

    try
    {
        File.WriteAllText(fileName, count.ToString());
    }
    catch (SecurityException e)
    {
        Console.WriteLine("Счётчик '{0}' обновить не удалось.", text);
        throw;
    }
}


Какие будут выводы?
0. Консольные приложения пишутся не так, как оконные. Без интерактива. Обычно они представляют собой команды, принимают параметры из командной строки, понимают перенаправление вывода, взводят errorlevel, и пр. Автором темы это всё, похоже, опущено.
1. Код, выделенный жирным, и особенно последний блок try-catch надо выкинуть, ибо написан он под воздействием Боевой Телепатии, а таковую надо гнать.
2. Предложенное автором темы описание задачи не достаточное и не полное, что требует ментальных усилий по удержанию Боевой Телепатии в узде от желания врубить воображение и безосновательно раздуть код.
3. Поскольку в описании автора темы не предусмотрено реакции программы на ошибки и сбои, кроме скудных комментариев в двух местах, то и я не буду выдумывать отсебятину, глобальные перехваты и вывод красочных сообщений. Итого код:

static void Main(string[] args)
{
    Console.WriteLine("Введите имя счетчика и нажмите ENTER:");
    
    string fileName = Console.ReadLine();

    string text = "";
    try
    {
        text = File.ReadAllText(fileName);
    }
    catch (NotFoundException e)
    {
        text = "-1"
    }

    int count = 0;
    try
    {
        count = int.Parse(text);
    }
    catch (FormatException e)
    {
        count = -1;
    }

    Console.WriteLine("Значение счетчика: ", count);

    count++;

    File.WriteAllText(fileName, count.ToString());
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>> SQL Express 2008 R2
Re[12]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 18.08.10 02:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>То есть

G>1)Файл гарантировано есть и заранее известен

Нет. Если файл не существует -- программа должна его создать.

G>2)Доступ к файлу гарантировано есть


Его уже может не быть по той причине, что файл используется второй программой.

G>3)Значение счетчика, записанного туда, обязательно корректно


Я же сказал: этот файл использует другая программа, которую мы не можем изменить. Она работает криво, может чего-то не того записать в файл.

G>Возьму код из первого поста и пропишу в нем путь к файлу.


См. то что вы забыли учесть выше.

0K>>Покажите нам как эту задачу решить правильно


Давайте пишите код. Неужели вам не лень базикать и лень писать код? Слова -- ничто, код -- все.
=сначала спроси у GPT=
Re[6]: Конкурс на умение работать с Exception
От: 0K Ниоткуда  
Дата: 18.08.10 02:36
Оценка:
Здравствуйте, Nikolay_P_I, Вы писали:

N_P>Здесь правильно про сценарии использования говорили. У нас половина такого кода просто прокидывает исходное исключение дальше и выводит юзеру окно с требованием позвать администратора системы. В окне все аж со стектрейсом. Ибо не юзерское это дело — голову ломать над тем — каких прав на чтение какого файла почему не хватает и как это ему, юзеру, исправлять.


А админ как узнает в чем проблема? 2 сообщения нужна: для админа и для пользователя. Там де написано в самом первом посте.

Вы сейчас ищите причину почему не делать.
=сначала спроси у GPT=
Re[2]: Критика варианта LF
От: 0K Ниоткуда  
Дата: 18.08.10 03:15
Оценка:
Здравствуйте, LF, Вы писали:

LF>От нечего делать написал, пинайте


Во-первых, благодарю за желание принять участие в конкурсе

Теперь критика.

По существу:

1. Если файл занят другим процессом, возникает ошибка: "Упс, не предвиденная ошибка: Could not find file..." Информация в ней не соответствует действительности, т.к. файл существует.

2. Если имя файла ввести с '\', то опять некорректная ошибка: "Упс, не предвиденная ошибка: Could not find a part of the path 'c:\gr\g'.. Обратитесь в службу поддержки."

3. С делегатами вы перемудрили -- программа выглядет запутанной. Можно было бы как-то проще ее написать. В Win-приложение со стандартными errorProvider переносить будет очень сложно...

Дополнительно:

1. После проверки прав на чтение/запись но перед самим актом чтения/записи, могли произойти изменения (хоть и маловероятно). Будет выведена непонятная ошибка

2. Warning: Review the following for a possible security vulnerability: Parameter 'fileIoPermissionAccess' of 'Worker.CheckAccessForFile(string, FileIOPermissionAccess)' is being passed to a 'FileIOPermission' constructor. Кстати, кто объяснит почему предупреждение?
=сначала спроси у GPT=
Re[4]: Критика Neco
От: 0K Ниоткуда  
Дата: 18.08.10 03:35
Оценка:
Здравствуйте, Neco, Вы писали:

N>это должно делаться на более-менее высоком уровне, чтобы не мельчить.


Не на таком уж низком уровне работа требуется Никто к командам ассемблера и устройству файлововой системы не прибегает.

Теперь критика.

По существу:

1. У вас три перехвата базового Exception. Вы, вероятно, читали в MSDN что так делать нельзя. Но проигнорировали, т.к. не нашли вы этом большого смысла. Смысл есть -- вы нейтрализуете (пытаетесь нейтрализовать) низкоуровневые исключения, такие как ExecutionEngineException, OutOfMemoryException.

Но благодаря такой стратегии ваш код -- неубиваемый. Мне не удалось найти ни одного способа заставить его упасть или сделать так, чтобы возникло нестандартное сообщение об ошибке.

Но опять же. Вы нарушили требования MS не перехватывать базовый Exception и в некоторых случаях ваш код все-таки сработает некорректно. Кроме того, в системах автоматической сборки его просто не пропустит FxCop.

Дополнительно:

1. int.ToString/int.Parse -- нужно указать нейтральную культуру.
2. Класс Exception не помечен аттрибутом Serializable.

N>Кстати, в ответ попрошу и свой код выложить.


Не спешите
=сначала спроси у GPT=
Re[2]: Критика akasoft
От: 0K Ниоткуда  
Дата: 18.08.10 03:52
Оценка:
Здравствуйте, akasoft, Вы писали:

Во первых, отвечу на вопросы.

A>Какие будут выводы?

A>0. Консольные приложения пишутся не так, как оконные. Без интерактива. Обычно они представляют собой команды, принимают параметры из командной строки, понимают перенаправление вывода, взводят errorlevel, и пр. Автором темы это всё, похоже, опущено.

Я же даже подсказал, код лучше всего делать универсальным: вынести логику в отдельный класс для повторного использования.

A>1. Код, выделенный жирным, и особенно последний блок try-catch надо выкинуть, ибо написан он под воздействием Боевой Телепатии, а таковую надо гнать.

A>2. Предложенное автором темы описание задачи не достаточное и не полное, что требует ментальных усилий по удержанию Боевой Телепатии в узде от желания врубить воображение и безосновательно раздуть код.
A>3. Поскольку в описании автора темы не предусмотрено реакции программы на ошибки и сбои, кроме скудных комментариев в двух местах, то и я не буду выдумывать отсебятину, глобальные перехваты и вывод красочных сообщений. Итого код:

А это уже сами думайте как пользователю удобнее. В данном задании требуется не только кодирование, но и думание как удобнее сделать для пользователя (т.е. нужны начальные знания в этой области).

Теперь критика.

По существу:

1. Ваша программа абсолютно не предназначена для среднего пользователя, только для админа какого-нибудь. Сообщения об ошиках среднему пользователю будут не понятны. Это ключевой момент, дальше то и обсуждать нечего. Требование было (самое первое сообщение) вывести 2 сообщения для разных уровней пользователей.
2. Код непереносим. Его нельзя задействовать в Win или WPF -приложении.
3. Вы перепутали FileNotFoundException и NotFoundException. Так что код даже не работает.

Дополнительно

1. Если пользователь ошибся при вводе данных -- ему не предоставляется второй шанс. Это не юзабельно. Хотя такого требования не было. Но кто о пользователе думать будет?
=сначала спроси у GPT=
Re[2]: И сбоку бантик
От: midcyber
Дата: 18.08.10 04:42
Оценка:
Здравствуйте, akasoft, Вы писали:

A>Читаем дальше. В строке 04 видим разбор полученного на предыдущем шаге значения. Тут мы можем словить FormatException, если окажется, что то, что мы проситали — не число. Реагируем на из предположения (тут включилась Боевая Телепатия, в коде про это ничего нет!), что если там чёртичто, то должен быть сбоку бантик, т.е. "-1":


A>
A>int count = 0;
A>try
A>{
A>    count = int.Parse(text);
A>}
A>catch (FormatException e)
A>{
A>    count = -1;
A>}
A>


Фишка в том, что создатели языка подумали об этой ситуации, и добавили метод TryParse, чтобы не строить логику на исключениях:

int count = 0;
if(!int.TryParse(text, out count))
  count = -1;


В других случаях язык тоже предлагает много инструментов для того, чтобы не строить логику на исключениях.
Для баз данных это Transaction Scope, для ресурсов это using + disposable.

Но топикстартер умышленно выбрал работу с файлами — единственное место, где в .NET спорная работа с исключениями. Поэтому конкурс изначально предвзятый.
Re[5]: Критика Neco
От: Neco  
Дата: 18.08.10 04:44
Оценка:
Здравствуйте, 0K, Вы писали:

0K>1. У вас три перехвата базового Exception. Вы, вероятно, читали в MSDN что так делать нельзя.

Не, не читал. Вот счас прочитал только.

# It hides bugs

не вижу как. предположим у меня где-то там баг. его обернут в exception более точно указывающий местоположение и вытолкнут дальше. баг не скрыт.

# Handling all exceptions without exception-specific handling logic will leave the application in an unknown state.

не согласен. я не отменяю исключения (не гашу их) — просто дополняю информацией.

# It circumvents higher-level exception handling.

это с одной стороны звучит убедительно. но с другой стороны — на фига вышестоящему классу заботиться о моих ошибках? сейчас я работаю с файловой системой, а завтра изменю реализацию и буду работать с сокетами (т.е. опять же с инкрменентной целью, но уже по сети). а послезавтра меня осенит, что инкрементность можно возложить на оракл и просто брать оттуда значение следующего сиквенса. заметьте — функционал класса с внешней точки зрения не поменялся. что же теперь пользователям моего класса писать надстройки на все случаи жизни? это невозможно и не нужно.
Если так уж нужно дать знать вышестоящему классу больше, то лучше делать несколько видов исключений.
IncrementorException
IncrementorReadErrorException
IncrementorWriteErrorException
по одному на каждый приватный метод. но это сильно утяжелит реализацию и я не знаю маньяка, который хотел бы с этим что-то делать при использовании моего класса (и главное, не знаю что бы он мог с этим сделать и зачем это ему).

A higher-level exception handler may know exactly what to do with a certain type of exception; possibly much better than your code. By using catch(Exception) you circumvent that and end up with the above--the application may be in a unknown state.

жалко, что они не приводят здесь же пример. как вышестоящий хэндлер может знать лучше, что делать с ошибкой?
как-то так?

                    string fileName = Console.ReadLine();
                    var incrementor = new Incrementor((new FileNameGenerator()).GenerateFileName(fileName));
                    try {
                        var result = incrementor.PerformIncrement();
                    } catch (FileNotFoundException ex)  {
                        Console.WriteLine("The file [{0}] was not found", fileName);
                    }

ну и с какого перепуга вышестоящий хэндлер может решить, что именно этот файл не найден? может я внутри класса лазаю в какие-то другие файлы и один из них у меня вдруг не нашёлся неожиданно?
и AccessDenied вышестоящий класс не сможет интерпретировать вменяемо — во время чтения не хватило прав или во время записи?

0K>Но благодаря такой стратегии ваш код -- неубиваемый. Мне не удалось найти ни одного способа заставить его упасть или сделать так, чтобы возникло нестандартное сообщение об ошибке.

0K>Но опять же. Вы нарушили требования MS не перехватывать базовый Exception и в некоторых случаях ваш код все-таки сработает некорректно. Кроме того, в системах автоматической сборки его просто не пропустит FxCop.
Требования должны идти с решениями. Иначе это выглядит как "я не знаю как надо, но вы делаете неправильно".
Если бы в дотнете были ограничения на виды исключений, как в Java, то такая рекомендация имела хоть какой-то смысл (да и то — переписывать классы-пользователи по каждому новому чиху подкласса — себе дороже).

про FxCop — согласился бы наверное, если бы пользовался им.

ну а в каких случаях мой код работает некорректно?

кстати, неубивамость — не моя цель. StackOverflow всё равно убьёт приложение. Моя цель — как можно больше рассказать об исключительной ситуации через Exception тому, кто будет иметь с ним дело.

0K>1. int.ToString/int.Parse -- нужно указать нейтральную культуру.

принимается.

0K>2. Класс Exception не помечен аттрибутом Serializable.

принимается.

Кстати, пара слов о рекомендацяих MS — сами-то они очень сильно нарушают общечеловеческие рекомендации по разделению ответственностей, например. Или взять их обработку ошибок в VB6, VBA, VBS — кто это им рекомендовал?
всю ночь не ем, весь день не сплю — устаю
Re[13]: Конкурс на умение работать с Exception
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.10 06:10
Оценка: :)
Здравствуйте, 0K, Вы писали:

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

Файл будет создан один раз, это можно вынести вне кода, увеличивающего значение счетчика.

G>>3)Значение счетчика, записанного туда, обязательно корректно

0K>Я же сказал: этот файл использует другая программа, которую мы не можем изменить. Она работает криво, может чего-то не того записать в файл.
Ну это уже чушь, если "другая программа" может записать что угодно, то и я могу записать что угодно и не париться по этому поводу.

G>>Возьму код из первого поста и пропишу в нем путь к файлу.

0K>См. то что вы забыли учесть выше.


0K>>>Покажите нам как эту задачу решить правильно

0K>Давайте пишите код. Неужели вам не лень базикать и лень писать код? Слова -- ничто, код -- все.
Мне всегда лень писать код. А если писать, то надо определиться с тем что он делает и не делает.
Re[7]: Конкурс на умение работать с Exception
От: Nikolay_P_I  
Дата: 18.08.10 08:11
Оценка:
Здравствуйте, 0K, Вы писали:

N_P>>Здесь правильно про сценарии использования говорили. У нас половина такого кода просто прокидывает исходное исключение дальше и выводит юзеру окно с требованием позвать администратора системы. В окне все аж со стектрейсом. Ибо не юзерское это дело — голову ломать над тем — каких прав на чтение какого файла почему не хватает и как это ему, юзеру, исправлять.


0K>А админ как узнает в чем проблема? 2 сообщения нужна: для админа и для пользователя. Там де написано в самом первом посте.


Потому и полное исключение со стектрейсом. Не поймет админ — позвонит разработчику.

0K>Вы сейчас ищите причину почему не делать.


Читайте внимательнее — "половина такого кода". Остальная, где можно предусмотреть ситуацию — или сама что-то правит незаметно от юзера или нормально с ним разговаривает.

Просто если к старту юзерской программы к ней должен быть нормальный, существующий и корректно разбирающийся конфиг — не дело юзера разбираться почему даже "file not found", не говоря уж о "ошибка при чтении XML, строка 5, позиция 4" потому как ЛЮБОЙ факт ошибки чтения конфига в такой ситуации свидетельствует о создании нештатной ситуации и неизвестно — чего там еще не так.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.