"мы не знаем что правильно, но знаем что делает GCC" - все верно, чтобы собрать Linux - надо быть конкретно GCC/C, Clang буквально флаг-в-флаг, атрибут-в-атрибут прикидывается GCC, чтобы тонны "как бы сишных исходников" собирать.
Ну берем самый "олдовый" из живых - GCC - был получен Столлманом в ходе переписывания, еще более олдового, компилятора Pastel(Столлману отдали исходники компилятора языка Паскаль, сказав "используй как хочешь"). А прежде чем GCC научился в "полную поддержку Си 89" - прошло лет 5.
Загляните в исходники GCC, а потом в CCC и сделайте выводы сами. Признаться честно у CCC они не самые "нечитаемые" среди виденных мною homebrew компиляторов.
Причем тут использование нейросетей? Я изменил изначальное TEsCustomControl на TEsWinControl короткое данное имя лучше ассоциируется.
Но до этого написали:
Ваш TEsWinControl является аналогом TCustomControl. Значит он должен соблюдать соглашение API.
Противоречие не находите? Сделали некий TEsWinControl, а мне пишите про «недостатки» TEsCustomControl.
Как связаны по вашему концепции наличие соглашение API и знание ООП? Я разве отрицал какие-то парадигмы и говорил что они неправильные? Не выдумывайте себе
Да, вы пишите, что я что-то там «сломал», хотя TEsCustomControl строго соблюдает интерфейс своего предка TWinControl. Вы же ожидаете соответствие интерфейсу TCustomControl, от которого мой класс НЕ наследуется.
Я вам говорю, о том, что расширение/изменение сигнатуры у обработчиков, с точки зрения дизайна VCL, не ломает общую логическую цепочку. Если у класса есть метод OnPaint, то этот метод всегда имеет одну сигнатуру, в противном случае, меняется название. Об этом статья. Вы зациклились на одном слове "API" и всякую фигню выдумываете
Где конкретно, в официальной документации Embarcadero, написано что OnPaint обязан иметь конкретную «стандартную» сигнатуру? Это ваше видение «красоты», не более. У меня оно свое - Canvas - не должен «торчать» в паблике.
Ваш TEsWinControl является аналогом TCustomControl. Значит он должен соблюдать соглашение API.
Вы точно не запутались с использованием нейросетей? У меня нет никакого TEsWinControl, у меня есть TEsCustomControl. TEsWinControl - это ваше изобретение, соблюдайте что хотите.
Мой TEsCustomControl является аналогом TCustomControl по концепции «кастомный компонент». Но TEsCustomControl не является наследником TCustomControl, и не должен соблюдать интерфейс TCustomControl, это ваша хотелка, не более.
Вы когда-нибудь слышали про концепцию ООП? Про наследование классов и т.д.? Вам должно быть известно, что наследник класса должен быть полностью работоспособным в коде ожидающим объект класса-предка. Но вот только вы требуете, чтобы TEsCustomControl соблюдал интерфейс «левого» TCustomControl, который не является предком TEsCustomControl. Предок TEsCustomControl это TWinControl, его «контракт» соблюден на 100%.
Иерархия классов, наследование, полиморфизм, вам знакомы эти слова? Вы точно профессионал и архитектор? Такое ощущение что вы базы ООП не понимаете.
Тогда необходимо расширять методы, менять название, чтобы не было внутренних противоречий со сложившей практикой написания сигнатур для обработчиков.
Что именно должен расширять TEsCustomControl? У его предка TWinControl нет события OnPaint. Я же в TEsCustomControl создал новое событие OnPaint, и создал его таким, каким захотел. И нет, ничего не сломал, в соответствии с базовыми принципами ООП, разрешающими добавлять в наследниках что угодно, пока оно не ломает интерфейс предка.
Контракт VCL таков, что события OnXXX предназначены для пользователя компонента(программиста который кидает его на форму), не для создания наследников.
Наследники должны перекрывать виртуальные методы.
В случае с TEsCustomControl (у TCustomControl кстати тоже)это метод Paint:
/// <summary> /// Descendantsmustoverride this method for custom rendering /// </summary> procedure Paint; virtual;
Аргументированная критика - это безусловно хорошо, но как автор "оригинала", не соглашусь по всем пунктам:
Ошибка №1: «Удобный» OnPaint ломает совместимость
Вспомните: у TForm, TPanel, TButton — везде один и тот же тип:
__property TNotifyEvent OnPaint; // т.е. void __fastcall(TObject* Sender)
Если вы меняете сигнатуру, ваш компонент:
Нельзя использовать в шаблонах, где ожидается наследование от TWinControl.
Требует уникального кода обработки, который не работает с другими контролами.
Ломает условную компиляцию: заменить TWinControl на TEsWinControl через #define теперь невозможно — придётся править множество мест, где используется данная сигнатура метода
Не ясно о чем вообще речь, у TWinControl и TButton - нет свойства OnPaint, следовательно - никакой контракт TWinControl не был нарушен.
То, что у TCustomControl тоже есть свойство OnPaint, которое отличается по сигнатуре - не более чем совпадение. В VCL куча мест, где одно и тоже свойство имеет разный тип в "дальних" ветках TControl.
TEsCustomControl это не наследник TCustomControl,
TEsCustomControl - это наследник TWinControl, и не должен соблюдать контракты TCustomControl.
Про #define - а зачем это вообще? Все, что я обеспечиваю - это работоспособность FreeEsVclComponents в C++Builder, игры с #define - это уже не ко мне.
Ошибка №2: Canvas уже есть — зачем его передавать?
При написание события возникает мысль «Почему бы не передать Canvas, чтобы пользователю было проще». Но это избыточно.
Во-первых, Canvas доступен напрямую:
Нет, у TEsCustomControl свойство Canvas не доступно напрямую. Свойство Canvas объявлено в секции protected, исключительно для удобства написания наследников данного компонента. Из кода "снаружи" Canvas не доступен.
Canvas передается в событие OnPaint, и это сделано специально, чтобы у пользователя не возникало "соблазна" рисовать вне события OnPaint, что не приводит ни к чему хорошему.
То, что в TCustomControl свойство Canvas доступно вне событий отрисовки - ошибка дизайна. Причем ошибка дизайна WinApi, которая "воссоздана" в VCL.
Ошибка №3: Rect вводит в заблуждение
В коде из статьи Rect всегда равен ClientRect
Параметр Rect был добавлен для удобства, дабы из Sender не надо было вытягивать ClientRect для "заливки" цветом и т.д.. Кому не надо - могут не использовать.
Сравнение с официальными компонентами VCL
Рассмотрим компонент TCustomPanel . Его метод TCustomPanel::Paint() — переопределяет отрисовку, но OnPaint остаётся стандартным по сигнатуре. У TGraphicControl рисуется напрямую в Canvas но не передаёт его в событие. А TDBGrid это вообще сложнейший компонент, но его OnDrawColumnCell это расширение, а не замена OnPaint. Они не ломают контракт. Они расширяют функционал, добавляя новые события, если нужно, но не меняют старые.
TCustomPanel - наследник TCustomControl и обязан соблюдать его контракт.
TEsCustomControl - не наследник TCustomControl и не должен соблюдать его контракт.
Если бы я унаследовал TEsCustomControl от компонента с событием OnPaint и поменял бы сигнатуру события, то да, я нарушил бы контракт OnPaint. Но я создал наследника от TWinControl, у которого нет никакого OnPaint, контракт которого я должен был бы соблюдать.
Совпали имена событий в разных "ветках"? Да. Бывает. Это нормально.
Если приходится писать отдельный обработчик, который больше ни с чем не работает, если приходится помнить, что «тут Canvas передаётся, а тут — нет», или если замена TWinControl на ваш класс ломает половину формы — вы не упростили ему жизнь. Вы просто переложили свою головную боль на него.
Да, при использовании TEsCustomControl приходиться задуматься, когда видишь другую сигнатуру OnPaint - это фича. Приходит понимание, почему рисовать на Canvas компонента можно только в OnPaint. И почему Canvas доступный "всегда" - это "багофича".
А суть хорошего компонента как раз в другом: пусть он делает всё сам, а пользователь рисует в Canvas, как привык, и даже не догадывается, что под капотом — двойная буферизация, кэширование фона и прочая магия.
Если из TEsCustomControl вытащить Canvas, и начать рисовать вне события OnPaint "как привык", что часто встречается в древнем коде, то будут какие угодно глюки.
Я сделал компонент с API запрещающим рисовать вне специально отведенного места. Это стандартный подход для GUI библиотек.
---
В конце концов, это всего лишь мой взгляд на "правильный" API OnPaint, если он не нравиться, то исходники открыты, можно сделать как удобно, пока соблюдается лицензия.
Смысл оригинальной статьи - дать набор идей и реализацию, которую каждый может доработать под себя. Вы доработали, нашли применение? - Отлично, поделитесь кейсом использования "в продакшене", как автору, это мне интереснее, чем абстрактная "красота" API.
Вопрос: Использует ли FFmpeg запатентованные алгоритмы?
Ответ: Мы не знаем, мы не юристы, поэтому мы не квалифицированы, чтобы ответить на это. Кроме того, мы никогда не читали патенты на реализацию какой-либо части FFmpeg, поэтому даже если бы мы были квалифицированы, мы не могли бы ответить на них, так как не знаем, что запатентовано. Кроме того, простое количество патентов на программное обеспечение делает невозможным их все, поэтому никто (юрисист или нет) не может ответить на такой вопрос определенным "нет", те, кто лжет. Что мы знаем, так это то, что различные стандарты, поддерживаемые FFmpeg, содержат расплывчатые намеки на то, что любая соответствующая реализация может подлежать некоторым патентным правам в некоторых юрисдикциях, примеры таких заявлений:
Вопрос: Вполне нормально ли включить все ядро FFmpeg в мой собственный коммерческий продукт?
Ответ: У вас здесь может быть проблема. Были случаи, когда компании использовали FFmpeg в своих продуктах. Эти компании выяснили, что как только вы начнете пытаться заработать деньги на запатентованных технологиях, владельцы патентов придут за своими лицензионными сборами. Примечательно, что MPEG LA бдительно и старательно собирает технологии, связанные с MPEG.
Имхо с учетом этой «жижи» сам FFMPEG должен распространяться под «паблик домеин» со словами «юзайте на свой страх и риск, мы хз».
На Хабре тут уже был один персонаж - mihip, тоже делал шизофренические компиляторы (WCT Lang - по факту просто замена HEX(0..9ABCDEF) на буквы ABCDEF…), продвигал бредо идею распределенного интернет провайдера поверх обычного интернета. Как и ты, постоянно создавал новые аккаунты на Хабре, после очередного слива кармы. Те же обороты речи с «мы разрабатываем», «мы анонсировали», и т.д.. Тоже рассказывал, что его «гнобят», и не понимают его «гениальность».
Настолько мне известно, в конечном итоге, mihip обратился к специалисту, пропил таблетки, и теперь спокойно работает в IT индустрии разработчиком. Тебе советую того же, обратиться к специалисту, дабы вправили чердак, пока не поздно.
"мы не знаем что правильно, но знаем что делает GCC" - все верно, чтобы собрать Linux - надо быть конкретно GCC/C, Clang буквально флаг-в-флаг, атрибут-в-атрибут прикидывается GCC, чтобы тонны "как бы сишных исходников" собирать.
Ну берем самый "олдовый" из живых - GCC - был получен Столлманом в ходе переписывания, еще более олдового, компилятора Pastel(Столлману отдали исходники компилятора языка Паскаль, сказав "используй как хочешь"). А прежде чем GCC научился в "полную поддержку Си 89" - прошло лет 5.
А где собственно ссылка на оригинальную публикацию?
Загляните в исходники GCC, а потом в CCC и сделайте выводы сами. Признаться честно у CCC они не самые "нечитаемые" среди виденных мною homebrew компиляторов.
А «кожаные» с нуля прям компиляторы пишут? То что ЛЛМ смогла довести компилятор си до рабочего состояния о чем то да и говорит.
Исходники любого компилятора - это не возможный для поддержки код, без структуры и логики. Специфика такая.
И да:
У делфового TWinControl нет никаких Canvas и OnPaint, вы нарушили ожидание разработчика о том что у TWinControl нет данных свойств :)
Т.е. в своем WinControl вы симитировали интерфейс CustomControl. Неожиданно знаете ли :)
Сейчас вы пишите:
Но до этого написали:
Противоречие не находите? Сделали некий TEsWinControl, а мне пишите про «недостатки» TEsCustomControl.
Да, вы пишите, что я что-то там «сломал», хотя TEsCustomControl строго соблюдает интерфейс своего предка TWinControl. Вы же ожидаете соответствие интерфейсу TCustomControl, от которого мой класс НЕ наследуется.
Где конкретно, в официальной документации Embarcadero, написано что OnPaint обязан иметь конкретную «стандартную» сигнатуру? Это ваше видение «красоты», не более. У меня оно свое - Canvas - не должен «торчать» в паблике.
Странно, я думал у архитектора есть «много денег».
За много денег вы можете получить от меня консультацию по основам создания VCL компонентов, писать в ЛС.
Вы точно не запутались с использованием нейросетей? У меня нет никакого TEsWinControl, у меня есть TEsCustomControl. TEsWinControl - это ваше изобретение, соблюдайте что хотите.
Мой TEsCustomControl является аналогом TCustomControl по концепции «кастомный компонент». Но TEsCustomControl не является наследником TCustomControl, и не должен соблюдать интерфейс TCustomControl, это ваша хотелка, не более.
Вы когда-нибудь слышали про концепцию ООП? Про наследование классов и т.д.? Вам должно быть известно, что наследник класса должен быть полностью работоспособным в коде ожидающим объект класса-предка. Но вот только вы требуете, чтобы TEsCustomControl соблюдал интерфейс «левого» TCustomControl, который не является предком TEsCustomControl. Предок TEsCustomControl это TWinControl, его «контракт» соблюден на 100%.
Иерархия классов, наследование, полиморфизм, вам знакомы эти слова? Вы точно профессионал и архитектор? Такое ощущение что вы базы ООП не понимаете.
Что именно должен расширять TEsCustomControl? У его предка TWinControl нет события OnPaint. Я же в TEsCustomControl создал новое событие OnPaint, и создал его таким, каким захотел. И нет, ничего не сломал, в соответствии с базовыми принципами ООП, разрешающими добавлять в наследниках что угодно, пока оно не ломает интерфейс предка.
И еще:
Контракт VCL таков, что события OnXXX предназначены для пользователя компонента(программиста который кидает его на форму), не для создания наследников.
Наследники должны перекрывать виртуальные методы.
В случае с TEsCustomControl (у TCustomControl кстати тоже) это метод Paint:
https://github.com/errorcalc/FreeEsVclComponents/blob/dc6caebea54e968d544f14a20dba7655786b3932/Source/ES.BaseControls.pas#L224
Таков контракт, вы его нарушили.
Аргументированная критика - это безусловно хорошо, но как автор "оригинала", не соглашусь по всем пунктам:
Не ясно о чем вообще речь, у TWinControl и TButton - нет свойства OnPaint, следовательно - никакой контракт TWinControl не был нарушен.
То, что у TCustomControl тоже есть свойство OnPaint, которое отличается по сигнатуре - не более чем совпадение. В VCL куча мест, где одно и тоже свойство имеет разный тип в "дальних" ветках TControl.
TEsCustomControl это не наследник TCustomControl,
TEsCustomControl - это наследник TWinControl, и не должен соблюдать контракты TCustomControl.
Про #define - а зачем это вообще? Все, что я обеспечиваю - это работоспособность FreeEsVclComponents в C++Builder, игры с #define - это уже не ко мне.
Нет, у TEsCustomControl свойство Canvas не доступно напрямую. Свойство Canvas объявлено в секции protected, исключительно для удобства написания наследников данного компонента. Из кода "снаружи" Canvas не доступен.
Canvas передается в событие OnPaint, и это сделано специально, чтобы у пользователя не возникало "соблазна" рисовать вне события OnPaint, что не приводит ни к чему хорошему.
То, что в TCustomControl свойство Canvas доступно вне событий отрисовки - ошибка дизайна. Причем ошибка дизайна WinApi, которая "воссоздана" в VCL.
Параметр Rect был добавлен для удобства, дабы из Sender не надо было вытягивать ClientRect для "заливки" цветом и т.д.. Кому не надо - могут не использовать.
TCustomPanel - наследник TCustomControl и обязан соблюдать его контракт.
TEsCustomControl - не наследник TCustomControl и не должен соблюдать его контракт.
Если бы я унаследовал TEsCustomControl от компонента с событием OnPaint и поменял бы сигнатуру события, то да, я нарушил бы контракт OnPaint. Но я создал наследника от TWinControl, у которого нет никакого OnPaint, контракт которого я должен был бы соблюдать.
Совпали имена событий в разных "ветках"? Да. Бывает. Это нормально.
Да, при использовании TEsCustomControl приходиться задуматься, когда видишь другую сигнатуру OnPaint - это фича. Приходит понимание, почему рисовать на Canvas компонента можно только в OnPaint. И почему Canvas доступный "всегда" - это "багофича".
Если из TEsCustomControl вытащить Canvas, и начать рисовать вне события OnPaint "как привык", что часто встречается в древнем коде, то будут какие угодно глюки.
Я сделал компонент с API запрещающим рисовать вне специально отведенного места. Это стандартный подход для GUI библиотек.
---
В конце концов, это всего лишь мой взгляд на "правильный" API OnPaint, если он не нравиться, то исходники открыты, можно сделать как удобно, пока соблюдается лицензия.
Смысл оригинальной статьи - дать набор идей и реализацию, которую каждый может доработать под себя. Вы доработали, нашли применение? - Отлично, поделитесь кейсом использования "в продакшене", как автору, это мне интереснее, чем абстрактная "красота" API.
Ну да, ну да, навесил GNU GPL на что угодно, и «освободил», это другое))
А знаете, забавно DMCA наезды от команды FFMPEG видеть, ибо они сами не уверены что что либо не нарушают:
https://ffmpeg.org/legal.html
Имхо с учетом этой «жижи» сам FFMPEG должен распространяться под «паблик домеин» со словами «юзайте на свой страх и риск, мы хз».
Ой, простите нет. “Все есть файл” - это самое убогое и анти-удобное что было создано, и закрепилось навсегда в виде нескончаемого UNIX/POSIX/C legacy.
Ага, конечно, юникс и си-баребухи с нами навсегда уже :с
Свалите уже с Хабра наконец, и заберите с собой свои непрошеные карьерные советы и унылые телеграм каналы.
Вижу "волк" - минусую, щито поделать.
На Хабре тут уже был один персонаж - mihip, тоже делал шизофренические компиляторы (WCT Lang - по факту просто замена HEX(0..9ABCDEF) на буквы ABCDEF…), продвигал бредо идею распределенного интернет провайдера поверх обычного интернета. Как и ты, постоянно создавал новые аккаунты на Хабре, после очередного слива кармы. Те же обороты речи с «мы разрабатываем», «мы анонсировали», и т.д.. Тоже рассказывал, что его «гнобят», и не понимают его «гениальность».
Настолько мне известно, в конечном итоге, mihip обратился к специалисту, пропил таблетки, и теперь спокойно работает в IT индустрии разработчиком. Тебе советую того же, обратиться к специалисту, дабы вправили чердак, пока не поздно.