Delphi - Ad in class or not?

More recently, perhaps because I was supporting some old code, I began to look at how / why I was doing something. How do you do it.

Most of my Delphi programming was done in-house or with examples scattered across networks or manuals. And in some cases, this is done only because "the way I do it"

What I am asking now is the declaration of variables, procedures, functions, etc.

When I work with a form, I put all my procedures and functions in the public or private . Although I will try to avoid global wars, and the constants will usually be under var or const , either in the interface or in the implementation, depending on where they should be called (sometimes they will be publicly / closed)

Otherwise, if its just a unit, I will declare the procedure in the interface and use it in the implementation. Some of the code that I have been supporting lately do not have an interface declaration, but instead have all correctly ordered calls after the procedures ...

Is there a proper way to do this? Are there rules for what should / should not go in a class? Or is it a style / when did you start the business?

Edit to add

My question is not whether the procedure declaration is private / public, but whether all declarations in TForm Unit must go in one of them. Similarly, if var / const will be in one or the other?

Further refinement

I understand that not a declaration in the interface or a declaration in public / private / etc affects the visibility of procedures / functions for other units in my application.
The core of my question is: why do not I want to announce? - especially when working in uniform / unit when placed in private, it is much more clear that the claimed item is not available for other units ...

Cheers Dan

+4
source share
2 answers

The question seems to relate to the scope. In other words, how easily accessible things can or should be.

As a general guide, you want to reduce the amount of things as much as possible, but still keep them accessible enough for reuse. The reason for this is:

  • that as your system grows and becomes more complex, things that have a wider reach become more accessible.
  • as a result, they are more likely to be reused in an uncontrolled manner.
  • (sounds great), but the problem arises when you want to make changes, and many things use what you want to change ...
  • it becomes much harder to make your changes without breaking something else.

Having said that, there is also a difference between data (variables, constants, class fields, record attributes) and subprograms (functions, procedures, methods on classes). You will want to apply the recommendations much more strictly to the data, since the “strange use” of the data can interfere with some of your routines in extremely unexpected and difficult to debug ways.

Another thing to consider is the particular difference between global variables and class fields or record attributes:

  • using global variables, there is only one 'value (the term is used freely) for the entire application.
  • Using class fields or record attributes, each new instance of a class or record has its own values ​​independent of other instances.
  • This seems to imply that you can use some form of global when your application needs only one. However, as mentioned earlier, this is not the only reason to avoid global change.
    • Personally, I am even inclined to avoid global procedures.
    • I often find that things that seemed to be declared global are not as universal as the first thought. (For example, Delphi VCL declares a global Screen object, I work on 2 screens, and many of our clients use 4 to 6.)
    • I also find it useful to associate routines that could be global with specific classes as class methods. This usually simplifies the code.

Thus, listing these “locations” from the largest region to the smallest, you would tend to choose the places below in the list (especially for data).

  • global interface
  • global implementation
  • threadvar interface
  • threadvar implementation
  • published (note that I really do not consider this an identifier for scope, it is really public, and includes RTTI information "- it would theoretically be useful to mark some private attributes as" include RTTI ".)
  • the public
  • protected
  • private
  • strict private
  • Local variable

I must confess: what I presented here is certainly an oversimplification. Knowing goals is one thing, and realizing them is another. There is a principle of balancing between encapsulation (hiding things) and identifying controlled interfaces to achieve a high level of reuse.

Methods for successfully balancing these needs fall into the category of much more complex (and sometimes even controversial) issues in system design. A poor design is likely to prompt it to “too much” with a “too large” scale and (perhaps paradoxically) also reduce reuse.

+4
source

Everything that may have a different meaning depending on the particular instance belongs to the class, i.e.

 TDog = class strict private FColor : TColor; FName : String; public property Color : TColor read FColor write FColor; property Name : String read FName write FName; end; 

Color and name are clearly attributes of each dog (and each dog will have different meanings here).

General rules:

  • Fields belong to private (visible in this class and in this module) or strict private (visible only in this class)
  • If you need access to fields from other classes, create a public property. This gives you the freedom to change easy access to the more complex getter / setter method without changing the interface of your class.
  • Everything should be as local as possible. If private enough, there is no need to make it protected (apparently also in subclasses). And just do those public things that you really need outside.
  • Forms: only the things you want to save in the DFM file should be published .
  • Put as much as possible in the implementation section and as little as possible in the interface section. This is true for uses clauses.

You may be confusing the term global variable. If it is declared in a class, it is not a global variable (even if public declared). Global variables (which you correctly consider appropriate) always go to the var section either in the interface or in the implementation section (which is preferable to the following general rules)

+6
source

Source: https://habr.com/ru/post/1299112/


All Articles