6
$\begingroup$

First of all I'm sorry if the wording of my question is off so let me be more specific with what I mean;

At my University we have some platforms we can code on and hand in assignments. They usually let us have as many tries as we want to (Not like they could stop us from compilling outside of the platform) but not once any lecturer or educator has discouraged us from compilling and testing our code as much as we'd like. This is also the case for the exam enviroments (Just with the restriction of a time limit)

I'm asking this out of curiosity, because I've developed a pretty bad habit of programming by permutation/shotgun debugging and in my first few months of Programming and even after 1.5+ years I still fall back to it sometimes. Part of the issue was probably, that I was never forced, or at least encouraged to spend as much time as possible to think about my code until I try something new again.

Is there a bigger reason educators generally see it as pointless to try to enforce a compile limit, or am I reading too much into the whole thing?

$\endgroup$
3
  • 7
    $\begingroup$ "not once any lecturer or educator has discouraged us from ... testing our code as much as we'd like". Normally the problem is the opposite: getting people to test their code sufficiently. $\endgroup$ Commented Nov 30, 2018 at 9:36
  • $\begingroup$ When computing cycles were expensive, people were discouraged from compiling frequently. You had to deliver your card deck to the operators, who would schedule your run and give you back a printout, sometimes as quickly as 24 hour turnaround.. With computer cycles being cheap, the most efficient way to learn and produce is too use the cycles. $\endgroup$
    – pojo-guy
    Commented Dec 15, 2018 at 10:06
  • $\begingroup$ An entire paradigm called CI/CD (Continuous Integration / Continuous Development) is doing exactly the opposite of what you're proposing. Trust me... if you ever join a company that has a completely counter-productive development pipeline, you'll know. The immediate symptom is you are unable to know whether your fix worked for an extended period of time. A change is pushed through so many layers of processing that by the time you got your results, you would have no idea what you did, nevermind what the error was about. $\endgroup$
    – Nelson
    Commented May 14, 2022 at 17:35

6 Answers 6

13
$\begingroup$

Because it's a meaningless obstacle

Putting an upper limit on compilations is like telling a car manufacturer that they must build a new supercar, but are only allowed to test drive it a few times.

This means that you're pushing your developers/mechanics to theorize about whether something would or wouldn't work, instead of actually finding out.

Theories are really just educated guesses; so do you genuinely think that guessing more often will achieve a better result than testing more often?


Because that's not the purpose of education

Especially in a hands-on field such as software development, the goal to learning programming is to keep trying until you stop failing. That inherently means that failing (and thus needed another compilation in the future) is an inevitable step in the process.

You seem to think that compiling often is indicative of a "bad" programmer. It isn't, but let's explore that assumption.
What exactly is your perceived problem with compiling more often? If a "bad" programmer is able to deliver the same end result in the same amount of time as a "good" programmer, does it really matter whether they compiled often or not?

Clients/managers tend to not care about how a programmer achieves their goal, they only care that they achieve it within the set parameters. If anything, I'd be more willing to hire the programmer who continually fact-checks himself (by compiling), compared to the programmer who assumes they know what they're doing (rarely compiling) and thus will get stuck needing to retrace their steps afterwards.

What you're suggesting is the equivalent of not permitting students to redo their calculations on a math exam. You're trying to teach them the exact opposite behavior of what you should be teaching them.


Because that's not how it works in a professional environment

Once you get to the stage of being a self-sufficient developer, there is still much to learn. One thing that junior developers often do wrong is down the problem into sufficiently small and simple parts.

In short, it is better to build something with 50 simple components than it is to build it with 10 moderately complex components.

Cleverness can be damning as a developer. When you're developing something, you understand the ins and outs, and you might find a very clever trick/workaround that may seem counterintuitive at first but actually solves your problem nicely. This can manifest itself in different ways: overly terse syntax, lack of accurate naming, an overly complex algorithm, lack of self-documentation, requiring specialized knowledge of a particular tool/library, ...

However, your cleverness can be your undoing when you (or someone else) needs to reevaluate this code in the future. If there's a bug, it will be hell to find out where the bug is located.
But even when there is no bug, e.g. if the requirements change, you will need to be able to pull the existing logic apart to introduce your changes.

Putting a hard limit on # of compilations wrongly incentivizes developers to only compile (and thus test) large changesets. When anything goes wrong, it's very hard to pinpoint where exactly it went wrong.

However, if you compile (and thus test) small changesets, it's very easy to see where it went wrong, as there is only a limited amount of changes that have occurred between the last (working) version and the current (failing) version.

This is the core argument for using unit testing and continuous integration. Developers are urged to take the smallest possible incremental steps, so that their code can be tested every step of the way, thus making it easier to find the source of a bug/error.

Since there is no purpose to retesting without recompiling; if you want to test often, you must therefore also compile often.


I've developed a pretty bad habit of programming by permutation/shotgun debugging and in my first few months of Programming and even after 1.5+ years I still fall back to it sometimes.

When all else fails, shotgun programming is the most reliable method of figuring things out.

That is not to say that shotgun programming should be your primary development approach, as it can lead to time wastage. But when all your clever logging and theorizing fails to solve the problem at hand, shotgun debugging pretty much guarantees that you can take (admittedly slow) steps towards finding the solution.

As much as I am pro-shotgun (in certain cases), I do concede that wanton shotgun debugging can be used as a way to brute force a solution and avoiding having to understand the problem, which is counterproductive in an educational context. But this is part of a bigger issue that is not easily preventable.

For example, some students may rely on StackOverflow as a snippet repository and avoid having to understand the snippet or why it works.
To be clear: as a software developer I use it as a snippet repository as well, but I use it as a shortcut or not having to reinvent the water, not as a way to avoid having to learn the core skills required.

The issues of students writing code that works but they do not understand why (regardless of whether it's copy/pasting or brute forcing a solution) is not something you can address with a simple test. This is where oral exams are most useful, because you can very quickly gauge the difference between a student who found the right snippet, and a student who understands the core problem and how to approach solving it.

$\endgroup$
0
10
$\begingroup$

I do it the other way round: I encourage my students to compile and test very often!

Of course, just changing random lines of code until the result seems to work is not a good idea and this should be avoided. I try to encourage thinking about the code by writing the essential parts in pseudocode first and writing the documentation of functions prior to implementing them.

What I want the students to do (especially in the beginning) is that they mentally decompose their program and test every testable step separately and check whether they are still on the right track. With more experience the tested chunks of code are growing, but in the beginning I sometimes compile nearly after each line of code I'm demonstrating to show how a program develops.

$\endgroup$
4
  • $\begingroup$ Do you think there is a difference when it comes to low vs high-level languages? In our Systems Programming course (where we use C) we've been encouraged to always compile our code every few lines to weed out syntax errors which become tedious to debug once the program is large enough. I do think there is a difference between trying to find logic and syntax/semantics errors when it comes to compiling to check on the code. $\endgroup$ Commented Dec 1, 2018 at 8:35
  • $\begingroup$ In most IDEs syntax errors are highlighted even without any compilation. But it is useful to check whether a loop works as desired. And this is independent of the language. $\endgroup$
    – OBu
    Commented Dec 1, 2018 at 13:28
  • $\begingroup$ Of course, just changing random lines of code until the result seems to work is not a good idea and this should be avoided. I find that the "when all else fails" argument works here. When you're out of ideas, manipulating the environment in seemingly unrelated ways can reveal information that is crucial to finding or reproducing a bug. The issue is more that developers should have other skills next to shotgun debugging, but that doesn't mean the same as suggesting that shotgun debugging is always a bad thing. $\endgroup$
    – Flater
    Commented Dec 13, 2018 at 11:58
  • $\begingroup$ @Flater in this case you are not shotgun debugging but using a special "last resort" method ;-). $\endgroup$
    – OBu
    Commented Dec 13, 2018 at 13:44
7
$\begingroup$

Back in my day (which wasn't that long ago), many of the tests for my programming courses involved writing code on a piece of paper, with a pencil. In this environment, I couldn't rely on the compiler at all. Your teachers might not want to do this because it involves a lot more hands-on grading, which might not make sense for your class size.

I can also think of a few other reasons to avoid limiting code compilations:

  1. It doesn't match real life. Like you've experienced, even "real" developers rely on the compiler to tell them where something is wrong.

  2. It doesn't match other subjects. Have you ever taken a math test where you were only allowed to use your eraser 3 times? Or written an essay where you could only use the backspace key 10 times?

  3. It's not enforceable. Even if I wanted to limit the number of times you compile your code, there's no way for me to stop you from writing the code in your favorite IDE and then copying it into my system. (Well, I could force you to use a locked-down system in a Faraday cage, but why bother?)

  4. There are bigger fish to fry. I'd be more worried about students copying each other's work, or getting a full code solution from Stack Overflow.

Shotgun debugging is not a shortcut to an answer. In fact, shotgun debugging generally takes longer than walking through the logic and figuring out what to do. My guess is that students who resort to shotgun debugging in tests and assignments generally perform worse than students who think through their code, without any teacher restrictions or interventions.

Your meta-point of teaching students to think about their code is a good one though. I think the process of breaking problems down into smaller steps is the most important skill a person can learn, and it's much more important than memorizing syntax. The only way to learn this skill is by practicing it over and over again. Every time you faced an assignment where you thought "how do I even start this?" was your teacher trying to teach you this lesson.

Part of the issue was probably, that I was never forced, or at least encouraged to spend as much time as possible to think about my code until I try something new again.

I don't think it's fair to blame your teacher or your education on you relying on shotgun debugging. The truth is that we all rely on it from time to time. And if you already personally recognize the value in thinking through your code, but still fail to do it, then there isn't much a teacher can do to help with that.

$\endgroup$
3
  • $\begingroup$ Hi! I really appreciate you taking your time to answer my question. I did not mean to blame my educators for my bad habits. I'm interested in becoming an educator myself so I put some thought in which didactive approaches of my educators has helped me to become a better programmer and which did not. It is probably fair to say that this is entirely on me. $\endgroup$ Commented Dec 1, 2018 at 8:32
  • $\begingroup$ In fact, shotgun debugging generally takes longer than walking through the logic and figuring out what to do. True, but there's a different between fixing the problem and learning the underlying cause of the problem. As much as I am pro-shotgun (cfr my answer), I do concede that wanton shotgun debugging can be used as a way to brute force a solution and avoiding having to understand the problem. $\endgroup$
    – Flater
    Commented Dec 13, 2018 at 12:01
  • $\begingroup$ I remember writing and testing code, then writing it out by hand. I got the highest grade in the class. This foolish teacher taught me well (if by accident). I now always test my code. $\endgroup$ Commented Dec 22, 2018 at 12:59
7
$\begingroup$

My philosophy is "use professional tools" and creating an experience that is like being in real programming shop.

The compiler can help you get rid of silly errors very fast without wasting time on unnecessary puzzling. If professional devs avail themselves of this, I think my students should have it.

Anyway, most of the compilers we are using are OSS and can be installed on any PC. Such a restriction makes little sense to me. How, in the face of this fact, do you enforce it?

$\endgroup$
4
$\begingroup$

While limiting use of compiling and testing, will stop same bad behaviours, it will also stop the best behaviours.

Test driven development is one of the best ways to write software, and it involves a lot of compiling and a lot of testing. However it is not about guessing (the shot gun approach).

Test driven development

Test driven development is about doing one thing at a time, writing the simplest test that will fail, writing the simplest code to make the test pass (the simplest thing that can work), and repeating.

With one thing at a time, the steps are tiny. No more than 3 lines of code, usually less than one. Never more than 5 minutes away from the previous test.

You write the tests first: That way you can test the test, by running it and seeing it fail. It will not be clear, what you are trying to do, until you can write a test for it.

To make the test pass, do the simplest thing that can work, and no more. Don't think ahead.

https://en.wikipedia.org/wiki/Test-driven_development


notes:

It is also a good idea to also be using a revision control system (such as mercurial, hg).

Ones you have practised for a bit, start using an automated unit-test tool.

One you have done all that for a bit, see https://en.wikipedia.org/wiki/Transformation_Priority_Premise

$\endgroup$
2
  • $\begingroup$ I am an advocate of the "mean teacher method" of writing functions. First, decide what the function is to do. Then stub it with an appropriate pro forma return value. Second: generate test cases for that check routine behavior as well as corner cases. Third: implement the function and hopefully it passes all tests. $\endgroup$ Commented Dec 7, 2018 at 23:19
  • $\begingroup$ @ncmathsadist Why mean? I would do same, but I would expect a test for the stub routine, before you write it. I would then expect just enough test, then just enough solution, etc, etc. Don't write any solution, except to pass a test, don't write any test, except to get tests to fail. If tests are already failing, then stop writing them, except to fix the test (compile error etc). $\endgroup$ Commented Dec 8, 2018 at 11:19
2
$\begingroup$

Here is something I tell my students. Compiling is like voting in Chicago: do it early and often. I tell them it is a bad idea to write a whole bunch of code without compiling because they then wind up having to sift through a ton of error messages. If you compile fairly often, you will not have a big search field for finding errors.

One of my principles is the "Little Red Riding Hood Principle" which says that you want to stay on or near the path (a compiling running program) so you don't get eaten by the wolf. This wolf takes the form of a fusillade of error messages; you get "eaten" if you become discouraged enough to pitch your code and start afresh.

$\endgroup$
2
  • 1
    $\begingroup$ "Compiling is like voting in Chicago: do it early and often" made me laugh. Nice. $\endgroup$
    – Ben I.
    Commented Mar 24, 2021 at 17:24
  • 1
    $\begingroup$ Christ, seeing this thread again made me nostalgic. $\endgroup$ Commented Mar 25, 2021 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.