CS 528, Spring 2024, Lecture 3b

CS 528 Spring 2024, Lecture 3b


Overview

Hints and principles organized based on the following dimensions:


If you only remember three things


Goals are in conflict

Engineering is the art of making tradeoffs! For instance among features, speed, cost, dependability, and time to market. Some simpler oppositions are: It also helps to choose the right coordinate system:


Functionality: Getting it Right!

The most important hints are about getting it to do the things you want it do do.

An interface that separates an implemenation of some abstraction from the clients who use the abstraction.

Defining interfaces is the most important part of system design.

The interface design must satisfy three conflicting requirements:

Each interface is like a small programming language: it defines a set of objects and the operations that can be used to manipulate the objects.

Recall Hoare's discussion on good language design:


Keep it simple

Do one thing at a time, and do it well.

An interface should capture the minimum essentials of an abstraction.

Don't generalize; generalizations are generally wrong.

The interface should not promise more than the implementer knows how to deliver.

Neither abstraction nor simpicity is a substitute for getting it right.

Other corollaries:


From Interfaces to Specifications

Hard questions when writing a spec:

Spec makes modularity precise (design, correctness, documentation)

Do it recursively

Refinement: one main's implementation is another man's spec.

Composition: use actions from one spec in another.

How to Write a Spec

What "implements" means (you can't tell Y and X by looking at only the external actions)


Continuity for Debugging & Maintenance

Keep basic interfaces stable.

Keep a place to stand if you have to change interfaces


Making implementations work

Plan to throw one away; you will anyhow.

Keep secrets of the implementation. Secrets are assumptions about an implementation that client programs are not allowed to make.

Divide and conquer. Reduce a hard problem into several easier ones.

Use a good idea again instead of generalizing it.


Handling all the cases

Handle normal and worst cases separately.


Speed: Making it fast

Split resources in a fixed way if in doubt, rather than sharing them.

Use static analysis if you can.

Dynamic translation.

Cache answers to expensive computations.

Use hints to speed up normal execution.

When in doubt, use brute force.

Compute in background when possible.


Fault-tolerance

Making a system reliable is not really hard, if you know how to go about it. But retrofitting reliability to an existing design is very difficult.


Copyright (c) 2009-2024, Zhong Shao, Dept. of Computer Science, Yale University.