Projeto Matplotlib

Esta página contém os detalhes de um projeto de redação técnica aceito para a Google Season of Docs.

Resumo do projeto

Organização de código aberto:
Matplotlib
Redator técnico:
brunobeltran
Nome do projeto:
Como melhorar a detecção de recursos padronizando a documentação de tipos "implícitos"
Duração do projeto:
Longa duração (cinco meses)

Project description

Motivação

Historicamente, a API da matplotlib dependia muito de "tipos implícitos" de string como enum. Além de imitar a API do matlab, essas strings de parâmetro permitem que o usuário transmita valores ricos em semântica como argumentos para funções do Matplotlib sem precisar importar explicitamente ou prefixar um valor de tipo enumerado apenas para transmitir opções básicas de plotagem (ou seja, plt.plot(x, y, linestyle='solid') é mais fácil de digitar e menos redundante do que algo como plt.plot(x, y, linestyle=mpl.LineStyle.solid)).

Muitos desses tipos implícitos de string como tipo enumerado evoluíram para recursos mais sofisticados. Por exemplo, um linestyle agora pode ser uma string ou um par ordenado de sequências, e um MarkerStyle agora pode ser uma string ou um matplotlib.path.Path. Embora isso seja verdade para muitos tipos implícitos, MarkerStyle é o único (que eu saiba) que tem o status de ter sido atualizado para uma classe Python adequada.

Como esses tipos implícitos não são classes, o Matplotlib historicamente precisava criar suas próprias soluções para centralizar a documentação e a validação desses tipos implícitos (por exemplo, o padrão de interpolação de docstring docstring.interpd.update e o padrão de validador cbook._check_in_list, respectivamente) em vez de usar as cadeias de ferramentas padrão fornecidas pelas classes do Python (por exemplo, docstrings e o padrão de validação __init__, respectivamente).

Embora essas soluções tenham funcionado bem para nós, a falta de um local explícito para documentar cada tipo implícito significa que a documentação geralmente é difícil de encontrar, grandes tabelas de valores permitidos são repetidas em toda a documentação e, muitas vezes, uma declaração explícita do escopo de um tipo implícito está completamente ausente dos documentos. Confira os documentos plt.plot, por exemplo: em "Notes", uma descrição do método de estilo de string de formato semelhante a matlab menciona as opções linestyle, color e markers. Há muitas outras maneiras de transmitir esses três valores do que se sugere, mas, para muitos usuários, essa é a única fonte de entendimento sobre quais valores são possíveis para essas opções até que eles encontrem um dos tutoriais relevantes. A tabela de atributos Line2D é incluída para mostrar ao leitor quais opções ele tem para controlar o gráfico. No entanto, embora a entrada linestyle seja boa para vincular a Line2D.set_linestyle (dois cliques necessários), onde as entradas possíveis são descritas, as entradas color e markers não são. color simplesmente é vinculado a Line2D.set_color, o que não oferece nenhuma intuição sobre quais tipos de entradas são permitidos.

Pode-se argumentar que isso é algo que pode ser corrigido simplesmente organizando as docstrings individuais que estão causando problemas, mas, infelizmente, o problema é muito mais sistêmico que isso. Sem um local centralizado para encontrar a documentação, isso simplesmente vai fazer com que tenhamos cada vez mais cópias de documentação mais detalhada repetida em todos os lugares em que cada um desses tipos implícitos é usado, dificultando ainda mais que usuários iniciantes simplesmente encontrem o parâmetro necessário. No entanto, o sistema atual, que força os usuários a juntar lentamente o modelo mental de cada tipo implícito por percurso no estilo de mergulho na Wiki em toda a nossa documentação ou em partes dos exemplos do StackOverflow, também não é sustentável.

Objetivo final

Idealmente, qualquer menção de um tipo implícito deve vincular a uma única página que descreva todos os valores possíveis que esse tipo pode ter, ordenados do mais simples e comum ao mais avançado ou esotérico. Em vez de usar um espaço visual valioso na documentação da API de nível superior para enumerar em partes todos os tipos de entrada possíveis para um parâmetro específico, podemos usar esse mesmo espaço para fornecer uma descrição simples da abstração de plotagem que o parâmetro pretende controlar.

Para usar o exemplo de linestyle novamente, o que queremos nos documentos LineCollection é apenas:

  1. Um link para documentos completos sobre entradas permitidas (uma combinação das encontradas em Line2D.set_linestyle e no tutorial de linestyle).
  2. Uma descrição simples do que o parâmetro deve alcançar. Para usuários avançados do matplotlib, isso é evidente pelo nome do parâmetro, mas para novos usuários, isso não precisa ser o caso.

A aparência disso nos documentos LineCollection reais é apenas python """""" linestyles: `LineStyle` or list thereof, default: :rc:`lines.linestyle` ('-') A description of whether the stroke used to draw each line in the collection is dashed, dotted or solid, or some combination thereof. """""" em que a referência do tipo LineStyle seria resolvida pelo Sphinx para apontar para um conjunto único, oficial e completo de documentação sobre como o Matplotlib trata os estilos de linha.

Vantagens

Alguns recursos poderosos dessa abordagem incluem

  1. Deixar a extensão completa do que cada função é capaz de fazer óbvia em texto simples (sem necessidade de cliques).
  2. Tornar a opção padrão visível (sem cliques). A visualização da opção padrão muitas vezes é suficiente para refrescar a memória dos usuários que retornam.
  3. Faça uma descrição completa das opções "mais comuns" e "mais fáceis" para um parâmetro facilmente disponível durante a navegação (com um único clique).
  4. Facilite o processo de descoberta de recursos e métodos de entrada mais eficientes, como "rolar para baixo" e conferir opções mais avançadas, com apenas um clique.
  5. Ofereça uma estratégia centralizada para vincular documentos de "API" de nível superior aos "tutoriais" relevantes.
  6. Evite a explosão de documentos da API, em que a verificação de várias opções possíveis para cada parâmetro torna as strings de documentação individuais difíceis de usar.

Outros benefícios dessa abordagem em relação aos documentos atuais são:

  1. Os documentos têm menos probabilidade de ficar desatualizados devido à centralização.
  2. Canonização de muitos "padrões implícitos" da matplotlib (como o que é um ""limites"" em vez de ""extensões"") que atualmente precisam ser aprendidos com a leitura do código.
  3. O processo destacaria problemas com a consistência da API de uma maneira que pode ser rastreada com mais facilidade pelo rastreador de problemas do GitHub, ajudando no processo de melhoria da nossa API.
  4. Tempos de build de documentos mais rápidos devido a reduções significativas na quantidade de texto que precisa ser analisado.

Implementação

As melhorias descritas acima vão exigir dois esforços importantes para os quais um redator técnico dedicado será de grande valor. A primeira é criar uma página "tutorial" centralizada por tipo implícito. Isso vai exigir que você trabalhe com a equipe principal de desenvolvedores para identificar uma lista concreta de tipos implícitos cuja documentação seja valiosa para os usuários (normalmente, porque eles contêm recursos poderosos e ocultos da nossa biblioteca, cuja documentação é encontrada apenas em tutoriais difíceis de encontrar). Para cada tipo implícito, vou sintetizar os vários tutoriais relevantes, documentos da API e páginas de exemplo em uma única fonte de documentação oficial que pode ser vinculada a qualquer lugar em que esse tipo específico seja referenciado.

Depois que a documentação centralizada de um determinado tipo implícito é concluída, o segundo esforço principal começa: substituir a documentação de API atual por links para a nova documentação, com o objetivo de tornar a experiência de uso dessa nova documentação o mais fácil possível, tanto para quem usa o utilitário help() integrado do Python quanto para quem navega pela nossa documentação on-line.

Embora o formato exato da documentação proposta aqui esteja sujeito a mudanças conforme o projeto evolui, trabalhei com a equipe principal do Matplotlib durante as ""chamadas de desenvolvedor"" semanais para estabelecer um consenso de que a estratégia proposta aqui é a abordagem mais conveniente, útil e tecnicamente tratável para começar a documentar esses ""tipos implícitos"". As notas sobre essas chamadas estão disponíveis no hackmd. Vou usar a infraestrutura de "tutoriais" existente para os estágios iniciais da criação da documentação centralizada para cada tipo implícito, permitindo que eu referenciar essas páginas da seguinte forma, sem precisar criar novas classes públicas (novamente, usando os documentos LineCollection como exemplo):

""""""
linestyles: LineStyle or list thereof, default: :rc:`lines.linestyle` ('-')
    A description of whether the stroke used to draw each line in the collection
    is dashed, dotted or solid, or some combination thereof. For a full
    description of possible LineStyle's, see :doc:`tutorials/types/linestyle`.
""""""

No futuro, poderemos mudar facilmente a grafia dessas referências quando a equipe principal de desenvolvedores concordar com a melhor estratégia de longo prazo para incorporar nossa nova documentação de ""tipos"" a classes Python genuínas, por exemplo, como proposto por mim na Proposta de Melhoria 30 do Matplotlib.

Por fim, a lista preliminar de tipos implícitos que proponho documentar durante esta temporada de documentos do Google é a seguinte:

  1. capstyle
  2. joinstyle
  3. bounds
  4. extents
  5. linestyle
  6. colors/lists of colors
  7. colornorm/colormap
  8. tick formatters

Uma versão ativa deste documento pode ser encontrada no nosso Discurso.