Cheating in Programming
twitter.com
twitter.com
If you were to have infinite time, you would be idiotic to _not_ spend a bunch of time fully internalizing the entire stack; or at least, trying to comprehend as much as possible given your non-infinite memory. Hell, whilst you're at it, throw in a rounded education in the humanities and sprinkle a ton of socialization in there too.
But you don't have infinite time. So instead, you try to find the balance that allows you to perform the task you wish to perform.
And at that point it's a completely personal decision. Perhaps you spend more on soft skills because you have managerial aspirations. Perhaps you drill down into bit banging simply because it's of intrinsic interest to you.
There probably is some basic level that's useful for every programmer to have, sure, but what that even means is dependent on sector. I don't know a thing* about Windows because it's both highly uninteresting to me, but also because it'd be a waste of time for me to bother with it. (Perhaps the two are linked!)
* okay, I know a decent amount compared to the man on the Clapham omnibus, but not compared to a Windows developer
I am reminded of an old post (from HN I think) in similar vein that stuck on with me https://stackoverflow.com/questions/153234/how-deep-are-your...
I do take time to understand the code I am using, but for most part spend finding the code (and libraries) I want to use even in the simplest cases. I've developed a habit to give credit in my code ... in fact I have an expansion ';c' on my mac for giving credit! :-)
I see a lot of very experienced programmers spend time writing and debugging even simple lines of code which are perhaps completely obvious to them. I think it is just that way coding is. It is perhaps very difficult to get it "First Time Right".
I guess its a balance between getting things to work vs. self-gratification.
I tried espanso a bit and it seemed to work pretty well and is customizable.
Avoiding writing original code is primarily an excuse to limit personal liability through diverting blame. Organizations that care about product quality would blame that developer/team for poor product quality regardless of who wrote the code.
Those open source libraries might be tested to exhaustion, but not in your application. Your application still needs to be tested either way. The presence of excess code does not eliminate defects but rather moves them to locations less obvious which means they are harder to find by the end user and just as costly to fix. That is the very nature of debt.
Regardless of who owns the code you or your team own the product.
But the whole economic point of Divison of Labour[1] is that the effort is dispersed, no?
Knowing "enough" means that, for example, I don't
- use a page of Java to load two tables,
- put their keys into assiciative arrays
- loop through the arrays and build a list of unmatched keys
. . .when a single SQL statement can give me the Venn diagram output of the two sets. (Really saw that in some code.)
In my spare time I find joy in writing things from scratch but I see it more as challenging myself rather than "not cheating"
If I write a compiler purely to challenge myself, I'm much more confident in using an existing one in the future. However with a cheating/not cheating mindset I'd be reinventing the wheel every time.
So yeah, I'd probably go to a doctor who's really good at removing appendixes over the guy with comprehensive medical knowledge.
An eye specialist who is absolutely clueless about heart or kidney function would be unusual, and not particularly useful. Not only do most drugs have multi-system side-effects, but many conditions affect multiple systems.
So Dr Appendix Removal will almost certainly do all kinds of surgery.
Consultants tend to have a more limited focus, but you don't get to be a consultant without doing a lot of other medicine first. Usually they either work as supervisors/managers, or they're called on to consult/advise and maybe operate on more challenging cases.
So let's rephrase. Do you trust an AI controlled robot specialized in appendix removal (with a very good track record) but zero knowledge of other systems or procedures?
The parent's question was if you'd trust an appendix doctor who didn't understand the associated systems.
Which is a brake mechanic who doesn't fully get fluid dynamics, but does get brakes.
The ability of a surgeon to successfully remove an appendix necessarily involves a fair amount of knowledge of the circulatory system, so the analogy is flawed. In my experience some people get by just fine only knowing how to address a problem through some particular framework. The point of abstraction in the end is to release people from the burden of considering the details.
I think that this is a better analogy: would you go to a massage therapist who knows how to release tension in your back by manipulating your tissue, but doesn't know how neurons and axons work? Perhaps greatness can be achieved by a a therapist who knows the ins and outs of every aspect of your body, but as a patient/customer I am really only interested in the skills of the therapist insofar that they manifest in the ability to relax my back and shoulders. And really, a lot of development problems are like that. People perform well at their development jobs without a firm understanding of the mechanisms and inventions that enable them to perform it in the first place. It's by design.
The real problems arise when there is something you really ought to know. For example, if I don't know how memory is allocated by the black box framework I use and memory use suddenly blows up through my interactions with it, the only thing I can fall back on is a lower level understanding. But usually this is fine, and it is someone else's lower level understanding that you fall back on. If you're working high up in a web front-end perhaps you have to consult someone who contributed to a web framework you're using. Maybe you have the wrong approach in a way that leads to instantiating too many objects. On the very low end of software development you may end up having to consult someone who laid the board out and can reason about the operation of the application in terms of the electronics involved. Maybe these two buses shouldn't be used at the same time because of a reflection problem.
You should know one abstraction layer deeper. In this case one abstraction layer would be that the therapist knows what muscles there are in a back and where they are. You can administer massages without knowing it just by memorizing patterns, but you would get a lot better and can handle more cases if you know about the muscles.
Similarly you can become productive using a framework without knowing anything about how the framework works underneath just by memorizing patterns which works, but you would get a lot more productive and can handle more cases if you had a decent understanding how the framework is implemented.
More generally, I'd say that it's a matter of what improves your ability to perform the work you want to perform weighed against the possibly diminishing returns of investing time and energy in understanding things in more and more detail. Depending on the circumstances of your work, this may favor digging into more than a couple of abstraction layers (for example, an embedded developer that knows both software, digital circuit design and electricity can be immensely useful) or it may favor unquestioningly accepting the layer of abstraction you target as the whole truth (for example if I'm working on expressing some performance insensitive business glue logic for some proprietary platform, in which case I don't even have a choice).
Would you go to a doctor who understands how to do a heart transplant, but doesn't understand the Navier-Stokes equations underlying how viscous fluids like blood behave? Would you trust your car to a person who doesn't understand friction at the level of interatomic forces? Would you seriously trust your life to an airline pilot who couldn't single-handedly design and build a plane at least as capable as the Ford Trimotor?
People have always been specialized. Always always always. Even back before "specialization of labor" was officially invented, the people who lived in the Kalahari didn't know about hunting seals and people who lived in Polynesia couldn't hunt a buffalo or a bison to save their lives. There just isn't enough time, interest, or opportunity in one life to learn everything top-to-bottom. We're slowly improving the amount of opportunity, and you can fake an interest for a while, but increasing the amount of time is still a miserably slow process.
I think a better analogy for software would be construction. Multiple people of different specializations and skill-levels working together to produce a single artifact. As a framer, you don't need to know how to lay the foundation, you just need to know how to build on top of it. Furthermore, you don't need to know the chemical process of concrete to pour the foundation, you just follow the recipe that's been proven. You don't need to know the math required to determine the integrity of a structural load in order to frame a roof, you just follow a plan. Some projects may require engineers and specialists who do have a deep understanding of such things, but only to create the blueprints.
Nod.
Dependencies are a two edges sword. It's good that you get security updates. But if you can't review all the changes, security issues can also sneak in. Like if someones npm account get hacked and the hacker sneaks in a remote shell or backdoor. Those can be hard to find if you got millions of dependencies which get tons of updates every day. So I usually lock down dependencies, and NPM becomes a fancy tool for copy/pasting.
This duplication is necessary because npm is not a curated software distribution designed to work as a cohesive system. Anyone can push software to npm. As a result, there are packages that depend on different versions of the same library and they must have their own individual copies of the dependency in order to work. This isn't the case in a Linux distribution with maintainers: there's one instance of the package that's shared by all other packages.
As a front-end web developer there are only 2 APIs to learn: DOM and web API (the html5 and browser stuff). Both of those APIs are well documented industry standards. Both change more slowly than the average developer’s career and are almost entirely backwards compatible to their first versions. In short you almost never have to relearn the standards, they always work as designed, and risks of cross-browser failures are largely years in the past.
Yet most front-end developers are scared shitless of writing to the standards directly, because that means writing original code and putting their name on it. Better to play it safe with a giant monster framework and 1000 NPM packages in order to bind some CSS to a piece of dynamic content. The commonality of invented here syndrome suggests that not spending the time to use common libraries is what’s cheating.
No, school doesn't teach this. School just teaches that trivializing an assignment by using others code is cheating, since the point of school is to learn how things work and not learn how to find, evaluate and use libraries.
You could argue that school should better teach library usage, but that is a very hard topic to teach, what would the assignments look like? Would it be a case problem? Like you get a list of current dependencies, an overview of your team members skills, the task you are supposed to solve and then you go out looking for actual libraries and get graded based on how well your choice aligns with the professors?
In school, people have to prove themselves by doing stuff without any support whatsoever, only to be punished for any and all mistakes. All grades are final: there is no opportunity to review one's mistakes, learn from them and get re-evaluated. Either get it right the first time or risk failing the course. Of course people cheat: the cost of failure is simply too high. Outside school, people use every trick in the book to lower cost and risk; somehow that's not acceptable in school.
However many startups or research-oriented technology development will require some part of your stack to be reinvented from scratch to solve whatever problem is the premise of the business. In these situations it becomes clear pretty quickly who is comfortable solving technology problems from first principles, situations that these educational exercises are aiming towards.
There is no shame in using a library or tool to solve a problem that you do not understand. A "real" software engineer knows when it makes sense to outsource the work to an existing tool or write their own.
When you have to interoperate with other programs through an open standard then it may be counterproductive to write the code yourself. I've personally seen way too many hand written CSV parsers/writers that were just plain wrong.
To avoid such moral dilemmas I try to come up with projects that solve a new problem (which also comes with its own set of challenges). And then use all the means at my disposal.
As a bonus it also keeps me motivated, since it has a shot at being a profitable business idea.
Nevertheless, I fathered two children.
Likewise, you don't need to know the exact algorithmic details of something if you're still achieving your desired outcomes.
If you're not getting the outcome you want, you need to dig deeper into the components you don't fully understand to get them to perform as expected.
Real life results are best judged on metrics one step removed from the work.
“I know people making good money trading corn who would be shocked to learn that it’s a plant.”
And the same is true of the dev who copies tons of code from stack overflow without really understanding it. When issues like thread safety of the app come up, that dev is going to be lost.
Experienced musicians choose loops and samples understanding full well the trade-offs of quantization and timbre. Experienced devs bring in libraries understanding the trade-offs. Answering the question "how well do I need to know this library before introducing it in production?" is a really, really hard problem.
In practice, I see junior devs blindly copying code that subtly won't work more than I see them writing their own DI system because of not-invented-here syndrome. But, admittedly, the latter tends to be more destructive.
The enthusiast can afford to learn the "deeper" stuff first, then move up.
The professional needs to know enough to ship a safe, stable, on time product.
* Using your platform's graphics/sound/input/etc. APIs, or wrappers like SDL, is not cheating
* Using a third-party engine is cheating
Other programmers may draw the line elsewhere and that's fine. I think for me it's a question of, using a library to achieve <hard task> is fine, but using a framework puts on me the burden of understanding and then extending someone else's half-completed program. And when that someone else made a decision that I wouldn't have made that fucks with my workflow, it also puts on me the burden of, is it okay to go in and change it or implement a low-level hackaround? Or is that cheating, and should I do everything in the framework's own terms?
Some baseline of performance is sufficient as long as you can deliver the proper experience, which is really the only thing they’re seeking in your game. If that same experience can be delivered MUCH more quickly and easier why would someone deny themselves and their users those benefits?
I understand there is nuance in this decision but it feels dangerous as a hard and fast rule. I think especially so when team size > 1-2 and common understanding becomes important.
I used to think I wanted to make games, but I really just enjoy making game systems and game engine related things.
But we can kinda see how the "quick and easy" approach with modern engines is leading to lots and lots of sloppy games with leaky seams.
I always appreciate it when a gamedev writes their own engine, and IME these tend to come out as the more polished games. Doing your own engine would also enable open sourcing it, which is something gamers can be quite grateful for 10-20 years down the road.
Of the ones that finish perhaps.
I care. Plus, I open-source my games, so I expect players to appreciate them at one level and other coders to appreciate them at another.
No, using an already existing engine is called delivering a product in a predictable timeframe. Valid reasons to not use a specific engine for a specific project are plentiful, even if all engines get ruled out, but "cheating" is nonsense.
> If you wish to make an apple pie from scratch, you must first invent the universe.
- Carl Sagan
Fast forward two years, the teacher is trying to run the project to showcase an example project her students can do. She can't run it. She remembered it being a great project, but now for some reason some parts won't work.
I get a call to come help them. I dust up the old project, edit it, and get it running in front of the whole class. "What was the issue?" She asks.
"I used a webserver, now I hardcoded all the data since it's just a demo"
"Oh, so you guys cheated?"
Long story short, I was threatened to get my grade revoked, but because I have made things right I was forgiven.
As far as school is concerned, I cheated.
Back in college there was naturally a strong emphasis on writing your own code, after all, you're supposed to be learning. In the end, we had to roll out everything on our own - rarely, if ever, did we get to use libraries or frameworks.
They were extremely strict on plagiarism too, so you were constantly afraid of your code getting flagged (for whatever reason).
All of this really created a mindset that using libraries = cheating. Same with looking up help on the web.
It took me years to get rid of that mindset, simply because it didn't feel right.
If so, you weren't writing your own code. You were just writing a description of the code in some human oriented programming language, and the compiler wrote the actual code for you.
Also, the compiler almost certainly linked in a runtime library - more code you didn't write.
But let's skip the compiler and its runtime, and even any assembler, and just write raw binary machine code.
Now you're writing your own code, right?
Well... On any modern processor, your so-called "machine code" is just a high level language that the processor compiles into its own internal operations - which don't look anything like your machine code and don't even get executed in the same order. So you're not writing the code the machine runs.
You could avoid this issue by writing code for an older processor like the 6502, where your code bits go straight into the logic circuitry as is.
In fact, that would be a darn good idea - you would learn a lot doing it!
No, no. Developers don't write (their own) code, they simply translate the (customer's) specifications.
LOL no! If I did that my customers would go out of business.
Here is a true story. When I first started programming, we were told that professional companies developed software as follows. (Of course we were a scrappy timesharing startup, so we took shortcuts, but this is what we were told the pros did.)
• A systems analyst took business requirements and created a specification.
• A programmer took the specification and used it to draw flowcharts.
• A coder took the flowcharts and converted them into code in a particular programming language, hand-written on coding forms.
• A keypunch operator took the coding forms and punched the code onto cards.
Pop quiz! Who actually wrote the code: the programmer or the coder?
After all, you didn't want to have to wait many hours or a full day to get back your card deck and printout to find what you did wrong.
When you found a keypunch operator like that, you would seek them out every time, maybe even bring them little gifts.
Of course now we are all our own keypunch operators!
Learn to code in C & ASM. Learn to hand-compile to ASM, and hand-assemble to machine instructions for the CPU we were using. Now learn VHDL. Implement a processor on an FPGA. Write a (tiny, minimal, not fully standards compliant) C compiler for it. You're back to step 1.
Of course we didn't implement the synthesizer, or place & rout logic, or bitstream format, or the FPGA itself. You have to stop somewhere.
We also hired a guy who made simpler Javascript games, but his code looked great an he understood how it all worked.
One is still here, and isn't very useful, the other left for greener pastures as management wanted him to work on only the boring stuff.
C-level companies will prefer B-level players
Also don't hire programmers who demonstrated that they don't care about the fun stuff unless you have no other options.
This is why I feel like I'm a bad programmer and no longer look for work in that capacity. I enjoy the edge cases and challenging problems, but I am almost incapable of creating CRUD apis and user interfaces at this point. I'm amazing in a hackathon, but contribute poorly to regular sprint style work. I can pick up and integrate new technology extremely quickly and can refactor a spaghettified mess of code into something maintainable, but I am completely miserable doing maintenance level work after things are smoothed out.
> I am completely miserable doing maintenance level work
Sounds like something you might want to work on even if you don't get a job in programming. It seems unlikely you'll find any line of work where everything you do every day is new and exciting.
Programming-wise it isn't as hard to find as you might think. Maybe not working FAAMG or similar, but it's quite doable. If you don't compromise on the desire to work only on interesting* stuff when a big paycheck comes along, you'll eventually end up in a position where you only work on interesting stuff. The gamut of work is wide.
To be honest such work isn't even that rare. Most people would rather make $200k and complain about how boring their job is than have an interesting one. I think for many people "interesting work" is often the same as "stressful work" and so the interesting positions are not as easily filled.
[*] Interesting as defined by me, and probably the parent poster as well. Obviously this is subjective.
Most of the code I write these days is put together like a ransom note but it sure makes it easier to get things done.
Of course application becomes the concern, but can we really be assured that someone who can perform the calculations mentally also knows when best to use them?
You can draw the line where you want at a concert.
If you only need some background music for vocals, press play and be done with it.
If you are good enough to play something live while singing, you can gradually change the way.
Life is an optimization problem.