source code quality
TRANSCRIPT
source code quality
Alberto SimõesMarch 10, 2015 – ESEIG-IPP – Vila do Conde
Departamento de InformáticaUniversidade do Minho
outline
Motivation
Code Structure
Code Documentation
Testing
1
motivation
no bad code initiative
3
code problems
∙ Legibility Issues;
∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;
∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;
∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;
∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;
∙ Code should be elegant!
∙ Documentation Issues;
∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;
∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;
∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;
∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;
∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;
∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;∙ Code should work on correct input;
∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;∙ Code should work on correct input;∙ Code should work on incorrect input;
∙ Code should be tested on every change!
4
code problems
∙ Legibility Issues;∙ Code should document itself;∙ Code should be easy to read;∙ Code should be elegant!
∙ Documentation Issues;∙ Documentation should exist;∙ Documentation should follow standards;∙ Documentation should document!
∙ Testing Issues;∙ Code should work on correct input;∙ Code should work on incorrect input;∙ Code should be tested on every change!
4
code structure
code structure
6
use meaningful identifiers
What does this code do?
int x(string g[]) {string p = g[0]; int o = p.length();for (z=1;z<g.length;++z) {
if (g[z].length()>o) { p=g[z];o=p.length(); }}return o;
}
7
use meaningful identifiers
Is this better?
int x(string list[]) {string maxString = list[0];int maxSize = maxString.length();for (i=1;i<list.length;++i) {
if (list[i].length()>maxSize) { maxString=list[i];maxSize=maxString.length(); }
}return maxSize;
}
8
use coherent indentation
Do you prefer this…
int x(string list[]) {string maxString = list[0];int maxSize = maxString.length();for (i=1;i<list.length;++i) {if (list[i].length()>maxSize) { maxString=list[i];maxSize=maxString.length(); }}return maxSize;}
9
use coherent indentation
or this?
int x(string list[]) {string maxString = list[0];int maxSize = maxString.length();for (i=1;i<list.length;++i) {
if (list[i].length()>maxSize) {maxString=list[i];maxSize=maxString.length();
}}return maxSize;
}
10
use coherent identifiers
int x(string Lists[]) {string max_String = Lista[0];int maxSize = max_String.length();for (i=1;i<Lista.length;++i) {
if (Lista[i].length()>maxSize) {max_String=Lista[i];maxSize=max_String.length();
}}return maxSize;
}
11
use coherent identifiers
Choose:
∙ One language:I prefer English given keywords are English, but any will work!
∙ Use one variable style:If you prefer use CamelCaseIdentifiers;Or, why not, underscores_identifiers;but not both!
∙ Note that some languages have conventions:Java libraries use CamelCase;GNU Toolkit (GTK+) use underscores;So, probably a good idea to follow the flow…
12
use coherent identifiers
Choose:
∙ One language:I prefer English given keywords are English, but any will work!
∙ Use one variable style:If you prefer use CamelCaseIdentifiers;Or, why not, underscores_identifiers;but not both!
∙ Note that some languages have conventions:Java libraries use CamelCase;GNU Toolkit (GTK+) use underscores;So, probably a good idea to follow the flow…
12
use coherent identifiers
Choose:
∙ One language:I prefer English given keywords are English, but any will work!
∙ Use one variable style:If you prefer use CamelCaseIdentifiers;Or, why not, underscores_identifiers;but not both!
∙ Note that some languages have conventions:Java libraries use CamelCase;GNU Toolkit (GTK+) use underscores;So, probably a good idea to follow the flow…
12
use standard code structure
Does this work?
int x(string list[]) {; string maxString = list[0]; int maxSize = maxString.length(); for (i=1;i<list.length;++i)
if (list[i].length()>maxSize) {; maxString=list[i]; maxSize=maxString.length(); }; return maxSize; }
Isn’t it cute?
13
use standard and coherent code structure
Choose one, but stick to it!
int x(string list[]) {string maxString = list[0];int maxSize = maxString.length();for (i=1;i<list.length;++i)
if (list[i].length()>maxSize) {maxString=list[i];maxSize=maxString.length();
}return maxSize;
}
int x(string list[]){string maxString = list[0];int maxSize = maxString.length();for (i=1;i<list.length;++i)if (list[i].length()>maxSize){
maxString=list[i];maxSize=maxString.length();
}return maxSize;}
14
use vertical alignment
Most editors suck and mess with vertical alignment.
Nevertheless, it is useful.
See the error?
Sprite tank=LoadSprite(”path/to/sprites/tank.png”);Sprite chopper=LoadSprite(”path/to/sprtes/chopper.png”);Sprite balloons=LoadSprite(”path/to/sprites/balloons.png”);
And now?
Sprite tank = LoadSprite(”path/to/sprites/tank.png”);Sprite chopper = LoadSprite(”path/to/sprtes/chopper.png”);Sprite balloons = LoadSprite(”path/to/sprites/balloons.png”);
15
use vertical alignment
Most editors suck and mess with vertical alignment.
Nevertheless, it is useful.
See the error?
Sprite tank=LoadSprite(”path/to/sprites/tank.png”);Sprite chopper=LoadSprite(”path/to/sprtes/chopper.png”);Sprite balloons=LoadSprite(”path/to/sprites/balloons.png”);
And now?
Sprite tank = LoadSprite(”path/to/sprites/tank.png”);Sprite chopper = LoadSprite(”path/to/sprtes/chopper.png”);Sprite balloons = LoadSprite(”path/to/sprites/balloons.png”);
15
be explicit
C, Java and C# are tolerant, so you can write
if (foo < bar)do_something(foo, bar);
Look, m’a! No curly brackets!
Problem? Later you might need to add an action and probably youwill add it like this:
if (foo < bar)do_something(foo, bar);do_something_else(foo, bar);
And does that do what you mean?
16
be explicit
C, Java and C# are tolerant, so you can write
if (foo < bar)do_something(foo, bar);
Look, m’a! No curly brackets!
Problem? Later you might need to add an action and probably youwill add it like this:
if (foo < bar)do_something(foo, bar);do_something_else(foo, bar);
And does that do what you mean?
16
be explicit ii
So, how do you read this?
if (a < b)if (b < c)a = c;elsec = b;
Or, more important, how does the compiler read it?
if (a < b)if (b < c)
a = c;else
c = b;
if (a < b)if (b < c)
a = c;elsec = b;
17
be explicit ii
So, how do you read this?
if (a < b)if (b < c)a = c;elsec = b;
Or, more important, how does the compiler read it?
if (a < b)if (b < c)
a = c;else
c = b;
if (a < b)if (b < c)
a = c;elsec = b;
17
be explicit ii
Better with curly brackets!
if (a < b) {if (b < c) {
a = c;}
}else {
c = b;}
if (a < b) {if (b < c) {
a = c;}else {
c = b;}
}
Even without indentation you can understand it properly!!
And better! You do not need to know how the compiler interprets it.
18
use proper data structures
Implement related data as a data structure.
So, in pacman we have four ghosts. Store their positions.
int g1x, g1y, g2x, g2y, g3x, g3y, g4x, g4y;
There are only four, right? And it works!
Probably better:
class Pair { public int x, y; };
Pair[] ghost = new Pair[4];
// now use ghost[0].x, ghost[1].y, etc
19
use proper data structures
Implement related data as a data structure.
So, in pacman we have four ghosts. Store their positions.
int g1x, g1y, g2x, g2y, g3x, g3y, g4x, g4y;
There are only four, right? And it works!
Probably better:
class Pair { public int x, y; };
Pair[] ghost = new Pair[4];
// now use ghost[0].x, ghost[1].y, etc
19
use proper data structures
Implement related data as a data structure.
So, in pacman we have four ghosts. Store their positions.
int g1x, g1y, g2x, g2y, g3x, g3y, g4x, g4y;
There are only four, right? And it works!
Probably better:
class Pair { public int x, y; };
Pair[] ghost = new Pair[4];
// now use ghost[0].x, ghost[1].y, etc
19
code documentation
documentation
21
should it exist?
Real programmers don’t comment their code,if it was hard to write,it should be hard to understand and harder to modify.
— unknown
Kidding. It should really exist!
22
should it exist?
Real programmers don’t comment their code,if it was hard to write,it should be hard to understand and harder to modify.
— unknown
Kidding. It should really exist!
22
is this documentation?
/* Computes the length of the longer string */int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {if (list[i].length() > maxSize) {
maxString = list[i];maxSize = maxString.length();
}}return maxSize;
}
Not really!
23
is this documentation?
/* Computes the length of the longer string */int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {if (list[i].length() > maxSize) {
maxString = list[i];maxSize = maxString.length();
}}return maxSize;
}
Not really!
23
documentation relevance
Documentation is like sex:when it is good, it is very, very good;and when it is bad, it is better than nothing.
— Dick Brandon (?)
24
documentation content
Try to include:
∙ What the code is about;∙ What are each of the input arguments/parameters;∙ What is the type and content of the returned value;∙ If any of the method/function parameters are for output;∙ What restrictions does the input values have?∙ What happens when you do not follow that restriction?∙ What exceptions are thrown directy?∙ What exceptions are not catched and might be propagated?∙ What is the algorithm?
25
use standards
Most programming languages have a standard documentationapproach:
∙ Perl has POD;∙ Java has JavaDoc;∙ Haskell has Hadock;∙ C# has “XML Comments”;∙ Python has Sphinx;∙ C has Doxygen;∙ C++ has Doxygen too;∙ Lots of cross-language tools;
26
example: javadoc
/*** Given an array of strings, compute the length of the* longest string.* <p>* This method will not work for empty lists.** @param list the list of strings to be processed;* @return the size of the longest string* in the array;*/
int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {[...]
27
testing
testing
29
does this work?
int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {if (list[i].length() > maxSize) {
maxString = list[i];maxSize = maxString.length();
}}return maxSize;
}
Always!?
What happens on the empty list?
30
does this work?
int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {if (list[i].length() > maxSize) {
maxString = list[i];maxSize = maxString.length();
}}return maxSize;
}
Always!?
What happens on the empty list?
30
does this work?
int LongestString(string list[]){
string maxString = list[0];int maxSize = maxString.length();
for (i=1; i<list.length; i++) {if (list[i].length() > maxSize) {
maxString = list[i];maxSize = maxString.length();
}}return maxSize;
}
Always!?
What happens on the empty list?
30
unit testing
∙ Different tools have different approaches/tools;∙ The idea is the same: test!
∙ What to test?∙ Everything!
∙ Test a simple case;∙ Test a large case;∙ Test weird cases;∙ Test limit cases!
31
unit testing
∙ Different tools have different approaches/tools;∙ The idea is the same: test!∙ What to test?
∙ Everything!∙ Test a simple case;∙ Test a large case;∙ Test weird cases;∙ Test limit cases!
31
unit testing
∙ Different tools have different approaches/tools;∙ The idea is the same: test!∙ What to test?∙ Everything!
∙ Test a simple case;∙ Test a large case;∙ Test weird cases;∙ Test limit cases!
31
do it yourself testing
static class Test {static void is(int a, int b) {
System.out.println( a == b ? ”ok” : ”nok” );}
}
Then…
string[] array = { ”banana”, ”apple”, ”strawberry” };Test.is( 10, LongestString(array) );
string[] array1 = { ”pear” };Test.is( 4, LongestString(array) );
32
do it yourself testing
static class Test {static void is(int a, int b) {
System.out.println( a == b ? ”ok” : ”nok” );}
}
Then…
string[] array = { ”banana”, ”apple”, ”strawberry” };Test.is( 10, LongestString(array) );
string[] array1 = { ”pear” };Test.is( 4, LongestString(array) );
32
do it yourself testing
You can ever try and test if a method throws an exception!
static class Test {static void throws(Runnable code, Class<?> class) {
boolean ok = false;try {
code.run();} catch (Exception e) {
if (e instanceof class) ok = true;}System.out.println( ok ? ”ok” : ”nok” );
}}
Non Tested Code!
33
testing: why?
∙ To know your code is working;∙ To know your code is still working;∙ To know that your latest change does not mess with yourworking code;
34
must read
How To Write Unmaintainable Codeby Roedy Green
https://www.thc.org/root/phun/unmaintain.html
Thank you!
35