This thesis is at the crossing of object-orientation and reliable distributed systems, and contributes to integrate those two research fields. Existing distributed programming environments can be characterised according to whether they rely on object concepts and to whether they deal with reliability issues. Most of such environments combine objects and distribution, although they follow different approaches in doing so. However, only a minority is concerned with reliability. This is not surprising, since the design of reliable distributed software requires to deal with many non-trivial issues, such as reliable communication, failure detection, consensus, etc. In this context, the research presented here focuses on fundamental programming abstractions for structuring reliability issues at the system level. Three questions are at the heart of that concern: (1) what abstractions are most adequate to model reliability, (2) how to represent them to promote flexible design, and (3) how to implement them to promote code reuse. These questions enable to further categorise existing distributed environments as reliability-based or protocol-based. The former answer question 1, by proposing either group communication or transactions, whereas the latter answer questions 2 and 3 by providing protocols as basic structuring abstractions. Because transactions and group communication are primarily aimed at application programmers, reliability-based environments are of limited help for system programmers. As for protocol-based environments, none integrates recent advances in object-orientation, such as design patterns, and in the theory of asynchronous distributed systems augmented with unreliable failure detectors. The contribution of this research is in its attempt to address questions 2 and 3, while it acknowledges existing theoretical results as possible answers to question 1. The thesis introduces the protocol-oriented approach, together with Bast, an object-oriented framework written in Smalltalk and later ported on Java. The Bast framework relies on protocols as basic programming abstractions, each protocol representing an elemental problem/solution pair. It supports the composition of such elemental pairs through protocol objects and protocol patterns; they are the proposed answers to question 2. Protocol objects are distributed objects capable of participating in virtually any kind of remote interactions, whereas protocol patterns are domain-specific design patterns that describe how to compose protocol objects. Bast provides an extensible library of protocol object classes, implementing reliable point-to-point and multicast communication, failure detection, consensus, etc. Two protocol patterns are presented: Active Replication, which helps in the assembling of protocol objects for active replication, and Distributed Agreement, which captures the recurring structure of various classical agreement protocols. In Bast, three protocol object classes are derived from the Distributed Agreement pattern, each one solving a specific agreement problem, that is atomic commitment, total order multicast and view synchrony. The Bast framework is also based on an open implementation, which is the proposed answer to question 3. Protocol dependencies are managed within protocol objects using a general-purpose design pattern, known as Strategy. The Strategy pattern is applied to implement distributed algorithms as separate objects from the protocol objects that use them. It helps to overcome the limitations of single inheritance as far as protocol composition is concerned. As a consequence, one can flexibly change or customise any distributed algorithms within existing protocol objects. This pattern also enables to manage concurrent protocol executions in a transparent and recursive way. The thesis concludes by sketching how transparency could be added on top of Bast, with no loss of flexibility.