Evaluate replacing all usage of sprintf by dot concatenation or variable inside string

Created on 10 March 2020, almost 5 years ago
Updated 15 November 2023, about 1 year ago

Problem/Motivation

sprintf() does not add value over using a double-quoted string for scenarios like test assertions and exception messages, where no data type conversion or sanitization is needed, and it generally decreases readability. Compare:

  1. "A string with $bar, {$foo['a']}, $baz, $a and $c, plus also $b embedded";
    
  2. sprintf('A string with %s, %s, %s, %s and %s, plus also %s embedded', $bar, {$foo['a']}, $baz, $a, $c, $b);
    

Proposed resolution

  1. Where possible, use a pure string literal with a fixed test value in test assertions (rather than defining random names for test data). E.g:
    $session->assertWhatever("This is test data we're asserting for article1 with term2 or whatever");
    
  2. If variables must be used (or as an intermediate step between removing excess function calls and removing random fixture values), use a double-quoted string:
    $session->assertWhatever("This is test data we're asserting for $article1 with {$term2['name']} or whatever");
    
  3. As a last resort, use string concatenation or additional local variables. Avoid adding sprintf(), t(), FormattableMarkup(), etc. to either test assertions or exception messages.
  4. Maybe: Only consider sprintf() for deeply nested array structures or method calls.

References

πŸ“Œ Task
Status

Active

Version

11.0

Component
OtherΒ  β†’

Last updated 2 days ago

Created by

πŸ‡¨πŸ‡¦Canada xmacinfo Canada

Live updates comments and jobs are added and updated live.
  • Performance

    It affects performance. It is often combined with the Needs profiling tag.

  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States xjm

    I think the hypothesized performance aspect of this is needless micro-optimization. (That said, the addition to the call stack is unnecessary.)

    The reason not to use sprintf() -- and the reason we've avoided it historically -- is that it adds absolutely no value over simply using a double-quoted string. Compare:

    1. "A string with $bar, {$foo['a']}, $baz, $a and $c, plus also $b embedded";
      
    2. sprintf("A string with %s, %s, %s, %s and %s, plus also %s embedded", $bar, {$foo['a']}, $baz, $a, $c, $b);
      

    The first is much closer to natural language. The second is significantly longer and les readable, plus it's easy to lose track of which %s refers to what.

    The only debatable case is if something requires concatenation (e.g. a function call is used), and even then, I find sprintf() makes it less readable. In those cases, defining a local variable with the function call (and thus avoiding concatenation in favor of something that reads like natural language) is probably a more desirable alternative than either concatenation or sprintf().

  • πŸ‡ΊπŸ‡ΈUnited States xjm

    Updated the IS to de-emphasize the micro-optimization in favor of the readability aspects.

  • πŸ‡ΊπŸ‡ΈUnited States xjm

    Fixing typos in the IS.

  • πŸ‡¦πŸ‡ΊAustralia mstrelan

    I've been looking for a rector rule or phpcs sniff for this but can only find the inverse.

    Whereas phpstorm has the Convert a 'sprintf()' call to string interpolation intention.

    For implementation it would be good to find a way to automate this.

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    The simple cases with bare variable names in #13 are fine for interpolation, but when it comes to interpolating the results of method calls or deep array structures I personally prefer the sprintf style.

    To me there is no single best option here and we should have some flexibility on this, and therefore I think this is won't fix.

  • πŸ‡ΊπŸ‡ΈUnited States xjm

    I added a case 4 for #17, but I really think we should discourage people from using it when it reduces readability (which is most of the time). People use it for antiquated reasons that don't apply for test assertions or exception messages.

  • πŸ‡ΊπŸ‡ΈUnited States xjm
  • πŸ‡¦πŸ‡ΊAustralia acbramley

    We always use sprintf on internal projects, I find it more readable in most cases (when you only have 1 or 2 variables). I agree that the example in the IS is slightly more readable with embedded variables but I agree with #17 that this shouldn't be hard enforced.

  • πŸ‡§πŸ‡¬Bulgaria pfrenssen Sofia

    I vote for won't fix. We shouldn't gatekeep functions from the standard library.

  • πŸ‡ΊπŸ‡ΈUnited States xjm

    We "gatekeep" functional PHP code all the time; that's what coding standards are.

    Regarding performance, https://git.drupalcode.org/project/drupal/-/merge_requests/5166/diffs has a comment contradicting the above.

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    Moving this to the coding standards project where decisions about policies/standards like this live.

    Tagging for needing issue summary update as there is a prescribed format for coding standards issues β†’

    My 2c, simple variables should use pure string literals with variables as required (ie "Something $wicked this {$way['comes']}") and sprintf if there are expressions or functions sprintf('Something %s this way %s, $wicked, $way->comes())

Production build 0.71.5 2024