Sybase Programming Rocks
Sybases PowerBuilder is criticized as an event-driven programming language that is not truly object oriented. In truth, PB does not necessarily force the analyst into an Object Oriented corner. If an analyst so desires he can write the same sloppy, top-down code (in an event driven fashion) that he always has. However, the analyst who wants to share objects, make use of ActiveX, inherit from a class, share methods through non-visual objects, and use an excellent Foundation Class can save time and create clean, uniform object oriented GUIs with PowerBuilder.
The following concepts are widely agreed upon as features (requirements) of an Object Oriented programming language: Inheritance, Class, Method, Object, Encapsulation, Polymorphism, Overloading, Extending, Instances and other concepts, depending on with whom you are arguing.
Classes are the blueprint for objects in PowerBuilder. A class does not exist as a physical object; an object is the real code that is based on the definition set forth by the class. PowerBuilder allows the analyst to develop customizable classes through the user object painter. These classes define all of the objects that follow their instantiation.
Stohl
In his critical work Silicon Snake Oil astrophysicist Clifford Stoll claims that user interfaces are damned hard to build the more degrees of freedom available, the tougher the job. There is an almost mystical quality to good interface development among users. However, developing a quality product quickly and inexpensively is not an exaggerated dream with PowerBuilder, using Object Oriented PB concepts make this a reality. There is no voodoo programming involved. The biggest money and time saver is inheritance.
Sharing or re-using objects is the cornerstone of Object Oriented PowerBuilder (OOPB). It is beneficial to be able to re-use a security routine or a method that calculates the tax on various types of transactions. Understanding the difference between methods of sharing is important. It is not inheriting when an analyst merely copies a chunk of code from someone else, or even an entire object (a routine or method). When you truly inherit an object, you have a tie back to that object. With PB the two objects are then in a parent-child relationship. You have received all of the characteristics of that object, and yet you can customize your object to meet specific job requirements.
The advantage for an analyst is that he does not have to re-write code or functionality that already exists in many places. You can re-use an object, inheriting all of its attributes and code. If you have a global change to make to a specific object (say an error message or variable definition), with inheritance you make the change to the parent object and each of the children inherits the change. This can save a great deal of time and energy. As a team lead or project manager, you can maintain a uniform look and feel throughout the application as these attributes are inherited.
The down side can be ancestor objects of poor design. If an ancestor is too top-heavy (filled with a vast array of methods and visual objects), then it will force the developer to override too much code. A well-designed ancestor will provide just enough functionality, but certainly not too much. These overdone ancestors will also cause performance issues.
User Objects play a large role in OOPB, and are defined as either visual or class (non-visuals). Standard Visual Objects in PowerBuilder are combinations of window controls such as Radio Buttons, Drop-Down List Boxes or OLE Objects that can be put together in groups. Non-visual objects are used to store methods (called Functions or Window Functions in PB), that can be overloaded or made multi-functional (polymorphic). We make use of these stored methods by instantiating the non-visual objects, using dot notation to refer to the specific method desired at the time. The following code example would serve as a security checking routine in the Open Event of a Window or perhaps behind a Save or Close button object.
Some Coding Examples
On line 1 we instantiate the non-visual; on lines 2 and 3 we access the methods (functions in PB) within the non-visual, moving the results into instance variables. We then check the variables and act on them, and then destroy our instantiation; being careful to do our house keeping tasks.
uo_verify_eom_security = Create uo_verify_eom_security
iv_cycle_allow = uo_verify_eom_security.of_check_cycle_dates()
iv_pmt_allow = uo_verify_eom_security.of_check_cycle_dates_pmtbill()
If iv_cycle_allow = F then
cb_save.enabled = false
cb_save_as_inc.enabled = false
cb_delete_deal.enabled = false
End if
If iv_pmt_allow = F then
wf_columns_tab_off()
End if
destroy uo_verify_eom_security
The following is one of the methods (of_check_cycle_dates()) that is used to return a
code to find if updates are allowed. First we set all of our variables
boolean lv_acct_grp_flg
string ls_curr_date
string lv_deal_date
string lv_deal_type
iv_co = 99
iv_dept = H999
iv_book_co_no = 8000
iv_save_flag = 0
lv_deal_type = gv_deal
Next we check the deal type to determine the return value from the method.
If lv_deal_type = P then
lv_deal_date = gv_pur_prod_date
Else
lv_deal_date = gv_prod_date
End if
This function returns an instance variable based on the production date being greater than or equal to the current accounting cycle date with a current status code. The use of bind variables (iv_co, iv_dept, etc.) allows the analyst freedom by avoiding hard-coded values.
iv_save_flag = of_check_accounting_group(gv_co, gv_dept, SQLCA.Logid, lv_acct_grp_flg)
If iv_save_flag = 2 then
SELECT cycle_dte
INTO :ls_curr_date
FROM emss.cycle_dates
WHERE co = :iv_co
AND dept = :iv_dept
AND book_co = :iv_book_co_no
AND cycle_type_cde = :iv_code
AND cycle_stat_cde = C;
If lv_deal_date LT ls_curr_date then
If sqlca.sqlcode LT 0 then
messagebox(Fatal Error, Select on cycle_dates = +sqlca.sqlerrtext)
Return(DB ERROR)
End if
Return F
End if
End if
Return T
We can also see that we have overloaded this method forcing it to act differently if we feed it a Purchase type, than if we give it a Sale. We also see that the user object uo_eom_verify_security encapsulates all of the data and methods that are necessary to carry out the functionality needed for the security checking in this process.
In Conclusion
To accommodate this type of functionality, it is best to avoid hard coding any variables or names. Make use of bind variables, so that the users can set the amount or choose the range themselves. Leave the code open to run several different methods, depending on the need at the time.
Alan Cooper (the father of Visual Basic) says in the indispensable About Face: Essentials of User Interface Design. The developer who wants to create a better user interface often must roll-his-own without much help from the tool vendors. Using Object Oriented concepts when coding in PB requires planning and a bit more front-end analysis, but PB provides us with a number of excellent, ready made tools. In the final analysis, the rewards are orderly, easily maintainable screens, with a uniform look and feel that are, hopefully, easy to use.