São pré-condições e pós-condições necessárias, além de invariantes em funções membro se fazer programação por contrato?

StackOverflow https://stackoverflow.com/questions/1219564

Pergunta

Eu entendo que no método DbC, pré-condições e pós-condições estão associadas a uma função.

O que eu estou querendo saber é se isso se aplica a funções membro também.

Por exemplo, supondo que eu usar invariantes no início no final de cada função pública, uma função membro será parecido com este:

edit: (limpado meu exemplo)

void Charcoal::LightOnFire() {
  invariant();
  in_LightOnFire();

  StartBurning();    
  m_Status = STATUS_BURNING;
  m_Color = 0xCCCCCC;

  return; // last return in body

  out_LightOnFire();
  invariant();
}

inline void Charcoal::in_LightOnFire() {
  #ifndef _RELEASE_
  assert (m_Status == STATUS_UNLIT);
  assert (m_OnTheGrill == true);
  assert (m_DousedInLighterFluid == true);
  #endif
}

inline void Charcoal::out_LightOnFire() {
  #ifndef _RELEASE_
  assert(m_Status == STATUS_BURNING);
  assert(m_Color == 0xCCCCCC);
  #endif
}

// class invariant
inline void Charcoal::invariant() {
  assert(m_Status == STATUS_UNLIT || m_Status == STATUS_BURNING || m_Status == STATUS_ASHY);
  assert(m_Color == 0x000000 || m_Color == 0xCCCCCC || m_Color == 0xEEEEEE);
}

Está tudo bem para usar pré-condições e pós-condições, com apenas funções global / genéricos e usar apenas invariantes dentro das classes?

Este parece ser um exagero, mas talvez o seu o meu exemplo é ruim.

edit:

Não é a pós-condição apenas verificar um subconjunto da invariante?

No exemplo acima, eu estou seguindo as instruções do http://www.digitalmars.com /ctg/contract.html que afirma: "a invariante é verificada quando a completa construtor da classe, no início da destruição de classe, antes de um membro do público é executado e, após um público acabamentos de função".

Graças.

Foi útil?

Solução

Sim.

O Classe C invariante é uma propriedade comum de todas as suas instâncias (objetos). Os avalia invariantes para true se e somente se o objeto está em um estado semanticamente válido.

invariante de um elevador pode conter informações como ASSERT(IsStopped() || Door.IsClosed()), porque é inválido para um elevador para estar em um estado diferente do que parou (digamos, indo para cima) e com a porta aberta.

Em contraste, uma função de membro, tais como MoveTo(int flat) pode ter CurrentFlat()==flat como um postcondition ; porque depois de uma chamada para MoveTo (6) o plano atual é 6. Da mesma forma, ele pode ter IsStopped() como precondição , porque (dependendo do projeto), você não pode invocar a função MoveTo se o elevador é já em movimento. Primeiro, você tem que consultar o seu estado, certifique-se de que ele está parado, e, em seguida, chamar a função.

Claro que pode ser simplificar totalmente como funciona um elevador.

Em qualquer caso, as pré-condições e pós-condições não fará sentido, em geral, as condições invariantes; um elevador não precisa estar no piso 6 a estar em um estado válido.

Um exemplo mais conciso pode ser encontrada aqui: Intercepção e atributos:. Um projeto-por-contrato Amostra por Sasha Goldshtein

Outras dicas

Restringir os contratos nas classes para invariantes não é o ideal.

Pré-condições e Pós-condições não são apenas um subconjunto dos invariantes.

Invariants, pré-condições e pós-condições têm papéis muito diferentes.

Invariants confirma a coerência interna do objeto. Eles devem ser válidos no fim do construtor e antes e depois de cada chamada de método.

Pré-condições são a verificação de que o status do objeto e os argumentos são adequados para a execução do método. Pré-requisitos são complementares aos invariantes. Eles cobrem a verificação dos argumentos (uma verificação mais forte que o próprio tipo, ou seja, não nulo,> 0, .. etc), mas também pode verificar o estado interno do objeto (chamada ou seja, um para file.write ( "Olá ") é uma chamada válida somente se file.is_rw e file.is_open são verdadeiras).

Pós-condições são cheking que o método satisfeito a sua obrigação Pós-condições também são complementares aos invariantes. É claro que o status do objeto tem que ser coerente após a execução do método, mas as pós-condições são a verificação de que a ação esperada foi realizado (ou seja list.add (i) deve ter como consequência que list.has (i) é verdadeiro e list.count = idade list.count + 1).

Bem, a ponto de um invariante é que ele descreve algo que é true do objeto em todos os momentos . Neste caso, há algo na grelha, ou não (nada entre eles). Eles normalmente descrever uma propriedade de todo o estado do objeto.

Pré e pós-condições descrevem coisas que são verdadeiras antes de um executa o método, e logo após, e preocupação vontade apenas o estado que deveria ter sido tocado pelo método . Isso é diferente, presumivelmente, do estado do objeto. Pré e pós-condições pode ser pensado como descrever a pegada de um método -. Exatamente o que ele precisava, apenas o que tocou

Assim, à questão específica, as ideias fazer coisas diferentes, assim você pode muito bem querer tanto. Você certamente não pode apenas usar invariantes em vez de condições pré e pós - neste caso, parte do objeto invariante é "Algo está na grade ou não", mas a pré-condição de lightOnFire precisa saber que o item está na grelha. Você nunca pode inferir isso do objeto invariante. É verdade que desde a pré e pós-condições e de um estado inicial conhecido, você pode (assumindo que a estrutura de objetos só é mutável através de métodos e as condições pré e pós descrever todas as mudanças ambientais), inferir uma invariante objeto. No entanto, isso pode ser complexo, e quando você está afirmando coisas "na linguagem", é mais fácil simplesmente fornecer tanto.

Claro, fazendo em variantes que o estado de um item de boolean é verdadeiro ou falso é um pouco inútil - é assegurado sistema tipo que

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top