Last active
March 2, 2021 11:14
-
-
Save rondy/a9f167cca216dfb51d1dc1fac56755b1 to your computer and use it in GitHub Desktop.
Revisions
-
rondy revised this gist
Oct 17, 2017 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,6 +6,7 @@ * How should I name my objects that carry behavior? They're nouns or verbs? * Should I expose attr_readers/writers/accessors? * What kind of input should it receive from constructor/initializers? And what about methods? * https://hackernoon.com/api-design-temporal-coupling-2c1687173c7c * More consistent style among classes definitions. #### Benefits -
rondy revised this gist
Jun 21, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,7 +12,7 @@ * Message passing is natural; * Emphasize **what system does** rather rhan **what system is**; * Usage of mocking frameworks can be **dropped off**; #### Guidelines -
rondy revised this gist
Sep 14, 2016 . 1 changed file with 0 additions and 163 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,163 +0,0 @@ -
rondy revised this gist
Sep 14, 2016 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -33,9 +33,7 @@ end ``` * Public contract is a `#call` method; * Enables SRP; * Enables composition/polymorphism through proc/callables objects; * Receive stateful/impure collaborators through the object initializer; * This permits easy mocking/substitution. * This resembles curry-like functions; -
rondy revised this gist
Sep 14, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,7 @@ * How should I name my objects that carry behavior? They're nouns or verbs? * Should I expose attr_readers/writers/accessors? * What kind of input should it receive from constructor/initializers? And what about methods? * More consistent style among classes definitions. #### Benefits -
rondy revised this gist
Sep 14, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ #### Goals * Less questions asked. E.g: * How should I name my objects that carry behavior? They're nouns or verbs? * Should I expose attr_readers/writers/accessors? * What kind of input should it receive from constructor/initializers? And what about methods? -
rondy revised this gist
Aug 25, 2016 . 1 changed file with 14 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,6 +17,20 @@ #### Guidelines * Start class names with a verb; * ("do thing" instead of "thing doer"); ```ruby # Bad class BackupProcedure def perform end end # Good class PerformBackupProcedure def call end end ``` * Public contract is a `#call` method; * Enables SRP; * Enables composition; -
rondy revised this gist
Aug 25, 2016 . 1 changed file with 8 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,13 @@ ## Functional objects on Ruby programming language #### Goals * Less questions asked. * How should I name my objects that carry behavior? They're nouns or verbs? * Should I expose attr_readers/writers/accessors? * What kind of input should it receive from constructor/initializers? And what about methods? * More consistent style on classes definition. #### Benefits * Message passing is natural; -
rondy revised this gist
Aug 25, 2016 . 3 changed files with 0 additions and 67 deletions.There are no files selected for viewing
File renamed without changes.File renamed without changes.This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,67 +0,0 @@ -
rondy revised this gist
Aug 25, 2016 . 1 changed file with 67 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,67 @@ ## Functional objects on Ruby programming language #### Benefits * Message passing is natural; * Emphasize **what system does** rather rhan **what system is**; * Usage of mocking frameworks can be dropped off; #### Guidelines * Start class names with a verb; * Public contract is a `#call` method; * Enables SRP; * Enables composition; * Enables polymorphism; * Enables to receive Proc/callables objects; * Receive stateful/impure collaborators through the object initializer; * This permits easy mocking/substitution. * This resembles curry-like functions; * Receive "pure function" inputs through the `#call` method; * Collaborators are also other functional objects (they're named as verbs); * The `#call` calling always returns a value, preferably 'result'-like objects; * This avoids 'primitive obssesion' anti-pattern; * Consider monadics operations; * Define stateful/impure functions as default implementation, in case nothing is received; ```ruby #... private def get_page_title @get_page_title ||= begin lambda do |url| mechanize = Mechanize.new mechanize.get(url).title end end end end ``` * Object internal state is used only for stateful/impure collaborators. * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` #### Quote from "Functional and Reactive Domain Modeling" book ``` # Why mixing domain logic and side effects is bad ### Entanglement of domain logic and side effects. Violates separation of concerns. Domain logic and side effects are orthogonal to each other—entanglement violates a basic software engineering principle. ### Difficult to unit test. If domain logic is entangled with side effects, unit testing becomes difficult. You need to resort to mocking stuff that leads to other complications in your source code. ### Difficult to reason about the domain logic. You can’t reason about the domain logic that’s entangled with the side effect. ### Side effects don’t compose and hinder modularity of your code. Your entangled code remains an island that can’t be composed with other functions. ``` -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,6 +18,7 @@ * This permits easy mocking/substitution. * This resembles curry-like functions; * Receive "pure function" inputs through the `#call` method; * Collaborators are also other functional objects (they're named as verbs); * The `#call` calling always returns a value, preferably 'result'-like objects; * This avoids 'primitive obssesion' anti-pattern; * Consider monadics operations; @@ -37,7 +38,6 @@ end ``` * Object internal state is used only for stateful/impure collaborators. * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -44,7 +44,7 @@ end get_page_title.call(url) # is impure ``` #### Quote from "Functional and Reactive Domain Modeling" book ``` # Why mixing domain logic and side effects is bad -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 23 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,7 @@ * Emphasize **what system does** rather rhan **what system is**; * Usage of mocking frameworks can be dropped off; #### Guidelines * Start class names with a verb; * Public contract is a `#call` method; @@ -43,3 +43,25 @@ end extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` #### Quote from book "Functional and Reactive Domain Modeling" book ``` # Why mixing domain logic and side effects is bad ### Entanglement of domain logic and side effects. Violates separation of concerns. Domain logic and side effects are orthogonal to each other—entanglement violates a basic software engineering principle. ### Difficult to unit test. If domain logic is entangled with side effects, unit testing becomes difficult. You need to resort to mocking stuff that leads to other complications in your source code. ### Difficult to reason about the domain logic. You can’t reason about the domain logic that’s entangled with the side effect. ### Side effects don’t compose and hinder modularity of your code. Your entangled code remains an island that can’t be composed with other functions. ``` -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 9 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,12 @@ ## Functional objects on Ruby programming language #### Benefits * Message passing is natural; * Emphasize **what system does** rather rhan **what system is**; * Usage of mocking frameworks can be dropped off; ### Guidelines * Start class names with a verb; * Public contract is a `#call` method; @@ -35,6 +43,3 @@ end extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,5 +35,6 @@ end extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` * Message passing is natural; * Emphasize **what system does** rather rhan **what system is**; * Usage of mocking frameworks can be dropped off; -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,4 +35,5 @@ end extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` * Usage of mocking frameworks can be dropped off; * Message passing is natural; -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 19 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,16 +6,31 @@ * Enables composition; * Enables polymorphism; * Enables to receive Proc/callables objects; * Receive stateful/impure collaborators through the object initializer; * This permits easy mocking/substitution. * This resembles curry-like functions; * Receive "pure function" inputs through the `#call` method; * The `#call` calling always returns a value, preferably 'result'-like objects; * This avoids 'primitive obssesion' anti-pattern; * Consider monadics operations; * Define stateful/impure functions as default implementation, in case nothing is received; ```ruby #... private def get_page_title @get_page_title ||= begin lambda do |url| mechanize = Mechanize.new mechanize.get(url).title end end end end ``` * Object internal state is used only for stateful/impure collaborators. * Collaborators are also other functional objects (they're named as verbs); * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,8 +14,8 @@ * This avoids 'primitive obssesion' anti-pattern; * Consider monadics operations; * Define stateful/impure functions as default implementation, in case nothing is received; * Object internal state is used only for stateful/impure collaborators. * * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 101 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -60,3 +60,104 @@ def check_utm_campaign_is_valid(url) end end end class CheckEntryTitleMatchesPageTitle def initialize(get_page_title: nil) @get_page_title = get_page_title end def call(url, entry_title) page_title = get_page_title.call(url) normalized_page_title = normalize_page_title(page_title) entry_title_matches_page_title = entry_title_matches_page_title?(normalized_page_title, entry_title) [entry_title_matches_page_title, normalized_page_title] end private def normalize_page_title(page_title) page_title .gsub(/\s+/, ' ') .strip end def get_page_title(url) @get_page_title ||= begin lambda do |url| GetPageTitle .new(with: :mechanize) .call(url) end end end def entry_title_matches_page_title?(normalized_page_title, entry_title) (normalized_page_title =~ Regexp.new(entry_title.strip)) end end class GetPageTitle STRATEGIES = { mechanize: lambda do |url| Mechanize.new.get(url).title end } def initialize(with: strategy) @strategy = strategy end def call(url) STRATEGIES.fetch[@strategy].call(url) end end CheckEntryTitleMatchesPageTitle .new( get_page_title: lambda do |url| 'Elixir/Erlang Clustering in Kubernetes' end ) .call( url: 'http://bitwalker.org/posts/2016-08-04-clustering-in-kubernetes', entry_title: 'Elixir/Erlang Clustering in Kubernetes' ) # => [true, 'Elixir/Erlang Clustering in Kubernetes'] class CheckUtmCampaignIsValid def initialize(current_issue_number: nil) @current_issue_number = current_issue_number end def call(url) [ is_utm_campaign_valid?(extract_utm_campaign_value_from(url)), given_utm_campaign_value ] end private def is_utm_campaign_valid?(given_utm_campaign_value) (given_utm_campaign_value == current_issue_number.call) end def extract_utm_campaign_value_from(url) parse_query_strings(url) .fetch('utm_campaign', []) .first end def parse_query_strings(url) CGI.parse(URI.parse(url).query) end def current_issue_number @current_issue_number ||= lambda { $current_issue_number } end end -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 62 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,62 @@ class ReviseElixirRadarEntry def call(entry) result = Validation() do check { check_url_points_to_an_existing_page(entry[:url]) } check { check_domain_matches_url_host(entry[:domain], entry[:url]) } check { check_entry_title_matches_page_title(entry[:url], entry[:title]) } check { check_utm_campaign_is_valid(entry[:url]) } end review_result = { title: entry[:title] } case result when Success review_result[:status] = 'valid' when Failure review_result[:status] = 'invalid' review_result[:errors] = result end review_result end private def check_url_points_to_an_existing_page(url) if CheckUrlPointsToAnExistingPage.new.call(url) Success(url) else Failure('page_not_found') end end def check_domain_matches_url_host(domain, url) # case CheckDomainMatchesUrlHost.new.call(domain, url) # when true then Success(url) # when false then Failure('domain_does_not_match') # end if CheckDomainMatchesUrlHost.new.call(domain, url) Success(url) else Failure('domain_does_not_match') end end def check_entry_title_matches_page_title(url, entry_title) if CheckEntryTitleMatchesPageTitle.new.call(url, entry_title) Success(url) else Failure('page_title_does_not_match') end end def check_utm_campaign_is_valid(url) if CheckUtmCampaignIsValid.new.call(url) Success(url) else Failure('wrong_utm_campaign') end end end -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ #### Functional objects on Ruby programming language * Start class names with a verb; * Public contract is a `#call` method; * Enables SRP; * Enables composition; @@ -15,9 +15,9 @@ * Consider monadics operations; * Define stateful/impure functions as default implementation, in case nothing is received; * Stateful/impure functions are always returned as closures/lambda; * Object state is uded only for atateful/impure collaborators. ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` * Message passing is natural; -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,10 +12,12 @@ * This resembles curry-like functions; * The `#call` calling always returns a value, preferably 'result'-like objects; * This avoids 'primitive obssesion' anti-pattern; * Consider monadics operations; * Define stateful/impure functions as default implementation, in case nothing is received; * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` * Consider to be event-driven; * Message passing is natural; -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,13 +8,13 @@ * Enables to receive Proc/callables objects; * Receive stateful/impure functions through the object initializer; * This permits easy mocking/substitution. * Receive pure function inputs through the `#call` method; * This resembles curry-like functions; * The `#call` calling always returns a value, preferably 'result'-like objects; * This avoids 'primitive obssesion' anti-pattern; * Define stateful/impure functions as default implementation, in case nothing is received; * Stateful/impure functions are always returned as closures/lambda; ```ruby extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` -
rondy revised this gist
Aug 24, 2016 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,10 @@ * Start with a verb; * Public contract is a `#call` method; * Enables SRP; * Enables composition; * Enables polymorphism; * Enables to receive Proc/callables objects; * Receive stateful/impure functions through the object initializer; * This permits easy mocking/substitution. * Receive pure function inputs through the `#call` method. -
rondy created this gist
Aug 24, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,17 @@ #### Functional objects * Start with a verb; * Public contract is a `#call` method; * Receive stateful/impure functions through the object initializer; * This permits easy mocking/substitution. * Receive pure function inputs through the `#call` method. * This resembles curry-like functions. * The `#call` calling always returns a value, preferably 'result'-like objects * This avoids 'primitive obssesion' anti-pattern; * Define stateful/impure functions as default implementation, in case nothing is received; * Stateful/impure functions are always returned as closures/lambda; ``` extract_utm_campaign_value_from(url) # is pure get_page_title.call(url) # is impure ``` * Message passing is natural;