Por que as funções puras não devem ser sempre estáticas e públicas? [duplicado]

5

Quais são as razões, técnicas ou outras, de que as funções puras (funções que não dependem de estado externo e não têm efeitos colaterais) devem não ser sempre públicas e estático?

Quando uma função estática e pura é muito geral, como Math.floor() ou algo assim, faz todo o sentido tê-la pública e estática. Por que não deveríamos ter acesso global a funções matemáticas básicas? Mas quando você faz o mesmo com funções específicas para o domínio do aplicativo, específicas até mesmo para a classe em que são implementadas, então começo a sentir que estou fazendo algo errado.

Por exemplo, digamos que temos uma classe User e um atributo super específico chamado happiness , que pode ser alterado pela ingestão de alimentos. Em geral, eu teria uma função pública atuando como uma interface, obtendo as informações externas e, em seguida, chamando uma função auxiliar protegida que é puramente implementada, transmitindo quaisquer dados com estado como argumentos. A implementação pode ser assim:

class User {
    private FoodPreference foodPreference; 
    private float age; 
    // ... 
    // constructors initializing the users food preferences and
    // changing the Users preferences as they get older
    // ...

    // Impure interface relying on users state to get their preferences
    public void EatFood(Food food) {
        this.happiness = this.ComputeHappiness(this.foodPreference, food); 
    }

    // Pure, does not rely on Users state to compute this info, it's passed in as an argument.  
    protected Happiness ComputeHappiness(FoodPreference preference, Food food) {
      Happiness newHappiness = /* some user-specific logic computing their happiness due to eating food */
      return newHappiness; 
    }

}

Se ComputeHappiness() fosse público e estático , isso seria ruim? Minha reação instintiva é "Sim, seria", acho que porque parece que o uso da palavra-chave estática em OOP é algo geralmente evitado, já que é tão fácil atirar no próprio pé.

Eu vejo muitos benefícios em ter funções puras sendo estáticas e públicas, mesmo que não sejam muito genéricas:

  • Funções puras são mais fáceis de testar. Funções estáticas são fáceis de acessar. Seus testes de unidade precisarão fazer menos configurações para produzir os meios para testar a função. Agora você só precisa dos dados, o que geralmente não é a parte mais difícil das funções de teste.
  • Suas funções públicas podem ser interfaces que acessam os dados com estado (do objeto, banco de dados ou qualquer outra origem) e deixam a lógica de negócios para suas funções auxiliares puramente implementadas.
  • As funções puras podem ser reutilizadas com muito mais facilidade. Talvez outras partes do aplicativo gostariam de ComputeHappiness ()!

Quais são as razões pelas quais esta é uma ideia terrível? Certamente parece violar o princípio do menor espanto.

    
por PandemoniumSyndicate 19.09.2015 / 08:27
fonte

4 respostas

5

É uma questão de esconder informações e abstração de dados. Se você fizer suas operações (mesmo se elas forem puras e referencialmente transparentes) separadas do objeto, então o objeto deve tornar sua representação pública para as operações. Uma vez que ocultar a representação é uma característica importante (ou, de acordo com algumas definições, mesmo a somente ) da POO, o objeto deixa de ser um objeto e se torna basicamente uma estrutura.

Considerando que, com métodos que pertencem ao objeto, o método tem acesso privilegiado à representação do objeto e pode, assim, fazer uso da representação em seu cálculo, sem que o objeto vaze seus internos para outras partes do sistema. / p>

Veja Sobre a compreensão da abstração de dados, revisitada por < a href="http://WCook.BlogSpot.Com/"> William R. Cook para a distinção entre abstração de dados com tipos de dados abstratos e abstração de dados orientada a objetos. O artigo também contém um exemplo de abstração de dados orientada a objeto em Java que usa apenas métodos puros e referencialmente transparentes. De fato, um ponto importante que o autor faz nesse artigo é que a OO e a mutabilidade são ortogonais.

    
por 19.09.2015 / 10:08
fonte
2

Todas as funções públicas fazem parte da interface do componente. Interfaces são restritas em suas mudanças, elas precisam ser retrocompatíveis a maior parte do tempo, e quando não estão, seus clientes devem se adaptar às mudanças. Interfaces, portanto, tendem a ser tão estreitas quanto possível. O vazamento de detalhes de implementação na interface destrói a modularidade e introduz um custo de manutenção adicional.

    
por 19.09.2015 / 13:34
fonte
1

What are the reasons, technical or otherwise, that pure functions (functions which do not rely on external state and have no side effects) should not always be public and static?

Funções puras podem ser públicas e estáticas, portanto, se for adequado às suas necessidades, você pode tornar todas as suas funções puras públicas e estáticas. Ninguém disse que eles não deveriam ser públicos e estáticos. Mas quando você menciona " sempre seja público e estático" você parece estar se perguntando por que não existe uma regra que force a todos a tornar públicas e estáticas todas as suas funções puras. Bem, há muitas razões para isso, mas duvido que isso seja o que você queria perguntar. Então, você pode querer reformular sua pergunta um pouco, porque, do jeito que está, não faz muito sentido.

Why shouldn't we have global access to basic math functions?

Várias linguagens permitem que você tenha acesso global a funções estáticas públicas. Por exemplo, em java, você pode

import static Math.floor;

e, em seguida, você pode usar floor( x ) em vez de Math.floor( x ) . Se você está procurando uma maneira de usar floor( x ) sem ter que importá-lo estatisticamente, isso seria uma péssima idéia porque isso significaria que um módulo poderia reservar o nome da função global floor( double x ) e nenhum outro módulo poderia declarar a mesma função global.

What are the reasons this is a terrible idea?

Receio que você não tenha explicado, de uma maneira clara e concisa, precisamente de que ideia terrível você está falando. Talvez, se você reformular sua resposta, possamos fornecer algumas informações melhores.

    
por 19.09.2015 / 11:08
fonte
0

Você parece estar sofrendo de alguma confusão sobre como funções puras ou OOP funcionam.

Uma função pura é aquela que não depende de nada para produzir seu resultado, exceto os valores passados para ela. Um método (normal, não estático) no OOP leva o objeto ao qual está associado como um argumento implícito. Portanto, é completamente possível ter um método de objeto como uma função pura. Use-os quando fizerem sentido e use métodos estáticos quando eles fizerem sentido, e você deve estar bem.

    
por 19.09.2015 / 10:46
fonte