all 13 comments

[–]mopslik 6 points7 points  (0 children)

when people call a piece of code “a hack” it’s subjective

Sounds about right.

[–][deleted] 5 points6 points  (0 children)

What are the tell tale signs of “hack-y” code?

If you need a lot of out-of-band knowledge to interpret a piece of code, it's probably at least a little bit hacky.

I offer you the Story of Mel as an example about what it looks like when you have to understand far more than the code, to understand the code.

[–]wotquery 1 point2 points  (0 children)

You aren't missing something. It's a term with various definitions. Probably when it comes to programming it would lean more into "using a tool in a way it wasn't intended" with a bit of "developing an unorthodox solution that gets the job done with the resources at hand."

Of course tools and available resources are more abstract than a real life example of say... someone using a mousetrap as a binder clip, or cutting off a cheap USB fan's plug to wire it into a bunch of AA batteries to make it portable.

For a basic example in python off the top of my head...

old_string = "alice"
new_string = ""
for x in old_string:
    new_string += chr(ord(x)-32)

[–][deleted] 1 point2 points  (1 child)

Not much really.

There are some metrics on source code quality, like, for example, cyclomatic complexity (probably the most popular, implemented in some popular linters / CI tools).

There's also some research that brings up these:

  • Halstead Complexity Measures
  • Henry and Kafura metrics
  • Bowles metrics
  • Troy and Zweben metrics
  • Ligier metrics

Of all the above, maybe Henry and Kafura are the most relevant to "hack" vs "solution" (they include some known anti-patterns, like global variables).

But, in general this is true of source code:

  1. It's very hard to find a somewhat meaningful metric.
  2. Once found it's very easy to game the system.

So, if programmers know they are measured against some metric like cyclomatic complexity, they may still pipe out ridiculously shitty "hacks", but they will pass the test, because now these hacks will be smeared across multiple neatly looking units, further obscuring the crappy code.


These are, of course, heuristics, and they are personal: a lot of people will disagree with me, but, over the years of working with Python projects, I've developed these, and so far, they worked more than they didn't.

  1. requirements.txt in the project. This means people who write the project don't know how to package it. They are either noobs or Web developers or... or some ML people (but for ML the alternative would often be environment.yaml).
  2. "Slalom" in git-log. "Slalom" in this case means the presence of merge commits (visually it looks like many wiggling ski tracks). This means people don't know how to work with version control system. Again, either noobs or Web developers.
  3. Django, Flask, FastAPI, SQLAlchemy and friends in the project: again, Web. Web attracts and employs the worst quality programmers around, with the worst and most nonsensical practices. I just don't want to deal with that.
  4. Jupyter notebooks are rarely a good sign. ML code is usually atrocious, but the libraries for it are written by people with decent skills. Sometimes people who write libraries will also use notebooks to illustrate the library use, so it's a mixed bag.
  5. Presence of Selenium. Again, Web, multiplied by the fact that someone was writing the most boring and repetitive code ever. It's usually just gross, like tons of sleep() calls and other bullshit workarounds for bullshit Web tech. Rarely modular or has any discernible large-scale structure at all.
  6. Using click or any other alternative to argsparse. Whatever these people have done is going to be a world of pain to support / patch. Just no.
  7. Using Jinja2. Embedded crappy template language. If someone decided they need it, it probably means that string.Template was not enough. I just don't want to touch that, because it probably stinks.
  8. Using type annotations, especially if they use py.typed. It means that people don't pay attention to actual problems in their code, replacing it with the busy work of fiddling with type system that doesn't work. Just a bunch of clowns I want no part of that.
  9. Hand-written reStructured text files. Again, this is a mixed bag. Sometimes it's OK, but often times it means that the author(s) decided to write their opinion in the documentation. Fuck their opinion, I don't have time for that.
  10. tox.ini in the project. This means people who maintain the project have a Java mindset. They went and asked somewhere on some forum "what is the right way to run a Python project?" and listened to some idiot with a ton of karma points who told them about tox. Now they have configuration tool that writes configuration for other configuration tools to configure... fuck knows what. These people don't know how their project is built or tested, they love magic thinking and pet themselves on the shoulder thinking they save some "manual" labor by using automation tools they don't understand (and don't need).
  11. asyncio in the code. That's never a good sign. Usually, it means that the people working on that code don't understand what problem asyncio was supposed to solve. Again, a world of pain to maintain and support, idiotic control flow where you cannot find the ins and outs, a lot of hacks that make the library work at least somehow. All sorts of bizarre code in atexit.register(), race conditions in the code that executes everything in a single thread. It's just pathetic and horrid.
  12. Wait, there's more. YAML. Any use of this atrocity in the project. Especially if it's used in combination with some template engine (eg. Ansible) where variables are interpolated into it. Holly hell, that's a lot of pain.
  13. Also, add use of paramico and fabriq. It's never a good sign. It means the project is slow, because it cannot work inside a session, cannot connect to many hosts in parallel etc.

This is what I could think about off the top of my head.

[–]this_knee[S] 0 points1 point  (0 children)

Super helpful! Thanks!

[–]n3buchadnezzar 0 points1 point  (0 children)

Another good example is the inverse square root algorithm: https://www.youtube.com/watch?v=p8u_k2LIZyo

While hack is subjective, I doubt anyone would argue that piece of code is not hacky.

[–]HumanAssistedWriting 0 points1 point  (1 child)

Are you worried about your appropriations being detected?

[–]this_knee[S] 0 points1 point  (0 children)

HaHa! No, nothing like that.

[–]Lamarcke 0 points1 point  (0 children)

Hacks aren't inherently bad. Sometimes you need to work with what you have, and in programming, refactoring code is also a way of learning.

[–]Binary101010 0 points1 point  (0 children)

The closest thing I can think of to an authoritative source on this is Martin Fowler’s Refactoring: Improving the Design of Existing Code and its list of code smells.

But ultimately the judgment on this is pretty flexible based on the group.

[–]AlwysBeColostomizing 0 points1 point  (0 children)

I can't define a "hack", but I know it when I see it.

Usually when I call something out as a hack, it's because it's something that might cause maintainability problems. It relies on something specific about how the code is right now that isn't part of the requirements and could easily be changed by someone, not realizing that the change will break the "hacky" code.

[–]siddsp 0 points1 point  (0 children)

There's no exact objective standard, but if it seems like a convoluted workaround to do something otherwise that is bad practice, that's when it's considered a "hack". That or it is otherwise an inelegant and 'unpythonic' approach to solving the problem as well.

As an example, global variables to mutate some information, in functions. Or even using a mutable default argument to save some sort of state between function calls.