Em geral, eu não concordo que as estruturas da GUI violem SOLID . Pode haver exceções, mas isso encerra minha experiência com vários frameworks:
-
SRP: uma classe de GUI geralmente tem uma responsabilidade. Talvez esteja respondendo a um evento, renderizando um objeto ou talvez "represente esse elemento da interface do usuário". Esse último pode parecer que não é uma responsabilidade "única", porque essa responsabilidade é unir tudo (por exemplo,
JButton
ouJPanel
). A chave para procurar é esse objeto "grande", muitas vezes delegar a outros objetos que são especializados e lidar com um aspecto do objeto em detalhe (manipulação de eventos, renderização, etc). -
Aberto / fechado: seu exemplo mostra como as classes de interface do usuário estão definitivamente abertas para extensão: há muita herança acontecendo. Pode-se argumentar que as classes de interface do usuário violam o aspecto "fechado para modificação", uma vez que são tipicamente muito configuráveis e podem ser modificadas para fazer muitas coisas de maneira diferente, mas é um objetivo dessas classes.
-
Substituição Liskov: em praticamente todas as estruturas que vi, as subclasses adicionam mais funcionalidade e ainda permitem o comportamento da classe pai. Nem sempre faz sentido, mas é suportado. Por exemplo, você poderia aninhar elementos da interface do usuário dentro de um botão se estendesse um quadro (talvez um ícone pudesse ser adicionado a um botão, um elemento de imagem aninhado dentro de um botão apesar do "botão" não ser considerado como um elemento pai ). Esse princípio é fundamental para a natureza aninhada de estruturas de interface do usuário.
-
Segregação de interface: minha principal experiência aqui é com Java, onde existem muitas pequenas interfaces para vários ouvintes e manipuladores. Parece um bom ajuste.
-
Inversão de dependência: junto com o argumento de Liskov, muitos frameworks dependem de abstrações. Por exemplo, pode haver alguma interface de alto nível ou classe abstrata para representar todos os componentes da interface do usuário. Os componentes pai podem aceitar qualquer componente de alto nível como filho, o que permite layouts arbitrariamente complexos por meio de aninhamento.
No geral, acho que há um argumento strong para estruturas de GUI que aderem ao SOLID.