Rocket Uniface Support Resources

 View Only

Naming convention for Uniface projects

  • 1.  Naming convention for Uniface projects

    ROCKETEER
    Posted 05-21-2021 14:36

    Naming convention for Uniface projects 

     

    To uniquely identify something, we give it a name. In most cases, it is even mandatory. For example, parents give their child a name and entrepreneurs come up with a name for their company or product. Coming up with an appropriate name is quite a process. Fortunately for most people, this is an incidental task so it is okay if it takes a lot of time. After all, a lot depends on a good name. 

    Software developers, on the other hand, must come up with names day in and day out. After all, creating is their job. The screens they build, and the callable modules in the code, must be given a name. For software developers, naming is so obvious that they do not give it a second thought. And yet, a good name is very important. 

    Within organizations, there are usually naming guidelines and procedures that must be followed to name objects. These are the naming conventions. If these guidelines are present in your organization, you should of course follow them as much as possible. If they are not available, then it is wise to draw them up. But why is it necessary to have a guideline for naming? And what requirements should the names of the various objects meet? Are there specific conditions in Uniface that need to be considered? What is a good name in the first place? 

    In general, it can be said that anything that must be uniquely identifiable must be given a unique name. This applies to everything from objects (such as components and fields) to variables in the code. This applies to any development environment, including Uniface. Each platform or language has unique rules and naming limits that must be respected. Within these boundaries, anything is possible. The most important thing is that all objects are given a unique name. This name must be unique within a certain context. For example, a component must be unique within an application, while a variable must be unique within a ProcScript module. 

    However, naming is primarily a matter of personal, organizational, technical, and possibly even cultural factors. Therefore, I want to be careful to provide general guidelines in this article. I have compiled this article based on tips and advice from other Uniface professionals, widely accepted conventions, and my own experience. Let me start by answering the question of why we need a guideline for naming objects. 

    Why do we need a naming convention? 

    I am an entrepreneur and a software developer. Sometimes a challenging combination. As an entrepreneur, I want to explore and expand businesses without thinking about all bits and pieces, while my IT part wants to think in bits and bytes. Both have one thing in common: we are not building for today but for tomorrow. To be able to use interchangeable technology, I mean to be able to connect to a dynamic world, we need something stable to form the foundation of this application. This is Uniface. I foresee that we will be using Uniface for a long time. 

    I know that what I am building today must be built with a future user (developer and/or end-user) in mind. A good naming convention considers the following four goals: 

    1. Uniqueness 
    1. Efficiency 
    1. Readability 
    1. Scalability & reusability 

    Uniqueness 

    Proper naming is important. Obviously for purely technical reasons: for the unique identification of an object, as a kind of primary key. But if this was the only reason, then a technically generated name would be sufficient. Anyone who has ever drifted into the Windows registry will recognize those huge rows of technical keys. Okay, they are unique, but that's about it. Naming serves multiple purposes; it is more than just a primary key. 

    Efficiency 

    Developers develop. Implicitly, this means that they create a lot. If a developer has to think just as long about the name of an object as an organization has to think about the name of a new brand, little will be developed. A guideline that gives clear rules or directions can speed up the naming process considerably. Therefore, efficiency is one reason. 

    Readability 

    Considering that 80% of all costs during the software life cycle are in maintenance and that maintenance is rarely done by the original builder, you can imagine that a good naming guideline can make that job a lot easier. Uniface applications are characterized by low maintenance costs, while the applications generally last a long time. This increases the likelihood that many developers will be working on the software. Readability is thus another goal of naming. By readability, I also mean predictability, so is it clear from the name of the object what it is, or does. This transparency reduces the costs of both development and maintenance. 

    Another reason for readable names is the effort it takes to find objects. Uniface offers smart suggestions to find Main Development Objects in the IDE. It is up to the developer the specify the search criteria and recognize the object by its name in the search results. 

    Scalability & reusability 

    Naming also plays a role in the scalability of an application and the reusability of functionality. This aspect arising from naming is quite diverse. 

    For example, the compiled components are the building blocks of an application. This means that naming extends beyond the development environment. Naming also plays an important role in deployment, because there, too, objects must be uniquely identifiable. 

    However, an application can also consist of building blocks that have been developed in different development projects or environments. Uniface offers the possibility of using resources from different Uniface Archive files in one deployment. This increases the reusability enormously, but certainly imposes requirements on the naming convention. 

    Another aspect that plays an important role here is Uniface's ability to move application execution to another server or to simultaneously process data from multiple databases. All this without modifying the software, instead it is entirely on the basis of settings in assignment files. This enormously increases the scalability of an application. However, as we shall see, naming is of crucial importance here as well. 

    What does this naming convention look like? 

    What the convention looks like and what guidelines it contains is different for each organization. In most cases, it is at least a document. This document will answer the question: “What will be the name of a certain object or entity?”. Although the content, more on that in the next chapter, and structure will differ, some general recommendations can be given: 

    1. Make the guidelines mandatory, otherwise, they lose force. 
    1. Check from time to time (or continuously) that the guideline is being followed. Make it part of the QA procedure. 
    1. The naming convention for a Uniface project should be consistent with that of other platforms and tooling used. At the same time, it shouldn’t conflict. Reserved database keywords should not be used for naming entities for instance. 
    1. Use the same guidelines for all Uniface projects within the organization. 

    It is important to realize that naming conventions are dynamic. Adapt them where necessary. Be careful with adaptations, however, especially if they mean changes to the outside of the application (API’s for instance). In such cases, refactoring the application may even be necessary to continue to comply with the naming convention. 

    If there is no time to implement changes to the convention consistently in the application, this can be done at a later date, as long as the changes do not conflict with the existing naming convention. Adding a version number to the convention and stating it clearly in all objects can help. But in the midst of the day, this will often be forgotten. The result is an application that does not comply with the convention. 

    This is all the more reason to think about naming early in the development process. When a framework to build consistent objects is being used, a sound naming convention will probably be part of that. Framework and naming are the foundations of an application. 

    Naming conventions are there to help naming objects and will be different per organization. But apart from that, there are also requirements set by Uniface for naming objects. 

    What are Uniface's naming requirements? 

    Anything that has to be uniquely identifiable should be given a name and should thus comply with the convention. In Uniface, in addition to development objects, these are also identifiable elements in code (such as variables, parameters, module names, etc.) and in assignment files. Of the aforementioned four goals of naming, the first one is the most important: providing a unique name. It is important and mandatory to distinguish the type of object that needs to be named. 

    Development Objects 

    The main distinction is that of Development Object. Anything within Uniface that is uniquely identifiable and can have behaviour and/or properties is a Development Object. In Uniface, these Development Objects can be divided into two groups: 

    1. Objects that can only exist without any dependency on other objects. For example, components, modelled entities, and libraries. 
    1. Objects that can only exist within another Development Object. Fields, for example, can only exist in Uniface within an entity. 

    This first group are the Main Development Objects. These objects have their own editor in the IDE. This distinction is important in naming within Uniface because the name of a Main Development Object must be unique within the entire repository, while the name of other objects must be unique within a Main Development Object. The name of a field, for example, must be unique within the entity on which it is defined. 

    Application runtime settings 

    Besides naming within the development environment, naming also plays an important role at the runtime level. After all, naming also applies to assignment files, [LOGICALS] in assignment files, logical paths, and Uniface Server Type (UST's). These are often configuration options, which may or may not have been catered for by the developer. In an average application, these options will not be as dynamic as the software development itself. However, the same rules/goals apply. In addition to being uniquely identifiable, readability also plays a major role here, as these options are often used by system or application administrators. Choosing names correctly is of great value here. 

    A powerful feature of Uniface is the path-to-path assignment. This makes it possible, for example, to move certain behaviour to a server or to give the location of files or data a dynamic character. Core to this feature is, you guessed it, naming. Based on an object's name, it can be sent to a certain location. 

    Application versus repository 

    In addition to the configuration options in the assignment files, the entire application will eventually end up in the runtime environment. It is the Main Development Objects that are compiled and delivered as resource files in the development stack from development to production. While during development the names of the objects need to be unique in a repository, in a runtime environment they need to be unique for an entire application. An application need not all come from a single repository. Or, in other words, an application can consist of objects from several repositories. When naming, the developer needs to take this into account. 

    Uniface technical requirements 

    Each platform involved in an application will have certain requirements. Whether it is the OS, a DBMS or the development platform. These will obviously have to be respected to avoid conflicts. The Uniface documentation clearly describes the requirements for naming the various object types. 

    Bear in mind that these requirements are usually not fixed requirements and can have a dynamic character. For example, a database supplier may decide to allow longer field names. More space for naming means more freedom and will not lead to problems so quickly. However, restricting space can lead to major problems. A supplier will therefore not be so quick to decide to decrease sizes. 

    A name should be chosen with care and a naming convention is there to support that process. Nothing new. Here are some common sources of inspiration. 

    General insights for a naming convention 

    With the emergence of the IT field, the need for naming conventions also arose. From the time IT professionals began creating on a larger scale, in the 1960s, the naming challenge has been in play. Each era and associated IT trends seem to influence thoughts on naming. The central question in each case is how one guideline can cover all four mentioned goals of naming. 

    One of the most used scenarios to meet all four goals is to give a composite name. The name then consists of multiple elements. For example, these elements can indicate the function of an object, the application it belongs to, or the data type of the content. As a problem solver, if the name is still not unique, a sequence number can be used. The elements used in the name then depend on the object to be named. Most naming conventions use something like this. 

    A good, solid naming convention will start with general guidelines that apply generically to everything within an organization, regardless of the technology used, to a detailed description by object type. Unambiguous and never open to multiple interpretations. 

    A name consisting of multiple elements can quickly become unique, not entirely unimportant, but readability and predictability were also a goal of naming. Two things come into play here. The first is the order of the various elements in the name. The second concerns the separation of the elements. 

    The order of the elements in the name 

    First the order of the elements in the name. Why is it important to agree on that? Let's look at some of the objects that are created daily by developers: components, modules, variables, and parameters. 

    Hungarian notation for variables and parameters 

    Hungarian notation was once developed by Charles Simonyi, a software developer who worked at Xerox and later at Microsoft. He introduced the notation method to include the data type in variables and functions first, and after that the rest of the name. In Uniface this is not a technical necessity, but it gives a lot of clarity. 

    The Hungarian notation has two varieties: the Apps and the Systems variant. In the latter, the Systems variant, the actual data type is used. In the case of Uniface, this is not necessary because the actual implementation of the data(base) is hidden from the developer. The Apps variant uses a logical data type, which fits the Uniface idea much better. It primarily serves the purpose of readability. A Uniface datatype string can include even more logical types. For example, the content of a string can include JSON, BASE64URL, or a Uniface associated list. I call these functional data types. 

    My personal favourite is to include something that indicates the ‘functional’ datatype in every variable and parameter. These can be the same as the logical or technical datatypes, like numeric or time. But for readability purposes it better to be clear about the (possible) content of a variable or parameter. Agreeing on a naming convention is about making sure that all developers have a clear and sound understanding of the code. The code must be written with the future developer in mind, as they must be able to understand the code. 

    Let's take further inspiration from this notation method. In addition to specifying the data type, this notation mode can also be used to distinguish between variables and parameters. Parameters serve to transfer data between modules, variables to capture a value in a module. It is therefore advisable to indicate in the naming convention whether it is a parameter or a variable. Also, when it is a parameter, it can be useful to know whether it contains input or just provides the result to the outside or both. Suppose a module uses something called 'VsUsername' and 'iPsUsername', the first is a variable and the latter an incoming parameter. It is all about readability. 

    ProcScript modules 

    For ProcScript modules, the naming goals of unique identification and easy maintenance are also of paramount importance. The modules are always defined in the ProcScript container of an object but must be unique within the Main Development Object on which that object is used. So even a module defined at the field level must be unique within the component on which the field is used. Clear and consistent naming of modules in Uniface is therefore vital. 

    Let us, therefore, extend the idea of Hungarian notation to modules. Now, not with datatype, but with a verb that indicates what can be expected from the module. A module named 'calculate' is less clear than 'doCalculateRate'. It is about readability. 

    Components 

    Ultimately, components are what make up the application. They are the containers of everything the developer has created in the development environment. 

    The name of a component can also be made up of elements. For example, the name can include the application or module the component belongs to or the resource (or entity) it does something with. If an application is developed according to a design standard or framework, there will be several types of components, with certain behaviour or a specific purpose e.g. showing a list of records from which a selection can be made, or a maintenance form. This type can be part of the name. 

    Main Development Objects can be easily found in the Uniface IDE using the smart suggestions in the U-bar. This search feature eliminates the need to scroll through lists of objects. Do you still want an overview of the Main Development Objects? Then consider defining a project for all Objects that logically belong together. In the IDE, an Object can appear in multiple Projects, so feel free to create multiple projects to get an overview. This way you can use Projects to create various intersections of the collection of Objects. I always create multiple projects in a repository: per Resource or Moduleper functional type of component, for example, all services that can be executed on the server or all maintenance dialogues by feature I'm working on (or have worked on at some point, because I usually don't remove them …) 

    Particularly with components, naming is important. An application can consist of components from various sources. Components from various repositories can make up an application, but even components from other organizations. Does that sound strange? Suppose we build a component library in the Uniface community, where any developer can build and share components available to the community and every developer can use these components. In that case, a name must certainly be unique, even outside its own repository and application borders. 

    A feature of Uniface is the ability to redirect files, data, and logic execution to another physical location. Uniface uses connectors to assign objects to other locations. Files reads, data access, and component execution can be moved to a server. All of this can be configurated in the assignment files. 

    Providing a clear pattern in the naming of objects allows the use of wildcards in these assignment files. This avoids the dependency on the inclusion of hardcoded object names in the assignment files. 

    Patterns: CamelCase, snake case of Positional 

    The name of an object can therefore consist of several elements, each with its function. To avoid a name becoming a long mash of characters, there is a need to visibly separate these elements. Applying a pattern to the name of an object is mainly for readability reasons. 

    First, the Uniface ProcScript language is not case sensitive regarding most development objects. The use of upper- and lower-case characters in a name makes no difference from a technical point of view. So, when writing code, you don't need to take that into account. 

    Case (in)sensitivity can be tricky though. Most of the naming in Uniface is case insensitive, but there are a few exceptions. Node names of structs are case sensitive, just like element names in DTD’s. One of the reasons behind this is that data is case sensitive e.g. XML and JSON. Therefore, to convert to and from an XML and JSON the struct contents must be case sensitive. 

    For the name of a component, (at the time of writing) 16 characters are available in Uniface. This is where the Positional notation method comes in. This originates from the Cobol world where 8 positions were available in the name. This notation method assumes fixed positions in the name for the various elements, so that wildcards can be used in the assignment files to, for example, always execute services of a certain type, on a server. 

    You are free to choose a separator like an underscore, also called snake case, as long as you stay within the allowed number of characters. Given the space available, every underscore can be seen as lost space, so many developers, therefore, opt for CamelCase. This involves starting each word or element in the name with a capital letter. 

    Development Objects are stored by Uniface in a database. The name is the key and Uniface converts the names to upper case. In the code itself, it remains technically irrelevant whether characters are used in uppercase or lowercase. However, in the resource browsers in the IDE, Uniface will display the names of Development Objects in uppercase. Applying CamelCase in the name of a Development Object makes no sense here, applying it in code will enhance readability. In these cases, a separator, or the previously mentioned Positional notation, or a combination of both, offer better readability in code and in the resource browser. 

    There is quite a bit of confusion about how to write 'CamelCase'. Does the first word start with a capital letter or not? It's actually rather simple: If the first word starts with a capital letter, then it is 'UpperCamelCase' is therefore also called 'PascalCase'. If the first word begins with a lowercase letter, then it is 'lowerCamelCase'. Or just 'camelCase', also called 'dromedaryCase', but not 'CamelCase', because that is 'UpperCamelCase'. Makes sense, right? 

    With the positional notation method, each element has a fixed number of characters, and the order of the elements is also fixed. A reason for this is the readability of course, but there is more to this. For example, it might look like: 

    • Structure of name: AAARRREEE99XXX 
    • Whereby: 
    • AAA = Name of the application. For smaller standalone applications this seems overkill. Applications might use external resources. Open-source plugins for instance. Maybe you want to share (or sell) your developed resources. Better make sure the name is unique. Starting with a mnemonic from your application is something. 
    • RRR = Resource or module. RESTful services require an application divided into resources. A collection of related data and behaviour. Using this in the name of components adds the advantage that the components can be found easily in the IDE’s resource browser. 
    • EEE = Entity that is being edited. The major entity of a component. 
    • 99 = Sequence number to make the entity unique. 
    • XXX = Functional type of the component. Indicates the main purpose of the component: maintenance, index, search, select, print, etc. This will be defined in your framework, for example. There is a reason why I add this to the end of the name and not somewhere in the middle. Uniface has a very powerful feature to move the execution of a service to a server or to read the data via a server process. This can be configured in the assignment file. The functional component type can contain the information that can be used in the assignment file. Since the functional component type is the last part of the name, a wildcard can be used in the assignment file to control the use of the server processes. 

    Of course, it is important to maintain a list of the abbreviations used for the resources/modules, entities, and component types. 

    Language 

    As a final matter, I would like to touch on the use of language. In the Netherlands, it is common to use English in all software we build. With customers in other countries, I often see that they use their own language. There is, of course, nothing wrong with that. However, as soon as you start building software that crosses borders, or if you start using components that come from abroad, then it is advisable to switch to English. 

    Indeed, language can be important in the correct interpretation of names of modules, for example. A verb in imperative indicates an action to be performed. A verb in past tense indicates that an action has been completed and thus probably indicates a status. This may sound like too much detail but in a publish/subscribe mechanism, it is of enormous importance. Good language skills then become particularly relevant. 

    In the articles, I write and the open-source products I deliver, I always use the English language in the naming convention. 

    How to proceed 

    Currently, I am working on some open-source projects. These projects content can be freely used by anyone. They are also projects in which anyone can participate. In this regard, I think consistent naming is very important. If a good naming convention is the starting point, then there is no need to revise the naming afterwards. 

    I have reviewed the naming convention I have used over the years and updated it where necessary. In this article, I have summarized the points that I subjected these guidelines to. 

    A naming convention is a living document. However, major changes can affect existing applications, especially with the open-source thoughts I cherish and propagate. Therefore, I believe that the naming convention should also be an open-source project. 

    I warmly invite you to use this open-source document and improve on it where necessary. 

    References: