[JAVA] Une histoire sur la création d'un service qui propose des améliorations à un site Web à l'aide d'une API d'apprentissage automatique

Préface

Nous avons développé un service web open source ** «Visible» ** qui diagnostique les sites web sous l'angle de l'accessibilité et propose des bonnes pratiques basées sur les informations obtenues grâce à la plateforme IA.

Visible ─ アクセシビリティー診断&修正提案

Il existe depuis longtemps des services tels que Lighthouse et Lighthouse de Google qui diagnostiquent les sites Web, mais c'est un nouveau service qui non seulement diagnostique mais suggère également des améliorations **. En outre, il est conçu pour que vous puissiez approfondir votre compréhension de l'accessibilité, et la version en ligne de commande peut être exécutée de manière autonome.

Il a été adopté par le "Unxplored Juniors" (https://jr.mitou.org/) "Programme de soutien aux créateurs d'élèves du primaire, du collège et du lycée avec des idées originales et une technologie exceptionnelle" en 2020, et a reçu un soutien technique et financier. La Réunion du rapport final des résultats sur YouTube Live se tiendra le 1er novembre!

Introduction de fonctions

En entrant l'URL du site Web, la page sera diagnostiquée et des améliorations seront suggérées automatiquement.

診断結果のスクリーンショット

Voici un exemple des modifications proposées.

Attribut ʻAlt`

Il est recommandé que l'élément <img> soit fourni avec l'attribut ʻalt` pour expliquer le contenu de l'image au lecteur d'écran ou au robot d'exploration SEO, et de générer des légendes à l'aide de l'API Vision de Google Cloud Platform. Nous proposerons des suggestions d'amélioration.

image.png

Attribut lang

Si la langue de la page Web n'est pas explicitement spécifiée, il y a un problème avec l'agent utilisateur qui nécessite les informations de langue, donc l'API Translate détecte et propose les informations de langue à partir du contenu de la page.

image.png

Rapport de contraste de couleur

Bien entendu, des propositions d'amélioration qui n'utilisent pas le machine learning sont également possibles. Si le rapport de contraste des couleurs est faible, il est difficile pour les utilisateurs ayant des caractéristiques de vision des couleurs de l'utiliser, nous proposons donc une correction qui augmente le contraste.

コントラスト

Les meilleures pratiques d'accessibilité ont été standardisées par le W3C sous les noms WCAG wcag, et il existe d'autres règles basées sur des normes.

Mécanisme de proposition

Pour exécuter le programme de diagnostic, Puppeteer, qui peut exécuter Chrome sans tête, est utilisé, le programme qui implémente l'interface de point de contrôle (règle) est exécuté et les informations sur le fichier et le lien sont basés sur les valeurs renvoyées par chaque règle. Il peut être attaché et finalement affiché comme une différence.

ワークフロー。下で詳解します

L'ensemble se compose de trois composants: core, plug-in et application, et le traitement proprement dit est écrit par le plug-in sous la forme d'implémentation de l'implémentation minimale et de l'interface exposées dans le core. Le format du plug-in est basé sur ESLint.

動作フローを図で示しています。下で詳しく説明します。

Étant donné que l'algorithme de génération d'amélioration et le navigateur sans tête peuvent être étendus en tant que règle de type plug-in, il est possible d'utiliser d'autres méthodes en plus de Google Cloud Platform.

Technologie utilisée

Le projet est développé en TypeScript. Les piles technologiques sont:

** Partie centrale **

** Backend Web **

** Interface Web **

** Autre **

Épisode pendant le développement

Bien que j'ai toujours été intéressé par la technologie de l'accessibilité Web, je n'ai pas été obligé d'utiliser des technologies d'assistance, et ma seule motivation pour un balisage correct était l'optimisation pour les moteurs de recherche. Même ainsi, je crée souvent des sites Web qui manquent d'accessibilité, et j'ai pensé que ce serait bien d'avoir un logiciel comme ESLint qui m'apprendrait à résoudre ce problème.

En même temps, l'âge limite pour postuler pour les juniors inexplorés est jusqu'à 17 ans, et à l'époque j'avais déjà 17 ans, donc je pensais essayer à la fin, alors j'ai commencé à faire des prototypes pour le faire et postuler au bon moment. J'ai fait.

prototype

J'écris moi-même des programmes depuis que je suis lycéen et travaille à temps partiel, donc j'ai écrit beaucoup de code, mais il est encore assez difficile de terminer le prototype avec seulement quelques mois pour postuler (honnêtement, j'ai postulé plus qu'après l'adoption) J'avais besoin de me fixer un objectif clair (la scène aurait peut-être été plus chargée).

Un prototype n'est pas nécessaire pour l'application elle-même, et j'aurais dû envoyer un document décrivant le produit, mais pour être adopté, je dois montrer ma propre technologie et prouver que je peux la compléter jusqu'au bout. fait. Au contraire, si vous pouvez le montrer, vous pouvez juger de ce qui est intéressant et affiner au minimum les éléments pouvant être diagnostiqués, rejeter la "proposition de correction" et faire jusqu'à "le résultat du diagnostic sort lorsque vous entrez l'URL" J'ai décidé de. Après cela, j'ai écrit le concept moelleux dans mon cerveau dans un cahier, je l'ai incorporé dans le modèle de domaine et j'ai commencé à écrire du code avec la pile technologique que je connaissais le mieux.

Un prototype qui fonctionne en environ deux mois a été achevé et il a réussi l'examen des documents. Après cela, je devais être interviewé et interrogé les mentors en ligne sur le produit. Pour être honnête, je ne me souviens pas de ce que j'ai dit, mais je me souviens qu'on m'a demandé quel genre d'objectifs le produit lui-même avait à l'avenir, et je ne pouvais donner qu'une réponse vague ...

Après l'adoption

Après l'adoption, nous avions déjà un prototype, nous l'avons donc développé agile. Les juniors inexplorés sont censés recevoir du mentorat sur une base régulière, et dans mon projet, j'ai signalé les progrès au mentor une fois par semaine et j'ai reçu des commentaires, alors j'ai fixé des jalons environ chaque semaine et subdivisés d'ici là. Nous avons procédé au développement des fonctions.

La priorité des tâches jusqu'à ce que l'utilisateur l'utilise était complètement dans l'ordre du fort impact quand j'ai dit "je peux faire ça", mais maintenant j'y pense, c'est une très bonne méthode. Je pense que non. Cependant, grâce à cela, je sens que la vitesse a augmenté sans être trop altérée dans les détails du framework, même si je suis préoccupé par la logique métier.

Premier test utilisateur

Au cours de la période, des juniors inexplorés ont eu l'occasion de monter sur scène immédiatement après l'adoption, au point médian, et les trois dernières fois (même si c'était en ligne cette année), et depuis que l'opportunité de la première présentation s'est présentée, il est déjà au stade prototype + α. A été annoncé.

À ce moment-là, les personnes qui partageaient et écoutaient l'URL qui déployait celle à ce moment-là l'utilisaient réellement, mais j'ai fait une erreur en définissant la mémoire partagée du docker ou synchronisée là où elle devrait être asynchrone Je voulais répondre et le serveur est tombé en panne immédiatement après l'annonce, donc je n'ai pas pu obtenir le retour attendu (Tohoho ~)

Entretien avec des spécialistes A11y

Après un quart de la période, avec la coopération des mentors, j'ai eu l'occasion de faire part de mes commentaires à l'équipe d'accessibilité d'une certaine entreprise.

Nous avons pu demander quel type de processus est en cours dans le domaine de l'accessibilité, quels types d'outils sont utilisés, les problèmes spécifiques au développement de l'équipe, et dans cet entretien, nous avons pu matérialiser le scénario et affiner la base d'utilisateurs. C'était. Je pense que la priorité de la tâche est devenue plus claire à partir d'ici.

Amélioration ultérieure

En utilisant la deuxième annonce chez Unxplored Junior (bien sûr, nous avons pris des mesures contre la charge ...) et les abonnés Twitter, nous avons divisé la boucle de rétroaction en subdivisions dans lesquelles les gens l'utilisent réellement et répondent au questionnaire.

Le commentaire est un formulaire de commentaire créé dans Google Forms en recherchant "Comment créer une bonne enquête" et en posant la question ci-dessus qui est dite bonne, ainsi qu'une balise Google Analytics intégrée. J'essaie de l'obtenir de plusieurs côtés.

En particulier, nous accordons de l'importance aux informations souhaitées par l'utilisateur, par exemple, attribuer une URL à une fonction non implémentée et prioriser la fonction en fonction du trafic généré à cette URL qui sera reflété dans le développement. fait.

Google formのスクリーンショット

Où ça se coince

C'est peut-être un excellent créneau, mais je vais écrire une note sur le développement.

Impossible de mapper AST avec des informations pouvant être obtenues à partir de CSS DOM

Le code source tel que HTML et CSS est converti en DOM après avoir été analysé par le navigateur et rendu disponible à partir de JavaScript, mais quel fichier ou déclaration est appliqué à partir des informations CSS qui peuvent être obtenues à partir de méthodes telles que getComputedStlye. Je ne sais pas si c'est fait.

Par conséquent, j'ai décidé d'utiliser [Chrome Devtools Protocol] CDP, qui est l'API des outils de développement de Google Chrome. Puisque CDP peut obtenir les informations de la feuille de style lue à partir de l'événement [CSS.styleSheetAdded] styleSheetAdded, lorsqu'un problème est détecté, le fichier CSS correspondant est recherché à partir de l'ID de nœud et de la propriété CSS correspondante, et il est défini sur AST de PostCSS. J'ai pu le convertir et le gérer.

La question de savoir où placer l'ORM en architecture propre

Le livre explique que «la couche d'adaptateur d'interface est la couche qui se convertit au format de données requis par la couche de cadre», donc la partie qui émet des requêtes SQL est la couche d'adaptateur d'interface, et c'est le cadre qui l'exécute avec un SGBDR concret. Bien qu'il soit traité comme une couche, dans ORM, la frontière entre ces deux processus est ambiguë, et même si vous le recherchez sur Google, il semble que diverses personnes disent qu'elles sont complètement différentes.

TypeORM est une abstraction du SGBDR à utiliser (bien qu'il y ait des limites, bien sûr), et c'est finalement décidé par ʻormconfig`, donc si vous ne mentionnez pas les détails, vous pouvez le diviser dans la couche d'adaptateur d'interface. J'ai décidé de mettre en œuvre DAL.

En passant, le présentateur qui convertit le modèle de domaine en formulaire API conserve également la direction de la dépendance en utilisant le type défini du côté du présentateur au lieu de gérer directement la définition GraphQL.

Faire Docker dans Monorepo (Yarn Workspace) est trop douloureux

Je pense que les modules ne dépendent pas tellement les uns des autres dans le cas des micro-services, mais si vous souhaitez utiliser Yarn workspace et Docker dans un cas où il y a des packages partagés par le front-end et le back-end, chaque package Je ne peux pas créer un fichier de verrouillage, ou parce que le node_modules suivant est un lien symbolique, cela ne fonctionne pas même si je le copie simplement et il reste bloqué.

Pour l'instant, j'ai écrit une [solution de contournement désordonnée] dockerfile et cela fonctionne. Yarn v2 (berry) fournit une fonction appelée [yarn workspace focus] focus, et il semble que vous ne pouvez installer que les dépendances du package que vous voulez et les exécuter indépendamment, donc je veux avancer rapidement. Cependant, je n'y ai pas encore touché car je ne comprends pas parfaitement l'environnement de Plug'n'Play.

les composants stylisés sont épicés

Pour la première fois, j'ai créé correctement un composant d'interface utilisateur semblable à un système de conception, mais lorsqu'un composant semble avoir plusieurs variantes (ci-dessous), lorsque je l'ai fait avec des composants stylisés, la lisibilité était la pire et je me suis finalement échappé vers Tailwind.

const Button = styled.button`
  font-size: 12px;

  ${
    (props) => props.variant === 'primary'
      ? css`
        color: ${props.theme.primaryFgColor};
        background-color: ${props.theme.primaryBgColor};
      `
      : css`
        color: ${props.theme.secondaryFgColor};
        background-color: ${props.theme.secondaryBgColor}
      `;
  }
`;

Détails: https://qiita.com/rigarashi/private/5c97be5ed8fb15ea2d96

Il semble y avoir un système stylisé ou xstylé qui a importé Utilify-first vers CSS-in-JS, mais j'ai abandonné parce que le type de thème n'était pas attaché de manière statique.

Traitement parallèle avec Puppeteer

La bibliothèque appelée puppeteer-cluster semblait être sympa, mais elle semble être inutilisée et il est facile de recevoir une instance de page en guise de rappel. Je ne pouvais que le faire, et je l'ai arrêté car c'était difficile pour ce cas d'utilisation tel que la conversion en Observable.

Au lieu de cela, le soi-disant Object Pooling gère les instances occupées et non occupées et lance le traitement à celles qui semblent libres. .. Je pense qu'il est probablement préférable de bifurquer le processus de travail, mais cela n'a pas beaucoup de sens car il était déjà séparé du processus Chromium lorsque Puppeteer a été lancé, et il est devenu la source de l'abonnement GraphQL. C'est juste une tonne, et vous ne pouvez pas le dire au navigateur à moins que vous ne l'appeliez dans le même processus sans prendre en sandwich les redis.

Épilogue

S'il vous plaît, pardonnez-moi pour le titre un peu mien en raison de la réflexion sur la façon d'attirer l'attention des gens avec l'accessibilité souvent méprisée.

De plus, nous avons publié la version Web, etc., veuillez donc l'essayer et demander des ** commentaires **.

Liens connexes

Recommended Posts

Une histoire sur la création d'un service qui propose des améliorations à un site Web à l'aide d'une API d'apprentissage automatique
L'histoire de la création d'un service qui raconte l'histoire du portfolio en se développant seul
Une histoire à laquelle j'étais accro lors du test de l'API à l'aide de MockMVC
Créer un service d'API RESTful à l'aide de Grape
Une histoire qui a mis du temps à établir une connexion
Une histoire sur la création d'un Builder qui hérite du Builder
Histoire d'essayer de faire fonctionner le fichier JAVA
La voie de la création d'un service Web (partie 1)
Une histoire d'essayer de s'entendre avec Mockito
Une histoire sur l'effort de décompiler les fichiers JAR
Une histoire sur la réduction de la consommation de mémoire à 1/100 avec find_in_batches