mardi 22 février 2022

Which is the design pattern to go in this situation?

I'm working on something and I've already used some design patterns, but none of them fulfills my needs completely, and that makes me think I might use a combination of patterns, but I'm a little bit stuck so I will explain the situation here and hopefully somebody could add some light about the right way to work on this one. The language I'm working with is PHP 8, in case that it helps or limits on finding a solution.

I have a class that builds, via static methods, GraphQL queries and mutations. I can't give you the exact implementation but it's something like this:

class GraphQLBuilder
{
    public static function getSettings(): string
    {
        return <<<GRAPHQL
            query{
                settings{
                    id
                    name
                    alias
                }
            }
GRAPHQL;
    }

    public static function getSetting(string $id): string
    {
        return <<<GRAPHQL
            query{
                setting(id: "$id"){
                    id
                    name
                    alias
                }
            }
GRAPHQL;
    }

    public static function setName(string $id, string $name)
    {
        return <<<GRAPHQL
            mutation {
                setting(
                    id: "$id",
                    name: "$name"
                ) {
                    id
                    name
                }
            }
GRAPHQL;
    }
}

The GraphQL server is migrating to a new version and the field alias will be called aka, but for compatibility reasons they will keep the old field for a year. I need to create a new version of the Builder class that supports the new aka field, so it will have different getSettings() and getSetting($id) methods, but the setName() method will be the same.

My goal is to create a class that works with all the methods used (in the example, getSettings(), getSetting($id) and setName($id, $name)) but fallbacks to a base class for the not implemented methods. I'd use an interface to check that all the methods are covered in the new class.

So far, I've tried to use the strategy pattern by creating a BuilderFactory that returns whether GraphQLBuilder or GraphQLBuilderNewVersion, so the methods could be used at the same way: builder::getSettings(), but that makes me include the setName() method, without any difference, in the GraphQLBuilderNewVersion, and I wouldn't like to do that because I don't want to maintain the same code in different classes.

Another approach was creating an abstract class GraphQLAbstractBuilder that has a static $settingProvider attribute, and a GraphQLBuilderBase that holds all the methods that would be needed to fallback. Both GraphQLBuilder or GraphQLBuilderNewVersion extend from GraphQLBuilderBase and implement their own specific methods, but I'd like that those specific methods are controlled in the interface but they don't have a fallback, so I can make them fail in a controlled way.

I feel like I'm overthinking this and it may be a very straightforward solution, so any advice or tip to make a robust design on this problem will be really appreaciated.

Aucun commentaire:

Enregistrer un commentaire