In general
Whenever you try to implement an application try to use sentences to describe the desired behavior. After that ask yourself: "Can it be further refined?" If so, then write new sentences to detail your plan in a more fine-grained level.
Let me show you what I mean:
The view from 10 000 feet
The application can perform basic operations between two operands.
What can be further refined?
- What does it mean basic operation?
- What did we mean by two operands?
High-level view
The application can perform basic operations between two operands.
It allows addition, subtraction, multiplication and division.
User can provide two numbers and the desired operation.
The application will perform it on the user's behalf.
What can be further refined?
- How can an user provide numbers?
Fine-grained problem decomposition
The application can perform basic operations between two operands.
It allows addition, subtraction, multiplication and division.
User can provide two numbers and the desired operation.
The application receives an input from the user then it perform a preliminary check.
If it is valid then it goes to the next statement.
If it is invalid then it ask the user again to provide a valid input.
The application will perform it on the user's behalf.
Let's put together the skeleton
Now, we can translate each sentence into instructions.
This problem decomposition also helps us to well-organize our code:
///<summary>
/// The application can perform basic operations between two operands.
///</summary>
public static void Main()
{
}
///<summary>
/// User can provide two numbers and the desired operation.
///</summary>
private static void AskForInputs()
{
}
///<summary>
/// The application receives an input from the user then it perform a preliminary check.
/// <list type="bullet">
/// <item>
/// <description>If it is valid then it goes to the next statement.</description>
/// </item>
/// <item>
/// <description>If it is invalid then it ask the user again to provide a valid input.</description>
/// </item>
/// </list>
///</summary>
///</summary>
private static int AskForNumber()
{
}
///<summary>
/// The application receives an input from the user then it perform a preliminary check. <para />
/// It allows addition, subtraction, multiplication and division.
///</summary>
private static char AskForOperation()
{
}
///<summary>
/// The application will perform it on the users behalf.
///</summary>
private static void PerformRequestedOperation()
{
}
Observations about your implementation
The implementation is bit naive, because:
- It does not handle those cases when the user provides malformed input
- For example: instead of
3
(s)he provides three
- It does not handle under- or overflow cases
- For example:
int.MaxValue + 100
- It does not handle zero division case
- It does not handle properly a division where the result is a floating number
- etc.
In your switch
statement you repeat the following two statement in each case
:
Console.WriteLine(answer);
Console.ReadKey();
An alternative implementation could be:
switch (operation)
{
case "+":
answer = firstNumber + secondNumber;
break;
case "-":
answer = firstNumber - secondNumber;
break;
case "*":
answer = firstNumber * secondNumber;
break;
case "/":
answer = firstNumber / secondNumber;
break;
}
Console.WriteLine(answer);
Console.ReadKey();
This can be easily enhanced to include all the above validations as well:
switch (operation)
{
case "+":
answer = PerformAddition(lhs, rhs);
break;
case "-":
answer = PerformSubtraction(lhs, rhs);
break;
case "*":
answer = PerformMultiplication(lhs, rhs);
break;
case "/":
answer = PerformDivision(lhs, rhs);
break;
}
Console.WriteLine(answer);
Console.ReadKey();
Now as you can see we have introduced 4 new functions to abstract away the complexity to deal with different edge cases and the main flow remained easy to follow.