• Stars
    star
    1
  • Language
  • License
    Apache License 2.0
  • Created about 4 years ago
  • Updated about 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Several rules to write the best possible source code examples

The rules for good code examples

Code examples are very important, each example is most of the time designed to focus on a particular feature/characteristic of a programming language, a library or a framework. They help us to quickly test, experiment and remember how bigger project or at least some parts of them are working.

Learning or remembering is much quicker when you have at your disposal your own set of examples. This set of examples is a knowledge asset, we must become aware of its value for us but also from a project team point of view.

Being aware of this knowledge asset means that you should establish and follow some simple rules which will help you or your project team to valorize this asset.

Simple rules for good code examples

When writing source code examples, try to take into account the maximum number of those rules in order to implement the best possible examples.

One purpose rule

A good code example has one purpose such as learning the basics of a programming language (the typical println("Hello world") example) or experimenting/testing a library or framework.

It can also be used to illustrate how you can achieve one feature, for example date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" is a linux date command usage example which prints a date/time in the ISO8601 standard date format.

Limited size rule

1 example in 1 single file (when possible) helps to limit the overall example size as well as it simplifies greatly the sharing.

Try to keep each source code example as short as possible, if over the time one example becomes larger and larger, try to split it into several examples, it may also mean you need to drop the example format and switch to a dedicated project organization.

A good approach is to always start small through a source code example. When you want to enhance/refactor your initial example and probably add some complexities, create a copy of your example and make your changes, it is very important to keep your first iterations as they will retain the simplest aspects of what was your successive intentions.

Runnable rule

Your example self-contains all information required to run it, so it means that it must provide the following information :

  • what are the runtime prerequisites such as python, jshell, ammonite, bash, julia,...
    • while giving precise release information if required such as python-3, java-15
  • what are its required software dependencies
    • linux packages required to run this bash script example
    • python modules to install before trying to run the example
    • maven/classpath required artifacts

The minimum thing to do is to add comments in your example which list the required runtime and dependencies information. You can also use a shebang to make your example directly executable while giving to the example reader the information about how it is executed.

It is also important that your example prints something, for a function, add some usage example with visible results.

#!/usr/bin/env python3
def add(x,y):
  return x+y
print('1+2='+str(add(1,2)))

A very good developer experience is achieved when you use the ammonite REPL as it is able to load software dependencies at runtime !

#!/usr/bin/env amm
import $ivy.`com.lihaoyi::requests:0.6.5`
requests.get("https://httpbin.org/get").lines().foreach(println)

In this small example, the runtime context is given by the shebang, and the dependencies requirements is directly given by the executed import instruction.

Exploratory compatible rule

When a read-eval-print-loop (REPL) is available in your example context, organize your example in a way that it is easy to copy/paste the example in a REPL session for interactive exploratory live experiments.

For one-liner example this is trivial, with longer examples it may add some constraints depending of your technological choices, so while writing your example, use a REPL session interactivly to check how it behaves and also to help you enhance your code example.

For example for python don't forget to add an empty line after each function definition ;) And for ammonite, it may require either to add some braces within you example or to copy/paste within braces to avoid any issue.

Self-describing rule

When it makes sense, design your example to make its execution self-describing, this is quite simple when you use a unit test framework as most of them can generate a report. If you use specification oriented unit tests, it becomes trivial as you can see in the following example output :

split
- should be able to split in 2 parts using the last dot thanks to zero-width positive lookahead regexp
- should be able to split on characters while preserving those characters
regexp
- should allow partial matching
- should be possible to use named arguments

Which is generated by the following example script, a runnable example with flat specification output brought by the scalatest unit test framework :

#!/usr/bin/env amm
import $ivy.`org.scalatest::scalatest:3.2.2`
import org.scalatest._, flatspec._,  matchers._,  OptionValues._
import java.util.Locale
object StringOperations extends AnyFlatSpec with should.Matchers {
  "split" should "be able to split in 2 parts using the last dot thanks to zero-width positive lookahead regexp" in {
    val aType="ab.cd.de"
    val Array(aPackage, aClassName) = aType.split("[.](?=[^.]*$)", 2)
    aPackage shouldBe "ab.cd"
    aClassName shouldBe "de"
  }

  it should "be able to split on characters while preserving those characters" in {
    val in = "abc. truc? blah, blu."
    in.split("""\s*(?<=[?.,])\s*""").toList shouldBe List("abc.", "truc?", "blah,", "blu.")
  }
  "regexp" should "allow partial matching" in {
    val MyRE="TO(.*)TA".r.unanchored
    "xxTOTUTAxx" match {
      case MyRE(inside)=> inside shouldBe "TU"
      case _ => fail
    }
  }
  it should "be possible to use named arguments" in {
    val MyRE="TO(?<in>.*)TA".r
    val sample = "TOTUTA"
    MyRE.findFirstMatchIn(sample).map(_.group("in")).value shouldBe "TU"
  }
}
StringOperations.execute()

This example comes from a bigger one I maintain whose purpose is a sheet cheat about advanced operations on strings.

So when executed, the output describes exactly what it does, and even more, as this is unit tests based it will fail until you give the right implementation ! Or until you've understood what's going on ;)

Manageable and shareable rule

Once you've written dozens of examples, you'll quickly need to industrialize their life cycle. It will mean :

  • how to deal with maintenance ?
  • how to share them ? Publicly or internally ?
  • how to let people react over them ?
  • how to manage their change history ?
  • how to write them from your perspective or from the team one ?
  • how to search through your examples ?

All of these require some good practices, and tooling. Among the good practices one of the most important one is to insert within each of your example some meta-data in order to give more insights about it. You can add several meta-data fields such as a short description, a keywords list, some licensing information, ... which will greatly help your examples life-cycle management.

In fact this is quite easy thanks to this simple recipe :

  • GIT repository to store all your examples
    • store your examples or your team collective examples inside a GIT repository
    • this repository can be kept private or limited to given set of people
  • Gitlab snippets/Github gists solutions to share small code example, as they
    • give an easy way to publish and share any numbers of examples
    • provide user interactions for each example (comments, starring, ...)
    • provide a search engine
    • store the history of all examples changes
  • And it becomes even easier by using the code-examples-manager project
    • it automates everything, and becomes mandatory as soon as you have dozens of examples.
    • Take a look to my publicly shared examples knowledge bases to have a good idea of what it does.

More Repositories

1

jassh

High level scala SSH API for easy and fast operations on remote servers.
Scala
71
star
2

code-examples-manager

Software tool to manage your notes, scripts, code examples, configs,... to publish them as gists or snippets
Scala
37
star
3

zio-lmdb

Lightning Memory Database (LMDB) for scala ZIO
Scala
36
star
4

jajmx

scala JMX API
Scala
31
star
5

sotohp

Photos management
Scala
27
star
6

scala-drools-dummy-project

Minimalist scala drools project
Scala
19
star
7

coursier-launcher

coursier docker container for efficient application or service download and startup
Makefile
9
star
8

zwords

A wordle game for communities
Scala
8
star
9

jaseries

scala API for time numerical series operations.
Scala
7
star
10

primes

Playing with primes using scala language. Draw Ulam spiral, ...
Scala
7
star
11

zio-worksheet

Simplified ZIO user experience in REPL, worksheet or script contexts
Scala
6
star
12

bootstrap

scala script bootstrap mechanism with #include support
Scala
6
star
13

the-weakest-link

Scala
4
star
14

custom-collection

Custom scala collection examples
Scala
4
star
15

scala-dummy-project

scala dummy project with standalone executable jar
Shell
3
star
16

drools-scripting

Drools made easy to use for scripting or testing purposes
Scala
2
star
17

codingame-with-scalakit-example

codingame scalakit example using git submodule to reference the scalakit
Scala
2
star
18

simple-plugin-architecture

Scala simple plugin architecture (with plugin automatic compilation if required)
Scala
2
star
19

exproxy

a 2005 personal project...
Java
2
star
20

cntlm

dockerized cntlm
Shell
2
star
21

primes-scalatra-app

Scala
1
star
22

naturalsort

scala naturalsort algorithm
Scala
1
star
23

web-echo

A websocket/webhook JSON data recorder with API
Scala
1
star
24

akka-sandbox

temporary project to test and learn AKKA 2
Scala
1
star
25

advent-of-code-2023

Scala
1
star
26

bullyboy

sha1 brute force attack
Scala
1
star
27

data-recorder

Scala
1
star
28

advent-of-code-2020

Scala
1
star
29

jenkins-phantomjs-slave

jenkins slave with phantomjs 1.9 docker image
1
star
30

dock-primesui

Shell
1
star
31

jenkins

Jenkins docker image
Shell
1
star