Search
  • First Digital

Don't use comments

If anything seems undeniable, it’s that you have to apply comments to your code. I mean, why shouldn’t you? All programming languages have it, even markup languages have it - it’s obviously a feature that has survived the test of time.




Well I would say that object-oriented programming is also an old idea, older than some might think. Inheritance, being one of the major pillars of object-oriented programming, has shown to be probably one of the most useless features of OOP. Inheriting from concrete classes has the ability to violate at least 2 of the SOLID principles and even outside of those design methodologies, I’ve seen harsh criticism of the practice. The reality of design methodologies and coding movements is that they’re almost always a reaction to a previous practice found not to work. Agile was a reaction to the failure of Waterfall and the Software Craftsmanship movement was a reaction to the seriously misinterpreted message of Agile.


A lot of ideas in software development are best guesses, waiting to be tested by the harsh judgement of time.


That brings me to comments and why you shouldn’t use them.


REASON 1: VIEW DISTANCE


When you make a comment on a function or instance variable within a sourcefile, it’s only visible within that source file. So in OOP languages, if you use an object other than the instantiation of the current class, you can’t see any of the comments of the methods being called on that object. This obviously gets worse the further you “zoom” out of the current context. If you have an object containing multiple different nested objects, the reliability of the method names decreases with each object you go up the nested object hierarchy. This is because comments justify bad method names and bad method names create inaccurate messaging for users of a method.



This is best illustrated by example:


public class StudentCalculations {


//Calculate the average score, apply it and then penalise absent days

public void calculateAverageScore(ReportCard reportCard){

Int testsSum = 0;

foreach(TestDTO test: reportCard.getTests()) {

testsSum += test.getScore();

}

reportCard.average = testsSum / reportCard.getTests().count();

reportCard.average = reportCard.average - reportCard.getDaysAbsent();

}

}


public class SubjectClass {


//Calculate the average score of each student and apply it to

public void calculateStudentAverageScores(StudentDTO students) {

StudentCalculations calculator = new StudentCalculations();

foreach(StudentDTO student: students) {

calculator.calculateAverageScore(student.getReportCard());

}

}

}


public class Subject {


private List<ClassDTO> classes;


//Calculate subject averages of all students

public CalculateStudentAverages() {

SubjectClass subjectClass = new SubjectClass();

foreach(ClassDTO _class: classes) {

subjectClass.calculateStudentAverageScores(_class.getStudents());

}

}


}


Studying the code you’ll realize that there’s a bug here. The absent days penalty will be doubled, because the developer coding the “SubjectClass” class, didn’t look at the SubjectCalculator class comment and assumed that the penalty hasn’t been applied yet. You might say this is a bit contrived? Well, I would say it depends on the situation. I have found myself in this situation before, and it mostly happens when you’re reusing methods you’ve seen before. When anyone sees a method called “CalculateAverage”, they’d usually make a safe assumption it doesn’t do anything else.


Once you make a bunch of these small mistakes, it really starts to add up - as you have to scour the codebase to find that one spot where dev left a hidden feature in a badly named method. Taking a few seconds to think of a good method name and save you minutes of bug fixes. And these minutes add up over the long periods of development.


Below is an example of what better names might look like:


public class StudentCalculations {



public void applyAverageScoreAndPenalties(ReportCard reportCard){

Int testsSum = 0;

foreach(TestDTO test: reportCard.tests) {

testsSum += test.getScore();

}

reportCard.average = testsSum / reportCard.getTests().count();

reportCard.average = reportCard.getAverage() - reportCard.getDaysAbsent();

}

}


public class SubjectClass {


public void applyReportCardAverageScoresAndPenalties(StudentDTO students) {

StudentCalculations calculator = new StudentCalculations();

foreach(StudentDTO student: students) {

calculator.applyAverageScoreAndPenalties(student.getReportCard());

}

}

}


public class Subject {


private List<ClassDTO> classes;


public applyStudentReportCardAveragesAndPenatliesToReportCards() {

SubjectClass subjectClass = new SubjectClass();

foreach(ClassDTO _class: classes) {

subjectClass.applyReportCardAverageScoresAndPenalties(_class.getStudents());

}

}


}


REASON 2: READABILITY


This is one of the obvious reasons, but I think the real value can only be seen in an example.


Example 1: Using comments to write a quicksort algorithm


public void quickSort(int[] array) {

sort(array, 0, array.length -1);

}


//low = first index, high = last index

private void sort(int[] array, int low, int high) {

if(low < high) {

Int pb = partition(array, low, high); //partition border

// recursively sort the new partitions

sort(array, low, pb);

sort(array, pb+1, high);

}

}


private int partition(int[] array, int low, int high) {

Int p = array[(high+low)/2]; // pivot

Int x = low;

Int y = high;

while(true) {

//find the index of the item valued more than the pivot, starting from the left first index.

while (array[x] < pivot) {

x++;

}

//find the index of the item valued less than the pivot, starting from the right first index

while (array[y] > pivot) {

y--;

}

if(x >= y) {

return y;

}

Int t = array[y] //placeholder for item valued greater than the pivot, to be swapped with item valued less than the pivot


//swap the item value greater than the pivot, with the one valued less than the pivot

array[y] = array[x];

array[x] = t;

}

}


Example 2: Using good method and variable names


public void quickSort(int[] array) {

sort(array, 0, array.length -1);

}


private void sort(int[] array, int firstIndex, int lastIndex) {

if(low < high) {

Int partitionBorder = partition(array, low, high);

sort(array, firstIndex, partitionBorder);

sort(array, partitionBorder+1, lastIndex);

}

}


private int partition(int[] array, int firstIndex, int lastIndex) {

int pivot = array[(firstIndex+lastIndex)/2];

int lowerPartitionIndex = firstIndex;

int higherPartitionIndex = lastIndex;

while(true) {

lowerPartitionIndex = findItemValuedGreaterThanPivot(array, lowerPartitionIndex, pivot);

higherPartitionIndex = findItemValuedLessThanPivot(array, higherPartitionIndex, pivot);

if(lowerPartitionIndex >= higherPartitionIndex) {

return higherPartitionIndex;

}

swapValues(array, lowerPartitionIndex, higherPartitionIndex);

}

}


private int findItemValuedGreaterThanPivot(int[] array, int lowerPartitionIndex, int pivot) {

while (array[lowerPartitionIndex] < pivot) {

lowerPartitionIndex++;

}

return lowerPartitionIndex;

}


private int findItemValuedLessThanPivot((int[] array, int higherPartitionIndex, int pivot) {

while (array[higherPartitionIndex] > pivot) {

higherPartitionIndex--;

}

return higherPartitionIndex;

}


private void swapValues(int[] array, int lowerPartitionIndex, int higherPartitionIndex) {

Int higherPartitionIndexValueHolder = array[higherPartitionIndex];

array[higherPartitionIndex] = array[lowerPartitionIndex];

array[lowerPartitionIndex] = higherPartitionIndexValueHolder;

}


Writing code this way becomes way easier to read, than it would be when using comments. For one, comments do convey what a block of code does, but not exactly when and where specific steps are executed. With good method names, you can understand exactly how and where certain steps of a method interact. With comments you’re told what a method does, but you still have to read the code afterwards. With good method names, you’re reading code as fast as you read comments.


If my methods don’t read better than the comments to you, it’s mostly a fault to my bad naming. In any project, the goal should be to criticize each other’s use of language to improve code clarity to any fresh pair of eyes.


BIBLIOGRAPHY

http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata (Taught me to pursue writing better method names.)

https://en.wikipedia.org/wiki/Quicksort (Used to reference quick sort)


Published By: Duen Oosthuizen



4 views0 comments