The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 4,183 other subscribers

Delphi `with` post and discussion revisited (via: wiert.me and LinkedIn)

Posted by jpluimers on 2014/06/11

A bit more than a year ago, I wrote about Delphi: you should avoid the with statement as it makes your code less future proof. That caused some nice comments on the blog, and some more on LinkedIn where Paul Foster mentioned it in a thread ‘Jeroen Pluimers makes a case against “with” statements.‘ Both interesting reads, especially the reasons that people use or avoid with, or keep its use in balance. There is one set of comments I want to emphasize: refactoring multiple with statements into a one function and a call per former with.

Mark Stolworthy: I think when used simply the code becomes easier to read ?

with pdata do
begin
  DatabaseName := pDB.databasename;
  TableName := 'Xdata';
  readonly:=Preadonly;
  FieldDefs.clear;
  IndexDefs.clear;
end;

with pitem do
begin
  DatabaseName := pDB.databasename;
  TableName := 'Xitem';
  readonly:=Preadonly;
  FieldDefs.clear;
  Indexdefs.clear;
end;

I disagree with code like that, as it is very easily refactored into something like this:

Jeroen Pluimers • @Mark, Your code should be refactored to use a method, similar to the example at https://wiert.me/2013/03/27/delphi-you-should-avoid-the-with-statement-as-it-makes-your-code-less-future-proof/#comment-17355 Also if this is from production code, you should use code-completion to make sure the casing of the members is correct.

Initialize(PData, pDB, 'Xdata', PReadOnly);
Initialize(PItem, pDB, 'Xitem', PReadOnly);

procedure TMyClass.Initialize(MyDataSet: TMyDataSet; MyDataBase: TMyDatabase; string TableName; ReadOnly: Boolean);
begin
  MyDataSet.DatabaseName := MyDataBase.DataBaseName;
  MyDataSet.TableName := TableName;
  MyDataSet.ReadOnly := ReadOnly;
  MyDataSet.FieldDefs.Clear();
  MyDataSet.IndexDefs.Clear();
end;

–jeroen

PS: funny to see I officially hate hate hate the WITH statement got posted this week too, as my post above had been in the blog queue more than a year ago: since 20130505 (:

19 Responses to “Delphi `with` post and discussion revisited (via: wiert.me and LinkedIn)”

  1. EMB said

    >>PS: funny to see I officially hate hate hate the WITH statement got posted this week too, as my post above had been in the
    >> blog queue more than a year ago: since 20130505 (:

    #RaymondChenFeelings

    (:

  2. AgoraC said

    ‘Eliminate With’ refactoring. Vote, please!
    http://qc.embarcadero.com/wc/qcmain.aspx?d=30536

    • jpluimers said

      ModelMaker Code Explorer has had such a refactoring for a long while.

      It is awesome, as it makes it way easier to get rid of those risky `with` situations.

  3. Joseph G. Mitzen said

    Where did you learn to write such beautiful code? Elegant, expressive, clear, readable code and APIs hav never really been a part of Delphi culture (or at least it’s been drowned out by a focus on micro-optimizations). You, on the other hand, seem to value readability very much. Arnaud of Mormot framework fame has a talent and focus on thorough, clear and explanatory documentation, something that let’s just say EMBT doesn’t set a good example for. I think the two of you should do some joint CodeRage sessions on expressive, readable code and documentation. :-)

    The only thing that could make your example above nicer would be if Delphi had named parameters.

    • sglienke said

      I don’t share your euphoria about that code as it contains a clear LoD violation. Why pass the TMyDatabase if all you need is the DataBaseName. That certainly is not a clean API. It rather created unnecessary coupling.

      • Kmorwath said

        Sure, so whenever you need a change and need to use something also in TDatabase you break the interface…., beware of Demeter sometimes it works against you – if you don’t have a clear overall design of your classes and can’t predict well future evolutions…

      • sglienke said

        Yeah, let’s pass in everything so we are have the maximum flexibility. And when I need another property from TDatabase I can just grab it. If I need another property then I pass it also. Or I write an overload for the routine. There is something called refactoring and it’s not evil.

      • KMorwath said

        I start to imagine your code, functions with an ever increasing number of parameters, used only once, and refactored all the time… encapsulate into a class just to blow it up everytime and pass it piece by piece to a function…

  4. I keep saying over the years: “with” is as dangerous as “uses”.

    • jpluimers said

      Not sure if they’re on the same level (:

    • sglienke said

      Introducing a new member can change behavior because *with* causes a closer scope on the variable you use it on than local variables and method arguments have (TRect anyone?). Changing a unit in the uses clause might also introduce or hide a symbol on a previously used unit but less likely.

  5. KMorwath said

    If you use it more than once, it could be a good idea refactoring it into a function. If you use it just once, moving it to a function may “hide” what the code actually does, and require some “code navigation” to get there. Frankly, I do not understand why so many people hate “with”. Is like being able to disable ABS in a car or AF in a camera. Sure, you better keep them enable 95% of time, but there that 5% of cases where you need to go the “dangerous” route to easily achieve what you need and in a faster way. No one force you to use “with”, thereby what’s the real problem? Think about adding more power to Delphi, not neutering it to get a simpler language so noobs can’t fire in their feet…

    • sglienke said

      Your argumentation is flawed. Why do people always try to defend something that is bad in 95% or 99% of the cases just because it *might* be useful in the 1% or 5% rest of the cases. And that is still arguable. Oh yeah with saves you writing some letters, big deal. There is no actual functionality that it provides. And those who really find with being useful write such fugly code (law of demeter anyone?) that the with is one of the least of their problems to be honest.

      • Kmorwath said

        I didn’t said bad. Just “unsafer”, “riskier”. Because in the other 5% is very useful. Law of Demeter should be called “Demeter advice” – especially since it lacks any kind of proof to be a “law”. You guys take OO in a Taliban way, and risk to make Delphi look like Java…
        Most UI frameworks break Demeter Advice often because it would make very little sense to code them another way, when *there is* a strong hierarchy and interrelationship among elements. No actual functionality? If the compiler is well written, it can be an hint to the compiler it can keep a reference in some fast access location instead of reloading it over an over. But of course you prefer to setup a whole function call and return to achieve the same functionality…
        And those really obsessed by with should have code with big issues, if they need to find something in the language to yell at continuously, instead of simply ignoring it and coding as they like.

      • sglienke said

        If it’s for more understanding and empathy how to write clean, testable and maintainable code – then yes, a bit more Java or C# flavor would not hurt Delphi. But I guess people are just seeing black and white and when someone says Java, they think about some huge and horribly over-engineered “enterprise” software.
        Also in fact I am not taking OO in a Taliban way because my coworkers and people that are actually trying out advices(!) I am giving and giving me feedback are a proof that it leads to better code.
        A function call and clean structured reusable code over spaghetti code that might use a few CPU instructions less. Sounds like a good deal. Or are we stuck in 1980 or what?

      • sglienke said

        I just did a quick test and it turned out the with was not optimized at all. Having a routine with 4 parameters (first was the object to set the properties on and the other 3 were the values) declared as inline was equally if not faster.

      • KMorwath said

        Both Java and C# would need a bit of Delphi flavour, not vice-versa, it would be less painful to open one of those applications, but it explain why C++ is again the preferred language at many levels. The only one stuck in 1990 is you, still believing that OOP is something performed following blindfully laws with “arcane” names for the initiated without actually understanding what they really are and what actual software is and does. I already wrote that if a function is used more than *once* it perfectly makes sense. But littering the code with a large number of functions – probably with an ever increasing number of parameters – used exactly *once* just to set more than one field in a fragment of code looks pretty close to spaghetti code and overengineering to me. Functions can be inlined, but not always. But I understand some prefer to write “good looking code” instead of “good code” – they are not exactly the same.
        If the Delphi compiler is unable to optimize a with statement is just an example of the shameful state of the compiler. Anyway, again, if you don’t like with don’t use it, no one force it. It looks that supporting with makes Delphi something alike a devil’s language, really what’s your problem? You feel compelled to use it because you like it but then think it’s something alike an eternal damnation if you do, and you’ll be expelled from the OOParadise, more or like Eve’s Apple? Switch to Java or C#, and you’ll be safe, c’mon!

    • Joseph G. Mitzen said

      Ken, people hate with because what one gains does not offset what one potentially loses. I don’t have the link in front of me, but there’s a blog post in which the author relates using an object from a 3rd party library with a “with” statement. The object did not have x or y properties, so there was no problem using local x and y variables and referring to them in the “with”. What happened is that they upgraded to a new version of the library and unbeknownst to the author the new version of the object gained “x” and “y” properties. Now they were being set inside the “with” statement instead of of the local variables. With nothing having changed in their own code, the effects this produced were mystifying and took hours to track down. The author concluded with a new, passionate hate for the “with” statement.

      And that’s it in a nutshell. Other languages have specifically evaluated and rejected a “with” statement for this reason – the chance to introduce bugs with only a little syntactic sugar to gain.

      For a similar hated “feature”, think of C’s ability to assign a value inside the condition statement of a “while” loop:

      while (x = 10) instead of while (x == 10)

      One simple typo of omitting the extra = and now your loop is going to change a value and always evaluate to true. Meanwhile, there’s basically no sane reason to ever want to assign to a variable where there should be a condition. Essentially no benefit on the upside and potential for unobvious bugs on the downside. I was bit by this one myself when studying C in school and neither of the two people I showed my code to could spot the error either. When I found it I began a long rant about C compared to the virtues of Pascal in the computer lab. :-)

      All these years later I still remember that useless “power” doesn’t make up for the very real chance of hard-to-locate bugs.

      >No one force you to use “with”, thereby what’s the real problem?

      No man is an island. We’ll need to use and read the code of someone else who uses “with”.

      >Think about adding more power to Delphi

      “With” isn’t power. “With” is a tiny drop of syntactic sugar. Whenever people think about *really* adding power to Delphi the Old Guard screams “You’re trying to turn Delphi into C#/C++/D/Swift/Python!”

      > not neutering it to get a simpler language so noobs can’t fire in their feet…

      Simpler is generally better. “With” doesn’t simplify anything but adds the possibility to cause hidden problems. A vast amount of computer science effort has been in the realm of attempting to prove correctness in programs (even some of Wirth’s later work). Eliminating the chance of uncaught errors is one of the Holy Grails of computer science. There are books published now with titles like “C++: The Good Parts” and companies are restricting their developers to only use certain parts of the language. Some analysts have called the verbosity of Java “unsustainable” and suggest the same thing will happen to it shortly. Anything added to a language needs to justify itself by what it adds. Apple modernized Objective-C not by making it more complex, but less so. You don’t need to be a noob to shoot yourself in the foot. If you think that’s the case, go try programming in Brainf*ck for awhile. :-)

  6. sglienke said

    No need to define it as a method in your class because that will make it un-reusable in other classes. I would either make a standalone routine or a class helper.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: