Again and again I am asked if I can provide a complete example of EBC, which I will do that here.
However, I have to say beforehand that I thought at first that the coding is sufficient by Ralf (Ralf's EBC blog entries ) in order to identify the scope and benefits of the EBC. Since this is not so, I hereby make a first complete example available that were built on the basis of the first generation EBC and its Post from Christopher's ( Christophe review ) inspired.
The scenario
Christof described a board that calculates the gross value of an amount and then rounds the result to two decimal places. He was to bear in mind that a board contains an implicit logic in the wiring, resulting from the task. One could make the rounds before or after the calculation.At this point I want to talk but no implicit or explicit logic in the board, but EBC present in a sample. I opted for the round after the calculation.
textual formulation of the components
quote from Christophe's post:"Component A:
- calculating VAT from an input
- Input: any number
- Issue: Entry * value added tax rate (2% :-())
Part B:
- Task: Formatting the input
- Input: any numbers
- Issue: number with exactly 2 decimal places, if necessary suitably rounded
Both devices are connected to board "VAT" "
Graphic formulation - Wiring Diagram
I plead for a tool to have with the wiring is shown graphically, because this form of representation is much easier to understand than the underlying code.
The project
The Solution Project (Visual C # 2010 Express) I have to request such a way that is clear, where what happens. A project for the contracts, one for the implementation and one for the tests. So that it is running and can be tried once, I have not created a motherboard that instantiates the Tax Board and shall provide the parts.
Unfortunately I have to mix Concerns, because I have no further project for EBC is planned to open the framework, as a component, the numbers round, has now really looking to do with the calculation of gross value. But looking ahead I have the component and its carrying Contract de.ebc.Framework in the namespace for the event that it would later be such a framework.
The tests are still (!) Implemented with NUnit, but I prefer Behavior Driven Testing, and will probably get in the near future or NSpec MSpec back out of mothballs and then write all my tests with it. I find this kind of testing much easier to understand.
The Contracts
The Contracts define the components, that is not special, because now should be state of the art. The special feature of these contracts but the fact that no pins are defined and methods, functions and / or fields.Good, the input pin is also a method, but that is the nature of the thing. In some way so the signal must be, the message will be introduced into the component. It must, however, a fundamental difference between the pins of a board and where the parts are made.
In some tests, I checked the readability of the code by using pin variations and found that the difference increases the readability.
here once a complete example using the method of Ralf;
/ / Variant 1 InPin
/ / In Contract:
public interface IComponent {
void In_InMessage ( TypeOfMessage message ) ;
}
/ / The board
public class MyBoard {
private Action \u0026lt; TypeOfMessge > _channelMethod ;
public MyBoard ( IComponent component) {
/ / wiring on the board
this . _channelMethod = component. In_InMessage ;
...
}
/ / Board InPin
public void In_BoardMessage ( MessageType message ) {
this . _channnelMethod ( message ) ;
}}
This version I think While quite nice, but I did not find it particularly easy to read. Just the need for an extra box _channelMethod "came to pass in order to define the message to the first of the first component InPin me bulky. Other tools such as wire
classes that connect the pins have not please me. So I have found by trial and error the following variant of sufficiently good.
EBC Pins
- namespace de.ebc.Framework
- {
- public delegate void InPin \u0026lt;TInput> (TInput inmessages);
- public delegate void OutPin \u0026lt;TOut> (Tout outMessage);}
I start with the definition of the board, on which the two parts are connected. Two pins on the board are defined. One receives the message (In_CalcToGross) and the other returns the result (Out_Gross). Attention, here is the InPin as Field have been defined from the said above reason.
EBC IVatBoard Contract
- namespace de.ebc.vatboard
- {/ / / \u0026lt;summary>
- / / / Defines a component that can handle VAT
- / / / \u0026lt;/ summary>
- public interface IVatBoard
- {
- / / / \u0026lt;summary>
- / / / Computes the gross value of a number
- /// </summary>
- /// <param name="netto"></param>
- InPin < Decimal > In_CalcToGross { get ; set ; }
-
- / / / \u0026lt;summary>
- / / / Is the gross returns
- / / / \u0026lt;/ summary>
- event OutPin \u0026lt; Decimal > Out_Gross;
- }}
EBC IVatCalculator Contract
- namespace de.ebc.vatboard
- {
- / / / \u0026lt;summary>
- / / / Defines a component that calculates the gross value of a number
- / / / \u0026lt;/ summary> public
- interface IVatCalculator
- {
- / / / \u0026lt;summary>
- / / / Berchnet the gross value of a number
- ; / / / \u0026lt;/ summary>
- / / / \u0026lt;param name="netValue"> \u0026lt;/ param>
- void In_CalculateGross ( Decimal NetValue);
- / / / \u0026lt;summary>
- / / / Is the gross returns
- / / / \u0026lt;/ summary>
- event OutPin \u0026lt; Decimal > Out_Gross;
- ;}}
EBC IRoundDecimals Contract
- namespace de.ebc.Framework
- {/ / / \u0026lt;summary>
- can / / / Defines a component, round the numbers
- / / / \u0026lt;/ summary>
- ; public interface IRoundDecimals
- {
- / / / \u0026lt;summary>
- / / / number rounded to two decimal
- /// </summary>
- /// <param name="number"></param>
- void In_RoundingToTwoDecimals( Decimal number);
-
- / / / \u0026lt;summary>
- / / / Returns the number rounded back
- ; / / / \u0026lt;/ summary>
- event OutPin \u0026lt; ; Decimal > Out_RoundedNumber;
- }}
The Components (Parts and boards) What is to be expected, the components of the meat of the Contracts and it is waiting for us, again, no surprise.
First, the Board, which is home to the wiring. EBC VatBoard
- namespace de.ebc.vatboard.Components
- {
- public class VatBoard : IVatBoard
- {
- public VatBoard( IVatCalculator vatCalculator, IRoundDecimals numberRounder)
- {
- / / InPin the Board with the first component wiring
- this In_CalcToGross = vatCalculator.In_CalculateGross;.
- / / Result for rounding to the next component forward
- vatCalculator.Out_Gross + = numberRounder.In_RoundingToTwoDecimals;
- ;
- / / round number return
- numberRounder.Out_RoundedNumber += this .OnOutRoundedNumber;
- }
-
- private void OnOutRoundedNumber( Decimal number) {
- this .Out_Gross(number);
- }
-
- public InPin < Decimal > In_CalcToGross {
- get ;
- set;}
- public event OutPin \u0026lt; decimal> = Out_Gross delegate {};}
- }
Now just the two working components:
EBC VatCalculator
- namespace de.ebc.vatboard.Components
- {
- public class VatCalculator : IVatCalculator
- {
- public VatCalculator ( decimal vatInPercent) {
- this .VatInPercent = vatInPercent;
- }
-
- public Decimal VatInPercent { get ; private set ; }
-
- public void In_CalculateGross( decimal netValue)
- {
- Decimal gross = GetGross(netValue);
- this .Out_Gross(gross);
- }
-
- private decimal GetGross( decimal netValue)
- {
- return netValue * (1 + VatInPercent / 100);
- }
-
- public event OutPin < decimal > Out_Gross = delegate { };
- }
- }
EBC RoundDecimals
- namespace de.ebc.vatboard.Components
- {
- public class RoundDecimals : IRoundDecimals
- {
- public event OutPin < decimal > Out_RoundedNumber = delegate { };
-
- public void In_RoundingToTwoDecimals( decimal number)
- {
- decimal roundedNumber = RoundNumber(number);
- this .Out_RoundedNumber(roundedNumber);
- }
-
- private decimal RoundNumber( decimal number)
- {
- return Decimal Round (number, 2);.
- }
- }}
When I wrote the code well, it needs no further explanation of what happened here. And to determine this, I will make no further comment, because I hope for what the reader ;-)
The testing of the solution Testing is simple, because I can test each component individually through their paces. I could also try all the modules for the test and create. I have not done here.
As mentioned NUnit is used, what will I think change in the near future.Testing of VatCalculator component is a fixed net value of 12 to send into the component into it, only to receive the gross value and evaluate.
testing VatCalculator
- [ TestFixture ]
- public class TestVatCalculator : WithVatCalculator
- {
- [ Test ]
- public void Calculate_For_Number_12()
- {
- decimal netValue = 12;
- decimal vat = this .VatCalculator.VatInPercent;
- decimal shouldBrutto = (netValue * (1+vat/100));
-
- this .VatCalculator.Out_Gross += brutto =>
- {
- Assert AreEqual (should gross, gross).
- };
- ;. this VatCalculator.In_CalculateGross (NetValue);
- }}
The second Component, the curvature component, we tested the same way.
testing RoundDecimals
- [ TestFixture ]
- public class TestRounding : WithRoundDecimals
- {
- [ Test ]
- public void Round_To_Two_Decimals () {
- ; decimal aNumber = 12.34567m;
- this .RoundDecimals.Out_RoundedNumber += roundedNumber =>
- {
- Assert .AreEqual(12.35m, roundedNumber);
- }; .
- this RoundDecimals.In_RoundingToTwoDecimals (aNumber);}
- }
The solution as an application
I chose the example of the Console, which is not really about rachend and then the call to the following terms:
VatBoard as application
- namespace de.ebc.VatMainBoard
- {
- class Program
- {
- static void Main( string [] args)
- {
-
- Decimal vat = 16m;
-
- IVatCalculator vatCalculator = new VatCalculator (vat);
- IRoundDecimals numberRounder = new RoundDecimals ();
-
- IVatBoard vatBoard = new VatBoard (vatCalculator, rounder number);
- / / Result output
- vatBoard.Out_Gross + = large => {
- Console .WriteLine(gross);
- };
-
- string netValueString = Console .ReadLine();
- Decimal netValue = 0;
-
- Decimal .TryParse(netValueString, out netValue);
- vatBoard.In_CalcToGross(netValue);
-
- Console ReadLine ();.
- }
- }}
The project can be downloaded from CodePlex at the following link EBC samples.
Well then ran times and forth with the comments.
Jan (ek)
0 comments:
Post a Comment