mercredi 23 juin 2021

How to call a method at runtime based on a string value using springboot/ any java design?

Consider below example, I want to call appropriate produce method based on vehicle, where vehicle can be "car" or "bike" or "van"

Class Company {

public void manufacture(String vehicle) {

   //How to call appropriate **produce** method based on string(vehicle) passed as param in this method **without using if or switch condition here**?

}

}


Class AutoMob {

public void produce(Car c, ....){

}

public void produce(Bike b, ....){

}

public void produce(Van l, ....){

}

}

I dont want to use reflection or condition here and looking for design based approach or any idea using springboot?

Thanks in advance!!

mardi 22 juin 2021

is there a good design pattern for this classes relation in Python?

So imagine I have a class A, and class B can take class A as its member and use class A's functionality to do the job, like this

 class B:
    def __init__(self, A):
        self.A = A

    def do_something(self):
        # some other jobs ....
        self.A.do_the_job()

This is a straightforward design. However, in my case, class A can be accessed and modified outside of B as well, then this design is a little strange because although A is a member class of B, actually A could be changing its status outside of B. Therefore I change it to this design

 class B:
    def __init__(self):
        pass

    def do_something(self, A):
        # some other jobs ....
        A.do_the_job()

It is definitely perfectly fine, the only ugly thing is, right now everytime when I call B.do_something, I need to pass class A as its argument. Actually class B has several other functions that will use class A as well.

I wonder if there is any better design pattern to deal with this kind of situation?

How to refactor two similar methods and create correct readeable methods?

I have two similar methods in my controller:

First method:

public function parseDataLayerEvent()
{
    $events = $this->pixel_log->data['dataLayer'];

    if (!is_array($events)) {
        throw new \Exception('dataLayer is not an array');
    }
    foreach ($events as $event) {
        if (!isset($event['event'])) {
            continue;
        }
        if (!isset($event['ecommerce'])) {
            continue;
        }
        if (!isset($event['ecommerce']['purchase'])) {
            continue;
        }
        $purchase = $event['ecommerce']['purchase'];

        $validator = Validator::make($purchase, [
            'products.*.id' => 'required|string',
            'products.*.name' => 'required|string',
            'products.*.price' => 'required|numeric',
            'products.*.variant' => 'nullable|string',
            'products.*.category' => 'nullable|string',
            'products.*.quantity' => 'nullable|numeric|min:1',
            'actionField.id' => 'required|string',
            'actionField.action' => 'nullable|string|in:purchase',
            'actionField.revenue' => 'required|numeric',
        ]);

        if ($validator->fails()) {
            logger()->debug('Order validation failure');
            throw new ValidationException($validator);
        }

        $order_id = $purchase['actionField']['id'];
        $order = Order::query()
            ->where('pp_id', '=', $this->pixel_log->pp_id)
            ->where('order_id', '=', $order_id)
            ->first();

        if (!$order) {
            logger()->debug('Order №' . $order_id . ' does not exist, creating...');
            $order = new Order();
            $order->pp_id = $this->pixel_log->pp_id;
            $order->order_id = $order_id;
            $order->status = 'new';
        } else {
            logger()->debug('Order №' . $order_id . ' exist, updating');
        }
        $order->pixel_id = $this->pixel_log->id;
        $order->datetime = $this->pixel_log->created_at;
        $order->partner_id = $this->link->partner_id;
        $order->link_id = $this->link->id;
        $order->click_id = $this->pixel_log->data['click_id'] ?? null;
        $order->web_id = $this->pixel_log->data['utm_term'] ?? null;
        $order->offer_id = $this->link->offer_id;
        $order->client_id = $this->client->id;
        $order->gross_amount = 0;
        foreach ($purchase['products'] as $product_data) {
            $order->gross_amount += $product_data['price'] * ($product_data['quantity'] ?? 1);
        }
        
        $total_products = count($purchase['products']);
        $order->cnt_products = $total_products;
        $order->save();

        logger()->debug('Products found: ' . $total_products);
        foreach ($purchase['products'] as $product_data) {
            $product_id = $product_data['id'];
            $product = OrdersProduct::query()
                    ->where('pp_id', '=', $this->pixel_log->pp_id)
                    ->where('order_id', '=', $order->order_id)
                    ->where('product_id', '=', $product_id)
                    ->first() ?? new OrdersProduct();

            // if ($product->wasRecentlyCreated === false) {
            //     if (!is_null($product->reestr_id)) {
            //         return;
            //     }
            //     if ($product->status !== 'new') {
            //         return;
            //     }
            // }

            $product->pp_id = $this->pixel_log->pp_id;
            $product->order_id = $order->order_id;
            $product->parent_id = Order::query()
                ->where('pp_id', '=', $this->pixel_log->pp_id)
                ->where('order_id', '=', $order_id)
                ->first()->id;
            $product->datetime = $order->datetime;
            $product->partner_id = $order->partner_id;
            $product->offer_id = $order->offer_id;
            $product->link_id = $order->link_id;
            $product->product_id = $product_id;
            $product->product_name = trim(($product_data['name'] ?? '') . ' ' . ($product_data['variant'] ?? ''));
            $product->category = $product_data['category'] ?? null;
            $product->price = $product_data['price'];
            $product->quantity = $product_data['quantity'] ?? 1;
            $product->total = $product->price * $product->quantity;
            $product->web_id = $order->web_id;
            $product->click_id = $order->click_id;
            $product->pixel_id = $order->pixel_id;
            $product->amount = 0;
            $product->amount_advert = 0;
            $product->fee_advert = 0;
            $product->save();
            logger()->debug('Saved product: ' . $product->product_name);
        }
        $this->pixel_log->is_order = true;
        return true;
    }
}

Second method:

public function parseCheckoutDataLayerEvent()
{
    $events = $this->pixel_log->data['dataLayer'];

    if (!is_array($events)) {
        throw new \Exception('dataLayer is not an array');
    }
    foreach ($events as $event) {
        if (!isset($event['event'])) {
            continue;
        }
        if (!isset($event['ecommerce'])) {
            continue;
        }
        if (!isset($event['ecommerce']['checkout'])) {
            continue;
        }

        $purchase = $event['ecommerce']['checkout'];
        $validator = Validator::make($purchase, [
            'products.*.id' => 'required|string',
            'products.*.name' => 'required|string',
            'products.*.price' => 'required|numeric',
            'products.*.variant' => 'nullable|string',
            'products.*.category' => 'nullable|string',
            'products.*.quantity' => 'nullable|numeric|min:1',
        ]);

        if ($validator->fails()) {
            logger()->debug('Ошибка валидации заказа');
            throw new ValidationException($validator);
        }

        $order_id = $this->pixel_log->data['ed']['order_id'];
        $order = Order::query()
            ->where('pp_id', '=', $this->pixel_log->pp_id)
            ->where('order_id', '=', $order_id)
            ->first();

        if (!$order) {
            logger()->debug('Order №' . $order_id . ' does not exist, creating...');
            $order = new Order();
            $order->pp_id = $this->pixel_log->pp_id;
            $order->order_id = $order_id;
            $order->status = 'new';
        } else {
            logger()->debug('Order №' . $order_id . ' exist, updating');
        }
        $order->pixel_id = $this->pixel_log->id;
        $order->datetime = $this->pixel_log->created_at;
        $order->partner_id = $this->link->partner_id;
        $order->link_id = $this->link->id;
        $order->click_id = $this->pixel_log->data['click_id'] ?? null;
        $order->web_id = $this->pixel_log->data['utm_term'] ?? null;
        $order->offer_id = $this->link->offer_id;
        $order->client_id = $this->client->id;
        $order->gross_amount = 0;
        foreach ($purchase['products'] as $product_data) {
            $order->gross_amount += $product_data['price'] * ($product_data['quantity'] ?? 1);
        }
        // $order->gross_amount = $purchase['actionField']['revenue'] - ($purchase['actionField']['shipping'] ?? 0);
        $order->cnt_products = count($purchase['products']);
        $order->save();

        logger()->debug('Products found: ' . count($purchase['products']));
        foreach ($purchase['products'] as $product_data) {
            $product_id = $product_data['id'];
            $product = OrdersProduct::query()
                    ->where('pp_id', '=', $this->pixel_log->pp_id)
                    ->where('order_id', '=', $order->order_id)
                    ->where('product_id', '=', $product_id)
                    ->first() ?? new OrdersProduct();

            // if ($product->wasRecentlyCreated === false) {
            //     if (!is_null($product->reestr_id)) {
            //         return;
            //     }
            //     if ($product->status !== 'new') {
            //         return;
            //     }
            // }

            $product->pp_id = $this->pixel_log->pp_id;
            $product->order_id = $order->order_id;
            $product->datetime = $order->datetime;
            $product->partner_id = $order->partner_id;
            $product->offer_id = $order->offer_id;
            $product->link_id = $order->link_id;
            $product->product_id = $product_id;
            $product->product_name = trim(($product_data['name'] ?? '') . ' ' . ($product_data['variant'] ?? ''));
            $product->category = $product_data['category'] ?? null;
            $product->price = $product_data['price'];
            $product->quantity = $product_data['quantity'] ?? 1;
            $product->total = $product->price * $product->quantity;
            $product->web_id = $order->web_id;
            $product->click_id = $order->click_id;
            $product->pixel_id = $order->pixel_id;
            $product->amount = 0;
            $product->amount_advert = 0;
            $product->fee_advert = 0;
            $product->save();
            logger()->debug('Saved product: ' . $product->product_name);
        }
        $this->pixel_log->is_order = true;
        return true;
    }
}

As you see, I have approximately similar methods in terms of logic and operations. How can I rewrite these methods in the correct way using design patterns KISS, DRY ?

function.constructor vs function.prototype.constructor

I've ready quite a bit of blog post and stackoverflow questions but can't get good understanding regarding this.

Why is it necessary to set the prototype constructor?

Trying to understand the difference between prototype and constructor in JavaScript

Constructors in JavaScript objects

JavaScript inheritance and the constructor property

Understanding the difference between Object.create() and new SomeFunction()

Question:

function person(fname) {
  this.fname = fname;
}

let obj1 = new person('first'); //works well
console.log(obj1);
let obj2 = new person.prototype.constructor('second'); //works well
console.log(obj2);
//now the query
console.log(person.constructor); //1. it prints  function Function() { [native code] } what does it mean
let obj3 = new person.constructor('third') // 2. why this doesn't work ?
console.log(obj3); //

now as we know that a every function in javascript has a property call prototype which is an object which has a property called constructor which points back to the function on which prototype object is a property. - correct me if I'm wrong with this

so according to above statement person.prototype.constructor === person (both are the same)

Query: 1 person.constructor prints function Function() { [native code] } what does it means, please explain in detail.

Query: 2 why this new person.constructor('randon') doesn't work ?

Query: 3 what exactly is person.constructor and how it's different from person.prototype.constructor ?

Is it a better pattern to derive a class or just add to a method to existing class?

This question is specifically related to python but I guess it could be valid for any OO language. I have defined a Query class that imports the pyodbc package and groups in a single class some of its functionality, allowing to simplify the execution of queries against a database (for example, I have a run() method that executes the query and retrieves the resulting data).
pyodbc just allows positional parameter binding (binding each '?' in the source query with the corresponding element of a list of parameters) but I'd also like to have named parameter binding (binding each '@variable' in the source query with the corresponding value for a dict element having @variable as key). So, I need to transform a named parameter query into a positional parameter query and do some rework in the input parameterse. My question is related to the most correct way to achieve this. Is it better to:

  1. Define a new method of the class Query, say run_parsed(), that expects a query with the named parameter notation (@variable), and call that method when you need to run a query that way, or
  2. Define a derived class from Query (say Query_named), and use that class just when you want to run a named parameter query, and the base Query class when you want to run a positional parameter query?

Thanks for your insights

Should i use Mediator Design Pattern instead of Dependency Injection?

I am currently learning about MediatoR Pattern, And i feel like it is an alternative - or another solution for the same problem -, And i couldn't figure out when to use it instead of dependency injection.

So any one may clarify that?

How to resolve recursive dependency C#

I have a problem with two interfaces calling each other.
In my model each Component can contain a Grid. And each Grid can contain a Component.
I am trying implement mapper for this model with Dependency Injection.

public interface IComponent
{
    //if we found a grid in the content, we should call Map method from IGrid 
    ComponentViewModel Map(IContent content);
}

public interface IGrid
{
    //if we found a component in the content, we should call Map method from IComponent 
    GridViewModel Map(IContent content);
}

But now I have an error "Recursive dependency detected"
I fixed it when I changed it to static classes, but I think it is dirty hack.

I also tried to use factory for creating an instance for these interfaces in the both methods.
        var container = Current.Factory.Concrete as ServiceContainer;
        var mapper = container.GetInstance<IComponent>();

But it doesn't work too, because each instance of the interface expects an instance of another to come to its constructor.

What pattern should I implement to keep DI in my project?