1. Estático versus instância
Eu acho que existem diretrizes muito claras sobre o que é bom design de OO e o que não é. O problema é que a blogosfera torna difícil separar o bom do ruim e o feio. Você pode encontrar algum tipo de referência que apóie até a pior prática possível.
E a pior prática que consigo pensar é no Estado Global, incluindo as estáticas que você mencionou e a Singleton favorita de todos. Alguns trechos do artigo clássico de Misko Hevery sobre o assunto .
Para realmente entender as dependências, os desenvolvedores devem ler todas as linhas de código. Faz com que a ação assustadora à distância: ao executar conjuntos de testes, o estado global alterado em um teste pode causar a falha inesperada de um teste subsequente ou paralelo. Quebre a dependência estática usando injeção de dependência manual ou Guice.
Ação assustadora à distância é quando executamos uma coisa que acreditamos estar isolada (já que não passamos nenhuma referência), mas interações inesperadas e mudanças de estado acontecem em locais distantes do sistema sobre os quais não falamos ao objeto. Isso só pode acontecer via estado global.
Você pode não ter pensado dessa maneira antes, mas sempre que usa o estado estático, está criando canais de comunicação secretos e não os deixando claros na API. A ação assustadora à distância força os desenvolvedores a ler todas as linhas de código para entender as interações em potencial, reduzir a produtividade do desenvolvedor e confundir os novos membros da equipe.
O que isso se resume é que você não deve fornecer referências estáticas para qualquer coisa que possua algum tipo de estado armazenado. O único lugar em que uso a estática é para constantes enumeradas e tenho dúvidas sobre isso.
2. Métodos com parâmetros de entrada e valores de retorno vs. métodos sem nenhum
O que você precisa entender é que os métodos que não têm parâmetros de entrada e de saída são praticamente garantidos para operar em algum tipo de estado armazenado internamente (caso contrário, o que eles estão fazendo?). Existem idiomas inteiros criados com a idéia de evitar o estado armazenado.
Sempre que você tiver armazenado o estado, você tem a possibilidade de efeitos colaterais, portanto, sempre use-o com atenção. Isso implica que você deve preferir funções com entradas e / ou saídas definidas.
E, de fato, funções que definiram entradas e saídas são muito mais fáceis de testar - você não precisa executar uma função aqui e ir lá para ver o que aconteceu, e não precisa definir uma propriedade em algum lugar mais antes de executar a função em teste.
Você também pode usar com segurança esse tipo de função como estática. No entanto, eu não o faria, porque, se mais tarde eu quisesse usar uma implementação ligeiramente diferente dessa função em algum lugar, em vez de fornecer uma instância diferente com a nova implementação, ficaria preso sem nenhuma maneira de substituir a funcionalidade.
3. Sobreposição vs. Distinto
Eu não entendo a pergunta. Qual seria a vantagem em 2 métodos sobrepostos?
4. Privado x Público
Não exponha nada que não precise expor. No entanto, também não sou muito fã de privado. Não sou desenvolvedor de C #, mas desenvolvedor de ActionScript. Passei muito tempo no código Flex Framework da Adobe, que foi escrito por volta de 2007. E eles fizeram algumas escolhas muito ruins sobre o que tornar privado, o que torna um pesadelo tentar estender suas Classes.
Portanto, a menos que você pense que é um arquiteto melhor do que os desenvolvedores da Adobe em 2007 (da sua pergunta, eu diria que você tem mais alguns anos antes de ter a chance de fazer essa afirmação), provavelmente deseja apenas usar o padrão protegido .
Existem alguns problemas com seus exemplos de código, o que significa que eles não são bem arquitetados, portanto, não é possível escolher A ou B.
Por um lado, você provavelmente deve separar sua criação de objeto do seu uso . Então você normalmente não tem o seu new XMLReader()
direito próximo ao local onde é usado.
Além disso, como o @djna diz, você deve encapsular os métodos usados no XML Reader, para que sua API (exemplo de instância) possa ser simplificada para:
_document Document = reader.read(info);
Não sei como o C # funciona, mas, como já trabalhei com várias tecnologias da Web, desconfio que você nem sempre poderá retornar um documento XML imediatamente (exceto, talvez, como promessa ou tipo futuro). objeto), mas não posso dar conselhos sobre como lidar com uma carga assíncrona em c #.
Observe que, com essa abordagem, você pode criar várias implementações que podem usar um parâmetro que diz onde / o que ler e retornar um objeto XML e trocá-los com base nas necessidades do seu projeto. Por exemplo, você pode estar lendo diretamente de um banco de dados, de uma loja local ou, como no exemplo original, de um URL. Você não pode fazer isso se usar um método estático.