Skip to content

Commit 51f51bf

Browse files
authored
Merge pull request #1853 from bibonix/architecture-section
Add Architecture section to README.md
2 parents 705726a + 234ba79 commit 51f51bf

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,95 @@ public class FooTest {
109109
}
110110
```
111111

112+
## Architecture
113+
114+
The library maps every GitHub API concept to a Java interface
115+
(`GitHub`, `Repo`, `Issue`, `Comment`, etc.) with two
116+
complete parallel implementations: `Rt*` classes talk to
117+
the live [GitHub REST API](https://docs.github.com/en/rest),
118+
while `Mk*` classes provide an in-memory mock server.
119+
Unlike [github-api](https://github.com/hub4j/github-api),
120+
which ships only a real HTTP implementation,
121+
jcabi-github delivers both under the same interface
122+
hierarchy, so test code and production code share the same API.
123+
New programmers should use `RtGitHub` in production and
124+
`MkGitHub` in tests — no mocking framework is needed.
125+
126+
Each interface contains a static inner class `Smart`
127+
(e.g., `Issue.Smart`, `Comment.Smart`) that wraps the
128+
core interface and exposes convenience methods such as
129+
`isOpen()`, `author()`, and `close()`.
130+
The base interface holds only identity accessors and
131+
[JSON](https://www.json.org/json-en.html) I/O methods,
132+
following the
133+
[decorator pattern](https://refactoring.guru/design-patterns/decorator)
134+
as advocated by
135+
[Elegant Objects](https://www.elegantobjects.org/).
136+
New programmers should reach for `Issue.Smart` rather than
137+
raw `Issue` when reading human-friendly properties.
138+
139+
Every domain object implements `JsonReadable` (one `json()`
140+
method) and `JsonPatchable` (one `patch()` method).
141+
There is no ORM or intermediate object mapping: the
142+
[JSON](https://www.json.org/json-en.html) document from
143+
the REST endpoint is the canonical state, with typed
144+
extraction handled by `SmartJson`.
145+
Unlike [Jackson](https://github.com/FasterXML/jackson)-based
146+
libraries that map JSON to POJOs eagerly, each `json()`
147+
call here is a live HTTP round trip.
148+
New programmers must not assume property reads are cheap;
149+
wrap collections in `Bulk<T>` to avoid N+1 requests.
150+
151+
`RtPagination<T>` lazily follows
152+
[`Link` headers](https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api)
153+
(`rel="next"`) to traverse GitHub's paginated responses.
154+
Without `Bulk<T>`, each item triggers a separate HTTP call
155+
when its properties are first read.
156+
`Bulk<T>` pre-injects JSON from the listing response into
157+
each item, collapsing those N+1 requests into the minimum
158+
number of page fetches.
159+
New programmers must wrap `iterate()` results in
160+
`new Bulk<>(...)` when iterating large collections.
161+
162+
HTTP cross-cutting concerns — rate-limiting, retries, and
163+
redirects — are composed by stacking `Wire` decorators
164+
from [jcabi-http](https://http.jcabi.com/) on the entry
165+
`Request` via `.through()`.
166+
`CarefulWire` reads `X-RateLimit-Remaining` and sleeps
167+
until `X-RateLimit-Reset` to stay within GitHub's quota
168+
rather than failing with HTTP 429.
169+
Unlike interceptor-based clients such as
170+
[OkHttp](https://square.github.io/okhttp/) or
171+
[Apache HttpClient](https://hc.apache.org/httpcomponents-client-5.4.x/index.html),
172+
each behavior here is a standalone immutable class.
173+
New programmers should implement `Wire` and call `.through()`
174+
to add custom HTTP behavior.
175+
176+
The `Mk*` mock stores all state in a single
177+
[XML](https://www.w3.org/XML/) document inside `MkStorage`,
178+
mutated via [Xembly](https://github.com/yegor256/xembly)
179+
directives and queried with
180+
[XPath](https://www.w3.org/TR/xpath-31/).
181+
Unlike HTTP-replay tools such as
182+
[WireMock](https://wiremock.org/) or
183+
[MockServer](https://www.mock-server.com/), state is shared
184+
and consistent across the entire object graph: an issue
185+
created via `MkIssues` is immediately visible via `MkRepo`.
186+
New programmers can rely on cross-object consistency inside
187+
one `MkGitHub` instance but must not expect the mock to
188+
validate payloads against the live GitHub API schema.
189+
190+
All classes carry the `@Immutable` annotation from
191+
[jcabi-aspects](https://aspects.jcabi.com/), enforced by
192+
[AspectJ](https://eclipse.dev/aspectj/) at Maven build time.
193+
No class has setters or mutable fields; the build fails
194+
if any are added.
195+
This contrasts with builder-style libraries such as
196+
[github-api](https://github.com/hub4j/github-api) that
197+
rely on mutable state.
198+
New programmers must construct new objects rather than
199+
modifying existing ones.
200+
112201
## How to contribute?
113202

114203
Fork the repository, make changes, submit a pull request.

0 commit comments

Comments
 (0)