สถาปัตยกรรม
สถาปัตยกรรมSOLID

SOLID

Gato GraphQL ใช้แนวทาง SOLID สำหรับสถาปัตยกรรมซอฟต์แวร์ โดยจัดเตรียม entity ที่แตกต่างกันเพื่อรับผิดชอบในแต่ละด้าน เพื่อให้โค้ดสามารถบำรุงรักษา ขยาย และทำความเข้าใจได้ง่าย

นี่คือตัวอย่างที่ plugin จัดเตรียม user entity ไว้แล้ว ประเภท User ถูกจัดเตรียมผ่านโค้ดนี้:

class UserTypeResolver extends AbstractTypeResolver
{
  public function getTypeName(): string
  {
    return 'User';
  }
 
  public function getSchemaTypeDescription(): ?string
  {
    return $this->translationAPI->__('Representation of a user', "users");
  }
 
  public function getID(object $user)
  {
    return $this->usersAPI->getUserId($user);
  }
 
  public function getTypeDataLoaderClass(): string
  {
    return UserTypeDataLoader::class;
  }
}

type resolver ไม่ได้โหลดออบเจ็กต์จากฐานข้อมูลโดยตรง แต่จะมอบหมายงานนี้ให้กับออบเจ็กต์ TypeDataLoader แทน (ในตัวอย่างข้างต้น มาจากคลาส UserTypeDataLoader)

การเพิ่มฟิลด์ username, email และ url ให้กับประเภท User ทำได้ผ่านออบเจ็กต์ FieldResolver ด้วยโค้ดนี้:

class UserFieldResolver extends AbstractDBDataFieldResolver
{
  public static function getClassesToAttachTo(): array
  {
    return [
      UserTypeResolver::class,
    ];
  }
 
  public static function getFieldNamesToResolve(): array
  {
    return [
      'username',
      'email',
      'url',
    ];
  }
 
  public function getSchemaFieldDescription(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $descriptions = [
      'username' => $this->translationAPI->__("User's username handle", "users"),
      'email' => $this->translationAPI->__("User's email", "users"),
      'url' => $this->translationAPI->__("URL of the user's profile in the website", "users"),
    ];
    return $descriptions[$fieldName];
  }
 
  public function getSchemaFieldType(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $types = [
      'username' => SchemaDefinition::TYPE_STRING,
      'email' => SchemaDefinition::TYPE_EMAIL,
      'url' => SchemaDefinition::TYPE_URL,
    ];
    return $types[$fieldName];
  }
 
  public function resolveValue(
    TypeResolverInterface $typeResolver,
    object $user,
    string $fieldName,
    array $fieldArgs = []
  ) {
    switch ($fieldName) {
      case 'username':
        return $this->usersAPI->getUserLogin($user);
 
      case 'email':
        return $this->usersAPI->getUserEmail($user);
 
      case 'url':
        return $this->usersAPI->getUserURL($user);
    }
 
    return null;
  }
}

จะเห็นได้ว่าการนิยามฟิลด์สำหรับ GraphQL schema และการแก้ไขค่าของมัน ถูกแบ่งออกเป็นหลายฟังก์ชัน:

  • getSchemaFieldDescription
  • getSchemaFieldType
  • resolveValue

ฟังก์ชันอื่น ๆ ได้แก่:

โค้ดนี้อ่านง่ายกว่าการรวมฟังก์ชันทั้งหมดไว้ในฟังก์ชันเดียวหรือใช้ configuration array จึงทำให้การนำ resolver ไปใช้และบำรุงรักษาทำได้ง่ายขึ้น