Servoy Tutorial: Encapsulation

Servoy Tutorial Photo Credit:
angus clyne via Compfight

This Servoy Tutorial is a discussion about encapsulation and best practices. We have been given new abilities in Servoy Developer to use encapsulation with forms, relations, and even value-lists, but do we know what we are supposed to do with this capability?

For those of you that read my Servoy tutorials on object-oriented programming, you would have learned a lot about encapsulation with objects. In the Servoy tutorials, we learned how to build an object with private variables and private functions, which are not accessible to outside users. We also learned how to expose public functions, like an api, so that users could access them. Basically, we hid the things we did not want users to touch, keeping them private, and only exposed those things we wanted them to interact with, in a public interface. This is encapsulation, with respect to an object.

So what does that have to do with forms, relations and value-lists? Well, everything; its exactly the same idea. The problem is, that instead of doing things the right way, we cheat, and because it works for now, we think its good enough. What am I talking about? I am talking about calling another forms methods, accessing its dataproviders, foundset, elements or controller, from some other part of the system. Just because you can see it in the “Solution Explorer” view, does not mean it is okay for you to use it. For example, using  “forms.someForm.someMethod()” breaks encapsulation, and creates all kinds of problems for you down the line. It is generally considered a very bad thing to do and indicative of poor architecture.

There are lots of reasons why you should never call another forms method (or anything else). For one, another developer could change something in that method, unaware that you are using it from somewhere else (how would he know). Because you are tightly coupled to that method, your reliance on it will fail. If you do this a lot, and keep breaking encapsulation, you end up with a Big ball of mud. Furthermore, it is extremely bad architecture to do things like this. You need to design your system for modularity, encapsulating your code into a well designed interface, effectively hiding information, and exposing only a layered design (like MVC, commonJS, etc.). The value is to simplify development and maintenance, allowing individual sections to be modified, without breaking other code that is using it from somewhere else. Basically, its how you build software today.

A Big Ball of Mud is a haphazardly structured, sprawling, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair. Information is shared promiscuously among distant elements of the system, often to the point where nearly all the important information becomes global or duplicated. The overall structure of the system may never have been well defined. If it was, it may have eroded beyond recognition. Programmers with a shred of architectural sensibility shun these quagmires.

 – Brian Foote and Joseph Yoder

So stop breaking encapsulation! Don’t high-jack another form’s methods, value-list, or a relation. The original developer that wrote the code on that form, or created the value-list, did so for a specific purpose, and never expected anyone to call it from somewhere else. If they had, they would have exposed it as part of a public interface and made sure that it was designed to be used in that manner. The golden rule is “If its not yours, don’t touch it”. The good news is, Servoy provides all the tools you need, to implement a proper architecture, preserve encapsulation, and design a sustainable and modular system.

Lets get down to business and take a look at the tools we now have in Servoy to control encapsulation and build a better design. Once we understand how they work, then we can move on to a more practical discussion on how to implement an architecture that achieves that.

Servoy provides us with encapsulation properties on forms, relations, and value-lists. Let’s take a quick look at each property and see exactly what it does.

Form Encapsulation

First, we have some new properties that allow us to control encapsulation on a form. Lets go through each one and see what it does.

encap_5

  • Hide in Scripting: Module Scope
    If you turn this property on, the form will appear red in the “Solution Explorer” view, and if you try to use it, even from another form in the same module, it will generate a build marker warning you that the form is private. Code completion will be disabled for this form, so you will not have any code completion if you try to access the form, any of its methods, elements or variables, from another form, including another form in the same module. It is as strict as you can get. If you ignore all the warnings, and call a method on the private form, everything will still work. In fact the method call will work, even if the method is on a form that is in another module, that is not configured to have access to the original form’s module. This, by the way, generates a “form is undefined” build marker.

encap_6

  • Module Scope
    If you turn this property on, the form will be private to other modules, appear orange in the “Solution Explorer”, and only generate a build marker in another module. Code completion is disabled in other modules, but works in the same module as the form. Again, calling a method on this form, from any module, still works.

encap_7

  • Hide Dataproviders
    If you turn this property on, the form will be shown as green (which indicates something private on the form), the dataproviders from the form’s datasource will be hidden in code completion, including other forms in the same module, and a build marker will be generated if you try to use a dataprovider on that form. Again, if you ignore  the build marker, and use the dataprovider, it will work. Also, you can still see all the dataproviders in the “Solution Explorer” view.

encap_8

  • Hide Foundset
    This property works exactly the same as “Hide Dataproviders”. The form is shown in green, the foundset will be hidden in code completion, a build marker is generated if you use it, but a call on the form’s foundset still works.
  • Hide Controller
    This property works exactly the same as “Hide Dataproviders”. The form is shown in green, the controller will be hidden in code completion, a build marker is generated if you use it, but a call on the form’s controller still works. Also, the controller is visible in the “Solution Explorer” view.
  • Hide Elements
    This property works exactly the same as “Hide Dataproviders”. The form is shown in green, the elements will be hidden in code completion, a build marker is generated if you use one of the form’s elements from another form, but everything still works as expected. Also, the elements are visible in the “Solution Explorer” view.
  • extendsForm
    This is not a new property, but I put it in here because it is essential for good program architecture. Base forms are templates that other forms inherit from, so you can put things here that you want to share with all child forms. This includes methods, form properties, etc. This allows you to maintain one place where code is shared among all child forms. You can have as many of these as you want, and you can chain them. For example, there should be one base form in a module that all other base forms in that module inherit from. Then, you could have another base form, that all dialog child forms will inherit from, and so on.

 

Value-lists

Value-lists work similar to the form properties. As you would imagine, public means accessible from everywhere, and module scope means only for use in the module that they are created in. However, if accessed from somewhere else, you get a build marker, but they will still function properly.

  • Public
  • Module Scope

encap_9

 

Relations

Just like form properties, relations can be public, hidden from code completion in scripting, or only accessible to the module they were created in. They still work if accessed from somewhere else, but you get the build marker.

  • Public
  • Hide in Scripting: Module Scope
  • Module Scope

encap_11

 

JS DOC Tags

The JSDoc tags are very important. They allow you to specify which methods will be public, and which are private. Private methods will appear red in the “Solution Explorer”, while public methods appear in green.

  • @public
  • @private

This is what a properly encapsulated form should look like. Notice that very few of the methods on this form are accessible from anywhere else, without generating build markers. Effectively only two methods (in green) are available for public access.

encap_10

Okay, I wanted to make one final point on the new Servoy properties. You may be wondering why Servoy generates build makers to indicate that something is private and not accessible, but still allows the call to function. The reason is that too many of the programs out there have been breaking encapsulation rules, and would cease to function if they were upgraded to the latest Servoy. So, the build markers are generated, reminding you of the poor implementation, but everything continues to work as currently implemented.

At this point, we should understand that we need to have everything set to @private, and only expose a select few @public methods, relations, or value-lists, that other areas of the system can access. We have to do this with conscious effort and be judicious about it. Think of it like this; nothing should be exposed to the other parts of the system, with the exception of a single access point that controls and routes access; this is your interface. Probably the best way to do that is with a single object or function that acts a router, verifying that incoming calls contain the proper parameters, forwarding them to the local private function, and returning the result. Here’s a quick look at how both of these scenarios could work.

Here is an example of using a single public method to route calls to local private methods.

Here is an example of using an object to route calls to local private methods.

So that is an overview of the new Servoy properties that will assist you in preserving encapsulation and building a modular system with better architecture. The new Servoy will gently warn you where you have broken the rules, giving you a chance to clean things up, and bring them under control. You should also take the time to learn more about designing loosely coupled systems with modern design principles, like MVC, commonJS, requireJS, and AMD.

That concludes this Servoy tutorial. In the next Servoy tutorial, we are going to build upon what we learned here, and build a real example using an event-driven architecture that further demonstrates encapsulation and loose coupling.

Please subscribe to receive notification when new articles are published, and share your comments below.

Gary Dotzlaw
Gary Dotzlaw has 20+ years of experience as a professional software developer and has worked with over 100 companies throughout the USA and Canada. Gary has extensive qualifications in all facets of the project life cycle, including initial feasibility analysis, conceptual design, technical design, development, implementation and deployment. Gary is an expert Servoy Developer, with extensive large-commercial project experience, and has written numerous advanced tutorials on Servoy development.