28 ms·
Writing correct code at scale is essentially impossible. We have multiple operating systems, runtimes, libraries, and hardware platforms to worry about without
by mapleoin 11y ago
Writing correct code at scale is essentially impossible. We have multiple operating systems, runtimes, libraries, and hardware platforms to worry about without even considering things like random bit flips in RAM or our block devices lying to us with unknown probability.
The best we can do is write simple, understandable code with as few indirections and as little undocumented magic as possible.
Applies very well to all programming.
- userbinator 11y agoI've noticed that "low-level" languages like C, or for a more extreme example, assembly languages, tend to encourage simpler code if for nothing other than the fact that everything takes many more lines than in higher-level languages. E.g. if you want to do OOP you'll have to allocate memory and call constructors manually, pass explicit 'this' parameters into all method calls, declare virtual function tables, etc. Certainly there are cases where this tempts too easy solutions like fixed-size overflow-prone buffers instead of dynamically allocating strings, but on the other hand it forces you to think more about whether you actually need to do something ("should this string ever be more than X bytes long? Maybe not, might as well use fixed-size array - but I should not forget to check that length!"), which I think is overall a good thing.
- mrich 11y agoIt also makes you think upfront about the design much more. With all the intricacies of writing correct low-level code you really want to write it once only and not try out different designs and refactor between them, where mistakes quickly happen. Of course this is a disadvantage if you don't have sufficient experience in the problem domain. Sometimes I resort to writing prototypes in a script language in that case, translating the best design to the low-level language.
- adrianN 11y agoA language that is "write it right the first time, refactoring is painful" is a poor fit for most problems. Requirements change, if your software can't be adapted easily your project will fail. The general failure of waterfall-style software development is a strong indicator that finding the "right" design up front usually doesn't work out.
- kqr 11y ago> on the other hand it forces you to think more about whether you actually need to do something ("should this string ever be more than X bytes long? Maybe not, might as well use fixed-size array - but I should not forget to check that length!"), which I think is overall a good thing. While that certainly can't be a bad thing, you just have to keep in mind that it forces you to think about a specific set of details – the ones that matter for the machine ("how many bytes will the binary representation of this username require") – and it may fool you into forgetting to think about higher-level concerns ("Does å compare equally to å?").
- moonchrome 11y agoYeah, let's use copy & paste and C preprocessor macros as our abstraction tools ... Avoiding unnecessary abstractions is important but at the same time those abstractions were invented for a reason. Basically the Go vs generics debate, except even more rudimentary. It's fine if your code doesn't need those abstractions, it sucks badly if it does (eg. gobject)
- comex 11y agoDepends on your definition of rudimentary. The C preprocessor sucks in general, but you can use it to implement all sorts of abstractions Go basically isn't capable of.
- moonchrome 11y agoIf replacing standard high level programming concepts like generics/templates with C macros is your idea of a productive programming environment than I don't know what to say. Just look at any C collection library for things like maps compared to C++.
- pjmlp 11y agoThis is only true of C. Algol, PL/I, Mesa, Cedar, Modula-2 and many other languages of similar age or older than C, do offer both higher and lower level mechanisms.
- yoklov 11y agoI think it's mostly that C's lack of language features removes distractions. You have only a couple abstractions to work with if you're writing idiomatic C code, and so you can focus on the task at hand more easily. The tradeoff is that the task at hand tends to have more implementation details in it than in higher level languages, but as you said, this isn't always bad.
- lmm 11y agoI think it only looks that way because people don't compare like with like. x lines of code C may well be simpler than x lines of a given alternative. But http://qdb.us/301922 http://qdb.us/301922
- shwouchk 11y agoAaaand we got ourselves another site with an 8 or less char password
- noobermin 11y agoAu contraire my friend, I've seen C code with "functions" that are >1000 lines long, probably ~10 parameters with lovely names like `lfp`, and where probably 40% of those lines are #ifdef and #endif. The same code would be much simpler with C++ templates, but the "C being simple" really translates into limited, then you have that some have who never learned how to use macros and this unfounded and misunderstood fear of goto that gives you a nice long lines of error checking, each that that are duplicated if statements character by character where a goto and a single error handler would have worked. Perhaps this is an exception, but low-level in my case did not correspond to simple code.
- JoeAltmaier 11y agoIn an extreme example, I replaced a 10,000 line C method with one template of less than a page of C++ code. It was marshaling different structures for transmission over a mailbox port. All that code copied and pasted and one or two numbers changed depending on the structure size.
- ahoka 11y agoI think C does not make you write simpler code. It makes people take short-cuts. Static allocations, using a hand rolled linked list, skipping return value checks or boundary checks etc. are all typical to C programs.
- vardump 11y agoNot sure why you've been voted down. I've seen too many lines of C and what you said is true most of the time. Although developers skipping return value checks is true in most languages.
- Gibbon1 11y agoI have two things to say. #1 The submitted article is very good. #2 I'd add to it, avoid pointer arithmetic when possible. Use array notation instead. Typically the difference in execution speed is zero to nil. #3 I'd really like a pragma that forces an exception for unchecked return values. Something like int DoSomeThing(/* whatever*/) #pragma exit "unchecked non_zero" Meaning if DoSomething() doesn't return zero the program bails.
- unscaled 11y ago> Although developers skipping return value checks is true in most languages. Yes, which is why I disagree with Go's approach for error codes as return values. I'm not saying that exceptions are the right solution everywhere, but if you return a error code, you should make it pretty hard to ignore it. In languages with Algebraic Data Types it's very easy to use Maybe or a Error(code) | Success(result) type. You've then got to explicitly deconstruct that type to get the result, so it's a bit harder to just forget handling the error.
- vog 11y agoAlso, the very first advice applies to suprisingly many languages and frameworks, not just C: > The first rule of C is don't write C if you can avoid it.
- wdmeldon 11y agoProgramming in general honestly. Don't write code if you can avoid it, which loosely translates to "Don't solve problems that don't need solving".
- pampa 11y agoDon't write code if you can avoid it and somebody will sell you a half-baked closed source SaaS, which will be acquired and closed in two years.
- eizan 11y agoOr some obscure library found on github that's effectively become abandonware. Now you've just inherited a legacy codebase to maintain because some of your coworkers wanted to use a small subset of its functionality!
- lmm 11y agoNo, and to claim as much is simple laziness. It is possible to write provably correct code. Even if you don't want to go full formally verified, you can eliminate large categories of possible errors with a relatively small amount of proof. None of which removes the need to write simple, understandable code without undocumented magic. But we should not be throwing up our hands and treating invalid accesses, memory safety failures, buffer overflows, SQL injection, XSS, or a whole host of common failures as inevitable. It really is possible to do a lot better than most programs and a lot better than C.
- Avshalom 11y agoright "the best we can do" is actually pretty damned good, if anyone would bother doing it.
- ozim 11y agoI bother doing it but it still ends up: "the best they want to pay us for" which usually is less than the best.
- bloaf 11y agoThat reminds me of the old G.K. Chesterton quote, which was originally about religion. Provable correctness "...has not been tried and found wanting; it has been found difficult and not tried."
- AnimalMuppet 11y agoWhat is the largest program that has been proven correct? We're writing programs that are tens of millions of lines of code (OSes, databases, air traffic control systems). My impression of provable correctness is that the largest program that has been proven is in the area of 100,000 lines (feel free to correct if I am in error). We need to be able to prove programs two orders of magnitude bigger than that; provable correctness has not been tried for such programs because nobody wants to wait a generation or two before they get the results.
- hal9000xp 11y agoI'm highly disagree that it's impossible to write high quality code in C language for a big project (I don't like his statement: The first rule of C is don't write C if you can avoid it). I was mostly C developer (80% C, 20% C++) for 4 years in a big project (I was backend developer of ICQ Instant Messenger). It has more than 2M lines of C code. Almost all libraries was written from scratch in C language (since ICQ is very old project, many of essential stuff was written within AOL). I felt comfortable to write high level code in C. When I read Nginx source code (it's written in C), I see better code quality than 90% of proprietary commercial software which is written on nice and comfortable high level languages. Good developer is able to write high quality code in C language with minimum bugs in large scale project. Regardless of how nice and high level and convenient language, bad developer will write c....y code. You can also check my personal project which is written entirely in C. (I didn't contribute for 1.5 years to my github since I was changed countries of living, jobs etc. I hope I will return to it when my life become stable again). P.S. To be clear, I think that C++11 is great language. But unlike many C++ developers, I love pure C.
- stcredzero 11y agoI remember seeing someone's C++ code at GDC and thinking to myself, "That looks like good Smalltalk!" Everything was intention revealing. Everything was about objects "sending messages" to each other. I've also seen production Smalltalk that might as well have been FORTRAN from the 70's. (Not one instance method or variable in the whole system. Everything was indexed loops.) The people and the culture/organization of the shop counts for much more than your language. Language counts for something, but it's not where you get the most bang for your buck, and it shouldn't be your first priority!