Stories
Slash Boxes
Comments

SoylentNews is people

posted by hubie on Monday June 10, @02:11AM   Printer-friendly
from the be-descriptive-and-concise dept.

Programming style is not a matter of efficiency in a program. It is a matter of how easy it is to write or read a program, how easy it is to explain the program to someone else, how easy it is to figure out what the program does a year after you've written it; and above all, style is a matter of taste, of aesthetics, of what you think looks nice, of what you think is elegant.

Although style is mainly a matter of taste, a programmer with a "good" style will find his programs easy to write, easy to read, and easy to explain to others. ...

In particular, you may have acquired special programming tricks that you are very fond of, and that aren't used by other programmers, but that don't make your programs much more efficient. I urge you to stop using those tricks. As Samuel Johnson once said, "Read over your compositions, and when you meet with a passage which you think is particularly fine, strike it out."

In other words, make your style simple, not complicated, even though the complicated style may seem to have some abstract virtues. ...

(F. Black, "Styles of Programming in LISP," in The Programming Language LISP: Its Operations and Applications, ed. E. Berkeley and D. Bobrow (1964), p96 (p106 of the PDF))

When teaching an algorithms course, Craig Partridge, of Colorado State University, discovered that his students had little to no idea of how to divide their code into functions. So he wrote a short guidance paper (pdf).

What other advice, oh battle-hardened developer, would you give starting-out programmers/developers about how to approach a project/codebase?


Original Submission

This discussion was created by hubie (1068) for logged-in users only. Log in and try again!
Display Options Threshold/Breakthrough Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
(1)
  • (Score: 5, Insightful) by c0lo on Monday June 10, @02:27AM (5 children)

    by c0lo (156) Subscriber Badge on Monday June 10, @02:27AM (#1359971) Journal

    Programming style is not a matter of efficiency in a program.

    Unless it absolutely needs to be (and thus one needs to adopt a very specific programming style to abide by the constraints).

    It is a matter of ... how easy it is to explain the program to someone else

    To me, that's the crux of the matter; even when you need to code for efficiency (high speed or low memory), if you can't explain it (to someone else assumed equally aware of the efficiency constraints; or, shudders, even to yourself), you can throw away that code. Maintainability and extensibility demands a clear mental image of what the code does and how it does it (and why is it structured one way or the other).

    --
    https://www.youtube.com/watch?v=aoFiw2jMy-0 https://soylentnews.org/~MichaelDavidCrawford
    • (Score: 2) by ls671 on Monday June 10, @07:26AM (2 children)

      by ls671 (891) Subscriber Badge on Monday June 10, @07:26AM (#1359992) Homepage

      Coding for efficiency (high speed or low memory) doesn't necessarily makes code more complex and harder to explain. Most of the times it's just a matter of knowing what you are doing and understanding the underlying layers which often programmers sadly don't know anything about these days.

      --
      Everything I write is lies, including this sentence.
      • (Score: 2) by c0lo on Monday June 10, @11:04AM (1 child)

        by c0lo (156) Subscriber Badge on Monday June 10, @11:04AM (#1360012) Journal

        Coding for efficiency (high speed or low memory) doesn't necessarily makes code more complex and harder to explain.

        True, but it's not a given that optimizations will always let the code clear at the first read (i.e. why the code looks "special" - e.g. Real Time Systems)

        and understanding the underlying layers

        Special case if/when one needs to program (or read the code of) the underlying layers.

        --
        https://www.youtube.com/watch?v=aoFiw2jMy-0 https://soylentnews.org/~MichaelDavidCrawford
        • (Score: 3, Interesting) by ls671 on Monday June 10, @06:59PM

          by ls671 (891) Subscriber Badge on Monday June 10, @06:59PM (#1360068) Homepage

          Again, very often, no optimization is needed when you know what you are doing from the start. And quite often, only simple and quick thinking and a little knowledge is needed. There are plenty of examples like the one I give below and yet, I have seen the use case below and many others done the wrong way over and over again:

            https://www.baeldung.com/java-string-concatenation-methods [baeldung.com]

          I think that if you need to "optimize" such similar use cases, you are doing it wrong from the start but I have seen plenty of code doing it wrong from the start everywhere with many use cases.

          --
          Everything I write is lies, including this sentence.
    • (Score: 2, Interesting) by shrewdsheep on Monday June 10, @08:30AM (1 child)

      by shrewdsheep (5215) on Monday June 10, @08:30AM (#1359996)

      One strategy I have adopted is to write two versions: one that is clear and well-structured and one that is optimized. In a way this approach is necessary for correctness testing.

      • (Score: 3, Interesting) by c0lo on Monday June 10, @09:44AM

        by c0lo (156) Subscriber Badge on Monday June 10, @09:44AM (#1360004) Journal

        Sensible strategy, but it doesn't come for free:
        1. not always possible - think microcontrollers, strapped for the code memory too (thus, there's no room for a not-optimized version)
        2. not always risk free - you need a full-proof demonstration that the optimized and explicit/clear code produces the same behaviour
        3. maintenance/code change/enhancement is double the cost.

        --
        https://www.youtube.com/watch?v=aoFiw2jMy-0 https://soylentnews.org/~MichaelDavidCrawford
  • (Score: 5, Insightful) by DrkShadow on Monday June 10, @02:36AM (4 children)

    by DrkShadow (1404) on Monday June 10, @02:36AM (#1359972)

    Rule 1: Do not store documentation in Google Drive. It's an excellent way to ensure that no one will ever be able to find it.

    • (Score: 5, Insightful) by canopic jug on Monday June 10, @03:27AM (2 children)

      by canopic jug (3949) Subscriber Badge on Monday June 10, @03:27AM (#1359976) Journal

      And even if they do manage find a document there in Google Drive, it will have to be ignored because by being in Google Drive the association with the person or institution cannot be inferred. For all we know the document at the end of a Google Drive link is falsified, outdated, or just plain malware like most of them there are anyway. Where is the correct link to the guidance document? i.e. the one hosted at a colostate.edu domain?

      --
      Money is not free speech. Elections should not be auctions.
      • (Score: 5, Interesting) by quietus on Monday June 10, @12:32PM (1 child)

        by quietus (6328) on Monday June 10, @12:32PM (#1360019) Journal

        Astute comment. The original link came from an ACM Queue post, and I just blindly trusted it -- as one so often does on the Interwebs.

        You are right, ofcourse, I should have checked out the site of the educational institution the author *claims* to belong to. I did not though, which nicely circles back to a remark my brother made when I told him about the hack in A Hack Admirable (sub): that in future the Internet might become a thing for intellectuals/engineers only, while his children (now at university) might well pull out of it altogether, as it becomes ever harder to distinguish between what is real, trustworthy, and all the other content.

        • (Score: 3, Interesting) by acid andy on Monday June 10, @08:58PM

          by acid andy (1683) on Monday June 10, @08:58PM (#1360077) Homepage Journal

          in future the Internet might become a thing for intellectuals/engineers only, while his children (now at university) might well pull out of it altogether, as it becomes ever harder to distinguish between what is real, trustworthy, and all the other content.

          That sounds very optimistic. I have the impression that many or even most people don't really think about distinguishing between real and false online. If their tribe are pushing it, it's real as far as they're concerned. Or at best they rely on a subconscious feeling whether the source is valid, which could be based on who they think it came from.

          We're not completely immune to such tendencies here, but we tend to value information coming from scientists and technical experts a little higher initially than say, a celebrity or politician. But at least we stop to scrutinize the claims from time to time. In fact the usual commenting process on SN is to tear apart any claims in TFA with the utmost cynicism, so yeah, I still like to think we do better than most online.

          --
          Consumerism is poison.
    • (Score: 4, Informative) by Beryllium Sphere (r) on Monday June 10, @06:41AM

      by Beryllium Sphere (r) (5062) on Monday June 10, @06:41AM (#1359987)

      I knew someone who had a whole company dedicated to helping hospitals be sure they were working with up to date documentation. It was a surprisingly sophisticated problem.

  • (Score: 4, Insightful) by Rosco P. Coltrane on Monday June 10, @02:57AM (6 children)

    by Rosco P. Coltrane (4757) on Monday June 10, @02:57AM (#1359974)

    In most companies I've worked for, the style is imposed. There are many coding conventions and they have nothing to do with how pleasing they look.

    I for one stick to the (now very outdated) coding standards in force when I was young: I code strictly for 80 columns and I indent with 2 spaces. It works for me for my own personal projects, and while I often use 80-column terminals because they're more compact and you can have more of them side to side in a large window, it's mostly a matter of personal taste at this point. But it's only okay because they're my own projects: if I did that at work, I'd be asked why I didn't follow the guideline at the next software review, and quicky fired if I kept doing it.

    • (Score: 3, Insightful) by KritonK on Monday June 10, @05:24AM (1 child)

      by KritonK (465) on Monday June 10, @05:24AM (#1359985)

      I use 80 lines and two spaces for indentation myself, too.

      The 80 lines come from heaving learned to program on 24⨉80 terminals; I still prefer to use vi on a 24⨉80 window than use an IDE.

      Regarding two-space indentation: back in the dawn of time, I didn't care for indentation, until I saw someone use two spaces instead of an 8-space tab. I loved that style, as it was easy to type, made the code more readable, and didn't get out of hand, as it did with tabs. A few years later, I read an article in Software Practice and Experience, where they had measured the readability of programs that used different sizes of indentation. They concluded that the most readable programs were those that used 2-4 spaces for indentation. (I've seen programs using 8 spaces for indentation, where multiply nested lines begin past the middle of the wider than 80 characters text window. Perhaps this is why one of the rules in the guidance paper is not to use more than three levels of conditional control. I've also seen programs using only one space of indentation; they are worse than having no indentation at all!)

      • (Score: 4, Touché) by Rosco P. Coltrane on Monday June 10, @08:42AM

        by Rosco P. Coltrane (4757) on Monday June 10, @08:42AM (#1359998)

        The 80 lines come from heaving learned to program on 24⨉80 terminals; I still prefer to use vi on a 24⨉80 window than use an IDE.

        Was that the short-lived VT100-Portrait-Mode terminal? 🙂 80 lines sounds great, but 24 characters isn't much.

    • (Score: 4, Interesting) by JoeMerchant on Monday June 10, @08:57PM (2 children)

      by JoeMerchant (3937) on Monday June 10, @08:57PM (#1360076)

      I have been lucky enough that nobody has ever successfully imposed a style guide on my code. A few have tried, but wiser heads have always implemented such enthusiasm as guidelines rather than rules.

      My favorite style trick is formatting code tabularly.

      If you have two or more lines of code which do similar things with just a few differences, express each thing in a single row, and align the elements into columns so the similarities and differences are more readily seen.

      If the "thing" takes more than one (wide) line to express, put it into a function and call once per row with arguments aligned as vertical columns.

      It's pretty dramatic how much less readable code becomes when you start in this tabular style, then compare it to the same code processed through a style guide compliant formatter that strips the excess whitespace.

      --
      🌻🌻 [google.com]
      • (Score: 2) by gnuman on Monday June 10, @10:21PM (1 child)

        by gnuman (5013) on Monday June 10, @10:21PM (#1360088)

        There should be a mod for "Scary!". But without example, it's difficult to visualize what you are trying to say. Is your code python compatible? Or significant whitespace would jinx it?

        • (Score: 2) by JoeMerchant on Tuesday June 11, @02:43AM

          by JoeMerchant (3937) on Tuesday June 11, @02:43AM (#1360110)

          Python makes it more challenging, I generally avoid Python (exception being Raspberry Pi Pico land...)

          Mostly I am in C++.

          --
          🌻🌻 [google.com]
    • (Score: 2) by weirsbaski on Tuesday June 11, @07:52AM

      by weirsbaski (4539) on Tuesday June 11, @07:52AM (#1360126)

      and I indent with 2 spaces.

      Indenting with 2 spaces kind of bites- mess the indentation off by a single space, and you have to stop what you're thinking to load up the new task of deciding whether the indentation is 1 space too much or 1 space too little.

      For me the perfect indentation is 4 spaces- enough to keep the scoping clear even on indentation typos, but not so much that it blows up on the text-editor's width.

  • (Score: 5, Interesting) by Thexalon on Monday June 10, @03:18AM (5 children)

    by Thexalon (636) on Monday June 10, @03:18AM (#1359975)

    When programming, you will regularly be expected to come up with names for things: Classes, variables, parameters, functions, etc. A great name uses only words with meaning, is fairly compact, and tells you exactly what the thing is or does with minimal fuss. A bad name will either be too vague to be useful, or super-specific and unwieldy. And yes, your IDE will make it easy for you to not have to retype long confusing names, but it won't avoid you and your colleagues and anyone else who has to deal with your code having to read it every time you're going over your code again to try to discover WTF you did and why TF you did it that way.

    What I was just rattling off as advice for a junior developer last week about how to improve his naming:
    1. The name describes the "what".
    2. The comment before the function / class / public variable describes the "why".
    3. The body of the definition describes the "how".

    --
    The only thing that stops a bad guy with a compiler is a good guy with a compiler.
    • (Score: 4, Insightful) by PiMuNu on Monday June 10, @02:19PM (3 children)

      by PiMuNu (3823) on Monday June 10, @02:19PM (#1360033)

      > 2. The comment before the function / class / public variable describes the "why".

      Something I do but many others don't (maybe it is my mistake) is to describe sufficient implementation details on a method so that a reader can use it without digging into the detailed code. That means describing what the function does, what the variables are and any invalid values, what the return values are, pertinent exceptions. That is much more than "why".

      • (Score: 2) by JoeMerchant on Monday June 10, @09:09PM (2 children)

        by JoeMerchant (3937) on Monday June 10, @09:09PM (#1360078)

        IMO, the best code (with well chosen functions and symbol names) truly does document itself.

        Rarely should a function be longer that easily fits on a screen, unless it is doing a repetitive task with variations in the symbols being operated on.

        Local use only variables can be short like a, b, i and j, function parameters should have descriptive names, and global variables should be particularly descriptive.

        Yes, I am familiar with the philosophical abuse flung in the direction of global variables. Having implemented and maintained a large system which uses consistent property names throughout, including when crossing from microcontroller code to C++ to .NET, I can attest to the value of being able to grep all the code bases for references to both settings and getting those unique global property names.

        --
        🌻🌻 [google.com]
        • (Score: 2) by Mykl on Monday June 10, @11:29PM (1 child)

          by Mykl (1112) on Monday June 10, @11:29PM (#1360094)

          I stepped into an 'old school' development environment years ago. They didn't have a naming convention to distinguish between global and local variables (or data types), which occasionally resulted in drama. Once I was allowed to implement some changes to those conventions, those problems disappeared.

          Yes, the variable names were 1-2 characters longer afterward, but the extra bytes were worth it.

          • (Score: 2) by JoeMerchant on Tuesday June 11, @02:49AM

            by JoeMerchant (3937) on Tuesday June 11, @02:49AM (#1360111)

            Yeah, our global properties are readily recognizable by their name style (they start with a three letter code of the module that is the primary user of the property... Or SYS when there is no clear primary user.)

            What messed us up a little is when the .NET guys started a parallel property system for their internal use, newbies to the system get confused by the difference between "Rabbit properties" and ".NET properties."

            --
            🌻🌻 [google.com]
    • (Score: 3, Interesting) by DannyB on Monday June 10, @02:45PM

      by DannyB (5839) Subscriber Badge on Monday June 10, @02:45PM (#1360039) Journal

      Good variable names are definitely important. The best variable names can be squeezed to fit on one line of code without wrapping around in the editor.

      Variables should name what they hold. They should include the units (if applicable) unless the TYPE of the variable indicates the units.

      long whenToCheckEmailInBoxMillisecondsSinceMidnight1970;

      Or

      Time whenToCheckEmailInbox;

      Another example:

      int preferredHairColorRGB = 0x00FF00;

      Or

      Color preferredHairColor = Color.GREEN;

      None of this was a problem back in the day. In my day sonny, we could write some variable names with a single letter! Yessiree! This was before the dark times. Back when Java programmers were all safely institutionalized as God intended.

      --
      Since nobody defrags SSDs anymore, they are more (or less?) prone to failure of their seek mechanisms.
  • (Score: 5, Interesting) by Anonymous Coward on Monday June 10, @03:27AM (18 children)

    by Anonymous Coward on Monday June 10, @03:27AM (#1359977)

    In particular, you may have acquired special programming tricks that you are very fond of, and that aren't used by other programmers, but that don't make your programs much more efficient. I urge you to stop using those tricks.

    My style is definitely not elegant, nice looking or efficient. But I'm not going to change it just because some dude in a shiny ivory tower urges me.

    Example: My production code has got Log statements every few lines, often every other line.

    Also my logging library has context logging. Basically if the log message is below the log level, it doesn't appear in the log file but it goes to a ring buffer (size is configurable typically 50 lines worth). But if an ERROR occurs the logs in the ring buffer are logged followed by the ERROR log message. So this way even in production you can get some debug level logs if errors occur and the log file isn't cluttered with debug logs while things go well. The drive is less likely to get filled or slowed down by debug logs.

    This is not efficient CPU-wise, but for most business apps the performance impact isn't a problem and in production normally the loops where performance matter shouldn't be logging for every iteration anyway.

    It's also not elegant. But so far I'm more likely to get useful stuff in the log files when customers send me the log files. I've NEVER had to tell the customer change to log at debug level and wait for the error to occur again.

    So he can say I'm doing it wrong but in my opinion most of the world is doing it wrong if their logging doesn't require high performance (or strict/low resource requirements) and they're not already doing something similar to what I'm doing.

    Another thing, my logs have a column in the log line with the log level indicated by hashes and dots:

    #....... = Debug
    ##...... = Info
    ###..... = Notice
    ####.... = Warning
    #####... = Error
    etc

    This way you can grep the log files/directory/directories for #### and easily and quickly find log messages of Warning level and above.

    This "inefficient" trick costs extra characters per log message and CPU cycles used to look up the required hash string.

    Will I stop using it? Nope. While it is inefficient and inelegant for the real world main problem, to me it is more efficient and elegant for the real world side problems.

    his students had little to no idea of how to divide their code into functions

    One thing about dividing code to functions. It 100% makes sense if those functions are likely to be called by other stuff (even if only in the future and not today). However if those operations/code sections are only ever going to be done within that particular code block and nowhere else, splitting them out into separate functions may not be such a great idea in practice.

    Why? Because lots of IDEs let you fold/hide code sections. So folding those sections lets you (or some unfortunate inheritor of the code) easily see a top level view. Expanding sections of interest lets you quickly see the code in detail for the parts you're interested in.

    Whereas if you have it split into different functions it's slower and harder to do a similar thing. The unfortunate inheritor may have to drill down to each and every function to figure out stuff.

    As for advice for those starting out.
    1) Make backups
    2) Learn to use source control. And also use source control for your important documents too. Source control works on documents, not only code. Some people even use git on their /etc but I don't do that...

    • (Score: 3, Interesting) by Beryllium Sphere (r) on Monday June 10, @03:54AM

      by Beryllium Sphere (r) (5062) on Monday June 10, @03:54AM (#1359978)

      Source control helps a maintainer figure out why something got the way it is. One graybeard I know back in his youth added a comment with every bug fix that included the bug number. These days git blame will do the job, but the commit messages must be clear and informative.

      Git will repay you for going beyond the first level of understanding, https://xkcd.com/1597/. [xkcd.com] Give yourself a sandbox repo to experiment with, and ask ChatGPT when you get stuck. There is such a ton of git information in the training data that this is one of the areas where you (usually) get helpful information from an LLM.

    • (Score: 5, Insightful) by turgid on Monday June 10, @07:16AM (10 children)

      by turgid (4318) Subscriber Badge on Monday June 10, @07:16AM (#1359991) Journal

      However if those operations/code sections are only ever going to be done within that particular code block and nowhere else, splitting them out into separate functions may not be such a great idea in practice.

      I disagree for all the reasons in Clean Code by Robert C. Martin, Refactoring by Martin Fowler and Test-Driven Development by Kent Beck.Every time I leave blocks of code like that I come to regret it.

      Essentially you are writing legacy code, code that hasn't got unit tests. You are leaving technical debt. You should be putting the code into its own function or method with a descriptive name which can be isolated, tested and potentially reused with minimal effort. Let the compiler worry about optimisation (e.g. inlining the function or method).

      If you do it right, your function names should be like descriptive comments.

      • (Score: 3, Insightful) by PiMuNu on Monday June 10, @08:03AM (1 child)

        by PiMuNu (3823) on Monday June 10, @08:03AM (#1359993)

        I completely support turgid, and amplify it; long functions are a great evil that must be exorcised with utmost vehemence!

      • (Score: 2, Funny) by shrewdsheep on Monday June 10, @08:37AM (1 child)

        by shrewdsheep (5215) on Monday June 10, @08:37AM (#1359997)

        I am most happy when I can split my algorithm into one-line functions (two lines are also o.k.), one line of comment on top. Usually this makes the code crystal clear. Of course this requires some higher-level concepts like apply/comprehension. Lately, most languages can do this (perl/python/R/C++).

        • (Score: 5, Funny) by Rosco P. Coltrane on Monday June 10, @08:44AM

          by Rosco P. Coltrane (4757) on Monday June 10, @08:44AM (#1359999)

          I am most happy when I can split my algorithm into one-line functions (two lines are also o.k.), one line of comment on top.

          Good thing you tolerate 2-line functions, because you'll need the second line to call another function if your code is 3 lines or more.

      • (Score: 0, Troll) by Anonymous Coward on Monday June 10, @09:57AM (3 children)

        by Anonymous Coward on Monday June 10, @09:57AM (#1360006)

        If it's code that is going to be reused elsewhere etc, then it's not what I'm talking about. I already mentioned that.

        Imagine if you had to read and understand code where for every line there's a nice "descriptive name" and to figure out the definition you need to click on it and go to another page - which also is the same thing - yet more few lines of "descriptive names".

        That's no problem when everything works fine. But when stuff doesn't work as intended, is it really easier for some unfortunate inheritor to figure out what to change?

        All those dozens of descriptive names aren't the actual code that does the stuff (or doesn't do the stuff correctly)...

        Analogy: Is it really easier to understand a recipe for a dish where instead of seeing the whole thing in one page, everything is split into dozens of pages. First page might have 3 lines, each of those lines going to pages with 3-5 lines each, and so on.

        Only at leaf pages do you actually see the "action stuff" like "crack eggs".

        1) MakeSauce
        2) MakePasta
        3) MakePastaDish

        MakeSauce:
          CookSausagesAndBeef
          MakeTomatoBase
          AddTomatoBase
          SimmerSauce

        CookSausagesAndBeef:
            CookSausage
            CookBeef
            DrainFat.

        etc

        Enjoy your Clean Code/Recipe without all that dirty pesky code/cooking steps getting in the way. I'm sure you have a better understanding of what is ACTUALLY going on...

        And this way you can more quickly notice that for some reason the onions are done around the CookBeef step. Right?

        • (Score: 3, Funny) by turgid on Monday June 10, @11:49AM

          by turgid (4318) Subscriber Badge on Monday June 10, @11:49AM (#1360016) Journal

          Enjoy your intensive debugging sessions.

        • (Score: 4, Interesting) by PiMuNu on Monday June 10, @02:01PM (1 child)

          by PiMuNu (3823) on Monday June 10, @02:01PM (#1360031)

          > And this way you can more quickly notice that for some reason the onions are done around the CookBeef step. Right?

          One advantage of using functions is that the "CookBeef" step never has any onions in the function call, because we made a CookBeef function that takes oven and beef as function variables. So it is impossible to make the error you describe.

          Another way to look at it; when I debug, I do a bisect search to find the operation that is not working i.e. I find input X1 is as desired while output X50 is not as desired. I go to input/output X25 and check - is it as desired? If yes, go to input/output X37, else goto input/out X12, etc. This works well with code that is nested and with clearly defined "input/output" conditions for each line of code, with clearly defined scope for the execution.

          • (Score: 0) by Anonymous Coward on Tuesday June 11, @12:39AM

            by Anonymous Coward on Tuesday June 11, @12:39AM (#1360100)

            One advantage of using functions is that the "CookBeef" step never has any onions in the function call, because we made a CookBeef function that takes oven and beef as function variables. So it is impossible to make the error you describe.

            Ah, I see in the real world, when you're debugging someone else's code a CookBeef function will NEVER ever do any onions, because it's impossible.

            Good for you!

      • (Score: 2, Interesting) by pTamok on Monday June 10, @02:20PM (1 child)

        by pTamok (3042) on Monday June 10, @02:20PM (#1360034)

        It depends what you are coding for, and how sophisticated the compiler is.

        If/when you are coding for utmost performance, function calls are very, very expensive. If you can't rely on the compiler to inline a function, or do it via a compiler directive, then you are forced to duplicate code at times. I've done it. I prefer to use jump-tables.

        Of course, you flag it, and link every instance of duplicated code in the comments, so if a change is made to one block, the person doing the changes knows to do it elsewhere. It's a nasty, nasty hack, but sometimes (very rarely now) necessary.

        It illustrates just how you learn that 'rules are for the observance of fools and the guidance of wise men'. You need to deeply grok why a rule exists in order to be able to break it for good reasons, very occasionally. A lot of people think they understand enough, and in fact don't. Being humble about your level of knowledge is a good start.

        So yes: "Split your code into functions." is a good rule, and if you think you've found a counter-example, you probably haven't. There are some, but they are rare.

    • (Score: 3, Insightful) by Snotnose on Monday June 10, @01:05PM

      by Snotnose (1623) on Monday June 10, @01:05PM (#1360022)

      One thing about dividing code to functions. It 100% makes sense if those functions are likely to be called by other stuff (even if only in the future and not today). However if those operations/code sections are only ever going to be done within that particular code block and nowhere else, splitting them out into separate functions may not be such a great idea in practice.

      I agree with most of your comment but disagree with this one. Java and Kotlin let you create inner classes. C has a method (static? it's been a while) such that functions aren't visible outside of the file.

      I was lucky in that for my first job, if you wrote something it was yours. Didn't matter what your job is now, if you wrote code for foo, if foo had a bug or needed a new feature you were responsible for it. Nothing quite so eye opening as to revisit something you haven't looked at in 3 years and figuring out why you did THAT.

      --
      for (glee in 1..34) println("Guilty!")
    • (Score: 3, Interesting) by stormreaver on Monday June 10, @01:13PM

      by stormreaver (5101) on Monday June 10, @01:13PM (#1360024)

      However if those operations/code sections are only ever going to be done within that particular code block and nowhere else....

      That is a very common mistake I have had to fix in both my own code and others' code. The assumption is always that the code will never be needed anywhere else, which always seems perfectly logical at the time. The reality is more often than not that some unanticipated need arises that requires the "one-time-only" code to be duplicated. I've seen that assumption cascade to the point where the "one-time-only" code appears in multiple disparate places, often with typos in some of the copies.

    • (Score: 2) by DannyB on Monday June 10, @02:50PM (2 children)

      by DannyB (5839) Subscriber Badge on Monday June 10, @02:50PM (#1360040) Journal

      Source control pays back in spades years down the road. A tremendously valuable tool for researching how the current crisis came to be. Or how some clever trick came to be. Or why certain decisions were made to improve upon some earlier "obvious" approach. Etc.

      --
      Since nobody defrags SSDs anymore, they are more (or less?) prone to failure of their seek mechanisms.
      • (Score: 1, Funny) by Anonymous Coward on Monday June 10, @10:17PM (1 child)

        by Anonymous Coward on Monday June 10, @10:17PM (#1360086)

        Source control is when you

        1. look at code and say "WTF is this shit? Who wrote it!?"
        2. git blame ...
        3. find out it was you

        • (Score: 4, Touché) by DannyB on Tuesday June 11, @02:50PM

          by DannyB (5839) Subscriber Badge on Tuesday June 11, @02:50PM (#1360178) Journal

          It is important for source control to have useful comments intended to inform people in the future. One thing that should be included in source control comments is what you were drinking / smoking at the time of the commit.

          --
          Since nobody defrags SSDs anymore, they are more (or less?) prone to failure of their seek mechanisms.
    • (Score: 3, Interesting) by JoeMerchant on Monday June 10, @09:12PM

      by JoeMerchant (3937) on Monday June 10, @09:12PM (#1360080)

      Production level logging is very valuable, I frequently debug my code by adding debug log statements, which don't appear in production logs, but do serve to document the intent of the program flow, and can be switched back on whenever a problem surfaces in the previously challenging code.

      --
      🌻🌻 [google.com]
  • (Score: 5, Interesting) by Fluffeh on Monday June 10, @09:59AM

    by Fluffeh (954) Subscriber Badge on Monday June 10, @09:59AM (#1360007) Journal

    I write a half decent amount of code for my job, and that is then potentially shared with colleagues to maintain or use. That code is written to be easy to read. Easy to change.

    I am also currently working on a project for myself that is an android game. That code is written to be efficient and easy-to-read as a second priority as I am the one planning to be maintaining it, and no-one else. If it becomes successful, I'll work with a better coder to *really* make it efficient, especially the graphics engine, but I'll be involved in that process.

    So, when writing code, I guess understand your target audience, and cater to that.

    Also. You can't have enough error checking to cater for all manner of "Huh, didn't expect that to happen.... glad it didn't crash things....". Ever.

    Guess this is as good an opportunity to soylent-vertise my project for any potential android RPG gamers out there: https://blog.tornrealms.com/ [tornrealms.com]. It's likely about three to six months off an open beta.

  • (Score: 2) by bzipitidoo on Monday June 10, @06:03PM (1 child)

    by bzipitidoo (4388) on Monday June 10, @06:03PM (#1360058) Journal

    I've seen bad programmers churn out useless code to try to obscure that they don't know what the heck to do. They'll make useless functions and classes, needlessly copy data from one kind of structure to another kind, losing some in the process, get hung up on trivial stuff, blather on about OOP, Agile methodology, Unit Testing, or whatever the buzzwords of the month are, and it's all smoke and mirrors to hide their incompetence.

    • (Score: 3, Funny) by JoeMerchant on Monday June 10, @09:14PM

      by JoeMerchant (3937) on Monday June 10, @09:14PM (#1360081)

      Yes, but it proves that they at least paid some attention in class, even if they didn't understand the object of the lessons.

      --
      🌻🌻 [google.com]
  • (Score: 4, Insightful) by gnuman on Monday June 10, @10:14PM

    by gnuman (5013) on Monday June 10, @10:14PM (#1360085)

    For beginners, just write code. Then do some other project and come back to the code you wrote 6 months earlier. Then you'll learn what mistakes you've made rather quickly.

    DO NOT use AI crap and even avoid IDEs with auto-completion, or you'll never learn anything.

    Also, use Git or some revision control system, ALWAYS. Every project should have a history. I didn't say Github but git. Different tools.

  • (Score: 2) by jman on Tuesday June 11, @01:06PM (1 child)

    by jman (6085) Subscriber Badge on Tuesday June 11, @01:06PM (#1360161) Homepage
    I still write scripts for my own use in bash, but have been promising myself I'd convert to Pythone one of these days.

    The daily driver is a Mac, so I spend a lot of time in iTerm2. I also compile openssl, bash, python, apache, mariadb, etc. No homebrew!

    Let's say the script is named 'testme'. It will source at least three other files:
    • testme.vars -> any script-specific variables. As all bash varibles are global, they get unset at the end of the script run.
    • testme.funcs -> any script-specific functions. At the top of that file, a general-purpose function library is also sourced.
    • testme.args -> handles any command-line parameters passed to the main script.

    Of course there's also a script - 'eb', for 'edit batch' (I started coding in the mainframe days and picked up DAS back in the 80's), which loads all of these into my text editor (either vs code or vim, depending on how I'm accessing whatever machine I'm working on) when I want to refactor, add functionality or make other changes, with the ability to also load other 'one-off' files that may be needed which do not use the same base name as the main script.

    This may sound llke overkill, but it keeps the main script from being huge. (The main general-purpose function library is currently some 3,500 lines).

    A similar method is used for Python scripts, but I have a "defs" file with the same base name as the script which holds the script-specific class. I also have several function classes - general, date & time, db, pandas, etc. - which can be easily loaded at the top of any script.

    This approach has probably been used elsewhere, but I just made it up as I was going along when starting to explore bash years ago.

    • (Score: 2) by jman on Tuesday June 11, @01:14PM

      by jman (6085) Subscriber Badge on Tuesday June 11, @01:14PM (#1360164) Homepage
      A small correction. Bash does have local variables, but they have to be defined as such inside a function.

      At least that's better than, say, the old C64 days, when one got only two-digit vars, everything was global, and we still had goto.
  • (Score: 3, Insightful) by DannyB on Tuesday June 11, @04:03PM

    by DannyB (5839) Subscriber Badge on Tuesday June 11, @04:03PM (#1360188) Journal

    When writing code, think of it primarily as a human-to-human communication activity. Of course, it has to compile and run. But the compiler is not your primary audience. Your audience, who you are writing the code for, is the next guy who will read it after you. Will that person understand what you were thinking without themself also going insane?

    Fact: In today's world, MOST OF THE TIME you are NOT worried about bytes and cpu cycles. You should ALWAYS be optimizing for DOLLARS not bytes and cpu cycles.

    --
    Since nobody defrags SSDs anymore, they are more (or less?) prone to failure of their seek mechanisms.
(1)