Skip to content

Instantly share code, notes, and snippets.

@zm69
Last active March 20, 2018 20:08
Show Gist options
  • Save zm69/4ae08b0b57e9a810a852 to your computer and use it in GitHub Desktop.
Save zm69/4ae08b0b57e9a810a852 to your computer and use it in GitHub Desktop.

Revisions

  1. zm69 revised this gist Mar 20, 2018. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    # DCI EXAMPLE IN RUBY (with some prototype elements)
    # Blog post: https://www.ludyna.com/oleh/dci-example-in-ruby
    #
    # More info:
    #
  2. zm69 revised this gist Jan 2, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,8 @@ def do_parenting(parent, child)


    # (proposal #2) New Ruby keyword "as". This keyword _temporary_ extends modules into
    # _instances_ of classes and automatically removes them when out of scope.
    # _instances_ of classes and automatically removes them when out of scope. Some more
    # appropriate word can be used instead of "as" or different syntax - it is just an idea.

    # Previous example with "as" keyword
    def do_parenting(parent, child)
  3. zm69 revised this gist Jan 2, 2015. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -225,8 +225,9 @@ def self.receive_salary(human as EmployeeInteraction)
    # DCI usage example in Rails app
    # =========================================

    # In case of Rails, contexts should be called from controllers (if needed)
    # Contexts replace "managers", "services", "utility" modules/classes
    # In case of Rails, context methods should be called from
    # controller actions, cron jobs, rake tasks.
    # Often contexts replace "managers", "services" modules/classes


    class ParentingController < ApplicationController
  4. zm69 revised this gist Jan 2, 2015. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -253,8 +253,9 @@ def do_parenting
    # =========================================

    # !! With DCI many patterns are obsolete, like ActiveRecord or DataMapper
    # (they are just trying to "emulate" DCI using classes -
    # Classes Oriented Programming (COP)- correct me if I am wrong)
    # (they are just trying to "emulate" DCI ("instance plays role" part)
    # using classes - Classes Oriented Programming (COP)
    # - correct me if I am wrong)

    # For example if you need to save human data object into SQL DB
    # you just create SQL database interaction (role)
  5. zm69 revised this gist Jan 2, 2015. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -293,3 +293,8 @@ module HumanCassandraInteraction
    # ...
    end

    # or another approach could be like this
    human as HumanSqlDBInteraction, HumanCassandraInteraction
    human.save! # with "one" method call save data both
    # into SQL and Cassandra databases.

  6. zm69 revised this gist Jan 2, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -272,7 +272,8 @@ module HumanSqlDBInteraction
    # ....
    end

    human.unextend HumanSqlDBInteraction # remove SQL interaction, now we want to deal with Cassandra database
    human.unextend HumanSqlDBInteraction # remove SQL interaction, now we want to
    # deal with Cassandra database

    # do you want to save human instance to
    # "noSQL" Cassandra database? No problem
  7. zm69 revised this gist Jan 2, 2015. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -272,6 +272,7 @@ module HumanSqlDBInteraction
    # ....
    end

    human.unextend HumanSqlDBInteraction # remove SQL interaction, now we want to deal with Cassandra database

    # do you want to save human instance to
    # "noSQL" Cassandra database? No problem
  8. zm69 revised this gist Jan 2, 2015. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,10 @@
    #
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
    #
    #
    # Matz reaction about this idea:
    # https://twitter.com/yukihiro_matz/status/529854155314053120
    #
    # my twitter: @kajamite


  9. zm69 revised this gist Nov 20, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -16,6 +16,7 @@
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
    #
    # my twitter: @kajamite



  10. zm69 revised this gist Nov 5, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -222,7 +222,7 @@ def self.receive_salary(human as EmployeeInteraction)
    # =========================================

    # In case of Rails, contexts should be called from controllers (if needed)
    # Contexts replace "services","utility" modules/classes
    # Contexts replace "managers", "services", "utility" modules/classes


    class ParentingController < ApplicationController
    @@ -253,13 +253,13 @@ def do_parenting
    # Classes Oriented Programming (COP)- correct me if I am wrong)

    # For example if you need to save human data object into SQL DB
    # you just create SQL interaction (role)
    human as HumanSQLInteraction
    # you just create SQL database interaction (role)
    human as HumanSQLDBInteraction
    human.save! # <= human is saved into SQL database here

    # where HumanSqlInteraction could be something like this:
    module HumanSqlInteraction
    include SQLInteraction
    module HumanSqlDBInteraction
    include SQLDBInteraction

    has_many :bank_accounts

  11. zm69 revised this gist Nov 5, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -207,7 +207,7 @@ def self.receive_salary(human as EmployeeInteraction)

    HomeContext.do_parenting(julia, severyn)

    julia.get_pocket_money_amount_today # => Exception. Method give_pocket_money()
    julia.get_pocket_money_amount_today # => Exception. Method get_pocket_money_amount_today()
    # does not exist for "julia" object.

    # And, for example if you do something like this:
  12. zm69 revised this gist Nov 5, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -207,8 +207,8 @@ def self.receive_salary(human as EmployeeInteraction)

    HomeContext.do_parenting(julia, severyn)

    julia.parent.get_pocket_money_amount_today # => Exception. Method give_pocket_money()
    # does not exist for "julia" object.
    julia.get_pocket_money_amount_today # => Exception. Method give_pocket_money()
    # does not exist for "julia" object.

    # And, for example if you do something like this:
    julia = human as ParentInteraction
  13. zm69 revised this gist Nov 3, 2014. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,17 @@
    # DCI EXAMPLE IN RUBY (with some prototype elements)
    #
    # More info:
    #
    # Creator of MVC & DCI, Trygve Reenskaug - Object Orientation Revisited.
    # Simplicity and power with DCI
    # http://vimeo.com/43536416
    #
    # James Coplien: Why DCI is the Right Architecture for Right Now
    # http://www.infoq.com/interviews/coplien-dci-architecture
    #
    # Creator of MVC & DCI, Trygve Reenskaug: DCI: Re-thinking the foundations of
    # object orientation and of programming
    # http://vimeo.com/8235394
    #
    # James Coplien: Why DCI is the Right Architecture for Right Now
    # http://www.infoq.com/interviews/coplien-dci-architecture
    #
    # Creator of MVC & DCI, Trygve Reenskaug - Object Orientation Revisited.
    # Simplicity and power with DCI
    # http://vimeo.com/43536416
    #
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
  14. zm69 revised this gist Nov 3, 2014. 1 changed file with 8 additions and 4 deletions.
    12 changes: 8 additions & 4 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -2,12 +2,16 @@
    #
    # More info:
    #
    # Author of MVC, Trygve Reenskaug: DCI: Re-thinking the foundations of
    # object orientation and of programming
    # http://vimeo.com/8235394
    #
    # Creator of MVC & DCI, Trygve Reenskaug - Object Orientation Revisited.
    # Simplicity and power with DCI
    # http://vimeo.com/43536416
    #
    # James Coplien: Why DCI is the Right Architecture for Right Now
    # http://www.infoq.com/interviews/coplien-dci-architecture
    #
    # Creator of MVC & DCI, Trygve Reenskaug: DCI: Re-thinking the foundations of
    # object orientation and of programming
    # http://vimeo.com/8235394
    #
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
  15. zm69 revised this gist Nov 3, 2014. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,4 @@
    # DCI EXAMPLE IN RUBY (prototype)
    #
    # Main idea: Objects don't have responsibilities, roles do.
    # DCI EXAMPLE IN RUBY (with some prototype elements)
    #
    # More info:
    #
  16. zm69 revised this gist Nov 2, 2014. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -3,15 +3,18 @@
    # Main idea: Objects don't have responsibilities, roles do.
    #
    # More info:
    #
    # Author of MVC, Trygve Reenskaug: DCI: Re-thinking the foundations of
    # object orientation and of programming
    # http://vimeo.com/8235394
    #
    # James Coplien: Why DCI is the Right Architecture for Right Now
    # http://www.infoq.com/interviews/coplien-dci-architecture
    #
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
    #
    # Trygve Reenskaug: DCI: Re-thinking the foundations of object orientation and of programming
    # https://www.youtube.com/watch?v=cVkhEJq8Kow



    # =========================================
  17. zm69 revised this gist Nov 2, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -152,7 +152,8 @@ def do_one_task_from_list(tasks)
    end


    # CONTEXTS. Contexts are essentially a Use Cases.
    # CONTEXTS. What The-System-Does.
    # Contexts are essentially a Use Cases.
    # Muster objects to play the roles.
    # Inject role methods. Trigger interaction.
    # Place where roles are played. A collection of related possible scenarios.
  18. zm69 revised this gist Nov 2, 2014. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -80,7 +80,6 @@ def do_parenting(parent as ParentInteraction, child as ChildInteraction)
    # =========================================
    # DCI stands for Data, Contexts and Interactions.


    # DATA. What The-System-Is. Classes without interaction code.

    class Human
  19. zm69 revised this gist Nov 2, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -105,7 +105,7 @@ def say(text)
    end
    end

    # INTERACTIONS (Roles).
    # INTERACTIONS (Roles). Role methods direct the execution of the Use Case.
    #
    # Humans can play different roles in different contexts
    # like Parent, Child, Employee, etc.
  20. zm69 revised this gist Nov 2, 2014. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -105,8 +105,7 @@ def say(text)
    end
    end

    # INTERACTIONS (Roles). Muster objects to play the roles.
    # Inject role methods. Trigger interaction.
    # INTERACTIONS (Roles).
    #
    # Humans can play different roles in different contexts
    # like Parent, Child, Employee, etc.
    @@ -155,6 +154,8 @@ def do_one_task_from_list(tasks)


    # CONTEXTS. Contexts are essentially a Use Cases.
    # Muster objects to play the roles.
    # Inject role methods. Trigger interaction.
    # Place where roles are played. A collection of related possible scenarios.
    # In different contexts same human object can play different roles.

  21. zm69 revised this gist Nov 2, 2014. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -81,7 +81,7 @@ def do_parenting(parent as ParentInteraction, child as ChildInteraction)
    # DCI stands for Data, Contexts and Interactions.


    # DATA. Data is always pretty dumb.
    # DATA. What The-System-Is. Classes without interaction code.

    class Human
    attr_reader :name # name of human
    @@ -105,7 +105,9 @@ def say(text)
    end
    end

    # INTERACTIONS (Roles)
    # INTERACTIONS (Roles). Muster objects to play the roles.
    # Inject role methods. Trigger interaction.
    #
    # Humans can play different roles in different contexts
    # like Parent, Child, Employee, etc.

  22. zm69 revised this gist Nov 1, 2014. 1 changed file with 10 additions and 2 deletions.
    12 changes: 10 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,16 @@
    #
    # Main idea: Objects don't have responsibilities, roles do.
    #
    # More info: http://www.infoq.com/interviews/coplien-dci-architecture
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
    # More info:
    #
    # James Coplien: Why DCI is the Right Architecture for Right Now
    # http://www.infoq.com/interviews/coplien-dci-architecture
    #
    # James Coplien: The DCI Architecture: Supporting the Agile Agenda
    # https://www.youtube.com/watch?v=SxHqhDT9WGI
    #
    # Trygve Reenskaug: DCI: Re-thinking the foundations of object orientation and of programming
    # https://www.youtube.com/watch?v=cVkhEJq8Kow


    # =========================================
  23. zm69 revised this gist Oct 31, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -107,6 +107,7 @@ module ParentInteraction
    def get_pocket_money_amount_today
    amount = # ... # complex logic of parent decision, probably
    # based on family budget and child behaviour
    # or something like rand(20)

    withdraw(amount) # <= Human method is called
    amount # <= return amount
  24. zm69 revised this gist Oct 31, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -10,8 +10,8 @@
    # Proposals (ideas) to extend Ruby lang
    # =========================================

    # (proposal #1) New method .unextend() is added to Ruby, so we can effectively
    # remove modules from instances. Optimized for speed.
    # (proposal #1) New method .unextend() (or curtail()?, withdraw()?) is added to Ruby,
    # so we can effectively remove modules from instances. Optimized for speed.

    # For example:
    human.extend ParentInteraction # we can do this right now in Ruby
  25. zm69 revised this gist Oct 31, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -231,7 +231,7 @@ def do_parenting
    # Everything looks better when using DCI
    # =========================================

    # !! With DCI many patterns are absolete, like ActiveRecord or DataMapper
    # !! With DCI many patterns are obsolete, like ActiveRecord or DataMapper
    # (they are just trying to "emulate" DCI using classes -
    # Classes Oriented Programming (COP)- correct me if I am wrong)

    @@ -258,8 +258,8 @@ module HumanSqlInteraction
    human.save! # <= same human instance is saved
    # into "noSQL" database this time

    # where HumanCassadraInteraction could be:
    module HumanCassadraInteraction
    # where HumanCassandraInteraction could be:
    module HumanCassandraInteraction
    include CassandraInteraction

    attribute :name, :string
  26. zm69 revised this gist Oct 31, 2014. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -241,7 +241,8 @@ def do_parenting
    human.save! # <= human is saved into SQL database here

    # where HumanSqlInteraction could be something like this:
    module HumanSqlInteraction < SQLInteraction
    module HumanSqlInteraction
    include SQLInteraction

    has_many :bank_accounts

    @@ -258,7 +259,8 @@ module HumanSqlInteraction < SQLInteraction
    # into "noSQL" database this time

    # where HumanCassadraInteraction could be:
    module HumanCassadraInteraction < CassandraInteraction
    module HumanCassadraInteraction
    include CassandraInteraction

    attribute :name, :string
    attribute :amount, :decimal
  27. zm69 revised this gist Oct 31, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -133,7 +133,7 @@ def receive_salary(amount)
    # ...
    end

    def do_job_task()
    def do_one_task_from_list(tasks)
    # ...
    end

    @@ -162,7 +162,7 @@ def self.do_parenting(parent as ParentInteraction, child as ChildInteraction)
    class JobContext # at job humans might play employee, managers, etc. roles

    def self.do_your_job(human as EmployeeInteraction)
    human.do_job_task
    human.do_one_task_from_list(@job.tasks)
    end # <= out of scope, EmployeeInteraction is removed
    # from human object

  28. zm69 revised this gist Oct 31, 2014. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -240,10 +240,10 @@ def do_parenting
    human as HumanSQLInteraction
    human.save! # <= human is saved into SQL database here

    # where HumanSqlInteraction is:
    # where HumanSqlInteraction could be something like this:
    module HumanSqlInteraction < SQLInteraction

    has_many :accounts
    has_many :bank_accounts

    scope :active_users, -> { where(active: true) }

    @@ -257,12 +257,14 @@ module HumanSqlInteraction < SQLInteraction
    human.save! # <= same human instance is saved
    # into "noSQL" database this time

    # where HumanCassadraInteraction is:
    # where HumanCassadraInteraction could be:
    module HumanCassadraInteraction < CassandraInteraction

    partition_key :name
    attribute :name, :string
    attribute :amount, :decimal

    partition_key :name

    # ...
    end

  29. zm69 revised this gist Oct 31, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -190,8 +190,8 @@ def self.receive_salary(human as EmployeeInteraction)

    HomeContext.do_parenting(julia, severyn)

    julia.give_pocket_money(severyn) # => Exception. Method give_pocket_money()
    # does not exist for "julia" object.
    julia.parent.get_pocket_money_amount_today # => Exception. Method give_pocket_money()
    # does not exist for "julia" object.

    # And, for example if you do something like this:
    julia = human as ParentInteraction
  30. zm69 revised this gist Oct 31, 2014. 1 changed file with 22 additions and 12 deletions.
    34 changes: 22 additions & 12 deletions dci_example.rb
    Original file line number Diff line number Diff line change
    @@ -24,8 +24,11 @@ def do_parenting(parent, child)
    child.extend ChildInteraction # <= temporary extends "child" instance
    # with ChildInteraction module

    parent.give_pocket_money(child) # <= call ParentInteraction method which also calls
    # "child's" ChildInteraction methods inside
    amount = parent.get_pocket_money_amount_today # <= call ParentInteraction method


    child.receive_pocket_money(amount) # <= call ChildInteraction method


    child.unextend ChildInteraction # UNextend ChildInteraction module from "child"
    parent.unextend ParentInteraction # UNextend ParentInteraction module from "parent"
    @@ -43,8 +46,9 @@ def do_parenting(parent, child)
    child as ChildInteraction # <= temporary extends "child" instance
    # with ChildInteraction module

    parent.give_pocket_money(child) # <= call ParentInteraction method which also calls
    # child's ChildInteraction methods inside
    amount = parent.get_pocket_money_amount_today # <= call ParentInteraction method
    child.receive_pocket_money(amount) # <= call ChildInteraction method


    end # <= out of scope, ParentInteraction module is automatically
    # removed from "parent" instance and ChildInteraction
    @@ -53,7 +57,8 @@ def do_parenting(parent, child)

    # Previous example with "as" keyword in parameters list
    def do_parenting(parent as ParentInteraction, child as ChildInteraction)
    parent.give_pocket_money(child)
    amount = parent.get_pocket_money_amount_today
    child.receive_pocket_money(amount)
    end


    @@ -97,10 +102,14 @@ def say(text)
    # like Parent, Child, Employee, etc.

    module ParentInteraction
    def give_pocket_money(child)
    amount = 5 # five backs
    withdraw(amount)
    child.receive_pocket_money(amount)

    # parent decides how much it wants to spend on pocket money for child
    def get_pocket_money_amount_today
    amount = # ... # complex logic of parent decision, probably
    # based on family budget and child behaviour

    withdraw(amount) # <= Human method is called
    amount # <= return amount
    end

    # other role related methods
    @@ -109,8 +118,8 @@ def give_pocket_money(child)

    module ChildInteraction
    def receive_pocket_money(amount)
    deposit(amount)
    say('Thank you')
    deposit(amount) # <= Human method is called
    say('Thank you') # <= Human method is called
    end

    # other role related methods
    @@ -142,7 +151,8 @@ class HomeContext # at home humans might play parents and children roles

    # More than a subroutine - includes role / objects bindings
    def self.do_parenting(parent as ParentInteraction, child as ChildInteraction)
    parent.give_pocket_money(child)
    amount = parent.get_pocket_money_amount_today
    child.receive_pocket_money(amount)
    end # <= out of scope, ParentInteraction is removed from
    # "parent" object, Child is removed from child object