correctness through simplicity

29
Correctness through simplicity Ulvi K. Guliyev

Upload: hoholoho

Post on 01-Nov-2014

394 views

Category:

Documents


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Correctness through simplicity

Correctness through simplicityUlvi K. Guliyev

Page 2: Correctness through simplicity

“…domain of dependable software engineering boils down less to money and more to ethics. Its about your duty as a software engineer to ensure that system is of as higher quality as possible.”

Prof. Joseph Kiniry (Software Development Group)

Page 3: Correctness through simplicity

How do we think about computation?

Page 4: Correctness through simplicity

Meet imperative Bob

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}if(burp != null)

_burps.Add(burp);}else{

Environment.Spit(foodItem, bob);}

}}foreach(var burp in _burps){

Environment.Release(burp);}

}

BranchLo

op

Side-effect

Jump

Loop

Side-effect

Loop

Branch

Branch

Branch

Branch

Branch Side-effect

Side-effect

∞ ∞

Meet accidental complexity

Page 5: Correctness through simplicity

How do we change thinking

modality?

• We are computers• Technology is secondary• Intuition and ingenuity• Structured roadmap

Page 6: Correctness through simplicity

Roadmap to dependable software

• Targeted at imperative programmers• Focus on reducing code complexity• Step by step discovery• Meant to alter the way we reason about

computation

Page 7: Correctness through simplicity
Page 8: Correctness through simplicity

Step 1. Procedural decomposition

Page 9: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}if(burp != null)

_burps.Add(burp);}else

Environment.Spit(foodItem, bob);}

}foreach(var burp in _burps){

Environment.Release(burp);}

}

Operational

demarcation

Page 10: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}if(burp != null)

burps.Add(burp);}else

Environment.Spit(foodItem, bob);}

}Burp();

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}

}

Page 11: Correctness through simplicity

Step 2. Single responsibility

Page 12: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}if(burp != null)

_burps.Add(burp);}else{

Environment.Spit(foodItem, bob);}

}}

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}

}

Responsibility demarcation

Page 13: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp = ProcessFoodItem(foodItem, bob);if(burp != null)

_burps.Add(burp);else

Environment.Spit(foodItem, bob);}

}}Burp();

}

Burp ProcessFoodItem(FoodItem foodItem, ImperativeGeek bob) {

Burp burp = null;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}return burp;

}

Page 14: Correctness through simplicity

Step 3. Semantic regression

Page 15: Correctness through simplicity

Code beacons

• Patterns in code• Sequences of imperative instructions• Describe how to compute and not computation itself• Denote hidden semantic intent

Page 16: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = new List<Burp>();foreach(var dish in dishes){

foreach(var foodItem in dish.Items){if(foodItem.IsTasty(bob)){

Burp burp = ProcessFoodItem(foodItem, bob);if(burp != null)

_burps.Add(burp);else

Environment.Spit(foodItem, bob);}

}}Burp();

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}}

Beacon

Beacon

Beacon

Page 17: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = ProcessFood(dishes, bob);Burp();

}

List<Burp> ProcessFood(List<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}}

Page 18: Correctness through simplicity

Step 4. Controlled side-effects

Page 19: Correctness through simplicity

void InsertNutritionalSubstance(List<Dish> dishes, ImperativeGeek bob){

_burps = ProcessFood(dishes, bob);Burp();

}

List<Burp> ProcessFood(List<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}}

Mutable type

Mutable

type

Mutable type

Page 20: Correctness through simplicity

void InsertNutritionalSubstance(IEnumerable<Dish> dishes, ImperativeGeek bob){

_burps = ProcessFood(dishes, bob);Burp();

}

IEnumerable<Burp> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}}

Page 21: Correctness through simplicity

Step 6. Functional composition

Page 22: Correctness through simplicity

void InsertNutritionalSubstance(IEnumerable<Dish> dishes, ImperativeGeek bob){

_burps = ProcessFood(dishes, bob);Burp();

}

IEnumerable<Burp> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

void Burp(){

foreach(var burp in _burps){Environment.Release(burp);

}}

Non-compositional

Page 23: Correctness through simplicity

void InsertNutritionalSubstance(IEnumerable<Dish> dishes, ImperativeGeek bob){

Burp(ProcessFood(dishes, bob));}

IEnumerable<Burp> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

void Burp(IEnumerable<Burp> burps){

foreach(var burp in burps){Environment.Release(burp);

}}

Composition

Page 24: Correctness through simplicity

Step 7. Computational abstraction

Page 25: Correctness through simplicity

IEnumerable<Burp> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

Burp ProcessFoodItem(FoodItem foodItem, ImperativeGeek bob) {

Burp burp = null;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}return burp;

}

void Burp(IEnumerable<Burp> burps){

foreach(var burp in burps){Environment.Release(burp);

}}

Could be null

Page 26: Correctness through simplicity

IEnumerable<Maybe<Burp>> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

Maybe<Burp> ProcessFoodItem(FoodItem foodItem, ImperativeGeek bob) {

Burp burp = null;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}return burp != null ? burp.ToMaybe() : Maybe<Burp>.Nothing;

}

void Burp(IEnumerable<<Maybe<Burp>> burps){

foreach(var burp in burps.Where(b => b.HasValue)){Environment.Release(burp);

}}

Page 27: Correctness through simplicity

Step 8. Constrained state space

Page 28: Correctness through simplicity

IEnumerable<Maybe<Burp>> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

Maybe<Burp> ProcessFoodItem(FoodItem foodItem, ImperativeGeek bob) {

Burp burp = null;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}return burp != null ? burp.ToMaybe() : Maybe<Burp>.Nothing;

}

∞ ∞

∞ ∞

Page 29: Correctness through simplicity

IEnumerable<Maybe<Burp>> ProcessFood(IEnumerable<Dish> dishes, ImperativeGeek bob){

Contract.Requires(dishes.Any());Contract.Requires(bob.IsHungry);Contract.Ensures(bob.IsFull);

return dishes.SelectMany(d => d.Items) .Where(i => i.IsTasty(bob)) .Select(i => ProcessFoodItem(i, bob));

}

Maybe<Burp> ProcessFoodItem(FoodItem foodItem, ImperativeGeek bob) {

Contract.Requires(foodItem.ExpiryDate < DateTime.Now);Contract.Requires(foodItem.IsWarm);Contract.Requires(bob.IsHungry);

Burp burp = null;switch(foodItem.Kind){

case FoodKind.Yummy:bob.ConsumeItem(foodItem, out burp);break;

case FoodKind.Chewy:var timeout = TimeSpan.FromSeconds(10);bob.Chew(foodItem, timeout);break;

default:throw new Exception(“Yuk!”);

}return burp != null ? burp.ToMaybe() : Maybe<Burp>.Nothing;

}