Eu não acho que haja uma resposta independente de idioma para isso, já que o que constitui uma "propriedade" é uma pergunta específica do idioma, e o que um chamador de uma "propriedade" espera também é uma pergunta específica do idioma. Eu acho que a maneira mais proveitosa de pensar sobre isso é pensar no que parece do ponto de vista do chamador.
Em C #, as propriedades são distintas por serem capitalizadas (convencionalmente) (como métodos), mas não possuem parênteses (como variáveis de instância pública). Se você vir o código a seguir, documentação ausente, o que você espera?
var reciprocalHeading = myHeading.Reciprocal;
Como um novato em C # relativo, mas que leu as Diretrizes de uso de propriedades da Microsoft , eu esperaria Reciprocal
, entre outras coisas:
- ser um membro de dados lógicos da
Heading
classe
- ser barato para ligar, de modo que não seja necessário armazenar em cache o valor
- falta efeitos colaterais observáveis
- produz o mesmo resultado se chamado duas vezes consecutivas
- (talvez) ofereça um
ReciprocalChanged
evento
Dessas suposições, (3) e (4) provavelmente estão corretas (supondo que Heading
seja um tipo de valor imutável, como na resposta de Ewan ), (1) é discutível, (2) é desconhecido, mas também discutível e (5) é improvável que faça sentido semântico (embora o que quer que tenha um cabeçalho talvez deva ter um HeadingChanged
evento). Isso me sugere que em uma API C #, "obter ou calcular o recíproco" não deve ser implementado como uma propriedade, mas principalmente se o cálculo for barato e Heading
imutável, é um caso limítrofe.
(Observe, porém, que nenhuma dessas preocupações tem nada a ver com a possibilidade de chamar a propriedade criar uma nova instância , nem mesmo (2). Criar objetos no CLR, por si só, é bastante barato.)
Em Java, as propriedades são uma convenção de nomenclatura de método. Se eu ver
Heading reciprocalHeading = myHeading.getReciprocal();
minhas expectativas são semelhantes às acima (se menos explícitas): espero que a ligação seja barata, idempotente e sem efeitos colaterais. No entanto, fora da estrutura do JavaBeans, o conceito de "propriedade" não é tão significativo em Java, e particularmente ao considerar uma propriedade imutável sem correspondência setReciprocal()
, a getXXX()
convenção agora é um tanto antiquada. Do Effective Java , segunda edição (já com mais de oito anos):
Os métodos que retornam uma não- boolean
função ou atributo do objeto no qual são chamados geralmente são nomeados com um substantivo, frase substantiva ou uma frase verbal que começa com o verbo get
…. Existe um contingente vocal que afirma que apenas a terceira forma (começando com get
) é aceitável, mas há pouca base para essa afirmação. As duas primeiras formas geralmente levam a um código mais legível ... (p. 239)
Em uma API contemporânea e mais fluente, então, eu esperaria ver
Heading reciprocalHeading = myHeading.reciprocal();
- o que sugere novamente que a chamada é barata, idempotente e sem efeitos colaterais, mas não diz nada sobre a realização de um novo cálculo ou a criação de um novo objeto. Isto é bom; em uma boa API, eu não deveria me importar.
Em Ruby, não existe uma propriedade. Existem "atributos", mas se eu vir
reciprocalHeading = my_heading.reciprocal
Não tenho como saber imediatamente se estou acessando uma variável de instância @reciprocal
por meio de um attr_reader
método ou simples de acessador ou se estou chamando um método que executa um cálculo caro. O fato de o nome do método ser um substantivo simples, no entanto, em vez de dizer calcReciprocal
, sugere novamente que a chamada é pelo menos barata e provavelmente não tem efeitos colaterais.
Em Scala, a convenção de nomenclatura é que métodos com efeitos colaterais recebem parênteses e métodos sem eles, mas
val reciprocal = heading.reciprocal
pode ser um dos seguintes:
// immutable public value initialized at creation time
val reciprocal: Heading = …
// immutable public value initialized on first use
lazy val reciprocal: Heading = …
// public method, probably recalculating on each invocation
def reciprocal: Heading = …
// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …
(Observe que o Scala permite várias coisas que, no entanto, são desencorajadas pelo guia de estilo . Esse é um dos meus principais aborrecimentos com o Scala.)
A falta de parênteses me diz que a ligação não tem efeitos colaterais; o nome, novamente, sugere que a ligação deve ser relativamente barata. Além disso, eu não me importo como isso me dá valor.
Em resumo: conheça o idioma que você está usando e saiba quais expectativas outros programadores trarão para sua API. Tudo o resto é um detalhe de implementação.
Heading
um tipo imutável ereciprocal
retornar um novoHeading
é uma boa prática "poço de sucesso". (com a ressalva para as duas chamadas parareciprocal
deve retornar "a mesma coisa", ou seja, eles devem passar o teste de igualdade.)