dimanche 24 octobre 2021

Why does ChangeNotifierProvider exist?

According to Flutter's documentation here (https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple),

one way to control the state management is to use ChangeNotifierProvider(or InheritedWidget) when one of its descendants is a Consumer which is rebuilt when the underlying ChangeNotifier changes. Flutter's team reiterates that approach on the official youtube Flutter channel.

However, that means that some business logic element (ChangeNotifier) is now part of the Widget tree (which otherwise is all about how the UI will look like). So I don't understand why those classes (ChangeNotifierProvider,InheritedWidget,Consumer) even exist.

In particular, why isn't the following approach superior:

-Business logic is a singleton and a ChangeNotifier.

-Instead of Provider(...), for every Widget depending on the business logic simply do this:

BusinessLogicSingleton.instance.addListener(() {

      setState(() {

      });

at initState(...).

What am I missing here?

Should id field be optional or not?

For example, I have entity Person which can be obtained from DB, or inserted into DB.

class Person {
    id: number;
    name: string;
    age: number;
}

id field is autogenerated column in DB, so in situation when model is obtained from DB it will be always filled.

But when creating model, we are to set name and age fields.

So, in case, when we getting model from DB - id field is not optional and is always set. In case when we creating new model to insert into DB id field should be unset, and therefore in model definition should be optional.

Are there any best practices or common approaches to handle this problem?

Patterns for making two packages as loosely coupled as possible

So I'm learning to build a parser for a intro class for software design.

I have built a tokenizer package that splits my input string into Token objects that have getters for both the value and type. I can also return a raw String for value and type of the current token.

My public facing interface from the Tokenizer currently looks like this.

public Tokenizer(Grammar rules, String input)
public Token getCurrentToken() {...} // Token has public getters similar to the two methods below
public String getCurrentValue() {...}
public String getCurrentType() {...}
public void nextToken() throws InvalidTokenException {...}
public void previousToken() {...}

In my Parser class I also have a TokenReceiver(interface) and a TokenizerAdapter class (implements Receiver and my specific tokenizer)

  public void next();
  public Token getToken();
  public String getType();
  public String getValue();
  public Token getToken();
}

The rules are that each of the different steps in the parsing has to be done with different packages that are as loosely coupled as possible to any implementation details of the other packages, i.e. the parser should in theory work with any tokenizer I find(for example on Github), not just my own Tokenizer implementation, provided I just make an Adapter for it.

If I send back the Token objects from the Tokenizer then my parser will have to know about the Token objects (the getter methods specifically), which adds coupling to my Tokenizer implementation.

Sending back straight Strings for the value and type and then creating a another Token class in the Parser package and recreating Tokens objects feels instinctively wrong to me. Could an anonymous inner class for Token in the adapter class be a good solution?

I'm looking for what kind of patterns or concepts that can help me reference my Tokens from the Tokenizer while preserving a loose coupling to my specific tokenizer implementation.

Sorry if question is really stupid and the answer is really obvious, design patterns are still very abstract to me and we're learning about so many of them I have a hard time knowing which one to use for different circumstances.

How refactoring this function?

I need refactoring this function with SOLID or clean code or design patterns, any can help me? The switch I don't know if I can refactoring

I have created new functions for decoupling but switch loop it's driving me crazy

I added custom functions created by me, hasCorrectSugars check that number of sugars is 0,1 or 2 and checkSugars check that exists sugars...

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $this->setDrinkType($input);

    if (in_array($this->drinkType, $this->allowedDrinkTypes)) {
        /**
         * Tea       --> 0.4
         * Coffee    --> 0.5
         * Chocolate --> 0.6
         */
        $money = $input->getArgument('money');
        switch ($this->drinkType) {
            case 'tea':
                if ($money < 0.4) {
                    $output->writeln('The tea costs 0.4');
                    return 0;
                }
                break;
            case 'coffee':
                if ($money < 0.5) {
                    $output->writeln('The coffee costs 0.5');
                    return 0;
                }
                break;
            case 'chocolate':
                if ($money < 0.6) {
                    $output->writeln('The chocolate costs 0.6');
                    return 0;
                }
                break;
        }
        if ($this->hasCorrectSugars($input)) {
            $this->checkSugars($input, $output);
            return 0;
        }
        $output->writeln('The number of sugars should be between 0 and 2');
        return 0;
    }
    $output->writeln('The drink type should be tea, coffee or chocolate');
    return 0;
}

    protected function hasCorrectSugars($input): bool
{
    $sugars = $input->getArgument('sugars');

    if ($sugars >= $this->minSugars && $sugars <= $this->maxSugars) {
        return true;
    }

    return false;
}

protected function checkSugars($input, $output): void
{
    $sugars = $input->getArgument('sugars');

    $output->write('You have ordered a ' . $this->drinkType);
    $this->isExtraHot($input, $output);
    $output->write(' with ' . $sugars . ' sugars');
    if ($sugars > 0) {
        $output->write(' (stick included)');
    }
    $output->writeln('');
}

Public and Private API Auth with Microservices

BACKGROUND

I am wanting to develop a public and private API from my SaaS.

The web app would be accessible via app.example.com, with the private API being located at app.example.com/api.

The plan would be to have the public API that can be used externally at api.example.com.

Also, not all features/methods/endpoints will be available between the APIs.


QUESTION

Would it be best to write 1 microservice between the APIs (e.g. just User Microservice), or write 2 microservices (e.g. App User Microservice & API User Microservice) - one for each API?

I ask this as the intent is to use sessions or JWTs for the private API, and API keys/secrets (in headers) for the public API. I am unsure if it is best to implement both auth schemes in 1 service or have 2 separate services.

In other words: should I develop 2 microservices for the same feature but with different auth requirements, or should I develop 1 microservice but make it compatible with 2 multiple schemes?


EXTRA

Just as an FYI, Nginx would be used as a reverse proxy (API Gateway). I plan to implement auth within each microservice as opposed to within an API gateway to make the system more decentralized.

Thank you for your suggestions and help.

samedi 23 octobre 2021

How to implement behaviour in multiple classes?

Suppose n classes, each one of those got the same behavior at insertion in database:

  1. create connection
  2. query definition
  3. data for query definition
  4. error handling(in case duplicated or integrity errors in database)
  5. close connection

Some of the classes don't need this implementation, others need one implementation(says insert_user implementation) and other ones need two or more implementation(insert_reasons, insert_reason_video each one of those with different query, data definition and error handling)

How can I avoid copy/paste code. I'm coding in python

class One:
    def insert_objects(self, objects=None):
        db, cursor = open_connection()
        query_insert_object = """INSERT INTO objects (name, model_id)
        VALUES (%s,(SELECT id FROM models WHERE name=%s));"""
        try:
            for object in objects:
                object_data = (object, self.name)
                cursor.execute(query_insert_object, object_data)
            db.commit()
        except IntegrityError as e:
            if e.msg == "Column 'model_id' cannot be null":
                print("model_id no ha sido insertado, inserte el modelo")
            if e.msg == "Duplicate entry 'perrito-3' for key 'name'":
                print("model.name-object.name previamente insertado para el modelo: {}".format(self.name))
            db.rollback()
        finally:
            close_connection(db, cursor)

    def insert_model(self):
        db, cursor = open_connection()
        query_insert_model = """INSERT INTO models(name) VALUES (%s);
        """
        data_model = (self.name)
        try:
            cursor.execute(query_insert_model, data_model)
            db.commit()
        except IntegrityError a e:
            print("model.name previamente insertado con valor: {}".format(self.name))
            db.rollback()
        finally:
            close_connection(db, cursor)

class Two:
    def insert_user(self):
        db, cursor = open_connection()
        query_insert_user = """INSERT INTO users (id, name) VALUES (%s,%s);"""
        data_user = (self.id, self.name)
        try:
            cursor.execute(query_insert_user, data_user)
            db.commit()
        except IntegrityError:
            print("user.id previamente insertado con valor: {}".format(self.id))
            db.rollback()
        finally:
            close_connection(db, cursor)
.
.
.
class N:
    def insert(self):
        """Generalization of above code"""
        db, cursor = open_connection()
        query = get_query()
        data = get_data()
        try:
            execute_insert()
        except:
            error_handling()
        finally:
            close_connection()

Note: I've already seen Strategy Pattern but still no found solution for multiple implementations

How to implement conditional visibility of methods in a Builder design pattern?

How to change the visibility of methods in a Builder design pattern ?

For example I have this Builder :

public class Builder {

    public Builder a() {
        //
        return this;
    }

    public Builder b() {
        //
        return this;
    }

}

User can use the API and do this :

new Builder().a().b();
new Builder().a();
new Builder().b();
new Builder().b().a();

I want to allow him to access method b() only if a() has been called :

new Builder().a().b();
new Builder().a();

A simple example could be a SQL request Builder. You shouldn't be allowed to call when() before select().

How to do so?