powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / О правилах разработки...
35 сообщений из 35, показаны все 2 страниц
О правилах разработки...
    #35015184
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Мысль мне подкинули, хочется услышать, что по этому поводу опытные думают.
"Класс должен быть или абстрактным, или финальным".
Объяснение- "иначе конфликтует требование к конкретной функциональности и идеи для потомков".

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015348
belugin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_Samara
Мысль мне подкинули, хочется услышать, что по этому поводу опытные думают.
"Класс должен быть или абстрактным, или финальным".
Объяснение- "иначе конфликтует требование к конкретной функциональности и идеи для потомков".


С моей точки зрения это экстремизм. Например, иногда удобнее формулировать общие для предков свойства, интерпретируя это как конструкцию "как правило".

[src]
# как правило, у собаки 4 ноги
класс Собака:
def числоНог(self):
return 4;

# у собаки перееханной трамваем число ног зависит от собаки
класс СобакаПерееханнаяТрамваем(Собака):
def __init__(self, числоНог):
self.числоНог = числоНог
def числоНог(self):
return self.числоНог
[src]
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015352
belugin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
# как правило, у собаки  4  ноги
класс Собака:
    def числоНог(self):
        return  4 ;

# у собаки перееханной трамваем число ног зависит от собаки
класс СобакаПерееханнаяТрамваем(Собака):
    def __init__(self, числоНог):
          self.числоНог =  числоНог
    def числоНог(self):
          return self.числоНог
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015544
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
belugin
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
# как правило, у собаки  4  ноги
класс Собака:
    def числоНог(self):
        return  4 ;

# у собаки перееханной трамваем число ног зависит от собаки
класс СобакаПерееханнаяТрамваем(Собака):
    def __init__(self, числоНог):
          self.числоНог =  числоНог
    def числоНог(self):
          return self.числоНог


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

"Число ног" - это просто изменяемое свойство "Собаки". При помощи наследование можно создавать классификации только на основе неизменяемых свойств объектов. Классификации на основе изменяемых свойств (перееханные и перетраханные собаки) - в основном ноненс.


GKS_Samara
"иначе конфликтует требование к конкретной функциональности и идеи для потомков".

Если LSP не нарушается, то всё будет в порядке.
Можно в свободное время помедитировать над классом Object c методами Equals, HashCode.
Или посмотреть на шаблон Composite в различных имплементациях.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015603
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraМысль мне подкинули, хочется услышать, что по этому поводу опытные думают.
"Класс должен быть или абстрактным, или финальным".
Выдающаяся глупость, сказать которую может только человек, который никогда не погружался в программирование глубже использования готовых решений.

Красота такого подхода легко демонстрируется на простом примере. Допустим, я хочу сделать компонент "как JLabel", но в дополнение к его функционалу обладающий еще какой-нибудь мелкой деталью. Например, приобретающий красный цвет, если надпись в нем содержит грамматическую ошибку. Естественное решение - наследоваться от JLabel. А какой у нас JLabel - абстрактный али финальный? Если второе - наше желание идет лесом, и мы начинаем извращаться. Если первое - значит, страдают все, кому нужен JLabel без дополнений и кто в результате не может просто так взять и инстанциировать его.

Таким образом с практической точки зрения это сведется вот к чему: выпуская любую библиотеку классов, я буду вынужден продублировать каждый публичный ее класс. Если раньше были, допустим, JLabel, JButton, JText - то теперь я должен буду сделать JLabel, JFinalLabel, JButton, JFinalButton, JText, JFinalText. В результате чего всем участникам процесса станет намного, намного удобнее.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015655
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerКрасота такого подхода легко демонстрируется на простом примере. Допустим, я хочу сделать компонент "как JLabel", но в дополнение к его функционалу обладающий еще какой-нибудь мелкой деталью. Например, приобретающий красный цвет, если надпись в нем содержит грамматическую ошибку. Естественное решение - наследоваться от JLabel.

Вот сейчас смотрю на иерархию (все имена вымышленные, любые совпадения считать случайными):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
JComboBox 
	SearchBox 
		OMWrapperEditorComboBox 
			ClientDetailedAccountSearchBox 
			DefaultableOMWrapperEditorComboBox 
				OpenCloseComboBox 
				CommBasisTypeComboBox 
				CrossTradeComboBox 
				CurrencyComboBox 
				DeliveryMethodComboBox 
				PriceBasisTypeComboBox 
				PricingBasisComboBox 
					GetsPricingBasisComboBox 
			ExchangeComboBox 
			OrderCapacityComboBox 
				DerivativeCapacityComboBox 
			SimpleExchangeComboBox 
				HybridExchangeComboBox 
			CountryExchangeComboBox 
			ImagineBasicComboBox 
				ImagineAccountComboBox 
				ImagineGroupComboBox 
			Anonymous in getInstructionsCombo in AbstractOrderEntryTab 
			DeliveryComboBox 
		ValidateCombo 
			ValidateClientCombo 
				ClientCombo in ClientLookup 
				Anonymous in ClientAccountsLookupPanel 
				Anonymous in ClientInvestorIDsLookupPanel 
				Anonymous in LookupClientAccountsManager 
				Anonymous in DefaultOrderEntryPanel 
				Anonymous in DefaultOrderEntryPanel 
			ValidateDerivativeTextField 
				DerivativeTextField in DerivativeLookup 
					DerivativeTextField in DerivativeLookupGlobalDeriv 
					DerivativeTextField in DerivativeLookupUS 
			ValidateImagineClientAccountCombo 
		NonDeselectableComboBox 

и думаю: а всякое ли "естественное решение" небезобразно? :)
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015690
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NotGonnaGetUsи думаю: а всякое ли "естественное решение" небезобразно? :)
Как Вам сказать... думаю, Вы уже пару лет как в курсе моего мнения относительно красоты явовских решений; имхо авторы набросились на специализацию классов примерно так же, как неумный человек - на поклонение Господу. Это вызывает вполне понятные последствия и у кода, опирающегося на эти классы.

Тем не менее, принципа это ничуть не трогает. Задача "взять и немного доработать напильником" - одна из наиболее распространенных в практическом программировании. Если мы вдруг попробуем решать ее не наследованием - натолкнемся на две проблемы: во-первых, необходимость строить иерархию классов, параллельную уже существующей (совершенно идиотское занятие и особенно при отсутствии множественного наследования; тот же Swing это хорошо показывает); во-вторых, несовместимость наших классов со стандартными (как следствие - невозможность для любого стандартного кода, в том числе третьих авторов, работать с нашими объектами). Вторую проблему придется смягчать введением стопроцентно покрывающих класс интерфейсов.... в общем, уйма геморроя на пустом месте. Все оттого, что кому-то захотелось поиграть в солдатики.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35015742
0bsid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NotGonnaGetUs...
Вот сейчас смотрю на иерархию (все имена вымышленные, любые совпадения считать случайными):

возможно глупый вопрос
как ты сделал такое представление иерархии ? ручками или утилитой кокой?
мне понравилось это простое и понятное текстовое представление дерева
...
Рейтинг: 0 / 0
О правилах разработки...
    #35016118
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Тем не менее, принципа это ничуть не трогает. Задача "взять и немного доработать напильником" - одна из наиболее распространенных в практическом программировании.

Если мы вдруг попробуем решать ее не наследованием - натолкнемся на две проблемы:

во-первых, необходимость строить иерархию классов, параллельную уже существующей (совершенно идиотское занятие и особенно при отсутствии множественного наследования; тот же Swing это хорошо показывает);

во-вторых, несовместимость наших классов со стандартными (как следствие - невозможность для любого стандартного кода, в том числе третьих авторов, работать с нашими объектами).


Доработка напильником не такая тривиальная задача как кажется. Хотя бы из-за того, что "дорабатывать" можно разными способами и нужно уметь сделать "правильный" выбор.
Усугубляется всё тем, что "правильный" выбор в кроткосрочной и долгосрочной перспективах получается совершенно различным.

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

Про иерархию выше, могу сказать только одно. Она бы существенно схлопнулась, если наследование было заменено декомпозицей. Н-р, созданием классов валидаторов, рендереров и т.д. Создавать по классу наследнику для каждого типа отображаемых значений в каждом из контекстов где оно может использоваться - бред. Это всё равно, что для Пети дома делать класс ПетяДома extends Человек, а для Пети на работе - класс ПетяНаРаботе extends Человек.
Благо, что ругаемый вами swing построен так, что позволяет задавать валидаторы, рендереры и иже с ними для станадртных компонент, что не приводит ни к возникновению параллельных иерархий, ни к не совместимости со стандартными классами. Если правильно готовить :)

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


0bsid
возможно глупый вопрос
как ты сделал такое представление иерархии ? ручками или утилитой кокой?
мне понравилось это простое и понятное текстовое представление дерева

Idea. Ctrl-H - смотрим на панель с деревом наследования. Затем выделяем интересующие классы, Ctrl-C, Ctrl-V в любимый текстовый редактор и руками ставим табуляцию.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35016240
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NotGonnaGetUsДоработка напильником не такая тривиальная задача как кажется.
Не надо уводить разговор в сторону, давайте сосредоточимся на теме. Предлагаю простой и незамысловатый выбор:

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

2. Вы согласны с тем, что часть правильных доработок делается наследованием. В этом случае мы сосредотачиваемся на них и в свете оных обсуждаем мой пример и его связь с первоначальной темой.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35016917
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Тем не менее, принципа это ничуть не трогает. Задача "взять и немного доработать напильником" - одна из наиболее распространенных в практическом
программировании.


Это да. Но вот к чему это приводит? Заплатки- тоже распространенная практика, но не от хорошей жизни.

С чего все началось- с обсуждения одной небольшой системой управления предприятием.
Где наследование формочек (delphi) и панелек зашло так далеко, что при правке чего-либо одного приводит к фантастическим эффектам в другом месте.
Т.е. наследники заложились на цвет кнопочки вооооон там, а тут его поменяли. Цвет- это так, для ясности :)

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35016945
The_ShadoW
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_Samara
С чего все началось- с обсуждения одной небольшой системой управления предприятием.
Где наследование формочек (delphi) и панелек зашло так далеко, что при правке чего-либо одного приводит к фантастическим эффектам в другом месте.


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

Да и оно всегда так - никакие принципы не отменяют принцип номер 0: думать надо.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35017251
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraЭто да. Но вот к чему это приводит?
К нормальной работе.

GKS_SamaraЗаплатки- тоже распространенная практика, но не от хорошей жизни.
Хм. Ваша фраза показывает одну мою ошибку: я не уточнил, что под "практическим программированием" имел в виду то, что делают вменяемые и профессиональные люди. Заплатки я к этой категории не отношу.

GKS_SamaraС чего все началось- с обсуждения одной небольшой системой управления предприятием. Где наследование формочек (delphi) и панелек зашло так далеко, что при правке чего-либо одного приводит к фантастическим эффектам в другом месте. Т.е. наследники заложились на цвет кнопочки вооооон там, а тут его поменяли. Цвет- это так, для ясности :)
Безусловно, любую иерархию классов можно спроектировать неудачно; вполне возможно, получилось что-то вроде того, что ранее привел NotGonnaGetUs . Однако, не наследование тому виной, и указанный принцип от этого не спасет. Показать это проще всего тривиальным примером: допустим, мы взяли описанную Вами "плохую" структуру, взяли те классы, которые одновременно инстанциируются и имеют наследников и привели их в соответствие этому принципу: отпочковали от них тривиальных наследников и стали инстанциировать именно их. И что, программе от того станет лучше?

Визуальное наследование - отдельная интересная тема, но и там действует общий принцип. Формально то, что Вы сказали, можно сформулировать так:

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

Да, при плохой работе это легко может случиться. И абстрактно-финальные классы этого никак не меняют. В качестве универсального метода - можно предположить, что надо было не менять базовый класс, а выделить из него новый (финальный или промежуточный) и сделать изменения там. Хотя это далеко не всегда будет хорошим решением. Так или иначе, сформулированный принцип здесь - в лучшем случае, борьба с симптомами, а не с причиной.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35019247
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
- у этого класса то ли был контракт, то ли наследник считал, что этот контракт есть
- в результате изменений контракт оказался нарушен.


О! Понятно.
Да, по сути наследник должен расчитывать только на то, что явно описано в контракте.
Контракты увы, ни в delphi ни в java не внедряются, а комментарии их заменяют очень фигово,
но лучше так, чем ничего. eiffel- не в этой жизни :)

softwarer
Так или иначе, сформулированный
принцип здесь - в лучшем случае, борьба с симптомами, а не с причиной.


Да, согласен.

Мне кажется, что по затронутой теме все прояснилось (хотя кто его знает).

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35020359
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraКонтракты увы, ни в delphi ни в java не внедряются,
"Увы" здесь имхо лишнее.

GKS_Samaraа комментарии их заменяют очень фигово,
Контракт должен быть в голове, вернее читаться головой из структуры программы. Вспомним, что идеальная программа - не нуждается в комментариях. Этого нереально достигнуть на микроуровне, но на структурном, на уровне крупных объектов, к этому можно и нужно приблизиться.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35020590
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
GKS_SamaraКонтракты увы, ни в delphi ни в java не внедряются,
"Увы" здесь имхо лишнее.


Почему лишнее?

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


Но явно написанный в заголовке с проверкой при выполнении (require) или при тестах (ensure) - все же лучше, imho.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35020835
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraНо явно написанный в заголовке с проверкой при выполнении (require) или при тестах (ensure) - все же лучше, imho.
Как Вам сказать.... это детские игры. Тут есть пара моментов.

1. Ничего глобального таким образом не опишешь. Попробуйте сформулировать контракт, который например для дельфы скажет: "перед вызовом деструктора формы обязательно должно быть вызвано событие OnClose". То, что метод X должен быть вызван с параметром Y, значение которого не больше Z - чепуха, легко вылавливаемая и легко контролируемая кучей способов. Основные проблемы - архитектурные, а как раз на них никакого вменяемого формального контракта не навесишь.

2. Наиболее интересные проверки - промежуточные, а не входные-выходные. "Метод вызван с неправильным параметром" - гораздо более приятная ошибка, нежели, например, "sql-запрос в середине логической цепочки вернул ноль строк".
...
Рейтинг: 0 / 0
О правилах разработки...
    #35020986
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
1. Ничего глобального таким образом не опишешь. Попробуйте
сформулировать контракт, который например для дельфы скажет: "перед
вызовом деструктора формы обязательно должно быть вызвано событие
OnClose".


Очевидно, что OnClose меняет состояние объекта. Т.е. оно теперь принадлежит некому подмножеству В, а не А.
Вот это и задается требованием.


softwarer
2. Наиболее интересные проверки - промежуточные, а не входные-выходные.
"Метод вызван с неправильным параметром" - гораздо более приятная
ошибка, нежели, например, "sql-запрос в середине логической цепочки
вернул ноль строк".


Вынести запрос в отдельный метод, возвращающий набор строк результата и постулировать, что результат его не пуст.
Другое дело, что тут будет двойная выборка...
Надо думать на тему оптимизации компилятором...

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35021016
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraОчевидно, что OnClose меняет состояние объекта.
Совершенно не очевидно. Если, конечно, не делать этого специально.

GKS_SamaraВот это и задается требованием.
То есть мы начинаем ломать программу под попытку ее проверить. Это порочная практика.

GKS_SamaraВынести запрос в отдельный метод, возвращающий набор строк результата
То же самое. Представьте себе, что гаечный ключ, который Вы купили, для применения к автомобилю требует предварительно выломать из него задние сидения или, допустим, перекрасить его в зеленый цвет. Нужен Вам такой инструмент?
...
Рейтинг: 0 / 0
О правилах разработки...
    #35021049
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
GKS_SamaraОчевидно, что OnClose меняет состояние объекта.
Совершенно не очевидно. Если, конечно, не делать этого специально.


А что ж он делает тогда?

softwarer
То есть мы начинаем ломать программу под попытку ее проверить. Это порочная практика.


Это почему? Программа не ломается.
Да, пример с sql - это крайний случай, там не обойтись без спецификации.

Контракт- не панацея, это удобный инструмент для некоторых случаев.
И его отсутствие- привычно, но неудобно.
Ведь в любой java-программе встречаются вещи типа
"а вот этот параметр должен быть таким-то"
"а вот этот exception кидается если мы вот это нарушили".
Проблема в том, что при рефакторинге может быть рассинхронизация,
либо в наследнике кто-то усилит требования.
Контракт снимает эти проблемы. Я не говорю, что он снимает все проблемы.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35021205
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraА что ж он делает тогда?
Код: plaintext
1.
2.
3.
 procedure  TCustomForm.DoClose( var  Action: TCloseAction);
 begin 
   if  Assigned(FOnClose)  then  FOnClose(Self, Action);
 end ;

Как Вы предлагаете в деструкторе проверить, вызывался этот код или нет?

GKS_SamaraКонтракт- не панацея, это удобный инструмент для некоторых случаев.
И его отсутствие- привычно, но неудобно.
Во-первых, кто Вам сказал, что они отсутствуют? Отсутствует максимум - ненужная и вредная поддержка этого инструмента со стороны языка. Точно так же древние языки поддерживали средства работы с файлами, которые сейчас перенесены в куда более подходящее место.

GKS_SamaraВедь в любой java-программе встречаются вещи типа
"а вот этот параметр должен быть таким-то"
"а вот этот exception кидается если мы вот это нарушили".
И? Контракты не дают здесь ничего нового. Есть исключения, есть assert-ы, есть трассировка некритических ошибок и тревожных признаков.

GKS_SamaraКонтракт снимает эти проблемы.
Ничуть. Это всего лишь менее удобный способ сообщить об этих проблемах. Менее удобный - потому что для проверки "вернул ли запрос строки" мне достаточно написать assert, а "контрактнику" придется переделывать структуру класса.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35021341
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer wrote:

> Во-первых, кто Вам сказал, что они отсутствуют? Отсутствует максимум -
> ненужная и вредная поддержка этого инструмента со стороны языка.

А как мне просто записать, что "вот это должно выполнятся, иначе по башке получишь"?
Чтобы наследники по-умолчанию проверяли, но можно было явно отключить?
И чтобы при смене менялось все автоматом, а не править в двух местах?

> Менее удобный - потому что для проверки "вернул ли запрос строки" мне
> достаточно написать assert, а "контрактнику" придется переделывать
> структуру класса.

А assert'ы в контрактном программировании тоже есть.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35021372
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraА как мне просто записать, что "вот это должно выполнятся, иначе по башке получишь"?
Assert - для того, для чего подходит. Ну или любые аналогичные средства. Но архитектурных проблем это не исправит.

GKS_SamaraЧтобы наследники по-умолчанию проверяли, но можно было явно отключить?
Полиморфизм. Тут важно не только это; важно то, что если наследник вызывает inherited - должны провериться контракты предка. Как раз это и будет.

GKS_SamaraИ чтобы при смене менялось все автоматом, а не править в двух местах?
Не понял вопроса. Вернее, не понял, какую ситуацию Вы подразумеваете.

GKS_SamaraА assert'ы в контрактном программировании тоже есть.
Есть. Как вынужденная мера. Контрактное программирование - это по сути бесполезная надстройка над придуманным не помню кем простым и маленьким макросом ASSERT. Какой-то смысл у нее появляется с точки зрения автоматической верификации кода, впрочем....
...
Рейтинг: 0 / 0
О правилах разработки...
    #35022192
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Полиморфизм. Тут важно не только это; важно то, что если наследник вызывает inherited - должны провериться контракты предка. Как раз это и будет.


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

softwarer
GKS_Samara
И чтобы при смене менялось все автоматом, а не править в двух местах?

Не понял вопроса. Вернее, не понял, какую ситуацию Вы подразумеваете.


Рассмотри два исскуственный пример:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
   /**
    * Тупо корень
    * @param value то, от чего берется корень. Должно быть больше нуля
    * @throws LessNulException
    */
   public double sqrt(double value)
     throws LessNulException
   {
     if (value <  0 )
       throw new LessNulException("Значение меньше нуля");
     return Math.sqrt(value);
   }
Тут приходится дублировать и сам exception, и текст. Куча возможности для рассинхронизации.
А теперь рассмотрим тот же пример, как будто в java есть контракт
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
   /**
    * Тупо корень
    * @param value то, от чего берется корень
    */
   public double sqrt(double value)
     require value >=  0  else throw new LessNulException("Значение меньше нуля")
     ensure Result*Result = value
   {
     return Math.sqrt(value);
   }
Дублирования кода _нет_.
Существенный плюс, на мой взгляд. Учитывая то, что ООП-то было задумано для устранения дублирования кода
ensure- это несколько уменьшает потребность в unit-тестах ;)

softwarer
Контрактное программирование - это по сути бесполезная надстройка над придуманным не помню кем простым и маленьким макросом ASSERT.


Контрактное программирование - это способ жестко увязать декларацию, документацию и реализацию.
Что в java приходится делать вручную.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35023502
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraНо это не устраняет возможность появления такой ошибки, как ужесточение входного требования.
А что же устраняет возможность появления такой ошибки? Разве что редактор, который в момент написания кода высветит ошибку и не даст сохранить такой текст...

GKS_SamaraОчень грубой ошибки, кстати.
Очень простой, приятной и дешевой ошибки. В то время как интересна - борьба с серьезными ошибками.

GKS_SamaraТут приходится дублировать и сам exception,
Это персональная дурость явы, которую можно и нужно записать в минусы языку, но никак не концептуальный недостаток "всех языков". Лично я предпочитаю следующую точку зрения: в Delphi подпрограммы определяются с обязательным использованием ключевого слова procedure, в Яве подпрограммы определяются с обязательным использованием ключевых слов thows Throwable.

GKS_Samara и текст.
Где? Не вижу в примере дублирования текста. Или другую явовскую дурость под названием javadoc также относим к программе?

GKS_SamaraА теперь рассмотрим тот же пример, как будто в java есть контракт
....
Дублирования кода _нет_.
Не вижу, какое именно дублирование кода устранено. Ткните, пожалуйста, пальцем. А лучше - давайте так: я пишу тот же самый пример -

Код: plaintext
1.
2.
3.
4.
5.
 function  MySqrt (Value: double): double;
 begin 
  Assert (Value >=  0 , 'Value должно быть неотрицательным');
  Result := Math.Sqrt (Value);
  Assert (Abs (Result * Result - Value) <  0 . 00001 , 'Акела промахнулся');
 end ;

- а Вы покажите, пожалуйста, чем его улучшит введение контракта.

GKS_SamaraСущественный плюс, на мой взгляд. Учитывая то, что ООП-то было задумано для устранения дублирования кода
Это, простите, отдельная глупость.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35023813
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
GKS_Samara
Но это не устраняет возможность появления такой ошибки, как ужесточение входного требования.

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


А нельзя в наследнике добавить предусловий через and. Только через or.
Да, внутри можно assert'ов поставить, но вот require - нельзя.

softwarer
Это персональная дурость явы, которую можно и нужно записать в минусы
языку, но никак не концептуальный недостаток "всех языков". Лично я
предпочитаю следующую точку зрения: в Delphi подпрограммы определяются с
обязательным использованием ключевого слова procedure, в Яве
подпрограммы определяются с обязательным использованием ключевых слов
thows Throwable.


Честно говоря, после такого заявления хочется завершить разговор- настолько оно бредово.
Полное знание возможных exception'ов метода- то, чего _очень_ мне не хватает в других языках.

softwarer
А лучше - давайте так: я пишу тот же самый пример -

Код: plaintext
1.
2.
3.
4.
5.
6.
  function MySqrt (Value: double): double;
  begin
    Assert (Value >=  0 , 'Value должно быть неотрицательным');
    Result := Math.Sqrt (Value);
    Assert (Abs (Result * Result - Value) <  0 . 00001 , 'Акела промахнулся');
  end;
- а Вы покажите, пожалуйста, чем его улучшит введение контракта.


Поскольку рассматривание implementation части чужого unit'а- занятие для мазохиста,
то надо добавить еще и interface часть:

Код: plaintext
1.
2.
3.
  function MySqrt (Value: double): double;
  // Value должно быть неотрицательным, иначе- AssertException
  // Как результат - Result*Result = Value

Необходимость этого комментария и устраняет контракт.
Это кроме _синтаксических_ требований к наследнику- только ослаблять предусловия и только усиливать постусловия.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35023988
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraА нельзя в наследнике добавить предусловий через and. Только через or.
Да, внутри можно assert'ов поставить, но вот require - нельзя.
"Нельзя" - Вы здесь имеете в виду "нельзя физически" или "нельзя концептуально"? Впрочем, я не согласен ни с тем, ни с другим.

GKS_SamaraЧестно говоря, после такого заявления хочется завершить разговор- настолько оно бредово. Полное знание возможных exception'ов метода- то, чего _очень_ мне не хватает в других языках.
Во-первых, в яве полного знания нет. Во-вторых же, это скорее всего пройдет, как только Вам надоест, поменяв одну маленькую функцию, носиться исправлять throws во всех функциях, которые ее прямо или косвенно используют.

GKS_SamaraПоскольку рассматривание implementation части чужого unit'а- занятие для мазохиста,
Тогда давайте обойдемся без обсуждения явы - поскольку в ней implementation намертво увязан с interface, и как следствие, "не просматривать его" невозможно.

GKS_Samaraто надо добавить еще и interface часть:
Это, кстати, совершенно необязательно.

GKS_Samara
Код: plaintext
1.
2.
3.
  function MySqrt (Value: double): double;
  // Value должно быть неотрицательным, иначе- AssertException
  // Как результат - Result*Result = Value

Не надо портить код. Интерфейсная часть к этому имеет вид

Код: plaintext
1.
 { Замена стандартной Math.Sqrt }   
 function  MySqrt (Value: double): double;

GKS_SamaraНеобходимость этого комментария и устраняет контракт.
Необходимости в этом комментарии нет, это мусор.

GKS_SamaraЭто кроме _синтаксических_ требований к наследнику- только ослаблять предусловия и только усиливать постусловия.
Это мертворожденное требование, на практике - бессмысленное и нереальное.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35024310
Пользователь
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer GKS_SamaraЭто кроме _синтаксических_ требований к наследнику- только ослаблять предусловия и только усиливать постусловия.
Это мертворожденное требование, на практике - бессмысленное и нереальное.
(чтоб ваша дискуссия не затихла)
- Вроде создание "надежных" языков программирования - и подразумевает дополнение всякими проверками - пред и пост условиями?
(?) Почему тогда "мертворожденное требование, на практике - бессмысленное и нереальное"?
...
Рейтинг: 0 / 0
О правилах разработки...
    #35025123
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
GKS_Samara
А нельзя в наследнике добавить предусловий через and. Только через or.
Да, внутри можно assert'ов поставить, но вот require - нельзя.

"Нельзя" - Вы здесь имеете в виду "нельзя физически" или "нельзя
концептуально"?


Нельзя физически- компилятор пошлет.

softwarer
Впрочем, я не согласен ни с тем, ни с другим.


Иначе нельзя. А то я читаю спецификацию класса, вижу требование к параметру "value>=0", вызываю и получаю по шее.
Как? А оказывается мне подсунули его потомка в 10 колене и он хочет еще и "value!=1".

softwarer
Во-первых, в яве полного знания нет.


Оно достаточно полное. Знание о крахе виртуальной машины или ошибке четности памяти мне не надо- все одно надо будет убить себя об стену :)

softwarer
Во-вторых же, это скорее всего пройдет, как только Вам надоест, поменяв одну маленькую функцию, носиться исправлять throws во всех функциях, которые
ее прямо или косвенно используют.


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

softwarer
GKS_Samara
Поскольку рассматривание implementation части чужого unit'а- занятие для мазохиста,

Тогда давайте обойдемся без обсуждения явы - поскольку в ней implementation намертво увязан с interface, и как следствие, "не просматривать его"
невозможно.


У Явы надо читать не java, а JavaDoc'и.
Хотя подход Oberon/eiffel (в терминах delphi- создание interface по implementaton автоматически) мне нравится больше.
Ну или бы подход Ada/Modula2 с раздельными частями, когда package body можно не видеть вообще.

softwarer
Не надо портить код. Интерфейсная часть к этому имеет вид
Код: plaintext
1.
2.
{ Замена стандартной Math.Sqrt }
*function* MySqrt (Value: double): double;


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

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35025868
муня
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GKS_SamaraПолное знание возможных exception'ов метода- то, чего _очень_ мне не хватает в других языках.кстати, интересно, как в джаве это решают при реализации интерфейса. Ведь из реализующего кода могут вылетать совершенно любые эксепшены, не предусмотренные интерфейсом.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35025966
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
муня
кстати, интересно, как в джаве это решают при реализации интерфейса.


Очень логично и правильно- в реализации нельзя объявить exception'ов больше, чем в interface'е.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35026240
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GKS_SamaraНельзя физически- компилятор пошлет.
Значит, в таком вот "нарушающем" потомке просто не будут писать requires, сделают проверку другими способами.

GKS_SamaraИначе нельзя. А то я читаю спецификацию класса, вижу требование к параметру "value>=0", вызываю и получаю по шее. Как? А оказывается мне подсунули его потомка в 10 колене и он хочет еще и "value!=1".
Сугубо теоретически - согласен, нельзя. Очень красивая, стройная теория, с одним большим минусом - она не дает ответа на вопрос "как же писать программы, отвечающие этому требованию".

Как любил говорить мой научный руководитель - "Математик делает то, что можно, так, как нужно. Программист же делает то, что нужно, так, как можно". Вышеизложенное требование - сугубо математическое в смысле этого высказывания.

GKS_SamaraОно достаточно полное. Знание о крахе виртуальной машины или ошибке четности памяти мне не надо- все одно надо будет убить себя об стену :)
Существует полно ситуаций, когда и убивать себя незачем, но и "знания" нет. Я обычно привожу в пример обновление информации в статусбаре. Если код, обновляющий статусбар по таймеру, начнет падать по какой-либо дурацкой причине - надо всего лишь отключить это обновление и убрать статусбар, это будет лучшей реакцией в 99% случаев. Но программист, привыкший полагаться на throws как на источник информации о возможных исключениях, об этом заведомо никогда не подумает, не имеет права. А потому, в зависимости от деталей реализации, такой подход приведет к следующим вариантам:

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

GKS_SamaraЕсли у маленькой функции вдруг появилось еще одно слабое место или предусловие, то все одно всех клиентов надо пересматривать, что бы там компилятор не позволял.
Если не понимать смысла концепции исключений, то безусловно, надо. Есть такой очень забавный эффект, наблюдаю не в первый раз, я бы его назвал оптимизмом новичка. Выглядит он примерно так:

- была некая неудобная технология, например, "коды завершения функций" и обработка ошибок на основании их анализа

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

- постепенно сложилось поколение программистов, не работавших с кодами возврата

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

Это Ваше "надо пересматривать" противоречит принципу модульности. Нормальная ситуация: ошибку регистрирует один модуль, вызывается он из другого модуля, а обрабатываться ошибка будет в третьем модуле. И другой модуль ни фига не должен знать об этой ошибке; его задача всего лишь - не мешать ее нормальной обработке. Требуя "пересматривать", Вы предлагаете завязать хорошие и правильные модули в один дурацкий неразрывный клубок, в этакий "один большой пельмень" (который получается, если пачке пельменей дали подтаять).

GKS_SamaraУ Явы надо читать не java, а JavaDoc'и.
Это нереально. Мало-мальски серьезный javadoc не имеет ни шанса соответствовать реальному положению дел; этого можно добиться только либо в тривиальных искусственных случаях, а-ля примеры в книжках, либо есть "все бросить" и поставить основной целью не выпуск продукта, а поддержку javadoc-ов.

Для иллюстрации проще всего сослаться на javadoc-и по JDK. Вот уж, казалось бы, флагман, которым пользуются миллионы людей, который поддерживается большой командой, который является выставочным примером, показателем технологии. Однако, если работать на яве - регулярно приходится лезть в исходники и регулярно обнаруживается даже не неполнота, а явные ошибки javadoc-ов. Лично я - эдак полгода честно пытался пользоваться, после чего пришел к выводу, что это пустая трата времени. Если хочешь "узнать как надо делать" - надо смотреть tutorial, если хочешь "узнать, что за хрень творится" - надо сразу лезть в исходники.

GKS_SamaraХотя подход Oberon/eiffel (в терминах delphi- создание interface по implementaton автоматически) мне нравится больше.
Автоматизация кодогенерации показывает недостатки языка. Такие вещи лучше делать на уровне IDE (скажем, показать заголовок класса без реализации, а лучше и без приватных частей и с отключаемым отображением protected). Хотя еще лучше - иметь язык и технологию, которые позволят видеть и редактировать "то, что нужно, так, как нужно" хоть в нотепаде.

GKS_SamaraНу или бы подход Ada/Modula2 с раздельными частями, когда package body можно не видеть вообще.
По опыту PL/SQL, все нормальные средства редактирования тем не менее дают возможность смотреть их вместе :)

В целом, меня вполне устраивает реализация в PL/SQL (которая взята из Ada), дельфовая пожалуй чуть удобнее (поскольку позволяет быстрый и простой переход между interface и implementation во-первых, и нет теоретического шанса на разъезжание версий interface и implementation).

GKS_SamaraЭто пойдет только для вырожденного случая замены стандартной функции, который нафиг не нужен.
Нет. Комментарий к функции должен давать короткую и четкую формулировку того, зачем эта функция нужна, остальное - мусор, мешающий читать код. Более подробно - можно писать в документации, отделенной от кода, хотя постепенно я все больше и больше убеждаюсь, что потребность в такой документации вызывается проблемами проектирования и кодирования.

GKS_SamaraВ более сложных случаях надо описывать предусловия (а хорошо бы и пост) в заголовке.
Нет, не нужно, это маниловщина с элементами саботажа. Саботаж - потому, что наличие нетривиальных предусловий чаще всего означает плохую реализацию.
...
Рейтинг: 0 / 0
О правилах разработки...
    #35026273
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer- программа молча падает с необработанным исключением в логе
- программа молча срет в лог информацией об исключениях, статусбар на экране при этом неадекватен
- программа раз в секунду выплевывает на экран окно с сообщением об ошибке
- (не хочу утверждать, что это исчерпывающий список, просто типичные варианты, которые я видел)


Не исчерпывающий :)
Как тебе такой вариант (из жизни C++ - ников):

- программа молча завершает работу, так как было сформировано исключение непредусмотренное заданной спецификацией throw

?
...
Рейтинг: 0 / 0
О правилах разработки...
    #35026417
GKS_Samara
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Значит, в таком вот "нарушающем" потомке просто не будут писать requires, сделают проверку другими способами.


softwarer
Я обычно привожу в пример обновление информации в статусбаре. Если код, обновляющий статусбар по таймеру, начнет падать по какой-либо
дурацкой причине - надо всего лишь отключить это обновление и убрать статусбар, это будет лучшей реакцией в 99% случаев. Но программист,
привыкший полагаться на throws как на источник информации о возможных исключениях, об этом заведомо никогда не подумает, не имеет права.


Оба- от недостатка опыта, а не от недостатков технологии.

softwarer
Лично я - эдак полгода честно пытался пользоваться, после чего пришел к выводу, что это пустая трата
времени. Если хочешь "узнать как надо делать" - надо смотреть tutorial, если хочешь "узнать, что за хрень творится" - надо сразу лезть в исходники.


Да я не считаю java (тем более JDK) примером хорошо продуманной системы.
Очень много написанно "лишь бы как".

softwarer
Автоматизация кодогенерации показывает недостатки языка. Такие вещи
лучше делать на уровне IDE (скажем, показать заголовок класса без
реализации, а лучше и без приватных частей и с отключаемым отображением
protected). Хотя еще лучше - иметь язык и технологию, которые позволят
видеть и редактировать "то, что нужно, так, как нужно" хоть в нотепаде.


Вот это и достигается созданием спецификации (все публичные вещи + комментарии, помеченные для экспорта) при компиляции.
Хотя, еще раз, вариант создания "рыбы" реализации по спецификации- тоже хорош.

softwarer
Нет. Комментарий к функции должен давать короткую и четкую формулировку
того, зачем эта функция нужна, остальное - мусор, мешающий читать код.


Т.е. знание того, как и почему функция может упасть- лишнее? Не согласен категорически.

softwarer
Нет, не нужно, это маниловщина с элементами саботажа. Саботаж - потому,
что наличие нетривиальных предусловий чаще всего означает плохую реализацию.


Тривильность у каждого своя.

--
Алексей
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
О правилах разработки...
    #35027377
Пользователь
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerЭто Ваше "надо пересматривать" противоречит принципу модульности. Нормальная ситуация: ошибку регистрирует один модуль, вызывается он из другого модуля, а обрабатываться ошибка будет в третьем модуле.
- кроме тривиальных завершить\показать код ошибки, то все ошибки уникальны, тогда необходимо полное перечисление всех возможных ошибок + необходимо знать контекст, чтобы правильно реагировать, а полный контекст может быть недоступен "а обрабатываться ошибка будет в третьем модуле".
- насколько я понимаю, "надежное" программирование - вообще отказаться от исключений: каждое исключение перевести в нормальную ветвь логики в том месте, где оно возникло (особенно при проектировании автоматов, где нет пользователя).
...
Рейтинг: 0 / 0
35 сообщений из 35, показаны все 2 страниц
Форумы / Программирование [игнор отключен] [закрыт для гостей] / О правилах разработки...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]