By | 30 April 2011

Effectively Organizing your PeopleCode

I tend to code a lot of bolt-on customizations for clients. Many of these bolt-ons end up being very setup intensive which require a large amount of code to respond to peoplecode events. If you have a component with a large amount of event based PeopleCode it can get unwieldy very quickly as you will get peoplecode spread out over many different places at the component and record levels.

The PeopleCode development cycle of a component might look like this:

  • You have some code that needs to execute when the component loads so you put that code on the component PostBuild Event.
  • Then you need to do some similar code when data is read into the buffer so you put some additional code in the RowInit event.
  • Then you realize that you need to do the very same code when a row is inserted so you then have to add some code to the rowInsert event.
  • Finally, you realize that you need to run the same or similar piece of code when a field on the row changes. So you put the same code in the FieldChange event.

During this process what I see developers do is to actually copy and paste that similar code to each of the events which causes the exact or very similar code to be in different places. The event driven nature of PeopleTools components lends itself to having code interspersed throughout your application in all the component events (fieldchange, fieldDefault, Rowinit). This makes future changes and bug fixes really hard to figure out all the code that is touching a row of data or maybe a field. It is easy to miss one of these pieces of code when you are making a future bug fix or enhancement. Additionally, it violates some general programming best practices of copy and pasting code.

I have come up with a simple way to organize component level peoplecode that makes it easy for future changes. We also get some additional benefits which we will discuss later.

How can we organize our PeopleCode to make it better?

In the Component event-driven model, you need code in each of the events to respond to user actions. You can’t get around this. However, what I am proposing in this article is to not actually put the detail code in the event. I create a common code repository for all the component code. Here is what I generally do:

  • Create a new derived work record for my bolt-on. In our example, we will call this record CHG_DERIVED.
  • Create a new field in the database with some descriptive name of the component. If I were creating a bunch of code for a setup page I might call this new field CHG_HR_SETUP_CODE.
  • Then add this new field to the derived record which gives us a record field of CHG_DERIVED.CHG_HR_SETUP_CODE.
  • What I then end up doing is to pull all the detail event code into the CHG_DERIVED.CHG_HR_SETUP_CODE fieldFormula event. So lets go back to our example above. It would result in me creating several functions in CHG_DERIVED.CHG_HR_SETUP_CODE.fieldFormula with some naming convention like this:
    • function Component_PostBuild()
    • function Detail_RowInit()
    • Function Detail_RowInsert()
    • Function DetailEMPLID_FieldChange()
  • Then when I have all the functions defined I will go back into the actual component level PeopleCode event editor and add the following line of code.
 /* Component PostBuildEvent */
 /* Declare function where the actual code lives */
 Declare Function Component_PostBuild PeopleCode CHG_DERIVED.CHG_HR_SETUP_CODE fieldFormula;

/* Call the function */
  • I will then fill in all the detail peoplecode in the CHG_DERIVED.CHG_HR_SETUP_CODE.fieldFormula event that needs to occur each event.

End Result and Benefits

  • If you follow this organizational convention with discipline, you will have one place for all the PeopleCode in this component.
    • This means one place to look for changes to fields, rowsets and to fix bugs.
  • Now that you have the code in one place you will start to see all the redundant code you created and you can start replacing that redundant code and actually reduce the number of lines of code. Less code means less bugs.
  • An added benefit is that you can easily copy and paste this code into a text editor and save it off for “poor mans’s version control” since PeopleTools has zero support for version control (Oracle please fix this). Having everything in one file makes it a bit easier to compare versions later using something like beyond compare or winmerge tools.
  • If you use Component or dreaded global variables they have to be declared at the top of each PeopleCode event where you have code. With this organization technique, you only need them in one place.

General PeopleCode Organization Guidelines

  • I generally have a new derived work record for each bolt-on that I create. I don’t re-use existing derived work records for new projects.
    • I have seen some of my clients think that this causes problems during upgrades. I completely disagree and I think it causes less issues during upgrades.
  • I create a new field for each component to store the code in.
    • If I have a large bolt-on that consists of 3 setups components and maybe two employee level detail components, I will create a new field with some apparent naming convention that is obvious. The fields names may be something like CHG_DEPT_RULE_CODE, CHG_BUS_UNIT_CODE, CHG_APPRV_CODE, etc.
    • My intention is to make it every apparent when looking at the derived record what it contains. If you put all the code in a field like EMPLID it is less clear to the next person looking at your code.

I have found that using these conventions allows me to quickly and easily respond to feature requests and find bugs because I know if a bug is in the Business Unit Setup component then I know I have all the code in the CHG_DERIVED.CHG_BUS_UNIT_CODE fieldFormula event.

Additionally, since I have adopted this code organization convention I have found that I write less lines of code because I start to see that very similar code is needed in different events so I start to create “helper” functions that I can then use in the actual event detail.

Without this convention you might have had some code like this:

  • On RowInit
    • If field_1 > 50 then turn field red
    • Get Department Owner and populate derived field
    • Populate label description
  • On RowInsert
    • Populate label description
  • On Department fieldchange
    • Get Department Owner and populate derived field
    • Populate label description
  • On Amount FieldChange
    • If field 1 > 50 then turn field red

If you have the detail code spread out in the actual events, it would be hard to see that you have alot of repetition here. If you take my code organization approach you will start to see this repetition because the detail is in one place and you can start to create little helper functions that do all the things in the sub-bullets.

This results in less repeated code which means less chances of bugs and quicker development time for future enhancements. This has served me really well over the years.

Article Categories

Do you want to become a CI Expert?

If you want to learn more about developing using Component Interface then check out our CI Training Video.