Introduction to Computer Information Systems/Program Development
- 1 Program Design and Development
- 2 Program Development Life Cycle - Analysis, Design, Coding
- 3 Program Development Life Cycle - Debugging and Testing, Implementation and Maintenance
- 4 Program Development Tools
- 5 Programming Languages
- 6 Key Terms Review
- 7 Review Questions
- 8 Review Answers
- 9 References
Program Design and Development
Procedural programming is more or less self explanatory, it’s procedural so it will go step by step in order to solve a problem. This was a much older type of programming language that has since been outdated by object oriented programming. However this type of programming is very important and should be well understood if you want to understand the concepts of programming and what all goes into it. This process is also called imperative programming in some contexts, meaning top-down languages; this is how the programming functions, from a top to bottom procedural order. This is what makes this process self-explanatory in a way, because in order for something to work and pass along a message we assume it to go in this order. Along with going step by step in order to solve a problem, the list of instructions must be sent to the computer in order for it to know what to do with this information. It relies on routines, or procedures, that have multiple steps that need to be carried out. Procedural programming has been somewhat of a stepping stone for other types of programming because of its simplicity. It is an older type of programing and is now outdated by another popular form which is object oriented programming.  Object oriented programming is more focused on objects to make a program instead specific steps. An object, such as a person, should have a name, or be able to walk, which can be seen as a method in oriented programming. Having a method is this programming is like having a procedure in procedural programming.  One of the most popular object oriented programming languages is Java, which is used virtually everywhere. Objects within an object oriented program consists of attributes. If you have ever played D&D you know that your character has different attributes that would define them. If you have an object you can change its attributes like size, shape, and color.
Aspect Oriented Programming is a form of programming that compliments Object Oriented Programming (or OOP) by allowing the developer to modify OOP in a way where the system can grow to meet new requirements. It keeps the original model, which was developed in OOP, but allows for new syntax without having to change the compiler being used or reconfigure the editor either. In essence, it is complimentary to the previously developed OOP style and allows the application to adopt new characteristics over its lifetime without having to be completely remodeled or redeveloped. This ability for an application to be adapted to the current trend in technology prolongs the usefulness and life span of the application, which then benefit the users of that application as well. 
Adaptive software development consists of cyclical speculation, collaboration, and learning rather than the more traditional approach of linear planning, building, and implementation. First, the term "speculate" is used, because outcomes can never be fully predicted to the point of "planning" -- but also, of course, it would be a waste of time to wander around aimlessly without any organized approach. A mission is still defined; it is just acknowledged that the mission can never be inclusive of all possible outcomes and may need to be changed. Second, the term "collaborate" shows that management, per this model, does not just focus on "managing the doing" -- i.e. delegating instructions and seeing fit that they are followed -- but also focuses on fostering and maintaining a collaborative environment that is needed for real growth to take place. This can be difficult, because, per this model, that environment is often at the "edge of chaos" -- that is, a project can't be fully structured, because then nothing new can emerge, but things can't teeter over the edge into anarchy. Finally, there is a focus on learning from mistakes on the part of both the developers and the consumers. These three-phase cycles are short so that small mistakes, not large ones, are the ones from which lessons are learned.
Program Development Life Cycle - Analysis, Design, Coding
The following are six steps in the Program Development Life Cycle:
1. Analyze the problem. The computer user must figure out the problem, and the best program to fix it.
2.Design the program. A flow chart is important to use during this step of the PDLC. This is a visual diagram of the flow containing the program. All in all, this step is breaking down the problem.
3. Code the program. This is using the language of programming to write the lines of code. The code is called the listing or the source code. The computer user will run an object code for this step.
4. Debug the program. The computer user must debug. This is the process of finding the "bugs" on the computer. The bugs are important to find because this is known as errors in a program.
5. Formalize the solution. One must run the program to make sure there are no syntax and logic errors. Syntax are grammatical errors and logic errors are incorrect results.
6. Document and maintain the program. This step is the final step of gathering everything together. Internal documentation is involved in this step because it explains the reasoning one might of made a change in the program or how to write a program.
Flowcharts and Pseudocode
During the design process of the Program Development Life Cycle, it is important that programmers (and non-programmers) are able to visualize the way in which the program will work. Certain tools such as flowcharts and pseudocode are used to simplify the design process and allow the developers to see the program before any actual coding is used. A common type of design tool is the flowchart. A flowchart can be either handwritten or created with software such as Visual Logic or Flowgorithm  Many of these software programs have similar symbols to represent certain actions such as input, output, assignments, and various types of loops. Flowcharts are also useful for education tools because they focus more on the concept of programming rather than focusing on the syntax of languages. Another type of design tool is pseudocode. Pseudocode is very similar to a programming language except that it uses non-syntactical words to summarize the processes of a program. Pseudocode cannot be compiled or executed but it does serve as a good starting point for programmers.  Here is an example of pseudocode:
- If user’s age is greater than or equal to 18:
- Print “You can vote”
- Print”You cannot vote”
A compiler is a special program that processes statements written in a particular programming language and turns them into machine language or "code" that a computer's processor uses. When executing (running), the compiler first parses (or analyzes) all of the language statements syntactically one after the other and then, in one or more successive stages or "passes", builds the output code, making sure that statements that refer to other statements are referred to correctly in the final code. A compiler works with what are sometimes called 3GLs (FORTRAN, BASIC, COBOL, C, etc.) and higher-level languages. There are one-pass and multi-pass compilers as well as just-in-time compiler, stage compiler, and source-to-source. The compiler frontend analyzes the source code to build an internal representation of the program, called the intermediate representation. The compiler backend includes three main phases, such as analysis, optimization, and code generation.  Because compilers translate source code into object code, which is unique for each type of computer, many compilers are available for the same language. For example, there is a FORTRAN compiler for PCs and another for Apple Macintosh computers. In addition, the compiler industry is quite competitive, so there are actually many compilers for each language on each type of computer. More than a dozen companies develop and sell compilers for the PC. 
Program Development Life Cycle - Debugging and Testing, Implementation and Maintenance
A control structure is a diagram used to show how functions, statements, and instructions are performed in a program or module. The diagram shows exactly when an instruction is performed, and how it’s performed. Most importantly, a control structure shows the order of the instructions. There are three basic types of control structures: sequence, selection, and repetition. Choosing a specific control structure depends on what you want the program or module to accomplish. A sequence control structure is the simplest and least complex control structure. Sequence control structures are instructions that are executed one after another. The structure could be compared to following a recipe. A more complex control structure might be a selection control structure, a structure that involves conditions or decisions. This means that the structure can allow different sets of instructions to be executed depending on whether a condition is true or false. The last basic control structure is a repetition control structure, which is sometimes called an iteration control structure. This control structure is used when repeating a group of code is necessary. The code will be repeated until a condition is reached. Repetition control structures are used when looping is needed to reach a specific outcome.
Testing Program Design
Good program design needs to be specific. The program design is very important, especially because it involves the overall step-by-step directions regarding the program. A programmer must test the program design to ensure that it runs correctly and that there are no mistakes. The operation a programmer must to do complete this task is called desk checking. Desk checking allows the programmer to run through the program design step-by-step. Essentially, the programmer runs through lines of code to identify potential errors and to check the logic. The programmer uses tracing tables to keep track of any loop counters. The goal of checking the program design is to avoid running into mistakes further on in the program development cycle. The sooner the mistake is caught in the development cycle the better. If the error is not found until later in the developmental cycle, it may delay a project. Therefore, a programmer must make sure they pay strict attention while desk checking. Advantages to desk checking include the convenience of hands-on "proof-reading" of the programmer’s own code. The programmers wrote the code themselves, so it is an advantage that they can work immediately with familiar code. A disadvantage to the desk checking system includes potential human error. Since a computer is not checking the design code, it is prone to human error. 
Debugging is basically making sure that a program does not have any bugs (errors) so that it can run properly without any problems. Debugging is a large part of what a programmer does. The first step to debugging is done before you can actually debug the program; the program needs to be changed into machine language so that the computer can read it. It is converted using a language translator. The first goal of debugging is to get rid of syntax errors and any errors that prevent the program from running. Errors that prevent the program from running are compiler errors. These need to be removed right away because otherwise you cannot test any of the other parts of the program.  Syntax errors occur when the programmer has not followed the correct rules of the programming language. Another kind of error is a runtime error, which occurs while the program is running and it is not noticed until after all syntax errors are corrected. Many run time errors are because of logic errors, which are errors in the logic of the program. It could occur when a formula is written incorrectly or when a wrong variable name is used. 
There are different types of debugging techniques that can be used. One technique called print debugging, or also known as the printf method, finds errors by watching the print (or trace) statement live or recorded to see the execution flow of the process. This method originated in the early versions of the BASIC programming language. Remote debugging is the method of finding errors using a remote system or network, and using that different system to run the program and collect information to find the error in the code. If the program has already crashed, then post-mortem debugging can be used through various tracing techniques and by analyzing the memory dump of the program. Another technique is one created by Edward Gauss called wolf-fence debugging. Basically, this method find the error by zeroing in on the problem by continuous divisions or sectioning until the bug is found. Similar to this is the saff squeeze technique which uses progressive inlining of a failure test to isolate the problem. 
Debugging a program can be done by using the tools provided in the debugging software. Typically, and especially with high-level programming languages, specific debugging tools are already included in the. Having language-specific debugging tools make it easier to detect the errors in a code, because they can look for known errors as opposed to tediously “walking through” the code manually. It also good to note that fixing one bug manually may lead to there being another bug; this is also why language-specific debugging tools are helpful. There are also debugging software for embedded system as well. 
Testing/Implementation and Maintenance
Relating to getting a program up and running, many things need to happen before it can be used. One step is to test the program. After the debugging process occurs, another programmer needs to test the program for any additional errors that could be involved in the background of the program. This person needs to perform all of the tasks that an actual user of the program would use and follow. To ensure privacy rights, test data is used in the testing process. However, this still has the same structure and feel to the actual data. The tester needs to check for possible input errors as well, as this would create many problems and issues in the future had it not been checked. Companies usually implement different types of tests. An Alpha test  is first conducted, which is on-site at the company, and Beta tests are sent out to different states or countries to ensure the program is 100% ready for use. The Alpha test occurs before the Beta test. Once the debugging and testing are finished, the program is now in the system and the program implementation and maintenance phase are completed. Program maintenance still needs to be kept up, in case of future errors. This is the most costly to organizations because the programmers need to keep improving and fixing issues within the program.
As stated earlier, a program goes through extensive testing before it is released to the public for use. The two types of testing are called Alpha and Beta testing. First, it is important to know what each test does. Alpha testing is done “in house” so to speak. It is done within a company prior to sending it to Beta testing and its intention in this early stage is to improve the product as much as possible to get it Beta ready. Beta testing is done “out of house” and gives real customers a chance to try the program with the set intention of catching any bugs or errors prior to it being fully released. Alpha testing is the phase that takes the longest and can sometimes last three to five times longer than Beta. However, Beta testing can be completed in just a few weeks to a month, assuming no major bugs are detected. Alpha testing is typically performed by engineers or other employees of the company while Beta testing occurs in the “real world”, temporarily being released to the public to get the widest range of feedback possible. During Alpha testing, it is common for there to be a good amount of bugs detected as well missing features. During Beta testing, there should be a big decrease in the amount of these problems. When testing in the Alpha phase is over, companies have a good sense of how the product performs. After Beta testing is complete, the company has a good idea of what the customer thinks and what they experienced while testing. If all goes well in both phases, the product is ready to be released and enjoyed by the public. The length of time and effort that is put forth in order for the world to enjoy and utilize the many programs on computers today is often overlooked. Information such as this gives the user a new appreciation for computers and computer programs. 
Program Development Tools
Adobe Air allows the user to package all of the code into applications for Windows, MacOS, iOS, and Android desktops. Adobe air reaches billions of desktops and apps for 500 million devices. There are many applications that can be used with adobe air. Adobe air can open books online and allow the user to be able to read them easily that way. You can change the font size, quickly get to a page, and go to a full screen while reading the book. Adobe Air can also open desktop blog editor and allow the user to use HTML/Javescript. An example of this type of application is Bee. It can use word to start a blog and the user can add photos easily and allow the blog to flow evenly. BkMark is another application that can be used on Adobe Air. It allows the user to make bookmarks for favorite websites. It store actual data and allows you to reopen any website that you want to go to. It is really convenient application for users who want something fast to go to a commonly used website. Finally another example of an application that can be used with Adobe Air is dAIRnotes. This allows the user to make notes on the computer and keep track of all of the notes. 
Application Lifecycle Management (ALM) Tools
ALM tools are, surprise surprise, tools that manage an application throughout its entire life cycle. They are very helpful for programmers who are under increasing amounts of stress to develop new programs quickly. The helpfulness comes from wide range of features that the ALM tools can offer. One example is how many ALM programs come with built-in program design tools, along with the ability to generate the program code from the finished design to create the application. This code generating ability saves companies time and money that they don't have to put towards outsourcing, especially if they've got a small number of programming staff. In addition to code generators, another important tool that can be included in ALM programs is requirements management. Essentially, requirements management is defined in exactly that way, referring to keeping track of and managing program requirements as they are defined and then modified throughout the process of developing the program. The larger the company, the nicer ALM toolset they can purchase; there are many ALM toolsets on the market to choose from.
Application generators are extremely useful devices. They can be used by amateurs/people with less experience or by professionals. The point of an application generator is to make a task simpler than it is. Even if it is just changing a few basic formatting characteristics, these generators can make it so that the user only has to type in a specific key or command in order for all the actions to happen at once with much less effort. One of these useful generators is called a Macro. A macro is an application generator that simply makes it possible to perform repeated actions instantaneously on a single command. The idea is that it will make reformatting or calculating things much easier, thus saving the operator time . Most Microsoft programs contain a macro recorder which allows users to easily record all inputs and commands they use and associate them with a keyboard shortcut for future repetition. Other application generators create reports and form which make things such as memberships, records (such as medical treatments, history, and vaccinations), and even insurance claims more organized and easier to access by those who should be able to access them.
A few key features about RIAs include direct interaction, partial-page updating, better feedback, consistency of look and feel, offline use, and performance impact. 
Direct interaction allows for a wider range of controls, such as editing or drag-and-drop tools. Partial-page updating allows for real-time streaming and cuts down on load time waiting for a response from a server. RIAs can provide users with quicker feedback because of the partial-page updates. Also, it is sometimes possible to use RIAs offline when there is no connectivity. Once downside to RIAs is that smaller devices, such as mobile phones, often times do not have the means necessary to run such applications.
What is a Programming Language?
A programming language is designed to communicate instructions to a computer and so the computer can interpret the instructions and make sense of them. They are used to create programs that control the behavior of a machine and algorithms. There are multiple languages created into this program which are created from different styles or forms. The description of a programming language is known to be split into the two components of syntax (form) and semantics (meaning). The syntax is the form in which the language is presented in and the actual sense or meaning of the instructions is the semantics. A program is written so that it can be understood by computer so that the instructions can be interpreted, translated into so the computer can eventually make sense of it. So the moment you turn on your computer after it starts to run programs, it interprets these instructions, tests the ram and resets all attached devices and loads the operating system from hard disk. Every operation that the computer holds has instructions that someone had to translate into a programming language. With every language, they have to be created, compiled and tested which tends to be a long and complex task.
Categories of Programming Languages
Two categories that programming languages can fall under are procedural (programs that use the procedural approach) and object (for those programs that use the object-oriented approach). However, probably the most common way of categorizing programming languages is by their designation into a tier structure. Programming languages can fall under low-level languages, high-level languages, and very high-level languages. Low-level languages, which are made up of the first generation language, machine language, and second generation language, assembly language, are written at a very low level: programming consists of 0s and 1s for machine language and assembly language includes names and symbols for some of the 0s and 1s. These languages allow computer hardware to read commands quickly, but this happens at the cost of a much steeper learning curve as opposed to higher level languages. High-level languages, on the other hand, are easier to use because they are closer to natural language. They are also machine independent: programs written on one computer can be transferred to another computer without modification. This is in contrast to the machine dependent-nature of low-level programs where modification is necessary. Lastly, very high-level languages, also known as fourth-generation programming languages, are more difficult to distinguish from high-level languages. Fourth-generation languages (4GLs) are known to be declarative, which does not specify exactly how a computer should go about processing a command. This results in programmers using very little code. Although, those languages deemed very-high level languages in the past (e.g. Visual Basic, Python, Perl) have now been called simply high-level languages 
There are some high-level programming languages that are visual programming languages or graphical programming languages. They are referred to by these names because they have a graphical interface. In these programs, instead of typing program code, a user can drag and drop objects to generate the needed code. There are even programs that incorporate visual elements that help with coding but also still require actual coding. These kinds of programs are called visual programming environments (VPEs) One of the first programming languages to use a visual programming environment was Visual Basic. The convenience of visual programming environments is that you can drag and place objects but also with a code is typed, the program assists in creating the code by listing options. These helps users learn appropriate codes. An online definition of visual programming environments describes it as software which allows the use of visual expressions (such as graphics, drawings, and animations or icons) in the process of programming. These visuals items are then used as graphical interfaces for textual programming languages. These kinds of visual programming languages software are also used for educational purposes and in the future may be the most common programming language. Scratch is one example of an educational visual programming environment for children. As mentioned above, Visual Basic was one of the first programming languages to use visual programming environment, but since then C++, Pascal, and Java have also begun to create visual programming environments. 
Common Programming Languages
There are many programming languages out there that are still, to this day, used immensely on a day-to-day basis. Fortran, which is one of the older options, is used mainly in the scientific field for scientists, mathematicians, and formulating numerical formulas. Cobol is another programming language commonly used today, and can typically can be seen utilized in business environments for everyday transactions. This language is seen as extremely time consuming, and more and more businesses today are starting to move away from it, towards quicker processes. Pascal is yet another language that is used commonly in math and science programs. The Pascal programming language obtained its name from the famous mathematician, Blaise Pascal. It was created by Niklaus Wirth, a member of the International Federation of Information Processing Working Group. He created the Pascal programming language because he wanted to include new features that past programming languages did not provide. It was originally created as a teaching tool and uses control structures in its software. The use of control structures helped the programming language become more structured and organized compared to other languages, which is why it was used as a teaching tool. Pascal was published in 1971 and revised in 1973, which allowed for it to stay prominent in colleges from the 1970’s and into the late 1980’s. One of the new features of Pascal was the new data types, like Integer, Real, Character, and Boolean. These new types are what allowed Pascal to become a programming language used strongly in mathematic programs. Another new feature was a strong data typing element, which allowed the compilers for Pascal to see and correct an incompatible assignment in one type in accordance to a variable in a different type. This further helped keep the organized structure of Pascal and enabled it to be used more in college level classes. Pascal was a great creation for the programming language world.
Another common programming language is Basic. It is one of the most used languages because it can be considered user friendly. It was designed to be an uncomplicated and stressful language that is used typically for interactive programs. It is extremely easy to get to know, and many people enjoy its simplistic and understandable functioning. One aspect of basic is Visual Basic, which again uses their understandable language, but is focused on visual aid. These are just a few examples of the immense and intricate amount of languages that are out there. Though many of these are still used today, it is obvious that some of the older and more time-consuming software is on its way out. 
On the other hand, there are also some programming languages that are no longer widely used today. Among these programming languages are LISP and Prolog. Specified in 1958, LISP (LISt Processing) is the second-oldest high-level programming language, running right behind Fortran. It allows a code to be expressed in the same form as the data structures in the language, which is very beneficial when performing genetic algorithms or symbolic manipulation. On the other hand, in the early 1970s, Prolog was designed for natural language processing, and logical reasoning. This language allowed using similar grammars to translate logical representation back into language. Being a dialect of LISP comes another language used to teach children how to program: The Logo Programming language. To act as a tool for learning, its features included modularity, extensibility, interactivity, and flexibility. Another third generation programming language not used today is PL/I, “Programming Language 1.” This language was developed as an alternative to Cobol (large-scale business applications) and Fortran (scientific and algorithmic applications). Lastly, and most importantly, comes one of the first object-oriented programming languages: SmallTalk. As there is no such language called SmallTalk any more, other different languages like SmallTalk-xx (the xx being the year that the language was finalized,) have gradually taken its place. Therefore, although new languages such as C, Java, or PHP have now taken over, old programming languages still play a significant role behind the shift to the new and better technology.
Java is a high-level, object-oriented programming language that is designed to let developers write once, run anywhere. This means that the coding does not have to be recompiled for various platforms and can run the same on any system. The language was developed by Sun Microsystems in 1995 and was released to the public as open source software in 2007. Since then, the language has become one of the most popular programming languages in the world, particularly for client-server web applications. Much of the syntax used is derived from other programming languages C and C++. Java programs are compiled into the bytecode format, which can be run on any computer that runs Java virtual machine no matter how simple or complex the computer’s architecture may be. One popular application for the Java language is Java applets, which are small programs that can be inserted into a web page of a java-enabled web browser. These applets can be used to run games, banner ads, scrolling text, or various other types of programs from inside the browser. These applets are inserted into the HTML statements of the web page just as an image would be added. The applet is downloaded from the host server of the webpage when being displayed, allowing for the program to run on the viewer’s computer. 
Python is an open source, dynamic object-oriented programming language. Python can be used to develop a variety of applications, including gaming, database, and Web applications. It's a freely available programming language and can run on almost any computer without needing to change the program. Python's compatibility is the reason it's used daily in the Google search engine, Youtube, NASA, and the New York Stock Exchange. Also, due to its readability, ease of acquisition, and extensibility, Python was recently chosen by MIT for students learning to program. Another open source object-oriented programming language, often compared to Python, is Ruby. Ruby can be used to create both Web applications and general-purpose programming for Linux, Mac OS X, and Microsoft Windows computers. Similar to Python, Ruby uses a syntax that is relatively easy to read and write. A difference, however, is that Ruby tends to presume upon the programmer's intentions, while Python's information is typically plain in syntax. Ruby on Rails (RoR) is a framework for developing dynamic Web applications that are written in the Ruby programming language. RoR applications run on a variety of types of Web servers and with a variety of databases, consequently growing rapidly in use and popularity.
Key Terms Review
Procedural programming: An approach to program design in which a program is separated into small modules that are called by the main program or another module when needed.
Variable: A named memory location defined in a computer program that is used to store the current value of a data item used in that program.
Object-oriented programming (OOP): An approach to program design in which a program consists of objects that contain data (attributes) and processes (methods) to be used with those objects.
Aspect-oriented programming (AOP): An approach to program design in which different functions are clearly separated so program components can be developed and modified independently from one another, and the components can be easily reused with separate, nonrelated objects.
Program development: The process of creating application programs.
Program development life cycle (PDLC) The process containing the five phases of program development: analyzing, designing, coding, debugging and testing, and implementing and maintaining application software.
Problem analysis: The phase of the program development life cycle in which the problem is carefully considered and the program specifications are developed.
Programmer: A person whose job it is to write, test, and maintain computer programs.
Program design: The phase of the program development life cycle in which the program specifications are expanded into a complete design of the new program.
Flowchart: A program design tool that graphically shows step-by-step the actions a computer program will take.
Pseudocode: A program design tool that uses English-like statements to outline the logic of a program.
Unified Modeling Language (UML): A set of standard notations for creating business models; widely used for modeling object-oriented programs.
Control structure: A pattern for controlling the flow of logic in a computer program, module, or method.
Sequence control structure: A series of statements that follow one another.
Selection control structure: A series of statements in which the results of a decision determine the direction the program takes.
Repetition control structure: A series of statements in a loop that are repeated until a particular condition is met.
Program coding: The phase of the program development life cycle in which the program code is written using a programming language.
Coding: The process of writing the programming language statements to create a computer program.
Source code: A computer program before it is compiled.
Program debugging and testing: The phase of the program development life cycle that ensures a program is correct and works as intended.
Debugging: The process of ensuring a program is free of errors.
Object code: The machine language version of a computer program generated when the program's source code is compiled.
Language translator: A software program that converts source code to object code.
Compiler: A language translator that converts an entire program into machine language before executing it.
Interpreter: A language translator that converts program statements line-by-line into machine language, immediately executing each one.
1.) What is a computer program called before it is compiled?
2.) A program design tool that graphically shows step-by-step the actions a computer program will take is called a _______?
3.) What phase of the PDLC has the program code written using a programming language?
4.) If your job is to write, test, and maintain computer programs, you are a _______.
5.) What language translator converts an entire program into machine language before executing it?
6.) What process ensures a program is free of errors?
7.) What is the process of creating application programs?
8.) How many phases are there in the program development life cycle?
9.) List the phases of the PDLC in order.
10.) What is a software program that converts source code to object code?
1.) Source code 2.) Flowchart 3.) Program coding 4.) Programmer 5.) Compiler 6.) Debugging 7.) Program development 8.) Five 9.) Analyzing, designing, coding, debugging and testing, implementing and maintaining application software 10.) Language translator
- Understanding Computers 14th ed. by Deborah Morley & Charles Parker