flows 0.2.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/{build.yml → test.yml} +5 -10
  3. data/.gitignore +9 -1
  4. data/.mdlrc +1 -1
  5. data/.reek.yml +54 -0
  6. data/.rubocop.yml +26 -7
  7. data/.rubocop_todo.yml +27 -0
  8. data/.ruby-version +1 -1
  9. data/.yardopts +1 -0
  10. data/CHANGELOG.md +81 -0
  11. data/Gemfile +0 -6
  12. data/README.md +167 -363
  13. data/Rakefile +35 -1
  14. data/bin/.rubocop.yml +5 -0
  15. data/bin/all_the_errors +55 -0
  16. data/bin/benchmark +73 -105
  17. data/bin/benchmark_cli/compare.rb +118 -0
  18. data/bin/benchmark_cli/compare/a_plus_b.rb +22 -0
  19. data/bin/benchmark_cli/compare/base.rb +45 -0
  20. data/bin/benchmark_cli/compare/command.rb +47 -0
  21. data/bin/benchmark_cli/compare/ten_steps.rb +22 -0
  22. data/bin/benchmark_cli/examples.rb +23 -0
  23. data/bin/benchmark_cli/examples/.rubocop.yml +22 -0
  24. data/bin/benchmark_cli/examples/a_plus_b/dry_do.rb +23 -0
  25. data/bin/benchmark_cli/examples/a_plus_b/dry_transaction.rb +17 -0
  26. data/bin/benchmark_cli/examples/a_plus_b/flows_do.rb +22 -0
  27. data/bin/benchmark_cli/examples/a_plus_b/flows_railway.rb +13 -0
  28. data/bin/benchmark_cli/examples/a_plus_b/flows_scp.rb +13 -0
  29. data/bin/benchmark_cli/examples/a_plus_b/flows_scp_mut.rb +13 -0
  30. data/bin/benchmark_cli/examples/a_plus_b/flows_scp_oc.rb +21 -0
  31. data/bin/benchmark_cli/examples/a_plus_b/trailblazer.rb +15 -0
  32. data/bin/benchmark_cli/examples/ten_steps/dry_do.rb +70 -0
  33. data/bin/benchmark_cli/examples/ten_steps/dry_transaction.rb +64 -0
  34. data/bin/benchmark_cli/examples/ten_steps/flows_do.rb +69 -0
  35. data/bin/benchmark_cli/examples/ten_steps/flows_railway.rb +58 -0
  36. data/bin/benchmark_cli/examples/ten_steps/flows_scp.rb +58 -0
  37. data/bin/benchmark_cli/examples/ten_steps/flows_scp_mut.rb +58 -0
  38. data/bin/benchmark_cli/examples/ten_steps/flows_scp_oc.rb +66 -0
  39. data/bin/benchmark_cli/examples/ten_steps/trailblazer.rb +60 -0
  40. data/bin/benchmark_cli/helpers.rb +12 -0
  41. data/bin/benchmark_cli/ruby.rb +15 -0
  42. data/bin/benchmark_cli/ruby/command.rb +38 -0
  43. data/bin/benchmark_cli/ruby/method_exec.rb +71 -0
  44. data/bin/benchmark_cli/ruby/self_class.rb +69 -0
  45. data/bin/benchmark_cli/ruby/structs.rb +90 -0
  46. data/bin/console +1 -0
  47. data/bin/docserver +7 -0
  48. data/bin/errors +138 -0
  49. data/bin/errors_cli/contract_error_demo.rb +49 -0
  50. data/bin/errors_cli/di_error_demo.rb +38 -0
  51. data/bin/errors_cli/flow_error_demo.rb +22 -0
  52. data/bin/errors_cli/flows_router_error_demo.rb +15 -0
  53. data/bin/errors_cli/interface_error_demo.rb +17 -0
  54. data/bin/errors_cli/oc_error_demo.rb +40 -0
  55. data/bin/errors_cli/railway_error_demo.rb +10 -0
  56. data/bin/errors_cli/result_error_demo.rb +13 -0
  57. data/bin/errors_cli/scp_error_demo.rb +17 -0
  58. data/docs/README.md +3 -187
  59. data/docs/_sidebar.md +0 -24
  60. data/docs/index.html +1 -1
  61. data/flows.gemspec +27 -2
  62. data/forspell.dict +9 -0
  63. data/lefthook.yml +9 -0
  64. data/lib/flows.rb +11 -5
  65. data/lib/flows/contract.rb +402 -0
  66. data/lib/flows/contract/array.rb +55 -0
  67. data/lib/flows/contract/case_eq.rb +43 -0
  68. data/lib/flows/contract/compose.rb +77 -0
  69. data/lib/flows/contract/either.rb +53 -0
  70. data/lib/flows/contract/error.rb +24 -0
  71. data/lib/flows/contract/hash.rb +75 -0
  72. data/lib/flows/contract/hash_of.rb +70 -0
  73. data/lib/flows/contract/helpers.rb +22 -0
  74. data/lib/flows/contract/predicate.rb +34 -0
  75. data/lib/flows/contract/transformer.rb +50 -0
  76. data/lib/flows/contract/tuple.rb +70 -0
  77. data/lib/flows/flow.rb +96 -7
  78. data/lib/flows/flow/errors.rb +29 -0
  79. data/lib/flows/flow/node.rb +132 -0
  80. data/lib/flows/flow/router.rb +29 -0
  81. data/lib/flows/flow/router/custom.rb +59 -0
  82. data/lib/flows/flow/router/errors.rb +11 -0
  83. data/lib/flows/flow/router/simple.rb +25 -0
  84. data/lib/flows/plugin.rb +15 -0
  85. data/lib/flows/plugin/dependency_injector.rb +170 -0
  86. data/lib/flows/plugin/dependency_injector/dependency.rb +24 -0
  87. data/lib/flows/plugin/dependency_injector/dependency_definition.rb +16 -0
  88. data/lib/flows/plugin/dependency_injector/dependency_list.rb +55 -0
  89. data/lib/flows/plugin/dependency_injector/errors.rb +58 -0
  90. data/lib/flows/plugin/implicit_init.rb +45 -0
  91. data/lib/flows/plugin/interface.rb +84 -0
  92. data/lib/flows/plugin/output_contract.rb +85 -0
  93. data/lib/flows/plugin/output_contract/dsl.rb +48 -0
  94. data/lib/flows/plugin/output_contract/errors.rb +74 -0
  95. data/lib/flows/plugin/output_contract/wrapper.rb +55 -0
  96. data/lib/flows/plugin/profiler.rb +114 -0
  97. data/lib/flows/plugin/profiler/injector.rb +35 -0
  98. data/lib/flows/plugin/profiler/report.rb +48 -0
  99. data/lib/flows/plugin/profiler/report/events.rb +43 -0
  100. data/lib/flows/plugin/profiler/report/flat.rb +41 -0
  101. data/lib/flows/plugin/profiler/report/flat/method_report.rb +80 -0
  102. data/lib/flows/plugin/profiler/report/raw.rb +15 -0
  103. data/lib/flows/plugin/profiler/report/tree.rb +98 -0
  104. data/lib/flows/plugin/profiler/report/tree/calculated_node.rb +116 -0
  105. data/lib/flows/plugin/profiler/report/tree/node.rb +34 -0
  106. data/lib/flows/plugin/profiler/wrapper.rb +53 -0
  107. data/lib/flows/railway.rb +140 -34
  108. data/lib/flows/railway/dsl.rb +8 -18
  109. data/lib/flows/railway/errors.rb +8 -12
  110. data/lib/flows/railway/step.rb +24 -0
  111. data/lib/flows/railway/step_list.rb +38 -0
  112. data/lib/flows/result.rb +188 -2
  113. data/lib/flows/result/do.rb +158 -16
  114. data/lib/flows/result/err.rb +12 -6
  115. data/lib/flows/result/errors.rb +29 -17
  116. data/lib/flows/result/helpers.rb +25 -3
  117. data/lib/flows/result/ok.rb +12 -6
  118. data/lib/flows/shared_context_pipeline.rb +342 -0
  119. data/lib/flows/shared_context_pipeline/dsl.rb +12 -0
  120. data/lib/flows/shared_context_pipeline/dsl/callbacks.rb +35 -0
  121. data/lib/flows/shared_context_pipeline/dsl/tracks.rb +52 -0
  122. data/lib/flows/shared_context_pipeline/errors.rb +17 -0
  123. data/lib/flows/shared_context_pipeline/mutation_step.rb +30 -0
  124. data/lib/flows/shared_context_pipeline/router_definition.rb +21 -0
  125. data/lib/flows/shared_context_pipeline/step.rb +55 -0
  126. data/lib/flows/shared_context_pipeline/track.rb +54 -0
  127. data/lib/flows/shared_context_pipeline/track_list.rb +51 -0
  128. data/lib/flows/shared_context_pipeline/wrap.rb +73 -0
  129. data/lib/flows/util.rb +17 -0
  130. data/lib/flows/util/inheritable_singleton_vars.rb +86 -0
  131. data/lib/flows/util/inheritable_singleton_vars/dup_strategy.rb +100 -0
  132. data/lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb +91 -0
  133. data/lib/flows/util/prepend_to_class.rb +191 -0
  134. data/lib/flows/version.rb +1 -1
  135. metadata +253 -38
  136. data/Gemfile.lock +0 -174
  137. data/bin/demo +0 -66
  138. data/bin/examples.rb +0 -195
  139. data/bin/profile_10steps +0 -106
  140. data/bin/ruby_benchmarks +0 -26
  141. data/docs/CNAME +0 -1
  142. data/docs/contributing/benchmarks_profiling.md +0 -3
  143. data/docs/contributing/local_development.md +0 -3
  144. data/docs/flow/direct_usage.md +0 -3
  145. data/docs/flow/general_idea.md +0 -3
  146. data/docs/operation/basic_usage.md +0 -1
  147. data/docs/operation/inject_steps.md +0 -3
  148. data/docs/operation/lambda_steps.md +0 -3
  149. data/docs/operation/result_shapes.md +0 -3
  150. data/docs/operation/routing_tracks.md +0 -3
  151. data/docs/operation/wrapping_steps.md +0 -3
  152. data/docs/overview/performance.md +0 -336
  153. data/docs/railway/basic_usage.md +0 -232
  154. data/docs/result_objects/basic_usage.md +0 -196
  155. data/docs/result_objects/do_notation.md +0 -139
  156. data/lib/flows/node.rb +0 -27
  157. data/lib/flows/operation.rb +0 -52
  158. data/lib/flows/operation/builder.rb +0 -130
  159. data/lib/flows/operation/builder/build_router.rb +0 -37
  160. data/lib/flows/operation/dsl.rb +0 -93
  161. data/lib/flows/operation/errors.rb +0 -75
  162. data/lib/flows/operation/executor.rb +0 -78
  163. data/lib/flows/railway/builder.rb +0 -68
  164. data/lib/flows/railway/executor.rb +0 -23
  165. data/lib/flows/result_router.rb +0 -14
  166. data/lib/flows/router.rb +0 -22
data/Rakefile CHANGED
@@ -2,8 +2,42 @@ require 'bundler/gem_tasks'
2
2
 
3
3
  require 'rspec/core/rake_task'
4
4
  require 'rubocop/rake_task'
5
+ require 'reek/rake/task'
6
+ require 'inch/rake'
7
+
8
+ require 'forspell/cli'
9
+ require 'mdl'
5
10
 
6
11
  RSpec::Core::RakeTask.new(:spec)
7
12
  RuboCop::RakeTask.new(:rubocop)
13
+ Reek::Rake::Task.new
14
+ Inch::Rake::Suggest.new
15
+
16
+ PATHS_TO_SPELLCHECK = ['.'].freeze
17
+ PATHS_FOR_MDL = ['README.md', 'CHANGELOG.md', Dir.glob('docs/**/*.md')].flatten.freeze
18
+
19
+ desc 'Run self spellchecking'
20
+ task :spellcheck do |_task|
21
+ puts 'Run forspell checker...'
22
+ Forspell::CLI.new(PATHS_TO_SPELLCHECK).call
23
+ rescue SystemExit => err
24
+ if err.status.zero?
25
+ puts 'Everything is ok.'
26
+ else
27
+ exit err.status
28
+ end
29
+ end
30
+
31
+ desc 'Run markdown linter'
32
+ task :mdl do |_task|
33
+ puts 'Run MDL linter...'
34
+ MarkdownLint.run(PATHS_FOR_MDL)
35
+ rescue SystemExit => err
36
+ if err.status.zero?
37
+ puts 'Everything is ok.'
38
+ else
39
+ exit err.status
40
+ end
41
+ end
8
42
 
9
- task default: %i[rubocop spec]
43
+ task default: %i[rubocop reek spec spellcheck mdl]
@@ -0,0 +1,5 @@
1
+ inherit_from:
2
+ - ../.rubocop.yml
3
+
4
+ Style/Documentation:
5
+ Enabled: false
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ "${BASH_SOURCE%/*}/errors" contract
4
+ "${BASH_SOURCE%/*}/errors" router
5
+
6
+ echo
7
+ echo
8
+ echo "---------------------------"
9
+ echo "Dependency Injection plugin"
10
+ echo "---------------------------"
11
+ "${BASH_SOURCE%/*}/errors" di missing
12
+ "${BASH_SOURCE%/*}/errors" di unexpected
13
+ "${BASH_SOURCE%/*}/errors" di invalid_type
14
+ "${BASH_SOURCE%/*}/errors" di missing_default
15
+
16
+ echo
17
+ echo
18
+ echo "---------------------------"
19
+ echo "Output Contract plugin"
20
+ echo "---------------------------"
21
+ "${BASH_SOURCE%/*}/errors" output_contract no_contract
22
+ "${BASH_SOURCE%/*}/errors" output_contract contract
23
+ "${BASH_SOURCE%/*}/errors" output_contract status
24
+ "${BASH_SOURCE%/*}/errors" output_contract result_type
25
+
26
+ echo
27
+ echo
28
+ echo "---------------------------"
29
+ echo "Railway"
30
+ echo "---------------------------"
31
+ "${BASH_SOURCE%/*}/errors" railway no_steps
32
+
33
+ echo
34
+ echo
35
+ echo "---------------------------"
36
+ echo "Result"
37
+ echo "---------------------------"
38
+ "${BASH_SOURCE%/*}/errors" result ok_access
39
+ "${BASH_SOURCE%/*}/errors" result err_access
40
+
41
+ echo
42
+ echo
43
+ echo "---------------------------"
44
+ echo "Shared Context Pipeline"
45
+ echo "---------------------------"
46
+ "${BASH_SOURCE%/*}/errors" scp no_steps
47
+ "${BASH_SOURCE%/*}/errors" scp no_step_impl
48
+
49
+ echo
50
+ echo
51
+ echo "---------------------------"
52
+ echo "Flow"
53
+ echo "---------------------------"
54
+ "${BASH_SOURCE%/*}/errors" flow invalid_node_route
55
+ "${BASH_SOURCE%/*}/errors" flow no_first_node
@@ -1,111 +1,79 @@
1
1
  #!/usr/bin/env ruby
2
- # rubocop:disable all
3
2
 
4
3
  require 'bundler/setup'
5
- require 'benchmark/ips'
6
-
7
- require_relative './examples'
8
-
9
- with_all = ENV['WITH_ALL']
10
-
11
- with_railway = ENV['WITH_RW'] || with_all
12
- with_operation = ENV['WITH_OP'] || with_all
13
- with_dry = ENV['WITH_DRY'] || with_all
14
- with_trailblazer = ENV['WITH_TB'] || with_all
15
-
16
- with_poro = ENV['WITH_PORO']
17
-
18
- no_prebuild = ENV['NO_PREBUILD']
19
- no_eachbuild = ENV['NO_EACHBUILD']
20
-
21
-
22
- puts '-' * 50
23
- puts '- task: A + B, one step implementation'
24
- puts '-' * 50
25
-
26
- flows_summator = FlowsSummator.new
27
- flows_railway_summator = FlowsRailwaySummator.new
28
- dry_summator = DrySummator.new
29
-
30
- Benchmark.ips do |b|
31
- b.report 'Flows::Railway (build once)' do
32
- flows_railway_summator.call(a: 1, b: 2)
33
- end if with_railway && !no_prebuild
34
-
35
- b.report 'Flows::Railway (build each time)' do
36
- FlowsRailwaySummator.new.call(a: 1, b: 2)
37
- end if with_railway && !no_eachbuild
38
-
39
- b.report 'Flows::Operation (build once)' do
40
- flows_summator.call(a: 1, b: 2)
41
- end if with_operation && !no_prebuild
42
-
43
- b.report 'Flows::Operation (build each time)' do
44
- FlowsSummator.new.call(a: 1, b: 2)
45
- end if with_operation && !no_eachbuild
46
-
47
- b.report 'Dry::Transaction (build once)' do
48
- dry_summator.call(a: 1, b: 2)
49
- end if with_dry && !no_prebuild
50
-
51
- b.report 'Dry::Transaction (build each time)' do
52
- DrySummator.new.call(a: 1, b: 2)
53
- end if with_dry && !no_eachbuild
4
+ require 'flows'
54
5
 
55
- b.report 'Trailblazer::Operation' do
56
- TBSummator.call(a: 1, b: 2)
57
- end if with_trailblazer
58
-
59
- b.report 'PORO' do
60
- POROSummator.call(a: 1, b: 2)
61
- end if with_poro
62
-
63
- b.compare!
6
+ require 'benchmark/ips'
7
+ require 'pry'
8
+ require 'gli'
9
+ require 'warning'
10
+
11
+ require_relative 'benchmark_cli/helpers'
12
+ require_relative 'benchmark_cli/examples'
13
+
14
+ require_relative 'benchmark_cli/ruby'
15
+ require_relative 'benchmark_cli/compare'
16
+
17
+ Warning.ignore(/BigDecimal.new is deprecated/)
18
+
19
+ # Benchmarking CLI application
20
+ class BenchmarkCLI
21
+ extend GLI::App
22
+ extend Flows::Result::Helpers
23
+
24
+ program_desc 'Benchmark runner'
25
+
26
+ use_openstruct true
27
+
28
+ desc 'Run Ruby benchmarks'
29
+ ruby_benchmarks = Ruby::BENCHMARKS.keys.map(&:to_s)
30
+ command :ruby do |cmd|
31
+ cmd.flag(
32
+ %i[b benchmarks],
33
+ desc: "benchmarks to run. Pick from: #{ruby_benchmarks.join(', ')}. By default all the benchmarks are executed.",
34
+ type: String,
35
+ multiple: true,
36
+ must_match: ruby_benchmarks,
37
+ default_value: ruby_benchmarks
38
+ )
39
+
40
+ cmd.action do |_gopts, opts, _args|
41
+ result = Ruby::Command.new(opts.benchmarks).call
42
+
43
+ case result
44
+ when match_ok then puts 'Benchmark finished! Thank you for patience!'
45
+ when match_err then exit_now!(result.error)
46
+ end
47
+ end
48
+ end
49
+
50
+ desc 'Compare different Flows abstractions and alternatives from the other libraries'
51
+ command :compare do |cmd|
52
+ benchmarks = Compare::BENCHMARKS.keys.map(&:to_s)
53
+ cmd.flag %i[b benchmarks],
54
+ desc: 'benchmarks to run',
55
+ type: String,
56
+ multiple: true,
57
+ must_match: benchmarks,
58
+ default_value: benchmarks
59
+
60
+ implementations = Compare::IMPLEMENTATIONS.keys.map(&:to_s)
61
+ cmd.flag %i[i implementations],
62
+ desc: 'implementations to compare',
63
+ type: String,
64
+ multiple: true,
65
+ must_match: implementations,
66
+ default_value: implementations
67
+
68
+ cmd.action do |_gopts, opts, _args|
69
+ result = Compare::Command.new(opts.benchmarks, opts.implementations).call
70
+
71
+ case result
72
+ when match_ok then puts 'Benchmark finished! Thank you for patience!'
73
+ when match_err then exit_now!(result.error)
74
+ end
75
+ end
76
+ end
64
77
  end
65
- puts
66
-
67
-
68
- puts '-' * 50
69
- puts '- task: ten steps returns successful result'
70
- puts '-' * 50
71
-
72
- flows_ten_steps = FlowsTenSteps.new
73
- flows_railway_ten_steps = FlowsRailwayTenSteps.new
74
- dry_ten_steps = DryTenSteps.new
75
-
76
- Benchmark.ips do |b|
77
- b.report 'Flows::Railway (build once)' do
78
- flows_railway_ten_steps.call(a: 1, b: 2)
79
- end if with_railway && !no_prebuild
80
-
81
- b.report 'Flows::Railway (build each time)' do
82
- FlowsRailwayTenSteps.new.call(a: 1, b: 2)
83
- end if with_railway && !no_eachbuild
84
78
 
85
- b.report 'Flows::Operation (build once)' do
86
- flows_ten_steps.call(a: 1, b: 2)
87
- end if with_operation && !no_prebuild
88
-
89
- b.report 'Flows::Operation (build each time)' do
90
- FlowsTenSteps.new.call(a: 1, b: 2)
91
- end if with_operation && !no_eachbuild
92
-
93
- b.report 'Dry::Transaction (build once)' do
94
- dry_ten_steps.call(a: 1, b: 2)
95
- end if with_dry && !no_prebuild
96
-
97
- b.report 'Dry::Transaction (build each time)' do
98
- DryTenSteps.new.call(a: 1, b: 2)
99
- end if with_dry && !no_eachbuild
100
-
101
- b.report 'Trailblazer::Operation' do
102
- TBTenSteps.call(a: 1, b: 2)
103
- end if with_trailblazer
104
-
105
- b.report 'PORO' do
106
- POROTenSteps.call
107
- end if with_poro
108
-
109
- b.compare!
110
- end
111
- puts
79
+ exit BenchmarkCLI.run(ARGV)
@@ -0,0 +1,118 @@
1
+ require_relative 'compare/base'
2
+ require_relative 'compare/a_plus_b'
3
+ require_relative 'compare/ten_steps'
4
+
5
+ require_relative 'compare/command'
6
+
7
+ class BenchmarkCLI
8
+ module Compare # rubocop:disable Metrics/ModuleLength
9
+ BENCHMARKS = {
10
+ APlusB::NAME => APlusB,
11
+ TenSteps::NAME => TenSteps
12
+ }.freeze
13
+
14
+ MODES = {
15
+ class_call: 'execute `Implementation.call(...)`',
16
+ instance_call: 'execute `instance.call(...)`'
17
+ }.freeze
18
+
19
+ IMPLEMENTATIONS = {
20
+ flows_do: {
21
+ title: 'Flows Do-notation',
22
+ mode: :instance_call,
23
+ classes: {
24
+ APlusB::NAME => Examples::APlusB::FlowsDo,
25
+ TenSteps::NAME => Examples::TenSteps::FlowsDo
26
+ }
27
+ },
28
+ flows_railway_class: {
29
+ title: 'Flows Railway',
30
+ mode: :class_call,
31
+ classes: {
32
+ APlusB::NAME => Examples::APlusB::FlowsRailway,
33
+ TenSteps::NAME => Examples::TenSteps::FlowsRailway
34
+ }
35
+ },
36
+ flows_railway_instance: {
37
+ title: 'Flows Railway',
38
+ mode: :instance_call,
39
+ classes: {
40
+ APlusB::NAME => Examples::APlusB::FlowsRailway,
41
+ TenSteps::NAME => Examples::TenSteps::FlowsRailway
42
+ }
43
+ },
44
+ flows_scp_class: {
45
+ title: 'Flows Shared Context Pipeline, functional steps',
46
+ mode: :class_call,
47
+ classes: {
48
+ APlusB::NAME => Examples::APlusB::FlowsSCP,
49
+ TenSteps::NAME => Examples::TenSteps::FlowsSCP
50
+ }
51
+ },
52
+ flows_scp_instance: {
53
+ title: 'Flows Shared Context Pipeline, functional steps',
54
+ mode: :instance_call,
55
+ classes: {
56
+ APlusB::NAME => Examples::APlusB::FlowsSCP,
57
+ TenSteps::NAME => Examples::TenSteps::FlowsSCP
58
+ }
59
+ },
60
+ flows_scp_oc_class: {
61
+ title: 'Flows Shared Context Pipeline with contract for output, functional steps',
62
+ mode: :class_call,
63
+ classes: {
64
+ APlusB::NAME => Examples::APlusB::FlowsSCPOC,
65
+ TenSteps::NAME => Examples::TenSteps::FlowsSCPOC
66
+ }
67
+ },
68
+ flows_scp_oc_instance: {
69
+ title: 'Flows Shared Context Pipeline with contract for output, functional steps',
70
+ mode: :instance_call,
71
+ classes: {
72
+ APlusB::NAME => Examples::APlusB::FlowsSCPOC,
73
+ TenSteps::NAME => Examples::TenSteps::FlowsSCPOC
74
+ }
75
+ },
76
+ flows_scp_mut_class: {
77
+ title: 'Flows Shared Context Pipeline, mutation steps',
78
+ mode: :class_call,
79
+ classes: {
80
+ APlusB::NAME => Examples::APlusB::FlowsSCPMut,
81
+ TenSteps::NAME => Examples::TenSteps::FlowsSCPMut
82
+ }
83
+ },
84
+ flows_scp_mut_instance: {
85
+ title: 'Flows Shared Context Pipeline, mutation steps',
86
+ mode: :instance_call,
87
+ classes: {
88
+ APlusB::NAME => Examples::APlusB::FlowsSCPMut,
89
+ TenSteps::NAME => Examples::TenSteps::FlowsSCPMut
90
+ }
91
+ },
92
+ dry_do: {
93
+ title: 'dry-rb Do-notation',
94
+ mode: :instance_call,
95
+ classes: {
96
+ APlusB::NAME => Examples::APlusB::DryDo,
97
+ TenSteps::NAME => Examples::TenSteps::DryDo
98
+ }
99
+ },
100
+ dry_transaction: {
101
+ title: 'dry-rb Transaction',
102
+ mode: :instance_call,
103
+ classes: {
104
+ APlusB::NAME => Examples::APlusB::DryTransaction,
105
+ TenSteps::NAME => Examples::TenSteps::DryTransaction
106
+ }
107
+ },
108
+ trailblazer: {
109
+ title: 'Trailblazer Operation',
110
+ mode: :class_call,
111
+ classes: {
112
+ APlusB::NAME => Examples::APlusB::TB,
113
+ TenSteps::NAME => Examples::TenSteps::TB
114
+ }
115
+ }
116
+ }.freeze
117
+ end
118
+ end
@@ -0,0 +1,22 @@
1
+ class BenchmarkCLI
2
+ module Compare
3
+ # 'A + B' comparison.
4
+ class APlusB < Base
5
+ TITLE = 'A + B: one step implementation, input provided as kwargs'.freeze
6
+ NAME = :a_plus_b
7
+
8
+ def report_class_call(benchmark, title, klass)
9
+ benchmark.report title do
10
+ klass.call(a: 100, b: 200)
11
+ end
12
+ end
13
+
14
+ def report_instance_call(benchmark, title, klass)
15
+ instance = klass.new
16
+ benchmark.report title do
17
+ instance.call(a: 100, b: 200)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ class BenchmarkCLI
2
+ module Compare
3
+ # @abstract
4
+ #
5
+ # Base class for comparison benchmarks.
6
+ class Base
7
+ include Helpers
8
+
9
+ def initialize(implementations)
10
+ @implementations = implementations
11
+ end
12
+
13
+ def call
14
+ header self.class::TITLE
15
+
16
+ Benchmark.ips do |benchmark|
17
+ benchmark.config(stats: :bootstrap, confidence: 95)
18
+
19
+ report_implementations(benchmark)
20
+
21
+ benchmark.compare!
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def report_implementations(benchmark)
28
+ @implementations.each do |implementation|
29
+ report_implementation(benchmark, IMPLEMENTATIONS[implementation])
30
+ end
31
+ end
32
+
33
+ def report_implementation(benchmark, cfg)
34
+ mode = cfg[:mode]
35
+ title = "#{cfg[:title]} (#{MODES[mode]})"
36
+ klass = cfg[:classes][self.class::NAME]
37
+
38
+ case mode
39
+ when :class_call then report_class_call(benchmark, title, klass)
40
+ when :instance_call then report_instance_call(benchmark, title, klass)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end