Skip to content

Instantly share code, notes, and snippets.

@aritode
Forked from rondy/01_functional_objects.md
Created November 13, 2019 19:27
Show Gist options
  • Save aritode/df7d4a323d8b8d65c6edd53e8e123a71 to your computer and use it in GitHub Desktop.
Save aritode/df7d4a323d8b8d65c6edd53e8e123a71 to your computer and use it in GitHub Desktop.
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

Functional objects on Ruby programming language

  • 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 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;
    • 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.
    extract_utm_campaign_value_from(url) # is pure
    get_page_title.call(url)             # is impure
  • Message passing is natural;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment