| ▲ | time4tea a day ago |
| a = a; // misra Actual code i have seen with my own eyes. (Not in F-35 code) Its a way to avoid removing an unused parameter from a method. Unused parameters are disallowed, but this is fine? I am sceptical that these coding standards make for good code! |
|
| ▲ | tialaramex a day ago | parent | next [-] |
| Studies have looked at MISRA, I'm not aware of any for the JSF guidelines. For MISRA there's a mix, some of the rules seem to be effective (fewer defects in compliant software), some are the opposite (code which obeys these rules is more likely to have defects) and some were irrelevant. Notably this document is from 2005. So that's after C++ was standardized but before their second bite of that particular cherry and twenty years before its author, Bjarne Stroustrup suddenly decides after years of insisting that C++ dialects are a terrible idea and will never be endorsed by the language committee, that in fact dialects (now named "profiles") are the magic ingredient to fix the festering problems with the language. While Laurie's video is fun, I too am sceptical about the value of style guides, which is what these are. "TABS shall be avoided" or "Letters in function names shall be lowercase" isn't because somebody's aeroplane fell out of the sky - it's due to using a style Bjarne doesn't like. |
| |
| ▲ | platinumrad a day ago | parent | next [-] | | The "good" rules are like "don't write off the end of an array", and the bad ones are like "no early returns" or "variable names must not be longer than 6 characters". 95% of the "good" rules are basically just longer ways of saying "don't invoke undefined behavior". | | |
| ▲ | bboygravity 21 hours ago | parent | next [-] | | Why is "no early returns" not a good rule? I do early returns in code I write, but ONLY because everybody seems to do it. I prefer stuff to be in predictable places: variables at the top, return at the end. Simpler? Delphi/Pascal style. | | |
| ▲ | jandrewrogers 18 hours ago | parent | next [-] | | Early returns makes the code more linear, reduces conditional/indent depth, and in some cases makes the code faster. In short, it often makes code simpler. The “no early returns” is a soft version of “no gotos”. There are cases where it is not possible to produce good code while following those heuristics. A software engineer should strive to produce the best possible code, not rigidly follow heuristics even when they don’t make sense. There is an element of taste. Don’t create random early returns if it doesn’t improve the code. But there are many, many cases where it makes the code much more readable and maintainable. | |
| ▲ | stonemetal12 9 hours ago | parent | prev | next [-] | | Because good code checks pre conditions and returns early if they are not met. | |
| ▲ | mrgaro 18 hours ago | parent | prev | next [-] | | I remember having this argument with my professor at the school, who insisted that a function should have only one "return" clause at the very end. Even as I tried, I could not get him to explain why this would be valuable and how does this produce better code, so I'm interested on hearing your take on this? | | |
| ▲ | superxpro12 10 hours ago | parent [-] | | It helps prevent bugs with state. The apple login bypass bug comes to mind. Basically, you have code in an "if" statement, and if you return early in that if statement, you might have code that you needed to run, but didnt. Forcing devs to only "return once" encourages the dev to think through any stateful code that may be left in an intermediate state. In practice, at my shop, we permit early returns for trivial things at the top of a function, otherwise only one return at the bottom. That seems to be the best of both worlds for this particular rule. | | |
| ▲ | Symmetry 6 hours ago | parent | next [-] | | The rule of thumb I use is to only have one return after modifying state that will persist outside the function call. | |
| ▲ | SideburnsOfDoom 9 hours ago | parent | prev [-] | | > The apple login bypass bug comes to mind. I think you're talking about this "goto fail" bug? https://teamscale.com/blog/en/news/blog/gotofail > In practice, at my shop, we permit early returns for trivial things Are you also writing C or similar? If so, then this rule is relevant. In modern languages, there are language constructs to aid the cleanup on exit, such as using(resource) {} or try {} finally {} It really does depend on if these conveniences are available or not. For the rest of us, the opposite of "no early return" is to choose early return only sometime - in cases where results in better code, e.g. shorter, less indented and unlikely to cause issues due to failure to cleanup on exit. And avoid it where it might be problematic. In other words, to taste. > Kent Beck, Martin Fowler, and co-authors have argued in their refactoring books that nested conditionals may be harder to understand than a certain type of flatter structure using multiple exits predicated by guard clauses. Their 2009 book flatly states that "one exit point is really not a useful rule. Clarity is the key principle: If the method is clearer with one exit point, use one exit point; otherwise don’t". https://en.wikipedia.org/wiki/Structured_programming#Early_e... this thinking is quite different to say, 25 years earlier than that, and IMHO the programming language constructs available play a big role. |
|
| |
| ▲ | katzenversteher 19 hours ago | parent | prev | next [-] | | For me it's mostly about indentation / scope depth. So I prefer to have some early exits with precondition checks at the beginning, these are things I don't have to worry about afterwards and I can start with the rest at indentation level "0". The "real" result is at the end. | |
| ▲ | dragonwriter 18 hours ago | parent | prev | next [-] | | > Why is "no early returns" not a good rule? It might be a good guideline. Its not a good rule because slavishly following results in harder to follow code written to adhere to it. | |
| ▲ | SideburnsOfDoom 17 hours ago | parent | prev [-] | | The "no early returns" rule came about because was a good rule in context, specifically C and FORTRAN code before roughly 1990. It was part of "structured programming", contemporary to "Go To Statement Considered Harmful", Dijkstra, 1968. And it became received wisdom - i.e. a rule that people follow without close examination. For example of the rule, a function might allocate, do something and then de-allocate again at the end of the block. A second exit point makes it easy to miss that de-allocation, and so introduce memory leaks that only happen sometimes. The code is harder to reason about and the bugs harder to find. source: > A problem with early exit is that cleanup statements might not be executed. ... Cleanup must be done at each return site, which is brittle and can easily result in bugs. https://en.wikipedia.org/wiki/Structured_programming#Early_r... About 90% of us will now be thinking "but that issue doesn't apply to me at all in $ModernLang. We have GC, using (x) {} blocks, try-finally, or we have deterministic finalisation, etc." And they're correct. In most modern languages it's fine. The "no early returns" rule does not apply to Java, TypeScript, C#, Rust, Python, etc. Because these languages specifically made early return habitable. The meta-rule is that some rules persist past the point when they were useful. Understand what a rule is for and then you can say when it applies at all. Rules without reasons make this harder. Some rules have lasted: we typically don't use goto at all any more, just structured wrappers of it such as if-else and foreach | | |
| ▲ | zahlman 8 hours ago | parent [-] | | > And they're correct. In most modern languages it's fine. The "no early returns" rule does not apply to Java, TypeScript, C#, Rust, Python, etc. Because these languages specifically made early return habitable. Early return is perfectly manageable in C as long as you aren't paranoid about function inlining. You just have a wrapper that does unconditional setup, passes the acquired resources to a worker, and unconditionally cleans up. Then the worker can return whenever it likes, and you don't need any gotos either. | | |
| ▲ | SideburnsOfDoom 8 hours ago | parent [-] | | > In C, you just have a wrapper that does unconditional setup, passes the acquired resources to a worker, and unconditionally cleans up. Then the worker can return whenever it like Right, so you allow early return only in functions that do not have any setup and clean-up - where it's safe. Something like "pure" functions. And you describe a way to extract such functions from others. |
|
|
| |
| ▲ | lou1306 14 hours ago | parent | prev [-] | | > variable names must not be longer than 6 characters My memory might be lapsing here, but I don't think MISRA has such a rule.
C89/C90 states that _external_ identifiers only matter up to their first 6 characters [1], while MISRA specifies uniqueness up to the first 31 characters [2]. [1] https://stackoverflow.com/questions/38035628/c-why-did-ansi-... [2] https://stackoverflow.com/questions/19905944/why-must-the-fi... |
| |
| ▲ | windward 15 hours ago | parent | prev | next [-] | | Bjarne's just a guy, he doesn't control how the C++ committee vote and doesn't remotely control how you or I make decisions about style. And boiling down these guidelines to style guides is just incorrect. I've never had a 'nit: cyclomatic complexity, and uses dynamic allocation'. | |
| ▲ | writtiewrat a day ago | parent | prev [-] | | [flagged] | | |
| ▲ | tomhow 20 hours ago | parent | next [-] | | We've banned this account for continual guidelines breaches across multiple accounts. | | |
| ▲ | menaerus 18 hours ago | parent [-] | | You do realize that there's a handful of literally the same people here on HN continuously evangelizing one technology by constantly dissing on the other? Because of the pervasiveness of such accounts/comments it invites other people, myself included, to counter-argue because most of the time the reality they're trying to portray is misrepresented or many times simply wrong. This is harmful and obviously invites for a flame war so how is that not by the same principle you applied to above account a guideline breach too? | | |
| ▲ | tomhow 14 hours ago | parent [-] | | We act on what we see, and we see what people make us aware of via flags and emails. Comments like yours are difficult because they’re not actionable or able to be responded to in a way you’ll find satisfying if you don’t link to the comments that you mean. Programming language flamewars have always been lame on HN and we have no problem taking action against perpetrators when we’re alerted to them. |
|
| |
| ▲ | tialaramex a day ago | parent | prev [-] | | "No semantic effect" is one of those recurring C++ tropes like the "subset of a superset" or "trading performance for safety" that I think even its defenders ought to call bullshit on. The insistence on "No semantic effect" for attributes has poisoned them badly, and the choice to just ignore the semantic implications for Bjarne's C++ 20 Concepts makes this a poor substitute for the concepts feature as once imagined at the start of the century. I doubt I can satisfy you as to whether I'm somehow a paid evangelist, I remember I got a free meal once for contributing to the OSM project, and I bet if I dig further I can find some other occasion that, if you spin it hard enough can be justified as "payment" for my opinion that Rust is a good language. There was a nice lady giving our free cookies at the anti-racist counter-protests the other week, maybe she once met a guy who worked for an outfit which was contracted to print a Rust book? I sense you may own a corkboard and a lot of red string. | | |
|
|
|
| ▲ | unwind a day ago | parent | prev | next [-] |
| For C, the proper/expected/standard way to reference a variable without accessing it is a cast to void: (void) a;
I'm sure there are commonly-implemented compiler extensions, but this is the normal/native way and should always work. |
| |
| ▲ | amluto a day ago | parent [-] | | Not if you use GCC. https://godbolt.org/z/zYdc9ej88 clang gets this right. | | |
| ▲ | comex a day ago | parent | next [-] | | It does work in GCC to suppress unused variable warnings. Just not for function calls I guess. | | |
| ▲ | cminmin 17 hours ago | parent [-] | | __attribute__((maybe_unused)) or [[maybe_unused]] or such things (dependin on ur spec version i guess?) can be used not to disable a whole line of errors. |
| |
| ▲ | gpderetta 12 hours ago | parent | prev | next [-] | | interestingly it works for [[nodiscard]]! and assigning to std::ignore works for both. | |
| ▲ | Am4TIfIsER0ppos a day ago | parent | prev [-] | | You've defined that function with an attribute saying not to ignore the returned value. Is it right to explicitly silence an explicit warning? | | |
| ▲ | amluto a day ago | parent | next [-] | | I want some defined way to tell the compiler that I am intentionally ignoring the result. I encounter this when trying to do best-effort logging in a failure path. I call some function to log and error and maybe it fails. If it does, what, exactly, am I going to do about it? Log harder? | | |
| ▲ | dotancohen 18 hours ago | parent [-] | | Yes. When my database logging fails, I write a file that logs the database fail (but not the original log file). When my file logging fails, depending on application, I'll try another way of getting the information (the fact that for file logging failed) out - be that an http request or an email or something else. Databases fail, file systems fill up. Logging logging failures is extremely important. | | |
| ▲ | amluto 18 hours ago | parent [-] | | And when that last way fails, what do you do? I like to have a separate monitoring process that monitors my process and a separate machine in a different datacenter monitoring that. But at the end of the day, the first process is still going to do try to log, detect that it failed, try the final backup log and then signal to its monitor that it’s in a bad state. It won’t make any decisions that depend on whether the final backup logging succeeds or fails. | | |
| ▲ | dotancohen 16 hours ago | parent [-] | | I'm not working on anything life-critical, one additional layer of redundancy is all I budget for. If both my database is down and my local filesystem is full simultaneously, things have gone bad and I've likely got lots of other symptoms I'm going to find to direct me. |
|
|
| |
| ▲ | MathMonkeyMan a day ago | parent | prev [-] | | Sometimes. For example, you might be setting a non-crucial option on a socket, and if it fails you don't even care to log the fact (maybe the logging would be too expensive), so you just ignore the return value of whatever library is wrapping setsockopt. |
|
|
|
|
| ▲ | platinumrad a day ago | parent | prev | next [-] |
| I've (unfortunately) written plenty of "safety critical" code professionally and coding standards definitely have a negative effect overall. The thing keeping planes from falling out of the sky is careful design, which in practice means fail-safes, watchdogs, redundancy, and most-importantly, requirements that aren't overly ambitious. While maybe 10% of rules are sensible, these sensible rules also tend to be blindingly obvious, or at least table stakes on embedded systems (e.g. don't try to allocate on a system which probably doesn't have a full libc in the first place). |
| |
| ▲ | dilyevsky a day ago | parent [-] | | Many coding standards rules have nothing to do with correctness and everything to do with things like readability and reducing cognitive load (“which style should I use here?”) |
|
|
| ▲ | ivanjermakov a day ago | parent | prev | next [-] |
| Zig makes it explicit with _ = a;
And you would encounter it quite often because unused variable is a compilation error: https://github.com/ziglang/zig/issues/335 |
| |
| ▲ | bluecalm a day ago | parent | next [-] | | Doesn't it make it more likely unused variables stay in the codebase? You want to experiment, the code doesn't compile, you add this (probably by automatic tool), the code now compiles. You're happy with your experiment. As the compiler doesn't complain you commit and junk stays in the code. Isn't it just bad design that makes both experimenting harder and for unused variables to stay in the code in the final version? | | |
| ▲ | ivanjermakov a day ago | parent [-] | | It is indeed quite controversial aspect of Zig's design. I would rather prefer it be a warning. Argument "warnings are always ignored" just doesn't hold because anything can be ignored if there is a way to suppress it. | | |
| ▲ | dnautics a day ago | parent [-] | | there was a recent interview where andrew suggested if i understood correctly: the future path of zig is to make all compilations (successful or not) produce an executable. if theres something egregious like a syntax or type error, the produced artifact just prints the error and returns nonzero. for a "unused parameter", the compiler produces the artifact you expect, but returns nonzero (so it gets caught by CI for example. | | |
| ▲ | sumalamana a day ago | parent [-] | | Why would the compiler do that, instead of just printing the error at compile-time and exiting with a non-zero value? What is the benefit? | | |
| ▲ | dnautics 10 hours ago | parent | next [-] | | if you have a syntax error in file A, and file B is just peachy keen, you can keep compiling file B instead of stopping the world. Then the next time you compile, you have already cached the result of file B compilation. | |
| ▲ | j16sdiz 21 hours ago | parent | prev [-] | | It is more a debug/development feature. You can try out some idea without fixing the whole code base. |
|
|
|
| |
| ▲ | ErroneousBosh a day ago | parent | prev [-] | | Golang is exactly the same. It's extremely annoying until it's suddenly very useful and has prevented you doing something unintended. | | |
| ▲ | bluecalm a day ago | parent | next [-] | | I fail to see how a warning doesn't achieve the same thing while allowing you to iterate faster. Unless you're working with barbarians who commit code that complies with warnings to your repo and there is 0 discipline to stop them. | | |
| ▲ | FieryMechanic 14 hours ago | parent | next [-] | | > I fail to see how a warning doesn't achieve the same thing while allowing you to iterate faster. In almost every code base I have worked with where warnings weren't compile errors, there were hundreds of warnings. Therefore it just best to set all warnings as errors and force people to correct them. > Unless you're working with barbarians who commit code that complies with warnings to your repo and there is 0 discipline to stop them. I work with a colleague that doesn't compile/run the code before putting up a MR. I informed my manager who did nothing about it after he did it several times (this was after I personally told him he needed to do it and it was unacceptable). This BTW this happens more often than you would expect. I have read PRs and had to reject them because I read the code and they wouldn't have worked, so I know the person had never actually run the code. I am quite a tidy programmers, but it difficult for people even to write commit messages that aren't just "fixed bugs". | | |
| ▲ | ErroneousBosh 5 hours ago | parent [-] | | > I work with a colleague that doesn't compile/run the code before putting up a MR. I informed my manager who did nothing about it after he did it several times (this was after I personally told him he needed to do it and it was unacceptable). At this point what you need to do is stop treating compiler warnings as errors, and just have them fire the shock collar. Negative reinforcement gets a bad rep, but it sure does work. |
| |
| ▲ | ErroneousBosh 17 hours ago | parent | prev | next [-] | | Go is a very opinionated language. If you don't like K&R indentation, tough - anything else is a syntax error. It's kind of like the olden days. | | |
| ▲ | bluecalm 16 hours ago | parent [-] | | Yeah but this case just seem to be strictly worse. It makes experimenting worse and it makes it more likely (not less) that unused variables end up in the final version. I get being opinionated about formatting, style etc. to cut endless debates but this choice just seem strictly worse for two things it influences (experimenting and quality of the final code). | | |
| ▲ | ErroneousBosh 16 hours ago | parent [-] | | If you want to leave a variable unused, you can just assign it to _ (underscore) though. IIRC gofmt (which your editor should run when you save) will warn you about it but your code will compile. It's a slightly different mindset, for sure, but having gofmt bitch about stuff before you commit it rather than have the compiler bitch about it helps you "clean as you go" rather than writing some hideous ball of C++ and then a day of cleaning the stables once it actually runs. Or at least it does for me... |
|
| |
| ▲ | treyd 19 hours ago | parent | prev [-] | | You're not supposed to question the wisdom of the Go developers. They had a very good reason for making unused variables be an unconfigurable hard error, and they don't need to rigorously justify it. | | |
| ▲ | FieryMechanic 14 hours ago | parent [-] | | Warnings are often ignored by developers unless you specifically force warnings to be compile errors (you can do this in most compiler). I work on TypeScript/C# code-bases and unless you force people to tidy up unused imports/using and variables, people will just leave them there. This BTW can cause issues with dependency chains and cause odd compile issues as a result. |
|
| |
| ▲ | SoKamil a day ago | parent | prev [-] | | And what is the unintended thing that happens when you have unused variable? |
|
|
|
| ▲ | y1n0 a day ago | parent | prev | next [-] |
| The standards don't remove the need for code review. In fact they provide a standard to be used in code review. Anything you can automate is nice, but when you have exceptions to rules that say "Exception, if there's no reasonable way to do X then Y is acceptable" isn't really something you can codify into static analysis. |
|
| ▲ | qart 18 hours ago | parent | prev | next [-] |
| You're right. MISRA is a cult. Actual studies[1][2] have shown many of their rules to be harmful rather than helpful. I have worked in multiple safety-critical industries. MISRA is almost always enforced by bureaucrats who don't understand source code at all, or by senior developers who rose up ranks as code monkeys. One such manager was impressed with Matlab because Matlab-generated C code was always MISRA compliant, whereas the code my company was giving them had violations. Never mind the fact that every function of the generated, compliant code had variables like tmp01, tmp02, tmp03, etc. There are many areas of software where bureaucracy requires MISRA compliance, but that aren't really safety-critical. The code is a hot mess. There are other areas that require MISRA compliance and the domain is actually safety-critical (e.g. automotive software). Here, the saving grace is (1) low complexity of each CPU's codebase and (2) extensive testing. To people who want actual safety, security, portability, I tell them to learn from examples set by the Linux kernel, SQLite, OpenSSL, FFMpeg, etc. Modern linters (even free ones) are actually valuable compared to MISRA compliance checkers. [1] https://ieeexplore.ieee.org/abstract/document/4658076 [2] https://repository.tudelft.nl/record/uuid:646de5ba-eee8-4ec8... |
| |
| ▲ | sam_bristow 16 hours ago | parent [-] | | One key point that people overlook with that paper is that they were applying the coding standards retroactively. Taking an existing codebase, running compliance tools, and trying to fix the issues which were flagged. I think they correctly identified the issue with this approach in that you have all the risks of introducing defects as part of reworking the existing code. I don't think they have much empirical evidence for the case where coding standards were applied from the beginning of a project. In my opinion, the MISRA C++ 2023 revision is a massive improvement over the 2008 edition. It was a major rethink and has a lot more generally useful guidance. Either way, you need to tailor the standards to your project. Even the MISRA standards authors agree: """ Blind adherence to the letter without understanding is pointless.
Anyone who stipulates 100% MISRA-C coverage with no deviations does not understand what the are asking for.
In my opionion they should be taken out and... well... Just taken out.
- Chris Hill, Member of MISRA C Working Group (MISRA Matters Column, MTE, June 2012
""" |
|
|
| ▲ | a day ago | parent | prev | next [-] |
| [deleted] |
|
| ▲ | jjmarr a day ago | parent | prev | next [-] |
| An unused parameter should be commented out. |
| |
| ▲ | MobiusHorizons a day ago | parent [-] | | Unless it’s there to conform to an interface | | |
| ▲ | jjmarr a day ago | parent [-] | | Especially if it's there to conform to an interface. You can comment out the variable name and leave the type. |
|
|
|
| ▲ | binary132 a day ago | parent | prev | next [-] |
| It’s very weird how none of the sibling comments understood what it were saying is wrong with this. |
| |
| ▲ | binary132 a day ago | parent [-] | | Erm, sorry about the weird typo. Didn’t notice. Can’t edit now. |
|
|
| ▲ | msla a day ago | parent | prev | next [-] |
| Especially since there is a widely recognized way to ignore a parameter: (void) a;
Every C programmer beyond weaning knows that. |
| |
| ▲ | time4tea a day ago | parent | next [-] | | The point really was that the unused method parameter should in almost all cases be removed, not that some trick should be used to make it seem used, and this is the wrong trick! | | |
| ▲ | addaon a day ago | parent | next [-] | | Sometimes. But sometimes you have a set of functions that are called through function pointers that need the same signature, and one or more of them ignore some of the arguments. These days I’d spell that __attribute__((unused)); but it’s a perfectly reasonable case. | |
| ▲ | bluGill 15 hours ago | parent | prev [-] | | #if otherbuild
dosomething(param);
#endif
the above type of thing happens once in a while. nos the paramater is needed but the normal build doesn't use it |
| |
| ▲ | a day ago | parent | prev | next [-] | | [deleted] | |
| ▲ | stefan_ a day ago | parent | prev [-] | | I'm sure thats disallowed for the C-style cast. | | |
| ▲ | cpgxiii a day ago | parent | next [-] | | Fwiw, unused-cast-to-void is a case that GCC and Clang ignore when using -Wno-old-style-cast, which is what most projects prohibiting C-style casts are going to be using (or whatever the equivalent their compiler provides). | |
| ▲ | daringrain32781 a day ago | parent | prev [-] | | C++17 has the [[maybe_unused]] attribute. |
|
|
|
| ▲ | jojobas a day ago | parent | prev [-] |
| Isn't it inevitable for some cases of inheritance? A superclass does something basic and doesn't need all parameters, child classes require additional ones. |