SlideShare ist ein Scribd-Unternehmen logo
1 von 25
Use cases
            are
         important

Andrzej Krzywda
Use cases
in the code
     are
 even more
 important
class PlayTeamGameUseCase

  constructor: (@game, @player) ->
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)

  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()

    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)

  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()

    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->      Actors
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)

  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()

    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->      Actors
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)      Roles
  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()

    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->      Actors
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)      Roles
  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()          Algorithm
    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->      Actors
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)      Roles
  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()          Algorithm
    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()
                                                uses domain objects
    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
Name
class PlayTeamGameUseCase

  constructor: (@game, @player) ->      Actors
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)      Roles
  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

      @teachPlayerHowToPlay()          Algorithm
    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()
                                                uses domain objects
    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)       Nothing about GUI or persistence!
Where is?

• GUI
• Persistence
• API calls
• events
A clean use case code
   is the main goal
AOP + DCI
Aspect Oriented
 Programming
AOP gives us
method hooks
After, Before, Around
GUI & persistence
class GameUseCaseGlue
  constructor: (@gameUseCase, @game, @gui) ->

    execute: () =>
      Around(@gameUseCase,   'tryToEnterGameArea',                  @checkFbInvitation)
      After (@gameUseCase,   'tryToEnterGameArea',                  @showTeamArea)
      After (@gameUseCase,   'tryToEnterGameArea',                  @showButtonInviteOrPostPicture)
      Around(@gameUseCase,   'tellPlayerHeIsPartOfTeam',            @showTeamPopup)
      Around(@gameUseCase,   'askPlayerToLikeFanpage',              @showLikePopup)
      Around(@gameUseCase,   'teachPlayerHowToPlay',                @showTutorialPopup)
      Around(@gameUseCase,   'playerWantsToKnowWinnersWithPrize',   @showWinnersPopup)
      Around(@gameUseCase,   'playerWantsToKnowPrizes',             @showPrizesPopup)
      Around(@gameUseCase,   'askPlayerToDeclareHisFavCountry',     @showDeclareCountryPopup)
      Around(@gameUseCase,   'iAcceptMyFriendInvitationToATeam',    @onIAcceptMyFriendInvitationToATeam)

      Around(@gui, 'inviteClicked',    @inviteFriends)    # gameUseCase.inviteFriends
	
      Around(@gameUseCase, 'inviteFriends',    @storeInvitationInTheDB)     DB here

                                        Glue code
Around(@gameUseCase, 'tellPlayerHeIsPartOfTeam', @showTeamPopup)
(still glue code)

showTeamPopup: (proceed, friendsInviting) =>
  data = {inviting_friends: friendsInviting}
  popup = @popupsComponent.showPopup('team_popup', data)
  popup.onClose => proceed(friendsInviting))
DCI
class PlayTeamGameUseCase                 Use case == context
  constructor: (@game, @player) ->
    Role(@player, PlayerWithFriends)
    Role(@game,   TeamCompetition)         Roles injected runtime
  tryToEnterGameArea: () =>
    if @amIEnteringGameFirstTime()
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()
                                       data objects interact with
      @teachPlayerHowToPlay()
                                              each other
    else #n-th time...
      if @amICommingFromInvitation()
        @tellPlayerHeIsPartOfTeam()

    if @haveNotYetPickedFavPizzaCountry()
      @askPlayerToDeclareHisFavPizzaCountry()

  (more methods here)
class PlayerWithFriends
  setup: =>                                a role
    @friends = []
    @invitedFriends = []
    @acceptedFriends = []

  setInvitedFriends: (facebookUids) =>
    for facebookUid in facebookUids
      friend = new Friend({facebookUid: facebookUid})
      @invitedFriends.push(friend)

  setFriends: (friends) =>
    @friends = friends

  addFriend: (friend) =>
    existing = @getFriendByFacebookUid(friend?.facebookUid)
    if not existing?
      @friends.push(friend)
not only for
Single Page Applications
What use cases are in
   your project?
learn more about AOP and DCI and ...



   Enjoy writing
      elegant
     use cases!

Weitere ähnliche Inhalte

Was ist angesagt?

Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG CampinasFabio Akita
 
穏やかにファイルを削除する
穏やかにファイルを削除する穏やかにファイルを削除する
穏やかにファイルを削除する鉄次 尾形
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubyJason Yeo Jie Shun
 
Elixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitElixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitTobias Pfeiffer
 
Elixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitElixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitTobias Pfeiffer
 
Ruby - Uma Introdução
Ruby - Uma IntroduçãoRuby - Uma Introdução
Ruby - Uma IntroduçãoÍgor Bonadio
 
An (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonAn (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonNicholas Tollervey
 
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정itsming
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenPawel Szulc
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygookPawel Szulc
 
Test du futur avec Spock
Test du futur avec SpockTest du futur avec Spock
Test du futur avec SpockCARA_Lyon
 
Bringing Characters to Life for Immersive Storytelling - Dioselin Gonzalez
Bringing Characters to Life for Immersive Storytelling - Dioselin GonzalezBringing Characters to Life for Immersive Storytelling - Dioselin Gonzalez
Bringing Characters to Life for Immersive Storytelling - Dioselin GonzalezWithTheBest
 
The bones of a nice Python script
The bones of a nice Python scriptThe bones of a nice Python script
The bones of a nice Python scriptsaniac
 
Bringing characters to life for immersive storytelling
Bringing characters to life for immersive storytellingBringing characters to life for immersive storytelling
Bringing characters to life for immersive storytellingDioselin Gonzalez
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Kevlin Henney
 
SecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play FrameworkSecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play Frameworkjaliss
 

Was ist angesagt? (20)

Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
 
穏やかにファイルを削除する
穏やかにファイルを削除する穏やかにファイルを削除する
穏やかにファイルを削除する
 
Python 1
Python 1Python 1
Python 1
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
Elixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitElixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicit
 
Elixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicitElixir & Phoenix – fast, concurrent and explicit
Elixir & Phoenix – fast, concurrent and explicit
 
Ruby - Uma Introdução
Ruby - Uma IntroduçãoRuby - Uma Introdução
Ruby - Uma Introdução
 
An (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonAn (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to Python
 
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정
분데스리가====W­Е­4­9.сом====유료픽ポ프리메라리가ポ분데스리가일정
 
Get Kata
Get KataGet Kata
Get Kata
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heaven
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
 
Test du futur avec Spock
Test du futur avec SpockTest du futur avec Spock
Test du futur avec Spock
 
Bringing Characters to Life for Immersive Storytelling - Dioselin Gonzalez
Bringing Characters to Life for Immersive Storytelling - Dioselin GonzalezBringing Characters to Life for Immersive Storytelling - Dioselin Gonzalez
Bringing Characters to Life for Immersive Storytelling - Dioselin Gonzalez
 
The bones of a nice Python script
The bones of a nice Python scriptThe bones of a nice Python script
The bones of a nice Python script
 
Bringing characters to life for immersive storytelling
Bringing characters to life for immersive storytellingBringing characters to life for immersive storytelling
Bringing characters to life for immersive storytelling
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
 
Programação Funcional
Programação FuncionalProgramação Funcional
Programação Funcional
 
SecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play FrameworkSecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play Framework
 

Ähnlich wie Use cases in the code with AOP

Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfrozakashif85
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfasif1401
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfDEEPAKSONI562
 
Here are the instructions and then the code in a sec. Please R.pdf
Here are the instructions and then the code in a sec. Please R.pdfHere are the instructions and then the code in a sec. Please R.pdf
Here are the instructions and then the code in a sec. Please R.pdfaggarwalshoppe14
 
Thanks so much for your help. Review the GameService class. Noti.pdf
Thanks so much for your help. Review the GameService class. Noti.pdfThanks so much for your help. Review the GameService class. Noti.pdf
Thanks so much for your help. Review the GameService class. Noti.pdfadwitanokiastore
 
SCBCN17 - El camino hacia la programación declarativa
SCBCN17 - El camino hacia la programación declarativaSCBCN17 - El camino hacia la programación declarativa
SCBCN17 - El camino hacia la programación declarativaGerard Madorell
 
Sharable_Java_Python.pdf
Sharable_Java_Python.pdfSharable_Java_Python.pdf
Sharable_Java_Python.pdfICADCMLTPC
 
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdfInheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdfEvanpZjSandersony
 
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdfInheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdfvishalateen
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console componentHugo Hamon
 
public interface Game Note interface in place of class { .pdf
public interface Game  Note interface in place of class { .pdfpublic interface Game  Note interface in place of class { .pdf
public interface Game Note interface in place of class { .pdfkavithaarp
 
[EN] Ada Lovelace Day 2014 - Tampon run
[EN] Ada Lovelace Day 2014  - Tampon run[EN] Ada Lovelace Day 2014  - Tampon run
[EN] Ada Lovelace Day 2014 - Tampon runMaja Kraljič
 
I really need some help if I have this right so far. PLEASE CHANG.pdf
I really need some help if I have this right so far. PLEASE CHANG.pdfI really need some help if I have this right so far. PLEASE CHANG.pdf
I really need some help if I have this right so far. PLEASE CHANG.pdfaggarwalshoppe14
 
package com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdfpackage com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdfaparnacollection
 
I really need some help if I have this right so far. Please Resub.pdf
I really need some help if I have this right so far. Please Resub.pdfI really need some help if I have this right so far. Please Resub.pdf
I really need some help if I have this right so far. Please Resub.pdfaggarwalshoppe14
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfudit652068
 
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdf
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdfUse Netbeans to copy your last lab (Lab 07) to a new project called La.pdf
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdfashishgargjaipuri
 
The Ring programming language version 1.6 book - Part 51 of 189
The Ring programming language version 1.6 book - Part 51 of 189The Ring programming language version 1.6 book - Part 51 of 189
The Ring programming language version 1.6 book - Part 51 of 189Mahmoud Samir Fayed
 
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdf
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdfSuggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdf
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdfssuser58be4b1
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfinfo430661
 

Ähnlich wie Use cases in the code with AOP (20)

Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdf
 
Here are the instructions and then the code in a sec. Please R.pdf
Here are the instructions and then the code in a sec. Please R.pdfHere are the instructions and then the code in a sec. Please R.pdf
Here are the instructions and then the code in a sec. Please R.pdf
 
Thanks so much for your help. Review the GameService class. Noti.pdf
Thanks so much for your help. Review the GameService class. Noti.pdfThanks so much for your help. Review the GameService class. Noti.pdf
Thanks so much for your help. Review the GameService class. Noti.pdf
 
SCBCN17 - El camino hacia la programación declarativa
SCBCN17 - El camino hacia la programación declarativaSCBCN17 - El camino hacia la programación declarativa
SCBCN17 - El camino hacia la programación declarativa
 
Sharable_Java_Python.pdf
Sharable_Java_Python.pdfSharable_Java_Python.pdf
Sharable_Java_Python.pdf
 
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdfInheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
 
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdfInheritance - Creating a Multilevel Hierarchy  In this lab- you will s.pdf
Inheritance - Creating a Multilevel Hierarchy In this lab- you will s.pdf
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
public interface Game Note interface in place of class { .pdf
public interface Game  Note interface in place of class { .pdfpublic interface Game  Note interface in place of class { .pdf
public interface Game Note interface in place of class { .pdf
 
[EN] Ada Lovelace Day 2014 - Tampon run
[EN] Ada Lovelace Day 2014  - Tampon run[EN] Ada Lovelace Day 2014  - Tampon run
[EN] Ada Lovelace Day 2014 - Tampon run
 
I really need some help if I have this right so far. PLEASE CHANG.pdf
I really need some help if I have this right so far. PLEASE CHANG.pdfI really need some help if I have this right so far. PLEASE CHANG.pdf
I really need some help if I have this right so far. PLEASE CHANG.pdf
 
package com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdfpackage com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdf
 
I really need some help if I have this right so far. Please Resub.pdf
I really need some help if I have this right so far. Please Resub.pdfI really need some help if I have this right so far. Please Resub.pdf
I really need some help if I have this right so far. Please Resub.pdf
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
 
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdf
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdfUse Netbeans to copy your last lab (Lab 07) to a new project called La.pdf
Use Netbeans to copy your last lab (Lab 07) to a new project called La.pdf
 
The Ring programming language version 1.6 book - Part 51 of 189
The Ring programming language version 1.6 book - Part 51 of 189The Ring programming language version 1.6 book - Part 51 of 189
The Ring programming language version 1.6 book - Part 51 of 189
 
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdf
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdfSuggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdf
Suggestion- Use Netbeans to copy your last lab (Lab 07) to a new proje.pdf
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
 

Mehr von Andrzej Krzywda

[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?Andrzej Krzywda
 
[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?Andrzej Krzywda
 
Audit log with event sourcing
Audit log with event sourcingAudit log with event sourcing
Audit log with event sourcingAndrzej Krzywda
 
Event driven without microservices
Event driven without microservicesEvent driven without microservices
Event driven without microservicesAndrzej Krzywda
 
From legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsFrom legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsAndrzej Krzywda
 
Slack protips from Arkency
Slack protips from ArkencySlack protips from Arkency
Slack protips from ArkencyAndrzej Krzywda
 
From Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivFrom Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivAndrzej Krzywda
 
From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)Andrzej Krzywda
 
DCI - the architecture from the future
DCI - the architecture from the futureDCI - the architecture from the future
DCI - the architecture from the futureAndrzej Krzywda
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineAndrzej Krzywda
 
Service objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementService objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementAndrzej Krzywda
 
A programmer or a business consultant?
A programmer or a business consultant?A programmer or a business consultant?
A programmer or a business consultant?Andrzej Krzywda
 
Rails refactoring call for help
Rails refactoring call for helpRails refactoring call for help
Rails refactoring call for helpAndrzej Krzywda
 
[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchronicznaAndrzej Krzywda
 
Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Andrzej Krzywda
 

Mehr von Andrzej Krzywda (20)

[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
 
[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?
 
Audit log with event sourcing
Audit log with event sourcingAudit log with event sourcing
Audit log with event sourcing
 
Event driven without microservices
Event driven without microservicesEvent driven without microservices
Event driven without microservices
 
From legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsFrom legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting steps
 
Slack protips from Arkency
Slack protips from ArkencySlack protips from Arkency
Slack protips from Arkency
 
From Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivFrom Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, Lviv
 
From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)
 
From legacy to DDD
From legacy to DDDFrom legacy to DDD
From legacy to DDD
 
DCI - the architecture from the future
DCI - the architecture from the futureDCI - the architecture from the future
DCI - the architecture from the future
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMine
 
Beyond The Rails Way
Beyond The Rails WayBeyond The Rails Way
Beyond The Rails Way
 
Service objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementService objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacement
 
Developer oriented
Developer orientedDeveloper oriented
Developer oriented
 
Can you TDD Rails?
Can you TDD Rails?Can you TDD Rails?
Can you TDD Rails?
 
A programmer or a business consultant?
A programmer or a business consultant?A programmer or a business consultant?
A programmer or a business consultant?
 
Rails refactoring call for help
Rails refactoring call for helpRails refactoring call for help
Rails refactoring call for help
 
[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna
 
Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]
 
Madeleine on Rails
Madeleine on RailsMadeleine on Rails
Madeleine on Rails
 

Kürzlich hochgeladen

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024SynarionITSolutions
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024The Digital Insurer
 

Kürzlich hochgeladen (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 

Use cases in the code with AOP

  • 1. Use cases are important Andrzej Krzywda
  • 2. Use cases in the code are even more important
  • 3. class PlayTeamGameUseCase constructor: (@game, @player) -> Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 4. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 5. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Actors Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 6. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Actors Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) Roles tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 7. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Actors Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) Roles tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() Algorithm else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 8. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Actors Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) Roles tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() Algorithm else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() uses domain objects if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 9. Name class PlayTeamGameUseCase constructor: (@game, @player) -> Actors Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) Roles tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() @teachPlayerHowToPlay() Algorithm else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() uses domain objects if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here) Nothing about GUI or persistence!
  • 10. Where is? • GUI • Persistence • API calls • events
  • 11. A clean use case code is the main goal
  • 17. class GameUseCaseGlue constructor: (@gameUseCase, @game, @gui) -> execute: () => Around(@gameUseCase, 'tryToEnterGameArea', @checkFbInvitation) After (@gameUseCase, 'tryToEnterGameArea', @showTeamArea) After (@gameUseCase, 'tryToEnterGameArea', @showButtonInviteOrPostPicture) Around(@gameUseCase, 'tellPlayerHeIsPartOfTeam', @showTeamPopup) Around(@gameUseCase, 'askPlayerToLikeFanpage', @showLikePopup) Around(@gameUseCase, 'teachPlayerHowToPlay', @showTutorialPopup) Around(@gameUseCase, 'playerWantsToKnowWinnersWithPrize', @showWinnersPopup) Around(@gameUseCase, 'playerWantsToKnowPrizes', @showPrizesPopup) Around(@gameUseCase, 'askPlayerToDeclareHisFavCountry', @showDeclareCountryPopup) Around(@gameUseCase, 'iAcceptMyFriendInvitationToATeam', @onIAcceptMyFriendInvitationToATeam) Around(@gui, 'inviteClicked', @inviteFriends) # gameUseCase.inviteFriends Around(@gameUseCase, 'inviteFriends', @storeInvitationInTheDB) DB here Glue code
  • 19. (still glue code) showTeamPopup: (proceed, friendsInviting) => data = {inviting_friends: friendsInviting} popup = @popupsComponent.showPopup('team_popup', data) popup.onClose => proceed(friendsInviting))
  • 20. DCI
  • 21. class PlayTeamGameUseCase Use case == context constructor: (@game, @player) -> Role(@player, PlayerWithFriends) Role(@game, TeamCompetition) Roles injected runtime tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() data objects interact with @teachPlayerHowToPlay() each other else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam() if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavPizzaCountry() (more methods here)
  • 22. class PlayerWithFriends setup: => a role @friends = [] @invitedFriends = [] @acceptedFriends = [] setInvitedFriends: (facebookUids) => for facebookUid in facebookUids friend = new Friend({facebookUid: facebookUid}) @invitedFriends.push(friend) setFriends: (friends) => @friends = friends addFriend: (friend) => existing = @getFriendByFacebookUid(friend?.facebookUid) if not existing? @friends.push(friend)
  • 23. not only for Single Page Applications
  • 24. What use cases are in your project?
  • 25. learn more about AOP and DCI and ... Enjoy writing elegant use cases!

Hinweis der Redaktion

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n