PROGRAMMING DISTRIBUTED COMPUTING SYSTEMS – A FOUNDATIONAL APPROACH