Você não precisa aderir estritamente a esses princípios e não há penalidades religiosas por violá-los. Mas você deve pensar nesses princípios como campainhas de alarme. Se um deles for violado, a campainha de alarme soará.
(1) Todos os dados devem estar ocultos dentro da classe onde estão localizados.
(2) Os usuários de uma classe devem contar com a interface compartilhada da classe, mas uma classe não pode contar com seus usuários.
(3) Minimize as mensagens no protocolo de classe.
(4) Implementar a interface pública mais básica que todas as classes entendem [por exemplo, operações de cópia (cópia profunda e cópia superficial), julgamento de igualdade, conteúdo de saída correto, análise da descrição ASCII, etc.].
(5) Não coloque detalhes de implementação (como funções privadas que colocam código compartilhado) na interface pública da classe. Se dois métodos de uma classe tiverem um código comum, você poderá criar uma função privada que impeça esse código comum.
(6) Não perturbe a interface pública da classe com coisas que os usuários não possam usar ou nas quais não estejam interessados.
(7) Deve haver zero acoplamento entre classes, ou apenas relacionamentos de acoplamento derivados. Ou seja, uma classe não tem nada a ver com outra classe ou apenas utiliza operações na interface pública de outra classe.
(8) Uma classe deve representar apenas uma abstração chave. Todas as classes do pacote deverão ser fechadas conjuntamente para alterações no mesmo tipo de propriedades. Se uma mudança afetar um pacote, afetará todas as classes do pacote, mas não terá nenhum impacto em outros pacotes.
(9) Centralize os dados e comportamentos relacionados. Os designers devem estar cientes dos objetos que obtêm dados de outros objetos por meio de operações como get. Este tipo de comportamento implica que este princípio empírico seja violado.
(10) Colocar informações irrelevantes em outra categoria (ou seja, o comportamento de não se comunicarem). Faça dependências para estabilidade.
(11) Certifique-se de que os conceitos abstratos que você modela sejam classes, não apenas as funções desempenhadas pelos objetos.
(12) Distribuir as funções do sistema da forma mais uniforme possível na direção horizontal, ou seja: de acordo com o projeto, as classes de nível superior devem compartilhar o trabalho de maneira uniforme.
(13) Não crie classes/objetos onipotentes em seu sistema. Tenha especial cuidado com classes cujos nomes incluem Driver, Manager, System e Susystem. Planeje uma interface em vez de implementá-la.
(14) Tenha cuidado com classes que definem um grande número de métodos de acesso na interface pública. O grande número de métodos de acesso significa que os dados e comportamentos relevantes não são armazenados centralmente.
(15) Tenha cuidado com classes que contêm muitos comportamentos que não se comunicam entre si. Outra manifestação desse problema é a criação de muitas funções get e set na interface pública das classes da sua aplicação.
(16) Numa aplicação que consiste num modelo orientado a objectos que interage com a interface do utilizador, o modelo não deve depender da interface, mas a interface deve depender do modelo.
(17) Modelo de acordo com o mundo real, tanto quanto possível (muitas vezes violamos este princípio para cumprir o princípio da distribuição de funções do sistema, evitar o princípio de classe para todos os fins e colocar centralmente dados e comportamentos relevantes).
(18) Remova classes desnecessárias do seu design. Geralmente, rebaixaríamos essa classe para uma propriedade.
(19) Remova classes fora do sistema. A característica das classes fora do sistema é que, em termos abstratos, elas apenas enviam mensagens para o domínio do sistema, mas não aceitam mensagens de outras classes do domínio do sistema.
(20) Não transforme operações em classes. Questione qualquer classe cujo nome seja um verbo ou derivado de um verbo, especialmente uma classe com apenas uma ação significativa. Considere se esse comportamento significativo deve ser movido para uma classe que já existe ou que ainda não foi descoberta.
(21) Frequentemente introduzimos classes proxy ao criar modelos de análise de aplicações. Durante a fase de design, muitas vezes descobrimos que muitos agentes são inúteis e devem ser removidos.
(22) Minimizar o número de colaboradores de uma turma. O número de outras classes usadas por uma classe deve ser reduzido ao mínimo.
(23) Minimizar o número de mensagens passadas entre turmas e colaboradores.
(24) Minimizar a quantidade de colaboração entre turmas e colaboradores, ou seja: reduzir o número de mensagens diferentes passadas entre turmas e colaboradores.
(25) Minimizar o fan-out da classe, ou seja, reduzir o produto da quantidade de mensagens definidas pela classe pela quantidade de mensagens enviadas.
(26) Se uma classe contém um objeto de outra classe, a classe que a contém deve enviar uma mensagem ao objeto contido. Ou seja: uma relação de inclusão implica sempre uma relação de uso.
(27) A maioria dos métodos definidos em uma classe deve usar a maioria dos membros de dados na maior parte do tempo.
(28) O número de objetos contidos numa classe não deve exceder a capacidade da memória de curto prazo do desenvolvedor. Esse número geralmente é 6. Quando uma classe contém mais de seis membros de dados, você pode dividir os membros de dados logicamente relacionados em um grupo e, em seguida, usar uma nova classe contendora para conter esse grupo de membros.
(29) Deixe as funções do sistema serem distribuídas verticalmente em um sistema de herança estreito e profundo.
(30) Ao implementar restrições semânticas, é melhor implementá-las de acordo com as definições de classe. Isto muitas vezes leva ao estouro da classe, caso em que as restrições devem ser implementadas no comportamento da classe, geralmente, mas não necessariamente, no construtor.
(31) Ao implementar restrições semânticas no construtor de uma classe, coloque o teste de restrição no nível de inclusão mais profundo permitido pelo domínio do construtor.
(32) Se as informações semânticas nas quais as restrições dependem mudam com frequência, é melhor colocá-las em um objeto centralizado de terceiros.
(33) Se a informação semântica na qual as restrições dependem raramente muda, ela é melhor distribuída entre as classes envolvidas nas restrições.
(34) Uma classe deve saber o que contém, mas não pode saber quem a contém.
(35) Objetos que compartilham escopo literal (ou seja, estão contidos na mesma classe) não devem ter relacionamento de uso entre si.
(36)A herança só deve ser utilizada para modelar hierarquias de especialização.
(37) As classes derivadas devem saber sobre as classes base, e as classes base não devem saber nenhuma informação sobre suas classes derivadas.
(38) Todos os dados da classe base devem ser privados, não utilize dados protegidos. Os designers de classe nunca devem colocar coisas em uma interface pública que não sejam necessárias aos usuários da classe.
(39) Em teoria, a hierarquia de herança deveria ser mais profunda, quanto mais profunda melhor.
(40) Na prática, a profundidade da hierarquia de herança não deve exceder a capacidade de memória de curto prazo de uma pessoa média. Um valor de profundidade amplamente aceito é 6.
(41) Todas as classes abstratas devem ser classes base.
(42) Todas as classes base devem ser classes abstratas.
(43) Colocar dados, comportamento e/ou interfaces em comum o mais alto possível na hierarquia de herança.
(44) Se duas ou mais classes partilham dados comuns (mas nenhum comportamento comum), então os dados comuns devem ser colocados numa classe que esteja incluída em cada classe que partilha estes dados.
(45) Se duas ou mais classes tiverem dados e comportamentos comuns (ou seja, métodos), então cada uma dessas classes deverá herdar de uma classe base comum que represente esses dados e métodos.
(46) Se duas ou mais classes compartilham uma interface comum (referindo-se a mensagens, não a métodos), então elas devem herdar de uma classe base comum apenas se precisarem ser usadas polimorficamente.
(47) A análise caso a caso da exibição dos tipos de objetos é geralmente errada. Na maioria desses casos, os projetistas devem usar polimorfismo.
(48) A análise caso a caso da exibição dos valores dos atributos costuma estar errada. As classes devem ser dissociadas em uma hierarquia de herança, com cada valor de atributo transformado em uma classe derivada.
(49) Não modele a semântica dinâmica de uma classe através de relacionamentos de herança. A tentativa de modelar a semântica dinâmica com relações semânticas estáticas resulta na troca de tipos em tempo de execução.
(50) Não transforme objetos de classe em classes derivadas. Tenha cuidado com qualquer classe derivada que possua apenas uma instância.
(51) Se você acha que precisa criar uma nova classe em tempo de execução, dê um passo atrás e perceba que você está criando objetos. Agora, generalize esses objetos em uma classe.
(52) Deveria ser ilegal usar um método vazio (ou seja, um método que não faz nada) em uma classe derivada para substituir um método na classe base.
(53) Não confunda inclusão opcional com necessidade de herança. Modelar a inclusão opcional como herança leva a uma proliferação de classes.
(54) Ao criar hierarquias de herança, tente criar estruturas reutilizáveis em vez de componentes reutilizáveis.
(55) Se você usar herança múltipla em seu projeto, presuma que cometeu um erro. Se você não cometeu um erro, você precisa tentar provar.
(56) Sempre que a herança for usada no projeto orientado a objetos, pergunte-se duas questões: (1) A classe derivada é um tipo especial daquilo que ela herda? (2) A classe base faz parte da classe derivada?
(57) Se você encontrar herança múltipla em um design orientado a objetos, certifique-se de que nenhuma classe base seja na verdade uma classe derivada de outra classe base.
(58) No design orientado a objetos, se você precisar escolher entre inclusão e associação, escolha inclusão.
(59) Não utilize dados globais ou funções globais para escrituração de objetos de uma classe. Variáveis de classe ou métodos de classe devem ser usados.
(60) Os projetistas orientados a objetos não devem permitir que os princípios de projeto físico prejudiquem seus projetos lógicos. Entretanto, frequentemente usamos critérios de projeto físico na tomada de decisões sobre projeto lógico.
(61) Não ignore a interface pública para modificar o estado do objeto.