Skip to content

Commit 50f2a71

Browse files
committed
chore: documentation and CI updates
1 parent 974b90c commit 50f2a71

File tree

11 files changed

+196
-33
lines changed

11 files changed

+196
-33
lines changed

.github/workflows/build.yml

+4-12
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ on:
1111
- cron: 0 2 * * 1-5
1212

1313
jobs:
14-
build:
14+
test:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
fail-fast: false
1818
matrix:
1919
ruby:
2020
- 2.5.x
2121
- 2.6.x
22-
# - 2.7.x
22+
- 2.7.x
2323
steps:
2424
- uses: actions/checkout@v1
2525
- name: Set up Ruby
@@ -32,15 +32,7 @@ jobs:
3232
run: sudo apt-get install hunspell
3333
- name: Install Deps
3434
run: bundle install --jobs 4 --retry 3
35-
- name: Rubocop
36-
run: bundle exec rake rubocop
37-
- name: Reek
38-
run: bundle exec rake reek
39-
- name: RSpec
35+
- name: Test
4036
env:
4137
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
42-
run: bundle exec rake spec
43-
- name: Spelling Check (docs & code)
44-
run: bundle exec rake spellcheck
45-
- name: Markdown Linter (docs)
46-
run: bundle exec rake mdl
38+
run: bundle exec rake

.rubocop.yml

+4
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,7 @@ Style/CaseEquality:
5454

5555
Naming/RescuedExceptionsVariableName:
5656
PreferredName: err
57+
58+
Style/Documentation:
59+
Exclude:
60+
- 'lib/flows/shared_context_pipeline/step.rb' # false positive here

README.md

+174-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
[![codecov](https://codecov.io/gh/ffloyd/flows/branch/master/graph/badge.svg)](https://codecov.io/gh/ffloyd/flows)
55
[![Gem Version](https://badge.fury.io/rb/flows.svg)](https://badge.fury.io/rb/flows)
66

7-
**Right now library is under heavy development. Version 0.4.0 will be the first stable API candidate. And version 1.0.0 is coming after.**
8-
97
Small and fast ruby framework for implementing railway-like operations.
10-
By design it is close to [Trailblazer::Operation](http://trailblazer.to/gems/operation/2.0/) and [Dry::Transaction](https://dry-rb.org/gems/dry-transaction/),
11-
but has simpler and flexible DSL for defining operations and matching results. Also `flows` is faster.
8+
By design it is close to
9+
[Trailblazer::Operation](http://trailblazer.to/gems/operation/2.0/),
10+
[Dry::Transaction](https://dry-rb.org/gems/dry-transaction/) and Rust control
11+
flow style.
12+
Flows has simple and flexible DSL for defining operations and matching results.
13+
Also `flows` is faster than Ruby's alternatives.
1214

1315
`flows` has no production dependencies so it can be used with any framework.
1416

@@ -17,7 +19,7 @@ but has simpler and flexible DSL for defining operations and matching results. A
1719
Add this line to your application's Gemfile:
1820

1921
```ruby
20-
gem 'flows'
22+
gem 'flows', '~> 0.4'
2123
```
2224

2325
And then execute:
@@ -32,7 +34,173 @@ Or install it yourself as:
3234
gem install flows
3335
```
3436

35-
_Rest of documentation will be here when v0.4.0 be ready._ Stay tuned.
37+
## Usage & Documentation
38+
39+
* [YARD documentation](https://rubydoc.info/github/ffloyd/flows/master) - this
40+
link is for master branch. You can also find YARD documentation for any released
41+
version after `v0.4.0`. This documentation has a lot of examples, describes
42+
motivation behind each abstraction, but lacks some guides and defined conventions.
43+
* [Guides](https://ffloyd.github.io/flows/#/) - guides, conventions, integration
44+
and migration notes. Will be done before `v1.0.0` release. Right now is under development.
45+
46+
## Development
47+
48+
`Flows` is designed to be framework for your business logic. It is a big
49+
responsibility. That's why `flows` has near to be sadistic development
50+
conventions and linter setup.
51+
52+
### Anyone can make Flows even better
53+
54+
If you see some typos or unclear things in documentation or code - feel free to open
55+
an issue. Even if you don't have plans to implement a solution - a problem reporting
56+
will help development much. We cannot fix what we don't know.
57+
58+
### [Lefthook](https://github.com/Arkweid/lefthook) as a git hook manager
59+
60+
Installation on MacOS via Homebrew:
61+
62+
```sh
63+
brew install Arkweid/lefthook/lefthook
64+
```
65+
66+
Activation (in the root of the repo):
67+
68+
```sh
69+
lefthook install
70+
```
71+
72+
Run hook manually:
73+
74+
```sh
75+
lefthook run pre-commit
76+
```
77+
78+
Please, never turn off pre-commit hook.
79+
80+
### Rubocop as the first linter
81+
82+
[Rubocop](https://docs.rubocop.org/en/stable/) in this setup is responsible for:
83+
84+
* defining code style (indentation, etc.)
85+
* suggest performance improvements ([rubocop-performance](https://docs.rubocop.org/projects/performance/en/stable/))
86+
* forces all that stuff (with some exceptions) to snippets in Markdown files ([rubocop-md](https://github.com/rubocop-hq/rubocop-md))
87+
* forces unit-testing best practices ([rubocop-rspec](https://docs.rubocop.org/projects/rspec/en/latest/))
88+
89+
Rubocop config for library and RSpec files should be close to standard one only
90+
with minor amount of exceptions.
91+
92+
Code in Markdown snippets and `/bin` folder can ignore more rules. `/bin` folder
93+
contains only development-related scripts and tools so it's ok to ease linter requirements.
94+
95+
Rubocop Metrics (ABC-size, method/class length, etc) must not be eased
96+
globally. Never.
97+
98+
### Reek as the second linter
99+
100+
[Ruby Reek](https://github.com/troessner/reek) is a very aggressive linter that
101+
forces you to do a clean OOP design.
102+
103+
You will be tempted to just shut up this linter many times. But believe me, in 9
104+
of 10 cases it worth to refactor. And after each such refactoring you will
105+
understand OOP design better and better.
106+
107+
### Rest of the linters
108+
109+
* [MDL](https://github.com/markdownlint/markdownlint) - for consistent format of Markdown files
110+
* [forspell](https://github.com/kkuprikov/forspell) - for spellchecking in comments and markdown files
111+
* [inch](http://rrrene.org/inch/) - for documentation coverage suggestions (the
112+
only optional linter)
113+
114+
### Default Rake task and CI
115+
116+
Default rake task (`bundle exec rake`) executes the following checks:
117+
118+
* Rubocop
119+
* Ruby Reek
120+
* RSpec
121+
* Spellcheck (forspell)
122+
* MarkdownLint (mdl)
123+
124+
CI is also performing default Rake task. So, if you want to reproduce CI error
125+
locally - just run `bundle exec rake`.
126+
127+
Default Rake task is also executed as a pre-push git hook.
128+
129+
### Error reporting
130+
131+
I hope no one will argue that clear errors makes development noticeably faster.
132+
That's why _each_ exception in `flows` should be clear and easy to read.
133+
134+
This cannot be tested automatically: you only can test correctness
135+
automatically, convenience can only be tested manually. That's why when you
136+
introduce any new `raise` you have to:
137+
138+
* make an error message clear and descriptive
139+
* add this error to __errors demo CLI_ (`bin/errors`)
140+
* add this errors to __all the errors demo_ (`bin/all_the_errors`)
141+
* make sure that error is displayed correctly and follows a style of the rest
142+
of implemented errors
143+
144+
`bin/errors` is done using [GLI](https://davetron5000.github.io/gli/) library,
145+
run `bin/errors -h` to explore possibilities.
146+
147+
### Performance
148+
149+
Ruby is slow. Moreover, Ruby is very slow. Yes, again. In the past time we had
150+
to compare Ruby with Python. Python was faster and that's why people started to
151+
complain about Ruby performance. That was fixed. But is Ruby fast nowadays? No.
152+
Because languages like Clojure, Go, Rust, Elixir appeared and in comparison
153+
with any of these languages Ruby is very very slow.
154+
155+
That's why you **must** be extra careful with performance. Some business
156+
operations can be executed hundreds or even thousands times per request. Each
157+
line of code in your abstraction will slow down such request a bit. That's why
158+
you should think about each line performance.
159+
160+
Also, it's nearly impossible to make zero-cost abstractions in Ruby. The best
161+
thing you can do - to offload calculations to a class loading or initialization
162+
step. Sacrifice some warm-up time to make runtime performance better.
163+
164+
And to compare performance overhead between different `flows` abstractions
165+
and another libraries alternatives a benchmarking CLI was done: `bin/benchmark`.
166+
167+
This CLI is done using GLI, run `bin/benchmark -h` to explore possibilities.
168+
169+
So far, `flows` offers the best performance among alternatives. And this CLI
170+
is made to simplify comparison with alternatives and keep `flows` the fastest solution.
171+
172+
### Documentation
173+
174+
Each public API method or module **must** be properly documented with examples
175+
and motivation behind.
176+
177+
To run documentation server locally run `bin/docserver`.
178+
179+
Respect `@since` YARD documentation tag. When some module, class or method has any
180+
API change - you have to provide correct `@since` tag value to the documentation.
181+
182+
### Unit test
183+
184+
Each public API method or module **must** be properly tested. Internal modules
185+
can be tested indirectly through public API.
186+
187+
### Commit naming
188+
189+
You **must** follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
190+
191+
### Changelog
192+
193+
Starting from `v0.4.0` [keep a changelog](https://keepachangelog.com/en/1.0.0/)
194+
guideline must be met.
195+
196+
If you adding something - provide some lines to the unreleased section of the `CHANGELOG.md`.
197+
198+
### Versioning
199+
200+
The project strictly follows [SemVer](https://semver.org/spec/v2.0.0.html).
201+
202+
After `v1.0.0` even smallest backward incompatible change will bump major
203+
version. _No exceptions._
36204

37205
## Readme TODO: list of tasks to accomplish before
38206

forspell.dict

+3
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ postprocessor
1212
upcase
1313
fixpoint
1414
Megatron
15+
homebrew
16+
MDL
17+
forspell

lefthook.yml

+5
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ pre-commit:
1414
forspell:
1515
glob: "{*.md,*.rb}"
1616
run: bundle exec forspell {staged_files}
17+
18+
pre-push:
19+
commands:
20+
test:
21+
run: bundle exec rake

lib/flows.rb

-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
# Namespace for all the classes and modules of the library.
22
#
3-
# The most important ones are:
4-
#
5-
# * {Flows::Result}
6-
# * {Flows::Railway}
7-
# * TODO: fill this list
8-
#
93
# @since 0.4.0
104
module Flows
115
# Base class for all the library's errors.

lib/flows/contract.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ module Flows
274274
# But you should avoid constructing static contracts at runtime -
275275
# it's better to instantiate them during loading time (by putting it into constant, for example).
276276
#
277-
# TODO: Some {SharedContextPipeline} plugins will add DSL for contracts.
278-
# So, you don't need to invent anything to use contracts with shared context pipelines.
277+
# {Flows::Plugin::OutputContract} in combination with {SharedContextPipeline} will add DSL for contracts.
278+
# So, you don't need to invent anything to use output contracts with shared context pipelines.
279279
#
280280
# ## Private helper methods
281281
#

lib/flows/flow.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Flows
2222
# > From any state, there is only one transition for any allowed input.
2323
#
2424
# So, we represent DFSM states as {Node}s. Each {Node}, basing on input (input includes execution context also)
25-
# performs some side effects and returns output and next {Node} (DFSM state).
25+
# performs some side effects and returns output and next {Node} name (DFSM state).
2626
#
2727
# Side effects here can be spitted into two types:
2828
#

lib/flows/plugin.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module Flows
22
# Namespace for class behaviour extensions.
33
#
4+
# Feel free to use it to empower your abstractions.
5+
#
46
# @since 0.4.0
57
module Plugin
68
end

lib/flows/plugin/dependency_injector.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module Plugin
4141
# @example
4242
#
4343
# class MyClass
44-
# include Flows::Util::DepencyInjector
44+
# include Flows::Plugin::DependencyInjector
4545
#
4646
# dependency :logger, required: true
4747
# dependency :name, default: 'Boris', type: String # by default dependency is optional.

lib/flows/shared_context_pipeline/step.rb

-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# rubocop:disable Style/Documentation
2-
# ^^^ it is false positive here
3-
41
module Flows
52
class SharedContextPipeline
63
EMPTY_ARRAY = [].freeze
@@ -47,5 +44,3 @@ def to_node(pipeline_class)
4744
)
4845
end
4946
end
50-
51-
# rubocop:enable Style/Documentation

0 commit comments

Comments
 (0)