« first day  last day (15 days later) » 

00:08
@tym32167 спасибо за терпение и что продолжаете отвечать) Я не просто поспорить или поумничать пришел, мне действительно хочется понять как же все-таки правильно. По поводу D из SOLID. Событийная модель - это и есть абстракция, и подписка логики на события интерфейса это механизм как раз слабого, а не сильного связывания. UI генерирует события, а логика реагирует на те, которые ее интересуют, то есть инициатива остается за ней.
00:20
@tym32167 А вот вызов обработчиком события логики это уже конкретика, явно прописанная в самом UI, и подлежащая изменению каждый раз, когда эта логика будет изменена (удаление метода, к примеру). По поводу примера с консолью. Событийная модель может прекрасно работать и в консоли. Весь вопрос в том, что там будет генерировать эти события, а не в том, как их обрабатывать.
@tym32167 Ваш пример в этом плане не лучше - событие вызывает обработчик, он вызывает логику. А как вызывать нужную логику в консоли? Допустим, переделаем обработчик в самостоятельный метод, который будет вызывать остальную логику (так ведь должно быть если сменить UI на консоль?). Опять получается, что все все про всех знают, и опять получается сильная связность. С событиями этого просто не может произойти - нужно, например, удалить обработчик - удаляем вместе с подпиской на событие.
00:41
@tym32167 каким образом реакция на новое событие и его упоминание в логике ломают S и O? Святым духом инфа от кнопок не передается - кто-то где-то должен быть упомянут. Разница в том, что событийная модель это абстрация, а перечисление и вызов всех нужных методов из логики - конкретика. Мы хотим в каком-то классе реагировать на событие - мы подписываемся на него. Понадобилось вообще удалить класс с обработчиком - ничего не сломается. Слабее связности не придумаешь, как по мне.
01:33
@JamesBond всё проще. Вы упоминаете событийную модель, но что это конкретно значит? Что у окна, то есть представления, есть свои события. Всё. Каждый класс, который подписывается на эти события, должен о них знать. А значит, этот класс без окна смысла не имеет, ник просто нужно окно, чтобы работать. Это сильная связность.
Если же мы говорим об абстрактных событиях системы передающимся через общую шину сообщений - вот это событийная модель для слабого связывания, при этом окно со своими событиями не имеет с этой моделью ничего общего. В такой модели все события связаны с системой, условно, там есть событие "создан новый заказ", но нет события "юзер нажал зеленую кнопку".
Как это связано с консолью? Вот мы говорим про калькулятор. Там должен быть класс, что рассчитывает выражение и возаращает результат. Следуюя S и SOLID, этот класс должен заниматься только расчетами, больше ничем. Никаких подписок никуда ему не надо, чтобы вычислить выражение. Потому, если будет консоль, то у консоли будут свои обработчики консольных команд, которые вызовут этот класс для нужныжх расчетов. То есть в случае консоли никаких событий не надо вовсе.
При этом не путайте событие уровня приложения (та самая событийная модель) и события окна - это разные события, они создаются по разному, их назначение разное, у них разные подписчики, всё разное.
"UI генерирует события, а логика реагирует на те, которые ее интересуют, то есть инициатива остается" - логике вообще должно быть всё равно, что там в UI происходит. Еще раз, есть слой выше и ниже в приложении. UI - это верхний слой, логига приложения - это слой ниже. Верхний слой должен вызывать нижний, а не наоборот. Верхний слой должен знать о нижнем, нижний о верхнем знать не должен
это как пирамида, сверзу у вас UI , пол ним у вас какая то логика, под логикой у вас более низкоуровневые вещи типа доступа к БД или вызовов по сети или что еще. Процесс инициированный сверху юзером должен идти вниз, а не наоборот
по поводу связности, да, вы можете разделить слои или части вашего приложения используя общую шину сообщений (это не про события окна!). Такой пример действительно есть и это довольно продвинутые вещи, которые я вам бы не советовал трогать пока не освоитесь с более простыми вещами
для закрепления, если вашей логике нужно окно, чтобы подписаться на его события - у вас проблема связи логики с окном, логика начинает знать кто и как её вызывает, ничем хорошим это не заканчивается. Держитесь простого принципа что слои верхнего уровня вызывают слои нижнего уровня, а не наоборот, и вы уже избежите множества проблем с кодом
"А вот вызов обработчиком события логики это уже конкретика, явно прописанная в самом UI, и подлежащая изменению каждый раз, когда эта логика будет изменена (удаление метода, к примеру)." - нет, не так. Если логика меняется, она меняется внутри методов логики. Единственной причиной лезть в обработчике будет только если вызов какой то логики вообще больше не нужен, что бывает не так часто.
Глядите тот же S из SOLID - если у вас меняется логика приложения - то это означает изменения только классов логики. Если это не так, то у вас нарушен S и ваша логика размазана не только в классах логики, но и где то ещё
 
3 hours later…
05:19
@JamesBond не, неправильная логика. тут не все про всех знают, а ui, который отображает данные знает где эти данные взять. Сам класс данных не знает кто его данные использует, поэтому класс данных может быть использован в любом ui без изменений.
06:14
@tym32167 ну, технически, это мы знаем что в данном случае у нас события UI. Для логики же это не события UI, а "какие-то события", которые точно также могут легко быть воспроизведены в консоли, просто там это будет уже не "событие Click из WimForms", а "событие Click самого приложения". Но в целом уже начинаю сомневаться - если на консольку перейти легко, то вот сменить, например, WinForms на WPF уже нет. Надо обдумать все как следует...
06:36
Вообще, пример того же калькулятора наводит на слудующие соображения. Есть поле для ввода, которое само по себе не создает интересных событий, и кнопка "=", инициирующая передачу выражения в логику. Кнопка может вызвать логику, но не может передать дополнительные данные - отсутствует EventArgs. Значит, нужно создавать свое событие, у которого EventArgs будет, и которое будет вызываться при нажатии на кнопку, а оно само в свою очередь уже будет вызывать логику.
Напрашивается вывод о необходимости некого промежуточного слоя между UI и логикой - или какой-то класс, который их свяжет, или интерфейс...
06:52
По поводу S и смены логики - я на это и делал упор большую часть времени. Если логика меняется (или стала не нужна), то в модели где логика сама подписывается на интересующие события это не вызовет проблем и не потребует изменений больше нигде кроме класса логики (просто отписались от события и всё). UI менять не потребуется. В общем, я запутался, надо еще раз все обдумать)
@Grundy Может быть, может быть... Я уже и не знаю...
 
8 hours later…
14:56
@JamesBond если это другие события - то и реакция на них другая, и процесс подписки другой, и данные что приезжают с событием другие - соответвенно класс который подписывается подлежит ищменениям, что и означает сильную связность. Если у вас было событие "юзер нажал на синюю кнопку", а стало событие "юзер ввел что то в консоль" - то сами обработчики таких событий совершенно другие.
@JamesBond вы патаетесь решить проблемы UI слоя новой абстракцией. Это только усложняет код и не привиодит ни к чему хорошему. В примере калькулятора, есть UI слой со своими обработчиками своих событий и есть логика калькулятора. Калькулятору должно быть все равно, кто его вызывает. UI слой может в своих обработчиках вызвать калькулятор тогда, когда посчитает нужным
@JamesBond вам андо понять, что подписка на UI события и обработка этих событий - это логика UI, это не бизнес логика, это чисто лоника UI слоя. Потому если если надо изменить код обработчтика нажатия зеленой кнопки - это изменение UI слоя, это не изменение бизнес логики. В случае калькулятора - вычисление выражения, - это бизнес логика, а запись результата этого вычисления в поле на форме - это UI логика. Они мало связаны между собой.
Важно ли форме КАК выражение было вычислено? Нет. Важно ли классу-калькулятору куда результат выражения был записан? Тоже нет.
15:58
@tym32167 Возможно, меня все это время сбивало то, что я пытался думать в контексте паттерна MVC (который пока плохо понимаю). Нашел вот такую информацию:
О чем знают модель, представление и контроллер?
1. Модель не знает о существовании представления и контроллера;
2. Представление знает о модели, но не знает о контроллере.
3. Контроллер знает и о модели, и о представлении.
Контроллер не всегда является отдельным классом, часто частью представления на основе GUI в M/VC.
16:36
Что-то каша какая-то получается... У меня тут чат GPT и Gemini с ума сходят уже от моих вопросов - повторяются по кругу и противоречат сами себе)))
 
2 hours later…
18:20
@JamesBond я бы вам посоветовал просто сесть и написать что нибудь простое типа калькулятора, как напишете - можете на этом сайте задать новый вопрос, попросите в нем ревью кода, вам подскажут что и как. Просто пытаться понять теорию сложно без практики.
18:41
@tym32167 спасибо за уделенное время и подробные ответы) Я сейчас понял, в чем еще была моя проблема. Я отталкивался от паттерна MVC, но при этом интуитивно у меня было ощущение, что первой в иерархии структуры приложения должна идти вьюшка. Отсюда возникла ассоциация, что окно - это M в MVC)) Поэтому я подсознательно их отождествлял и все время старался сделать вьюшку независимой. Теперь понятно, в чем была ошибка.
18:54
Ну и еще я сильно переоценил нейросети - в паттернах они плавают еще почище, чем я сам) Так что сейчас нужно найти хорошие, понятные описания MVC, MVP и Document-View (для чего-то мелкого), и разобраться с ними.
По правде еще, львиная доля всей путаницы возникла из-за WinForms и partial-класса Form. Если полностью описывать все кодом, вся программа легчайше делится на любые части и по любому паттерну. Но это долго учить(
@Grundy, спасибо за помощь и подсказки, думаю, можно считать что я разобрался, в чем была моя проблема)
@JamesBond если разобрался можешь написать ответ на свой вопрос
@Grundy, хмммм... Что же написать...))) "ИИ неизбежен в WinForms?" - "нет, не неизбежен"...))
Я бы сейчас ответил примерно так:
Такой риск существует, поэтому стоит выбрать подходящий для сложности проекта паттерн и отталкиваться от него, отделяя логику от представления.
Как-то жиденько больно для ответа...
20:01
@JamesBond просто добавь аргументацию
20:56
@Grundy готово)

« first day  last day (15 days later) »