Delphi, methods and default values. Convenience or contract enforcement?

Delphi, methods and default values.

Being somewhat unique in methods declaration for the classes, Delphi requires you to have proper method parameters declaration, but:

  1. You do not have to have any default values for the parameters being propagated into implementation section for the method.
  2. And you do not have to have any parameters being specified in implementation section at all.
  3. If your class implements an interface, then while order and type of parameters remain unchanged for the interface method implemented, compiler would not not even detect it.
  4. When declaring the method and then using code complete feature of the IDE, stub generated would have all parameters but no default values.
  5. Declaration of the parameters could be “optimized” by changing the way they are grouped if they are of the same type. And sync is not enforced between declaration and implementation.

Convenient. Nice. Easy.

Again, it is convenient since it does not force you to propagate your changes between two if you are to change your default values.

Is default value good or evil?

Well, Microsoft saying it is specific to an implementation of the language (C#) and suggests to use overloads instead. Yes, it can be done, but defaults were introduced for a reason. And, in fact, some compilers, even Delphi, would be confused with overloaded declaration if there is a slight chance of mixing two.

Back in 2005, dflat wrote:

Disadvantage:
1. A bit tedious to call, because even if you don’t put any actual parameters, you have to write down all the types.

Advantages:
1. Unlike C++ default params, this allows all combinations
2. No signature conflict or ambiguity. The whole signature is matched when calling a method with default parameters, because type must be specified if the parameter is missing.
3. No run-time overhead, because everything can be determined at compile time.

Feasibility. I don’t think it’s difficult to implement (in later version of  C#) because:
1. No additional key word is introduced. “default” is already a key word in C#
2. No ambiguity. It doesn’t conflict with any existing C# language semantics

I may sound old fashioned, but I prefer propagate declaration of the method into implementation, because:

  1. if for any reason you have to move things around the code, it is convenient to be able grab implemtation of the methoid and easily reusing it in declaration of another class.
  2. while reading the code, be able to see exact calling contract for the function you are investigating without a need to jump between declaration and implemtation.
  3. also having it in sync, force you to review the code when any default values are changed and if you are using something like XMLDoc/JavaDoc/PasDoc, compiler will force you review your method documentation.

Yes, it “breaks” a “Dry code” principle. But it is not more of “dryness” with that approach then not having any parameters in implemtation section of the method. And while it “polutes” the code, it adds more self-documenting and readability to it.

What are yours points “for” and “against” default parameters and use of them?

This entry was posted in Delphi, Technology and tagged , , , , . Bookmark the permalink.

6 thoughts on “Delphi, methods and default values. Convenience or contract enforcement?”

  1. naf says:

    This would all be moot if Delphi was intelligent enough to automatically synchronize the interface and implementation sections (including comments and defaults).

    It would probably require less than 1000 manhours on CodeGears end and would save twenty million hours in lost productivity each year (conservatively based on 1,000,000 Delphi users saving five minutes each day). I doubt there is any single change CodeGear could make that would offer that kind of productivity return.

    I’m amazed more Delphi users are not annoyed by this blatant contradiction of DRY and shocked that CodeGear have not addressed this remnant of 1980’s programming.

  2. I think number of spent hours by programmers is much less. Contract once established could be only changed during a new development cycle.
    I am not sure though if you are being sarcastic or serious. 🙂 I liked your Delphi 2010 proposal in the past.

    I have decided to bring up the subject because of small debate I have few days ago which then lead to “old” C# discussion and Delphi comparison.

    Now, would it be good to have an option for synchronization between declaration and implementation? Yes, and there is number of IDE extensions which allow to do just that – be able introduce a new or modify parameters and having code synchronized accordingly.

  3. Brian says:

    Newer Delphi IDEs have change parameters as a refactoring tool. On the name for a method press CTRL-SHIFT-X. Or right click and select Refactoring, change parameters.

    I do miss CodeRush’s delcaration view that I had in Delphi 6 which would show me the declaration and/or implementation for the method I was tryinig to call.

  4. Ops! Yes, you are right about that, except that refactoring in Delphi today is a little bit too much. To compare, you can look at implementation in Refactor! by Developer Express.

  5. Fabricio says:

    (the blog engine eat the comments)
    Serge,

    [Defaul Parameter vs Overload – not comment the syncronizing]
    For me, they different tools for different needs:
    Default parameters –
    Need: hide optional parameters
    Advantages: does not add any implementation code.

    Overloading
    Need: type translator/cruncher. When you need the class method
    to work with new datatypes or simplifying the use of the
    existing functionality. Lets do some pseudocode: class A
    is a list of
    objects of the class b. Class B have the following
    properties: Name, Cost, Distance. With overloading you do:
    (*…*)
    function Add(pClassObj: TClassB):Integer; overload;
    function Add(pName:String; pCost:Currency;
    pDistance: Integer):Integer;
    (*..Implementation..*)
    function TClassA.Add(pClassObj:TClassB):Integer;
    begin
    (* do some house keeping and *)
    Result := inherited AddObject(pClassObj.Name,pClassObj);
    end;

    function TClassA.Add(pName:String; pCost:Currency;
    pDistance: Integer):Integer;
    var
    Aux:TClassB;
    begin
    Aux := TClassB.Create;
    (* Set the properties with the parameter values *)
    Result := Add(Aux);
    end;

    Advantage:
    It’s obvious in the above example that overloading gave
    result to cleaner and readable code.

    [About the syncronization of the declarations
    in interface and implementation sections of a unit]
    It’s ooooooooooooooooooold bug in Delphi.

  6. Yosh says:

    I waiting of delphi 64bit

Leave a Reply