What does a professional programmer do first to gain an understanding of a problem?

Reuse in the world of end user programmers

Christopher Scaffidi, Mary Shaw, in No Code Required, 2010

Conclusion and future directions

Professional programmers cannot anticipate and provide components for every domain-specific need. To close this functional gap, end users create code that is valuable in its own right. Other end users often can benefit from reusing this code, but reusing it is not as simple as plucking components from a catalog and stitching them together. Reuse is more typically a multistage, white box process in which users search for useful code, attempt to understand it, and make needed modifications through cloning, editing, or both. Users also need to understand code to learn reusable concepts from it. Empirical studies show that code with certain traits tends to be more reusable. At least in the Web macro domain, it is actually possible to accurately predict whether code will be reused, based on information that may be informal, imprecise, and unreliable, but that can nevertheless be gathered, analyzed, and synthesized with a minimal amount of effort and skill.

These results represent one step toward providing end users with more effective approaches for quickly identifying reusable code created by other users, understanding that code, and adapting the code or learning from it to create new code. A great deal of additional work will be needed before end users obtain anything resembling the benefits originally promised by the stereotypical vision of component-based reuse.

First, our results create the opportunity to collect and exploit low-ceremony evidence in new system features aimed at supporting reuse. Several of the systems presented in this book would provide excellent test beds for this exploration. For example, the CoScripter repository (Chapter 5) could use the model presented in this chapter as a ranking function in search results, to be able to sort scripts by their reuse potential. Another possible application would be to integrate reusability scores with information from other sources, such as models of social networks; for example, if reuse is localized within a community, or among people with shared interests, then the CoScripter repository could rank code more highly if it appears to be highly reusable and if it was created by somebody with similar interests to the user running the search.

Systems might use evidence to rank code differently, depending on the user who is looking for code to reuse. For example, the designers of the ITL framework note that “Advanced users may be comfortable with complex structures, such as conditionals and iteration, but these may confuse novice users” (Chapter 11). Consequently, it might be useful for the repository to differentiate between advanced users and novices, presenting different search results to each. Novice users might be identified as those who have never uploaded code that had conditionals and iteration; advanced users then would be those who have uploaded such code at least once. When presenting search results to a novice user, the repository could filter out (or downrank) code that contained conditionals and iteration, but it would use no such filter for advanced users. In this case, the evidence of reusability (the presence of conditionals and iteration) would be used to characterize users and code, with the goal of only presenting hard-to-understand code to users who have previously presented evidence that they are capable of understanding such code. Of course, any such innovation would need thorough testing to determine whether it is effective at linking users with useful code.

As one final idea for how to apply low-ceremony evidence in the context of end user programming for the Web, consider the notion of “trusted” and “untrusted” widgets created by users for users in the Mash Maker system (Chapter 9). Trusted widgets are allowed to execute certain operations in the user's browser that untrusted widgets are not allowed to execute (such as to read cookies transmitted between the browser and server). To become trusted, a widget must receive an imprimatur provided by the Mash Maker system administrators at Intel. This creates a bottleneck – no widget can become trusted until after Intel's employees have a chance to look at it. One possible improvement would be to let users decide for themselves whether they want to trust a widget that another user created, based on low-ceremony evidence. For example, after downloading an untrusted widget, the user could click on a button in the Mash Maker client to view evidence about trustworthiness. The client might indicate, for instance, “This widget does not call any API functions that could send data outside your browser. It was authored by a user who was confirmed to have the email address [email protected] It has previously been trusted by 9 people whose code you have previously trusted, including [email protected]” Depending on whether the user is persuaded by this evidence, he could decide to trust the widget or not.

Second, we have found relatively few studies showing that code reuse is related to the code's authorship or prior uses. This was somewhat surprising, because evidence about prior uses has been incorporated into many repositories in the form of rating, review, and reputation features. Thus, one direction for future work is to perform more studies aimed at empirically identifying situations where this and other low-ceremony evidence helps to guide end user programmers to highly reusable code. Further empirical studies might also help to extend our catalog by identifying new sources of low-ceremony evidence, beyond the code itself, authorship, and prior uses.

Third, it will be desirable to empirically confirm the generalizability of our machine learning model. This will require amassing logs of code reuse in some domain other than Web macros (such as spreadsheets), collecting low-ceremony evidence for that kind of code, and testing the model on the data. At present, except for the CoScripter system, we are unaware of any end user programming repository with enough history and users to support such an experiment. Ideally, just as we have drawn on research from studies performed by many teams, the machine learning model would be confirmed on different kinds of code by different research teams.

Fourth, although these studies have shown the importance of understandability in promoting white box and conceptual reuse, there has been virtually no work aimed at helping end users to produce code that other people will be able to understand. For example, though virtually all of the studies emphasized the importance of code comments in promoting understandability, most studies also showed that end user programmers rarely take the time to embed comments in their code. End users lack the time to make significant up-front investments in understandability, yet this hampers reusability by their peers. New approaches are needed to break this deadlock.

Finally, a similar deadlock exists in the problem of designing code that other end user programmers can easily adapt. Among professional programmers, it is widely accepted that good design promotes flexibility, chunks of manageable and useful functional size, and ultimately mass appeal. Yet end user programmers often lack the time and skills to invest up front in design. The resulting code can be not only hard to understand but also hard to adapt. End user programmers need effective techniques and tools to support the creation of well-designed code, as well as the adaptation of poorly designed code. Perhaps this might involve providing approaches that help users to create code that can more easily be reused in a black box fashion. In other cases, it will be necessary to develop techniques and tools for analyzing, refactoring, combining, and debugging existing code.

End user code is not a simple thing, and helping end users to effectively reuse one another's code will require more than simply snapping together building blocks.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780123815415000213

Computer Programming Languages

Howard Austerlitz, in Data Acquisition Techniques Using PCs (Second Edition), 2003

13.1.3 C Programming Language

C is one of the most popular general-purpose computer languages used by professional programmers. As we discussed previously, C combines the best features of low-level languages (ability to directly access hardware and to produce fast, efficient code) with those of high-level languages (supports abstract data structures, handles complex mathematical calculations, is well structured and maintainable).

The power and popularity of C reside, paradoxically, in its inherent simplicity. In one sense, C is not very robust, because it lacks many functions present in other high-level languages, such an x2 command. However, it contains all the building blocks to create this function along with any other high-level language operation. Many of these features are present in standard libraries that are part of a commercial C compiler package. In addition, C contains many operators not found in most high-level languages, such a bit manipulation commands. Since C is modular, it is easy to add new functions, as needed, and use them as if they were an inherent part of the system.

C is also a well-standardized language. It was developed at AT&T Bell Laboratories, during the early 1970s, by Dennis Ritchie, where it was well controlled. The language is defined by the standard text, The C Programming Language, by Kernighan and Ritchie. Virtually all commercial C compilers adhere to this or a later ANSI standard (although some may add enhancements, along with additional function libraries).

To illustrate some of the features of C, here is the program for calculating an average value, from the previous BASIC section, rewritten in C:

What does a professional programmer do first to gain an understanding of a problem?

Many aspects of C are shown in this example. Functions (including the main program and any subroutines) are specified by a name followed by parentheses, with or without arguments inside. The statements comprising the function are delimited by the braces, {}. These same braces also delimit various loops within a function or even array initialization data (for a[]). Program execution starts with the function main(), the main program. When another function name appears, such as calc_avg(), that function starts execution. When it completes, control is returned to main(), along with a return value (if any). Statements in C are terminated by a semicolon (;) and pairs of special characters (/* */) delimit comments. Statements (and comments) can span multiple lines. C is not rigorous about text formatting in the source code. It allows programmers to format a file for easy readability. In this respect, C is a fairly free-form language. Also, it does not use line numbers, although you can give statements a label.

There are many important facets of C. One of these is function privacy. Any variable defined and used within a function is private or local to that function. Another function cannot directly access that variable. This is in sharp contrast to BASIC, where all variables are global (none are private). When a function sends a variable value to another function, it sends a copy of that variable, so the original cannot be changed by the other function. For a variable to be global, it must be defined outside of a function. In the preceding example, a[] is a global array of floating-point numbers. The only reason a[] was made a global array, instead of a local array in main(), was to initialize its values more easily. Also note that all variables have to be explicitly declared before they can be used. As opposed to some other languages (MATLAB, for example), C must know explicitly what all the variable types are (integer, floating-point) before it can use them.

Another significant aspect of C is the use of pointers. In C, any variable (scalar or array) has two values associated with it: the lvalue and the rvalue. The lvalue is the address of a variable, while the rvalue is its actual numeric content. A pointer is used to address a variable (or a memory location). If we have a pointer, pntr1, containing the address of a variable, we can store the value of that variable in another variable, x, with the indirection operator, *, as follows:

What does a professional programmer do first to gain an understanding of a problem?

Similarly, if we want another pointer, pntr2, to contain the address of the variable x, we can use the address of operator, &, as follows:

What does a professional programmer do first to gain an understanding of a problem?

The utility of this pointer scheme is shown in the program example just given. Function calc_avg() defines two dummy parameters, data and nval. The parameter data is defined as a pointer to an array of floating-point values via

What does a professional programmer do first to gain an understanding of a problem?

If data was just a scalar variable, it would be defined without the indirection operator:

What does a professional programmer do first to gain an understanding of a problem?

By specifying this parameter as a pointer, we do not have to pass 10 variables to calc_avg(). In addition, the function can handle input data arrays of variable length—it just needs to know where the array starts (via data), how long it is (via nval), and how big each element is (via the float declaration for *data).

Another aspect of pointers is that they are the means to circumvent variable privacy. The only way one function can modify the rvalue of another function's local variable is if that function sends it the lvalue (pointer) of that variable. This is necessary when a relatively large amount of data must be passed between functions. Still, this is done explicitly, and the indirection operator must be used to access the variable, from its pointer.

Several aspects of the notations used in C can be bewildering at first. One source of confusion is = (the assignment operator) versus == (the equality operator). The assignment operator is used to assign the rvalue of a variable, as in most high-level languages:

What does a professional programmer do first to gain an understanding of a problem?

The equality operator tests a statement to see if it is true or false (in C, false is considered 0 and true is considered nonzero). So, a conditional statement checking if x equals 10 would be

What does a professional programmer do first to gain an understanding of a problem?

If x does equal 10, any statements within the braces would be executed.

Other notation in the sample program may seem odd. C allows for special assignment operators, such as += or /= (as used in the sample program). The statement

What does a professional programmer do first to gain an understanding of a problem?

is equivalent to

What does a professional programmer do first to gain an understanding of a problem?

Similarly,

What does a professional programmer do first to gain an understanding of a problem?

is equivalent to

What does a professional programmer do first to gain an understanding of a problem?

These assignment statements are notational conveniences. Other important operators are increment (++) and decrement (––). As used in the sample program, the increment operator statement

What does a professional programmer do first to gain an understanding of a problem?

is equivalent to

What does a professional programmer do first to gain an understanding of a problem?

Similarly,

What does a professional programmer do first to gain an understanding of a problem?

is equivalent to

What does a professional programmer do first to gain an understanding of a problem?

Logical operators also can be confusing. The bitwise AND operator (&) is different from the logical AND operator (&&). For example,

What does a professional programmer do first to gain an understanding of a problem?

evaluates i = 13h AND 27h as 03h (note the use of 0x for hexadecimal numbers). When used as a logical operator,

What does a professional programmer do first to gain an understanding of a problem?

i is evaluated as TRUE only if both a AND b are true. The same distinctions hold true for the OR operators (| and ||).

There are two important loop control statements in C, the for loop (shown in the example program) and the while loop. In the example, the for loop consists of a for() statement followed by one or more program statements, enclosed in braces. The for() statement consists of three sets of expressions, separated by semicolons: initializations (i = 0, × = 0.0), test condition (i < nval), and execute at end of loop (++i). The initializations set up a loop index variable (i) and any other variables used in the loop (x), where required. The test condition (i < nval) is evaluated at the start of each loop. This usually checks if the index is within bounds. If the test condition is true, the statements within the loop's braces are executed (x += *(data + i);). This is followed by the executable expression (++i), usually used to increment the loop index. When the test condition is no longer true, as when the loop has been executed the requisite number of times, execution continues with the first statement following the for loop.

The while loop is simpler. It consists of a while() statement, which contains only a test expression, followed by braces enclosing the loop statements. If we rewrite the for loop from the example program as a while loop, we get

What does a professional programmer do first to gain an understanding of a problem?

The while() statement is a useful way to wait for an event to happen, regardless of how many times to try. If we are waiting for a device to produce data, via a function get_data(), which returns 0 if no data is present, the statement

What does a professional programmer do first to gain an understanding of a problem?

waits indefinitely until get_data() returns a nonzero value. Of course, in actual practice there should be a way of terminating this wait, in case of error (such as a time-out).

This concludes our brief overview of the C programming language, which is one of the most important general-purpose languages for data acquisition applications. Next, we will examine C++, an offshoot of C.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780120683772500139

Computing with/on Images

In Artificial Vision: Image Description, Recognition, and Communication, 1997

Khoros–Cantata

Khoros (Rasure and Williams, 1991) is designed stressing the integration of different tools in image processing together with the interface.

Khoros is a comprehensive system which relies on existing standards (X-Window and UNIX) to allow non-professional programmers to tailor it into high level interfaces to domain specific operators. A resulting Khoros application consists of domain-specific processing routines which are accessed by an automatically-generated user interface. The Khoros infrastructure consists of several layers of interacting subsystems whose organization is inspired to the metaphor of a chorus, ‘any speech, song or other utterance made in concert by many people’. Khoros is based on Cantata, a general purpose visual multistyle data-flow programming language. The styles employed are flow-graphs, forms with various buttons and sliders, and textual programming.

A Cantata program is a data-flow graph, constructed from a user definable lexicon composed of: glyphs (operator or function), direct arcs (a path over which data tokens flow) and forms (interfaces between the visual data-flow graph and the textual nodes) (Figure 11.11). The descriptions of the lexicon elements are conventional programs. A textual label in the image part of a glyph identifies the associated description, arrow buttons identify the inputs and outputs, and icon buttons (e.g. Run, Reset buttons) are used to drive the execution mode (Figure 11.12).

What does a professional programmer do first to gain an understanding of a problem?

Figure 11.11. CANTATA: an example of a control structure.

What does a professional programmer do first to gain an understanding of a problem?

Figure 11.12. CANTATA: a noise cleaning visual program

[reproduced from Rasure and Williams (1991), with kind permission from Academic Press Ltd].Copyright © 1991

A program is built by arranging the processing elements and their interconnection. Procedural abstraction is allowed: a subgraph can be associated with a glyph and substituted by it in the main graph.

Cantata is an interpretative language: the user can stop the execution, modify parameters or connections and continue the execution or SAVE the entire workspace, including the data flow graph and intermediate results. It supports both data-driven and demand-driven execution approaches. It also supports single step execution, parallel execution and responsive modes. Khoros exhibits a) high user-driven adaptability; b) the fourth degree of liveness through animation of the glyphs; a programmable level of reactivity allowing automatic triggering of re-execution of the flow-graph. Originally based on a software environment created for research in image processing, Khoros is currently being used as a research and development tool to solve a variety of problems at numerous sites through the world. It is available at no cost via anonymous ftp at chama.unm.edu.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780124448162500174

Common Problems, Causes, and Solutions

Shane Cook, in CUDA Programming, 2013

Back-to-back testing

Testing is something that is key to a programmer being perceived as either someone who writes “good code” or someone who throws together something that occasionally works. As a professional programmer you should strive to deliver the best-quality software you are able to in the timeframe available. How can you achieve this?

Back-to-back testing is a technique that acknowledges that it is much harder to write code that executes in parallel than a functionally equivalent set of code for a serial processor. With this in mind you always develop, in parallel to or prior to the CUDA application, a serial implementation of the problem. You then run the identical dataset through both sets of code and compare the output. Any difference tells you that you may have an issue.

Now why do I only say “may” have an issue? The answer is largely down to if you are using floating-point (single- or double-precision) numbers or not. The issue with floating-point numbers is rounding and precision. Adding a large series of random floating-point numbers on a serial CPU from the lowest array value to the highest array value will result in a different value than if you were to add the same numbers from the highest array index to the lowest array index. Try it and see.

Now why is this? Single-precision, floating-point numbers use 24 bits to hold the mantissa value and 8 bits to hold the exponent. If we add 1.1e+38 to 0.1e−38 what do you think the result will be? The answer is 1.1e+38. The tiny value represented by 0.1e−38 is too small to be represented in the mantissa part. Over a large set of numbers there will be many of these types of issues. Therefore, the order in which the numbers are processed becomes important. To preserve accuracy often the best way to solve this issue is to sort the set of numbers and add from the lowest number to the largest. However, this introduces potentially a significant amount of work, in the terms of the sort, for this enhanced precision.

There are also other issues concerning the handling of floating-point values in compute 1.x devices, especially with very small numbers around 0, which may cause them to handle floating-point numbers in different ways than the same code running on the CPU. Thus, it’s often best to compromise and allow a certain threshold of error when dealing with floating-point equivalence tests.

If you have an existing CPU solution, then it is relatively simple to compare the results. With integer-based problems the standard C library function memcmp (memory compare) is quite sufficient to see if there is a difference between two sets of outputs. Usually when there is a programming error on the GPU side, the results are not just a little different, but greatly different, so it’s easy to say this code does or does not work and at which point in the output the difference occurs.

More difficult are aspects where the results match up until a certain point. Typically this might be the first 256 values. As 256 is often used as a thread count, this points to an error in the block index calculation. Only the first 32 values being correct points to an error in the thread index calculation.

Without an already existing CPU implementation, you’ll need to write one or use someone else’s implementation that you know works. However, actually writing your own serial implementation allows you to formulate the problem and understand it much better before attempting a parallel implementation. You have to, of course, ensure the serial version produces the expected answer before you start the parallel work.

It also provides a useful benchmark to see if using the GPU is providing a good speedup. In this evaluation always consider any transfer times for the PCI-E bus. As with the reduction example, we could write a reduction algorithm on the GPU that runs much faster than its CPU OpenMP equivalent. However, just sending the data to the GPU swamped any execution time saving. Be aware the GPU is not always the best solution. Having a CPU counterpart can let you evaluate this decision easily. The solution should be about maximizing the use of whatever resources are available, CPU and GPU.

Once the back-to-back test is set up, and there are many such examples where we do this in the various examples in this book, you can instantly see if you introduce an error. As you see this at the point you introduce it, it makes finding and identifying the error far easier. Combining this with a version control system, or simply always making a new backup after every major step, allows you to eliminate a lot of hard debugging effort later in the development cycle.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780124159334000120

The Way of the Psychologist

Robert Charles Metzger, in Debugging by Thinking, 2004

12.6.17 Summary

Performing experimental research on programmers doing debugging is difficult for several reasons. The subjects available to university researchers are usually novice programmers. Novice and expert programmers don't exhibit the same behaviors. The economic cost of using enough professional programmers in psychological experiments whose results have statistical significance is high. Debugging actually involves a number of skills and behaviors, which are difficult to separate in a controlled experiment.

Previous experimental research in debugging has limited value to the professional programmer. Researchers tested programming languages and development techniques that are no longer used in modern computing environments. Most experiments were performed on tiny programs that aren't typical of the complex software that professional programmers develop.

Some of the experimental work is also difficult to assess because of the limited sample size, the design of the experiment, or the subjects used. Most of the subjects in the experiments were complete novices taking a first or second programming course. The related topic of program comprehension has interested researchers more recently, but a survey of that literature is beyond the scope of this section.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9781555583071500124

End user programming on the Web

Allen Cypher, in No Code Required, 2010

Publisher Summary

This chapter defines end-user programming, summarizes the current state of the field, and shows how the Web has removed many of the obstacles to widespread adoption of end-user programming. End-user programming is programming by people who are not professional programmers. The program is often something that only an end user wants. And because end users are engaged in performing real-world tasks, the solution often needs to be accomplished right away while the user is performing the task. The challenge to researchers in this field is to find ways to make limited forms of programming sufficiently understandable and pleasant that end users will be willing and able to program. The goal is to bring programming to “the rest of us,” and advances in end-user programming come when systems achieve an elegant balance between power and ease of use. There have been two main approaches to enable end users to create their own programs: scripting languages and programming by demonstration. Scripting languages approach end-user programming by still using a programming language but by making that language simpler and easier to use. To accomplish this, they may restrict their solutions to a limited domain—such as spreadsheets or Web pages—and offer only limited power within that domain. Programming by demonstration system demonstrates an activity, and the system writes a program to perform that activity. After outlining the challenges that confront these approaches, one shall see how the Web has removed some of the most significant barriers, opening the way for the recent progress.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780123815415000018

Introduction

Jules J. Berman, in Repurposing Legacy Data, 2015

1.4.2 Simple Programming Skills

Like many individuals, I am not a cook. Nonetheless, I can prepare a few dishes when the need arises: scrambled eggs, oatmeal, and spaghetti. In a pinch, I’ll open a can of tuna or baked beans. My wife insists that such activities do not qualify as cooking, but I maintain that the fundamental skills, such as heating, boiling, mixing, and measuring, are all there. It’s cooking if I can eat it.

Programming for practitioners of data repurposing can be much like cooking for individuals who feel out-of-place in the kitchen. It would be a terrible mistake to surrender all programming chores to professional programmers. Each of us must have some programming skills, if we hope to survive as data professionals. Some of our most common and indispensable computational tasks are ridiculously easy to achieve, in any programming environment. We do not ask a master chef to fill a glass of water at the sink. Why would we seek the services of a professional programmer when we need to alphabetically sort a list or find records in a data set that match a query string, or annotate a collection of files with a name and date (see Glossary items, Query, String)? The bulk of the work involved in data repurposing projects will require skills in data organization, data curation, data annotation, data merging, data transforming, and a host of computationally simple techniques, that you should learn to do for yourself [4,5] (see Glossary items, Curation, Transformation).

There are hundreds of fine programming languages available; each with its own strengths and weaknesses. Perl, Python, and Ruby are powerful, no-cost programming languages, with versions available for most of the popular operating systems. Instructional online tutorials as well as a rich literature of print books provide nonprogrammers with the skills they will need, as data scientists [5–8]. If you intend to confine your programming efforts to simple tasks, such as basic arithmetic operations, simple descriptive statistics, search and replace methods, then you may wish to avoid the languages preferred by professional programmers use (e.g., C and Java). GUI (Graphic User Interface) languages such as Visual Basic require a level of programmatic overhead that you would probably not require. Specialty languages, such as R, for statistics, may come in handy, but they are not essential for every data scientist [9]. Some tasks should be left to specialists.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780128028827000014

End-User Computing Tools

Jose Stigliano, Marco Bruni, in Encyclopedia of Information Systems, 2003

V.A. Application Generators

Application generators are software tools that automate the process of developing computer applications, generating the necessary application programs, or program components, from high-level descriptions of the problem. A range of products has been classified as application generators, from early software engineering tools intended to increase the productivity of professional programmers, to specialized components of 4GLs for less technical users, to end-user tools associated with DBMSs that automatically generate relatively simple database applications.

End-user application generators are usually a component of a DBMS or are part of a development environment that includes a database. These tools are used mainly to create menu-driven database applications and are based on a data dictionary or repository stored in the database.

In the simplest tools, the user only needs to specify the data to be used and the type and number of items to be included in the menu and then select options to specify the actions assigned to each item. The application generator typically interprets the user selections, merges those selections with prebuilt code, and draws on the data dictionary of the associated DBMS to understand the relevant data structures. The tool then generates all the necessary program code for the application, which is usually built as a single component with a predefined organization.

In more advanced application generators, the developer can define business rules that are stored in the data dictionary, store application design preferences in style sheets, and use templates to generate the appropriate program code. As with the simpler tools, the developer does not need to write program code if a standard design for the application is acceptable.

In general, end-user application generation tools offer limited functionality as well as relatively little control over the design and performance of the application obtained, thereby offering a limited range of information processing possibilities. Applications created through this kind of automatic generation often suffer a “performance penalty” at runtime due to excess (nonoptimized) code. This penalty becomes increasingly severe as the volume of processing grows, although the increasing processing speed of computers sometimes makes performance a noncritical issue.

Besides functionality and performance, applications generated with some application generators may be difficult to integrate with other existing user applications, in particular, with those created with office productivity and workgroup computing tools. Some application generators require a runtime license to execute the applications, limiting the deployment possibilities.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B0122272404000575

Clients

Tony Redmond, in Microsoft Exchange Server 2007 with SP1, 2008

7.4 Out of Office Changes

Outlook 2007 and Outlook Web Access both support different OOF messages to send to internal and external correspondents and both allow you to create a scheduled OOF message with a start and end time. The OOF message can also be in HTML format. Exchange stores the OOF messages as hidden items in the root of the mailbox. There are two items—one for internal and one for external. These items are message class IPM.Microsoft.OOF. UserOOFSettings, which is a new class introduced in Exchange 2007.

The decision whether a correspondent is internal or external depends on the authoritative domains that you have defined for the Exchange organization. See Chapter 6 for more information about how to create authoritative domains for Exchange 2007. If a user comes from an authoritative domain, then Exchange automatically considers them as internal. Exchange considers a user from any other domain as external.

The Microsoft Exchange Mailbox Assistants service runs on a mailbox server to send OOF messages. If the service is not running, Exchange cannot send OOFs in response to incoming messages. Interestingly, if the service is not running, Exchange does not queue OOFs for future dispatch.

7.4.1 The big question: Is Outlook 2007 worth the upgrade?

Microsoft has struggled with the richness of its Office applications for years. Few know how to use the power of Excel and most are happy to build simple spreadsheets. Few know how to use Word to build a book composed of many chapters, hundreds of figures, cross-references, and all the other complex document parts that professional authors depend on, but we can all generate simple documents. Word 2.0 remains my favorite release, possibly because it was my first exposure to a Windows-based word processor and I wonder if I really use all of the features and improvements that Microsoft has made to Word since. Professional Programmers like the power and flexibility of Access and it is certainly easier to generate databases with Access 2007 than it was with the first few releases. Apart from anything else, each upgrade to a new desktop application is costly because of the need to touch so many PCs, to train users, and to provide the inevitable increase in help desk support through the transition.

When I wrote about Outlook 2003 for my Exchange 2003 book, I concluded that Outlook 2003 was a worthwhile upgrade in terms of the additional useful functionality that it included and the economical benefit that an organization could gain from its implementation. Features such as cached Exchange mode delivered better performance and usability for users while allowing organizations to consolidate servers into central locations and so save hardware and operational costs. The reduction in network costs in many countries made it economically feasible to connect clients over extended links back to datacenters and the ability to use RPC over HTTP connections allowed users to piggyback on standard Internet connections to get their email, assuming that the organization deployed the necessary infrastructure to support these connections. I also liked the network “smarts” included in Outlook 2003, such as better checkpointing, drizzle synchronization, buffer packing, and compression and the junk mail filtering capability consigned spam to the wastebasket without bothering me with offers that I never wanted to accept. Overall, Outlook 2003 delivered the necessary combination of features, functionality, and value to make it a compelling upgrade.

I wish that I could say the same about Outlook 2007, but I cannot. There is no doubt that Outlook 2007 is an evolution from Outlook 2003 that includes many worthwhile improvements in the user interface as well as bug fixes. As such, you can regard Outlook 2007 as the best client for Exchange 2007, at least in terms of the total feature set and client usability. However, Outlook 2007 struggles to deliver and headline new pieces of functionality to build the financial case to back a recommendation to deploy Outlook 2007 company-wide, unless you can wrap it up all in the costs of a desktop migration where you plan to upgrade hardware—the operating system (to Vista) and applications. Sure, the AutoDiscover service is a nice way to avoid knowing the name of the server that holds your mailbox, but knowing this information has never been an intellectual or tortuous challenge for me in the past. The integrated search feature is a terrific way of finding messages and attachments quickly. The scheduling assistant makes it easier to find gaps in calendars to bring an important meeting together and probably saves time, but I cannot quite put a compelling value on this feature. The ability to cache a delegate calendar so that you can work with it offline is also good. I can make the same comment as I go through other features like support for RSS feeds. All of the new features are nice and add some value, but maybe they are not essential and certainly not enough to change either the way that I work or the way that the company deploys Exchange.

It's not all doom and gloom however. Companies will upgrade to Office 2007 and use Outlook 2007 because of two factors. First, Microsoft has signed them up for upgrades as part of license deals and many small companies will find it a logical step to proceed with an upgrade because they have a relatively small number of clients to migrate. Second, the advent of Vista presents an opportunity for a desktop refresh. It makes a lot of sense to combine an upgrade to a new operating system with a new applications suite alongside a possible hardware upgrade if everything can be accommodated by a company's regular PC refresh cycle. I think Outlook 2007 will have slower acceptance in large corporations than Outlook 2003 has enjoyed so far. Companies who deploy Exchange 2007 don't have to change their desktop clients unless they need some specific functionality or have an opportunity to reduce operating costs.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9781555583552500106

Systems Safety, Normal Accidents, and Social Vulnerability

Rob Kling, in Computerization and Controversy (Second Edition), 1996

Strategies for Improving Systems Safety

Despite the many difficulties cataloged so far, it is apparent from existing systems (space exploration, airline transportation, etc.) that safe systems are not always an impossible dream. In fact, we take safety so much for granted that the fatal explosion of the space shuttle Challenger in January 1986 shocked the nation and cost NASA immense credibility (Heimann, 1993).3 Although the technical failure of the Challenger was caused by faulty seals (O rings), the problem was known to certain managers and engineers in the firm (Morton-Thiokol) that designed the rockets. The nature of a managerial decision to risk the shuttle's launching and cover up the engineering criticisms of possible O ring failures was widely reported after a Congressional inquiry into this disaster. Heimann published an interesting analysis that shows how a change in NASA's organizational structure also made this kind of disaster more likely.

There is a strong cultural bias in North America to focus on discrete causes for system failures—like a broken device, a software bug, a single person's error, or even a cover-up. We are much less likely to examine whether the ways that organizations are structured or the character of their cultures can lead to system failures. Scholars are systematically studying organizational failures and high-performance organizations to better understand these issues (see, e.g., Weick and Roberts, 1993). Only recently have systematic organizational-level analyses influenced the information and computer science professions. But professional interest in developing safe systems should help fuel broader interest in systematic organizational analysis (see Kling and Allen, Part III, Chapter M).

There have been sustained studies of technological strategies for improving the quality of software designs. Software engineering methods incorporate various error-reducing strategies, including systematic testing strategies.4 The licensing of professional programmers (see Jacky's discussion in Part VII, Chapter C) has been suggested. And computer scientists have worked hard to develop a meaningful theoretical basis for software design (see Winograd and Flores, 1987; Dahlbom and Mathiassen, 1993).

Formal verification techniques may help uncover the discrepancies between a program's specification and the actual program. For example, in the fall of 1994, Intel admitted that its highly touted and widely sold Pentium chip was not 100% reliable in carrying out arithmetic calculations. Intel admitted the flaws only after a mathematician publicly criticized the chip's accuracy. Further, Intel lost credibility when it minimized the importance of the problem and was unwilling to automatically replace the millions of Pentium chips that it had sold. Intel's spokespersons claimed that the computational errors were exceptionally rare and would show up only in specially complex calculations. Critics retorted that the errors could occur more frequently and that even common financial calculations,5 could lead to erroneous results. Formally verifying the correctness of the chip's mathematical routines might have avoided the Pentium's problems.

The Pentium fiasco may lead more chip vendors to try verifying the correctness of their chips. Even so, vendors’ claims should be carefully scrutinized, especially claims of “software engineering” and “program verification,” and particularly in contexts where mistakes may be irreversible and catastrophic. Discussions of program verification tend to flounder due to confusion over what the “verification” process actually involves. The Verifiable Integrated Processor for Enhanced Reliability (VIPER) microprocessor was designed in the late 1980s for safety-critical military, space, and transportation applications, such as “fly-by-wire” aircraft and railroad crossing controllers. VIPER includes the equivalent of several million transistors. The sheer complexity of these chips makes guarantees of correctness alluring. VIPER's designers used mathematical proof techniques to help ensure absolute correctness and freedom from design errors. But it was the subject of exaggerated advertising after it was “proven to be free” of design errors (Dobson and Randell, 1989:422). For example, the proofs of correctness do not ensure that the original specifications were correct, and analysts subsequently claimed to have found four specification errors in VIPER's design.

Some of the debates on the meaning and significance of formal verification have been quite heated.6 Brian Smith's paper (Chapter E) provides one lucid interpretation, explaining that a verification (“formal proof of correctness”) establishes relative consistency between a program specification and program code. Smith goes on to observe, however, that if the specification itself reflects a world model that is deficient in some relevant respect, the deficiency will carry over to the program, thus remaining undetected by any formal consistency proof. This point is crucial, for it implies that a computer system with perfectly functioning hardware, and software that adheres accurately to a set of written requirements, may still result in serious failures. The indispensability of robust testing should be apparent in the face of this argument.7 Still, software engineers will argue that formal methods help improve programs by encouraging people to carefully consider their designs and develop simpler systems that are easier to verify.8 Jon Jacky, for example, comments,

… it can be very valuable, and it provides far more assurance than we get from most projects. Even being in a position to attempt such a verification requires that somebody provide a complete and explicit specification that documents what the system is expected to do and reveals the builders’ assumptions about what the system will demand of its environment. Most projects never produce such a specification, and as a result the expected system behaviors and the assumptions about the environment cannot be reviewed or criticized or even examined because they are hidden in the program text itself—usually encoded in some obscure way (they don't call it code for nothing). Because of this, the specification can be as valuable as the verification itself—maybe more so. (Jacky, 1994; Part VII, Chapter C).

Safe technological designs are a key element of safe systems. Jacky's article illustrates how the behavior of equipment users, such as radiological technicians in the case of the Therac-25, is also crucial. The 1991 fiasco in which a power system failure in one of AT&T's switching centers grounded air lanes at three major airports illustrates how high-quality preventive maintenance can also play a key role. Safe systems are most likely to be operated by high-performance organizations that place a premium on the safety of their customers, clients, and employees. Gary Stix's account of the way that the FAA is able to operate a highly reliable air traffic control system with ancient and unreliable technologies underlines this point. However, relatively few organizations have the safety consciousness of the FAA. Given the infusion of computer technology into everyday affairs, it is only to be expected that malfunctions will result in inconvenience, serious harm, or even threats to life, in an ever-widening spectrum.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780124150409501445

What does a professional programmer usually do first to gain an understanding of the problem?

What does a professional programmer usually do first to gain an understanding of a problem? Programmers will conduct an initial interview with their customer to understand what exactly the customer wants out of the program and how it should function.

What is the first step of the programming process?

The first step is to examine the problem carefully to try to identify what qualifies as a solution. A single problem may have many different solutions, but they will all have something in common. So here you're trying to work out exactly what your program will be required to do. and display the result for the user.

What are the 5 steps of the programming process?

There are five main ingredients in the programming process:.
Defining the problem..
Planning the solution..
Coding the program..
Testing the program..
Documenting the program..

What does a programmer do during the analysis?

What does a programmer do during the analysis phase of software development? Writes the algorithms for solving a problem. -A programmer will write an algorithm for solving the problem during the analysis phase of software development and analyses the efficiency of the algorithm while solving the problem.