Recent

Author Topic: Naming conventions for libraries and 3rd party units - prefixing names  (Read 769 times)

SuperSathanas

  • New Member
  • *
  • Posts: 16
I've done some searching around here and through several Google searches, and I'm not really seeing an answer to my question, so here we go...

Is there any sort of accepted/expected naming conventions specifically for libraries or just 3rd party units in general, insofar as naming them in such a way that they are easily identified as being from those units? I don't mean things like prefixing type names with "T" or the intended usage of "Get", "Set", "Do" and whatnot. I'm talking about how in the BaseUnix unit, most functions are prefixed with "fp", although I get the feeling that the only reason some of these units that ship with FPC that have use this kind of naming is because they are based on or translated from equivalent C headers that used the same or similar prefixing.

As an example of what I mean, for my own units that I've written for my own purposes, their names are prefixed with "gem" (gemutil, gemimage, gemaudio, gemtypes, gemmath, etc...), and the types, constants, global variables and functions inside them are also prefixed with "gem" or some variant in some way.

TGEM* for types (TGEMOpenGLWindow, TGEMDirectory)
gem* for global functions/procedures (gemAngle(), gemNormalizeGain())
GEM_* for constants (GEM_EXEPATH, GEM_RED_F)

I do this primarily so that I can identify what is coming from my own units, and also avoid naming conflicts (System.Move and ncurses.move come to mind). My naming style is pretty C-like, I like to think, simply because I learned my conventions from C and C++ before ever touching Pascal, and Pascal is pretty C-like itself in many ways.

I have a lot of units I've written to do things I couldn't find other units for, or to otherwise do them in a way that made more sense for some use cases, and I've been considering cleaning many of them up and putting them out there, on offer to whoever might happen across them and want to use them. I'd like them to be as user friendly as far as naming and coherency goes, though, before I do that.

Edit: I guess I should also ask if there are any good reasons to not name things this way. I could just not and then I or some hypothetical user could just unitname.function, but then in my head that still leaves the possibility of using the wrong function from the wrong unit, and also makes the code look inconsistent, specifying unit names in some places but not others. Maybe that's just one of my personal hang ups, what with being used to C++ namespaces (std::function, glm::vec3, etc...).
« Last Edit: May 21, 2024, 04:36:45 pm by SuperSathanas »

440bx

  • Hero Member
  • *****
  • Posts: 4212
Is there any sort of accepted/expected naming conventions specifically for libraries or just 3rd party units in general, insofar as naming them in such a way that they are easily identified as being from those units?
Not that I'm aware of.

I've seen some libraries prefix their function names in some way and, in general, I find it helpful for the reasons you mentioned but, I've never seen any standards or guidelines about why and how they should (or shouldn't) be prefixed.

Personally, I am a firm believer of prefixing just about everything under the editor (editor = sun of code.) I normally prefix every record field and find that it really clarifies and simplifies code but, it obviously isn't a standard (at least not one I've seen anywhere.)  I prefix function and procedure parameters with their disposition, e.g, if a parameter is input (must have a value) then it is InParameterName, if it is in and out then InoutParameterName and so on.  Makes differentiating parameters from local variables very easy (MS annotates parameter names with SAL but does not prefix them with the disposition, instead they may still use the "hungarian" thing which I find extremely poor, deficient and less than useless.)

The only identifiers I don't prefix are local variables and that "gives them away" as local variables because everything else is prefixed. 

No standards that I know of for any of this stuff. 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

SuperSathanas

  • New Member
  • *
  • Posts: 16
I've never felt the need to prefix or otherwise identify parameters in order to communicate their usage, probably because I've always had the luxury of IDEs with hinting and tooltips that give you the function declaration as you're filling them in. If I see var, out, constref, etc... in the declaration, then I can pretty well deduce what the function wants and whether or not it may modify the data I pass it. The only real exception is for when I want a function to be passed as a variable parameter a pointer or something else that may be both read and modified. Usually this means it may be a buffer of some sort, or the function might be sanitizing the contents of whatever is passed to it, so it needs to have its original data (so no out declaration), but also be able to modify the thing. So I can do something like

Code: Pascal  [Select][+][-]
  1. procedure gemSanitizeThing(var aInOutThing: PByte);
  2.  

instead of something more clumsy like

Code: Pascal  [Select][+][-]
  1. function gemSanitizeThing(const aThing: PByte): PByte;
  2.  
  3. thing := gemSanitizeThing(Thing);
  4.  

But then if it doesn't hurt consistency or affect performance too much, I might just decide to create a type for the things that might need that sanitization, and either have properties with write functions that automatically sanitize when the thing is written to, or provide a method for the user to call. Whatever makes things easy to understand and/or keeps consistent with the rest of the code.

440bx

  • Hero Member
  • *****
  • Posts: 4212
I've never felt the need to prefix or otherwise identify parameters in order to communicate their usage, probably because I've always had the luxury of IDEs with hinting and tooltips that give you the function declaration as you're filling them in.
I understand that.  Prefixing the parameters with their disposition, in addition to stating how they are used, it also identifies them as parameters.  Consider seeing code like this: Somename := Anidentifier * 2 div AnotherIdentifier.  That doesn't say anything about what those identifiers are but, instead seeing code like this:  InoutSomename := Anidentifier * 2 div InAnotherIdentifier.

Now, there is a lot of information in that statement.  First there is a side effect, a parameter passed by reference (Inout) is being modified, therefore that value will "float up" when the function/procedure returns.  Anidentifier is a local variable (because of its lack of prefix), InAnotherIdentifier is another parameter (because of the In prefix) but one whose value(s) will vanish once the function/procedure returns (it's not out.)

IMO, any convention that makes the code easier to understand/follow is likely to be a good thing to indulge into.  That said, for throw away code, I can be rather cavalier.

I guess the lack of standards is partially due to the personal nature of writing code.  It's a bit like painting. 

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Bitbeisser

  • New Member
  • *
  • Posts: 33
I think that there are far too many possible ways to handle this to cover this in one all-encompassing standard.
I name variables/procedures/functions/methods the way it makes sense in the context (program/unit/object) they are written in.
If there is an ambiguity (as I tried to show in another thread), I will always prefix it with the unit/object name. This is the safest and IMHO most logical way to do it. I don't care if this is more to type, but it helps to write readable, understandable and thus maintainable code...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11567
  • FPC developer.
I've done some searching around here and through several Google searches, and I'm not really seeing an answer to my question, so here we go...

Is there any sort of accepted/expected naming conventions specifically for libraries or just 3rd party units in general, insofar as naming them in such a way that they are easily identified as being from those units? I don't mean things like prefixing type names with "T" or the intended usage of "Get", "Set", "Do" and whatnot.

That is roughly the Delphi/Borland style guide for Object Pascal. E.g. Pascal in general has a unified namespace for all symbols, types, functions, constants etc, so it is a good habit to prefix types with  "T" , to leave the core identifier free for use as variable or fieldname.

Quote
I'm talking about how in the BaseUnix unit, most functions are prefixed with "fp", although I get the feeling that the only reason some of these units that ship with FPC that have use this kind of naming is because they are based on or translated from equivalent C headers that used the same or similar prefixing.

That and the socket unit is something different. The main reason is that there are many POSIX names that are reserved identifiers or core library functions (read, write, close), and many were very generic words (like wait and send() that are also very  common)

In an older Linux interface, only some of those were escaped, and it constant caused questions and confusion, so it was decided to prefix in the new environment to get rid of that, and have a consistent prefixing.

Posix, Unix_ and Unx_ were rejected (Posix is wrong as Pascal won't interpret C headers, so Posix source compatibily isn't guaranteed the same way it is on C). APIs like the sockets unit are not Unix only, and Unix is a trademark. So in the end a short prefix was chosen. "fp" without hyphen. I think it originally meant "FreePascal Posix", but I'm not entirely sure anymore. (I favored unx_ back then)

Quote
I do this primarily so that I can identify what is coming from my own units, and also avoid naming conflicts (System.Move and ncurses.move come to mind). My naming style is pretty C-like, I like to think, simply because I learned my conventions from C and C++ before ever touching Pascal, and Pascal is pretty C-like itself in many ways.

Yes, somewhat, but due to the Pascal unit/namespace system, clashes are a bit rarer, and bit less absolute than in C (where symbols can clash at the linker without being otherwise related). Specially if the API uses very generic identifiers.

So it is only a convention/best practice however, and in no way enforced.

Quote
Edit: I guess I should also ask if there are any good reasons to not name things this way. I could just not and then I or some hypothetical user could just unitname.function, but then in my head that still leaves the possibility of using the wrong function from the wrong unit, and also makes the code look inconsistent, specifying unit names in some places but not others. Maybe that's just one of my personal hang ups, what with being used to C++ namespaces (std::function, glm::vec3, etc...).

I think it is mainly a evaluation of the chance on clashes. Is it a very generic unit to be imported in many units? (like baseunix and sockets on Unix) Does it contain very common identifiers? Do you intend to distribute widely ?

If all yes, a prefix is best. If all no, probably better not. If in between then it depends.....  :)

E.g. the Windows API don't have prefixes. Partially because the concept is older (Delphi...).
« Last Edit: May 21, 2024, 06:20:03 pm by marcov »

 

TinyPortal © 2005-2018