Programming Principles in Java: Architectures and Interfaces