Neste tumblr reflito sobre os ensinamentos do livro Java Efetivo levando em conta também a minha experiência. Um verdadeiro devaneio meu, quase uma conversa comigo mesmo. Fique a vontade para viajar comigo, mas isso não descarta a leitura do livro no meu ponto de vista! =)
Don't wanna be here? Send us removal request.
Text
Item 1 - Static Factory vs Construtor
Considere os métodos static factory em vez de construtores
Logo de cara o livro já trás um conceito bem interessante que é o de preferir métodos estáticos para para retornar uma instância do próprio objeto ao invés dos construtores.
A verdade que eu sempre gostei de fazer isso mas apenas quando construía uma cadeia de comandos, como um builder, nestes casos eu deixava o construtor privado e um método estático público que devolvia a instância deste objeto. Utilizo desta forma principalmente por uma questão de estética no momento de utilizar o método, pois assim posso definir qual é o primeiro método que deve ser chamado, por exemplo, uma vez eu criei uma cadeia de comandos que no final fazia um update no mongo de forma fácil e queria que o primeiro comando utilizado fosse o que passava a collection:
MongoUpdate.collection(User.class) .set("password", userRequest.getNewPasswordRequested()) .where("email", userRequest.getEmail()) .updateFirst();
Poderia deixar que a collection ficasse no construtor? Sim! Mas não seria tão legível para quem estivesse lendo o que seria aquele parâmetro. Claro que além do primeiro método tenho estratégias diferentes para definir a ordem dos demais métodos, como que venha primeiro o set antes do where, mas isso é outro assunto, porém me inspirei nestes designs de classes com o Spring Security quando definimos as permissões de acesso de URIs (fica a dica, li muito código do Spring).
Voltando a motivação do artigo, é claro que tudo deve ser usado com parcimônia e o autor do livro cita vantagens e desvantagens.
Vantagem 1: Diferente dos construtores os static factory tem nomes!
Genial, realmente é algo muito simples de se ver, quando temos aquelas classes com mais de um construtor, qual é a diferença entre um construtor e outro? O que eu faço é entrar no código e ler cada construtor, o que é exatamente o que não necessitaríamos fazer quando o código é compreensível. O pior é que 90% das vezes o construtor 2 chama o construtor 1 passando os valores que ele não recebe como nulos. Agora se os construtores são na verdade métodos com nomes, sabemos o que ele faz sem precisar olhar o código!
Outro caso é aquele momento em que precisamos de dois construtores com os mesmos parâmetros, não dá! Mas com métodos static factorys sim!
Um bom exemplo de classes que utilizam métodos static factory são a família java.math como BigInteger, BigDecial e etc, podem reparar sempre criamos um objeto destes tipos com algo como: BitDecimal.valueOf(...).
Vantagem 2: Podemos utilizar sempre a mesma instância
Este é o princípio do singleton, pois com métodos static factory não necessitamos necessariamente sempre criar um novo objeto, podemos sempre retornar uma mesma instância estática! Isso dependente claro do tipo de objeto que você está construindo, mas quase sempre se encaixa isso.
Vantagem 3: Podemos retornar subtipos
Ora, se utilizamos um construtor de uma classe vamos sempre obter a instância daquela classe, mas poder retornar uma instância de um subtipo é bem interessante. Podemos ter um método static factory cujo o retorno seja uma interface e que retorna um subtipo desta privado. Desta forma não é necessário deixar claro para o programador que vai utilizar sua API que existem diversas classes para ele se preocupar no que faz cada uma. Assim você reduz drasticamente a complexidade da sua API para quem vai utilizar-la pelo motivo citado antes.
Neste caso poderíamos ter sua interface Carro e uma classe (ou a própria interface a partir do Java 8) que possui os seguintes métodos static factory:
public static Carro getCarroAntigo(){...} public static Carro getCarroModerno(){...} public static Carro getCarroEsportivo(){...}
E cada método retornar respectivamente suas classes privadas que implementam carro: Fusca, Fusion e Ferrari. O programador nem precisa saber quais são os carros e ter que se preocupar em saber como manipular cada um.
Vantagem 4: Um mesmo método static factory pode retornar pode retornar instâncias diferentes de acordo com os parâmetros
Essa vantagem 4 é quase uma continuação da 3, mas vamos lá, aqui ao invés de termos diversos métodos podemos ter apenas um e dado o parâmetro retornamos a classe adequada. O livro da um exemplo fantástico, isso por que eu (e você com certeza) se beneficio muito disso e nem sabia. A classe EnumSet não possui construtor públicos, apenas static factory onde dependendo do tamanho do Enum ela retorna uma classe mais adequada, ou seja, se for pequeno uma classe que manipula melhor Enums pequenos e se for grande uma outra para isso! E essa é a mágica, nós não queremos saber disso ou ter estes dois tipos a disposição para que nós escolhermos qual utilizar, não!
Tanto nesta vantagem quanto na anterior ainda temos a TOTAL liberdade de trocar essas classes filhas, então podemos trocar a classe Ferrari pela classe Porsche e nenhum código cliente quebrará por conta disso, realmente incrível o conceito!
Desvantagem 1: Classes com construtores privados não podem ser dividas
Essa é uma desvantagem que está mais para uma vantagem como confessa o autor. Se você estava me acompanhando até aqui e já imaginando como fazer algumas coisas deve ter passado pela sua cabeça em algum momento de utilizar-se de composição. E é justamente esse o mal que vem para o bem, se você faz o design de sua classe com métodos static factory, você se obriga a utilizar composição.
Desvantagem 2: É difícil para um programador encontrar os static factory
Esse é um ponto que discordo. O que o autor quiz dizer com isso é que uma classe cheio de métodos, como você vai saber quais são os static factory? Afinal não existe alguma marcação do javadoc para destacar que estes métodos são os nossos construtores.
De fato, isso pode ser um problema, mas pera lá, você está desenvolvendo no Gedit (ou bloco de notas para quem é o do Windows)? Se você pega uma classe sem construtor a IDE não vai deixar você dar um new e ao tentar procurar os métodos estáticos, quando der um ponto a IDE vai te listar apenas estes.
Talvez o autor se refira a classes que se utilizam de construtores públicos e static factory, neste caso sim, pode ser que você não utilize um static factory pois não sabe da existência dele e utilize o construtor, logo recomendo não utilizar-se desta combinação. :)
Para reduzir esta última desvantagem e até como dica, o autor lista nomes de métodos comuns de se utilizar para static factory, assim você sabe o que procurar nestas classes:
from: Método de conversão, exemplo Date.from(instant);
of: Método de agregação, exemplo EnumSet.of(FUSCA, FUSION, FERRARI);
valueOf: Alternativa para from e of, exemplo Integer.valueOf("23");
instance ou getInstance: retorna uma instância;
create ou newInstance: similar ao getInstance mas com a certeza que você sempre terá uma nova instância;
getType ou newType: similar ao getInstance mas o retorno é uma classe diferente, onde type substituímos pelo tipo, exemplo Files.getFileStore(path);
type: uma alternativa a getType e newType, exemplo Collections.list(...);
Não existe uma convenção para estes nomes, e as vezes vai de acordo com o seu contexto como o meu próprio exemplo que dei no inicio, mas esses são os padrões vistos por aí que o autor felizmente elencou.
A dica final do autor é que antes de criar um construtor avalie os métodos static factory primeiro!
Fontes
Effective Java 3rd Edtion
0 notes
Conversation
O livro Java Efetivo
Um professor de um curso avançado de Java que eu fiz disse um dia algo do tipo: "Se você não tem todo o conhecimento do livro Java Efetivo, você não programa Java de verdade".
Claro que fiquei curioso para saber o que este livro ensinava! Então estou aqui lendo e devaneando sobre isso aqui no Tumblr. Fique a vontade para me seguir nesta aventura.
Abraços!
1 note
·
View note