{week 3}

W18A

What will we cover today?

  • Design By Contract
  • Domain Modelling
  • Debugging
  • Exceptions

Programming Approaches

Defensive Programming

- Proactively identify and handle problematic situations to prevent software failures.


- In practice, this means having a lot of checks before the actual logic is executed (Eg. input checks, null checks etc)


- Trust no one! 😤


Pros: higher safety

Cons: redundant checks, more complex, harder to spot errors due to unclear responsbilities

1.

2.

Design By Contract

- Establish clear responsibilities via a contract (eg. expected input, expected output) at design time. All parties abide by the contract to guarantee correct behaviour.

 

- In practice, this means clearly documenting preconditions, postconditions and class invariants.

 

- Trust me bro🗿

 

Pros: cleaner, reduces redundant checks, faster

Cons: code crashes if contract is broken

Design by Contract (DbC) 📑

Providing an interface for others to use with clear preconditions, postconditions and invariants which, when adhered to, guarantees correct and expected behaviour.

T&C : Terms and Conditions 📝

A contract generally consists of these 3 components:

  • Class Invariant: Something that is true for all instances of a class.
  • Precondition: Something that must be true before an operation is invoked (to guarantee that it will work correctly). Users need should meet such conditions before calling an operation
  • Postcondition: Something that must be true after an operation is invoked. Condition is to be met by the implementor.

Liskov Substitution Principle 🔄

  • LSP is a way to ensure DbC in terms of OOP.
  • I know I used way too many abbreviations here. Alas, I am lazy and the slide is small.

 

The main logic of LSP:

  • Every subclass should be a substitute for its parent class
  • This substitution should never result in unexpected errors

LSP Rules🗽

  • Preconditions cannot be strengthened in a subtype.
  • Postconditions cannot be weakened in a subtype.
  • Invariants of the supertype — conditions that must remain true — must be preserved in a subtype.

Breaking LSP 🐣

  • Give an example of a real-life subclass that would violate the given contract:

public class Bird {
/**
 * Make the bird fly to the given height
 * @precondition given height must be >= 0
 *(birds cannot burrow into the ground)
**/
   public void fly(float height) {}
}

Note: by real-life subclass, I mean some kind of creature that is a type of Bird.

A suggestion 🐧

interface Flying {
 /**
 * Make the creature fly to the given height
 * @precondition given height must be >= 0
*/
 public void fly(float height);
}

// Not all birds can fly
class Bird {}
// We implement it directly for the birds that can
class Hummingbird extends Bird implements Flying {}
// And don't implement it otherwise
class Penguin extends Bird {}
// And we can apply the interface to other creatures,
// even if they're not birds
class Pterosaur extends Reptile implements Flying {}

Exceptions 👀

Exceptions in Java fall under 2 categories:

  • Checked Exceptions: These exceptions are caught at compile time and need to be handled (using a try-catch block). Eg: IOException, ServletException
  • Unchecked Exceptions: These exceptions are caught at run-time and do not need to be handled. Eg: NullPointerException, IllegalArgumentException

Errors 🤯

There's a third category to represent serious and usually irrecoverable conditions like a library incompatibility, infinite recursion, or memory leaks. These are called Errors.

  • Even though they don’t extend RuntimeException, they are also unchecked.
  • In most cases, it’d be weird for us to handle, instantiate or extend Errors. Usually, we want these to propagate all the way up.
  • Eg: StackOverflowError, OutOfMemoryError

Exceptions and Errors

All exceptions and errors in Java extend Throwable.

{The End}

Thank you for attending!

Code

By esha tripathi

Code

  • 59