In a hotel in Beijing. I wonder what the words say? "Please press the buttons gently" perhaps?
Hi. I'm Jon Jagger, director of software at Kosli.
I built cyber-dojo, the place teams practice programming.
is the title of another excellent book (isbn 1857885198) by Geoff Colvin. As usual I'm going to quote from a few pages:
Deliberate practice is not what most of us do when we think we're practising.
Most organizations are terrible at applying the principles of great performance. Many companies seem arranged almost perfectly to prevent people from taking advantage of these principles for themselves.
nothing, it turned out, enabled any group to reach any given grade without putting in those hours. ... There is absolutely no evidence of a 'fast track' for high achievers.
memory ability is very clearly created rather than innate.
General Electric CEO Jeff Immelt has been clear about what the company is looking for: someone who is externally focused, is a clear thinker, has imagination, is an inclusive leader, and is a confident expert.
The roadblocks we face seem to be mostly imaginary.
Jerry Rice was the greatest because he worked harder in practice and in the off-season that anyone else; he spent very little time playing football; he designed his practice to work on his specific needs; he did much of the work on his own; it wasn't fun; he defied the conventional limits of age.
Practice is so hard that doing a lot of it requires people to arrange their lives in particular ways.
The advantage of practice was cumulative.
Deliberate practice requires that one identify certain sharply defined elements of performance that need to be improved, and then work intently on them.
Practicing without feedback is like bowling through a curtain that hangs down to knee level. You can work on technique all you like, but if you can't see the effects, two things will happen: You won't get any better, and you'll stop caring.
Feedback? At most companies this is a travesty, consisting of an annual performance review dreaded by the person delivering it and the one receiving it. Even if it's well done, it cannot be effective. Telling someone what he did well or poorly on a task he completed eleven months ago is just not helpful.
Practice is designed, so it can be designed well or badly.
Great performers never allows themselves to reach the automatic, arrested-development stage in their chosen fields. The essence of practice, which is constantly trying to do the things one cannot do comfortably, makes automatic behavior impossible.
In fact what they [great performers] have achieved is the ability to avoid doing it automatically.
is the title of an excellent book by Michael Abrashoff (isbn 0446529117).
As usual I'm going to quote from a few pages:
A recent Gallup study found that when people leave their companies, 65 percent of them are actually leaving their managers.
What I suddenly realized was that I had the power to do this all along. I just never had the self-confidence.
Something happened as a result of those interviews. I came to respect my crew enormously.
Secrecy spawns isolation, not success.
No matter how fantastic your message is, if no one is receiving it, you aren't communicating.
You earn trust only by giving it.
More often than not, bureaucracies create rules and then forget why they were needed in the first place, or fail to see that the reasons for them no longer exist.
Once leadership opportunities are squandered, you can never get them back.
If a rule doesn't make sense, break it.
If a rule does make sense, break it carefully.
I felt as small as a man could. I had just had my core values calibrated by someone half my age.
One-size-fits-all programs tend to fit none.
Leadership is mostly the art of doing simple things very well.
Open yourself. Coldness congeals. Warmth heals.
The goal shouldn't be to reduce the standards for some, but to raise everyone else to the highest possible level.
Train for unity.
If you don't intend to act, then don't bother to ask if it is going on. It will only make matters worse.
I kept walking around the ship, questioning the crew, drawing them out.
Having fun with your friends creates infinitely more social glue for any organization than stock options and bonuses will ever provide.
Thanks to Tobias Fors for tweeting the following onto my radar.
Reading up on how learning works, I came across a couple of quotes on the subject. I particularly like the one about the vaccination approach to knowing - it exposes our fantasy that all it takes is to “send people back to school”, and then everything will be fine.
The learners become their own subjects and no longer objects to be filled with packages of knowledge in the manner of what Neil Postman and Charles Weingartner call the vaccination approach to knowing - “where education is something you take and, when you have taken it, you’ve had it, and if you’ve had it you are immune and need not take it again.”
When you tell me stupid things, like you do I just have to, have to, have to, change the rules
In a rush, never trust ... if I'd only stop and take my time ... with you I'm running somewhere I can't get to
Ellie's bike had a puncture today. I used some tyre-levers to prise the tyre off its wheel rim. Then I carefully pulled the inner tube out and was puzzled to see a large section had folded over on top of itself! How did that happen? A hurried previous repair? I attached a pump to the valve and pumped some air into the inner tube. Then I filled a bowl of water and plunged the inner tube into the water, shifting it along section by section. Suddenly a tell-tale stream of air bubbles revealed the source of an invisible hole in the inner tube. Right in the middle of an existing patch. More evidence of a hurried previous repair. I was struck by a few thoughts
is the title of another excellent book by Dan Pink.
As usual I'm going to quote from a few pages:
The first ten years of this century [have been] a period of truly staggering underachievement in business, technology, and social progress.
Rewards, by their very nature, narrow our focus.
By offering a reward, a principal signals to the agent that the task is undesirable.
Mediocrity is expensive.
Consider the very notion of "empowerment". It presumes that the organization has the power and benevolently ladles some of it into the waiting bowls of grateful employees.
Management isn't the solution, it's the problem.
Effort is one of the things that gives meaning to life. Effort means you care about something, that something is important to you and you are willing to work for it. [Carol Dweck].
Being a professional is doing the things you love to do, on the days you don't feel like doing them. [Julius Erving]
In the end, mastery attracts precisely because mastery eludes.
How people spend their money may be at least as important as how much they earn [for well-being].
is the title of an excellent book by Kenneth and William Hopper. As usual I'm going to quote from a few pages:
For a century and a half, historians have been asking themselves the chicken-and-egg question: which came first: Puritanism or Capitalism?
A system is a set of connected things or parts, bound together to a purpose.
No enemy is more terrible than money, and no friend is more trustworthy.
At the heart of the system lies mutual trust.
Given's approach was avowedly descriptive rather than prescriptive.
In spite of appearances, good decision-making is essentially the same in all walks of life.
A belief that life was not merely best understood, but also best experienced, as a struggle.
You do not own a dog and bark.
Statistics are a wonderful servant and an appalling master.
The Cult of the (so-called) Expert would severely damage the great tradition of 'generalist', 'hands-on' management.
No greater damage could be done to our economy or to our society than to attempt to 'professionalize' management by 'licensing' managers, for example, or by limiting access to management to people with a special academic degree [Peter Drucker, 1954].
I absolutely loathe the idea of professional management [Jeff Immelt, 2004].
is the title of an excellent book by Dan Pink. As usual I'm going to quote from a few pages:
At the Yale School of Medicine, students are honing their powers of observation at the Yale Center for British Art, because students who study paintings excel at noticing subtle details about a patient's condition.
The MFA is becoming the new MBA.
Stories are how we remember.
One of the best ways to understand and develop the aptitude of Symphony is to learn how to draw.
The most creative among us see relationships the rest of us never notice.
Everything you create is a representation of something else.
Poets are our original systems thinkers.
More males than females have brains that systematize and more females than males have brains that empathize.
The people who will thrive will be those who can toggle between the two. As we've seen again and again, the Conceptual Age requires androgynous minds.
If you are laughing you cannot think. That is the objective we achieve in meditation.
People have enough to live, but nothing to live for; they have the means but no meaning.
is the title of an excellent book by Robert Coram.
As usual I'm going to quote from a few pages:
He was determined to excel athough he did not yet know in what area. He only knew that he had to do something better than anyone had ever done it before.
Boyd is the only known Hun driver to work in the dangerous low-speed end of the airplane's envelope. And that was how he solved the adverse yaw problem.
They might have lost three or four pounds during the strenuous high-G maneuvers. They were thirsty and longed for a cold beer. But first they had to catch a ride on the truck that served as the flight-line taxi. They headed back to ops for the debrief, the most important part of the mission.
...more usable energy always goes into a system than comes out, because there is unavailable energy called entropy.
Tactically, the ability to quickly slow down is as important as the ability to quickly speed up.
Boyd despised optimization.
The Air Force launched a Zero Defects Campaign, and the base commander at Eglin wanted every person on base to sign a pledge saying he would make no mistakes during the coming year. Most organizations at Eglin already flew a flag saying the office was 100% FOR ZERO DEFECTS. But Boyd knew, as did almost everyone who signed the pledge, that he and everyone else would make mistakes. He thought Zero Defects was a stupid idea and refused to sign. A group of lieutenants working for Christie not only followed his lead but raised a flag that proudly proclaimed there were 100% AGAINST ZERO-DEFECTS.
Study after study shows that the higher the rank a military officer ascends, the less likely he is to make change.
You gotta challenge all assumptions. If you don't, what is doctrine on day one becomes dogma forever after.
Anything new and different is feared by a bureaucracy.
He did not become fixated on technology or "one-point" numerical solutions.
Boyd worked daily to remove things.
A twenty-pound maintenance ladder does not simply add twenty pounds to the aircraft.
Again and again they practiced.
In life there is often a roll call. That's when you will have to make a decision. To be [someone] or to do [something]? Which way will you go?
The lightweight fighter had such an extraordinary thrust-to-weight ratio and could recover energy so quickly that energy dumping became a tactic of choice rather than of desperation.
Boyd liked ambiguity.
One cannot determine the character or nature of a system within itself.
He must operate inside his adversary's time-scale.
People, ideas, hardware - in that order.
"You synchronize watches," Boyd shouted, "not people."
expected = 42; actual = expression(); assert_equals(expected, actual);you could write something like this...
ARE_EQUAL(int)
{
...
expected = 42;
actual = 40+1
}
Admittedly this was not much of an improvement, if at all. However, on a flight to Oslo a few days ago I suddenly realized a way to improve it. The idea is to fold an expected == actual assertion down to this:
expected(42) == actual(40+1);Where expected and actual can be two function templates that return objects wrapping their arguments. These objects can have an overloaded == operator that does the assertion for me. Instead of emphasizing the assertion I emphasize the roles instead. Here's some proof of concept code:
#include <cassert>
#include <iostream>
template<typename T>
struct asserted_role
{
asserted_role(const char * name, const T * ptr)
: name(name)
, ptr(ptr)
{
}
const char * name;
const T * ptr;
};
template<typename T>
void failed_assertion(const asserted_role<T> & lhs,
const char * op,
const asserted_role<T> & rhs)
{
std::cout << "FAILED ASSERTION" ...
<< " " << lhs.name << "(" << *lhs.ptr << ") "
<< op
<< " " << rhs.name << "(" << *rhs.ptr << ")"
<< endl;
}
template<typename T>
void operator==(const asserted_role<T> & lhs,
const asserted_role<T> & rhs)
{
if (*lhs.ptr == *rhs.ptr)
;
else
failed_assertion(lhs, "==", rhs);
}
template<typename T>
asserted_role<T> expected(const T & t)
{
return asserted_role<T>("expected", &t);
}
template<typename T>
asserted_role<T> actual(const T & t)
{
return asserted_role<T>("actual", &t);
}
int main()
{
expected(42) == actual(40+1);
}
There are a couple of things I like about this idea. The first is I no longer have to remember to get the expected and actual in the right order; if I want to I can write:
actual(40+1) == expected(42);The second is that the idea can be extended. For example, I can create similar function templates called lesser and greater and add a < operator:
lesser(42) < greater(40+1);I can create a new template function of any name I like to express the role I'm thinking of. For example, suppose I want to test that the value of one expression is equal to the value of another expression, but neither value is "expected" or "actual" they are just two values and I don't care what the values actually are, other than the two values are equal. I can create two function templates called lhs and rhs:
lhs(2 + 2) == rhs(4);
Do you want the truth or something beautiful?
Just close your eyes and make believe
Do you want the truth or something beautiful?
I am happy to deceive you
is the title of an excellent book by Tom DeMarco, Peter Hruschka, Tim Lister, Steve McMenamin, James Robertson and Suzanne Robertson.
As usual I'm going to quote from a few pages:
On most development projects, time is a scarcer resource than money.
Film critics believe they can be successful even if the project they are on is a failure.
Perfection is not expected; delivery is.
Whenever people get together and break rank and responsibility, the organization gets a little healthier.
Organizational lines exists for control and decision-making. They don't usually exist to accelerate work throughput.
Reality is king.
An abundance of information creates a paucity of attention.
Suppressing bad news can turn solvable problems into unsolvable problems.
The result of this misdirected civility is deep mediocrity.
Whenever you hear "I don't know," you hear a declaration of trust.
Coaches work one step at a time rather than creating a whirl-wind of change.
Patience is one of the most important qualities of a coach.
We find the hardest part of listening is resisting the temptation to jump in too early with advice or to switch the conversation to a similar story that happened to you.
People usually speak much slower than you can think, which is why it is so hard to give your full attention when someone else is talking.
You have to do more than suggest a course of action for people to follow it. You need to lead the way by explaining why it's important and then show them how to get started with it.
Your focus is process improvement, not individual performance.
Each change they adopt reduces their resistance to the next change.
Take care not to ask questions when you actually want to give guidance.
When people start caring only about their own tasks, teamwork starts to break down.
Useful information should be visible to all and not hidden away in computers. Plans kept electronically are information fridges; they give up their information only when they are opened.
is the title of an excellent book by Jerry Weinberg. As usual I'm going to quote from a few pages:
Software development is not primarily a manufacturing operation for we (ideally) never develop the same software twice. This uniqueness of product means that Deming's "statistical signal" - though necessary - is not sufficient for feedback control, because there often isn't enough repetition - enough stability - to generate meaningful statistics.
In software we are attempting to obtain value by achieving higher precision than human beings have ever attempted before.
The switch from cost observation to value observation is the strongest indication that an organization has made the transition from Pattern 2 (Routine) to Pattern 3 (Steering).
Under emotional pressure, people literally stop thinking.
A fact becomes a feeling as soon as you observe it.
The triad has special significance for observation, because it is the first grouping in which there is both interaction and observation of interaction.
The way I remember the difference between faults and failures is to think of earthquakes. Faults (in the ground) leads to failures (in bridges, buildings, and so forth).
One of the most sensitive measures of the cultural pattern of any organization is how quickly it finds and removes problems.
Any plan is just a plan - a series of guesses about how the future will work out.
Bureaucracy: people doing things whose purpose they don't understand.
is the title of an excellent book by Richard Bach. It's well worth rereading every year or so. As usual I'm going to quote from a few pages:
...to eat, to stay alive as long as we possibly can.
Jonathan Seagull discovered that boredom and fear and anger are the reasons that a gull's life is so short, and with these gone from his thought, he lived a long life indeed.
We choose our next world through what we learn in this one.
Heaven is not a place, and it is not a time. Heaven is being perfect.
You have less fear of learning than any gull I've seen in ten thousand years.
"Why is it", Jonathan puzzled, "that the hardest thing in the world is to convince a bird that he is free, and that he can prove it for himself if he'd just spend a little time practising? Why should that be so hard?
You don't love hatred and evil, of course. You have to practise and see the real gull, the good in every one of them, and to help them see it in themselves.
Don't believe what your eyes are telling you. All they show is limitation. Look with your understanding, to find out what you already know, and you'll see the way to fly.
// wibble.h
#include "grommet.h"
#include "flange.h"
typedef struct
{
grommet g;
flange f;
} wibble;
void wopen(wibble * w, int i);
...
void wclose(wibble * w);
The definition of wibble exposes the types involved in its
representation (grommet and flange in this made up example), and hence
requires a #include for those types in its header file. This exposure
has a price. One cost is that any change to the grommet or flange
header files, or any header files they in turn #include, at any depth,
will require a recompilation of any source file that #includes wibble.h
(either directly or transitively). Another cost is that client code can
easily become reliant on the exposed representation rather than relying
solely on the functional api. Note that in C++ you can avoid this
problem by declaring your data members private.
// wibble.h typedef struct wibble wibble; wibble * wopen(int); ... void wclose(wibble *);
#include "wibble.h"
void eg(void)
{
wibble * ptr; // ok
wibble value; // constraint violation
ptr = malloc(sizeof *ptr); // constraint violation
}
The wibble type's representation is defined in its source file and
so only code
in the source file can create wibble objects. Furthermore, these wibble
objects have to be returned to users as pointers. These two constraints
mean the created objects cannot have auto storage class. This is a
great loss since auto storage class alone of the three storage class
options allows the clients to decide where the objects live which can
greatly improve locality of reference.
// wibble.c
...
wibble * wopen(int value)
{
wibble opened;
...
return &opened; // very very bad
}
...
A second possibility is to create the objects with static storage class:
// wibble.c
...
static wibble wstorage[42];
static size_t windex = 0;
...
wibble * wopen(int value)
{
wibble * opened = &wstorage[windex];
windex++;
...
return opened;
}
...
The final possibility is to create the objects with allocated storage class. That is,
to create the objects dynamically on the heap:
// wibble.c
...
wibble * wopen(int value)
{
wibble * opened = malloc(sizeof *opened);
...
return opened;
}
...
The static and the allocated approaches have opposing advantages and disadvantages.
Static storage is very fast and doesn't fragment the memory but the type has to decide
the maximum number of objects the application will need. That might be a dependency going in the wrong direction.
Allocated storage is much slower and can create memory fragmentation issues, but
the application decides how many objects it needs.
In short, the classic ADT technique creates an abstraction that is
very opaque and pays a hefty price for this "over-abstraction".
Abstracting away the representation also abstracts away the size
details of a type and it is the loss of the size information that
creates the storage class restrictions.
The Shadow Data Type implementation technique attempts to rebalance
these forces of abstraction by separating size abstraction from representation abstraction.
// wibble.h
typedef struct
{
unsigned char size_shadow[16];
} wibble;
void wopen(wibble *, int);
...
void wclose(wibble *);
The "true" definition of the type (together with its accompanying #includes) moves into the source file:
// wibble.c
#include "wibble.h"
#include "grommet.h"
#include "flange.h"
#include <string.h>
typedef struct
{
grommet g;
flange f;
} wibble_rep;
// sizeof(wibble) >= sizeof(wibble_rep)
void wopen(wibble * w, int value)
{
wibble_rep rep;
...
...
memcpy(w, &rep, sizeof rep);
}
...
However, there are two problems needing attention.
// alignment.h
typedef union
{
// one of each of all the basic types go here
// including data pointers and function pointers
} alignment;
We redefine wibble to be a union with two members; one member to take care of the
memory footprint and one member to take care of the alignment:
// wibble.h
#include "alignment.h"
typedef union
{
unsigned char size_shadow[16];
alignment universal;
} wibble;
...
The main problem with wibble being a union is that unions are rare.
Suppose you want to forward declare the wibble type in a header. You're
quite likely to forget it's a union.
typedef struct wibble wibble; // OooopsWe can fix this by simply putting the union inside a struct!
// wibble.h
#include "alignment.h"
typedef struct
{
union
{
unsigned char size[16];
alignment universal;
} shadow;
} wibble;
...
This is now sufficiently tricky to warrant an abstraction of its own:
// shadow_type.h
#ifndef SHADOW_TYPE_INCLUDED
#define SHADOW_TYPE_INCLUDED
#include "alignment.h"
#define SHADOW_TYPE(name, size) \
typedef struct \
{ \
union \
{ \
unsigned char bytes[size]; \
alignment universal; \
} shadow; \
} name
#endif
// wibble.h #include "shadow_type.h" SHADOW_TYPE(wibble, 16);
// sizeof(wibble) >= sizeof(wibble_rep)This comment, like all comments, has no teeth. Ideally we'd like an assurance that if the types' sizes lose synchronization we're told about it. This can be done by asserting the relationship inside a unit test of course. The problem with this the possibility that the runtime check inside a unit-test won't get run. Or, more likely, that the unit-test simply won't get written at all. Fortunately in this case we can check the relationship using a compile time assertion. We start with the fact that you cannot declare an array of negative size:
extern char wont_compile[-1]; extern char will_compile[+1];Now we have to select a size of either +1 or -1 if the asserted expression is true or false respectively.
// may or may not compile extern char compile_time_assert[sizeof(wibble) >= sizeof(wibble_rep) ? +1 : -1];Hiding this mechanism behind a macro inside a dedicated header helps to make the code more Intention Revealing.
// compile_time_assert.h #define COMPILE_TIME_ASSERT(description, expression) \ extern char description[ (expression) ? 1 : -1 ]
// wibble.c ... #include "compile_time_assert.h" ... COMPILE_TIME_ASSERT(sizeof_wibble_is_not_less_than_sizeof_wibble_rep, sizeof(wibble) >= sizeof(wibble_rep)); ...It's worth spending a few moments to think about alignment carefully. The wibble type contains a union to give us the strictest alignment. This means a single wibble_rep and a single wibble can overlay each other in either direction. If we create an array of wibbles the compiler will ensure the address of each wibble is suitably aligned. To do this it may add trailing padding to the wibble type but this padding will be reflected by sizeof(wibble). Similarly, any padding for the wibble_rep type will also be reflected by sizeof(wibble_rep). Importantly, since sizeof(wibble_rep) may be strictly less than sizeof(wibble) we cannot overlay an array of either type directly onto an array of the other type. However, we are only concerned with creating an array of wibbles since that is the type the client uses. There should never be any need to create an array of wibble_reps. Nevertheless, the .c file implementation must always do any array pointer arithmetic in terms of wibbles and never in terms of wibble_reps. Note also that using >= rather than == also allows binary compatibility with any alternative smaller representation.
// wibble.c
static inline void shadow(wibble * dst, wibble_rep * src)
{
memcpy(dst, src, sizeof *src);
}
bool wopen(wibble * w, const char * name)
{
wibble_rep rep =
{
.g = ...,
.f = ...,
};
shadow(w, &rep);
...
}
Careful use of memcpy can help to make the wibble functions behave atomically from the users perspective. That is to say, the function can do the work off to the side in a local wibble_rep, and copy
back into the shadow only if everything is successful.
An alternative to memcpy is to cast the pointer on each access:
// wibble.c
static inline wibble_rep * light(wibble * w)
{
return (wibble_rep *)w;
}
void wclose(wibble * w)
{
wibble_rep * rep = light(w);
rep->g = ...;
rep->f = ...;
...
}
void pointless(void)
{
const wibble w; // :-(
// ... ?
}
However, this is not an issue since the wibble type is opaque anyway.
Nevertheless, a slight redesign can accommodate const wibble
objects if desired, at the cost of copying struct objects:
...
wibble wopen(int value)
{
wibble_rep rep = { ...value... };
wibble w;
memcpy(&w, &rep, sizeof rep);
return w;
}
void ok(void)
{
const wibble w = wopen(42);
...
}
is the title of an excellent book by Jerry Weinberg. As usual I'm going to quote from a few pages:
Information is neutral but people's reactions to information are rarely neutral.
I'm not in the proof business; I'm in the evidence and inference business.
A process description is just that, a description ... not of what has actually been done.
To qualify as a test, an action has to seek information that will influence an action.
Fixing under pressure tends to raise the fault-feedback-ratio.
Anyone who makes promises about the future must be some sort of devil.
Errors are made, not born.
In a moment of weakness it is difficult to resist infantile suggestions.
Good tools amplify effectiveness; if your effectiveness is negative, adding tools will amplify only the negativity.
enum suit { clubs, hearts, diamonds, spades };
you could write it like this:
struct suit
{
enum { clubs, hearts, diamonds, spades } value;
};
The struct wrapper adds a modicum of type safety. It also allows you to forward declare suit (you can't forward declare enums). The enumerators (clubs, hearts, diamonds, clubs) are still visible and can be used when a compile time value is required (e.g., switch cases). As usual, caveat emptor.
is the title of an excellent book by Fred Brooks. It's well worth rereading every year or so.
As usual I'm going to quote from a few pages:
The accumulation of simultaneous and interacting factors brings slower and slower motion.
Human beings are not accustomed to being perfect and few areas of human activity demand it.
Our estimating techniques fallaciously confuse effort with progress.
No part of the schedule are so thoroughly affected by sequential constraints as component debugging and system test.
Take no small slips... Trim the task.
I will contend that conceptual integrity is the most important consideration in system design.
...the total creative effort involves three distinct phases: architecture, implementation, and realization. It turns out that these can in fact be begun in parallel and proceed simultaneously.
Any software system should be grown by incremental improvement... Nothing in the past decade has so radically changed my own practice, or its effectiveness.
Unless we teach people how to design, the languages matter very little.
The Mythical Man Month is only incidentally about software but primarily about how people in teams make things.
is the title of an excellent book by Jerry Weinberg.
As usual I'm going to quote from a few pages:
Underlying organic models is the fundamental idea of systems thinking: "It is impossible to change just one thing at a time."
Leaders are leaders of change in themselves.
People don't become leaders because they never fail. They become leaders because of the way they react to failure.
If you are a leader, people are your work.
There is no conflict between people and task.
Doing something new heightens awareness, which is stimulating, but also a little uncomfortable.
If you intend to grow you cannot avoid some pain.
Very few of the classic leadership studies have been done in environments even vaguely resembling the technical work situation.
The only way we can see ourselves is through other people. This inability to see ourselves as others see us is the number one obstacle to self-improvement.
Becoming a leader means shifting the focus from your ideas to the ideas of others.
Systems Thinkers presents a biographical history of the field of systems thinking, by examining the life and work of thirty of its major thinkers.
# excluder.rb
include = Regexp.new('(\s*)#(\s*)include(.*)')
STDIN.readlines.each do |line|
if include.match(line)
line = "#if 0\n" + line + "#endif\n"
end
STDOUT.write line
end
This small Ruby program reads in a source file and writes out the same source file, except the #includes are commented out. Each line like this:
#include <stdio.h>is replaced like this:
#if 0 #include <stdio.h> #endifThis enables you to create an "isolated" version of a source file. One where all the dependencies arising from the #includes, to any depth, are slashed in one swift cut. One where your tests clearly and visibly have to recreate all those dependencies in a custom mock environment.
typedef struct wibble wibble; void f(wibble * ptr);but this does not:
typedef struct wibble wibble; void f(wibble array[]);A bit of searching in the Standard reveals
6.7.5.3 Function declarators
paragraph 12 - If the function declarator is not part of a definition of that function, parameters may have incomplete types...
6.7.5.2 Array declarators
paragraph 1 - the element type shall not be an incomplete type
6.2.5 Types
paragraph 22 - An array of unknown size is an incomplete type.
In the shower a few days ago I realized that showering vs bathing is a nice example of being lean-agile or not. Imagine 10 people bathing sequentially vs showering sequentially...
is the title of an excellent book by Dee Hock. As usual I'm going to quote from a few pages:
All things, even life itself, are a seamless blending of chaos and order.
By structure I mean the embodiment of purpose, principles, people, and concept.
The results of the best organizations are apparent, but the structure, leadership, and process and transparent.
Information multiplies by transfer and is not depleted by use.
Knowledge becomes understanding when related to other knowledge in a manner useful in conceiving, anticipating, evaluating, and judging. Understanding becomes wisdom when informed by purpose, ethics, principles, memory of the past, and projection into the future.
All knowledge is an approximation.
The information age is primarily an extension of mental power.
We are at that very point in time when a four-hundred-year-old age is rattling in its deathbed and another is struggling to be born.
is the title of an excellent book by Ken Robinson. As usual I'm going to quote from a few pages:
People are not creative in general but in doing something concrete.
Spontaneity sometimes has to be carefully planned.
Creativity is not just a matter of letting go: it involves hanging on.
Creativity is as much a process of finding problems as solving them.
Trying to put some experiences into words is like stringing clothes on a washing line when in practice they are worn one inside the other.
Creativity is a process not an event.
We classify at our peril.
Creativity is incremental.
Creativity relies on the flow of ideas.
In one of his books Jerry Weinberg mentions a cleaner who wasn’t allowed to wipe the whiteboards. The story conjures familiar images of whiteboards full of stuff labeled “important - do not rub off”. It’s likely the stuff has lain untouched on that no-longer-white-whiteboard for weeks or months. It’s no longer important but there it stays, filling the whiteboard. A whiteboard full of stuff discourages its use in exactly the same way an empty whiteboard encourages it. And a whiteboard with the words “important - do not rub off” positively discourages use. It's really saying "keep away".
Good systems tend to oppose their own proper function.
Bad systems tend not to oppose their own proper function.
is the title of an excellent book by Dan Ariely. As usual I'm going to quote from a few pages:
We don't have an internal value meter...rather we focus on the relative advantage of one thing over another
Our first decisions resonate over a long sequence of decisions.
With everything you do you should train yourself to question your repeated behaviour.
Humans are intrinsically afraid of loss.
For market norms to emerge it is sufficient to mention money.
Money, it turns out, is very often the most expensive way to motivate people.
We fall in love with what we already have.
Expectations can influence nearly every aspect of our lives.
The majority of people cheated, and they cheated just a little bit.
What a difference there is in cheating for money versus cheating for something that is a step away from cash!
The fundamental difference between code and data is that programmers care about code whereas users care about data.