dimanche 7 mai 2023

Crash occurs when detaching from subject

I am trying to implement observer design pattern using C++ 11 smart pointers. Below is my code. The below program crashes if we try to remove the observer from the subject.

  //observer
    
    class iobserver
    {
    
    public:
        virtual void update() = 0;
    
    };
    
    
    
    using ObserverSPtr = shared_ptr<iobserver>;
    class isubject
    {
    public:  
    
        virtual void notifyall() = 0;
        virtual void attach(ObserverSPtr obserber) = 0;
        virtual void detach(ObserverSPtr obserber) = 0;
    
        virtual int&  getState() = 0;
        virtual void setState(int state) = 0;
    };
    
    
    using ObserverList = list< ObserverSPtr>;
    using SubjectSptr = shared_ptr<isubject>;
    
    
    class Subject :public isubject
    {
        int state;
        ObserverList subscribed_observers;
    
    public:
    
        Subject()
        {
            state = -1;
            subscribed_observers.clear();
        }
        void attach(ObserverSPtr observer)
        {
            subscribed_observers.push_back(observer);
        }
    
        void detach(ObserverSPtr observer)
        {
            subscribed_observers.remove(observer);
        }
    
        void notifyall()
        {
            for (auto &observer : subscribed_observers)
            {
                observer->update();
            }
        }
    
        int& getState()
        {
            return state;
        }
    
        void setState(int state)
        {
           this->state = state;
           this->notifyall();
        }
    
    };
    
    class Observer :public iobserver
    {
        weak_ptr<isubject> subject;
    public:
    
        Observer( SubjectSptr subject)
        {
            this->subject = subject;
            subject->attach(static_cast<ObserverSPtr>(this));
            
        }
        void update()
        {
            cout << "Subject got updated to new state:" << subject.lock()->getState() << endl;
        }
    };

 

Below is the driver code

    int main()
    {
        //observer
        /*
         1.subject
         2.observer
         
        
        */
    
        auto subject = make_shared<Subject>();
        auto observer1 = make_shared<Observer>(subject);
        auto observer2 = make_shared<Observer>(subject);
        auto observer3 = make_shared<Observer>(subject);
        subject->detach(observer3);
        subject->setState(2);
        
        
                return 0;
    }

Crash occurs when we try to detach observer3 from subject. Can anyone help me with this? How to efficiently implement observer pattern using smart pointers?

samedi 6 mai 2023

Why is class and subclass reduction a particular consequence of the Prototype design pattern?

I read the Design Patterns book (written by the Gang of Four) and I'm now recapping on the Prototype Design pattern. In the consequence section, of the Prototype design pattern, (explained on page 119 and 120) the following consequences are listed:

  • Specifying new object by varying values
  • Reduced subclassing

The first consequence, specifying new object by varying values, seems to me not really a consequence of the Prototype design pattern. The consequence is elaborated, I quote:

Highly dynamic systems let you define new behavior through object composition - by specifying values for an object's variables, for example - and not by defining new classes. This kind of design lets users define new "classes" without programming. In fact, cloning a prototype is similar to instantiating a class. The Prototype pattern can greatly reduce the number of classes a system needs.

This means we can apply the Prototype design pattern to reduce classes by 'cloning' and 'shaping' an existing class/object. However, this doesn't seem to be a really 'distinctive' consequence of the Prototype design pattern. The Prototype pattern states nothing about the 'shaping' of the cloned object. On top of that, we can reduce classes without cloning, by just 'new-ing' and 'shaping'.

The second consequence, reduced subclassing, seems also not really a consequence of the Prototype design pattern. The consequence is elaborated, I quote:

Factory Method often produces a hierarchy of Creator classes that parallels the product class hierarchy. The Prototype pattern lets you clone a prototype instead of asking a factory method to make a new object. Hence you don't need a Creator class hierarchy at all.

The Prototype pattern might indeed reduce subclassing when applied instead of the Factory Method pattern. However, this seems again not really a 'distinctive' consequence of the Prototype design pattern. An alternative to a Clone function, within the Product, could be a Create function. This would also make the Creator hierarchy redundant and provide the identical consequence.

My question: Why is class and subclass reduction a particular consequence of the Prototype design pattern?

vendredi 5 mai 2023

How to pick between CDC, Event Sourcing, CQRS and Outbox Pattern?

I'm studying System Design and I'm looking at distributed transactions right now. The basics on how each of these work is pretty clear to me but understanding how to pick the right one for the job isn't. Also would really like to understand the pros and cons of each.

How to prevent a context class using the state design pattern from having too many responsibilities?

I am making use of the state design pattern for a project of mine where I have a Car class which is the context class and it can have 3 states - neutral, drive and park. In each of those states, the car can execute different actions such as in Neutral, you can play a movie in the car, in Drive you can do something else and in Parked as well.

Now, I can see the benefits of the state design pattern, not using too many if statements and keeping logic separate for each state and making it easily extensible code but after some thinking I am not sure how to prevent the Context class from having way too many responsibilities. At the moment I have just a few actions but in the future I might want to add like 5-6 actions per different state and then my Context class will be full, in addition to keeping track of the speed of the car, fuel etc.

First of all, is that a problem and second, if yes how to prevent that?

I tried researching online but could not see any articles on the Context class having too many responsibilities which led me to thinking that maybe this is normal but still I am not completely sure.

How can I create a scalable solution for implementing state transitions in Laravel 7, given that the client frequently requests changes to the states?

I have a project in Laravel 7, and I need to help with good practices and design patterns to implement it, I have a class ManagementPlan who has states, depending on its state when its approved or rejected, updates its state to another depending on the previous state.

The flow of states and transitions is as follows:

  1. Draft: this status can only be approved and goes to the "Awaiting admissibility" state
  2. Awaiting admissibility: this state can be approved and change to "Under Review" or rejected and go to "Admissibility Observed"
  3. Admissibility Observed: this state can only be approved and becomes "Review Admissibility"
  4. Review Admissibility: this state can be approved and changes to "Under Review" or rejected and becomes "Inadmissible"
  5. Under Review: final state approved
  6. Inadmissible: final state rejected

Now, to handle the states and transitions of the ManagementPlan class in a maintainable and scalable way, I've think to implement the State Design Pattern.

Here's an example implementation of the State Design Pattern for my ManagementPlan class:

  • Create an abstract base class called State that defines the interface for all state classes:
abstract class State {
    protected $plan;

    public function __construct(ManagementPlan $plan) {
        $this->plan = $plan;
    }

    abstract public function approve();
    abstract public function reject();
}
  • Create concrete state classes for each state of the ManagementPlan:
class DraftState extends State {
    public function approve() {
        $this->plan->setState(new AwaitingAdmissibilityState($this->plan));
    }

    public function reject() {
        // Do nothing or throw an exception, since a draft can't be rejected
    }
}

class AwaitingAdmissibilityState extends State {
    public function approve() {
        $this->plan->setState(new UnderReviewState($this->plan));
    }

    public function reject() {
        $this->plan->setState(new AdmissibilityObservedState($this->plan));
    }
}

class AdmissibilityObservedState extends State {
    public function approve() {
        $this->plan->setState(new ReviewAdmissibilityState($this->plan));
    }

    public function reject() {
        // Do nothing or throw an exception, since admissibility observed can't be rejected
    }
}

class ReviewAdmissibilityState extends State {
    public function approve() {
        $this->plan->setState(new UnderReviewState($this->plan));
    }

    public function reject() {
        $this->plan->setState(new InadmissibleState($this->plan));
    }
}

class UnderReviewState extends State {
    public function approve() {
        // Do nothing or throw an exception, since under review is already approved
    }

    public function reject() {
        // Do nothing or throw an exception, since under review can't be rejected
    }
}

class InadmissibleState extends State {
    public function approve() {
        // Do nothing or throw an exception, since inadmissible is already rejected
    }

    public function reject() {
        // Do nothing or throw an exception, since inadmissible can't be rejected
    }
}
  • Modify the ManagementPlan class to keep track of its current state and delegate the approve() and reject() methods to the current state:
class ManagementPlan {
    protected $state;

    public function __construct() {
        $this->state = new DraftState($this);
    }

    public function setState(State $state) {
        $this->state = $state;
    }

    public function approve() {
        $this->state->approve();
    }

    public function reject() {
        $this->state->reject();
    }
}

the problem I have with this solution is that the client always adds more states, so I don't know if this is recommended.

I also thought, in create a ManagementPlanState where to storage the states that coould be in the ManagementPlan

class ManagementPlanState {
    protected $fillable = [
        'name',
        'description',
        'state_to_approved',
        'state_to_rejected',
        'users_allow_change_state',
        'process',
        'first_state',
    ];
}

Then in my ManagementPlan class update the state depending of the current state and if it is being approved or rejected.

class ManagementPlan {
    protected $state;

    public function approve() {
        $managementPlanState = ManagementPlanState::where('state', $this->state)->first();
        $this->update([
            'state' => $managementPlanState->state_to_approved
        ]);
    }

    public function reject() {
        $managementPlanState = ManagementPlanState::where('state', $this->state)->first();
        $this->update([
            'state' => $managementPlanState->state_to_rejected
        ]);
    }
}

I would appreciate your experiences in this case and what do you think is the best solution, always taking into account that the client likes to add and change the states.

I'm concerned about the maintainability and scalability of your solution, especially since the client frequently adds and changes the states.

I'm looking for feedback and advice on which solution would be better in terms of maintainability and scalability, given your particular situation.

mercredi 3 mai 2023

Thin or Fat Structures

So say we have a User struct that represents some User object that in a web application. The User needs to be: Saved in the database Have their password set Sent an email to the attached email address

In general, there are two flavors of implenentation. One is to create a fat User class and add StoreUserinDB, SetPassword, SendEmail as methods to the User Class. This is the way that I am most naturally inclined to.

Another way is to encapsulate the three different methods into their own Classes/Modules, and then have a very thin User Class (basically zero methods, just fields) that interacts with each of these modules separately.

I know under SOLID design principles, the second way is preferred, but I would like to hear some personal anecdotes/gotchas for people who have used both methods, and could go through why one is preferrable over the other, and under which (all?) circumstances. On a personal note, I favor the first approach, because it keeps all of the logic and data in the same place, instead of forcing you to look across different locations to find the info.

SAGA Pattern in a macro-services Spring Boot Web application

I'm trying to understand what could be the best solution to manage a Web application in Spring Boot made of "Macro-services" and if the SAGA Pattern (Orchestrator) can be adequate in this context with or without the use of an Event Bus .

I try to describe the scenario we have:

N "Macro-services" where each is a particular workflow to manage the onboarding - unboarding of users in a system made up of different databases.

Flow A (Onboarding utente) Spring Boot App A

Step 1

  1. Filling in a form
  2. Data entry on a MongoDB database
  3. Entering data into a MySQL database
  4. Entering data on Active Directory
  5. Create an account on Salesforce
  6. Sending an email with a link to user X

Step 2

  1. User X receives the email with a link
  2. Click on the link that leads to a form
  3. Compilation of the form
  4. Data update on MongoDB
  5. Data update on MySQL

Flow B (Unboarding utente) Spring Boot App B

  • Conceptually similar to flow A but with reverse operations regarding data entry and updating.

Currently Flow A and B are two separate applications built with Spring Boot and share the code for the "Repository Layer" (external Lib in a multi-module Maven application) when there is a need to write/read from databases (MongoDB, MySQL, ActiveDirectory etc.)

The order of operations within the single flow is important and should be able to have a mechanism to manage the restart of the flow from its point of interruption.

Example without errors: Writing to MongoDB => Writing to MySQL => Writing to Active Directory => Salesforce API call => Sending email

Example with errors:

Writing to MongoDB => Writing to MySQL => Failure Writing to Active Directory => Error log

Manual Flow Restart:

Skip Writing to MongoDB => Skip Writing to MySQL => Writing to Active Directory => Salesforce API Call => Sending Email

As I indicated above we don't have separate micro-services that communicate via an Event Bus but several monolithic applications each dedicated to a distinct application flow that affects different databases (and not only).

Is it possible/recommended to use the SAGA pattern (Orchestrator) with REST APIs instead of an Event bus in this case?

Advantages and disadvantages?

If we wish we could still use an Event bus since we are working on AWS.

Thanks