Basic Programming Skills


Published: 2020-08-09
Updated: 2021-01-09
Web: https://fritzthecat-blog.blogspot.com/2020/08/basic-programming-skills.html


When I searched for "Basic Programming Skills" on the Internet, I didn't find any useful article. So here is my list of things every software developer should know and practice. Of course this is about programming languages. Code examples were taken from Java and JS (JavaScript).

A software developer translates business language into computer language. Sometimes they also do business analysis, sometimes they also play table-tennis, and all are waiting for what they call career. This Blog is for the first kind of developer, not the Jack of all trades.

  1. Avoid Copy & Paste Programming
  2. Naming Matters
  3. Define Local Variables Where Used
  4. Don't Catch Exceptions
  5. Minimize Dependencies

Avoid Copy & Paste Programming

Also called "Code Duplication". Copy & paste programming is the oldest and worst programmer sin. This causes days and days of repeated bug-tracking with subsequent refactoring. Copy & paste code is like a virus, it spreads everywhere.

There have been so many writings about this that I don't want to go into details. Simply don't do it, take your time to do everything once-and-only-once. Try to be DRY = "Don't Repeat Yourself". Don't be WET = "We Enjoy Typing" :-)

Bad:

class Person
{
public final String firstName;
public final String secondName;

Person() {
this.firstName = null;
this.secondName = null;
}
Person(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
}

Good:

class Person
{
public final String firstName;
public final String secondName;

Person() {
this(null, null);
}
Person(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
}

Don't use programming languages that offer no facilities to avoid code duplication. Give yourself time to learn DRY, it's not so easy. Prefer inheritance to delegation, but avoid deep hierarchies. Avoid multiple inheritance to not become ambiguous and hard to understand, keep it simple.

Naming Matters

One of the major problems you find in source code written by newcomers is bad naming.

The saying of "Doesn't matter how this function is called" has been around for decades. Wrong. All other developers should be able to understand your solutions. Naming builds onto common sense, and teams that lack it will name badly.

Another one is "Nobody except me will maintain this code". Wrong, the times when a single person could maintain a software project are long gone. Moreover I've seen lots of developers that couldn't understand their own code after some time.

Next is abbreviations. In old times it was justified by memory economy, but we've been living in times of Gigabytes for long now, so there's no more justification for using abbreviations.

The biggest problem is that names are chosen too abstract. Functions like process() or doit() take over as soon as the problem deviates from business logic into purely technical issues. It is like losing reality, deep inside the problem, not being able to communicate any more: "Nobody knows the trouble I've seen":-(

Bad:

public void process(String s) {
....
}

Good:

public void interpretXmlContent(String filePath) {
....
}

Rules:

Bonus: if you're good in naming, you won't need to document so much.

Define Local Variables Where Used

Another programmer habit that has been around for decades, called variable hoisting: "On top I define all variables I'll need below". Wrong, this pushes refactoring ("Extract Method") to the brink of impossibility.

Bad:

function interpretXmlContent(xmlContent) {
var i, header, fragment;

for (i = 0; i < xmlContent.size(); i++) {
header = interpretHeader(xmlContent);
fragment = interpretFragment(xmlContent);
....
}
};

Good:

function interpretXmlContent(xmlContent) {
for (let i = 0; i < xmlContent.size(); i++) {
let header = interpretHeader(xmlContent);
let fragment = interpretFragment(xmlContent);
....
}
};

Rules:

Take note: in reality the smallest unit developers pack their solutions into is not the function() { ... }, it is the { block }! Thus such parts should be later extractable as separate functions. In the example above it is the loop body I may want to extract.

Don't Catch Exceptions

As soon as you get to know exceptions, you will be seduced to use it for implementing application logic. Result is code that is full of useless try-catch clauses, suppressing any trace of any bug. An exception is an error indicator and needs to be seen on the logging console, including all of its stack-trace.

Bad:

public void playSound(Sound sound) {
if (sound == null)
throw new IllegalArgumentException("Can not play null sound!)"

....
}

public void playAllSounds(List<Sound> sounds) {
for (Sound sound : sounds) {
try {
playSound(sound);
}
catch (Exception e) {
log.error("We don't like exceptions so we log them where nobody looks: "+e);
}
}
}

Good:

public void playSound(Sound sound) {
if (sound == null)
throw new IllegalArgumentException("Can not play null sound!)"

....
}

public void playAllSounds(List<Sound> sounds) {
for (Sound sound : sounds) {
playSound(sound);
}
}

Rules:

Minimize Dependencies

This is about the number of imports, fields and methods in a class, the number method parameters and calls made from a method. For Java, this could be extended to the number of classes in a packages, and packages in a module.

Small is beautiful. The smaller the unit of work, the more it will be reusable. A high number of dependencies makes any source code short lived. Of course it is not possible without dependencies, but we should try to reduce them.

Bad:

class Rectangle
{
public void drawRectangle(
int x,
int y,
int width,
int height,
int borderThickness,
Color foreground,
Color background)
{
....
}
}

Good:

class Rectangle
{
private final int borderThickness;
private final Color foreground;
private final Color background;

public Rectangle(
int borderThickness,
Color foreground,
Color background) {
this.borderThickness = borderThickness;
this.foreground = foreground;
this.background = background;
}

public void drawRectangle(
int x,
int y,
int width,
int height)
{
....
}
}

Here I don't prefer parameters to class fields, because the high number of parameters demands a context.

Rules:

The smaller classes and methods are, the more we will need good naming. Software heavily depends on it.

Conclusion

This was a morale lecture. Badly needed in times where everybody tells morale being replaced by money. Don't insist on freedom when writing code, this is the last thing we want if we're going for common sense.





ɔ⃝ Fritz Ritzberger, 2020-08-09