Como sabemos, o SRP declara que toda classe deve ter responsabilidade única e essa responsabilidade deve ser totalmente encapsulada pela classe.
Mas setters e getters cumprem outra responsabilidade - eles fazem acesso à propriedade de classe abstrata (dados).
se Setters e getters fazem acesso à propriedade de classe abstrata, eles servem outra responsabilidade .
Então, se eu tenho algo assim,
class Config
{
private location;
public function write(array $data)
{
....
}
public function read($key)
{
...
}
public function exists($key)
{
...
}
public function delete($key)
{
...
}
// Below comes property abstraction
// Here I doubt - I CANNOT USE this class without them
// but they seem to break the SRP at the same time!?
public function setFileLocation($location)
{
$this->location = $location;
}
public function getFileLocation()
{
return $this->location;
}
public function setConfigArray(...)
{
...
}
public function getConfigArray()
{
...
}
}
Eu quebro o SRP. O problema é que essa é a única maneira de existir a classe.
Então a questão é:
Na minha situação, é quase impossível evitar métodos setFileLocation()
e getFileLocation()
métodos CRUD.
Portanto, se combinando métodos CRUD com abstração de acesso a dados eu quebro o SRP,
Existe alguma maneira de aderir ao SRP e manter o conceito comum da classe Config (operações CRUD) ao mesmo tempo?
Respostas:
Honestamente, acho que você está levando o conceito de responsabilidade única um pouco longe demais. Os getters e setters são incidentais ao funcionamento da classe, seja por acesso direto a membros públicos ou por métodos (ou propriedades) para fazê-lo.
Você está argumentando que conseguir e definir algum membro da classe é uma responsabilidade separada e, portanto, deve ser movido para outro lugar. Digamos que fazemos isso, e agora você tem as classes chamadas
Config
eConfigAccessor
. Neste ponto, agora você tem um espaço de ar entre as duas classes, porqueConfig
não possui interface para acessar seulocation
membro. Isso torna impossível escreverConfigAccessor
, e você fica com uma classe imutável de escrever uma vez que não tem qualquer utilidade. Se você adicionar algum tipo de interface para permitirConfigAccessor
que ele faça seu trabalho, você se encontrará com um problema recursivo.O SRP, como muitas outras coisas neste campo, é um princípio, não uma regra rígida. Isso significa que você deve aplicar julgamento à sua situação em vez de tentar segui-la incondicionalmente. Há uma linha entre ser um purista e fazer o trabalho, e quando o primeiro está impedindo o segundo, você está do lado errado.
Se posso criticar um pouco seu design: se sua
Config
classe foi projetada para ser uma interface entre um arquivo de configuração armazenado em disco e seu código, a última coisa que você deseja fazer é mudar sua localização no meio do caminho. Se você estiver alterando alocation
forma de iniciar o acesso a um arquivo diferente, destrua o objeto antigo e crie um novo. Você não deixou claro se pretende armazenar o conteúdo do arquivo no objeto. Se você planejou usá-lo como uma maneira de inalar o conteúdo de um arquivo de configuração e gravá-lo em outro, considere usar um método que clone os dados em um novo objeto que aponte para o novo arquivo.fonte
Existem dois níveis distintos nos quais você pode aplicar o SRP.
O primeiro nível é o nível de funções / métodos individuais. Cada um deve executar apenas uma tarefa (e, a julgar pelos nomes dos métodos, nenhum dos métodos de
Config
quebrar o SRP).O segundo nível é o nível de uma classe. Aqui, o conceito de uma única responsabilidade se torna um pouco mais abstrato, mas um bom indicador é se você pode declarar as responsabilidades de uma classe em uma frase sem o uso (implícito) da palavra e . Se você puder fazer isso com a presença de getters e setters, a classe não interromperá o SRP.
Em geral, getters e, em menor grau, setters são , no entanto, uma indicação de que o encapsulamento de uma classe está quebrado. No caso da
Config
classe, osetFileLocation
método é bom, poisConfig
precisa de alguma maneira de saber onde os dados estão localizados, mas os outros parecem suspeitos, porque expõem informações das quais os usuáriosConfig
não precisam.fonte
Sua classe de configuração tem a responsabilidade de rastrear a configuração, que é implementada mantendo referências particulares a determinados dados e fornecendo acesso a eles por meio de métodos mutadores. Isso não quebra o SRP, porque a própria classe ainda tem uma única responsabilidade ; os mutadores simplesmente ajudam a cumprir essa responsabilidade abstraindo o acesso aos dados. Os mutadores não têm uma responsabilidade separada da da classe; eles fazem parte da maior responsabilidade da classe.
fonte