SlideShare a Scribd company logo
Creating Stable 
Assignments Jose Ortega/SIS 
A paradigm for creating efficient, aesthetic self-referential code 
The First Rule of Optimization: Don’t do it. 
The Second Rule of Optimization (For experts only): Don’t do it yet. 
—Michael Jackson⁄ 
When defining a copy assignment operator for a class, 
the problem of self assignment is often considered trivial 
or irrelevant, or is simply not considered. However, there 
are good reasons to consider what might happen if an ob-ject 
is assigned to itself, and there is also documented wisdom in 
this area. The standard form to handle self assignment was cap-tured 
by Coplien as part of his Orthodox Canonical Class Form 
(OCCF)¤: 
type &type::operator=(const type &rhs) 
{ 
if(this != &rhs) 
{ 
appropriate copying and release actions 
} 
return *this; 
} 
Kevlin Henney 
This is the basic schema you should seek to follow for all your 
assignment operators. A revisit to the Orthodox Canonical Class 
Form calls into doubt its general applicability for reasons of 
efficiency,‹ but before dealing with that issue specifically it is im-portant 
to establish what is meant by Orthodox Canonical Class 
Form and what we hope to achieve with it. 
ORTHODOX CANONICAL CLASS FORM 
orthodox adj. conforming with established standards, as in reli-gion, 
behavior, or attitudes.› 
canonical adj. (of an expression, etc.) expressed in a standard form.fi 
The OCCF is a recommendation, not a rule: 
Programming standards must be valid for both newcomers and ex-perts. 
This is oˇen diƒcult to accomplish. We have solved this 
problem by diÏerentiating our guidelines into rules and recom-mendations. 
Rules should almost never be broken by anyone, 
whereas recommendations are supposed to be followed most of the 
C++ Report ∫ http://www.sigs.com 25
CREATING STABLE ASSIGNMENTS 
time, unless there is a good reason not to. This division allows ex-perts 
to break a recommendation, or sometimes even a rule, if they 
badly need to.fl 
It is not something to be followed slavishly, but has an important 
property: It works, it’s safe and, as an idiom, it clearly communi-cates 
its purpose to readers. You can have greater conˆdence in 
something that is written following this form than in something 
that has not been. 
Confidence and Intrinsic Quality Conˆdence is not something 
woolly that should be underestimated or ignored in the process 
of soˇware development; it is essential. In the past, I have been 
presented with code that looked like it grew on a spaghetti tree, 
If you can understand the code 
by its form, it will be easier for you 
to both have confidence in it 
and spot any mistakes. 
greeted it with a perplexed expression, and then been told chirpily 
by its author “not to worry; it works.”* Not. 
Not only should a piece of soˇware “work” (what this means 
is a whole topic in itself, but I’m sure you can come up with a num-ber 
of plausible consensus deˆnitions), but it should also look like 
it works. Commercial code is not written solely for the beneˆt of 
its author—although clearly the industry would empty out in the 
absence of any such gratiˆcation—and the idea that the only de-liverable 
is a piece of executable code at the end of a waterfall de-velopment 
process should be greeted with the derision (as well as 
project failure) it deserves. 
If you can understand the code by its form, it will be easier for 
you to both have conˆdence in it and spot any mistakes. If you 
cannot see that a piece of code is correct, how can you have 
conˆdence that it is correct? Executing it is not the answer: Dy-namic 
bug hunting and bashing is a poor substitute for code that 
is internally well structured. The concept we are identifying here 
is that of intrinsic quality.‡ 
Orthodoxy and Heresy There is a great deal of beneˆt in following 
a standard form for something that could otherwise give rise to 
obscure and unsafe behavior. One of the aims in programming is 
to be precise. If you are not being precise, you are being vague. If 
you are being vague, you don’t need the help of a programming 
language—beer is a far better medium for this. 
But as I said, this is a recommendation and not a doctrine or 
religious law. What if you feel an alternative solution is more ap-propriate? 
Will you be cast out from the gates of the C++ pro-gramming 
community and roasted over a code review? Should you 
just rebel outright, go oÏ and establish your own orthodoxy? 
Nothing so dramatic is necessary: A comment will do. Just show 
that not having an explicit self check was considered, but deemed 
unnecessary as the code presented is already safe. 
The important property of the canonical form is that it is based 
on some guarantees of behavior; a speciˆcation. Whatever code 
structure you settle on should satisfy this spec. To return to the 
idea of rules and recommendations, the OCCF is a recommen-dation, 
but the spec it is based on is a rule: 
Rule 5.12 Copy assignment operators should be protected from 
doing destructive actions if an object is assigned to itself.fl 
Any departure from the OCCF must satisfy the same set of re-quirements. 
In short, it must still work. 
EQUIVALENT FORMS The basic structure of the code oÏered by 
Glassborow can be summarized as: 
type &type::operator=(const type &rhs) 
{ 
take a copy of rhs’s resources 
release existing resources 
bind copy to self 
return *this; 
} 
Placing copy before release is required because this control Òow 
ensures self assignment is not a problem. If &rhs is the same as this, 
we will waste a bit of time making a redundant copy of the cur-rent 
object, releasing current resources and then reassigning the 
copy. Perhaps the redundancy is not so aesthetically pleasing, but 
it is certainly safe and it will not be executed commonly enough 
to make it an issue. Perhaps the only thing missing is a comment 
(note: “comment,” not “essay”) stating that this code is safe for 
self assignment. 
The applicability of this is for dynamically allocated represen-tation— 
typically a single pointer to an object—that can be easily 
copied (based on the statically declared type) or cloned (based on 
the dynamic type—giving rise to the concept of type-shallow and 
type-deep copying). 
What we have is the idea of behavioral (or black box) equiva-lence. 
Given the basic requirements outlined, this structure is 
substitutable for the OCCF. 
Don’t Optimize So, in the name of overall eƒciency and correctness: 
no problems. Glassborow’s motivation, however, is questionable: 
[T]he cost of making the check for self assignment is some kind 
of comparison and branch statement. Branches are bad news on 
pipelined architecture. If we can write code with fewer branches 
we should do so.‹ 
This misplaced concern for code-level eƒciency is the kind of thing 
that has been shown time and again as subordinate to optimiza- 
* I am reminded of an occasion when I was working on-site and needed some new 
code from someone back at the office. I said that I didn’t expect it to be fully tested 
as he didn’t have the right environment in which to do this. I was a little perplexed 
when the code arrived and failed to compile. Upon closer inspection, I understood 
why: There were basic syntax errors all over the place, and the code could never 
have been compiled. This was confirmed when I rang him to discover that because 
I had not expected full testing, he had taken this to mean that he didn’t need to 
compile it either. In his vocab “compile” and “test” had somehow ended up as 
synonyms! Confidence was not high. 
26 June 1998
tion through eÏective data structure and algorithm use. 
Let’s take a look at some code: 
type &type::operator=(const type &rhs) 
{ 
rep_type *new_body = new rep_type(*rhs.body); 
delete body; 
body = new_body; 
return *this; 
} 
No branches? Take a look at a pseudo-assembler output: 
push sizeof__rep_type 
call __op_new ; operator new 
move new_body, result 
compare new_body, null 
jmpifeq postctor 
push rhs + body 
push new_body 
call rep_type__ctorcp ; rep_type::rep_type 
postctor: 
compare this + body, null 
jmpifeq postdtor 
push this + body 
call rep_type__dtor ; rep_type::~rep_type 
postdtor: 
push this + body 
call __op_delete ; operator delete 
move this + body, new_body 
move result, this 
return ; return *this 
That’s right; there are two implicit conditional branches: 
∫ A null return from a new should not have a constructor called 
on it˚; and 
∫ a null pointer should not have a destructor called on it before 
being handed to delete. 
In truth, this is a case of two rather than three branches, as op-posed 
to zero or one. The diÏerence? Look at everywhere there is 
a call instruction. This means we are calling four other functions, 
two of which we know handle heap management. Against that 
backdrop, the extra couple of instructions from an explicit self 
check look even less clock threatening than normal: 
compare this, rhs 
jmpifeq wayout ; if(this != &rhs) 
… 
wayout: 
move result, this 
return ; return *this 
The level of optimization we have achieved is what the phrase “a drop 
in the ocean” was intended to describe—if we used the word “op-timize” 
anywhere near such code we would be deceiving ourselves. 
Don’t Optimize Yet The next claim to investigate is that of 
branches—speciˆcally conditional branches—on pipelined ar-chitectures. 
Eliminating them based on some hope for optimiza-tion 
is as rational as not walking under ladders based on 
superstition—there are times when it is unwise to do so, e.g., 
when someone’s already up the ladder with a can of paint, but that 
kind of judgment is not the same as superstition. So clearly we need 
to understand something about both conditional branching and 
pipelining before making a decision. 
Some uses of conditional branching are simply the result of 
poor basic programming skills: 
if(enabled) 
enabled = false; 
else 
enabled = true; 
The previous example illustrates the weak grasp the programmer has 
of logic. You don’t need to be a genius to write and comprehend: 
enabled = !enabled; 
I agree with the basic tenet that we should write fewer control 
structures. A well-abstracted system tends to encapsulate control 
˚ A relatively late but minor change to the Draft ISO C++ Standard clarifies that 
any version of operator new that has a throw spec is assumed not to return null to 
indicate failure. The global new is specified to throw std::bad_alloc—therefore, this 
null check will not be required. However, it will take a little time for implemen-tors 
to catch up with this change. 
C++ Report ∫ http://www.sigs.com 27
CREATING STABLE ASSIGNMENTS 
Òow within operations. Examples of this include polymorphism 
over explicit switch code, STL’s combination of iterators and it-erator 
algorithms, and the Enumeration Method pattern.° 
But many conditional branches are a fact of life: It is diƒcult 
to eliminate them if they are intrinsic to a problem description. 
How many branches are there in the following code? 
if(year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)) 
cout << “Leap!!!” << endl; 
Three. One for every condition: Remember, C++’s built-in con-ditional 
operators are short circuiting. 
An instruction pipeline contains instructions prefetched for ex-ecution. 
The many stages of an eÏective pipeline might include 
fetch instruction, decode instruction, calculate operands, fetch 
operands, execute instruction, and write operand result. Run-ning 
these in parallel rather than in sequence is a very eÏective 
processor optimization. The only glitch appears to be that a branch 
in the control Òow may invalidate the instructions in the pipeline: 
Although one branch is prefetched, what if the other is taken? 
It would be surprising and unfortunate if such an elegant ar-chitecture 
had not been fully thought out —“bad news” indeed— 
but luckily, the impact of branches is anything but devastating, 
and pipelined chips sell and perform very well. One solution is 
to use a multi-stream architecture, i.e., you 
can hold more than one branch at a time. 
Branch prediction and delayed branching are 
more cerebral in their approach. Perhaps the 
simplest approach used is that the instruction 
stream following the branch instruction is 
loaded, i.e., what would have happened in the 
pipeline anyway. 
How much of an impact does this last ap-proach 
have on the code we’ve examined so 
far? None whatsoever. If you look at how the 
code is arranged, it is the common case that im-mediately 
follows the branch, and the uncom-mon 
one that must be branched on. If you 
wanted a rule concerning branches that took 
this into account it would be a simple one: 
Place the commonly executed code nearest to the 
condition that tests for it. 
Interestingly, this is what many program-mers 
tend to do already, but for readability rea-sons: 
Given an if else, the if body should deal with 
the common case code, and the else body with the 
more exceptional occurrence. If they are equally 
valid, i.e., neither is exceptional, then the order is 
best determined by the most positive phrasing of 
the condition, i.e., the equivalent expression with 
the least contorted logic. 
It is oˇen said that cleanly structured code 
tends to be more eƒcient than code whose 
guiding philosophy has been one of successive 
application of folklore optimizations. This case 
seems to vindicate that. 
Relative Merits We have looked at behav-iorally 
equivalent forms, but there is a stronger 
equivalence that is hinted at in the recom-mendation 
given above where I mention 
“equivalent expression” for a condition. For 
built-in types (and—one would hope—user-de 
ˆned types) an example of strong logical 
equivalence would be that !(a == b) and a != b 
have the same meaning and are fully inter-changeable. 
Gimple 
1/2 Island 
28 June 1998
Here’s an interesting question: How much time is spent de-bating 
the following code snippets: 
type &type::operator=(const type &rhs) 
{ 
if(this != &rhs) 
{ 
appropriate copying and release actions 
} 
return *this; 
} 
Or: 
type &type::operator=(const type &rhs) 
{ 
if(this == &rhs) 
return *this; 
appropriate copying and release actions 
return *this; 
} 
Which is the better implementation? These are equivalent in the 
sense that they have identical meaning, and one can be trans-formed 
into the other by a good compiler. If you are wondering 
which way such a compiler would lean, look back at some of the 
points we have discussed. That’s right, the scruÏy multiple return 
version is less optimal than the version that uses the structured 
programming form.Δ 
However, few compilers do that well enough so you are leˇ 
with a separate set of concerns to balance. The common case is 
that the leˇ and right hand sides of an assignment are not the same, 
so if your interest is either pipeline eƒciency or layout, you would 
chose the ˆrst example. A direct translation of the second exam-ple 
into assembler tends to result in two jumps: 
compare this, rhs 
jmpifne postif ; if(this == &rhs) 
jmp wayout 
postif: 
… ; perform copying, etc. 
wayout: 
move result, this 
return ; return *this 
For C++ it is important that common function exit code is shared 
as this can involve destructor calls which, if space is your concern, 
you would not wish to have duplicated at every return point. If 
you ask to optimize the second example for speed you will prob-ably 
end up with duplicated code: 
compare this, rhs 
jmpifne postif ; if(this == &rhs) 
move result, this 
return ; return *this 
postif: 
… ; perform copying, etc. 
wayout: 
move result, this 
return ; return *this 
It is interesting that we can arrive at the same conclusion from 
two completely diÏerent approaches; it says something about 
the relationship between forms at diÏerent levels. I personally side 
with those whose concern is the structure of the written code— 
my reasons for this are based on the belief that soˇware devel-opment 
is an engineering profession, albeit an immature one. 
What if you feel an alternative solution 
is more appropriate? Will you be 
cast out from the gates of the C++ 
programming community and roasted 
over a code review? 
There are a few people who need to be concerned with the ma-chine 
level, but that ˆgure is a lot less than the number who con-cern 
themselves with it. 
STABLE INTERMEDIATE FORMS Returning to the proposed alter-native 
code structure for assignment: Although arrived at from a 
faulty line of logic, it is sound. For those interested in patterns, 
what we have here is a language level pattern (better known as an 
idiom) that has a well-deˆned context, i.e., C++ copy assignment 
operator for an object structured using the Handle/Body idiom¤¯· 
(more generally, the Bridge pattern⁄‚) where the body is easily 
copied (either shallow or deep with respect to its type). The pro-posed 
conˆguration is something that works, meeting all the re-quirements 
for an assignment operator. 
Exception Safety However, a pattern has three essential parts: con-text, 
forces, and conˆguration.⁄⁄ The conÒicting forces that are 
listed for this pattern are at fault, and hence it is not a pattern. But 
since the context is valid and the conˆguration seems to have some 
merit, can we say something more about it? Alan Griƒths, in his 
role as editor, commented on Glassborow’s solution: 
This has the added beneˆt of leaving the object in a consistent state 
if an exception is thrown during the clone operation. I’d rate this 
as more important than worrying about the diÏerent number of 
processor cycles required for each version.‹ 
My only caveat to this—as we have shown—is that exception safety 
is the only beneˆt to this approach—as an issue, processor cycles 
are not even on the radar. In addition to the usual forces describ-ing 
the requirements on a copy assignment operator, exception 
safety is the most important force resolved. Don’t underestimate 
how significant exceptions can be for invalidating assumptions— 
and therefore code.⁄⁄ Let us examine the problem solved: 
Δ It has been said that in the light of modern optimizing techniques based on data 
rather than control flow, Niklaus Wirth wishes he had not included any jump state-ments 
(a function return statement and a loop exit) in Oberon (MODULA 2’s suc-cessor) 
as the discontinuities introduced into the control flow are not only 
inelegant, but they thwart a number of optimizations. 
C++ Report ∫ http://www.sigs.com 29
CREATING STABLE ASSIGNMENTS 
1. release existing resources 
2. take a copy of rhs’s resources 
3. bind copy to self 
What if an exception is thrown during step two? The object re-mains 
in existence, but it now has a chaotic and unstable state: Its 
resources have been released, but it still refers to them. What will 
happen upon destruction of that object? That’s right, destruction 
of a completely diÏerent kind! Objects in an unstable state can-not 
be destroyed without spreading that instability to the rest of 
the program. However, there is no safe and consistent way to 
stop an object from reaching the end of its life. To put it mildly, 
this is a nontrivial issue. 
The solution is to ensure that at every intermediate step the ob-ject 
has a coherent state, i.e., not only is the result of every macro 
change stable, but each micro change from which it is composed 
is also stable. This principle of Stable Intermediate Forms under-lies 
successful soˇware development strategies⁄¤ as well as other 
disciplines of thought and movement, e.g., T’ai Chi. 
1. take a copy of rhs’s resources 
2. release existing resources 
3. bind copy to self 
This sequence resolves the forces. It is also suƒciently general that 
it is possible to use this with the original OCCF—for instance, 
when writing a copy assignment for a class whose objects have a 
mixed style of representation. 
A Pattern In summary, the many concerns facing a developer 
branch into myriad forces that fall somewhere between “chal-lenging” 
and “daunting” in the soˇware engineer’s dictionary. 
Compared to other industries, soˇware development sports a high 
number of people who can juggle. In this light, it is perhaps easy 
to see why. Close inspection of the configuration reveals a sound 
solution to a different problem, and a documentable pattern. 
COPY BEFORE RELEASE 
Problem: 
∫ Ensuring copy assignment in C++ is exception safe. 
Context: 
∫ A class has been implemented as handle/body pair. 
∫ The body is copyable—type shallow or deep as appropriate. 
Forces: 
∫ Any of the steps taken in performing the assignment may fail, 
resulting in a thrown exception. Partial completion of the steps 
may leave the handle in an unstable state. 
∫ The result of assignment, successful or otherwise, must result 
in a stable handle. 
∫ Self assignment must also result in a stable handle. 
∫ Aˇer successful completion of the assignment, the handle on 
the leˇ-hand side of the assignment must be behaviorally 
equivalent to the handle on the right-hand side. 
∫ Assignment—successful or otherwise—must be nonlossy, 
i.e., no memory leaks. 
Solution: 
∫ Perform the body copy before releasing the existing body. 
∫ Bind the body copy to the handle aˇer releasing the existing 
body. 
Resulting Context: 
∫ The existing body is not deleted before the body copy has been 
attempted. Therefore, a failed body copy will not result in an 
unstable handle. 
∫ Failed body release may still result in an unstable handle. How-ever, 
throwing exceptions from destructors is a practice com-monly 
cautioned against. 
∫ The ordering accommodates safe self assignment at the cost 
of redundant copy. 
∫ If the body copy preserves behavior equivalence, a successful as-signment 
will preserve it for the composite handle/body object. 
∫ The solution can be used in conjunction with the schema for 
copy assignment from the Orthodox Canonical Class Form. 
The issue of a failed deletion is an interesting one, although not 
often one worth solving.⁄‹ However, it is possible in this pattern 
with a minor tweak to the ordering. The solution is left, as they 
say, as an excercise for the reader. ˘ 
References 
1. Bentley, J. More Programming Pearls, Addison–Wesley, 
Reading, MA, 1988. 
2. Coplien, J. Advanced C++ Programming Styles and Idioms, 
Addison–Wesley, Reading, MA, 1992. 
3. Glassborow, F. “The Problem of Self Assignment,” Overload 19, 
Association of C and C++ Users, UK, Apr./May 1997. 
4. The Collins Concise Dictionary, Collins, UK, 1988. 
5. Borowski, E. J. and J. M. Borwein. Dictionary of Mathematics, 
Collins, UK, 1989. 
6. Henricson, M. and E. Nyquist. Industrial Strength C++: Rules and 
Recommendations, Prentice Hall, Upper Saddle River, NJ, 1997. 
7. Hatton, L. Safer C, McGraw–Hill, New York, NY, 1994. 
8. Beck, K. Smalltalk Best Practice Patterns, Prentice Hall, Upper 
Saddle River, NJ, 1997. 
9. Coplien, J. Software Patterns, SIGS Books, New York, NY, 1996. 
10. Gamma, E. et al. Design Patterns: Elements of Reusable Object- 
Oriented Software, Addison–Wesley, Reading, MA, 1995. 
11. Alexander, C. The Timeless Way of Building, Oxford University 
Press, UK, 1979. 
12. Booch, G. Object-Oriented Analysis and Design with 
Applications, Benjamin/Cummings, Menlo Park, CA, 1994. 
13. Sutter, H. “More Exception-Safe Generic Containers,” C++ 
Report, 9(10):24–31, Nov./Dec. 1997. 
Kevlin Henney is a Senior Technologist with QA Training in the UK. He can 
be contacted at kevlin@acm.org. 
30 June 1998

More Related Content

What's hot

Exceptional Naming
Exceptional NamingExceptional Naming
Exceptional Naming
Kevlin Henney
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
HamletDRC
 
What's in a Name?
What's in a Name?What's in a Name?
What's in a Name?
Kevlin Henney
 
Object-oriented design principles
Object-oriented design principlesObject-oriented design principles
Object-oriented design principles
Xiaoyan Chen
 
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Steven Smith
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Code
mtoppa
 
How To Navigate And Extend The Flex Infrastructure
How To Navigate And Extend The Flex InfrastructureHow To Navigate And Extend The Flex Infrastructure
How To Navigate And Extend The Flex Infrastructure
michael.labriola
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2
Hammad Rajjoub
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID Principles
Ganesh Samarthyam
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principles
Edorian
 

What's hot (10)

Exceptional Naming
Exceptional NamingExceptional Naming
Exceptional Naming
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
What's in a Name?
What's in a Name?What's in a Name?
What's in a Name?
 
Object-oriented design principles
Object-oriented design principlesObject-oriented design principles
Object-oriented design principles
 
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Code
 
How To Navigate And Extend The Flex Infrastructure
How To Navigate And Extend The Flex InfrastructureHow To Navigate And Extend The Flex Infrastructure
How To Navigate And Extend The Flex Infrastructure
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID Principles
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principles
 

Viewers also liked

Introducing the FLUID Principles
Introducing the FLUID PrinciplesIntroducing the FLUID Principles
Introducing the FLUID Principles
Kevlin Henney
 
A Tale of Three Patterns
A Tale of Three PatternsA Tale of Three Patterns
A Tale of Three Patterns
Kevlin Henney
 
The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...
Alberta Soranzo
 
97 Things Every Programmer Should Know
97 Things Every Programmer Should Know97 Things Every Programmer Should Know
97 Things Every Programmer Should Know
Kevlin Henney
 
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Codemotion
 
DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)
dpc
 
A Tale of Two Patterns
A Tale of Two PatternsA Tale of Two Patterns
A Tale of Two Patterns
Kevlin Henney
 
Seven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java ProgrammersSeven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java Programmers
Kevlin Henney
 
Patterns of Value
Patterns of ValuePatterns of Value
Patterns of Value
Kevlin Henney
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
Kevlin Henney
 
Collections for States
Collections for StatesCollections for States
Collections for States
Kevlin Henney
 
SOLID Deconstruction
SOLID DeconstructionSOLID Deconstruction
SOLID Deconstruction
Kevlin Henney
 
Substitutability
SubstitutabilitySubstitutability
Substitutability
Kevlin Henney
 
Framing the Problem
Framing the ProblemFraming the Problem
Framing the Problem
Kevlin Henney
 
Driven to Tests
Driven to TestsDriven to Tests
Driven to Tests
Kevlin Henney
 
Immutability FTW!
Immutability FTW!Immutability FTW!
Immutability FTW!
Kevlin Henney
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
Kevlin Henney
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
Kevlin Henney
 

Viewers also liked (18)

Introducing the FLUID Principles
Introducing the FLUID PrinciplesIntroducing the FLUID Principles
Introducing the FLUID Principles
 
A Tale of Three Patterns
A Tale of Three PatternsA Tale of Three Patterns
A Tale of Three Patterns
 
The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...The web you were used to is gone. Architecture and strategy for your mobile c...
The web you were used to is gone. Architecture and strategy for your mobile c...
 
97 Things Every Programmer Should Know
97 Things Every Programmer Should Know97 Things Every Programmer Should Know
97 Things Every Programmer Should Know
 
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
Keynote: Small Is Beautiful - Kevlin Henney - Codemotion Rome 2015
 
DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)DPC2007 Objects Of Desire (Kevlin Henney)
DPC2007 Objects Of Desire (Kevlin Henney)
 
A Tale of Two Patterns
A Tale of Two PatternsA Tale of Two Patterns
A Tale of Two Patterns
 
Seven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java ProgrammersSeven Ineffective Coding Habits of Many Java Programmers
Seven Ineffective Coding Habits of Many Java Programmers
 
Patterns of Value
Patterns of ValuePatterns of Value
Patterns of Value
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
 
Collections for States
Collections for StatesCollections for States
Collections for States
 
SOLID Deconstruction
SOLID DeconstructionSOLID Deconstruction
SOLID Deconstruction
 
Substitutability
SubstitutabilitySubstitutability
Substitutability
 
Framing the Problem
Framing the ProblemFraming the Problem
Framing the Problem
 
Driven to Tests
Driven to TestsDriven to Tests
Driven to Tests
 
Immutability FTW!
Immutability FTW!Immutability FTW!
Immutability FTW!
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
 
Worse Is Better, for Better or for Worse
Worse Is Better, for Better or for WorseWorse Is Better, for Better or for Worse
Worse Is Better, for Better or for Worse
 

Similar to Creating Stable Assignments

Put to the Test
Put to the TestPut to the Test
Put to the Test
Kevlin Henney
 
Writing Quality Code
Writing Quality CodeWriting Quality Code
Writing Quality Code
indikaMaligaspe
 
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
LizzyManz
 
Principled And Clean Coding
Principled And Clean CodingPrincipled And Clean Coding
Principled And Clean Coding
Metin Ogurlu
 
The Taming Of The Code
The Taming Of The CodeThe Taming Of The Code
The Taming Of The Code
Alan Stevens
 
Code quality
Code quality Code quality
Code quality
Sunil Prasad
 
Cinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patternsCinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patterns
Steven Smith
 
Node.JS error handling best practices
Node.JS error handling best practicesNode.JS error handling best practices
Node.JS error handling best practices
Yoni Goldberg
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
Eyob Lube
 
Clean Code Software Engineering
Clean Code Software Engineering Clean Code Software Engineering
Clean Code Software Engineering
Inocentshuja Ahmad
 
Clean code quotes - Citações e provocações
Clean code quotes - Citações e provocaçõesClean code quotes - Citações e provocações
Clean code quotes - Citações e provocações
André de Fontana Ignacio
 
How to find 56 potential vulnerabilities in FreeBSD code in one evening
How to find 56 potential vulnerabilities in FreeBSD code in one eveningHow to find 56 potential vulnerabilities in FreeBSD code in one evening
How to find 56 potential vulnerabilities in FreeBSD code in one evening
PVS-Studio
 
The "Evils" of Optimization
The "Evils" of OptimizationThe "Evils" of Optimization
The "Evils" of Optimization
BlackRabbitCoder
 
Making an Exception
Making an ExceptionMaking an Exception
Making an Exception
Kevlin Henney
 
The Perfect Couple
The Perfect CoupleThe Perfect Couple
The Perfect Couple
Kevlin Henney
 
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
Andrey Karpov
 
why c++11?
why c++11?why c++11?
why c++11?
idrajeev
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
PVS-Studio
 
Clean Code - Part 2
Clean Code - Part 2Clean Code - Part 2
Clean Code - Part 2
Knoldus Inc.
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Abdelkrim Boujraf
 

Similar to Creating Stable Assignments (20)

Put to the Test
Put to the TestPut to the Test
Put to the Test
 
Writing Quality Code
Writing Quality CodeWriting Quality Code
Writing Quality Code
 
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
“Don’t Repeat Yourself”: 4 Process Street Features to Keep Work DRY
 
Principled And Clean Coding
Principled And Clean CodingPrincipled And Clean Coding
Principled And Clean Coding
 
The Taming Of The Code
The Taming Of The CodeThe Taming Of The Code
The Taming Of The Code
 
Code quality
Code quality Code quality
Code quality
 
Cinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patternsCinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patterns
 
Node.JS error handling best practices
Node.JS error handling best practicesNode.JS error handling best practices
Node.JS error handling best practices
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
 
Clean Code Software Engineering
Clean Code Software Engineering Clean Code Software Engineering
Clean Code Software Engineering
 
Clean code quotes - Citações e provocações
Clean code quotes - Citações e provocaçõesClean code quotes - Citações e provocações
Clean code quotes - Citações e provocações
 
How to find 56 potential vulnerabilities in FreeBSD code in one evening
How to find 56 potential vulnerabilities in FreeBSD code in one eveningHow to find 56 potential vulnerabilities in FreeBSD code in one evening
How to find 56 potential vulnerabilities in FreeBSD code in one evening
 
The "Evils" of Optimization
The "Evils" of OptimizationThe "Evils" of Optimization
The "Evils" of Optimization
 
Making an Exception
Making an ExceptionMaking an Exception
Making an Exception
 
The Perfect Couple
The Perfect CoupleThe Perfect Couple
The Perfect Couple
 
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
PVS-Studio and CppCat: An Interview with Andrey Karpov, the Project CTO and D...
 
why c++11?
why c++11?why c++11?
why c++11?
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
Clean Code - Part 2
Clean Code - Part 2Clean Code - Part 2
Clean Code - Part 2
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
 

More from Kevlin Henney

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
Kevlin Henney
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
Kevlin Henney
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
Kevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Kevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Kevlin Henney
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
Kevlin Henney
 
Get Kata
Get KataGet Kata
Get Kata
Kevlin Henney
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
Kevlin Henney
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
Kevlin Henney
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
Kevlin Henney
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
Kevlin Henney
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
Kevlin Henney
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
Kevlin Henney
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good Name
Kevlin Henney
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Kevlin Henney
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
Kevlin Henney
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
Kevlin Henney
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
Kevlin Henney
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
Kevlin Henney
 
Good Code
Good CodeGood Code
Good Code
Kevlin Henney
 

More from Kevlin Henney (20)

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
 
Get Kata
Get KataGet Kata
Get Kata
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good Name
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
 
Good Code
Good CodeGood Code
Good Code
 

Recently uploaded

Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
45unexpected
 
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
3610stuck
 
03. Ruby Variables & Regex - Ruby Core Teaching
03. Ruby Variables & Regex - Ruby Core Teaching03. Ruby Variables & Regex - Ruby Core Teaching
03. Ruby Variables & Regex - Ruby Core Teaching
quanhoangd129
 
How to Secure Your Kubernetes Software Supply Chain at Scale
How to Secure Your Kubernetes Software Supply Chain at ScaleHow to Secure Your Kubernetes Software Supply Chain at Scale
How to Secure Your Kubernetes Software Supply Chain at Scale
Anchore
 
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdfAI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
Daniel Zivkovic
 
SAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple SoftwareSAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple Software
Zyple Software
 
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
902basic
 
How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024
TaskSprint | Employee Efficiency Software
 
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
shanihomely
 
TEQnation 2024: Sustainable Software: May the Green Code Be with You
TEQnation 2024: Sustainable Software: May the Green Code Be with YouTEQnation 2024: Sustainable Software: May the Green Code Be with You
TEQnation 2024: Sustainable Software: May the Green Code Be with You
marcofolio
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
87tomato
 
Amadeus Travel API, Amadeus Booking API, Amadeus GDS
Amadeus Travel API, Amadeus Booking API, Amadeus GDSAmadeus Travel API, Amadeus Booking API, Amadeus GDS
Amadeus Travel API, Amadeus Booking API, Amadeus GDS
aadhiyaeliza
 
Authentication Review-June -2024 AP & TS.pptx
Authentication Review-June -2024 AP & TS.pptxAuthentication Review-June -2024 AP & TS.pptx
Authentication Review-June -2024 AP & TS.pptx
DEMONDUOS
 
04. Ruby Operators Slides - Ruby Core Teaching
04. Ruby Operators Slides - Ruby Core Teaching04. Ruby Operators Slides - Ruby Core Teaching
04. Ruby Operators Slides - Ruby Core Teaching
quanhoangd129
 
01. Ruby Introduction - Ruby Core Teaching
01. Ruby Introduction - Ruby Core Teaching01. Ruby Introduction - Ruby Core Teaching
01. Ruby Introduction - Ruby Core Teaching
quanhoangd129
 
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
andrehoraa
 
當測試開始左移
當測試開始左移當測試開始左移
當測試開始左移
Jersey (CHE-PING) Su
 
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
OnePlan Solutions
 
Empowering Businesses with Intelligent Software Solutions - Grawlix
Empowering Businesses with Intelligent Software Solutions - GrawlixEmpowering Businesses with Intelligent Software Solutions - Grawlix
Empowering Businesses with Intelligent Software Solutions - Grawlix
Aarisha Shaikh
 
06. Ruby Array & Hash - Ruby Core Teaching
06. Ruby Array & Hash - Ruby Core Teaching06. Ruby Array & Hash - Ruby Core Teaching
06. Ruby Array & Hash - Ruby Core Teaching
quanhoangd129
 

Recently uploaded (20)

Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Servic...
 
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
 
03. Ruby Variables & Regex - Ruby Core Teaching
03. Ruby Variables & Regex - Ruby Core Teaching03. Ruby Variables & Regex - Ruby Core Teaching
03. Ruby Variables & Regex - Ruby Core Teaching
 
How to Secure Your Kubernetes Software Supply Chain at Scale
How to Secure Your Kubernetes Software Supply Chain at ScaleHow to Secure Your Kubernetes Software Supply Chain at Scale
How to Secure Your Kubernetes Software Supply Chain at Scale
 
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdfAI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
 
SAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple SoftwareSAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple Software
 
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
Private Girls Call Navi Mumbai 🛵🚡9820252231 💃 Choose Best And Top Girl Servic...
 
How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024
 
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
 
TEQnation 2024: Sustainable Software: May the Green Code Be with You
TEQnation 2024: Sustainable Software: May the Green Code Be with YouTEQnation 2024: Sustainable Software: May the Green Code Be with You
TEQnation 2024: Sustainable Software: May the Green Code Be with You
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
 
Amadeus Travel API, Amadeus Booking API, Amadeus GDS
Amadeus Travel API, Amadeus Booking API, Amadeus GDSAmadeus Travel API, Amadeus Booking API, Amadeus GDS
Amadeus Travel API, Amadeus Booking API, Amadeus GDS
 
Authentication Review-June -2024 AP & TS.pptx
Authentication Review-June -2024 AP & TS.pptxAuthentication Review-June -2024 AP & TS.pptx
Authentication Review-June -2024 AP & TS.pptx
 
04. Ruby Operators Slides - Ruby Core Teaching
04. Ruby Operators Slides - Ruby Core Teaching04. Ruby Operators Slides - Ruby Core Teaching
04. Ruby Operators Slides - Ruby Core Teaching
 
01. Ruby Introduction - Ruby Core Teaching
01. Ruby Introduction - Ruby Core Teaching01. Ruby Introduction - Ruby Core Teaching
01. Ruby Introduction - Ruby Core Teaching
 
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
PathSpotter: Exploring Tested Paths to Discover Missing Tests (FSE 2024)
 
當測試開始左移
當測試開始左移當測試開始左移
當測試開始左移
 
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
 
Empowering Businesses with Intelligent Software Solutions - Grawlix
Empowering Businesses with Intelligent Software Solutions - GrawlixEmpowering Businesses with Intelligent Software Solutions - Grawlix
Empowering Businesses with Intelligent Software Solutions - Grawlix
 
06. Ruby Array & Hash - Ruby Core Teaching
06. Ruby Array & Hash - Ruby Core Teaching06. Ruby Array & Hash - Ruby Core Teaching
06. Ruby Array & Hash - Ruby Core Teaching
 

Creating Stable Assignments

  • 1. Creating Stable Assignments Jose Ortega/SIS A paradigm for creating efficient, aesthetic self-referential code The First Rule of Optimization: Don’t do it. The Second Rule of Optimization (For experts only): Don’t do it yet. —Michael Jackson⁄ When defining a copy assignment operator for a class, the problem of self assignment is often considered trivial or irrelevant, or is simply not considered. However, there are good reasons to consider what might happen if an ob-ject is assigned to itself, and there is also documented wisdom in this area. The standard form to handle self assignment was cap-tured by Coplien as part of his Orthodox Canonical Class Form (OCCF)¤: type &type::operator=(const type &rhs) { if(this != &rhs) { appropriate copying and release actions } return *this; } Kevlin Henney This is the basic schema you should seek to follow for all your assignment operators. A revisit to the Orthodox Canonical Class Form calls into doubt its general applicability for reasons of efficiency,‹ but before dealing with that issue specifically it is im-portant to establish what is meant by Orthodox Canonical Class Form and what we hope to achieve with it. ORTHODOX CANONICAL CLASS FORM orthodox adj. conforming with established standards, as in reli-gion, behavior, or attitudes.› canonical adj. (of an expression, etc.) expressed in a standard form.fi The OCCF is a recommendation, not a rule: Programming standards must be valid for both newcomers and ex-perts. This is oˇen diƒcult to accomplish. We have solved this problem by diÏerentiating our guidelines into rules and recom-mendations. Rules should almost never be broken by anyone, whereas recommendations are supposed to be followed most of the C++ Report ∫ http://www.sigs.com 25
  • 2. CREATING STABLE ASSIGNMENTS time, unless there is a good reason not to. This division allows ex-perts to break a recommendation, or sometimes even a rule, if they badly need to.fl It is not something to be followed slavishly, but has an important property: It works, it’s safe and, as an idiom, it clearly communi-cates its purpose to readers. You can have greater conˆdence in something that is written following this form than in something that has not been. Confidence and Intrinsic Quality Conˆdence is not something woolly that should be underestimated or ignored in the process of soˇware development; it is essential. In the past, I have been presented with code that looked like it grew on a spaghetti tree, If you can understand the code by its form, it will be easier for you to both have confidence in it and spot any mistakes. greeted it with a perplexed expression, and then been told chirpily by its author “not to worry; it works.”* Not. Not only should a piece of soˇware “work” (what this means is a whole topic in itself, but I’m sure you can come up with a num-ber of plausible consensus deˆnitions), but it should also look like it works. Commercial code is not written solely for the beneˆt of its author—although clearly the industry would empty out in the absence of any such gratiˆcation—and the idea that the only de-liverable is a piece of executable code at the end of a waterfall de-velopment process should be greeted with the derision (as well as project failure) it deserves. If you can understand the code by its form, it will be easier for you to both have conˆdence in it and spot any mistakes. If you cannot see that a piece of code is correct, how can you have conˆdence that it is correct? Executing it is not the answer: Dy-namic bug hunting and bashing is a poor substitute for code that is internally well structured. The concept we are identifying here is that of intrinsic quality.‡ Orthodoxy and Heresy There is a great deal of beneˆt in following a standard form for something that could otherwise give rise to obscure and unsafe behavior. One of the aims in programming is to be precise. If you are not being precise, you are being vague. If you are being vague, you don’t need the help of a programming language—beer is a far better medium for this. But as I said, this is a recommendation and not a doctrine or religious law. What if you feel an alternative solution is more ap-propriate? Will you be cast out from the gates of the C++ pro-gramming community and roasted over a code review? Should you just rebel outright, go oÏ and establish your own orthodoxy? Nothing so dramatic is necessary: A comment will do. Just show that not having an explicit self check was considered, but deemed unnecessary as the code presented is already safe. The important property of the canonical form is that it is based on some guarantees of behavior; a speciˆcation. Whatever code structure you settle on should satisfy this spec. To return to the idea of rules and recommendations, the OCCF is a recommen-dation, but the spec it is based on is a rule: Rule 5.12 Copy assignment operators should be protected from doing destructive actions if an object is assigned to itself.fl Any departure from the OCCF must satisfy the same set of re-quirements. In short, it must still work. EQUIVALENT FORMS The basic structure of the code oÏered by Glassborow can be summarized as: type &type::operator=(const type &rhs) { take a copy of rhs’s resources release existing resources bind copy to self return *this; } Placing copy before release is required because this control Òow ensures self assignment is not a problem. If &rhs is the same as this, we will waste a bit of time making a redundant copy of the cur-rent object, releasing current resources and then reassigning the copy. Perhaps the redundancy is not so aesthetically pleasing, but it is certainly safe and it will not be executed commonly enough to make it an issue. Perhaps the only thing missing is a comment (note: “comment,” not “essay”) stating that this code is safe for self assignment. The applicability of this is for dynamically allocated represen-tation— typically a single pointer to an object—that can be easily copied (based on the statically declared type) or cloned (based on the dynamic type—giving rise to the concept of type-shallow and type-deep copying). What we have is the idea of behavioral (or black box) equiva-lence. Given the basic requirements outlined, this structure is substitutable for the OCCF. Don’t Optimize So, in the name of overall eƒciency and correctness: no problems. Glassborow’s motivation, however, is questionable: [T]he cost of making the check for self assignment is some kind of comparison and branch statement. Branches are bad news on pipelined architecture. If we can write code with fewer branches we should do so.‹ This misplaced concern for code-level eƒciency is the kind of thing that has been shown time and again as subordinate to optimiza- * I am reminded of an occasion when I was working on-site and needed some new code from someone back at the office. I said that I didn’t expect it to be fully tested as he didn’t have the right environment in which to do this. I was a little perplexed when the code arrived and failed to compile. Upon closer inspection, I understood why: There were basic syntax errors all over the place, and the code could never have been compiled. This was confirmed when I rang him to discover that because I had not expected full testing, he had taken this to mean that he didn’t need to compile it either. In his vocab “compile” and “test” had somehow ended up as synonyms! Confidence was not high. 26 June 1998
  • 3. tion through eÏective data structure and algorithm use. Let’s take a look at some code: type &type::operator=(const type &rhs) { rep_type *new_body = new rep_type(*rhs.body); delete body; body = new_body; return *this; } No branches? Take a look at a pseudo-assembler output: push sizeof__rep_type call __op_new ; operator new move new_body, result compare new_body, null jmpifeq postctor push rhs + body push new_body call rep_type__ctorcp ; rep_type::rep_type postctor: compare this + body, null jmpifeq postdtor push this + body call rep_type__dtor ; rep_type::~rep_type postdtor: push this + body call __op_delete ; operator delete move this + body, new_body move result, this return ; return *this That’s right; there are two implicit conditional branches: ∫ A null return from a new should not have a constructor called on it˚; and ∫ a null pointer should not have a destructor called on it before being handed to delete. In truth, this is a case of two rather than three branches, as op-posed to zero or one. The diÏerence? Look at everywhere there is a call instruction. This means we are calling four other functions, two of which we know handle heap management. Against that backdrop, the extra couple of instructions from an explicit self check look even less clock threatening than normal: compare this, rhs jmpifeq wayout ; if(this != &rhs) … wayout: move result, this return ; return *this The level of optimization we have achieved is what the phrase “a drop in the ocean” was intended to describe—if we used the word “op-timize” anywhere near such code we would be deceiving ourselves. Don’t Optimize Yet The next claim to investigate is that of branches—speciˆcally conditional branches—on pipelined ar-chitectures. Eliminating them based on some hope for optimiza-tion is as rational as not walking under ladders based on superstition—there are times when it is unwise to do so, e.g., when someone’s already up the ladder with a can of paint, but that kind of judgment is not the same as superstition. So clearly we need to understand something about both conditional branching and pipelining before making a decision. Some uses of conditional branching are simply the result of poor basic programming skills: if(enabled) enabled = false; else enabled = true; The previous example illustrates the weak grasp the programmer has of logic. You don’t need to be a genius to write and comprehend: enabled = !enabled; I agree with the basic tenet that we should write fewer control structures. A well-abstracted system tends to encapsulate control ˚ A relatively late but minor change to the Draft ISO C++ Standard clarifies that any version of operator new that has a throw spec is assumed not to return null to indicate failure. The global new is specified to throw std::bad_alloc—therefore, this null check will not be required. However, it will take a little time for implemen-tors to catch up with this change. C++ Report ∫ http://www.sigs.com 27
  • 4. CREATING STABLE ASSIGNMENTS Òow within operations. Examples of this include polymorphism over explicit switch code, STL’s combination of iterators and it-erator algorithms, and the Enumeration Method pattern.° But many conditional branches are a fact of life: It is diƒcult to eliminate them if they are intrinsic to a problem description. How many branches are there in the following code? if(year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)) cout << “Leap!!!” << endl; Three. One for every condition: Remember, C++’s built-in con-ditional operators are short circuiting. An instruction pipeline contains instructions prefetched for ex-ecution. The many stages of an eÏective pipeline might include fetch instruction, decode instruction, calculate operands, fetch operands, execute instruction, and write operand result. Run-ning these in parallel rather than in sequence is a very eÏective processor optimization. The only glitch appears to be that a branch in the control Òow may invalidate the instructions in the pipeline: Although one branch is prefetched, what if the other is taken? It would be surprising and unfortunate if such an elegant ar-chitecture had not been fully thought out —“bad news” indeed— but luckily, the impact of branches is anything but devastating, and pipelined chips sell and perform very well. One solution is to use a multi-stream architecture, i.e., you can hold more than one branch at a time. Branch prediction and delayed branching are more cerebral in their approach. Perhaps the simplest approach used is that the instruction stream following the branch instruction is loaded, i.e., what would have happened in the pipeline anyway. How much of an impact does this last ap-proach have on the code we’ve examined so far? None whatsoever. If you look at how the code is arranged, it is the common case that im-mediately follows the branch, and the uncom-mon one that must be branched on. If you wanted a rule concerning branches that took this into account it would be a simple one: Place the commonly executed code nearest to the condition that tests for it. Interestingly, this is what many program-mers tend to do already, but for readability rea-sons: Given an if else, the if body should deal with the common case code, and the else body with the more exceptional occurrence. If they are equally valid, i.e., neither is exceptional, then the order is best determined by the most positive phrasing of the condition, i.e., the equivalent expression with the least contorted logic. It is oˇen said that cleanly structured code tends to be more eƒcient than code whose guiding philosophy has been one of successive application of folklore optimizations. This case seems to vindicate that. Relative Merits We have looked at behav-iorally equivalent forms, but there is a stronger equivalence that is hinted at in the recom-mendation given above where I mention “equivalent expression” for a condition. For built-in types (and—one would hope—user-de ˆned types) an example of strong logical equivalence would be that !(a == b) and a != b have the same meaning and are fully inter-changeable. Gimple 1/2 Island 28 June 1998
  • 5. Here’s an interesting question: How much time is spent de-bating the following code snippets: type &type::operator=(const type &rhs) { if(this != &rhs) { appropriate copying and release actions } return *this; } Or: type &type::operator=(const type &rhs) { if(this == &rhs) return *this; appropriate copying and release actions return *this; } Which is the better implementation? These are equivalent in the sense that they have identical meaning, and one can be trans-formed into the other by a good compiler. If you are wondering which way such a compiler would lean, look back at some of the points we have discussed. That’s right, the scruÏy multiple return version is less optimal than the version that uses the structured programming form.Δ However, few compilers do that well enough so you are leˇ with a separate set of concerns to balance. The common case is that the leˇ and right hand sides of an assignment are not the same, so if your interest is either pipeline eƒciency or layout, you would chose the ˆrst example. A direct translation of the second exam-ple into assembler tends to result in two jumps: compare this, rhs jmpifne postif ; if(this == &rhs) jmp wayout postif: … ; perform copying, etc. wayout: move result, this return ; return *this For C++ it is important that common function exit code is shared as this can involve destructor calls which, if space is your concern, you would not wish to have duplicated at every return point. If you ask to optimize the second example for speed you will prob-ably end up with duplicated code: compare this, rhs jmpifne postif ; if(this == &rhs) move result, this return ; return *this postif: … ; perform copying, etc. wayout: move result, this return ; return *this It is interesting that we can arrive at the same conclusion from two completely diÏerent approaches; it says something about the relationship between forms at diÏerent levels. I personally side with those whose concern is the structure of the written code— my reasons for this are based on the belief that soˇware devel-opment is an engineering profession, albeit an immature one. What if you feel an alternative solution is more appropriate? Will you be cast out from the gates of the C++ programming community and roasted over a code review? There are a few people who need to be concerned with the ma-chine level, but that ˆgure is a lot less than the number who con-cern themselves with it. STABLE INTERMEDIATE FORMS Returning to the proposed alter-native code structure for assignment: Although arrived at from a faulty line of logic, it is sound. For those interested in patterns, what we have here is a language level pattern (better known as an idiom) that has a well-deˆned context, i.e., C++ copy assignment operator for an object structured using the Handle/Body idiom¤¯· (more generally, the Bridge pattern⁄‚) where the body is easily copied (either shallow or deep with respect to its type). The pro-posed conˆguration is something that works, meeting all the re-quirements for an assignment operator. Exception Safety However, a pattern has three essential parts: con-text, forces, and conˆguration.⁄⁄ The conÒicting forces that are listed for this pattern are at fault, and hence it is not a pattern. But since the context is valid and the conˆguration seems to have some merit, can we say something more about it? Alan Griƒths, in his role as editor, commented on Glassborow’s solution: This has the added beneˆt of leaving the object in a consistent state if an exception is thrown during the clone operation. I’d rate this as more important than worrying about the diÏerent number of processor cycles required for each version.‹ My only caveat to this—as we have shown—is that exception safety is the only beneˆt to this approach—as an issue, processor cycles are not even on the radar. In addition to the usual forces describ-ing the requirements on a copy assignment operator, exception safety is the most important force resolved. Don’t underestimate how significant exceptions can be for invalidating assumptions— and therefore code.⁄⁄ Let us examine the problem solved: Δ It has been said that in the light of modern optimizing techniques based on data rather than control flow, Niklaus Wirth wishes he had not included any jump state-ments (a function return statement and a loop exit) in Oberon (MODULA 2’s suc-cessor) as the discontinuities introduced into the control flow are not only inelegant, but they thwart a number of optimizations. C++ Report ∫ http://www.sigs.com 29
  • 6. CREATING STABLE ASSIGNMENTS 1. release existing resources 2. take a copy of rhs’s resources 3. bind copy to self What if an exception is thrown during step two? The object re-mains in existence, but it now has a chaotic and unstable state: Its resources have been released, but it still refers to them. What will happen upon destruction of that object? That’s right, destruction of a completely diÏerent kind! Objects in an unstable state can-not be destroyed without spreading that instability to the rest of the program. However, there is no safe and consistent way to stop an object from reaching the end of its life. To put it mildly, this is a nontrivial issue. The solution is to ensure that at every intermediate step the ob-ject has a coherent state, i.e., not only is the result of every macro change stable, but each micro change from which it is composed is also stable. This principle of Stable Intermediate Forms under-lies successful soˇware development strategies⁄¤ as well as other disciplines of thought and movement, e.g., T’ai Chi. 1. take a copy of rhs’s resources 2. release existing resources 3. bind copy to self This sequence resolves the forces. It is also suƒciently general that it is possible to use this with the original OCCF—for instance, when writing a copy assignment for a class whose objects have a mixed style of representation. A Pattern In summary, the many concerns facing a developer branch into myriad forces that fall somewhere between “chal-lenging” and “daunting” in the soˇware engineer’s dictionary. Compared to other industries, soˇware development sports a high number of people who can juggle. In this light, it is perhaps easy to see why. Close inspection of the configuration reveals a sound solution to a different problem, and a documentable pattern. COPY BEFORE RELEASE Problem: ∫ Ensuring copy assignment in C++ is exception safe. Context: ∫ A class has been implemented as handle/body pair. ∫ The body is copyable—type shallow or deep as appropriate. Forces: ∫ Any of the steps taken in performing the assignment may fail, resulting in a thrown exception. Partial completion of the steps may leave the handle in an unstable state. ∫ The result of assignment, successful or otherwise, must result in a stable handle. ∫ Self assignment must also result in a stable handle. ∫ Aˇer successful completion of the assignment, the handle on the leˇ-hand side of the assignment must be behaviorally equivalent to the handle on the right-hand side. ∫ Assignment—successful or otherwise—must be nonlossy, i.e., no memory leaks. Solution: ∫ Perform the body copy before releasing the existing body. ∫ Bind the body copy to the handle aˇer releasing the existing body. Resulting Context: ∫ The existing body is not deleted before the body copy has been attempted. Therefore, a failed body copy will not result in an unstable handle. ∫ Failed body release may still result in an unstable handle. How-ever, throwing exceptions from destructors is a practice com-monly cautioned against. ∫ The ordering accommodates safe self assignment at the cost of redundant copy. ∫ If the body copy preserves behavior equivalence, a successful as-signment will preserve it for the composite handle/body object. ∫ The solution can be used in conjunction with the schema for copy assignment from the Orthodox Canonical Class Form. The issue of a failed deletion is an interesting one, although not often one worth solving.⁄‹ However, it is possible in this pattern with a minor tweak to the ordering. The solution is left, as they say, as an excercise for the reader. ˘ References 1. Bentley, J. More Programming Pearls, Addison–Wesley, Reading, MA, 1988. 2. Coplien, J. Advanced C++ Programming Styles and Idioms, Addison–Wesley, Reading, MA, 1992. 3. Glassborow, F. “The Problem of Self Assignment,” Overload 19, Association of C and C++ Users, UK, Apr./May 1997. 4. The Collins Concise Dictionary, Collins, UK, 1988. 5. Borowski, E. J. and J. M. Borwein. Dictionary of Mathematics, Collins, UK, 1989. 6. Henricson, M. and E. Nyquist. Industrial Strength C++: Rules and Recommendations, Prentice Hall, Upper Saddle River, NJ, 1997. 7. Hatton, L. Safer C, McGraw–Hill, New York, NY, 1994. 8. Beck, K. Smalltalk Best Practice Patterns, Prentice Hall, Upper Saddle River, NJ, 1997. 9. Coplien, J. Software Patterns, SIGS Books, New York, NY, 1996. 10. Gamma, E. et al. Design Patterns: Elements of Reusable Object- Oriented Software, Addison–Wesley, Reading, MA, 1995. 11. Alexander, C. The Timeless Way of Building, Oxford University Press, UK, 1979. 12. Booch, G. Object-Oriented Analysis and Design with Applications, Benjamin/Cummings, Menlo Park, CA, 1994. 13. Sutter, H. “More Exception-Safe Generic Containers,” C++ Report, 9(10):24–31, Nov./Dec. 1997. Kevlin Henney is a Senior Technologist with QA Training in the UK. He can be contacted at kevlin@acm.org. 30 June 1998