Boundaries are objects that interface with system actors:
user interfaces, gateways, proxies, etc.

Controllers are objects that mediate between boundaries and
entities. They orchestrate the execution of commands coming from the boundary.

ATM Example

The Hexagonal Architecture Pattern (aka Ports & Adapters)

The Hexagonal Architecture partitions objects into one of
three nested hexagons: Entities in the inner hexagon, controllers in the middle
hexagon, boundaries in the outer hexagon, and actors outside of the outer
hexagon:

Actors interact with boundary objects.

Boundary objects issue commands to controller objects.

Controller objects may send queries back to the boundary
objects to get more information from the actors.

Controllers then update entities.

Boundaries refresh themselves as needed to reflect changes
among the entities.

Mapping to MVC

We can map the inner hexagon filled with entities to the
Model role in the Model-View-Controller Pattern. Controllers obviously map to
Controllers, and boundaries, at least boundaries that interact with users, map
to views.

The Hexagonal architecture has several nice features.

1. It doesn't distinguish between user interfaces and
interfaces to other types of actors such as servers and devices.

2. We can view a boundary object as any object that happens
to implement an interface required by a controller. This interface can be
viewed as a port on the boundary of the middle hexagon. This makes testing easy
since we can implement boundary objects as real actor interfaces or as mock
actors.

The Use Case Controller Pattern

Developers often have trouble pointing to the place in the
design where a particular use case is implemented. This problem can be
mitigated by identifying each use case with a specific controller object. In
this case the controller is called a use case controller.