fix code blocks

This commit is contained in:
2026-09-10 22:54:41 +02:00
parent 2dc30200a1
commit cd8a75ec13
9 changed files with 519 additions and 666 deletions
+41 -52
View File
@@ -15,44 +15,41 @@ Erstens muss man die IDE anpassen: im März kommt .NET 4.0 raus und da wird Desi
Jetzt zum Code: Nehmen wir eine ganz einfache Klasse `Bill` deren Objekte mit einem `IRepository` gespeichert bzw. geladen werden.
```
using System.Diagnostics.Contracts;
namespace ContractsPrototyp
```csharp
using System.Diagnostics.Contracts;
namespace ContractsPrototyp
{
public class Bill
public class Bill
{
public int Id { get ; set ; }
public string Number { get ; set ; }
public double Value { get ; set ; }
public int Id { get ; set ; }
public string Number { get ; set ; }
public double Value { get ; set ; }
}
10
11
public interface IRepository
public interface IRepository
{
Bill GetBill( string number);
void SaveBill( Bill bill);
Bill GetBill( string number);
void SaveBill( Bill bill);
}
```
Die Kontrakte kann man in den einzelnen Methoden oder für eine ganze Klasse schreiben (unter dem Attribut `ContractInvariantMethode`) aber ich finde am schönsten, dass man die auch auslagern kann: durch eine gegenseitige Markierung können Kontrakt-Klassen und Interfaces als “Paare” definiert werden:
```
```csharp
[ ContractClass ( typeof ( RepositoryContracts ))]
public interface IRepository
public interface IRepository
{
Bill GetBill( string number);
void SaveBill( Bill bill);
Bill GetBill( string number);
void SaveBill( Bill bill);
}
[ ContractClassFor ( typeof ( IRepository ))]
public class RepositoryContracts : IRepository
public class RepositoryContracts : IRepository
{
public Bill GetBill( string number)
public Bill GetBill( string number)
{
Contract .Requires(! string .IsNullOrEmpty(number));
return null ;
return null ;
}
25
public void SaveBill( Bill bill)
public void SaveBill( Bill bill)
{
Contract .Ensures(bill.Id > 0);
}
@@ -63,43 +60,40 @@ Eine Vorbedingung wird mit `Contract.Requires` und eine Nachbedingung mit `Contr
Die eigentliche Implementierung der Klasse schaut dann so aus:
```
public class Repository : IRepository
```csharp
public class Repository : IRepository
{
public Bill GetBill( string nummer)
public Bill GetBill( string nummer)
{
//Würde das Objekt aus Datenhaltung laden
return new Bill ();
return new Bill ();
}
38
public void SaveBill( Bill bill)
public void SaveBill( Bill bill)
{
//Würde das Objekt speichern und ihm eine Id zuweisen
if (BillIsValid( bill )) bill.Id++;
if (BillIsValid( bill )) bill.Id++;
}
44
private static bool BillIsValid( Bill bill)
private static bool BillIsValid( Bill bill)
{
return ! string .IsNullOrEmpty(bill.Nummer);
return ! string .IsNullOrEmpty(bill.Nummer);
}
}
```
Woher können wir wissen, dass das funktioniert? Es ist einfach, wir schreiben ein Paar Tests dazu!
Woher können wir wissen, dass das funktioniert? Es ist einfach, wir schreiben ein Paar Tests dazu!
Bei Kontraktverletzung wird eine Exception geworfen. Um diese und dadurch die genaue Verletzung überprüfen zu können braucht man etwas Workaround:
```
```csharp
[ TestFixture ]
public class BillTests
public class BillTests
{
private IRepository m_repository;
private string m_message;
60
private IRepository m_repository;
private string m_message;
[ SetUp ]
public void Setup()
public void Setup()
{
m_repository = new Repository ();
m_message = string .Empty;
m_repository = new Repository ();
m_message = string .Empty;
Contract .ContractFailed += ( sender, e ) =>
{
e.SetUnwind();
@@ -110,37 +104,32 @@ m_message = e.Message;
Danach sind die Tests dann einfach:
```
```csharp
[ Test ]
public void Laden_mit_leerer_Nummer_verletzt_Kontrakt()
public void Laden_mit_leerer_Nummer_verletzt_Kontrakt()
{
76
try
{
m_repository.GetBill( null );
m_repository.GetBill( null );
}
catch
{
//Nichts
}
85
Assert .That( m_message, Is .EqualTo( "Precondition failed: !string.IsNullOrEmpty(number)" ) );
Assert .That( m_message, Is .EqualTo( "Precondition failed: !string.IsNullOrEmpty(number)" ) );
}
88
[ Test ]
public void Speichern_Rechnung_ohne_Nummer_verletzt_Kontrakt()
public void Speichern_Rechnung_ohne_Nummer_verletzt_Kontrakt()
{
92
try
{
m_repository.SaveBill( new Bill {Value = 25} );
m_repository.SaveBill( new Bill {Value = 25} );
}
catch
{
//Nichts
}
101
Assert .That( m_message, Is .EqualTo( "Postcondition failed: bill.Id > 0" ) );
Assert .That( m_message, Is .EqualTo( "Postcondition failed: bill.Id > 0" ) );
}
```