Skip to content

Commit

Permalink
Merge pull request #1 from stakater/develop
Browse files Browse the repository at this point in the history
first release of handbook
  • Loading branch information
kahootali authored Nov 30, 2018
2 parents a5d68b9 + 9f7afe3 commit 13ed451
Show file tree
Hide file tree
Showing 28 changed files with 8,016 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
.vuepress/dist/
.DS_Store
.vscode
.idea
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM stakater/pipeline-tools:1.15.0

LABEL name="Stakater Developer Handbook" \
maintainer="Stakater <[email protected]>" \
vendor="Stakater" \
release="1" \
summary="Developer Handbook"

WORKDIR $HOME/application

# copy the entire application
COPY application/ .

# install yarn globaly
RUN npm install -g yarn

# download the application dependencies
RUN yarn install

# build the application
RUN yarn run build

ENTRYPOINT ["yarn", "run", "serve"]
5 changes: 5 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env groovy
@Library('github.com/stakater/[email protected]') _

appWithDockerfileBuildRelease {
}
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CHART_NAME ?= developer-handbook
NAMESPACE_NAME ?= tools
RELEASE_NAME ?= $(NAMESPACE_NAME)-$(CHART_NAME)

install-chart:
helm upgrade --install --wait --force --recreate-pods $(RELEASE_NAME) deployments/kubernetes/chart/$(CHART_NAME) --namespace $(NAMESPACE_NAME) || (helm rollback --force --recreate-pods $(RELEASE_NAME) 0 ; exit 1)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# developer-handbook

A developer handbook!

Check application/README.md for how to run the application.
46 changes: 46 additions & 0 deletions application/.vuepress/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module.exports = {
title: 'Developer Handbook',

head: [
['link', { rel: 'icon', href: '/favicon.png' }]
],

themeConfig: {
sidebar: [
'/',
{
title: 'Architecture',
children: [
'/architecture/ddd',
'/architecture/rest',
'/architecture/microservices/',
]
},
{
title: 'Java Backend',
children: [
'/java-backend/',
'/java-backend/datetime',
]
},
{
title: 'Database',
children: [
'/database/',
]
},
{
title: 'API',
children: [
'/api/naming',
'/api/resources',
'/api/request-response',
]
}
],

repo: 'stakater/developer-handbook',
editLinks: true,
editLinkText: 'Help us improve this page!'
}
}
Binary file added application/.vuepress/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions application/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# developer-handbook

A developer handbook!

Local development

## MacOS

All dependencies for the developer handbook is handled with yarn.

```
# install nodejs with brew
brew install node
# install yarn with npm
npm install -g yarn
# install dependencies with yarn
yarn
# start local development server
yarn run dev
```
Empty file added application/api/README.md
Empty file.
65 changes: 65 additions & 0 deletions application/api/naming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# API Naming

Here are the API naming conventions we must follow:

## MUST: Use lowercase separate words with hyphens for Path Segments

Example:

```
/purchase-orders/{purchase-order-id}
```

This applies to concrete path segments and not the names of path parameters. For example `{purchase_order_id}` would be ok
as a path parameter.

## MUST: Use snake_case (never camelCase) for Query Parameters

Examples:

```
customer_number, order_id, billing_address
```

## MUST: Use Hyphenated HTTP Headers

## MUST: Pluralize Resource Names

Usually, a collection of resource instances is provided (at least API should be ready here). The special case of a
resource singleton is a collection with cardinality 1.

## MUST: Avoid Trailing Slashes

The trailing slash must not have specific semantics. Resource paths must deliver the same results whether they have the trailing slash or not.

## MUST: Use Conventional Query Strings

If you provide query support for sorting, pagination, filtering functions or other actions, use the following standardized naming conventions:

- `q` — default query parameter (e.g. used by browser tab completion); should have an entity specific alias, like sku
- `limit` — to restrict the number of entries. See Pagination section below. Hint: You can use size as an alternate query string.
- `cursor` — key-based page start. See Pagination section below.
- `offset` — numeric offset page start. See Pagination section below. Hint: In combination with limit, you can use page as an alternative to offset.
- `sort` — comma-separated list of fields to sort. To indicate sorting direction, fields my prefixed with + (ascending) or - (descending, default), e.g. /sales-orders?sort=+id
- `fields` — to retrieve a subset of fields.
- `embed` — to expand embedded entities (ie.: inside of an article entity, expand silhouette code into the silhouette object). Implementing “expand” correctly is difficult, so do it with care.

## SHOULD: Prefer Hyphenated-Pascal-Case for HTTP header Fields

This is for consistency in your documentation (most other headers follow this convention). Avoid camelCase (without hyphens). Exceptions are common abbreviations like “ID.”

Examples:

```
Accept-Encoding
Apply-To-Redirect-Ref
Disposition-Notification-Options
Original-Message-ID
```

See also: [HTTP Headers are case-insensitive (RFC 7230)](http://tools.ietf.org/html/rfc7230#page-22).

## COULD: Use Standardized Headers

Use [this list](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields) and mention its support in your OpenAPI definition.

29 changes: 29 additions & 0 deletions application/api/request-response.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Request & Response Classes

Here is the naming convention for API request (command) and response (query) classes to follow:

e.g.

- Request/Command: ApiCreateVehicleRequest or ApiCreateVehicleCommand or CreateVehicleCommand
- Response: ApiVehicle or ApiVehicleResponse

Why separate classes; why not just ONE jumbo class:

- You want to modify the model object or the request object independent of each other.
- Separation of concerns. Your request class ApiCreateVehicleRequest may contain all kinds of interface/protocol
related annotations and members (e.g. validation annotations that the JAX-RS implementation knows how to enforce).
These interface-related annotations should not be in the model object.
- From an OO perspective ApiCreateVehicleRequest is not a Vehicle (not IS_A) nor does it contain a vehicle.
- You might have some internal fields which shouldn't be exposed; e.g. entity id won't exist at create time but will be
returned at response API calls

Now to the question asked... What should be the relationship between the requests and response classes?

Request classes should extend from request classes and not extend nor contain response classes, and vice versa. Usually
you have a very basic BaseRequest class, extended by something like CreateRequest, UpdateRequest, etc... where
properties common to all create requests are in CreateRequest which is then extended by more specific request classes
such as CreateVehicleRequest...

Similarly, but parallel to it, the is the Response class hierarchy.

[Reference](https://stackoverflow.com/a/48450483)
55 changes: 55 additions & 0 deletions application/api/resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Resources

## MUST: Avoid Actions — Think About Resources
REST is all about your resources, so consider the domain entities that take part in web service interaction, and aim to model your API around these using the standard HTTP methods as operation indicators. For instance, if an application has to lock articles explicitly so that only one user may edit them, create an article lock with PUT or POST instead of using a lock action.

Request:

```
PUT /recipes/{recipe-id}
```

The added benefit is that you already have a service for browsing and filtering article locks.

## MUST: Keep URLs Verb-Free
The API describes resources, so the only place where actions should appear is in the HTTP methods. In URLs, use only nouns.

## MUST: Use Domain-Specific Resource Names
API resources represent elements of the application’s domain model. Using domain-specific nomenclature for resource names helps developers to understand the functionality and basic semantics of your resources. It also reduces the need for further documentation outside the API definition. For example, "purchase-order-items" is superior to "purchase-items" in that it clearly indicates which business object it represents. Along these lines, “items” is too general.

## MUST: Identify resources and Sub-Resources via Path Segments
Basic URL structure:

```
/{resources}/[resource-id]/{sub-resources}/[sub-resource-id]
```

Examples:

```
/orders/1681e6b88ec1/items
/orders/1681e6b88ec1/items/1
```

## SHOULD: Define useful resources
As a rule of thumb resources should be defined to cover 90% of all its client's use cases. A useful resource should contain as much information as necessary, but as little as possible. A great way to support the last 10% is to allow clients to specify their needs for more/less information by supporting filtering and embedding.

## COULD: Consider Using (Non-) Nested URLs
If a sub-resource is only accessible via its parent resource and may not exists without parent resource, consider using a nested URL structure, for instance:

```
/orders/1681e6b88ec1/items/1
```

However, if the resource can be accessed directly via its unique id, then the API should expose it as a top-level resource. For example, customer is a collection for sales orders; however, sales orders have globally unique id and some services may choose to access the orders directly, for instance:

```
/customers/1681e6b88ec1
/orders/5273gh3k525a
```

## SHOULD: Limit number of Resources
To keep maintenance and service evolution manageable, we should follow "functional segmentation" and "separation of concern" design principles and do not mix different business functionalities in same API definition. In this sense the number of resources exposed via API should be limited - our experience is that a typical range of resources for a well-designed API is between 4 and 8. There may be exceptions with more complex business domains that require more resources, but you should first check if you can split them into separate subdomains with distinct APIs.

## SHOULD: Limit number of Sub-Resource Levels
There are main resources (with root url paths) and sub-resources (or “nested” resources with non-root urls paths). Use sub-resources if their life cycle is (loosely) coupled to the main resource, i.e. the main resource works as collection resource of the subresource entities. You should use <= 3 sub-resource (nesting) levels -- more levels increase API complexity and url path length. (Remember, some popular web browsers do not support URLs of more than 2000 characters)
Loading

0 comments on commit 13ed451

Please sign in to comment.