Author Topic: Short but Sweet Daily WTF #1  (Read 178 times)

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 1928
    • LairWorks Entertainment
Short but Sweet Daily WTF #1
« on: August 28, 2018, 05:45:34 PM »
Browsing The Daily WTF and came across this article with the following code snippet:

Code: [Select]
public String getUsername(String username)
{
    return username;
}
- Leeor
LairWorks Entertainment

Titanum UFO's

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4439
Re: Short but Sweet Daily WTF #1
« Reply #1 on: August 28, 2018, 10:35:38 PM »
Lol.

I was a little code blind to that one at first. Didn't notice the function parameter until it was pointed out.

That makes for a pretty useless function. Useless and misleading.

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 1928
    • LairWorks Entertainment
Re: Short but Sweet Daily WTF #1
« Reply #2 on: August 29, 2018, 04:01:51 PM »
Not knowing the full history of that code snippet (never described in the article) and without any documentation comments, I can only assume that the function did more than just return the username and over time was simplified but instead of modifying tons and tons and tons of code to remove the function call they just had it return itself.

Just a guess, of course... like it could have done something like sanitizing/normalizing the username in some way.
- Leeor
LairWorks Entertainment

Titanum UFO's

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 696
Re: Short but Sweet Daily WTF #1
« Reply #3 on: August 29, 2018, 07:51:23 PM »
This could be code from someone who does rigid unit testing. You are supposed to only write enough code to get your test passing before writing the next test. So if there first test was making sure that a username of "username" was returned, this might fit the bill. Of course they should then write another test that forces the function to be re-written into something more useful.

Well, what am I saying, there isn't enough context to really say anything for sure.

-Brett

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 1928
    • LairWorks Entertainment
Re: Short but Sweet Daily WTF #1
« Reply #4 on: August 29, 2018, 08:24:28 PM »
Yup.

It's still a head-scratcher moment... you look at it and you're just aghast and bewildered at what possessed someone to write such a useless function.
- Leeor
LairWorks Entertainment

Titanum UFO's

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4439
Re: Short but Sweet Daily WTF #1
« Reply #5 on: August 29, 2018, 10:06:47 PM »
Oh come now, it's just a badly named identity function.  ;)

Identity functions have uses. Namely eliminating null checks when you have no function transformation to perform. Rather than conditionally call a function through a pointer after first checking if the function pointer is not null, you can instead unconditionally call a function through a pointer that defaults to the identity function.

Really, it should be transformUsernameDefault or transformUsernameIdentity. ;)

Offline Crow!

  • Newbie
  • *
  • Posts: 12
Re: Short but Sweet Daily WTF #1
« Reply #6 on: August 30, 2018, 11:20:42 AM »
My guess would be that the program needs to grab a Username from a variety of sources, and is making one overloaded function name to do it.  I'd expect to also find getUsername(ClientClass user), getUsername(DataClassAttributedToAParticularUser data), etc. in the same scope in that case.
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 1928
    • LairWorks Entertainment
Re: Short but Sweet Daily WTF #1
« Reply #7 on: August 30, 2018, 06:55:17 PM »
Right, but I think you missed the WTF of it returning the value that was passed in. So the calling code would look something like:

Code: [Select]
String _un = getUsername("whatever");

Which is literally equivalent to:

Code: [Select]
String _un = "whatever";
« Last Edit: August 30, 2018, 07:13:15 PM by leeor_net »
- Leeor
LairWorks Entertainment

Titanum UFO's

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4439
Re: Short but Sweet Daily WTF #1
« Reply #8 on: August 30, 2018, 11:33:20 PM »
Right, the identity function is just a dummy adapter for the simple degenerate case.

Generate a report, given any one of the following data sources:
Code: cpp [Select]

AccountingDataSource companyExpenseList; /* { currency amount, std::string expenseIncurredBy; std::string paidTo; } */
SantasNaughtyOrNiceList santasList; /* { std::string kidName; bool naughty; } I was good! I swear! */
HitList hitList; /* { std::string name; } A name is all you need to know */


Without adapters:
Code: cpp [Select]

void GenerateReport(DataSource& dataSource) {
  ...
  for (auto& row : dataSource) {
    std::string userName = "";
    if (accountingRow = dynamic_cast<AccountingRow&>(row)) {
      userName = accountingRow.expenseIncurredBy;
    } else if (naughtyInfo = dynamic_cast<NaughtInfo&>(row)) {
      userName = naughtyInfo.kidName;
    } else if (name = dynamic_cast<String&>(row)) {
      userName = name;
    }
    ...
  }
  ...
}

GenerateReport(oneOfTheDataSources);


With adapters, but lacking identity:
Code: cpp [Select]

void BuildReport(DataSource& dataSource, UsernameFn* getUserName) {
  ...
  for (auto& row : dataSource) {
    auto userName = getUserName(row);
    std::string userName = "";
    if (getUserName != null) {
      userName = getUserName(row)
    } else {
      userName = row; /* Data consists of just a name */
    }
    ...
  }
  ...
}

std::string accountingExpenseUserName(AccountingRow& row) { return row.expenseIncurredBy; }
std::string accountingPaidToUserName(AccountingRow& row) { return row.paidTo; }

GenerateReport(companyExpenseList, accountingExpenseUserName);
GenerateReport(companyExpenseList, accountingPaidToUserName);  /* Can choose alternate fields, not based solely on type */
GenerateReport(hitList, null); /* Not much adapting to do here. You have what you need. */


With adapters, and identity function:
Code: cpp [Select]

void BuildReport(DataSource& dataSource, UsernameFn* getUserName) {
  ...
  for (auto& row : dataSource) {
    auto userName = getUserName(row);
    ...
  }
  ...
}

std::string accountingExpenseUserName(AccountingRow& row) { return row.expenseIncurredBy; }
std::string accountingPaidToUserName(AccountingRow& row) { return row.paidTo; }
std::string identityFunction(std::string name) { return name; }

GenerateReport(companyExpenseList, accountingExpenseUserName);
GenerateReport(companyExpenseList, accountingPaidToUserName);  /* Can choose alternate fields, not based solely on type */
GenerateReport(hitList, identityFunction); /* Not much adapting to do here. You have what you need. */


You'll notice the hitman isn't too picky about the identity function. ;)
« Last Edit: August 30, 2018, 11:42:20 PM by Hooman »