Search code examples
javascriptnode.jsoopdesign-patternsmediator

Passing Methods vs Generic Objects vs Event Specific Objects


I often reach a crossroad in my code when it comes to passing methods vs generic objects vs specialised objects. Let me explain.

I am using the mediator pattern. I have DAO's which have generic methods based on a specific entity of the database it's targeting.If a method is targeting that specific entity I am putting it in that class. Sometimes the entity targeted is a table, other times it's a column within a table depending on whether this DAO class starts to be complex or not and needs breaking down. Then I have service type classes where it receives the DAO as the dependancy. This is an additional layer but it prevents me from passing my DAO classes directly into a mediator. This is so that I can unit test each class outside of the main meditator and call methods from each service class inside the mediator. This also allows me to potentially pick service objects which mediate together and pass that mediator into the main mediator if my dependancies start to grow.

However I often struggle when deciding upon the next step. Do I

  1. pass the whole service object to the mediator giving it access to things it never intends to use. Ive read this goes against the Least Privilidge principle. Like this

    const turn = new ServerTurnMediator(
     new DiceService(DiceDAO),
     new PlayerMoneyService(PlayerMoneyDAO)
    )
    
  2. Pass only methods from the specific service class to the mediator using and bind the methods I am passing in to the instance of the service object like this :

     const playerMoneyService = new PlayerMoneyService(PlayerMoneyDAO);
     const methodFromPlayerMoneyService = playerMoneyService.addMoneyToPlayer.bind(playerMoneyService);
    
     const turn = new ServerTurnMediator(
      new DiceService(DiceDAO),
      methodFromPlayerMoneyService
     )
    

here I pass methodFromPlayerMoneyService into the mediator class that requires it. If the mediator then needs 3 other methods from this service objects shall I repeat this binding process for each method?When is this too much ?

  1. Start to create more event specific service objects that take in the DAO but rename the service objects around what they are trying to achieve and then pass the service object in full into the mediator. The methods are cohesive and are all referenced and possibly used in specific situations within the mediator class and there are no derelict methods within the class for the given mediator its passed into. If I did this I could use either inheritance or composition to extend each event specific class so that I prevent repeating methods in different event specific classes.

    const turn = new ServerTurnMediator(
     new DiceService(DiceDAO),
     new PlayerMoneyIncreaserService(PlayerMoneyDAO)
    )
    

This also feels like I am adhering to SRP more, but suddenly I will need a lot more classes specific to each event that occurs rather a single service object.

  1. I could do the same as 3 but also create the same inheritance hierarchy or composition within my DAO classes so that the correct service object receives the DAO that has access to the functionality the service object is trying to achieve.

I am using interfaces where appropriate and my service classes often receive different DAO implementations with the same named methods or abstract methods.

Is there a right or wrong answer here or any specific moments that scream out for refactoring ? If so then why ?


Solution

  • Why not option 4 where my Dao’s are also event specific where one service object accepts one Dao which completes the db functionality when called from the service class? Rather than the event specific service class accepting a Dao with methods it may not need ?

    Having known this information, I would stay with the fourth option because it is a way to encourage use SOLID principles in code. It would also look like Traditional "N-Layer" architecture applications

    This also feels like I am adhering to SRP more, but suddenly I will need a lot more classes specific to each event that occurs rather a single service object.

    yeah, you are right. However, when your code has less lines of code, it is:

    • easier to read it for future readers (this person can also be you in two weeks)
    • easier to make changes in it
    • easier to write tests
    • easier to give name for methods and classes

    If I did this I could use either inheritance or composition to extend each event specific class so that I prevent repeating methods in different event specific classes.

    yeah, you are right. You can read more here when to use composition or inheritance