Resumo executivo (TM)
Você recebe algumas coisas.
- Herança prototípica e clonagem
- Adição dinâmica de novas propriedades
- Coexistência de objetos de diferentes versões (níveis de especificação) da mesma classe.
- Objetos pertencentes às versões mais recentes (níveis de especificação) terão propriedades "opcionais" extras.
- Introspecção de propriedades, antigas e novas
- Introspecção de regras de validação (discutidas abaixo)
Há uma desvantagem fatal.
- O compilador não verifica se há strings incorretas.
- As ferramentas de refatoração automática não renomearão os nomes das chaves de propriedade para você - a menos que você pague pelos nomes sofisticados.
O problema é que você pode obter introspecção usando, hum, introspecção. Isto é o que geralmente acontece:
- Ativar reflexão.
- Adicione uma grande biblioteca de introspecção ao seu projeto.
- Marque vários métodos e propriedades de objetos com atributos ou anotações.
- Deixe a biblioteca de introspecção fazer a mágica.
Em outras palavras, se você nunca precisar interagir com o FP, não precisará seguir o conselho de Rich Hickey.
Por último, mas não menos importante (nem o mais bonito), embora usar String
como chave de propriedade faça o sentido mais direto, você não precisa usar String
s. Muitos sistemas legados, incluindo o Android ™, usam IDs inteiros extensivamente em toda a estrutura para se referir a classes, propriedades, recursos etc.
Android é uma marca comercial da Google Inc.
Você também pode fazer os dois mundos felizes.
Para o mundo Java, implemente os getters e setters como de costume.
Para o mundo do FP, implemente o
Object getPropertyByName(String name)
void setPropertyByName(String name, Object value) throws IllegalPropertyChangeException
List<String> getPropertyNames()
Class<?> getPropertyValueClass(String name)
Dentro dessas funções, sim, código feio, mas existem plugins IDE que o preencherão, usando ... uh, um plug-in inteligente que lê seu código.
O lado Java das coisas terá o mesmo desempenho de sempre. Eles nunca usarão essa parte feia do código. Você pode até querer escondê-lo do Javadoc.
O lado FP do mundo pode escrever o código "leet" que eles querem, e geralmente não gritam com você sobre o código ser lento.
Em geral, o uso de um mapa (bolsa de propriedades) no lugar do objeto é comum no desenvolvimento de software. Não é exclusivo da programação funcional ou de qualquer tipo específico de linguagem. Pode não ser uma abordagem idiomática para qualquer idioma, mas há situações que exigem isso.
Em particular, serialização / desserialização geralmente requer uma técnica semelhante.
Apenas algumas idéias gerais sobre "mapa como objeto".
- Você ainda precisa fornecer uma função para validar um "mapa como objeto". A diferença é que "mapear como objeto" permite critérios de validação mais flexíveis (menos restritivos).
- Você pode adicionar facilmente campos adicionais ao "mapa como objeto".
- Para fornecer uma especificação do requisito mínimo de um objeto válido, você precisará:
- Listar o conjunto de chaves "minimamente necessário" esperado no mapa
- Para cada chave cujo valor precisa ser validado, forneça uma função de validação de valor
- Se houver regras de validação que precisem verificar vários valores de chave, forneça isso também.
- Qual o benefício? Fornecer a especificação dessa maneira é introspectivo: você pode escrever um programa para consultar o conjunto de chaves minimamente necessário e obter a função de validação para cada chave.
- No POO, tudo isso é acumulado em uma caixa preta, em nome de "encapsulamento". No lugar da lógica de validação legível por máquina, o chamador só pode ler a "documentação API" legível por humanos (se felizmente existir).