Skip to main content

CodeSOD: An Argument With QA

3 months 2 weeks ago

Markus does QA, and this means writing automated tests which wrap around the code written by developers. Mostly this is a "black box" situation, where Markus doesn't look at the code, and instead goes by the interface and the requirements. Sometimes, though, he does look at the code, and wishes he hadn't.

Today's snippet comes from a program which is meant to generate PDF files and then, optionally, email them. There are a few methods we're going to look at, because they invested a surprising amount of code into doing this the wrong way.

protected override void Execute() { int sendMail = this.VerifyParameterValue(ParamSendMail); if (sendMail == -1) return; if (sendMail == 1) mail = true; this.TraceOutput(Properties.Resources.textGetCustomerForAccountStatement); IList<CustomerModel> customers = AccountStatement.GetCustomersForAccountStatement(); if (customers.Count == 0) return; StreamWriter streamWriter = null; if (mail) streamWriter = AccountStatement.CreateAccountStatementLogFile(); CreateAccountStatementDocumentEngine engine = new CreateAccountStatementDocumentEngine(); foreach (CustomerModel customer in customers) { this.TraceOutput(Properties.Resources.textCustomerAccountStatementBegin + customer.DisplayName.ToString()); // Generate the PDF, optionally send an email with the document attached engine.Execute(customer, mail); if (mail) { AccountStatement.WriteToLogFile(customer, streamWriter); this.TraceOutput(Properties.Resources.textLogWriting); } } engine.Dispose(); if (streamWriter != null) streamWriter.Close(); }

Now, this might sound unfair, but right off the bat I'm going to complain about separation of concerns. This function both generates output and emails it (optionally), while handling all of the stream management. Honestly, I think if the developer were simply forced to go back and make this a set of small, cohesive methods, most of the WTFs would vanish. But there's more to say here.

Specifically, let's look at the first few lines, where we VerifyParameterValue. Note that this function clearly returns -1 when it fails, which is a very C-programmer-forced-to-do-OO idiom. But let's look at that method.

private int VerifyParameterValue(string name) { string stringValue = this.GetParam(name, string.Empty); bool isValid = this.VerifyByParameterFormat(name, stringValue); if (!isValid) return -1; int value = -1; try { value = Convert.ToInt32(stringValue); } catch (Exception e) { this.TraceOutput(string.Concat("\n\n\n", e.Message, "\n\n\n")); return -1; } return value; }

We'll come back to the VerifyByParameterFormat but otherwise, this is basically a wrapper around Convert.ToInt32, and could easily be replaced with Int32.TryParse.

Bonus points for spamming the log output with loads of newlines.

Okay, but what is the VerifyByParameterFormat doing?

private bool VerifyByParameterFormat(string name, string value) { string parameter = string.Empty; string message = string.Empty; if (value.Length != 1) { parameter = Properties.Resources.textSendMail; message = string.Format(Properties.Resources.textSendMailNotValid, value); this.TraceOutput(string.Concat("\n\n\n", message, "\n\n\n")); return false; } string numbers = "0123456789"; char[] characters = value.ToCharArray(); for (byte i = 0; i < characters.Length; i++) { if (numbers.IndexOf(characters[i]) < 0) { parameter = Properties.Resources.textSendMail; message = Properties.Resources.textSendMailNotValid; this.TraceOutput(string.Concat("\n\n\n", message, "\n\n\n")); return false; } } return true; }

Oh, it just goes character by character to verify whether or not this is made up of only digits. Which, by the way, means the CLI argument needs to be an integer, and only when that integer is 1 do we send emails. It's a boolean, but worse.

Let's assume, however, that passing numbers is required by the specification. Still, Markus has thoughts:

Handling this command line argument might seem obvious enough. I'd probably do something along the lines of "if (arg == "1") { sendMail = true } else if (arg != "0") { tell the user they're an idiot }. Of course, I'm not a professional programmer, so my solution is way too simple as the attached piece of code will show you.

There are better ways to do it, Markus, but as you've shown us, there are definitely worse ways.

.comment { border: none; } [Advertisement] Plan Your .NET 9 Migration with Confidence
Your journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
Remy Porter

Goldman Sachs: Why AI Spending Is Not Boosting GDP

3 months 2 weeks ago
Goldman Sachs, in a research note Thursday (the note isn't publicly posted): Annualized revenue for public companies exposed to the build-out of AI infrastructure increased by over $340 billion from 2022 through 2024Q4 (and is projected to increase by almost $580 billion by end-2025). In contrast, annualized real investment in AI-related categories in the US GDP accounts has only risen by $42 billion over the same period. This sharp divergence has prompted questions from investors about why US GDP is not receiving a larger boost from AI. A large share of the nominal revenue increase reported by public companies reflects cost inflation (particularly for semiconductors) and foreign revenue, neither of which should boost real US GDP. Indeed, we find that margin expansion ($30 billion) and increased revenue from other countries ($130 billion) account for around half of the publicly reported AI spending surge. That said, the BEA's (Bureau of Economic Analysis) methodology potentially understates the impact of AI-related investment on real GDP by around $100 billion. Manufacturing shipments and net imports imply that US semiconductor supply has increased by over $35 billion since 2022, but the BEA records semiconductor purchases as intermediate inputs rather than investment (since semiconductors have historically been embedded in products that are later resold) and therefore excludes them from GDP. Cloud services used to train and support AI models are similarly mostly recorded as intermediate inputs. Combined, we find that these explanations can explain most of the AI investment discrepancy, with only $50 billion unexplained. Looking ahead, we see more scope for AI-related investment to provide a moderate boost to real US GDP in 2025 since AI investment should broaden to categories like data centers, servers and networking hardware, and utilities that will likely be captured as real investment. However, we expect the bulk of investment in semiconductors and cloud computing will remain unmeasured barring changes to US national account methodology.

Read more of this story at Slashdot.

msmash