Re[7]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 10:41
Оценка:
Здравствуйте, aka50, Вы писали:

A>А что мешает им кинуть выше?


Под 'наверху должны всегда производить обработку' я имел ввиду как оборачивание в try-catch, так и объявление во throws.


A>Ведь checked на то и checked чтобы обратить внимание на то, что метод не может принять решение что делать дальше.


Имхо ситауция, когда метод кидает unchecked, не означает, что метод принял решение, что делать дальше


A>Т.е. сами по себе checked конечно не панацея, но отказываться от них полностью — суть зло.


Видишь, здесь разные подходы — мне кажется, что пользователю моего класса удобнее работать, не будучи обязанным ловить какие бы то ни было эксепшны. Но при этом вся информация по поводу того, что может вылететь и в каких случаях, должна быть доступна (равно как и cause ). И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.


A>Я обычно руководствуюсь простыми правилами:

A>1. Утилитный класс или внутренняя логика — checked
A>2. Компонентный (например dao) — unchecked либо один большой checked

Ок.
http://denis-zhdanov.blogspot.com
Re[8]: Какие вы видите проблемы в данном коде?
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 17.05.07 10:59
Оценка: +2
Здравствуйте, bolshik, Вы писали:

B> И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.

Не согласен. Зачастую уровень, который кидает исключение, сам не может с ним справится. Самый простой и наглядный пример — открытие файла, спрятанное в вызовах и затребованное пользователем. Тут логично вынести обработку исключения поближе к пользователю.
http://jvmmemory.com — простой способ настройки JVM
Re[6]: Какие вы видите проблемы в данном коде?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 17.05.07 11:18
Оценка:
Здравствуйте, bolshik, Вы писали:

D>>А в чём проблема то? Там, наверху, в зависимости от того, что и куда пишем, сами разберутся, что с исключением делать.


B>В том, что неудобно. Там, наверху, должны сами решать, хотят они обрабатывать эксепшн или не хотят (мы со своей стороны четко прописываем IllegalStateException в сигнатуре, плюс пишем джавадок, т.е. даем всю необходимую информацию). В случае же с checked exception наверху должны всегда производить обработку.

Подмена IOException на IllegalStateException, ИМХО, некорректна. К тому же, хотя ты и написал ниже, что объявление метода через throws тоже не нравится, но меня такой вариант, если в данном месте я не хочу ничего обрабатывать, вполне устраивает.

D>>По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.


B>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого.

Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.
Re[8]: Какие вы видите проблемы в данном коде?
От: aka50 Россия  
Дата: 17.05.07 11:24
Оценка:
Здравствуйте, bolshik, Вы писали:

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


A>>Т.е. сами по себе checked конечно не панацея, но отказываться от них полностью — суть зло.


B>Видишь, здесь разные подходы — мне кажется, что пользователю моего класса удобнее работать, не будучи обязанным ловить какие бы то ни было эксепшны. Но при этом вся информация по поводу того, что может вылететь и в каких случаях, должна быть доступна (равно как и cause ). И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.


Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_. Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get. По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), что согласись в случае с чтением из файла таковым не является. Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"...

Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e) и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать).
Re[7]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 11:36
Оценка: -1
Здравствуйте, Donz, Вы писали:

D>Подмена IOException на IllegalStateException, ИМХО, некорректна.


А логическое обоснование можно?


D>К тому же, хотя ты и написал ниже, что объявление метода через throws тоже не нравится, но меня такой вариант, если в данном месте я не хочу ничего обрабатывать, вполне устраивает.


Да ради Бога, я ж не настаиваю, на том, что мой подход самый правильный подход


D>>>По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.


B>>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого.

D>Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.

На самом деле, я сразу не сообразил, что ошибки-то в этом нет (в случае оборачивания в unchecked; как альтернатива можно использовать логирование). Кинуть эксепшн в обоих случаях (и при write(), и при close()) не получится ==> надо выбирать что-то одно. Я выбираю вариант, когда эксепшн из close() перезатирает эксепшн из write(). Эта ситуация мне не нравится меньше, чем когда наверх летит эксепшн от write(), и остается открытый поток.
http://denis-zhdanov.blogspot.com
Re[9]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 11:37
Оценка:
Здравствуйте, LeonidV, Вы писали:

LV>Не согласен. Зачастую уровень, который кидает исключение, сам не может с ним справится. Самый простой и наглядный пример — открытие файла, спрятанное в вызовах и затребованное пользователем. Тут логично вынести обработку исключения поближе к пользователю.


Дык пусть обрабатывает unchecked, кто ж ему мешает-то?
http://denis-zhdanov.blogspot.com
Re[9]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 11:56
Оценка:
Здравствуйте, aka50, Вы писали:

A>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_.


Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.


A>Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get.


А что, если бы в сигнатуре не было бы объявления throws Exception, в Executor'е нельзя было бы делать catch (Exception)?


A>По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), ...


Очень спорное утверждение. По такой логике получается, что спринговский DataAccessException — вполне себе устранимый эксепшн, а какой-нить java.sql.Statement.execute() неустранимый?


A>...что согласись в случае с чтением из файла таковым не является.


Во-первых, запись, во-торых не соглашусь — все зависит от задачи


A>Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"...


Так пусть же он принимает это решение на основании анализа checked exception'a.


A>Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)...


Вот как-то не дается мне глубина этой логики. Что есть такого у checked, что позволяет 'всю обработку ошибок сконцентрировать', а в случае unchecked 'придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)'...


A>...и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать).


Module3 дурак что ли бросать все, что угодно? Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
http://denis-zhdanov.blogspot.com
Re[10]: Какие вы видите проблемы в данном коде?
От: aka50 Россия  
Дата: 17.05.07 12:29
Оценка:
Здравствуйте, bolshik, Вы писали:

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


A>>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_.

B>Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.
Проблемы трудностей выстрела в свою ногу — проблемы практикующих такие выстрелы.

A>>Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get.

B>А что, если бы в сигнатуре не было бы объявления throws Exception, в Executor'е нельзя было бы делать catch (Exception)?
В случае с Runnable видно: выше никого нет (разве что Thread.UncaughtExceptionHandler), а в случае с Callable интерфейс явно говорит, что ошибка будет обработана (хотя бы в виде ExecutionExeception).

A>>По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), ...

B>Очень спорное утверждение. По такой логике получается, что спринговский DataAccessException — вполне себе устранимый эксепшн, а какой-нить java.sql.Statement.execute() неустранимый?
Я, если честно, не в восторге от подхода spring-а к тотальному отказу от checked. Но с другой стороны spring обычно используется для объединения компонент. В этом случае компонент обязан сам разбираться с проблемами и бросать unchecked и узкий набор checked только в крайнем случае, т.к. во многих программах забытый unchecked скорее всtго пришибет весь поток и хорошо если это будет не main поток.

A>>Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"...

B>Так пусть же он принимает это решение на основании анализа checked exception'a.
Кто? Если writeData кинет unchecked кто будет принимать решение? Или это должен делать сам writeData. А если у нас несколько writeData, которые еще и не так просто в один загнать? Если у нас writeData зарыт в другом классе и к writeData у нас нет javadoc (если обязывать это все вести в javadoc — получим проблему с актуальностью). Тогда вопрос, почему бы не использовать возможности компилятора?

A>>Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)...

B>Вот как-то не дается мне глубина этой логики. Что есть такого у checked, что позволяет 'всю обработку ошибок сконцентрировать', а в случае unchecked 'придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)'...
То, что все внутренние методы будут промаркированны соответствующими ексепшонами (возможно даже иерархией, типа ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException). В случае unckecked я должен буду проанализировать весь call graph чтобы этот ProtoMissingField аж до самого main не вылетел, когда просто забылил или не знали что такое может выскочить.

A>>...и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать).

B>Module3 дурак что ли бросать все, что угодно? Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
Так и я о том же, но котролировать внутри модуля проще именно checked, т.е. все методы внутри модуля кидаются разнымими внутримодульными ексепшонами... Наверх вылетают либо "страшные" ConcurrentModification-ы которые однозначно показывают — мега проблема либо небольшой набор checked (в случае с spring они unchecked, но пользоваться unchked особо не заставляют).

Вот посуди сам, разработчик забыл перехватить IO при попытки записи в кеш неких данных, и из вызова module1.findData вылетело Module1(IOException("Can't write /tmp/2342SSDGF.dat")) О чем это скажет тому, кто пользуется module1 и может даже не подозревать что там вообще файлы используются? Правильнее будет Mudule1CacheOperationFailed("Can't write to cache file", IOExce(...)), но для того, чтобы проконтролировать все это легче использовать checked.
Re[8]: Какие вы видите проблемы в данном коде?
От: Blazkowicz Россия  
Дата: 17.05.07 12:30
Оценка:
Здравствуйте, bolshik, Вы писали:


D>>Подмена IOException на IllegalStateException, ИМХО, некорректна.

B>А логическое обоснование можно?

Оно в API доке к классу IllegalStateException.
Re[10]: Какие вы видите проблемы в данном коде?
От: aka50 Россия  
Дата: 17.05.07 12:31
Оценка:
Здравствуйте, bolshik, Вы писали:

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


A>>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_.

B>Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.

А вообще какой-то спор не правильный... в инете полно флейма на эту тему... т.е. нужно смотреть конкретную задачу и условия, в которых пишется приложение... Архитектуру... в общем использовать или не использовать checked — "it depends".
Re[9]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 12:34
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

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



D>>>Подмена IOException на IllegalStateException, ИМХО, некорректна.

B>>А логическое обоснование можно?

B>Оно в API доке к классу IllegalStateException.


Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.


Нет у процесса сейчас права на запись в файл — чем не 'illegal or inappropriate time'?
http://denis-zhdanov.blogspot.com
Re[10]: Какие вы видите проблемы в данном коде?
От: Blazkowicz Россия  
Дата: 17.05.07 12:36
Оценка:
Здравствуйте, bolshik, Вы писали:

B>

B>Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.


B>Нет у процесса сейчас права на запись в файл — чем не 'illegal or inappropriate time'?


Состояние внешней среды не является состоянием "Java environment or Java application"
Re[11]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 12:52
Оценка:
Здравствуйте, aka50, Вы писали:

A>Проблемы трудностей выстрела в свою ногу — проблемы практикующих такие выстрелы.


С одной стороны да, а с другой лично меня отчаянно раздражает необходимость обработки checked, которые методы стандартной библиотеки объявляют на каждый чих. Очень не хочется заставлять пользователей своего кода испытвать те же чувства.


A>В случае с Runnable видно: выше никого нет (разве что Thread.UncaughtExceptionHandler), а в случае с Callable интерфейс явно говорит, что ошибка будет обработана (хотя бы в виде ExecutionExeception).


Имхо то, что у call стоит throws Exception значит не то, что 'ошибка будет обработана', а то, что код, работающий с этим интерфейсом, должен писать обработчик Exception.


A>Я, если честно, не в восторге от подхода spring-а к тотальному отказу от checked. Но с другой стороны spring обычно используется для объединения компонент.


Ну, скажем, DataAccessException используется для объединения с субд.


A>В этом случае компонент обязан сам разбираться с проблемами и бросать unchecked и узкий набор checked только в крайнем случае, т.к. во многих программах забытый unchecked скорее всtго пришибет весь поток и хорошо если это будет не main поток.



A>Кто? Если writeData кинет unchecked кто будет принимать решение? Или это должен делать сам writeData. А если у нас несколько writeData, которые еще и не так просто в один загнать?


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


A>Если у нас writeData зарыт в другом классе и к writeData у нас нет javadoc (если обязывать это все вести в javadoc — получим проблему с актуальностью). Тогда вопрос, почему бы не использовать возможности компилятора?


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


A>То, что все внутренние методы будут промаркированны соответствующими ексепшонами (возможно даже иерархией, типа ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException). В случае unckecked я должен буду проанализировать весь call graph чтобы этот ProtoMissingField аж до самого main не вылетел, когда просто забылил или не знали что такое может выскочить.


А кто мешает сделать ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException unchecked а анализировать их только тогда, когда это действительно нужно?


A>Так и я о том же, но котролировать внутри модуля проще именно checked, т.е. все методы внутри модуля кидаются разнымими внутримодульными ексепшонами... Наверх вылетают либо "страшные" ConcurrentModification-ы которые однозначно показывают — мега проблема либо небольшой набор checked (в случае с spring они unchecked, но пользоваться unchked особо не заставляют).


A>Вот посуди сам, разработчик забыл перехватить IO при попытки записи в кеш неких данных, и из вызова module1.findData вылетело Module1(IOException("Can't write /tmp/2342SSDGF.dat")) О чем это скажет тому, кто пользуется module1 и может даже не подозревать что там вообще файлы используются? Правильнее будет Mudule1CacheOperationFailed("Can't write to cache file", IOExce(...)), но для того, чтобы проконтролировать все это легче использовать checked.


По-моему, это другая сторона той же медали, что и catch (Exception) {}. Нормальный чувак не будет писать catch (Exception) {}, и не будет же игнорировать unchecked эксепшны, объявленные во throws, а с unchecked геморроя меньше.
http://denis-zhdanov.blogspot.com
Re[11]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 12:52
Оценка:
Здравствуйте, aka50, Вы писали:

A>А вообще какой-то спор не правильный... в инете полно флейма на эту тему... т.е. нужно смотреть конкретную задачу и условия, в которых пишется приложение... Архитектуру... в общем использовать или не использовать checked — "it depends".


http://denis-zhdanov.blogspot.com
Re[11]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 12:59
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Состояние внешней среды не является состоянием "Java environment or Java application"


Почему же, можно трактовать так, что запущено джава-приложение, у которого нет прав на запись в файл, т.е. 'Java application is not in an appropriate state for the requested operation'.
http://denis-zhdanov.blogspot.com
Re[8]: Какие вы видите проблемы в данном коде?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 17.05.07 13:16
Оценка: 2 (2)
Здравствуйте, bolshik, Вы писали:

B>>>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого.

D>>Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.

B>На самом деле, я сразу не сообразил, что ошибки-то в этом нет (в случае оборачивания в unchecked; как альтернатива можно использовать логирование). Кинуть эксепшн в обоих случаях (и при write(), и при close()) не получится ==> надо выбирать что-то одно. Я выбираю вариант, когда эксепшн из close() перезатирает эксепшн из write(). Эта ситуация мне не нравится меньше, чем когда наверх летит эксепшн от write(), и остается открытый поток.


Ты же поток не закроешь, если кинешь исключение о том, что не получилось его закрыть.
Если код, например, построить таким образом:
OutputStream out = new smth.getOutputStream();
try
{
  out.write( data );
}
finally
{
  try
  {
    out.close();
  }
  catch( Exception ignored ){}
}

То будет выполнена попытка закрытия поток, и наверху мы получим "правильное исключение".
Ещё можно ввести флажок, а каким образом вызван блок finally: нормально или из-за исключения, и, анализируя флажок, принимать решение, подавлять исключение, возникшее при закрытии потока, или выбрасывать его наверх. Только это уже как-то мудрено получается. Я обычно использую приведёный код.
Re[2]: Какие вы видите проблемы в данном коде?
От: Аноним  
Дата: 17.05.07 13:21
Оценка: +1
Здравствуйте, bolshik, Вы писали:

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


<skip>

B>2. Я бы не кидал checked exception наружу, т.е. либо тупо логировать его, либо оборачивать в unchecked;

<skip>

Этот пункт меня убил
Re[12]: Какие вы видите проблемы в данном коде?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 17.05.07 13:23
Оценка:
Здравствуйте, bolshik, Вы писали:

B>>Состояние внешней среды не является состоянием "Java environment or Java application"


B>Почему же, можно трактовать так, что запущено джава-приложение, у которого нет прав на запись в файл, т.е. 'Java application is not in an appropriate state for the requested operation'.


Тогда таким образом можно трактовать любое исключение. Ну не вовремя ява-машина запустилась: сервер сгорел или у пользователя настроение плохое
IOException — даже само название класса исключения говорит о том, что произошла ошибка ввода/вывода, то есть надо смотреть в сторону работы с потоками.
IllegalStateException — ява-машина не готова запустить какой-либо метод или выполнить операцию из-за состояния самой ява-машины, а не внешнего состояния, как это уже сказал Blazkowicz
Re[9]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 13:27
Оценка:
Здравствуйте, Donz, Вы писали:

D>Ты же поток не закроешь, если кинешь исключение о том, что не получилось его закрыть.

D>Если код, например, построить таким образом:
D>
D>OutputStream out = new smth.getOutputStream();
D>try
D>{
D>  out.write( data );
D>}
D>finally
D>{
D>  try
D>  {
D>    out.close();
D>  }
D>  catch( Exception ignored ){}
D>}
D>

D>То будет выполнена попытка закрытия поток, и наверху мы получим "правильное исключение".
D>Ещё можно ввести флажок, а каким образом вызван блок finally: нормально или из-за исключения, и, анализируя флажок, принимать решение, подавлять исключение, возникшее при закрытии потока, или выбрасывать его наверх. Только это уже как-то мудрено получается. Я обычно использую приведёный код.

Да, правильно, я протупил, так все хорошо будет.
Единственно что, это как раз пример увеличения объема кода и уменьшения читабельности.
http://denis-zhdanov.blogspot.com
Re[3]: Какие вы видите проблемы в данном коде?
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 17.05.07 13:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Этот пункт меня убил


Покойся с миром..
http://denis-zhdanov.blogspot.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.