Feed aggregator
UK Cyber Chief Warns Country 'Widely Underestimating' Risks From Cyberattacks
Read more of this story at Slashdot.
India's EV Paradox: Highest Subsidies, Lowest Uptake
Read more of this story at Slashdot.
China Retaliates Over New US Chip Restrictions
Read more of this story at Slashdot.
Australia Struggling With Oversupply of Solar Power
Read more of this story at Slashdot.
CodeSOD: Layered Like Spaghetti
"We use a three tier architecture," said the tech lead on Cristian's new team. "It helps us keep concerns separated."
This statement, as it turned out, was half true. They did divide the application into three tiers- a "database layer", a "business layer", and a "presentation layer". The "database layer" was a bunch of Java classes. The "business layer" was a collection of Servlets. And the "presentation layer" was a pile of JSP files.
What they didn't do, however, was keep the concerns separated.
Here's some code from their database layer:
public synchronized StringBuffer getStocTotGest(String den, String gest) { StringBuffer sb = new StringBuffer("<table width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">" + "<tr bgcolor=\"#999999\">" + "<td>Denumire</td>" + "<td>Cant</td>" + "<td>PretVanz</td>" + "</tr>"); try { ResultSet rs = connectionManager .executeQuery("select (if(length(SUBSTRING(den,1,instr(den,'(')-1))>0,SUBSTRING(den,1,instr(den,'(')-1),den)) as den,um,pret_vinz,sum(stoc) as stoc from stmarfzi_poli where den like '" + den + "%' " + gest + " group by den order by den"); while (rs.next()) { sb.append("<tr><td>" + rs.getString("den") + "</td>"); sb.append("<td><div align=\"right\">" + threeDecimalPlacesFormat.format(rs.getDouble("stoc")) + " " + rs.getString("um") + "</div></td>"); sb.append("<td><div align=\"right\">" + teoDecimalPlacesFormat.format(rs.getDouble("pret_vinz")) + "</div></td></tr>"); } sb.append("</table>"); } catch (Exception ex) { ex.printStackTrace(); } return sb; }I guess a sufficiently motivated programmer can write PHP in any language.
This just has a little bit of everything in it, doesn't it? There's the string-munged HTML generation in the database layer. The HTML is also wrong, as header fields are output with td tags, instead of th. There's the SQL injection vulnerability. There's the more-or-less useless exception handler. It's synchronized even though it's not doing anything thread unsafe. It's truly a thing of beauty, at least if you don't know what beauty is and thing it means something horrible.
This function was used in a few places. It was called from a few servlets in the "business layer", where the resulting StringBuffer was dumped into a session variable so that JSP files could access it. At least, that was for the JSP files which didn't invoke the function themselves- JSP files which mixed all the various layers together.
Cristian's first task in the code base was changing the background colors of all of the rendered table headers. Since, as you can see, they weren't using CSS to make this easy, that involved searching through the entire codebase, in every layer, to find all the places where maybe a table was generated.
Changing those colors was Cristian's first task in the code base. I assume that Cristian is still working on that, and will be working on that for some time to come.
[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!Coinbase Expands Crypto Buying Reach With Apple Pay Integration
Read more of this story at Slashdot.
India Takes Out Giant Nationwide Subscription To 13,000 Journals
Read more of this story at Slashdot.
Mexican Cartels Lure Chemistry Students To Make Fentanyl
Read more of this story at Slashdot.
Nike-owned NFT Wearables Startup RTFKT is Winding Down
Read more of this story at Slashdot.
Company Claims 1,000% Price Hike Drove It From VMware To Open Source Rival
Read more of this story at Slashdot.
The Casual Moviegoer is a Thing of the Past
Read more of this story at Slashdot.
Getty Images CEO Says Content-Scraping AI Groups Use 'Pure Theft' For Profit
Read more of this story at Slashdot.
'Brain Rot' Named Oxford Word of the Year 2024
Read more of this story at Slashdot.
ChatGPT Refuses To Say One Specific Name
Read more of this story at Slashdot.
Employee Lawsuit Accuses Apple of Spying on Its Workers
Read more of this story at Slashdot.
Intel CEO Gelsinger Exits as Chip Pioneer's Turnaround Falters
Read more of this story at Slashdot.
China Extends Dominance Over US in Critical Technology Race
Read more of this story at Slashdot.
Bluesky's Open API Means Anyone Can Scrape Your Data for AI Training. It's All Public
Read more of this story at Slashdot.
Exxon Lobbyist Investigated Over 'Hack-and-Leak' of Environmentalist Emails
Read more of this story at Slashdot.
CodeSOD: A Pair of Loops
Alexandra inherited a codebase that, if we're being kind, could be called "verbose". Individual functions routinely cross into multiple thousands of lines, with the longest single function hitting 4,000 lines of code.
Very little of this is because the problems being solved are complicated, and much more of it is because people don't understand how anything works.
For example, in this C++ code, they have a vector of strings. The goal is to create a map where the keys are the strings from the vector, and the values are more strings, derived from a function call.
Essentially, what they wanted was:
for (std::string val : invec) { umap[val] = lookupValue(val); }This would have been the sane, obvious way to do things. That's not what they did.
unordered_map<string, string> func(vector<string> invec) { unordered_map<string, string> umap; vector<pair<string, string*> idxvec; for(string name : invec) { umap[name] = ""; idxvec.push_back(make_pair(name, &umap[name])); } for(auto thingy : idxvec) { //actual work, including assigning the string thingy.get<1>() = lookupValue(thingy.get<0>()); } return umap; }I won't pick on names here, as they're clearly anonymized. But let's take a look at the approach they used.
They create their map, and then create a new vector- a vector which is a pair<string, string*>- a string and a pointer to a string. Already, I'm confused by why any of this is happening, but let's press on and hope it becomes clear.
We iterate across our input vector, which this I get. Then we create a key in the map and give it an empty string as a value. Then we create a pair out of our key and our pointer to that empty string. That's how we populate our idxvec vector.
Once we've looped across all the values once, we do it again. This time, we pull out those pairs, and set the value at the pointer equal to the string returned by lookup value.
Which leads us all to our favorite letter of the alphabet: WHY?
I don't know. I also am hesitant to comment to much on the memory management and ownership issues here, as with the anonymization, there may be some reference management that got lost. But the fact that we're using bare pointers certainly makes this code more fraught than it needed to be. And, given how complex the STL data structures can be, I think we can also agree that passing around bare pointers to memory inside those structures is a recipe for disaster, even in simple cases like this.
What I really enjoy is that they create a vector of pairs, without ever seeming to understand that a list of pairs is essentially what a map is.
In conclusion: can we at least agree that, from now on, we won't iterate across the same values twice? I think about 15% of WTFs would go away if we all followed that rule.
Oh, wait, no. People who could understand rules like that aren't the ones writing this kind of code. Forget I said anything.
[Advertisement] Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.