Translate

Search This Blog

Total Pageviews

Friday, November 30, 2018

Object-Oriented Software Development

Have you ever wondered why some organizations refer to the group responsible for computers and information systems as “data processing”?
  1. Structured programming and structured design (which grew out of structured programming) understand the mission of software as that of processing data.
  2. Structured programming and structured design are focused on the changes programs make in transforming input data to output data, seeing computer programs as action-oriented.
The early name of the computer programming profession—data processing—reflects this procedural perspective.

Object-oriented programming and design emphasize the view that software systems model the real world. 
Objects within an object-oriented system may still transform input data to output data, but this is not the only possible way to organize an object-oriented program.
From an object-oriented perspective, the group responsible for computers and information systems might aptly be named the Business Object Portfolio (BOP) group. Their function, is to assemble and maintain a portfolio of objects that model their organization’s processes.
If  you’re therefore less than enthusiastic about the prospect of being called a BOPper, never fear. You can choose to work in the health care industry, in which case you may come to be known HOPper (for “Health care Object Portfolio”) or
MOPper (for “Medical Object Portfolio”). That’s decidedly better than working in law enforcement, where you might come to be known as a COPper (for “Crime Object Portfolio”), or working in agriculture, where you might come to be known as a CROPper (for “Crop Rotation Object Portfolio”).


                            Procedural Programs

Computer programs, whether designed based on structured design or object-oriented design, usually model some process that exists in the real world.
A payroll program, for example, models the manual process that a real business goes through when it pays its employees. In a small business, the process might work something like this:
  1. Get the list of employees from the file over by the coffee machine.
  2. Get the federal and state withholding schedules out of the bottom right drawer of the desk.
  3. Get the general ledger from the supervisor’s office.
  4. For each employee on the list, do the following:
  5.   (4.1). Get the amount of pay from the employee record.
  6.   (4.2).  Calculate the amount of taxes due, based on the  withholding schedules.
  7.   (4.3). Calculate the net pay by subtracting the deductions and withholding from the gross pay.
  8.   (4.4). Prepare the check.
  9.   (4.5). Record the check in the general ledger.
  10. (5). Take the stack of checks to the boss to be signed.
  11. (6). Mail the checks at the post office.
  12. (7). Return the general ledger, withholding schedules, and list of employees to their regular places.
Most of these operations could be performed by a computer, though the computer wouldn’t do them exactly the same way the payroll clerk would.
  1. When written as part of a computer program, the steps necessary to carry out a task are called a process
  2. Each step within a process is known as a procedure
  3. When a procedure is long or complex, it may consist of several steps, called subprocedures or simply procedures.
  4. Procedures are the blocks used to build structured programs.
A typical payroll program, for example, would contain procedures to
  • open and read the files, 
  • perform the payroll calculations, and 
  • print the checks.
  • By using direct deposit, the program might even “sign” and “mail” the checks.
A procedural payroll program is structured like

Each of the boxes in Figure represents a procedure that carries out a series of steps.
Each procedure
  1. receives input data, 
  2. processes the data, and 
  3. transmits the results of its processing, either to a subsequent procedure or to a human.
Data is fed to the procedures in much the same way that raw materials are fed to an assembly line—except the procedures produce information rather than cars or toasters.
A useful property of structured programs is that the “shape” of the solution (that is, the program) closely models the shape of the problem. 
Each of the procedures of the structured program in Figure relates to one or more of the steps in the process for manually preparing payroll checks.
Structured programs are designed by means of procedural decomposition
Using procedural decomposition, a designer studies the problem and attempts to break it apart by identifying a series of actions that solve it.
When a designer is asked to automate an existing business process, the design process is often simple because procedural decomposition is easy to perform. The designer merely uses the steps of the manual process to identify the actions that the program must perform. Because these steps have successfully kept the business from devolving into chaos, using them as the basis for a computer program may be less risky that trying an entirely new series of steps.
Think again, though, about what would happen to the manual payroll process in your imaginary business if it grew to 20,000 employees instead of 20.
  • The employee file could no longer be kept in the filing cabinet over by the coffee machine. 
  • Fred, the part-time bookkeeper, could no longer finish his work each Tuesday afternoon. 
  • And, most importantly, the boss, who previously signed every check and would likely notice if Ms.Smallie’s check had $1,000 written on it, instead of $100, could no longer sign each check personally—there simply wouldn’t be enough remaining time to properly watch over the business.
When businesses grow, they change their structure to handle the added complexity caused by their growth. Finance departments, vice-presidents, controllers, and auditors are added because the simple structure that worked fine for a 20-person company is no longer adequate.
Computer programs can suffer from a similar malady. The  procedural paradigm (paradigm is just a fancy word for pattern) works fine for automating routine office processes, like preparing payroll checks. But it fails to offer sufficient structure when applied to many other kinds of problems, such as simulations and interactive environments.

If you’ve been around a while, you might remember when the main job of computer programmers and designers was writing programs that solved “assembly-line” problems like
  • payroll, 
  • batch accounting, and 
  • monthly invoicing.
Things are different today.
  • Instead of being assigned to write a data-processing program to tally the month-end statements, a bank programmer is more likely to be responsible for writing code to control the ATM or the bank’s new World Wide Web site. 
  • A programmer for a stock broker might design automatic trading programs instead of a simple client billing application.
  • Such interactive or “reactive” programs are much more complex than traditional data-processing applications, because the flow of control is no longer linear. Data doesn’t come in at the start of the program, flow through a number of predefined procedures, and exit at the end, relaxed and refreshed. 
  • In a reactive program, the procedure DoThingC() might be called first, second, last, or not at all—unlike the procedural program where DoThingC() always follows DoThingA() and DoThingB().
Look back at Figure What does it look like? A pyramid, right? The pyramid structure occurs because of the hierarchical nature of control in the program.
ReadEmployeeRecord() relies on the fact that ProcessPayroll() has already performed the OpenEmployeeFile() process. The data and the environment required by ReadEmployeeRecord() are available only because the OpenEmployeeFile() procedure has been called first.
If you attempt to write an interactive program that uses procedures as its basic building block, however, the program structure no longer resembles a neat pyramid. Instead, it begins to look like a dense web of interconnections.

If you remember your first programming class, this might set off a light bulb.
  1. Before the advent of structured programming, back in the days of “iron men,” when “big-iron” was not merely metaphorical, computer programs were largely monolithic—they had no procedures at all. Thus, when a programmer needed to execute a piece of code in another part of the program, an unconditional branch was used; such branches were called gotos. As programs got larger, the typical path of program execution began to resemble a large web. Such code became known as spaghetti code, code that was difficult or impossible to understand and thus difficult or impossible to maintain, fix, or change. The underlying problem was that programs were organized as a collection of source statements. Too many “blocks” (that is, source statements) were required to build large programs. 
  2. To solve this problem, structured programming introduced the procedure as a second, larger organizing unit. Source statements were used to build procedures, but procedures (not source statements) were used to build programs. Thus, the number of blocks required to build a program decreased, reducing the complexity of the program.

                  Object-Oriented Programs

Object-oriented programming attacks the complexity of today’s programs in a similar fashion. By grouping procedures into still larger organizing units called objects, programs require fewer blocks and are, therefore, simpler.

Studying object-oriented programming, it’s hard not to notice the fact that different folks have very different views when it comes to OOP.
Reading various OOP books and papers, it almost seems that people are talking about entirely different things.
When you finally cut through all the rhetoric, though, there are two points of view:
  1. the revolutionary: The advocate of the revolutionary view loudly proclaims that OOP is so different from traditional programming that you have to learn programming over again from scratch.
  2. the evolutionary: The evolutionists, in contrast, say that OOP is really just new packaging of old concepts. Perhaps there’s some truth, as well as some error, in each of these views.


The evolutionists are correct when they assert that it is possible to write clear, well-commented, understandable code in a procedural language, and that it is possible to write incomprehensible, unmaintainable code in an object-oriented language.
The evolutionist generally fails to recognize, however, that an OOP program is organized in a fundamentally different manner than a procedural program.

The revolutionist is right in pointing out that the OOP design process uses different tools and different types of abstraction, and that no amount of functional decomposition will ever yield an object-oriented program.
The revolutionist overestimates, perhaps, the value of such an object-oriented design when weighed against factors of clarity and understandability.
A well-designed and implemented procedural program is definitely to be preferred over a poorly conceived and written OOP program. OOP and object-oriented languages provide tools to express ideas clearly, but are not instant, automatic panaceas.
Five fundamental concepts govern object-oriented programs:
  • Objects
  • Classes
  • Encapsulation
  • Inheritance
  • Polymorphism

                      What Are Objects?

Just as procedures are used to build structured programs, objects are used to build object-oriented programs.
An object-oriented program is a collection of objects that are organized for, and cooperate toward, the accomplishment of some goal. 
Every object:
  • Contains data. The data stores information that describes the state of the object.
  • Has a set of defined behaviors. These behaviors are the things that the object “knows” how to do and are triggered by sending the object a message. 
  • Has an individual identity. This makes it possible to distinguish one object from another, just as it’s possible to distinguish one program variable from another.
Like the records or structures used in procedural programs, objects contain data. In this sense, an object looks very much like one of the employee records that would be used in the payroll program. An object’s data is used to represent the object’s state. For example, data within an employee object might indicate whether an employee is full-time or part-time, hourly or salaried.

Unlike the employee record within a procedural program, however, an employee object can also contain operations. These operations may be used to read or change the object’s data.
In this sense, an object acts like a small “mini-program” that carries its own data around on its back
If you want to do something to an object, or want to know something about it, you “ask it” to perform one of its operations. In object-oriented parlance, you send it a message.
In response, it performs some behavior.

The second characteristic of an object, then, is that it has some built-in behavior: An  employee object may know how to tell you its salary, or how to print itself out to a mailing-address label.
The third characteristic of an object is that every object has a unique identity. This doesn’t mean that every object necessarily has an ID number, or a “primary key” like you find in relational databases. Objects are very much like program variables in a procedural language. 
The integer variables i and j may have exactly the same value—say 3—and yet they are distinct variables, stored at different locations within the computer’s memory.
Changing the value of i to 4, for example, does not change the value of j.
Similarly, two employee objects that represent the identical twins who work in shipping, Fred and Ned, may have the same data contents, yet still be distinct objects.

Much, but not all, of the terminology used in object-oriented programming is the same from programming language to programming language. However, knowing about the differences in terminology might help you avoid some confusion when you find yourself “talking objects” to a Smalltalk or Object Pascal or C++ programmer.
In Java, the operations of an object or class are called methods, just as in Smalltalk.
C++ programmers call methods member functions.
While Smalltalk programmers always speak of sending a message, C++ programmers tend to refer to calling a member function.
Java programmers tend to split the difference, and speak either of  sending a message to an object, or calling an object’s method, depending on whether it is the sender or the recipient of the message that is the focus of discussion.




[to be continued...]

Java beginner5: Conditionals and Logic

The programs we’ve seen in previous lessons do pretty much the same thing every time, regardless of the input. For more complex computations, programs usually react to the inputs, check for certain conditions, and generate appropriate results.
This lesson presents the features you need for programs to make decisions:
  • a new data type called boolean
  • operators for expressing logic, and 
  • if statements.

                              Relational Operators

Relational operators are used to check conditions like
  1. whether two values are equal, or 
  2. whether one is greater than the other.
The following expressions show how they are used:

x == y // x is equal to y
x != y // x is not equal to 
x > y // x is greater than y
x < y // x is less than y
x >= y // x is greater than or equal to y
x <= y // x is less than or equal to y

The result of a relational operator is one of two special values,
  1. true or 
  2. false.
These values belong to the data type boolean; in fact, they are the only boolean values.
You are probably familiar with these operations, but notice that the Java operators are different from the mathematical symbols like =, ≠, and ≤.
  1. A common error is to use a single = instead of a double ==. Remember that = is the assignment operator, and == is a comparison operator. 
  2. Also, there is no such thing as the =< or => operators.
  3. The two sides of a relational operator have to be compatible. For example, the expression 5 < "6" is invalid because 5 is an int and "6" is a String. When comparing values of different numeric types, Java applies the same conversion rules we saw previously with the assignment operator. For example, when evaluating the expression 5< 6.0, Java automatically converts the 5 to 5.0.
  4. Most relational operators don’t work with strings. But confusingly, == and != do work with strings—they just don’t do what you expect. We’ll explain what they do later; in the meantime, don’t use them with strings. Instead, you should use the equals method:
    String fruit1 = "Apple";
    String fruit2 = "Orange";
    System.out.println(fruit1.equals(fruit2));

    The result of fruit1.equals(fruit2) is the boolean value false.

                              Logical Operators

Java has three logical operators: &&, ||, and !, which respectively stand for and, or, and not. The results of these operators are similar to their meanings in English.
For example, x > 0 && x < 10 is true when x is both greater than zero and less than 10. The expression evenFlag || n % 3 == 0 is true if either condition is true, that is, if evenFlag is true or the number n is divisible by 3.

Finally, the ! operator inverts a boolean expression. So !evenFlag is true if evenFlag is not true.
Logical operators evaluate the second expression only when necessary. Ignoring the second operand, when possible, is called short circuit evaluation, by analogy with an electrical circuit.Short circuit evaluation can save time, especially if anything takes a long time to evaluate. It can also avoid unnecessary errors, if anything might fail.
For example, true || anything is always true, so Java does not need to evaluate the expression anything.
Likewise, false && anything is always false.

If you ever have to negate an expression that contains logical operators, and you
probably will, De Morgan’s laws can help:
  • !(A && B) is the same as !A || !B
  • !(A || B) is the same as !A && !B
Negating a logical expression is the same as negating each term and changing the operator.
The ! operator takes precedence over && and ||, so you don’t have to put parentheses around the individual terms !A and !B.
De Morgan’s laws also apply to the relational operators. In this case, negating each term means using the “opposite” relational operator


[to be continued...]

Wednesday, November 28, 2018

What Is Software Design and Why Is it Needed?


As you approach the door of the small shop where you’ve picked up your dinner a hundred times before, the front door is closed, but the smells from inside seem—if it were possible—to come right through the glass.
You grab the big, brass, door handle, look straight at the large prominent sign that says PUSH, and give the handle a pull—exactly like you have done every other time in the years you’ve been coming here. “D’oh!” you exclaim, sounding very much like Homer Simpson.
Have you ever had an experience like this? Why is it that you, an intelligent, educated person can’t read a large, prominently displayed sign, and follow a one-word instruction?
Why does everyone pull instead of push when presented with a door like the one shown below? What does this door say to you?


The answer is really very simple:
because the door handle itself is a sign, a sign that says more fundamentally and forcefully than the written sign above it, “PULL!!!” 
The problem is not with your ability to read, but with the “designers” of the building who combined an inward-opening front door with a door-pull instead of  a push-plate.
Someone made a fundamental design error, and all the user-friendly instructions in the world won’t fix it.
What is design? What are the design fields, and how are building design (architecture), graphic design, industrial design, and software design similar?
As you ask these questions, you’ll discover many different viewpoints:
  1. those who see design as science,
  2. those who claim design for engineering
  3. those who feel design is an art, and 
  4. those who insist that design is (or should be) a profession like law or medicine. 
Let's explores those ideas as well as the common concepts of
  • modeling, 
  • abstraction, 
  • structuring, and how all of these ideas relate to developing software;
after all, what you really want to do is to turn out a great program, right?
To do that, you will learn:
  • How to distinguish between different design philosophies and viewpoints.
  • Why design is needed.
  • How to describe the basic goals of design: “firmness, commodity, and delight.”
  • How to recognize the basic problems of design: essential and accidental complexity.
  • How the fundamental tools of design—models, abstraction, and decomposition—can be used to attack the basic problems of design.
  • How software abstraction mechanisms can be used to simplify the building of software, enabling you to build better programs.
  • How software design methodologies help the software designer approach different parts of the design problem.
  • How object-oriented design and structured design are related, and the basic terms common to each.

                                   What Is Design?

“One of the main reasons most computer software is so abysmal is that it’s not designed at all, but merely engineered.”
You might be surprised to find out that these are not the words of some disgruntled Luddite or some ivory-tower academician. The speaker was Mitch Kapor, the designer of one of the most popular software packages of all time (Lotus 1-2-3) and also the author of “A Software Design Manifesto.” Originally given as the keynote address at Esther Dyson’s PC forum in 1990, Kapor’s manifesto has been widely reprinted in the ensuing years.
In it, he argues for the creation of a new type of software professional: the software designer, who fulfills the role that an architect does in building construction, making sure that a building meets the needs of its inhabitants.
Almost everyone would agree with Kapor, (although, after your latest software crash, you might think that software is neither designed nor engineered).
How to actually design good software is the real question.
The ancient Roman architect Vitruvius considered a similar question:
what makes a good building?
In his treatise De Architectura Libri Decem (Ten Books on Architecture), written in 29 B.C., he proposed three principles that many think provide a good starting point for evaluating software designs.
A well-designed building, said Vitruvius, should have the qualities of commodity, firmness, and delight. 
Notice, that a product that balances commodity, firmness, and delight does not necessarily possess an equal amount of each.
E.g. most people think a good cup of coffee should contain more coffee than cream or sugar.

  • When you buy a software package, you want it to do exactly what the box says it will do. This is the characteristic of commodity—the program is effective in the sense of being well fit for its purpose. 
  • You also want the program to be well built: you want it be as fast and small as possible, and to continue working in a wide range of situations. This is the characteristic of firmness
  • Finally, you want your software to be attractive and pleasant to use. In a sense, you “live inside” your software, and it’s important that the interface be both functional and aesthetic. This is the quality of delight.
Each of these qualities is important.
Good-looking software that doesn’t run well or is hard to use is no better than software that is fast and efficient (that is, software that uses as few resources as possible) but doesn’t do what you want or does it in an ugly or unappealing way. 

Software designers, like all of us, tend to see the design process through their own particular lenses and to concentrate on one specific aspect or method of designing programs. 
  1. Some see software development as a scientific endeavor
  2. Others see it as an engineering exercise
  3. Still others think of designing computer programs as artistic expression, like painting or music .

                              DESIGN AS SCIENCE

How do you become a lawyer or doctor? You go to law school or medical school. But, what do you study if you want to design computer software? If you’re just embarking on your academic career and you ask this question, almost certainly you’ll be encouraged to major in Computer Science.
Are software designers scientists, and, if so, what does such a science entail?
You might have heard the old joke,
“You can tell if something’s a science—it doesn’t have the word science in its name.” 
And there’s some truth to this observation. All of us agree that physics and astronomy and chemistry—the so-called hard sciences—are really sciences.
But how about political science or military science or social science? How are the so-called “soft” sciences different from physics and geology?

Nobel prize winner Herbert Simon, one of the founders of the Computer Science department at MIT, attempted to answer this question in his 1969 book, The Sciences of the Artificial.
 According to Simon, there really are two sorts of sciences:
  • The natural sciences—physics, chemistry, biology, and geology—which are concerned with the discovery of the natural world—finding out “how” things work, and building workable theories of explanation.
  • The artificial sciences—political science, the social sciences, engineering, and computer science—which study things that have been built by humans, rather than naturally existing phenomena. Unlike the natural sciences, the artificial sciences are concerned with how things should work, not merely how things do work. An engineer wants to find the best way to build a bridge and a doctor wants to find the most effective method of treatment. All of these are issues of design.
Science, then, is about the study and discovery of general principles (theories), and the artificial sciences apply those theories to man-made artifacts, including the design of software. Software design, from the scientific point of view, includes
  • Theories that deal with structure and representation.
  • Rigorous and formal techniques for evaluating properties of designs.
  • Formal methods for choosing the optimal (or at least a satisfactory) design from a set of possible designs.
Reading this, you may be thinking, “what does that have to do with writing a word processor or spreadsheet?” Think back to the goals of design—to create artifacts that  exhibit firmness, commodity, and delight.
The role of the computer scientist is to provide an objective, rigorous, theoretical foundation for constructing software that exhibits firmness.

                          DESIGN AS ENGINEERING

“The scientist builds in order to study; the engineer studies in order to build.”
These are the words of the universally acknowledged father of software engineering, Fred Brooks, who was also the founder of the Computer Science Department at the University of North Carolina at Chapel Hill. His book, The Mythical Man Month (recently re-released in a nth anniversary edition), was written after the completion of one of the largest software development projects ever attempted: the design and construction of the operating system for the IBM System/360. For those designing or managing the construction of a software product, it remains a unique and indispensable information resource

For Brooks, the difference between the engineer and the scientist is not so much what they do, but the purpose behind their work. Software engineers design software in much the same way that mechanical engineers design bridges, industrial engineers design cars, and construction engineers design houses and auditoriums.

What does the software engineer design? Tools: tools for writing, tools for computing, tools for communicating.

The software engineer succeeds only to the extent that he builds a useful tool. 
To quote Brooks, “That swordsmith is successful whose clients die of old
age.”

“This is more like it,” you might be thinking. “I understand that engineering is about building things, and it seems obvious that the software that I use could benefit from some engineering techniques.” You’re right.
Like the computer scientist, those who see software design as engineering are concerned with the quality of “firmness.” Building on the foundation of computer science—the fundamental data structures and algorithms discovered and constructed there—the software engineer builds “things that work.”
Many of the techniques, such as
  1. the various diagramming techniques and 
  2. the rules of thumb about class design,
have their origin in the software engineering community.
Software engineering is essential for well-designed software, but, as Kapor pointed out, it is not enough


                                          DESIGN AS ART

If software development is an art, are software developers artists? How far can the notion of “art” be stretched?
“Look,” said the hopeful student to his long-suffering advisor, “everyone who watches Michael Jordan or Giannis Antetokounmpo play says he’s a real artist. So why can’t I get art units for playing basketball?” The reason, of course, is similar to the reason that computer science students don’t receive foreign language credit for learning C, Pascal, or Java: because the word “language” means something different in each context.
The same can be said for the word “art.” In one sense, a good basketball player is an artist, but in another, very real sense, basketball players are not artists at all.

What, exactly, do we mean when we talk about design as art? The fine  arts—painting, drawing, sculpture—exist to provide an aesthetic experience.
Though it’s conceivable that you could write a program whose primary purpose was aesthetic, in the ordinary course of things you’ll probably never do that. But, if we consider the applied arts—the construction of artifacts that are both useful and aesthetic—then software design certainly is one of the arts, in much the same way that graphic design or industrial design is.
The purpose of graphic design is to create documents such as books and magazines in which the aesthetic structure, the use of type and color and layout, serves the message that the piece conveys in a way that the reader can readily appreciate. 
In industrial design, the designer tries to create appliances or automobiles that are both attractive and functional. Of course, balancing functionality and aesthetics is not always easy. 
Think of the tail-fins on the 1958 Cadillac! Though at the time many people thought them attractive, most people today see the non-functional tail-fins as a case of wretched excess.

“Well, I don’t know,” you might be saying to yourself. “I’m not really artistic, and it seems like all this stuff is just a little superfluous.” You have a point. Adding an “artistic” gloss to  an aging and infirm superstructure is seldom successful.
You might even find yourself writing software that has no visible interface—embedded or systems software, for example. In such cases, arguing for “good-looking” programs is a misplaced concern.
Most of you, though, will write software for other people to use, and when you do, you take on the role of the artist-designer, striving to inspire delight, as well as commodity and firmness. This is a difficult role.
Software (at least good software) doesn’t just lie there and look pretty. Instead, it involves its user in an interactive experience. Not only do you want your program to look cool, you want it to act cool as well.
The demands of your role resemble those under which a playwright works. You must strive to get all the actors to line up and say their lines in a way that leaves the audience begging for more. However, your job is tougher still. The piece you’ve been commissioned to write is a more like a “murder-mystery dinner” where the actors and the audience intermingle. Your job is made doubly difficult because you have to anticipate the unscripted actions of your diners, and provide contingent lines for your players to use when things go off on a tangent.
If all this seems a little vague and abstract to you, you’ll be happy to know that designing software that is attractive and a pleasure to use does not require an “artistic temperament,” or the talent of pop artist David Hockney or playwright Neil Simon (RIP).


                                    DESIGN AS ARCHITECTURE

If “firmness” is the special purview of the engineer-designer, then “delight” has a similar place in the world of the artist-designer.
Yet, concentrating on firmness and delight is not enough; the designer must also be concerned with commodity, balancing form and function. In this regard, many software designers see a close parallel between their role and that of the architect.
This analogy was the central theme of Mitch Kapor’s “A Software Design Manifesto,” and the similarities between software design and architecture have greatly influenced the “patterns” movements.
Like the artist, the architect wants to build structures that are visually pleasing; 
visual design is central to every architect’s training.
But, like the engineer, the architect wants to build structures that stand the test of time. 
The science of materials and construction techniques is an important part of an architect’s training.
In the end, the architect designs neither for beauty nor for durability, but for the client. The architect’s goal is to build a structure that meets the client’s needs.

                              The Process of Design

“So,” you say, “you’ve talked about science and engineering and art and architecture. Let’s not beat around the bush! Just what is design? How do you go about it?”
Those are two very good questions, and they deserve a direct, if not exhaustive, answer:
  • Design is preliminary; it’s done before construction. Designing and building a house are two different activities.
  • Design uses models. One dictionary definition of design is “to plan by making preliminary sketches or outlines.” A design may use several different models, but the models are all distinct from the creation.
  • Design has a goal: to create artifacts for human use. The designer acts as an agent for the client, and needs to ask “does it work?” not only in the mechanical sense of running without error, but “does it work?” in the larger sense of meeting the needs of the client.
  • Design is a process, yet the same process may not be applicable to every artifact. A process appropriate for designing a computer game might place a high emphasis on spontaneity and creative intuition, while a process used to develop a heart monitor or a missile-defense system might, appropriately, be much more formal and rigorous.

                                       WHY DESIGN IS NEEDED

If you are a student who has written a few programs, or if you write software for your own use, you might be asking, “Why bother? Why not just start coding?” Though some software projects may not need a long or formal design process, nobody with substantial experience sits down at the keyboard and just bangs away with no thought or reason. And, though an informal design process might be appropriate for most of the work you do, learning about more formal processes can help you to consider aspects of software design you have previously ignored.

Design is the planning process you go through before you build something. But again, why bother to plan at all?
  • The major reason is that it’s cheaper to change your mind while you’re planning something than after it’s half built. This is true for buildings, of course; erasing a line on a blueprint is much less expensive than ripping out a wall. For software,the same thing is true. A change that may cost $100 to make while you are designing your program can cost $1,000 to make after parts of the program are already built, simply because so many other parts have to be adjusted. And, if you find you have to make the change after the program is finished and in operation, the same change can cost $10,000 or more. “Look before you leap,” is more than just a hoary old cliché.
More broadly, design involves an attitude that seeks to identify alternatives and
intelligently choose an appropriate course of action.
Good design involves
  1. analysis,
  2. reflection, and the 
  3. development of insight.
The way in which design is done has changed over time, as such insights have accumulated.
In the 16th century, if you wanted to build a house, you wouldn’t work from a set of blueprints created by an architect and given to a contractor. Instead, you would hire a master-builder who would build your house based on his own experience and the experience of the master-builder who had trained him. Today, the development of a common language—the blueprint—and a common process (supported by such things as the Uniform Building Code and the licensing of building contractors) enables you to build a house by any number of firms, with little variation in the output of the finished product.

This “separation of concerns” is one of the factors that leads to a more efficient process




Today, if you decide to build a house, your architect acts as your agent, making sure that the house meets your needs.
To do this, the architect uses many different types of models—not only blueprints, but sketches, mock-ups, and even style books of common house types and floor plans, etc.
Normally, as a client you review the sketches and mock-ups, whereas the building contractor relies on the blueprints.
These models help the parties communicate and record the respective decisions they make. 
Your builder does not decide, halfway through construction, to add a stairway to the west wing—at least not without consulting the architect.
This whole system works because of the availability of different models—at several levels of detail and abstraction—and a common agreement among all the parties about how those models correspond to reality.

                              THE PROBLEMS OF DESIGN: WHY IS SOFTWARE HARD?

If design—the use of planning and models—has been so successful in architecture and engineering, why can’t we just apply to software the same principles used to make buildings, bridges, and cars?
Is designing a piece of software the same as designing a bridge—or a computer? There is a lot of evidence to suggest it is not; that software design is fundamentally more difficult than engineering skyscrapers. Professor Brooks, in
his famous article, “No Silver Bullet,” tells us why.

Perhaps you’ve had a dream like this. You are taking a walk with your sweetheart. You turn to look into each other’s eyes, and, as you watch, your loved ones turn into something different— something horrible. You wake in a sweat, with your heart pounding. This primordial fear— the familiar changing into the unknowable and fearful—is at the heart of the medieval legend of the werewolf. In the modern retelling of the legend, the only hope for deliverance is the “magical” effect of a silver bullet. And, if you’ve ever worked on a piece of software that seems to have grown ravenous and rapacious, the metaphor seems especially apt.

Why is designing software more difficult than designing a bridge? Because software has four essential qualities that resist easy solutions:
  • Software is complex.
  • Software is unprincipled.
  • Software changes.
  • Software is invisible.
Software is complex because it contains so many “moving parts.” A modern jet fighter plane may contain a few thousand moving parts. A software system of even moderate size may contain tens of thousands of lines of code, each of which must correctly “mesh” with the rest of the system. Every additional line of code, every new condition or event, leads to the possibility of new conditions, previously unconsidered, or overlooked.

Software is “unprincipled” because there are no known fundamental and unifying laws that can cause software programs to “make sense.”
Software programs are written not to conform to a regular universe, but to the arbitrary, capricious, and illogical mind of man.
Software changes because it is so malleable. Although the London Bridge was moved to Lake Havasu, Arizona, that was an event both expensive and uncommon in bridge-building lore (Plus, the bridge remained essentially unchanged).
By contrast, software is moved, twisted, and distorted with such regularity, and with such little foresight, that it’s a wonder that any of it works at all.

Finally, software is invisible. Any design problem involves two translation steps. The first step is the translation of a mental(or conceptual) model to an abstract model.
Suppose you decide to splurge on a new, custom designed hot-rod. Your conceptual model is the picture in your mind. The designer’s first task is to translate your mental model into a specification. This specification may include textual parts—the type of engine, and the brand of tires—but most of the specification will be visual: sketches, scale models, and photographs of similar cars. When designing software, this translation is much more difficult, as Figure  shows.




Prototypes and interface builders have done much to make the “external face” of a program visible, and software engineering diagramming techniques are of considerable value; but, in the final analysis, the “mapping” between an abstract model and a finished software product is much more tenuous than that for
buildings, cars, or dresses.



                             The Designer’s Toolbox

Software, then, because of its very nature, is hard to design. But hard is not impossible, and, while the problems presented by complexity, change, and invisibility don’t have magical solutions, they do have solutions.


                                     MODELING AND MODELS

You’ve seen the word model bandied about, but what, exactly, is a model?
A model is a representation of something else: something real or imaginary. A model can be textual, mathematical, graphical, or can use some other form of symbolic representation. 
The supply-demand curve in economics is a model of a social interaction.
J.R.R. Tolkien’s The Lord of the Rings is a literary model of an imaginary world. A map is a model of our physical world.


How is a model different from what it represents?
A model is an abstraction. The globe on your desk is not the real earth; your Thomas’ Guide is not really your town; Tolkien’s novel is not Middle Earth; supply and demand is not the buying and selling of hot dogs and off-road vehicles. 
Instead, abstraction lets us model the thing we’re studying by ignoring the irrelevant elements and concentrating on the essential.





   ABSTRACTION, COMPLEXITY, HIERARCHY, AND DECOMPOSITION

“Why on earth,” you say, “would I want to ignore details? What do I gain from that?”
A good way to illustrate the importance of ignoring details is to compare a street map with a photograph of the same area taken by a LandSat satellite. Which is clearer, a street map or a satellite map?


Taken from space by high-resolution cameras, the satellite photo will let you count the blades of grass on your lawn. Yet, with all this incredible detail, it’s almost entirely useless for finding your way across town. It doesn’t have too little detail for this purpose; it has too much.

As you’ve already seen, one of the essential elements that makes software hard is its complexity. Human limitations—our memories and our senses of perception—prevent us from comprehending and dealing with very complex situations without the help of a simplifying model.
For instance, social systems simplify our relationships with each other by proscribing behavior (through laws) and describing roles (through government).
You can use such models both to understand the world, and as a tool to create  artifacts.
Faced with the multitude of different animals in the world, you group similar animals together into classes based on their similarities to each other. You can arrange those classes into a “pyramid” (or hierarchy) based on the similarities of each class to other classes.



When you encounter a creature that is 1/4 inch high and has six legs, you put it in the insect category.
Creating such categories gives you a mental tool you can use to deal with individual animals. 
Can you imagine what your life would be like if you didn’t do this? If you were bitten by a snake, you’d have no reason to avoid others.
A special form of classification, decomposition, is useful as a tool for creating solutions, not merely for understanding. Decomposition is not merely recognizing similar “things,” but recognizing that most big things can be broken into simpler things, and those simpler things into still simpler things. 
Trees have branches, leaves (or needles), roots, bark, and trunk, and the countless types of trees have innumerable variations.
But, when you decompose a tree you find it is composed of simpler structures known as cells, and that the cells themselves are composed of simpler pieces yet—molecules and atoms.

Most human artifacts exhibit similar structure, and such structure can usually be described in the form of a hierarchy or decomposition.

            Design Solutions in the Software World

Architects have been designing buildings for thousands of years, and thinking about design nearly as long. Vitruvius wrote his books laying down the principles of firmness, commodity, and delight over two thousand years ago.
In comparison, the computer was invented yesterday, and we may someday regard today’s latest software creation the same way we regard Stonehenge in comparison to the Acropolis. Perhaps the golden age of software development is just ahead.


               SOFTWARE ABSTRACTION MECHANISMS

Short though the history of software design has been, the ideas of
  • abstraction,
  • decomposition, and 
  • hierarchy
have played an important part.
Originally, computers were somewhat simple, and programmers could keep all the relevant details straight in their minds. As programs got larger and (subsequently) more complex, these principles were used to create various software abstraction mechanisms that were brought to bear in an attempt to master complexity.

The first programmers worked almost directly with the “naked” machine.
A very thin abstraction, numbering memory locations to give some order to their seemingly unlimited (perhaps 12K) reserve of memory, was the only concession. 
Unfortunately, even 12K of memory, which seems laughably small today, is too much complexity for our brains to handle. Named variables (the ability to refer to GROSS_PAY instead of location AF3CH) enabled programmers to handle more complex problems by hiding an unnecessary detail—the actual physical location where GROSS_PAY was stored


Just as the ability to name variables enabled programmers to hold bigger “chunks” of a program in their minds at a time, the ability to name sections of code (called named subroutines) enabled them to think of their programs in still larger pieces.
These two advances, both of which involved ignoring irrelevant details, increased the productivity of programmers more than ten-fold. So, what do you suppose they did? That’s right, they wrote programs that were ten times larger, and then some. And, just as you might expect, the additional complexity rendered those programs unmaintainable and unreliable.


        THE SOFTWARE CRISIS AND STRUCTURED PROGRAMMING

In the late 1960s, the Department of Defense (DOD) was one of the largest purchasers of custom-made software. No doubt you’ve heard the stories of the $900 ash-trays. But even for folks accustomed to those sorts of apparent extravagances, the problems with software had gotten out of hand. In a pair of conferences sponsored by the North Atlantic Treaty Organization (NATO), two memorable terms were added to the software development lexicon:
The term software crisis was coined to describe the fact that software was consistently late, over budget, and buggy.
“Why can’t we get software on time, at the price agreed upon, and why doesn’t it work as specified?” NATO asked.
The prescription of the experts at the conference was to endorse an engineering model. Once software was engineered—like bridges or weapons systems—bugs, cost overruns, and late delivery would be a thing of the past. With 45 years hindsight, it’s easy to see that things weren’t so simple; nevertheless, the techniques promoted and developed as a result of the proclamation of the software crisis, did, in fact
  1. raise the level of abstraction, 
  2. increase the robustness (firmness) of the software that was written, and 
  3. open the way for much larger programs to be written.
Of course, this started the same cycle of improvement followed by rising expectations all over again.



                              SPECIFIC DESIGN TECHNIQUES

Structured programming, one set of techniques popularized as a means of combating the software crisis, was designed to make software more readable and maintainable.
Because, as the DOD researchers discovered, over 75% of the cost of a software system occurs during maintenance, it made sense to concentrate efforts on techniques to reduce that effort.

  1. The first of these techniques was to simplify the “flow of control” inside programs. Flow of control is simply the sequence in which program statements are executed. In early computer programs, all or most program execution was controlled by the unconditional branch—the infamous goto. Although, at the machine level, gotos were still required, by using the goto to build more abstract control structures—the loop and the selection statement—and then programming entirely in terms of those higher-level constructs, programmers were able to eliminate a whole class of common errors and thus, increased their ability to write and understand more complex programs.
  2. If hiding the “actual” flow of control inside the computer was a success, the technique of hiding or limiting the access to data was an even greater success. Researchers discovered that many common software errors of the time were caused by two subroutines inadvertently modifying a piece of data that both used. The invention of local variables— and David Parnas’ ideas on data hiding, modularization, and abstract data types—were responsible for the next advance in the creation of “firm” software. Each of these was an attempt to hide more of the details of the problem and only show the relevant information.

                 Software Design Methodologies

In applying the abstraction mechanisms that were developed during the “years of crisis” to help in mastering software complexity, programmers began to follow, and encourage others to follow, software development methodologies.
A methodology is simply a prescribed way of using abstraction mechanisms.
Methodologies consist of three things:
  • A process—the step-by-step activities and related deliverables that are used to model and construct software.
  • A notation—a representation, often graphical, of the subsystems that make up a system and the way they interact.
  • A set of heuristics—rules of thumb or figures of merit that give the designer guidance about how the artifact being built should work.

             STRUCTURED DESIGN AND OBJECT-ORIENTED DESIGN

Software design methodologies were developed to exploit the abstraction mechanisms that were introduced with better programming techniques.
  • Developed in the 1970s, structured design takes the best practices of structured programming and adds a graphical notation and a development process.The primary abstraction mechanism in procedural languages is the subroutine, sometimes called a function, which operates on a piece of data.
The primary design decision in a procedural program is apportioning the work of the program among specialized subroutines. Because of this, the shape or morphology of a system developed using structured design almost always takes the form of a tree, with centralized control invested in the top or main module

Object-oriented design (OOD), in a similar manner, arose from the ideas introduced in object-oriented programming with SmallTalk and Simula.
In an OOD system, the primary abstraction mechanism is the class.
  1. A class is a combination of both data and the legal operations that can be performed on that data. 
  2. The data in an OOD system,rather than being passed between operations (subprograms), is hidden and protected from access by other parts of the program, by means of a principle called encapsulation. This is simply a refinement of the ideas of data hiding that began with local variables and abstract data types.
  3. The flow of control in an object-oriented program is also different from that within a structured program. Instead of superior and subordinate subroutines, the action in the program occurs as objects (instances of a class) interact with each other by sending messages

One way to think about the difference between structured designs and OO designs is to think about the difference between a centralized (planned) economy and a free-market economy.
  • In a planned economy, decisions about who should produce what, and about what will be sold in the marketplace, are made at the top. 
  • In a free-market economy, the economy runs itself by the interaction of millions of autonomous, independent decisions.
You could say that the major difference between structured and OO systems is the degree to which intelligence (and thus flow-of-control) is vertical or horizontal.


Resources

  • The classic book treating design as a scientific subject was written by the cofounder of the Computer Science program at MIT, Herbert Simon. The Sciences of the Artificial is a set of essays that make thought-provoking, if difficult, reading. Would-be designers should give a special look.
  • Looking at software design from the engineering and management perspective is Frederick Brooks Jr.’s The Mythical Man Month. The best known and most widely read book on software development, MMM was recently re-released in a nth anniversary edition. If you think that a 40-year-old book on software design and development couldn’t have anything to say to you, pick up a copy and you’ll find yourself very pleasantly surprised. This is one book everyone in software design should own.
  • When Terry Winograd, Stanford University Professor of Computer Science, set out to hold a conference on software design, the unexpected result was the many different perspectives of those represented. Another unexpected result was the publication of Bringing Design to Software, which gives each of those different hearings a platform. This book, which leads off with Mitch Kapor’s “A Software Design Manifesto,” provides the broadest view on software design as a user-centered activity. Each essay is interesting in
    its own right, and is supplemented by case studies of actual software products and the design issues that they illustrate.
  • That's another book that attempts to reconcile the engineering and user-centered design camps in software development is Nathaniel Borenstein’s Programming As If People Mattered: Friendly Programs, Software Engineering, and Other Noble Delusions. Written as a series
    of anecdotes, this book will be especially helpful to the programmer or software engineer who wants to learn about adding “commodity” to his(her) programs. If you still can’t decide whether computer science is really a science, you’ll want to read Chapter 20, “The Ivory Tower.”

Monday, November 26, 2018

Java beginner4:Void Methods

So far as beginners we’ve only written short programs that have a single class and a single method (main). Now I’ll show you how to organize longer programs into multiple methods and classes and also present the Math class, which provides methods for common mathematical operations.


                                    Math Methods

In mathematics, you have probably seen functions like sin and log, and you have
learned to evaluate expressions like sin(Ï€/2) and log(1/x) .
  1. First, you evaluate the expression in parentheses, which is called the argument of the function. 
  2. Then you can evaluate the function itself, maybe by punching it into a calculator.
This process can be applied repeatedly to evaluate more complex expressions like log(1/ sin (Ï€/2) ).
First we evaluate the argument of the innermost function, then evaluate the function itself, and so on.

The Java library includes a Math class that provides common mathematical operations. Math is in the java.lang package, so you don’t have to import it. You can use, or invoke, Math methods like this:

double root = Math.sqrt(17.0);
double angle = 1.5;
double height = Math.sin(angle);

The first line sets root to the square root of 17. The third line finds the sine of 1.5
(the value of angle).
Arguments of the trigonometric functions—sin, cos, and tan—should be in radians.
To convert from degrees to radians, you can divide by 180 and multiply by Ï€. 
Conveniently, the Math class provides a constant double named PI that contains an approximation of π:

double degrees = 90;
double angle = degrees / 180.0 * Math.PI;

  1. Notice that PI is in capital letters (as all constants per convention in Java). Java(is case sensitive) does not recognize Pi, pi, or pie. 
  2. Also, PI is the name of a variable(constant), not a method, so it doesn’t have parentheses. 
  3. The same is true for the constant Math.E, which approximates Euler’s number.
Converting to and from radians is a common operation, so the Math class provides methods that do it for you.

double radians = Math.toRadians(180.0);
double degrees = Math.toDegrees(Math.PI);


Another useful method is round, which rounds a floating-point value(double) to the nearest integer and returns a long. A long is like an int, but bigger.
  1. More specifically, an int uses 32 bits(4 bytes); the largest value it can hold is 2^31 − 1, which is about 2 billion. 
  2. A long uses 64 bits(8 bytes), so the largest value is 2^63 − 1, which is about 9 quintillion.

long x = Math.round(Math.PI * 20.0);

The result is 63 (rounded up from 62.8319).

Take a minute to read the documentation for these and other methods in the Math class.
The easiest way to find documentation for Java classes is to do a web search for “Java” and the name of the class.

                             Composition Revisited

Just as with mathematical functions, Java methods can be composed. That means you can use one expression as part of another. For example, you can use any expression as an argument to a method:

double x = Math.cos(angle + Math.PI / 2.0);

This statement divides Math.PI by two, adds the result to angle, and computes the cosine of the sum.

You can also take the result of one method and pass it as an argument to another:

double x = Math.exp(Math.log(10.0));

In Java, the log method always uses base e. So this statement finds the log base e of 10, and then raises e to that power. The result gets assigned to x.

Some math methods take more than one argument. For example, Math.pow takes two arguments and raises the first to the power of the second. This line of code assigns the value 1024.0 to the variable x:

double x = Math.pow(2.0, 10.0);

When using Math methods, it is a common error to forget the Math. For example, if you try to invoke pow(2.0, 10.0), you get an error message like:
File: Test.java [line: 5]
Error: cannot find symbol
    symbol: method pow(double,double)
    location: class Test
The message “cannot find symbol” is confusing, but the last line provides a useful hint. The compiler is looking for pow (definition) in the same class where it is used, which is Test. If you don’t specify a class name, the compiler looks in the current class.


                              Adding New Methods

You have probably guessed by now that you can define more than one method in a class. Here’s an example:

public class NewLine {
    
    public static void newLine() {
        System.out.println();
    }
    
    public static void main(String[] args) {
        System.out.println("First line.");
        newLine();
        System.out.println("Second line.");
    }
    
}

The name of the class is NewLine. By Java's convention, class names begin with a capital letter. NewLine contains two methods, newLine() and main().
Remember that Java is case-sensitive, so NewLine and newLine are not the same.
Method names should begin with a lowercase letter and use “camel case”, which is a cute name for jammingWordsTogetherLikeThis. You can use any name you want for methods, except main or any of the Java keywords.
  • newLine and main are public, which means they can be invoked from other classes.
  • They are both static, but we can’t explain what that means yet.
  • And they are both void, which means that they don’t yield a result (unlike the Math methods, for example).
  • The parentheses after the method name contain a list of variables, called parameters,where the method stores its arguments. main has a single parameter, called args, which has type String[]. That means that whoever invokes main must provide an array of strings
Since newLine has no parameters, it requires no arguments, as shown when it is
invoked in main. And because newLine is in the same class as main, we don’t have to specify the class name.
The output of this program is:
First line.
Second line.
Notice the extra space between the lines. If we wanted more space between them, we could invoke the same method repeatedly:

public static void main(String[] args) {
    
    System.out.println("First line.");
    newLine();
    newLine();
    newLine();
    System.out.println("Second line.");
    
}

Or we could write a new method that displays three blank lines:

public static void threeLine() {
    
    newLine();
    newLine();
    newLine();
    
}



public static void main(String[] args) {
    
    System.out.println("First line.");
    threeLine();
    System.out.println("Second line.");
    
}

  1. You can invoke the same method more than once, and 
  2. you can have one method invoke another.
In this example, main invokes threeLine, and threeLine invokes newLine.

Beginners often wonder why it is worth the trouble to create new methods. There are many reasons, but this example demonstrates a few of them:
  • Creating a new method gives you an opportunity to give a name to a group of statements, which makes code easier to read and understand.
  • Introducing new methods can make a program smaller by eliminating repetitive code. For example, to display nine consecutive new lines, you could invoke threeLine three times.
  • A common problem solving technique is to break tasks down into sub-problems. Methods allow you to focus on each sub-problem in isolation, and then compose them into a complete solution.

                                   Flow of Execution

Pulling together the code from the previous section, the complete program looks like this:

public class NewLine {
    
    public static void newLine() {
        System.out.println();
    }
    
    public static void threeLine() {
        newLine();
        newLine();
        newLine();
    }
    
    public static void main(String[] args) {
        System.out.println("First line.");
        threeLine();
        System.out.println("Second line.");
    }
}

When you look at a class definition that contains several methods, it is tempting to read it from top to bottom. But that is likely to be confusing, because that is not the flow of execution of the program.
Execution always begins at the first statement of main(), regardless of where it is in the source file. 
Statements are executed
  1. one at a time, in order, until you reach a method invocation, which you can think of as a detour. 
  2. Instead of going to the next main()'s statement, you jump to the first line of the invoked method, 
  3. execute all the statements there, and then come back in main() and pick up exactly where you left off.
That sounds simple enough, but remember that one method can invoke another one.
In the middle of main(),
  1. we go off to execute the statements in threeLine. While we are executing threeLine, 
  2. we go off to execute newLine(). 
  3. Then newLine() invokes println(), which causes yet another detour. Fortunately, Java is good at keeping track of which methods are running. So when println() completes, 
  4. it picks up where it left off in newLine(); when newLine completes, 
  5. it goes back to threeLine, and when threeLine completes, 
  6. it gets back to main().
In summary, when you read a program, don’t read from top to bottom. Instead, follow the flow of execution.


                            Parameters and Arguments

Some of the methods we have used require arguments, which are the values you provide when you invoke the method. For example,
  1. to find the sine of a number, you have to provide the number, so the methode sin takes a double as an argument. 
  2. To display a message, you have to provide the message, so the methode println takes a String.
When you use a method, you provide the arguments (called also actual parameters). When you define(write) a method, you name the parameters (called also formal parameters).
The parameter list indicates what arguments are required. The following class shows an example:

public class PrintTwice {
    
    public static void printTwice(String s) {
        System.out.println(s);
        System.out.println(s);
    }
    
    public static void main(String[] args) {
        printTwice("Don't make me say this twice!");
    }
    
}

  • printTwice() has a parameter named s with type String. 
  • When we invoke(call) printTwice(), we have to provide an argument with type String.
  • Before the method executes, the argument gets assigned to the parameter. In this example, the argument "Don't make me say this twice!" gets assigned to the parameter s. This process is called parameter passing because the value gets passed from outside the method to the inside.
An argument can be any kind of expression, so if you have a String variable, you can use it as an argument:

String argument = "Never say never.";
printTwice(argument);

The value you provide as an argument must have the same(or a compatible) type as the parameter. For example, if you try:

printTwice(17);  // syntax error

You will get an error message like this:
File: Test.java [line: 10]
Error: method printTwice in class Test cannot be applied
            to given types;
required: java.lang.String
found: int
reason: actual argument int cannot be converted to
             java.lang.String by method invocation conversion
Sometimes Java can convert an argument from one type to another automatically(that's called implicit conversion).
For example, Math.sqrt() requires a double, but if you invoke Math.sqrt(25), the integer value 25 is automatically converted to the floating-point value 25.0. But in the case of printTwice(), Java can’t (or won’t) convert the integer 17 to a String.

Parameters(they're also considered as local variables) and other variables only exist inside their own methods. Inside main(), there is no such thing as s. If you try to use it there, you’ll get a compiler error. Similarly, inside printTwice() there is no such thing as argument. That variable belongs to main().

Because variables only exist inside the methods where they are defined, they are often called local variables.


                               Multiple Parameters

Here is an example of a method that takes two parameters:

public static void printTime(int hour, int minute) {
    System.out.print(hour);
    System.out.print(":");
    System.out.println(minute);
}

In the parameter list, it may be tempting to write:

public static void printTime(int hour, minute) {
    ...

But that format (without the second int) is only legal for variable declarations. In
parameter lists, you need to specify the type of each variable separately.

To invoke this method, we have to provide two integers as arguments:

int hour = 11;
int minute = 59;
printTime(hour, minute);

A common error is to declare the types of the arguments, like this:

int hour = 11;
int minute = 59;
printTime(int hour, int minute);

That’s a syntax error; the compiler sees int hour and int minute as variable declarations, not expressions.
You wouldn’t declare the types of the arguments if they were simply integers:

printTime(int 11, int 59);  // syntax error


                                    Stack Diagrams

Pulling together the code fragments from the previous section, here is a complete class definition:

public class PrintTime {
    
    public static void printTime(int hour, int minute) {
        System.out.print(hour);
        System.out.print(":");
        System.out.println(minute);
    }
    
    public static void main(String[] args) {
        int hour = 11;
        int minute = 59;
        printTime(hour, minute);
    }
    
}

printTime() has two parameters, named hour and minute. And main() has two variables, also named hour and minute.
Although they have the same names, these variables are not the same. 
hour in printTime() and hour in main() refer to different storage locations, and they can have different values.
For example, you could invoke printTime() like this:

int hour = 11;
int minute = 59;
printTime(hour + 1, 0);

Before the method is invoked, Java evaluates the arguments; in this example, the
results are 12 and 0. Then it assigns those values to the parameters. Inside printTime(), the value of hour is 12, not 11, and the value of minute is 0, not 59. Furthermore, if printTime() modifies one of its parameters, that change has no effect on the variables in main.

One way to keep track of everything is to draw a stack diagram, which is a state diagram that shows method invocations. For each method there is a box called a frame that contains the method’s parameters and variables. The name of the method appears outside the frame; the variables and parameters appear inside.
As with state diagrams, stack diagrams show variables and methods at a particular point in time. Figure below is a stack diagram at the beginning of the printTime() method.



                            Writing Documentation

As you benefit from reading good documentation, you should “pay it forward” by
writing good documentation.
A nice feature of the Java language is the ability to embed documentation in your source code. That way, you can write it as you go, and as things change, it is easier to keep the documentation consistent with the code.
If you include documentation in your source code, you can extract it automatically, and generate well-formatted HTML, using a tool called Javadoc. This tool is included in standard Java development environments, and it is widely used. In fact, the online documentation of the Java libraries is generated by Javadoc.

Javadoc scans your source files looking for specially-formatted documentation comments, also known as “Javadoc comments”. They begin with /** (two stars) and end with */ (one star). Anything in between is considered part of the documentation.

Here’s a class definition with two Javadoc comments, one for the class and one for the main method:

/**
* Example program that demonstrates print vs println.
*/
public class Goodbye {

    /**
    * Prints a greeting.
    */
    public static void main(String[] args) {
        System.out.print("Goodbye, "); // note the space
        System.out.println("cruel world");
    }
}

The class comment explains the purpose of the class. The method comment explains what the method does.

Notice that this example also includes an inline comment, beginning with //. In general, inline comments are short phrases that help explain complex parts of a program.
They are intended for other programmers reading and maintaining the source code.

In contrast, Javadoc comments are longer, usually complete sentences. They explain what each method does, but they omit details about how the method works. And they are intended for people who will use the methods without looking at the source code.
Appropriate comments and documentation are essential for making source code
readable.
And remember that the person most likely to read your code in the future, and appreciate good documentation, is you.

                             Exercises

Exercise 4-1.
The point of this exercise is to practice reading code and to make sure that you
understand the flow of execution through a program with multiple methods.
  1. What is the output of the following program? Be precise about where there are spaces and where there are newlines.Hint: Start by describing in words what ping and baffle do when they are invoked. 
  2. Draw a stack diagram that shows the state of the program the first time ping is invoked.
  3. What happens if you invoke baffle(); at the end of the ping method? (We will see why in the next post.)

public static void zoop() {
    baffle();
    System.out.print("You wugga ");
    baffle();
}

public static void main(String[] args) {
    System.out.print("No, I ");
    zoop();
    System.out.print("I ");
    baffle();
}
public static void baffle() {
    System.out.print("wug");
    ping();
}

public static void ping() {
    System.out.println(".");
}

Exercise 4-2.
The point of this exercise is to make sure you understand how to write and invoke methods that take parameters.
  1. Write the first line of a method named zool that takes three parameters: an int and two Strings.
  2. Write a line of code that calls zool, passing as arguments the value 11, the name of your first pet, and the name of the street you grew up on.

Exercise 4-3.
The purpose of this exercise is to take code from a previous exercise and encapsulate it in a method that takes parameters. You should start with a working solution to Exercise 2-2.
  1. Write a method called printAmerican that takes the day, date, month and year as parameters and that displays them in American format.
  2. Test your method by invoking it from main and passing appropriate arguments. The output should look something like this (except that the date might be different): Saturday, July 22, 2015
  3. Once you have debugged printAmerican, write another method called printEuropean that displays the date in European format.

Resources