Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Architectural Decision Records #5360

Merged
merged 4 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/close_stale_pr_and_issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ jobs:
days-before-stale: 90
days-before-close: 30
operations-per-run: 260
exempt-issue-labels: 'Roadmap'
exempt-issue-labels:
- 'Roadmap'
- 'ADR'
ascending: true
94 changes: 94 additions & 0 deletions ADRs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Architectural Decision Records (ADRs)

An Architectural Decision (AD) is a justified software design choice that addresses a functional or
non-functional requirement that is architecturally significant. ([adr.github.io](https://adr.github.io/))

## Process

Architectural decisions we make in the developer meetings are recorded here. If the decision is
small and uncontroversial, but yet important and can be expressed in maximum 2 sentences, we will
list it here without any reference. If the decision require a bit more discussion and explanations
an issue on GitHub should be created - use the template below.

### How to discuss and document an Architectural Decision

- [Create a new issue](https://github.com/opentripplanner/OpenTripPlanner/issues/new/choose?template=adr.md)
using the [ADR.md](https://github.com/opentripplanner/OpenTripPlanner/blob/dev-2.x/ISSUE_TEMPLATE/ADR.md)
template.
- Make sure to update the main description based on the feedback/discussion and decisions in the
developer meeting.
- The final approval is done in the developer meeting, at least 3 developers representing 3
different organisations should approve - and no vote against the proposal. If the developers
are not able to agree the PLC can decide.
- Add the ADR to the list below. Maximum two sentences should be used - try to keep it as short as
possible. Remember to link to the discussion.
- References to Architectural Decision Records in reviews can be done by linking or just typing
e.g. `ADR2`. Use the `[ADR1]()`


## Records

### ADR-0 Scout rule
Leave Things BETTER than you found them - clean up code you visit or/and add unit
tests. Expect to include some code cleanup as part of all PRs.

### ADR-1 Naming
[Follow naming conventions](CODE_CONVENTIONS.md#naming-conventions) . Make sure the
code is easy to read and understand.

### ADR-2 Code documentation - JavaDoc
Document the business intention and decisions in the relevant code. Do not repeat the logic
expressed in the code. The prefered way is to use JavaDoc, you may have to refactor part of your
code to encapsulate the business logic into a method or class to do this.

> If you decide to NOT follow an Architectural Decision, then expect to document why.

**See also**
- [Developers-Guide > Code comments](docs/Developers-Guide.md#code-comments).
- [Codestyle > Javadoc Guidlines](docs/Codestyle.md#javadoc-guidlines) - JavaDoc checklist

### ADR-3 Code style
OTP uses prettier to format code. For more information on code style see the
[Codestyle](docs/Codestyle.md) document.

### ADR-4 OOP
Respect Object-Oriented principals
- Honer encapsulation & Single-responsibility principle
- Abstraction - Use interfaces when a module need "someone" to play a role
- Inheritance - Inheritances expresses “is-a” and/or “has-a” relationship, do not use it "just"
to share data/functionality.
- Use polymorphism and not `instanceof`.

### ADR-5 Dependency injection
Use dependency injection to wire components. You can use manual DI or Dagger. Put the
wiring code in `<module-name>/configure/<Module-name>Module.java`.

### ADR-6 Module encapsulation
Keep modules clean. Consider adding an `api`, `spi` and mapping code to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word "clean" here could have many interpretations, and even conflicting interpretations by different people. It may be effectively equivalent to "keep code good". A reader might not know if the following two points are elucidating the meaning of "clean" or if they are in addition to cleanness.

isolate the module from the rest of the code. Avoid circular dependencies between modules.

### ADR-7 JavaDoc
Document all `public` types, methods and fields.

### ADR-8 API doc
Document API and configuration parameters.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't ADR-7 and 8 associated to ADR-2?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think 7 and 8 could be merged into 2. Also, 8 does not specify whether we are talking about JavaDoc and could be interpreted as manual documentation in some other file.


### ADR-9 DRY
Keep the code [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) - Do not
repeat yourself. Avoid implementing the same business rule in two places -> refactor.

### ADR-10 Feature envy
[Feature envy](https://refactoring.guru/smells/feature-envy)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This design decision just states the name of a problem. It should be rephrased to state that this problem should be avoided and how to do so. The linked document contains detailed suggestions on how to avoid or eliminate the problem, but the ADR item does not mention this.

Also, as mentioned on a comment below, the distinction between code style and architectural decisions does not seem clear.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think we should repeat something that is better documented elsewhere, but we should express it as a sentence: "Respect/Follow/Avoid Feature envy".


### ADR-11 Test coverage
All business logic should have unit tests. Keep integration/system tests to a
minimum. Add test at the lowest level practical to test the business feature. Prefer unit tests on
a method over a class, over a module, over the system.

### ADR-12 Immutable types
Prefer immutable types over mutable. Use builders where appropriate. See
[Records, POJOs and Builders](CODE_CONVENTIONS.md#records-pojos-and-builders)

### ADR-13 Records
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of these Architectural Decisions could be seen as code conventions and overlap with https://github.com/opentripplanner/OpenTripPlanner/blob/dev-2.x/CODE_CONVENTIONS.md. For example, use of records is specifically discussed in the code conventions document. Do we have guidelines on what is a code convention and what is an architectural decision? This could be important for both writers and readers to avoid redundancy and inconsistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we break code conventions into smaller pieces and list them in "ADRs", we could also try to break the ADR list up into more than one list (using separate prefixes).

[Avoid using records if you can not encapsulate it properly](CODE_CONVENTIONS.md#records)

6 changes: 5 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OTP Architecture

OTP is developed over more than 10 years, and most of the design documentation is in the code as
OTP is developed over more than 15 years, and most of the design documentation is in the code as
comments and JavaDoc. Over the years the complexity have increased, and the natural developer
turnover creates a demand for more architecture and design documentation. The new OTP2 documentation
is put together with the source; hopefully making it easier to maintain. Instead of documenting
Expand All @@ -11,6 +11,10 @@ This document is far from complete - hopefully it can evolve over time and becom
introduction to OTP architecture. The OTP project GitHub issues are a good place to look for
detailed discussions on many design decisions.

We document Architectural Decision in a log. Make sure you as a developer is familiar with the
decisions and follow them. Reviewers should use them actively when reviewing code and may use them
to ask for changes.

Be sure to also read the [developer documentation](docs/Developers-Guide.md).

## Modules/Components
Expand Down
25 changes: 9 additions & 16 deletions CODE_CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,6 @@ These conventions are not "hard" rules, and often there might be other forces wh
decision in another direction, in that case documenting your choice is often enough to pass the
review.

## Best practices - in focus

- [ ] Document `public` interfaces, classes and methods - especially those part of a module api.
- [ ] Leave Things BETTER than you found them - clean up code you visit or/and add unit tests.
- [ ] [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) - Do not repeat yourself. Avoid implementing the same business rule in two places -> refactor.
- [ ] [Feature envy](https://refactoring.guru/smells/feature-envy)
- [ ] Make types immutable if possible. References to other Entities might need to be mutable, if
so try to init them once, and throw an exception if set again.
Example:

```java
Builder initStop(Stop stop) {
this.stop = requireNotInitialized(this.stop, stop);
}
```

## Naming Conventions

Expand Down Expand Up @@ -104,7 +89,15 @@ stop = stop.copyOf().withPrivateCode("TEX").build();
## Records, POJOs and Builders

We prefer immutable typesafe types over flexibility and "short" class definitions. This make
the code more robust and less error-prune.
the code more robust and less error-prune. References to other entities might need to be mutable,
if so try to init them once, and throw an exception if set again. Example:

```java
Builder initStop(Stop stop) {
this.stop = requireNotInitialized(this.stop, stop);
}
```


### Records

Expand Down
32 changes: 32 additions & 0 deletions ISSUE_TEMPLATE/ADR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


### Description
*One or two sentences witch goes into the [Architectural Decision Records](../ADRs.md) document
later*

### Context and Problem Statement
*Describe the context and problem statement, e.g., in free form using two to three sentences. You
may want to articulate the issue in form of a question*

### Other options

-

### Decision & Consequences
Describes the effects of the change. What becomes easier? What will be more difficult?

#### Positive Consequences

-

#### Negative Consequences

-

#### Checklist
- [ ] Tag issue with `ADR`.
- [ ] Give it a meaningful title that quickly lets the reader understand what this ADR is all about.
- [ ] Approved in a developer meeting with 3 votes in favor (3 organisations)
- [ ] This issue description is up-to-date with the discussion below.
- [ ] The name and description is added to the
[Architectural Decision Records](../ADRs.md) document and the ADR is linked this issue.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

/**
* Repository for Stop entities.
*
* ARCHITECTURAL_DECISION_RECORDS.md
*/
public class StopModel implements Serializable {

Expand Down