I wrote the following (slightly edited) text as the forward for, Using Motif with C++, a book written by Daniel Bernstein.

Whenever I teach people about software programming, I always emphasize a few basic fundamentals that will help produce good working code as well as good performing code. The most basic fundamental is "abstract and generalize" your work. This always applies more to GUI programming than any other kind, mostly because the user interface typically involves reusing a lot of code in different contexts. If you write a segment of code that you find you can use somewhere else in your application, you should break out that code into a function and call it from the places in the code that need to use it. Sound simple? Well, that's only half the perspective. Another basic fundamental is, "don't take that other rule too seriously." Let me explain.

Long ago, every UNIX vendor had its own proprietary windowing system and API to the graphical layer, so in order to appeal to the largest possible audience, software programmers had to choose the workstation that was used more than any other for a particular market. Those that used CAD software may have chosen one UNIX vendor, and those that used financial software would choose another. And so it would go till all 30 UNIX vendors were considered. Because of the proprietary nature of different vendors' workstations, it would have been too costly to support too many systems.

This was a major problem for software programmers, vendors, and customers alike since most applications were not available across enough platforms, and the UNIX market was too fragmented for any one vendor to dominate the entire market. Thus, one fundamental goal was shared by the designers of these workstations and their application developers: design code that is highly portable (among various UNIX implementations) to make it as easy as possible to make the software more widely available. This objective helped popularize another growing trend: object oriented programming (OOP).

OOP was nice in that it generalized many "methods" of implementing common tasks, and proceduralized different classes of methodologies. This way, the programmer could write relatively few lines of code and accomplish many complex (yet common) tasks.

Unfortunately, without empirical experience across many platforms, products, and windowing systems (and other library layers), the methods of OOP had a long way to go. There were OOP languages, but they were not suitable for commercial products usually because of poor performance. Thus, OOP's stigma had to be overcome, and people learned that the way to do it was to bypass the "object layer" and write code fragments that took advantage of the lower layers of the system.

One of the best examples of where this has been successful is with the X Window System. This is a "distributed windowing system", which means that the windowing system functions are broken up between a client and a server, and they communicate through the network. An X client is an application that resides (traditionally) on the a computer that does the CPU management, and the X "server" resides on the user's computer so as to control the screen (the "windows") and the devices (mouse, keyboard, etc). Typically, these two computers are the same system, so the communication between the client and the server usually avoid the "network." However, they don't have to be: one can run a UNIX application on a remote machine and have it be displayed on a local PC, giving the user the illusion that the actual application is running locally.

The X protocol consists of requests that client makes to the server to perform functions. For example, an application can send a request to draw a circle, and the X server would then "implement" that instruction by calling the appropriate graphics system calls to draw that circle. That may be a proprietary command for any given computer, but the X programmer needn't be bothered by those details. As long as the programmer sends the instruction using X protocol, the user will see the correct thing on the screen, regardless of the computer he's using. Thus, the request to draw a circle has been generalized.

Because the X protocol requires knowledge about networking and other inconvenient (and irrelevant) layers normally associated with GUI programming, a library called Xlib, was derived as the primary and most direct way (short of writing impractical networking code) to interface with the X Window System. However, Xlib can be rather verbose, so to simplify things, a new library layer was written on top of Xlib, called the X Toolkit (Xt). Xt provided a number of different features that ultimately encapsulated a number of different Xlib functions into a much smaller set of commands. For example, if you wanted to create a window that said "Hello World" in it, Xt makes this possible using much fewer calls than it would to get the same result in Xlib.

However, because Xt generalized a number of different methods for doing X Window activities, most of the better programmers learn that there are times when you simply have to bypass Xt to get the right job done, or done "faster", and go directly to Xlib.

Motif is the next step beyond Xt in that it has further abstracted and generalized the task of writing even more specific, fundamental user interface code. The Motif toolkit, written in C by the Open Software Foundation, has similar characteristics to any other software toolkit: it has a number of features, bugs, workarounds and blatant omissions that the programmer should know about, so he can work around them (or take advantage of them) as necessary. In this case, there are plenty of bugs in Motif that may require the programmer to bypass Motif and go directly to Xt (or Xlib in some cases) to get the right job done (or the job done right).

And, for completeness, the same is true for C++ and its relationship to C.

Why is this significant? Because knowledge about why things evolved will help the programmer understand the constraints about their designs. Having specific knowledge about how X works will not only help you understand the best way to program something, but it will also help you diagnose a problem in case something doesn't work. The same can be said about Xlib, Xt and even C. This knowledge may also provide insight as to more efficient ways to do something.

Like anything else (and everything else) from which they are built, you should use lower layers when they work to your advantage, and you should avoid them when they don't. That is, don't take Motif too seriously -- it has its problems, and rest assured that you are going to have to lift the hood and tinker with the components inside (bypass the toolkit) to get the right thing done. Accordingly, it is not advisable to learn about Motif without a good fundamental understanding of Xt, and if you don't already know how X works, then you should start there. If you don't know C very well, learning C++ will only help you in very superficial ways. Don't be afraid to learn the prerequisites and don't take the higher level APIs too seriously. It's great that you are now using higher level tools such as C++ and Motif, but learning the basics will only help your understanding and it will definitely help the software you ultimately write.