invenio
invenio copied to clipboard
RFC Move example apps docstring to README.rst
It may be useful and easier for users to have the information on how to run the example applications directly in the example folder.
Thus, when you are on github (or browsing the code locally) and you are viewing the examples
folder, you can see the instructions and how to run the small example, instead of looking for it on readthedocs or look into the app.py
file.
cc @inveniosoftware/developers
See also my related past musings about:
- propagating example app's documentation into RTFD as we did e.g. in Flask-Menu;
- simplifying the number of example app's helper scripts via Makefile;
in https://github.com/inveniosoftware/invenio-deposit/pull/122#r79128189
Makefile would be basically a "runnable README", so to speak.
Whatever we choose, we could tag instructions with :start-after: # sphinxdoc-initdb
like technique, which would make the documentation also nicely readable on RTFD.
I like the idea of having the instructions inside the example_app.py
- they are usually short and I can easily see what steps will be required to install this example app.
On the other hand, moving those steps to an executable Makefile
will have the same benefits (you can open the file to see what steps are needed to install the example app) and if it's an executable file, it will save some copy-pasting into the terminal, so :+1: for the Makefiles.
I saw that we are using examples in some places already:
https://github.com/inveniosoftware/invenio-oauth2server/blob/master/examples/app.py
@tiborsimko Wouldn't be simple to propagate this doc to a specific section in our RTFD? (Perhaps I misunderstood your comment).
The reason for including README.rst
is to help people see what's in the example when browsing the code on GitHub. There is a good example in Flask repo: https://github.com/pallets/flask/tree/master/examples/minitwit
The reason for including README.rst is to help people see what's in the example when browsing the code on GitHub.
This is obviously the same with the Makefile-based approach, because any verbiage text that you would put into a README file for people to read, you would put the same in the beginning of the Makefile.
Makefile, as a "runnable README", has the same information carrying weight in my eyes. Moreover, it has one notable advantage, because it's runnable. Hence it's natural to "rerun" all the example app steps with Makefiles, it's easy to write integration tests for Makefile-based instructions. You don't have these advantages with README-plaintext-file based instructions, they tend to get outdated more easily.
Moreover, consider the unnecessary clutter we currently have, with the README-based approach: (example taken from invenio-search-ui
)
README.rst
app-fixtures.sh
app.py
app-setup.sh
app-teardown.sh
data
requirements.txt
versus the cleaner Makefile based approach:
Makefile
app.py
data
requirements.txt
(In theory, the latter could also have a README
file, but it's kind of unnecessary as per the presence of Makefile
.)
The README
is for people that browse the repository and find the example. It can be very simple and just mention that you can run make
command to build, prepare, run and clean the example. Sometimes we need to mention somewhere the need of configuring external services (e.g. installing Elasticsearch plugins). IMHO example app is not a documentation and it should help people to "play" with the module.
I'm not saying that we should not include Makefile
, but the target audience of Makefile
is different from the one that would like to see README.rst
.
The goal of the RFC is simply to help users to setup the example even if they know nothing about python, flask, bash... If you find a code with a README, you will read it because it is standard (and github print it by default). If you only find a Makefile, you'll have to open it, and you'll need the technical skills to understand it.
Finally, what you can do is a file README.sh
with a comment at the begining saying "run me to launch the example" and eventually some other comments so it is well printed in Github, AND you can run it easily without any copy/paste.
example here: https://github.com/remileduc/invenio/tree/remileduc-patch-2/invenio
README.sh
What a trick 🎩
I'm not saying that we should not include Makefile, but the target audience of Makefile is different from the one that would like to see README.rst.
Consider a Makefile
looking like:
# This is a minimal example application for Invenio-Records-UI.
#
# Prerequisites: Redis, SQlite.
#
# The example application demonstrates foo and bar. You can run xyzzy and zyxxy
# and see the output on http://0.0.0.0/records/1.
#
# ...
all:
...
Would having an extra README file be advantageous in this case? Isn't the verbiage at the start of Makefile enough?
That said, I'm not fully against including a minimal README either :smile: but I think it is not really necessary, because Makefile is a "runnable README" already. ("Less is more.")
I assume that people have a habit of reading a Makefile when they meet one... we are targetting developers, they should be already familiar with the concept.
Finally, what you can do is a file README.sh with a comment at the begining saying "run me to launch the example"
This approach would have the clutter disadvantage I mentioned above if you keep the tiny shell scripts for people to rerun the "populate" step or the "destroy" step more than once.
Unless you thought of using README.sh together with Makefile? In that case, we don't need README.sh, it would be more than enough to use a plain-text README or a formatted README.rst. These are more standard, and possibly easier to include "as is" into RTFD documentation.
If you only find a Makefile, you'll have to open it, and you'll need the technical skills to understand it.
Well, if a developer doesn't understand Makefiles yet, then it'll be a good investment for him/her to learn the concept :smile: Let's aim at using the right tool for the job. Frankly, the concept shouldn't be hard to understand:
# This is some help text.
all: build run init populate test
init:
flask db init
flask db create
populate:
flask fixtures records
destroy:
flask db drop
so it is well printed in Github
I reckon this was not my primary goal. I think that random visitors interested in an Invenio package would tend to browse our RTFD pages in order to learn more about the package, and Invenio developers would have the code checked out locally, so "browsing code directories on GitHub" wasn't of top concern to me.
Instead, I've been calling for taking advantage of this RFC to aim for more than that, notably (i) to propagate example instructions into RTFD, (ii) to declutter the source code base of the current tiny shell scripts, (iii) to enable easy rerunning of example app steps for smoother development and integration testing, and all this (iv) without having to repeat the either the information or the instruction steps in several places, if at all possible.
(We started these musings with @hachreak in https://github.com/inveniosoftware/invenio-deposit/pull/122 and this RFC seemed like a good place to take over and conclude on these thoughts...)
I really don't want to lead the discussion to Makefile vs. README.rst. They can both co-exist and have their own audience. Moreover if we start with some more complex examples that have non trivial setup and requirements, then I see benefits for new developers in having README displayed when browsing the code on GitHub.
Yes, I agreed above that README and Makefile aren't mutually exclusive, and both can be used. However, the decision about Makefiles influences the decision about READMEs. It seems advantageous to consider the two topics together, so that we don't have to redo things twice for all the 46 repositories that contain the example app...
I reckon this was not my primary goal. I think that random visitors interested in an Invenio package would tend to browse our RTFD pages in order to learn more about the package, and Invenio developers would have the code checked out locally, so "browsing code directories on GitHub" wasn't of top concern to me.
As an example, yesterday I wanted to have a look at invenio-webhooks. I went to the repo and since there is no doc for usage/installation on RTD, first thing I did was to check the example. Just as my personal perception, I would have found it extremely confortable and convenient if there would have been a README.sh directly printed there. Then again, I can read the makefile :)
I went to the repo and since there is no doc for usage/installation on RTD [...]
This points to the core of the matter for me, and illustrates why I was calling for addressing RFTD at the same time. We don't have RTFD for many packages still, which is the ultimate goal before releasing Invenio 3.0 final... So @inveniosoftware/developers let's join I3B-API-Docs kanban to get there faster!
I would have found it extremely confortable and convenient if there would have been a README.sh directly printed there
I really wonder how frequent is the use case of "people-expecting-to-see-something-displayed-inline-when-browsing-GitHub-directories". How do people know that if they click on "examples" that they would get some help directly printed there? And where do we stop? Would people expect to click on "tests" directory to see a directly printed guide on how to run and write tests? Would they expect to click on "docs" and see direct link to RTFD? Would they expect to see a Transifex guide after clicking on "translations" directory? And what about clicking inside our source code directories? How many READMEs would we need to fit this "browsing around" use case?
In my eyes, all these "getting started" needs are better addressed in a more scalable way by (i) boot camp exposure to package structure for new developers (already being done, but IRL only), accompanied by (ii) currently subdocumented package anatomy, which we should further expand upon #3657 #3658. Richer documentation would address these needs in a more comprehensive manner.
Then again, I can read the makefile
... this is what I was thinking that a developer instinct would do. :smile: It's true that it's "one click away" when browsing GitHub, but is it really such a big deal?
P.S. Again, let me repeat that we could have both examples/README
and examples/Makefile
... I simply find it a bit redundant, especially if README is more or less going to point to Makefile...
This points to the core of the matter for me, and illustrates why I was calling for addressing RFTD at the same time. We don't have RTFD for many packages still, which is the ultimate goal before releasing Invenio 3.0 final... So @inveniosoftware/developers let's join I3B-API-Docs kanban to get there faster!
👍
I really wonder how frequent is the use case of "people-expecting-to-see-something-displayed-inline-when-browsing-GitHub-directories". How do people know that if they click on "examples" that they would get some help directly printed there? And where do we stop? Would people expect to click on "tests" directory to see a directly printed guide on how to run and write tests? Would they expect to click on "docs" and see direct link to RTFD? Would they expect to see a Transifex guide after clicking on "translations" directory? And what about clicking inside our source code directories? How many READMEs would we need to fit this "browsing around" use case?
I simply said that I would find it more convenient...not that I would expect to find it there 😄 Actually, I would rather prefer to see more info directly from the README in the root of the repo. Which is what we want at the end of the day, right?
(ii) currently subdocumented package anatomy, which we should further expand upon #3657 #3658. Richer documentation would address these needs in a more comprehensive manner.
👍
... this is what I was thinking that a developer instinct would do. 😄 It's true that it's "one click away" when browsing GitHub, but is it really such a big deal?
I don't think so. Just less convenient than the first one 😃
How do people know that if they click on "examples" that they would get some help directly printed there?
They don't have to know they just hope that it's there 😆
It's true that it's "one click away" when browsing GitHub, but is it really such a big deal?
From UX point of view - yes. For a Python developer who never had to see a Makefile in his/her life because she never wrote a single line of code in language that needs to be compiled.
From UX point of view - yes. For a Python developer who never had to see a Makefile in his/her life because she never wrote a single line of code in language that needs to be compiled.
:+1: Makefile
s are indeed out of context in a Python project. And for non-python projects I rarely have found projects using directly Makefile
s, unless they were very small ones. Most projects use automake/autoconf, so one would basically never look into a Makefile looking for documentation.
They don't have to know they just hope that it's there :laughing:
Browsing around inside various GitHub directories, from "examples" to "docs" to " tests" to "translations" to dunno-wherever-else-inside-our-codebase, hoping to see some interactive help printed out automatically, doesn't constitute a very efficient information discovery technique to me :smile: I'd rather populate our "Package anatomy" parts of the documentation guide, so that people could find appropriate help in a centralised place and in an organised manner.
Makefiles are indeed out of context in a Python project.
Please note we are talking example app instructions here, and these are shell commands, such as flask initdb
. They are not Python commands. Makefile is a perfectly usable tool for automatising running shell commands of that sort.
If you want to see some use case examples in Python projects:
- what I have in mind is akin to Sphinx's use of Makefiles, that we already have in each Invenio package anyway: https://github.com/inveniosoftware/invenio/blob/master/docs/Makefile
- and I gave an example of pypa's warehouse before, to cite just one more example: https://github.com/pypa/warehouse/blob/master/Makefile
Let me try with a story, perhaps it can illustrate my thoughts better. Let us imagine that we have now introduced README.rst
or README.sh
, which gives:
README.sh
app-fixtures.sh
app.py
app-setup.sh
app-teardown.sh
data
requirements.txt
I would argue that we have an unnecessary clutter here, because the example app is small, and the helper shell scripts like app-teardown.sh
are tiny, typically 1-2 liners only, such as: (illustrative example only)
$ cat app-teardown.sh
flask db drop
Say I don't like the additional clutter that this brings to the source code file tree. Wouldn't people be able to focus better on the example app without seeing all that additional clutter?
One way to address the clutter problem would be to "hide" these ultra tiny helper shell scripts inside README.sh
as shell functions, for example:
$ cat README.sh
setup () {
flask init
flask create
}
populate () {
flask fixtures records
}
teardown () {
flask db drop
}
if [ "$1" = "setup" ]; then
setup
elif [ "$1" = "populate" ]; then
populate
else
...
This would give nicely uncluttered source tree:
README.sh
app.py
data
requirements.txt
and people would type:
$ ./README.sh setup
$ ./README.sh populate
$ firefox http://0.0.0.0/records/1
$ ./README.sh teardown
to run the example app. (If README.sh
looks a bit weird here, let's imagine app.sh
or run.sh
or something; the exact name of the unified helper script is of secondary importance to the story.)
So far so good; the clutter is gone, the focus is back.
However, let's ponder how is this different from the Makefile approach? With a Makefile, we'd have similar content (with less boiler plate):
``` console` $ cat Makefile
setup: flask init flask create
populate: flask fixtures records
teardown: flask db drop
with similarly uncluttered files:
Makefile app.py data requirements.txt
with people typing similarly:
``` console
$ make setup
$ make populate
$ firefox http://0.0.0.0/records/1
$ make teardown
to run this example app.
The two examples are pretty similar, aren't they? In other words, aren't we simply "rediscovering" the standard Makefile facility, if we start from the README.sh
approach first, using a plethora of tiny helper scripts, and if we try to unclutter the source code tree to hide away those unnecessary tiny helper scripts later?
(Moreover, let's imagine the additional goodies that using the standard Makefile tool would bring. For example, people could type make <TAB> <RET>
to see all the available options, with auto-completed value of either setup
, populate
or teardown
for them, thanks to the usual Makefile shell completion. Yes, we could write a dedicated shell completion snippet for README.sh
too, but isn't this again a sign that illustrates my point about "reinventing" the Makefile wheel again?)
In my eyes, this use of Makefiles is pretty common in the Unix world. Makefile is useful not only to compile C programs and the like. See the Sphinx example, see various TeX examples... I would guess that most developers had come across examples of this kind during their exposure to Unix.
@tiborsimko from your examples looks like README and Makefile are two exclusive options, but they can co-exist together.
Makefile
README
app.py
requirements.txt
I would go even one step further and introduce setup.py
, which has working shell completion too and we can remove requirements.txt
.
README
app.py
setup.py