A questão apresenta um falso dilema. A aplicação adequada do princípio YAGNI não é algo não relacionado. É um aspecto do bom design. Cada um dos princípios do SOLID também são aspectos de bom design. Você nem sempre pode aplicar totalmente todos os princípios em qualquer disciplina. Os problemas do mundo real impõem muitas forças ao seu código, e alguns deles pressionam em direções opostas. Os princípios de design devem ser responsáveis por todos esses aspectos, mas nenhum punhado de princípios pode atender a todas as situações.
Agora, vamos dar uma olhada em cada princípio com o entendimento de que, embora às vezes possam seguir direções diferentes, eles não estão inerentemente em conflito.
O YAGNI foi concebido para ajudar os desenvolvedores a evitar um tipo específico de retrabalho: o que resulta da construção da coisa errada. Isso é feito nos orientando a evitar decisões erradas muito cedo, com base em suposições ou previsões sobre o que pensamos que mudará ou será necessário no futuro. A experiência coletiva nos diz que, quando fazemos isso, geralmente estamos errados. Por exemplo, o YAGNI diria para você não criar uma interface com a finalidade de reutilização , a menos que saiba agora que precisa de vários implementadores. Da mesma forma, o YAGNI diria que não crie um "ScreenManager" para gerenciar o formulário único em um aplicativo, a menos que você saiba agora que terá mais de uma tela.
Ao contrário do que muitas pessoas pensam, o SOLID não se trata de reutilização, genericidade ou mesmo abstração. O SOLID tem como objetivo ajudá-lo a escrever o código preparado para a mudança , sem dizer nada sobre o que pode ser essa alteração específica. Os cinco princípios do SOLID criam uma estratégia para criar código flexível sem ser excessivamente genérico e simples sem ser ingênuo. A aplicação adequada do código SOLID produz classes pequenas e focadas, com papéis e limites bem definidos. O resultado prático é que, para qualquer alteração de requisitos necessária, um número mínimo de classes precisa ser tocado. E da mesma forma, para qualquer alteração de código, há uma quantidade minimizada de "ondulação" para outras classes.
Olhando para a situação de exemplo que você tem, vamos ver o que YAGNI e SOLID podem ter a dizer. Você está considerando uma interface de repositório comum devido ao fato de que todos os repositórios têm a mesma aparência do lado de fora. Mas o valor de uma interface comum e genérica é a capacidade de usar qualquer um dos implementadores sem precisar saber qual é o particular. A menos que haja algum lugar no seu aplicativo em que isso seja necessário ou útil, YAGNI diz que não faça isso.
Existem 5 princípios do SOLID a serem considerados. S é responsabilidade única. Isso não diz nada sobre a interface, mas pode dizer algo sobre suas classes concretas. Pode-se argumentar que o manuseio do acesso a dados em si pode ser uma responsabilidade de uma ou mais outras classes, enquanto a responsabilidade dos repositórios é traduzir de um contexto implícito (CustomerRepository é um repositório implicitamente para entidades do Cliente) em chamadas explícitas para o API de acesso a dados generalizada, especificando o tipo de entidade Cliente.
O é Aberto-Fechado. Isto é principalmente sobre herança. Isso se aplicaria se você estivesse tentando derivar seus repositórios de uma base comum implementando funcionalidades comuns ou se esperava derivar ainda mais dos diferentes repositórios. Mas você não é, então não.
L é substituibilidade de Liskov. Isso se aplica se você pretendeu usar os repositórios através da interface comum do repositório. Ele impõe restrições à interface e implementações para garantir consistência e evitar manuseio especial para diferentes impulsores. A razão para isso é que esse tratamento especial prejudica o objetivo de uma interface. Pode ser útil considerar esse princípio, pois pode alertá-lo para o uso da interface comum do repositório. Isso coincide com a orientação da YAGNI.
Eu sou Segregação de Interface. Isso pode ser aplicado se você começar a adicionar diferentes operações de consulta aos seus repositórios. A segregação de interface se aplica onde você pode dividir os membros de uma classe em dois subconjuntos, onde um será usado por determinados consumidores e o outro por outros, mas nenhum consumidor provavelmente usará os dois subconjuntos. A orientação é criar duas interfaces separadas, em vez de uma comum. No seu caso, é improvável que a busca e o salvamento de instâncias individuais sejam consumidos pelo mesmo código que faria consultas gerais; portanto, pode ser útil separá-las em duas interfaces.
D é injeção de dependência. Aqui voltamos ao mesmo ponto que o S. Se você separou o consumo da API de acesso a dados em um objeto separado, esse princípio diz que, em vez de apenas atualizar uma instância desse objeto, você deve transmiti-lo ao criar um repositório. Isso facilita o controle da vida útil do componente de acesso a dados, abrindo a possibilidade de compartilhar referências a ele entre seus repositórios, sem ter que seguir o caminho de torná-lo um singleton.
É importante observar que a maioria dos princípios do SOLID não se aplica necessariamente nesse estágio específico do desenvolvimento do seu aplicativo. Por exemplo, se você deve interromper o acesso aos dados depende de quão complicado é e se deseja testar a lógica do repositório sem atingir o banco de dados. Parece que isso é improvável (infelizmente, na minha opinião), então provavelmente não é necessário.
Portanto, depois de toda essa consideração, descobrimos que o YAGNI e o SOLID realmente fornecem um conselho comum e relevante imediatamente: provavelmente não é necessário criar uma interface genérica comum de repositório.
Todo esse pensamento cuidadoso é extremamente útil como um exercício de aprendizado. Consome tempo enquanto você aprende, mas com o tempo você desenvolve intuição e se torna muito rápido. Você saberá a coisa certa a fazer, mas não precisará pensar em todas essas palavras, a menos que alguém lhe peça uma explicação.