Python >> Tutoriel Python >  >> Python

Interfaces utilisateur captives - Pourquoi vous devriez les éviter

Ce didacticiel vous montre la signification des interfaces utilisateur captives et pourquoi elles sont découragées dans la philosophie Unix. J'ai écrit ceci comme premier brouillon de chapitre pour mon prochain livre "From One to Zero" à paraître en 2020 avec l'éditeur NoStarch basé à San Francisco.

Qu'est-ce qu'une interface utilisateur captive ?

Une interface utilisateur captive est un moyen de concevoir un programme qui oblige l'utilisateur à interagir avec le programme dans une session avant de pouvoir poursuivre son flux d'exécution principal. Si vous appelez un programme dans votre terminal (Windows, MacOS ou Linux), vous devez communiquer avec le programme avant de pouvoir revenir au terminal. Des exemples sont des mini-programmes tels que SSH, top, cat, vim, ainsi que des fonctionnalités de langage de programmation telles que la fonction input() de Python.

Exemple d'interface utilisateur captif Python

Supposons que vous créez un simple calculateur d'espérance de vie en Python. L'utilisateur doit saisir son âge et il renvoie le nombre prévu d'années restantes sur la base d'une heuristique simple. C'est un projet amusant trouvé ici.

"If you’re under 85, your life expectancy is 72 minus 80% of your age.
Otherwise it’s 22 minus 20% of your age."

Votre mauvais code Python initial est affiché ici :

def your_life_expectancy():
    age = int(input('how old are you? '))
    
    if age<85:
        exp_years = 72 - 0.8 * age
    else:
        exp_years = 22 - 0.2 * age

    print(f'People your age have on average {exp_years} years left - use them wisely!')


your_life_expectancy()

Liste 8-8 : Calculateur d'espérance de vie - une heuristique simple - implémentée sous forme d'interface utilisateur captive.

Voici quelques exécutions du code :

>>> how old are you? 10
People your age have on average 64.0 years left - use them wisely!
>>> how old are you? 20
People your age have on average 56.0 years left - use them wisely!
>>> how old are you? 77
People your age have on average 10.399999999999999 years left - use them wisely!

Cahier Jupyter interactif pour calculer votre espérance de vie à l'aide d'une interface utilisateur captive

Au cas où vous voudriez l'essayer vous-même, j'ai créé un cahier Jupyter interactif que vous pouvez exécuter dans votre navigateur pour calculer votre propre espérance de vie. Mais, s'il vous plaît, ne le prenez pas trop au sérieux! Voici le carnet :

Le code utilise le input() de Python fonction qui bloque l'exécution du programme et attend l'entrée de l'utilisateur. Sans intervention de l'utilisateur, le code ne fait rien. Cela limite sérieusement la convivialité du code.

Et si je voulais calculer l'espérance de vie pour chaque âge de 1 à 100 ans sur la base de l'heuristique et la tracer ? Je devrais taper manuellement 100 âges différents et stocker les résultats dans un fichier séparé. Ensuite, vous devrez copier et coller les résultats dans un nouveau script pour le tracer.

La fonction fait vraiment deux choses :traiter l'entrée de l'utilisateur et calculer l'espérance de vie. Cela enfreint déjà la règle numéro 3 :Faites en sorte que chaque programme fasse bien une chose .

Mais cela enfreint également notre règle :n'utilisez pas d'interfaces utilisateur captives si possible.

Exemple Python d'interface utilisateur non captive

Voici comment la fonction aurait pu être implémentée plus proprement :

def your_life_expectancy(age):
    if age<85:
        return 72 - 0.8 * age
    return 22 - 0.2 * age


age = int(input('how old are you? '))
exp_years = your_life_expectancy(age)
print(f'People your age have on average {exp_years} years left - use them wisely!')

Liste :Calculateur d'espérance de vie - une heuristique simple - sans interface utilisateur captive.

Le code est fonctionnellement identique au code avec interface utilisateur captive. Cependant, il présente un gros avantage :désormais, vous pouvez utiliser la fonction de manière différente et inattendue (par le développeur initial) :

import matplotlib.pyplot as plt


def your_life_expectancy(age):
    '''Returns the expected remaining number of years.'''
    if age<85:
        return 72 - 0.8 * age
    return 22 - 0.2 * age


# Plot for first 100 years
plt.plot(range(100), [your_life_expectancy(i) for i in range(100)])

# Style plot
plt.xlabel('Age')
plt.ylabel('No. Years Left')
plt.grid()

# Show and save plot
plt.savefig('age_plot.jpg')
plt.savefig('age_plot.pdf')
plt.show()

Liste :Code pour tracer l'espérance de vie pour les années 0-99.

Le tracé résultant est illustré dans la figure suivante :

Figure  :Comment fonctionne l'heuristique pour les années d'entrée 0-99.

Ne parlons pas trop des défauts de cette heuristique - elle est grossière de par sa conception - mais concentrons-nous sur la façon dont la règle d'éviter l'interface utilisateur captive nous a aidés à produire cette intrigue. Sans la règle, nous aurions dû écrire une nouvelle fonction, ajouter des redondances et une complexité inutile. En tenant compte de la règle, nous avons simplifié le code et ouvert toutes sortes de futurs programmes à utiliser et construits sur l'heuristique. Au lieu d'optimiser pour un cas d'utilisation spécifique, nous avons écrit le code d'une manière générale qui peut être utilisée par des centaines d'applications différentes.