Software Construction
Covering LotusScript as a language involves covering programming languages in general. It is not possible in one chapter to cover effectively every key programming concept in detail. A good book on basic program construction techniques is Code Complete , by Steve McConnell (Microsoft Press, 1993). This book is one of the few books that are not in my library but instead sits right on my desk at all times.
Poor program design and construction is the root of most of the problems that give Lotus Notes a bad name . Granted, Lotus Notes is a complex beast , but at the end of the day, the vast majority of problems and bugs are easily eliminated by basic construction techniques. For example, in the introduction, I noted that Notes/Domino 6 now supports the automatic enabling of Option Declare in LotusScript code. If you do not know what Option Declare is or why it is important, I suggest that you definitely read this section.
When training new Notes developers, I like to share with them a basic defensive programming "shield" called the four C's (three good, one bad):
- Communication (good ”maximize it)
- Cohesiveness (good ”maximize it)
- Code review (good ”maximize it)
- Coupling (bad ”minimize it)
Communication
Communication is the act of designing and coding that results in clearly understood code and designs.
Communication includes (but is not limited to), commenting and documentation, naming, and consistency. The main theme is that the developer should focus on several audiences for clear, consistent communication. These audiences are typically the developer himself, the end users, other developers, and the system (yes, the system is also a user ).
For example, let us consider a good use of communication: commenting and documentation. Most developers consider commenting and documentation as a task to be done after programming is complete. But for a moment, think about what comments really are. Comments are a form of communication between the developer and the next reader of the code (which could be the same developer in the future). Comments should communicate the developer's problem and solution to that next reader.
Without the need to read the code, the comments should communicate what problem is being solved and how it is being solved . Therefore, before you write one line of code, write your comments first. Can you do it?
If you cannot write your comments before coding, you likely do not understand the problem to be solved or the solution proposed to solve the problem. This should warn you that you need to go back and rethink what you are doing.
This one little technique catches one of the worst and most difficult type of errors to find and debug: logic errors. Logic errors are errors of a flawed design. They usually do not cause an application to crash, but they cause the application to "not work" as expected. This results in hours of futile debugging because the problem is not in the code ”it's in the developer's head!
The logical extension of commenting and documentation is naming. How you name things communicates a great deal about your understanding of the problem and the bits and pieces of the solution, just as commenting does. Everything that you name should have a clear, concise , and atomic meaning ( atomic means that it cannot conceptually be reduced further). For example, consider a subroutine named ComputeAndSendEmail . Its name communicates immediately that it is trying to do two things, which is not atomic. Because it is not atomic, it will be hard to conceptualize. It is trying to do two things at once, and humans have a hard time trying to conceptualize two different concepts as one. (That's why there is no word for something like ComputeAndSendEmail .) Also, the "SendEmail" part of the name is clear, but the "Compute" part is not clear. Compute what? So, we have an unclear part, "Compute," doing who knows what inside, combined with a clear part, "SendEmail," which, we can guess, sends an email.
This same thing applies to the naming of subroutines, classes, variables , and libraries ”and it extends even outside LotusScript, to the naming of forms, views, subforms, and so on. If you cannot concisely, clearly, and atomically name the object with which you are working, you do not understand it or you need to further break it down. (See the section "Cohesiveness" for more examples ”naming and cohesion complement each other.)
Consistency is another subtopic of communication. In addition to maintaining a consistent GUI (I assume that you already know why that is important), your programming should be consistent in how you code, how you lay out forms, and how you name the various objects, variables, fields, libraries, and so on. If it is not, it will be confusing ”not only to others, but also to you. Developers coming after you will find it very difficult to understand your thinking if everything constantly changes.
Cohesiveness
Things that belong together should be together. Things that do not belong together should not be together.
We will return to this topic later in more detail when we talk about variables and scope, classes, and libraries. For now, consider the example from the last section, the ComputeAndSendEmail function.
This function also suffers from weak cohesion, in addition to being poorly named. (Of course, one could argue that it is poorly named because it suffers from weak cohesion, which is caused by the developer not understanding the problem in the first place.) The problem is that whatever is being computed should not impact how the email is sent. The Compute part might impact the recipient of the email, but we don't know that from the name ”it could be just computing an amount based upon the contents of the email being sent. And, that's the problem: We don't know.
The best way to detect whether you have good, solid cohesion is to try to name the object at hand. For example, if I describe an object that has four wheels, four doors, a steering wheel, an engine, a transmission, and the ability to go from 0 to 60 in 7 seconds, and then I told you that it was a car, you'd understand. All of those things go together and can be described as a car without a loss of understanding. In fact, your brain makes these types of cohesive connections all of the time. They are called stereotypes. You could easily reverse the process if I said "car" and asked you to decompose it.
Now consider this example: an object that has a whale 's tail, is covered with feathers, has a rocket engine, has a mechanical claw, and has a bicycle wheel on top. What is it? Can you name it? I can't. None of those things goes together; they are not cohesive. Because they do not make up a cohesive object, that object cannot be named. Of course, in the world of programming, I have seen people try to do exactly that. That is why names are so important: They reflect cohesion.
As you can guess, cohesion is extremely important for object-oriented design and programming.
Code Review
Code review is the process by which developers review each others' code, either live (such as in extreme programming) or after the fact.
Because code reviews are really a business process, I do not cover them in much detail here. However, from catching logic bugs (bugs in thought processes) to potential fraud ("Hey, why are you recording everyone's password in this application?"), code reviews stop problems before they spread to production environments. They enrich the knowledge of all developers involved, so the whole team benefits and grows. Synergy becomes a normal part of the team. However, most companies do not have time to dedicate to code reviews ”and, sadly, most developers have too much pride to engage in them.
Coupling
Coupling is the bane of all good programmers. It is the creation of a dependency between the internal workings of two design elements.
Coupling is a design flaw, not a coding flaw. It is usually a nightmare to deal with if you are unlucky enough to come across it. However, like a bad disease, some indicators of it can be easily detected in code. Others are almost impossible to find. When we cover variables (in the upcoming "Variables" section), I will discuss global variables, which are one example of coupling that is easy to find. There are numerous ways to do coupling and not even know it.
Here is a real-world example that I encountered with a client. I worked on a system that was used to process claims. When an adjustor paid the detail item on the claim, he hit a button called Pay to pay that detail item. When he did that, the LotusScript was supposed to pull account information off the detail item and place it on the check request that was generated by the Pay button. Now, here is the catch. Normally, the account information was computed by the account info field itself (in Formula language) if it was blank when loaded. However, a routine in the PostOpen event of the form was used to compute the current detail item's ID. Within this computation (this is an example of failed cohesion and failed naming as well), a handle to the claim header document was fetched to get the claim number that was used to generate the detail item ID. The developer decided that because he already had the claim document handle, he could just pull over the account information as well, but only under certain conditions ” otherwise , the account information would be blank. Of course, all of this was unknown to me at that time.
Now, the business decided that it no longer needed the account information on the claim header. So, that field was eventually removed. Then the random (and rare) problems began to occur on the check requests . They had the wrong account numbers . We couldn't figure it out because the account field was computing just fine. After hours of searching the entire design of the form, I found the routine in the PostOpen event that computed the detail ID. And that's when I found the hidden dependency. Under certain conditions, this routine was overriding the account information field from the account information field on the claim header. That's why the account information field on the detail item computed only if it was blank when it loaded.
This is an example of coupling. It represents not an error in logic, but hidden logic. In this case, because I was not the author of the code, I never knew how the original developer had the form working. Its logical design was hidden. This example, of course, represents more than just a coupling error. It also shows a lack of communication and cohesion.
This section has reviewed, at a high level, some basic software construction concepts. These concepts apply to all programming, but within the Lotus Domino world, it particularly applies to LotusScript. Now that this background has been reviewed, it is time to begin to apply these concepts as you begin to learn LotusScript itself. It is recommended that you review them repeatedly. As I stated earlier, Lotus Notes gets a bad name from poor programmers, not from a poor product.