Sunday, March 29, 2009

Time for a Paradigm Shift in Programming Pedagogy

### CODE ALA BUGS ###

A long-standing problem in software development is the detection and elimination of bugs. Numerous procedures such as Design by Contract , Cleanroom Software Engineering and Test-driven Development (TDD) are known to minimize bugs. Thus, one wonders why such practices are not used extensively in contemporary practices. Michael Feathers has recently noted that the common attribute among these practices was that they all required contemplation of the code’s purpose.

As an educator this lack of certainty regarding a programmer’s ability to write effective code triggers the question whether we are teaching programming courses appropriately.

### PEDAGOGICAL PRACTICES ###

Examination of current programming texts reveals the general approach to how programming courses are taught. This involves the reading, lecturing and discussion of the programming concept, studying code examples implementing the concept, and problem solving. The later generally requires the student to write a simple application involving the use of the above-mentioned concept or principle. The code correctness is easily determined because the application is simple. The application can be executed with a varying set of input data and the results determine the correctness of the code. This approach works adequately in such simplistic circumstances but fails when programming larger and complex software systems. Nevertheless the beginning programmer learns to depend on this quick method of verification during this important developmental stage.

### DENIAL AND INTERVENTION ###

The troubling aspect of this approach to teaching programming is the denial ensconced in the approach to the solution. The approach assumes the programmer will write code that will do what the programmer thinks it will do. The denial lies in the failure to recognize that the code often doesn’t do what it was written to do. In the words of Kent Beck
“I am good at fooling myself into believing that what I wrote is what I meant.”1
Even worse is the inability to alter behavior to compensate for this failure. Could contemporary computer science faculty be responsible for permitting this state of denial? Is it time for intervention?

### UNCERTAINTY IN PROGRAMMING ###

Programming students should learn about the uncertainty inherent in writing code; that all programmers, even excellent ones like Kent Beck, are susceptible to this uncertainty. Programming students should be taught that along with the recognition of the uncertainty implicit in the process of writing code, comes the realization that their solutions must be considered hypothetical. Hence, the validity of their hypothetical code solutions relies on how extensively the hypothesis has been tested. But wait! – isn’t this the scientific method every school kid learned in their K-12 years?

### PROGRAMMING AS SCIENTIFIC PROCESS ###

Considerable evidence exists that software creation is riddled with uncertainty and thus untested code represents at best a guess at a possible solution. Shouldn’t this be the fundamental principle taught to programming students? Why isn’t testing the validity of the hypothetical taught as the foundation of programming? In the face of the problems currently found in software development, why do we continue with a failed approach to programming pedagogy? Isn’t it time to confront the denial ensconced in the assumption that we can write code that will do what we intend? Hasn’t the time come to teach programming as a scientific process?

### SCIENCE & TDD ###

Test-driven development (TDD) defines a process whereby the programmer first writes a test which determines whether the intended function accomplishes its purpose. After the test is written, the function is then written to pass the test. Inherent in this procedure is the recognition that to truly understand the function one must understand how to test whether the function works as intended. This act is what Michael Feathers calls the contemplation of the code which is required to practice TDD along with other processes such as Design by Contract and Cleanroom Software Engineering. However, also implicitly assumed is the recognition that writing code is fraught with uncertainty and although the language of TDD is not that of the scientific method, the intent and the results are equivalent.

### REFERENCES ###
1. Beck, Kent (2000) Extreme Programming Explained: Embrace Change, Pearson Education, [ISBN 8178086670]

Thursday, March 19, 2009

SOA IS A HACK

Anyone reading my expositions must recognize that most of these writings were created when I was teaching software design courses in the masters of software engineering program at Carroll University. Thus, a good part of the tone I have strived for is that of provocation, and stimulation to think about the problem. The following piece was written in 2008 after reading a piece on SOA - which used to be called web services. Today I came across a blog by UncleBob Martin on SOA and I decided to recreate my original exposition here.

Here is the email I sent my class introducing them to my discussion of SOA.

##BEGIN PASTE##
First, thanks to StudentX for continuing the discussion with the link to the article by Craggs on reasons for failures in SOA projects.

Second, anecdotal pieces by consultants that contain no factual data should always be considered with skepticism. This statement comes from my background as a scientist who wandered into the “software engineering” arena. My primary criticism of “computer science” has long been (I recall arguments with my wife in the 80’s over this point) that it has little to do with the scientific method.

I recognize that I’m thinking at an idealistic level but many of the problems described in Craggs’ article can be considered from my perspective. Consider the following quote from the Craggs’ article:

“SOA is not just something that can be “installed and switched on.” It’s a lengthy process, involving the business as a whole rather than just IT. As already discussed, for example, failure to involve the business units with SOA design decisions will result in an implementation almost guaranteed to fail to match expectations.”

This is the problem my son brought up – that the various groups within the organization could never get together to create an integrated domain-object model (DOM). In addition to the cultural mismatch, there was probably also a physical separation between groups. But I say, as indicated by the above quote, that there has to be significant integration of the cultures in the various functional organizations to do the SOA integration too. Just because it’s SOA, doesn’t make this problem go away. I’d rather work on integrating the disparate systems by putting them into the same DOM than speculate with SOA.

I got a chuckle out of the following quote from Craggs’ piece because it could have been taken out of a classic systems and analysis book (Kendall & Kendall, Whitten & Bentley, etc.) published in the 80s. This is nothing new – this problem has been around for a long long time. No silver bullet here.

“But the last reason for failure to meet expectations is by far the most common and can be truly devastating. Companies repeatedly build great strategies and plans for SOA, only to find that when execution is attempted, there are countless roadblocks and inhibitors to success. The cross-departmental interchanges never happen, resource availability becomes a problem, and attempts to gain agreement on service specifications descend into endless bickering. These issues typically stem from a lack of buy-in for SOA at the senior management level.”

And finally, the last quote really comes back to my original challenge of *how* the SOA was going to solve problems. This is a reformulation of the ‘South Park Underpants Gnomes’ problem.

“Another common frustration is being unable to get budget approval to support an SOA implementation. A major contributor to this problem is having a poorly prepared business case.”

Thanks for your indulgences – feedback is welcomed – this is an important topic.
##END PASTE##

Doktat Pontificates on
Systems Integration
or
DON'T BURY YOUR SKELETONS

Since 2001-2002 I have been pondering the move to systems integration via web services (we first studied web services in CSC560 in spring 2002). Conceptually, the idea seems plausible, but I heard the first warning shots several years ago during a web seminar. The participants were discussing attempts to create web services architectures and were finding unacceptable performance and were experiencing difficulties locating the source of the problems. The message was that when an organization moves in this direction, it should have a clearly defined strategy for how the system will be tested and criteria for what will be acceptable performance. Recently (spring 2008) an article appeared citing survey results indicating that most of those surveyed thought their IT departments incapable of implementing a system with the degree of sophistication required by a web services architecture. Subsequent discussions in the CSC560 course prompted the following.

For purposes of discussion, consider the schematic below. Here we see the integration of three different systems running on three different platforms using three different languages

encapsulating the business logic of three different databases. Basically each system is converted to a service by wrapping with an xml-based layer that assumes responsibility for marshalling/un-marshalling requests for that system's resources. The business logic remains encased in the language of the system; the methods of which are invoked via the xml wrapper. Integration of these disparate systems is implemented by an architecture shown here as the services oriented architecture (SOA). If we consider each of these systems "legacy" systems (and I'm using the term legacy to imply any system not accompanied by an automated suite of unit tests), one must wonder where in the system the tests will reside. So, from my perspective, we have just overlooked a nasty problem that the magic of web services isn't going to solve. I don't think this type of approach is the way to solve integrating systems with different platforms and different languages supporting business logic. The following schematic suggests an alternative approach to this problem. The platform problem is handled by JDBC drivers that handle the communication with the database.

The critical difference is the movement of the business logic from the platform and language-dependent system into a domain object model which is where the integration should occur. Organizations refusing to deal with this problem are not facing the real problem. The translation and integration of the business logic into the domain object model would provide enormous advantages and set a better foundation for moving towards a progressively complex future. It is clear that the best path to managing complexity is via POJOs that can be tested independently and this requires an integrated domain object model. Thus, in my opinion, the use of web services for integration of an organization's disparate systems is a hack. Who would want the responsibility of managing such a monster when at its very foundation lurk the nightmares that prevent a clear and fear-free testing strategy with no clear way to test its network performance?
Am I saying no web services at all? Consider the schematic below. Note that the marshalling/un-marshalling of xml-based requests can be handled by the front-end controller displayed there.

I Can't Believe It's Not Software

In yesterday's congressional testimony with AIG CEO Edward Liddy, the following was stated by New York's Gary Ackerman:

There's a great product called "I Can't Believe It's Not Butter," but at least they have the decency to tell you it's not butter... They're calling it "credit default swaps" because if they called it "I Can't Believe It's Not Insurance," he says, maybe no one would buy it.

In last evening's lecture, I found myself comparing this to software systems. A software system is code which includes an automated suite of unit tests. The unit tests are part of the system. A program is code without an automated suite of unit tests but often "sold" as a software system. Feathers calls any code not accompanied by a suite of unit tests, "legacy software." Perhaps a better name for it could be, "I Can't Believe It's Not A Software System." I offer this in the spirit of hope that software developers assume pride in their craft (ala UncleBob Martin) and at least have the decency to tell you when they are giving you a program versus a software system.

Tuesday, March 10, 2009

State Design Pattern and Schrodinger's Cat

In Programming Without Ifs: Challenge Two, our state diagram modeled that of a stopwatch. We found what varied (the behavior in response to a button click) and abstracted into an interface and named the method 'execute'. However because we wanted to avoid the use of conditional logic to decide what to do depending on which button was selected, we created more states to encapsulate the specific behavior we wanted. For example, when the stopwatch was in the 'RUNNING' state it could transition to either a 'HOLD' state or a 'STOPPED' state depending on whether the HOLD or the START/STOP button was subsequently pressed. Thus, we created two states, RunningToStopped and RunningToHold to represent the respective behaviors. How is this like the famous Schrodinger's Cat problem?

A fundamental property of quantum theory is superposition of states which mathematically expresses a system as a combination of many different states. When we go to take a measurement of the system, we collapse the wave function (expressed as a superposition of many states) into one of the possible states. But before we made the measurement, we have no way of knowing what state the system is in. Schrodinger's Cat was a thought experiment (gedanken) designed to show the strangeness of quantum behavior. I liken the above described application of the State Design Pattern to Schrodinger's Cat for the following reason. When the stopwatch is running it is actually in both the RunningToHold and RunningToStopped states simultaneously and we don't know which one it is until we hit either the 'HOLD' or the 'STOP/START' button. It is only after the button is clicked that the stopwatch assumes one or the other state.

Friday, March 6, 2009

Conditional Logic and Code Smells

>>>

At Ward Cunningham's wiki one finds a discussion entitled Switch Statements Smell. This discussion begins with considerations of Beck and Fowler's statement in chapter 3 of Refactoring (Fowler, 1999) that switch statements were smelly because they tended to create duplicated code. I unsuccessfully tried to add to that discussion the treatment found in the Gang-Of-Four book (Gamma, 1999). So, please find below a few more thoughts.

MONOLITHIC and LESS EXPLICIT
The following quote predates and complements Fowler and Beck's discussion in chapter 3 of Refactoring. In the Gang-Of-Four book one finds the following quote on page 307.

“Like long procedures, large conditional statements are undesirable. They’re monolithic and tend to make the code less explicit, which in turn makes them difficult to modify and extend. The State pattern offers a better way to structure state-specific code. The logic that determines the state transitions doesn’t reside in monolithic if or switch statements but instead is partitioned between the State subclasses.”

DECOUPLED STATE-BEHAVIOR PRINCIPLE and TEMPORAL IGNORANCE
Using conditional logic to implement behavior which is dependent on the state of a class is programming in temporal ignorance. If a change of state has occurred that affects behavior, then the readyness of that class to implement the appropriate behavior should occur synchronously with the change of state. Why should an object live in ignorance when a change of state has occurred that will also change how the object behaves? I refer to this state of ignorance as decoupled state-behavior (DSB). Allowing the state of an object to be decoupled from its behavior should be considered a loose end, a piece of untidyness which requires conditional logic to be resolved. Why leave such loose ends around? They can only lead to problems. Note that this does not apply to using conditional logic to determine other actions not related to the state of the object. DSB refers stricly to the relationship between the state and behavior of the same object. Since DSB requires conditional logic for resolution, this situation also demands consideration from the race condition perspective.

IF STATEMENTS AND RACE CONDITIONS
Temporal ignorance creates race conditions. In addition to violating a principle of OO programming, that a method should do no more than one thing, conditional logic statements are not thread safe. Consider the following 'if' statement:

if (propertyValue == 1)
execute statement1;
else
execute statement2;;

We generally assume that nothing will change the value of propertyValue before we execute statement1. That is a false assumption. It is easy to create race conditions where the propertyValue is set to 2 by a competing thread in between executing the 'if' statement and executing statement1 in the example above. Wouldn't it be smarter to securely change the behavior at the same time the property value is changed?

public void setPropertyValue(int intValue)
{
synchronized (this)
{
propertyValue = intValue;
currentStrategy = appropriateStrategy;
}
}

REFERENCES

Gamma, Erich et al (1994) Design Patterns: Elements of Reusable Object-Oriented Software [0201633612]

Fowler, Martin (1999) Refactoring [ISBN 0201485672]

Over-Engineering and Design Patterns

I began studying design patterns in roughly the same period that I read Beck’s treatise on eXtreme Programming (Beck,1999). There is a conflict between the two schools and it’s important to consider it. The design pattern mantra is that we have identified a pattern that occurs often in programming and we have a way to solve it. No sense reinventing the wheel, there’s a pattern that solves the problem in a way that creates desirable software architecture. By learning these patterns we are creating a system of best practices which includes a richer vocabulary. By applying these patterns, we create more loosely coupled systems that are easier to maintain and change. From a pedagogical perspective, this is important to learn and a key stage to development. The process of understanding your system’s responsibilities and identifying these patterns is important in the development of OO thinking - which is entirely different from procedural thinking. But then the student encounters the “Stop Over-Engineering” people and becomes confused.

After passing through his phase of studying, understanding and applying design patterns, Kerievsky (2002) wrote a short paper entitled, “Stop Over-Engineering.” He thoughtfully describes his evolution to the following recognition: “But over time, the power of patterns led me to lose sight of simpler ways of writing code.” After relating a story where he realized, while pair-programming, that his approach to solving a problem was "… like applying a sledgehammer when a few light taps with a small hammer would do," he proceeds to describe what I believe is the next pedagogical stage in a programmer’s education, refactoring.
Nevertheless, a student of OO programming can’t stop over-engineering unless they know how to over-engineer in the first place. Kerievsky’s insight and subsequent treatise (Kerievsky, 2005) is the product of an active consultant in the software construction business. Students must learn the difference between the teachings of a professor and the teachings of a professional. The latter isn’t necessarily concerned with the entire pedagogical structure - their audience includes those who have mastered the stages leading up to their current level of understanding. The Kerievsky teachings are not for those who haven’t already studied design patterns. So, in my opinion, learn to over-engineer first (Gamma et al, 1994; Metsker, 2002; Shalloway & Trott, 2004;Martin, 2002 ) and then begin your studies of Kerievsky (2005) , Fowler (1999) and Beck (2002).

REFERENCES:
Beck, Kent (1999) eXtreme Programming eXplained: Embrace Change [ISBN 0201616416]
Fowler, Martin (1999) Refactoring [ISBN 0201485672]
Kerievsky, Joshua (2002) Stop Over-Engineering [http://www.industriallogic.com/papers/StopOverEngineering.pdf]
Kerievsky, Joshua (2005) Refactoring to Patterns [ISBN 0321213351]
Martin, Robert (2002) Agile Software Development: Principles, Patterns and Practices [ISBN 0135974445]
Metsker, Steven (2002) Design Patterns Java Workbook [ISBN 0201743973]
Shalloway, Alan and Trott, James R. (2004) Design Patterns Explained: A New Perspective on Object-Oriented Design, 2nd Ed. [ISBN 0321247140]

Thursday, March 5, 2009

Dropping Procedural To Go Object-Oriented

I am often making the statement that many programmers who think they are object-oriented (OO) programmers are procedural programmers using an object-oriented language. In this piece I hope to explain clearly what I mean.

For the past ten years I've been interacting with professional programmers enrolled in the Masters of Software Engineering program at Carroll University. In general these people are bright and clever at solving algorithmically-oriented problems. However, they often struggle with learning techniques in OO programming and design - particularly with the idea of assigning responsibility for actions among a collection of objects working in harmony. They have learned to solve programming problems in a procedural manner and when presented with the OO paradigm, they quickly learn the OO language but fall into patterns where they use the OO language to program procedurally. Talented procedural programmers need to expand their capabilities to meet the demands of more complex software.

There are many different interpretations of what procedural programming means. For example UncleBob Martin has stated that inverted dependencies is a sign of procedural programming(Martin, 19XX). I like this definition but I think it takes someone who already understands how to "object think" to grok it. I will continue here with more discussion of what I mean by procedural programming.

For me the first sign of a procedural programmer is the centralization of responsibility which is seen when we find objects that are doing too many things. Also, within these mega-classes are found methods that are also doing too many things and generally contain large conditional logic structures. The cognitive process used to create these types of programs indicates either ignorance of or a misunderstanding of the goals of OO programming. Or, if the goals are understood, the method for achieving these goals has never been learned. At this point the discussion could easily segue into an "objects first" debate which will be considered in some other piece. For me which side of the "objects first" debate one may take is irrelevant, it is clear that somewhere in the progammer's education, a critical step in their thinking processes has not occurred. These types of programmers are not suited for creating large enterprise software systems. These types of programmers create what are known as Big Balls of Mud.