Skip to content

Commit 15fefba

Browse files
authored
Merge pull request #493 from microsoft/vncz/enum-tips
Add enum guidance
2 parents 4085e6a + 50481c1 commit 15fefba

File tree

4 files changed

+143
-21
lines changed

4 files changed

+143
-21
lines changed

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
> # NOTICE TO READERS
2-
>
3-
> ## Guidance for Azure service teams
4-
> Azure service teams should use companion documents, [Azure REST API Guidelines](./azure/Guidelines.md) and [Considerations for Service Design](./azure/ConsiderationsForServiceDesign.md), when building or modifying their services. These documents provide a refined set of guidance targeted specifically for Azure services. For more information please refer to the [README](./azure/README.md) in the Azure folder.
5-
>
6-
> ## Guidance for Microsoft Graph service teams
7-
> Microsoft Graph service teams should reference the companion document, [Graph REST API Guidelines](./graph/GuidelinesGraph.md) when building or modifying their services.
8-
>
9-
> In the process of building many of Microsoft's highest scale services, the Microsoft Graph team found the Microsoft API guidelines tremendously useful as a baseline. However, there are several areas where we need to provide more clarity on how developers should describe their APIs. The companion document, [Graph REST API Guidelines](./graph/GuidelinesGraph.md) is a set of amendments and clarifications for Microsoft Graph that act as further reading. Recognizing that two documents is a lot for a new API designer to absorb, our plan is to follow the approach Azure have taken and roll out guidelines for Microsoft Graph into a single consolidated document.
1+
# NOTICE TO READERS
2+
3+
## Guidance for Azure service teams
4+
Azure service teams should use companion documents, [Azure REST API Guidelines](./azure/Guidelines.md) and [Considerations for Service Design](./azure/ConsiderationsForServiceDesign.md), when building or modifying their services. These documents provide a refined set of guidance targeted specifically for Azure services. For more information please refer to the [README](./azure/README.md) in the Azure folder.
5+
6+
## Guidance for Microsoft Graph service teams
7+
Microsoft Graph service teams should reference the companion document, [Graph REST API Guidelines](./graph/GuidelinesGraph.md) when building or modifying their services.
8+
9+
In the process of building many of Microsoft's highest scale services, the Microsoft Graph team found the Microsoft API guidelines tremendously useful as a baseline. However, there are several areas where we need to provide more clarity on how developers should describe their APIs. The companion document, [Graph REST API Guidelines](./graph/GuidelinesGraph.md) is a set of amendments and clarifications for Microsoft Graph that act as further reading. Recognizing that two documents is a lot for a new API designer to absorb, our plan is to follow the approach Azure have taken and roll out guidelines for Microsoft Graph into a single consolidated document.
1010

1111
---
1212

graph/GuidelinesGraph.md

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
Table of contents
44

55
- [Microsoft Graph REST API Guidelines](#microsoft-graph-rest-api-guidelines)
6-
- [](#)
7-
- [History](#history)
86
- [Introduction](#introduction)
97
- [Legend](#legend)
108
- [Design approach](#design-approach)
@@ -15,21 +13,12 @@ Table of contents
1513
- [Query support](#query-support)
1614
- [Behavior modeling](#behavior-modeling)
1715
- [Error handling](#error-handling)
16+
- [Enums](#enums)
1817
- [API contract and non-backward compatible changes](#api-contract-and-non-backward-compatible-changes)
1918
- [Versioning and deprecation](#versioning-and-deprecation)
2019
- [Recommended API design patterns](#recommended-api-design-patterns)
2120
- [References](#references)
2221

23-
##
24-
25-
#### History
26-
27-
| Date | Notes |
28-
|-------------|-----------------------------|
29-
| 2023-Aug-8 | New and updated patterns |
30-
| 2022-Jun-14 | Edit pass for formatting, links |
31-
| 2021-Sep-28 | Using summary and patterns style |
32-
| 2020-Oct-04 | Initial version in Wiki |
3322

3423
## Introduction
3524

@@ -202,6 +191,8 @@ The three most often used patterns in Microsoft Graph today are type hierarchy,
202191

203192
- **[Flat bag of properties](./patterns/flat-bag.md)** is represented by one entity type with all the potential properties plus an additional property to distinguish the variants, often called type. The type property describes the variant and also defines properties that are required or meaningful for the variant given by the type property.
204193

194+
- **[Enums](./patterns/enums.md)** represent a subset of the nominal type they rely on, and are especially useful in cases where certain properties have predefined, limited options.
195+
205196
The following table shows a summary of the main qualities for each pattern and can help you select a pattern fit for your use case.
206197

207198
| API qualities\patterns | Properties and behavior described in metadata | Supports combinations of properties and behaviors | Simple query construction |

graph/patterns/enums.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
### Enums
2+
3+
In OData, enums represent a subset of the nominal type they rely on, and are especially useful in cases where certain properties have predefined, limited options.
4+
5+
```xml
6+
<EnumType Name="color">
7+
<Member Name="Red" Value="0" />
8+
<Member Name="Green" Value="1" />
9+
<Member Name="Blue" Value="2" />
10+
</EnumType>
11+
```
12+
13+
#### Pros
14+
15+
- Our SDK generators will translate the enum to the best representation of the target programming language, resulting in a better developer experience and free client side validation
16+
17+
#### Cons
18+
19+
- Adding a new value requires to go through a (generally fast) API Review
20+
- If the enum is not [evolvable](./patterns/evolvable-enums.md), adding a new value is a breaking change and will generally not be allowed
21+
22+
#### Enum or Booleans
23+
24+
Enumerations are a good alternative to Booleans when one of the two values (`true`, `false`) conveys other possible values not yet conceived. Let's assume we have an `publicNotification` type and a property to communicate how to display it:
25+
26+
```xml
27+
<ComplexType Name="publicNotification">
28+
<Property Name="title" Type="Edm.String" />
29+
<Property Name="message" Type="Edm.String" />
30+
<Property Name="displayAsTip" Type="Edm.Boolean" />
31+
</ComplexType>
32+
```
33+
34+
The `false` value here merely communicates that the notification shall not be displayed as a tip. What if, in the future, the notification could be displayed as a `tip` or `alert`, and then in a more distant future, a `dialog` option is viable?
35+
36+
With the current model, the only way is to add more boolean properties to convey the new information:
37+
38+
```diff
39+
<ComplexType Name="publicNotification">
40+
<Property Name="title" Type="Edm.String" />
41+
<Property Name="message" Type="Edm.String" />
42+
<Property Name="displayAsTip" Type="Edm.Boolean" />
43+
+ <Property Name="displayAsAlert" Type="Edm.Boolean" />
44+
+ <Property Name="displayAsDialog" Type="Edm.Boolean" />
45+
</ComplexType>
46+
```
47+
48+
Additionally speaking, the workload will now also have to validate the data structure and make sure that only one of the 3 values is `true`
49+
50+
By using an evolvable enum, instead, all we need to do is to add new members:
51+
52+
```diff
53+
<ComplexType Name="publicNotification">
54+
<Property Name="title" Type="Edm.String" />
55+
<Property Name="message" Type="Edm.String" />
56+
+ <Property Name="displayMethod" Type="microsoft.graph.displayMethod" />
57+
- <Property Name="displayAsTip" Type="Edm.Boolean" />
58+
- <Property Name="displayAsAlert" Type="Edm.Boolean" />
59+
- <Property Name="displayAsDialog" Type="Edm.Boolean" />
60+
</ComplexType>
61+
```
62+
63+
```xml
64+
<EnumType Name="displayMethod">
65+
<Member Name="tip" Value="0" />
66+
<Member Name="unknownFutureValue" Value="1" />
67+
<Member Name="alert" Value="2" />
68+
<Member Name="dialog" Value="3" />
69+
</EnumType>
70+
```
71+
72+
Similarly speaking, if you find yourself using a `nullable` Enum, that is a indication that maybe what you are trying to model is something that has 3 states and an enum is more appropraite. For instance, let's assume we have a boolean property called `syncEnabled`, where `null` means that the value is undefined and inherited from the general tenant configuration. Instead of modelling like a boolean:
73+
74+
```xml
75+
<Property Name="syncEnabled" Type="Edm.Boolean" Nullable="true"/>
76+
```
77+
78+
An enum not only better conveys the message:
79+
80+
```xml
81+
<EnumType Name="syncState">
82+
<Member Name="enabled" Value="0" />
83+
<Member Name="disabled" Value="1" />
84+
<Member Name="tenantInherit" Value="2" />
85+
<Member Name="unknownFutureValue" Value="3" />
86+
</EnumType>
87+
```
88+
89+
but it is also open for future scenarios:
90+
91+
```diff
92+
<EnumType Name="syncState">
93+
<Member Name="enabled" Value="0" />
94+
<Member Name="disabled" Value="1" />
95+
<Member Name="tenantInherit" Value="2" />
96+
<Member Name="unknownFutureValue" Value="3" />
97+
+ <Member Name="groupInherit" Value="4" />
98+
</EnumType>
99+
```
100+
101+
Additionally speaking, depending on the situation, a nullable enum can very likely be avoided by adding a `none` member.
102+
103+
#### Flag Enums or Collection of Enums
104+
105+
In case an enum can have multiple values at the same time the tentation is to model the property as a collection of Enums:
106+
107+
```xml
108+
<Property Name="displayMethods" Type="Collection(displayMethod)"/>
109+
```
110+
111+
However, [Flagged Enums](https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html#_Toc38530378) can model this use case scenario:
112+
113+
```diff
114+
- <EnumType Name="displayMethod">
115+
+ <EnumType Name="displayMethod" isFlag="true">
116+
- <Member Name="tip" Value="0" />
117+
+ <Member Name="tip" Value="1" />
118+
- <Member Name="unknownFutureValue" Value="1" />
119+
+ <Member Name="unknownFutureValue" Value="2" />
120+
- <Member Name="alert" Value="2" />
121+
+ <Member Name="alert" Value="4" />
122+
- <Member Name="dialog" Value="3" />
123+
+ <Member Name="dialog" Value="8" />
124+
</EnumType>
125+
```
126+
127+
With such enum, customers can select multiple values in a single field:
128+
129+
`displayMethod = tip | alert`

graph/patterns/evolvable-enums.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Microsoft Graph API Design Pattern
44

55
*The evolvable enums pattern allows API producers to extend enumerated types with new members without breaking API consumers.*
66

7+
Note: You might be interested in reading the [Enum guidance](./enums.md) first
8+
79
## Problem
810

911
Frequently API producers want to add new members to an enum type after it is initially published. Some serialization libraries might fail when they encounter members in an enum type that were added after the serialization model was generated. In this documentation, we refer to any added enum members as unknown.

0 commit comments

Comments
 (0)