Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] Captive User Interfaces — Why You Should Avoid Them

#1
Captive User Interfaces — Why You Should Avoid Them

<div><p>This tutorial shows you the meaning of captive user interfaces and why they’re discouraged under the Unix philosophy. I’ve written this as a first chapter draft for my upcoming book <em><strong>“From One to Zero”</strong></em> to appear in 2020 with San Francisco-based publisher NoStarch. </p>
<h2>What’s a Captive User Interface (CUI)?</h2>
<p class="has-pale-cyan-blue-background-color has-background">A captive user interface is a way of designing a program that requires the user to interact with the program in a session before they’ll be able to proceed with their main execution flow. If you invoke a program in your terminal (Windows, MacOS, or Linux), you must communicate with the program before you can go back to the terminal. Examples are mini programs such as SSH, top, cat, vim—as well as programming language features such as Python’s input() function.</p>
<h2>Python Example Captive User Interface</h2>
<p>Say you create a simple life expectancy calculator in Python. The user must type in their age and it returns the expected number of years left based on a straightforward heuristic. This is a fun project found <a href="http://www.decisionsciencenews.com/2014/10/15/rules-thumb-predict-long-will-live/" target="_blank" rel="noreferrer noopener" title="http://www.decisionsciencenews.com/2014/10/15/rules-thumb-predict-long-will-live/">here</a>.</p>
<pre class="wp-block-preformatted"><em><strong>"If you’re under 85, your life expectancy is 72 minus 80% of your age.</strong>
<strong>Otherwise it’s 22 minus 20% of your age."</strong></em></pre>
<p>Your initial, bad, Python code is shown here:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def your_life_expectancy(): age = int(input('how old are you? ')) if age&lt;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()
</pre>
<p><em><strong>Listing 8-8:</strong> Life-expectancy calculator – a simple heuristic – implemented as a captive user interface.</em></p>
<p>Here are some runs of the code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> 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!
</pre>
<h2>Interactive Jupyter Notebook to Calculate Your Life Expectancy Using a Captive User Interface</h2>
<p>In case you want to try it yourself, I’ve created an interactive Jupyter notebook you can run in your browser to calculate your own life expectancy. But, please, don’t take it too serious! Here’s the notebook: </p>
<figure class="wp-block-image size-large"><a href="https://colab.research.google.com/drive/1VsKPuKlBoB0vBTDpeQbAnAREmZrxDoUd?usp=sharing" target="_blank" rel="noopener noreferrer"><img loading="lazy" width="1024" height="359" src="https://blog.finxter.com/wp-content/uploads/2020/12/image-62-1024x359.png" alt="" class="wp-image-19015" srcset="https://blog.finxter.com/wp-content/uploads/2020/12/image-62-1024x359.png 1024w, https://blog.finxter.com/wp-content/uplo...00x105.png 300w, https://blog.finxter.com/wp-content/uplo...68x269.png 768w, https://blog.finxter.com/wp-content/uplo...150x53.png 150w, https://blog.finxter.com/wp-content/uplo...age-62.png 1047w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>
<p>The code makes use of Python’s <code>input()</code> function that blocks the program execution and waits for user input. Without user input, the code doesn’t do anything. This seriously limits the usability of the code. </p>
<p>What if I wanted to calculate the life expectancy for every age from 1 to 100 based on the heuristic and plot it? I’d have to manually type 100 different ages and store the results in a separate file. Then, you’d have to copy&amp;paste the results into a new script to plot it. </p>
<p>The function really does two things: process the user input and calculate the life expectancy. This already violates rule number 3: <strong><em>Make Every Program Do One Thing Well</em></strong>. </p>
<p>But it also violates our rule: <strong><em>don’t use captive user interfaces</em></strong> if possible.</p>
<h2>Non-Captive User Interface Python Example</h2>
<p>Here’s how the function could’ve been implemented more cleanly:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def your_life_expectancy(age): if age&lt;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!')
</pre>
<p><em><strong>Listing</strong>: Life-expectancy calculator – a simple heuristic – without captive user interface.</em></p>
<p>The code is functionally identical to the code with captive user interface. However, it has a big advantage: now, you can use the function in different and unexpected—by the initial developer—ways:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import matplotlib.pyplot as plt def your_life_expectancy(age): '''Returns the expected remaining number of years.''' if age&lt;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()
</pre>
<p><em><strong>Listing</strong>: Code to plot the life expectancy for years 0-99.</em></p>
<p>The resulting plot is shown in the following figure:</p>
<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" width="605" height="454" src="https://blog.finxter.com/wp-content/uploads/2020/12/image-63.png" alt="" class="wp-image-19020" srcset="https://blog.finxter.com/wp-content/uploads/2020/12/image-63.png 605w, https://blog.finxter.com/wp-content/uplo...00x225.png 300w, https://blog.finxter.com/wp-content/uplo...50x113.png 150w" sizes="(max-width: 605px) 100vw, 605px" /></figure>
</div>
<p class="has-text-align-center"><em><strong>Figure</strong>: How the heuristic works for input years 0-99.</em></p>
<p>Let’s not talk too much about the flaws of this heuristic—it’s crude by design—but focus on how the rule of avoiding captive user interface has helped us produce this plot. Without the rule, we’d have to write a new function, add redundancies and unnecessary complexity. By considering the rule, we’ve simplified the code and opened up all kinds of future programs to use and built-upon the heuristic. Instead of optimizing for one specific use case, we’ve written the code in a general way that can be used by hundreds of different applications.</p>
<p>The post <a href="https://blog.finxter.com/captive-user-interfaces-why-you-should-avoid-them/" target="_blank" rel="noopener noreferrer">Captive User Interfaces — Why You Should Avoid Them</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>


https://www.sickgaming.net/blog/2020/12/...void-them/
Reply



Forum Jump:


Users browsing this thread:
2 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016