Code Readability for "Higher" Level Languages

  • Thread starter STEMucator
  • Start date
  • Tags
    Code
In summary: Compacting code may seem like a time-saving technique, but it can actually cause more problems in the long run. It can make code harder to understand and maintain, and can also lead to bugs and errors. Writing clear and readable code is important for all developers, regardless of their level of skill. It may take a bit more effort, but it ultimately results in more efficient and effective code.
  • #36
newjerseyrunner said:
Outside of C, you should never use goto, you should use scope to clean up:

Bad code
Code:
FILE * fp1 = fopen("/tmp/test.txt", 'w');
if (!fp1) goto error1;
FILE * fp2 = fopen("tmp/test2.txt", 'w');
if (!fp2) goto error2;

error2:
   fclose(fp1);
error1:
    return;

Good code
Code:
struct file_cleanup {
    file_cleanup(FILE * fp) : myfp(fp){}
    ~file_cleanup(){ if (myfp) fclose(myfp); }
    FILE * myfp;
};

file_cleanup fp1(fopen("/tmp/test.txt", 'w'));
if (!fp1.myfp) return;
file_cleanup fp2(fopen("/tmp/test.txt", 'w'));
if (!fp2.myfp) return;   //fp1 is automatically cleaned up

Baloney. I agree your goto example is bad 'need to use goto' code, mine is not in the correct context (C device driver).
http://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/
http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c

http://c.learncodethehardway.org/book/
 
Last edited:
Technology news on Phys.org
  • #37
newjerseyrunner said:
Outside of C, you should never use goto, you should use scope to clean up:

Bad code
Code:
FILE * fp1 = fopen("/tmp/test.txt", 'w');
if (!fp1) goto error1;
FILE * fp2 = fopen("tmp/test2.txt", 'w');
if (!fp2) goto error2;

error2:
   fclose(fp1);
error1:
    return;
That's bad code because you left the file pointer fp2 open. That would be considered "good code" in some circles that code in C had you added a fclose(fp2) just before error2.

It would of course be considered very bad code in the C++ world. It would be non-compilable code in Java (even without the pointers).

Good code <elided>
I wouldn't quite call that "good" (raw pointers, leaky abstraction), but I do get the point, and it is a very important point. Well-written C++ code doesn't need gotos because the objects clean up after themselves on destruction. This goes by the terrible acronym "RAII" (Resource Allocation Is Initialization). This doesn't just apply to memory. It applies to resources of all types. I'm biased, but C++ is better in this regard than garbage collection languages. C++ doesn't have a "finally" keyword because it's not needed. Instances of classes that follow RAII magically clean themselves up when they go out of scope.
 
  • #38
Just used another ternary operator to add a delay enhancement to my local Linux branch for SPI transfers. If you don't change the field from the default of 0 the old 10us remains but if you set cs_change_usecs to a value >0 it's used instead of the fixed delay. Quick and easy to understand.
Code:
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 57a1950..3f784df 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -836,7 +836,7 @@ static int spi_transfer_one_message(struct spi_master *master,
                                keep_cs = true;
                        } else {
                                spi_set_cs(msg->spi, false);
-                               udelay(10);
+                               udelay(xfer->cs_change_usecs ? xfer->cs_change_usecs : 10);
                                spi_set_cs(msg->spi, true);
                        }
                }
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 856d34d..131f145 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -622,6 +622,7 @@ struct spi_transfer {
#define        SPI_NBITS_DUAL          0x02 /* 2bits transfer */
#define        SPI_NBITS_QUAD          0x04 /* 4bits transfer */
        u8              bits_per_word;
+       u8              cs_change_usecs;
        u16             delay_usecs;
        u32             speed_hz;
 
  • #39
Zondrina said:
are there actual advantages to writing code so compactly?
There are only disavantages. A few of them have already been point out. This question is about High level language. You compact nothing by avoiding to write two return one "if" and two braces. The expression tree would be the same, if you had not introduced a bug. The correct equivalent is
Code:
return !booked ? booked = true : false;
So, concretely, you have shoot yourself in the foot already by asking explicitly to read 'booked' twice (**). It was too hard.

There is is more. Writing high level language means your code will have a long lifetime and be maintained by coworker.
This original code is surely a made up example. There is no way a real booking will use such a method.
Here is what's going to happens. The method will be called in a dozen places, expecting a bool.
One years later, another smart ass will turn (private) booked into an enum (confirmed state added), or worse, a object with bool conversion semantic (called trice ***)
So the method will need anyway to have its braces back.

Code readability, for any type of language, should express your intent with less possible obfuscation. In most case, the code will be its own documentation, and won't need even a glance at the comments. And in most cases, it will be more efficient.
 

Similar threads

Replies
3
Views
3K
Replies
7
Views
2K
Replies
5
Views
4K
Replies
75
Views
5K
Replies
12
Views
3K
Back
Top