Skip to content

Commit 90402fa

Browse files
author
Phil Peble
committed
[issue-24] Reorganize documentation into doc/ and add ADR for custom methods change
1 parent 8e89255 commit 90402fa

File tree

7 files changed

+127
-31
lines changed

7 files changed

+127
-31
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Holiday definitions
22

3+
## 3.0.0
4+
5+
Major semver bump as the format for custom methods has been changed to complete [issue-24](https://github.com/holidays/definitions/issues/24). Downstream consumers will need to update to be able to parse them. However there are **no behavior changes** with this update.
6+
7+
In summary: we have switched to language-specific custom methods. Instead of a plain `source` field you will need a specific language implementation, e.g. `ruby`, `golang`, etc.
8+
9+
Currently we only have `ruby` but we can now expand these definitions for use in other languages. Please see the [custom methods ADR](doc/architecture/adr-001.md) for more in-depth information on why this change was made.
10+
11+
You can also view the updated ['Methods' section in the SYNTAX doc](doc/SYNTAX.md#methods) for more info and examples.
12+
313
## 2.5.3
414

515
* Add missing `observed` logic for 'St. Patricks Day' in `gb_nir`

README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@ Currently it is only used by the [existing Holidays gem](https://github.com/holi
77
definitions and generates ruby classes for use in that gem. In the future it will be used by other languages in
88
a similar manner.
99

10-
*Please note* that this is *not* a gem. The validation process is written in ruby simply for convenience. The real
10+
**Please note** that this is _not_ a gem. The validation process is written in ruby simply for convenience. The real
1111
stars of this show are the YAML files.
1212

13-
### Syntax
13+
### Documentation
1414

15-
The definition syntax is a custom format developed over the life of this project. Please see
16-
[our syntax doc](SYNTAX.md) for more information on how to format definitions.
17-
18-
### How to contribute
19-
20-
See our [contribution guidelines](CONTRIBUTING.md) for information on how to help out!
15+
1. [Syntax Guide](doc/SYNTAX.md)
16+
2. [Contribution Guidelines](doc/CONTRIBUTING.md)
17+
3. [Maintainer Guidelines](doc/MAINTAINERS.md)
18+
4. [Architecture Decision Records](doc/architecture/README.md)
2119

2220
### Credits
2321

CONTRIBUTING.md renamed to doc/CONTRIBUTING.md

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ In this repository we have all of the definitions that are used in holiday calcu
66

77
Please read our [Code of Conduct](https://github.com/holidays/holidays/blob/master/CODE_OF_CONDUCT.md) before contributing. Everyone interacting with this project (or associated projects) is expected to abide by its terms.
88

9-
## For definition updates
9+
## Definition Updates
1010

11-
Our definitions are written in YAML. You can find a complete guide to our format in the [README](README.md). We take the YAML definitions and generate final definition files in the various projects
12-
that are loaded at runtime for fast calculations.
11+
Our definitions are written in YAML. You can find a complete guide to our format in the [syntax docs](SYNTAX.md). We take the YAML definitions and generate final definition files in the various projects that are loaded at runtime for fast calculations.
1312

1413
Here are the steps to take once you have a good idea on what you want to change:
1514

@@ -18,8 +17,7 @@ Here are the steps to take once you have a good idea on what you want to change:
1817
* Run `make validate` to ensure that all updates match our definition format
1918
* Open a PR with your changes
2019

21-
Including documentation with your updates is very much appreciated. A simple Wikipedia entry or government link in the
22-
comments alongside your changes would be perfect.
20+
Including documentation with your updates is very much appreciated. A simple Wikipedia entry or government link in the comments alongside your changes would be perfect.
2321

2422
Lastly, note that there are many 'meta' regions. For example, there are regions for Europe, Scandinavia, and North America. If your new region(s) falls into these areas consider adding them. You can find these 'meta' regions in `definitions/index.yaml`.
2523

@@ -29,12 +27,8 @@ Don't worry about versioning, we'll handle it on our end.
2927

3028
## Definition Validation
3129

32-
We maintain a `make validate` command to ensure that all YAML definitions match our internal specifications. This is to make
33-
working with this repository as independent as possible from the other repositories (like the existing ruby repository). If
34-
`make validate` passes then we ensure that anything consuming these files will receive 'correct' formats.
30+
We maintain a `make validate` command to ensure that all YAML definitions match our internal specifications. This is to make working with this repository as independent as possible from the other repositories (like the existing ruby repository). If `make validate` passes then we ensure that anything consuming these files will receive 'correct' formats.
3531

36-
If you run into any weird `make validate` errors please open an issue or PR and highlight to what you are seeing. The
37-
validation code is brand-new and might have issues. Maintainers will respond quickly to any open problems.
32+
If you run into any weird `make validate` errors please open an issue or PR and highlight to what you are seeing. The validation code is brand-new and might have issues. Maintainers will respond quickly to any open problems.
3833

39-
If you would like to add to, update, or otherwise fix any of our specs then please fork and submit a PR like you would any
40-
other change. Please note that we require 100% test coverage. Your builds will not pass if you fall below 100%.
34+
If you would like to add to, update, or otherwise fix any of our specs then please fork and submit a PR like you would any other change. Please note that we require 100% test coverage. Your builds will not pass if you fall below 100%.

MAINTAINERS.md renamed to doc/MAINTAINERS.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,8 @@ will need to investigate further (contact a core member for assistance).
3232
that has the new version and associated changes. This is pretty open-ended! Include the information that you feel is
3333
important. Use past CHANGELOG updates as a guide.
3434
* Open a PR against the CHANGELOG branch and merge it (this may require another maintainer for safety)
35-
* Once the updated CHANGELOG is merged, go to the [releases](https://github.com/holidays/definitions/blob/master/CHANGELOG.md) page
36-
and create a new release. The release should point at the latest commit that contains the changes that you want included in
37-
this release. If you just merged then you can just point at master. All release versions follow this
38-
format: `vMAJOR.MINOR.PATCH`. This follows the normal [semver](https://github.com/holidays/definitions/blob/master/CHANGELOG.md)
39-
rules. Look at recent releases to figure out what the new version should be.
35+
* Once the updated CHANGELOG is merged, go to [releases](https://github.com/holidays/definitions/releases) and create a new release. It should point at the latest commit that contains the changes that you want included in this release. If you just merged then you can just point at master. All release versions follow this format: `vMAJOR.MINOR.PATCH`. This should follow normal [semver rules](https://semver.org/).
4036

41-
You don't need to list out the specific changes that were made on the release, you can just give a general overview. You can link to the
42-
updated CHANGELOG that you did in a previous step. Example: [v2.2.0](https://github.com/holidays/definitions/releases/tag/v2.2.0)
37+
You don't need to list out the specific changes that were made on the release description. You can just give a general overview and then link to the updated CHANGELOG that you did in a previous step. Example: [v2.2.0](https://github.com/holidays/definitions/releases/tag/v2.2.0)
4338

44-
Once the release is created in Github you are done! The definitions have been 'released' and downstream projects (right now just ruby)
45-
can reference them without issues. See the downstream maintainers guides for information on how to release updates.
39+
Once the release is created in Github you are done! The definitions have been 'released' and downstream projects (right now just ruby) can reference them without issues. See the maintainers guides in downstream projects for information on how to release updates for each language.

SYNTAX.md renamed to doc/SYNTAX.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Holiday Gem Definition Syntax
1+
# Holiday Definition Syntax
22

3-
All holidays are defined in these YAML files. These definition files have three main top-level properties:
3+
The definition syntax is a custom format developed over the life of this project. All holidays are defined in these YAML files. These definition files have three main top-level properties:
44

55
* `months` - this is the meat! All definitions for months 1-12 are defined here
66
* `methods` - this contains any custom logic that your definitions require

doc/architecture/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Architecture Decision Records
2+
3+
Here we document decisions we made regarding high level architecture/design of this repository.
4+
5+
For details on what ADR is and why it's important, please reference the following blog posts:
6+
7+
- https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0
8+
- http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
9+
10+
Please note that we only began keeping ADRs for this project in October of 2018. Decisions made before that are not covered.
11+
12+
## Table of contents
13+
14+
1. [Language specific custom methods](adr-001.md)

doc/architecture/adr-001.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# ADR 1: Custom Methods Format Change
2+
3+
## Context
4+
5+
We would like these definitions to be usable by any language. The original `holidays` project was written purely in `ruby` but the definitions were generally plain `YAML`.
6+
7+
The issue is that `ruby` has been sprinkled into the otherwise plain `YAML` when it made sense with no plan for use outside of `ruby`. This makes sense when you are never planning on using the `YAML` files in other languages.
8+
9+
Over time we have [been working](https://github.com/holidays/definitions/issues/7) to make the syntax more generic so that other language implementations could consume them. The last hurdle was custom methods.
10+
11+
An example of the original format:
12+
13+
```yaml
14+
methods:
15+
ca_victoria_day:
16+
arguments: year
17+
source: |
18+
date = Date.civil(year, 5, 24)
19+
if date.wday > 1
20+
date -= (date.wday - 1)
21+
elsif date.wday == 0
22+
date -= 6
23+
end
24+
25+
date
26+
```
27+
28+
As you can see the actual function is just plain `ruby`.
29+
30+
After lots of trial and error I have decided that I cannot see a generic format for this logic that would satisfy all use cases for existing custom methods in our definitions. While some custom methods are relatively simple `if/else` statements there are many that are much more complicated.
31+
32+
An example of a 'complicated' custom method from the `ch` (Swiss) region:
33+
34+
```yaml
35+
ch_vd_lundi_du_jeune_federal:
36+
# Monday after the third Sunday of September
37+
arguments: year
38+
ruby: |
39+
date = Date.civil(year,9,1)
40+
# Find the first Sunday of September
41+
until date.wday.eql? 0 do
42+
date += 1
43+
end
44+
# There are 15 days between the first Sunday
45+
# and the Monday after the third Sunday
46+
date + 15
47+
```
48+
49+
The logic itself is not hard to follow but coming up with a generic way to phrase this seems like a complex problem. Every attempt that was made devolved into very complex parsers of nested `YAML` so that we correctly handled each new edge case that appeared. It was very slow going and the complexity was growing and growing.
50+
51+
Additionally, having a complex `YAML` syntax for custom methods would require each downstream repository to implement the 'standard'. That seems pretty scary to think about maintaining.
52+
53+
The other option is to just make each future language provide their own implementations.
54+
55+
## Decision
56+
57+
The decision is to simply require language-specific implementations of custom methods. Since all custom methods are currently in `ruby` we are changing every `source` field to `ruby`. In the future new languages will need to provide their own implementations. For example, we could add a `golang` or `swift` section next to the existing `ruby` section.
58+
59+
There are three significant advantages:
60+
61+
- It is very easy to understand
62+
- All holidays using custom methods have tests so each downstream project will have built-in protection in case a bug is introduced in only one language implementation
63+
- It is very easy to implement for the current `ruby` implementation (which is our only project currently)
64+
65+
There are significant downsides:
66+
67+
- Possible divergence between languages due to separate implementations, causing confusion and frustration
68+
- More pressure on maintainers to handle the various implementations, ensuring they can build without issues when new custom methods are added
69+
- Confusion for new contributors who may only be comfortable in a single language
70+
- New downstream languages will have a higher hurdle to overcome since they will need to implement the existing logic in their own language
71+
72+
In the end I don't want to hold things up because of _possible_ new language implementations that might show up in the future. I personally want to create a new `golang` version of `holidays` but beyond that maybe no one else will consume these definitions!
73+
74+
If the `holidays` projects become wildly popular in the future and this becomes a huge problem then I can address it with the (presumably huge) community to find a solution.
75+
76+
## Consequences
77+
78+
We might lose contributions due to confusion or fear.
79+
80+
We might burn out maintainers if the juggling of languages becomes too much of a burden.
81+
82+
This puts more pressure for the completion of an updated [test framework](https://github.com/holidays/definitions/issues/42) for downstream repositories.
83+
84+
## Status
85+
86+
Accepted.

0 commit comments

Comments
 (0)