Rethinking Distributed Programming