Coding: Understanding Abstraction
When I started learning programming in college I had no idea what I was doing, and to be honest, the teaching style was not very effective. Most of my classmates were in the same boat, we had to google a lot and work with each other to try to understand the principles of programming. After many years of coding and learning I was able to grasp the concepts. I am going to attempt to explain these principles in the simplest terms.
As mentioned in this other post [Programming Languages: Differences] one of the core principles of Object-Oriented programming is the concept of abstraction (the process of hiding the internal details of an application from the outer world).
I am going to try to explain this principle with the process of buying coffee from a coffee machine.
The way you order a coffee from a machine is to choose your coffee type such as espresso shot, dripped, americano, pour over, etc.
Then you would pick your size; small, medium, large.
The machine then would take these inputs and process your request depending on the input. As a customer you do not know what those steps might be, espresso could be a different process than dripped coffee or pour over. The coffee machine leave that out of sight, you only need to tell it what type of beverage you want.
I think the best way to explain this concept is to review some code.
First, we can define the objects needed for the coffee machine to process our request.
public class Coffee
{
public int ID;
public string Name;
public double Quantity;
public RoastTypeEnum RoastTypeEnum;
public CoffeeSelectionEnum CoffeeSelection;
public bool IsBrewed;
}
Coffee object contains simple attributes such as name, quantity of coffee, roast type, etc.
The coffee selection enum is the type of coffee that will be brewed, such as americano, pour over, etc.
public enum CoffeeSelectionEnum : byte
{
Drip = 1,
EspressoShot = 2,
Americano = 3,
PourOver = 4
}
Cup size to display the user the options available
public enum CupSizeEnum : byte
{
Small = 1,
Medium = 2,
Large = 3
}
These are all the objects needed to the user to make their selection, with these inputs the coffee machine will know what to do.
Now that we have these available, we can look at the actual Coffee Machine class.
The public method is BrewCoffee, that is all the outer classes needs to know.
The principle of abstraction is that the process of brewing certain type of coffee is not exposed to other classes, there is no need to know that to brew americano coffee you need to brew an espresso shot and add water after, all outer classes need to know is that coffee machine brews coffee.
public class CoffeeMachine
{
private Coffee _coffee;
private string _cupSizeName;
public CoffeeMachine(Coffee coffee, CupSizeEnum cupSizeEnum)
{
_coffee = coffee;
switch (cupSizeEnum)
{
case CupSizeEnum.Small:
_cupSizeName = "Small";
break;
case CupSizeEnum.Medium:
_cupSizeName = "Medium";
break;
case CupSizeEnum.Large:
_cupSizeName = "Large";
break;
}
}
public Coffee BrewCoffee()
{
Coffee brewedCoffee = _coffee;
switch (_coffee.CoffeeSelection)
{
case CoffeeSelectionEnum.EspressoShot:
brewedCoffee = BrewEspressoShot();
break;
case CoffeeSelectionEnum.Americano:
brewedCoffee = BrewAmericano();
break;
case CoffeeSelectionEnum.Drip:
brewedCoffee = BrewDrip();
break;
case CoffeeSelectionEnum.PourOver:
brewedCoffee = BrewPourOver();
break;
default:
Console.WriteLine("Coffee Selection not chosen.");
break;
}
int count = 0;
while (count <= 4)
{
Thread.Sleep(1000);
Console.Write(".");
count++;
}
brewedCoffee.IsBrewed = true;
Console.WriteLine("Enjoy your fresh cup of joe!");
return brewedCoffee;
}
private Coffee BrewEspressoShot()
{
DisplayProcessStep();
//Do whatever needs to be done to brew espressoShot
return _coffee;
}
private Coffee BrewAmericano()
{
DisplayProcessStep();
//Do whatever needs to be done to brew americano
return _coffee;
}
private Coffee BrewDrip()
{
DisplayProcessStep();
//Do whatever needs to be done to brew drip coffee
return _coffee;
}
private Coffee BrewPourOver()
{
DisplayProcessStep();
//Do whatever needs to be done to brew pour over coffee
return _coffee;
}
private void DisplayProcessStep()
{
Console.WriteLine($"Brewing {_cupSizeName} cup of {_coffee.Name}");
}
}
For other classes, CoffeeMachine class would have BrewCoffee method available. As long as you instantiate CoffeeMachine with Coffee object populated and CupSize, you can call BrewCoffee.
var coffeeMachine = new CoffeeMachine(selectedCoffee, cupSizeEnum);
var brewedCoffee = coffeeMachine.BrewCoffee();
I hope that this small code snippet helps understand the principle of abstraction a little bit better.
You check out the whole code in this repository.