Here’s a fun exercise. Imagine you have three shapes: Point, rectangle and circle, with the following properties:
- Point: int x, int y
- Rectangle: Point bottomLeft, Point topRight
- Circle: Point center, int radius
Add two behaviours: area and draw.
How would you organize the implementation to enforce:
- Cohesion: A class (or module) should be responsible for one thing only
- Coupling: You should be able to isolate change in the system
- Encapsulation: Classes shouldn’t share internal representation
- Polymorphism: The design should be based on interfaces
It should be possible to do something like:
forall shapes as shape, do shape.draw(surface)
Or if you move out the drawing logic:
forall shapes as shape, do surface.draw(shape.getDrawData())
The simple solution in OCaml is to use ADT for each shape. This will make it easy to add new behaviour, just as expected for the expression problem in functional programming. You can also break out each shape into a separate module. This will make it easy to add new data (types of shapes). Are there any other alternatives?
The following question can be asked:
- How easy would it be to move to a 3D representation?
- How easy would it be to add a new shape, say, triangle?
- How easy would it be to add a new behaviour to all shapes, like save/load from a SQL database?