Notes to self

Whatever I feel like writing

Subscribe to RSS feed

Posts tagged with "design"

Video links

, , ,

Four Kinds of Tests for Basic Correctness

, ,

This is from J. B. Rainsbergers talk Integrations Tests Are a Scam, which by the way is a great talk that is very worth watching.

Rainsberger defines three kinds of tests:
  1. Collaboration tests
  2. Contract tests
  3. State-based tests

I would like to add a fourth kind to that list, called the Concurrency tests.

Let me try to explain what each of those are about, in turn.

Collaboration tests: I talk to a bunch of other guys and, assuming they work correctly, am I working correctly? In essence, we are testing the correct behaviors of the individual units in our system, under the assumption that all other units work correctly in accord with their contract.

Contract tests: someone uses this thing in a certain way and expects a certain behavior from that, do you live up to that contract? In essence, we are testing that the units use each other correctly. In other words, that we have gotten the links between the collaborators right.

For example, if we have ThisThing that expects ThatThing to return an empty list under certain conditions, then we would mock the world as such in our collaboration tests but we will make sure that this assumption holds, in our contract test. In other words, we must have a test that sets up ThatThing in those certain conditions and verifies that it really does return and empty list, and not something else, like null or a list with something in it.

State-based tests: doing someAction to someThing must produce thisObservableEffect. These are the good old super simple tests for pure functions, or very simple state mutations, or side-effects to the outer world.

Concurrency tests: like state-based tests, except the observable effect is some specific behavior of the unit under concurrent use.

Concurrency tests makes sense to separate from state-based tests because a) things that deal with concurrency should deal with nothing else, and b) testing for specific concurrent behaviors is typically harder and more complex than single-threaded state-based tests and if they are not then you are doing something horribly wrong with your state-based tests.

If you do these tests, and design your system this way with all these things ind mind, then, Rainsberger postulates, you will only need integration tests as a debugging tool for figuring out which contract or collaboration tests are either missing or wrong. And once that issue has been fixed, you will have a focused object test that covers the same exact case as the integration test did and so you remove the latter to get rid of the duplication.

I must say that that sounds like a very nice place to be.

Responsive Design

,

I just read Kent Becks article in the third issue of PragPup Magazine called Responsive Design.

His points ring very true with me and I am looking forward to seeing his results become a book at some point.

The fundamental thesis is that software design is not created through a rational process. Rather, the design emerges, guided by the programmer, as a response to the problem at hand.

Our illusion of control over software design is a dangerous conceit best abandoned.



To think that we are controlling the design of our software is a lie. It is this lie that leads us to believe that we can create big detailed class diagrams before the first line of code is written, and believe that they resemble anything but a fantasy.

There is a very simple way to illustrate why these upfront designs don't work. See, design exists to solve problems. The solution exists because the design does. The design causes the solution to be - brings it into being, but not only it. With a design comes also flaws and imperfections. A design contains decisions, some of which are good, some may be bad and some are compromises. A design causes not only solutions, but also new problems.

These problems may be bug or they may be limitations of sorts, but if we want them solved we will need a design. As this cycle continues, it becomes increasingly difficult to predict and describe problems and design with any level of accuracy. And as fate would have it, we really only have two levels of accuracy: accurate, or not. Even the tiniest assumption can have vast consequences for a design - only with runnable code can we really know what the truth is.

Design is not a rational process.



Design grows in response to problems. Responsive Design. But the design is not chaotic. Consider a plant: it is not design - no one can say before the seed is planted, how, exactly, it is going to look. It will grow in what way it finds most meaningful in an effort to solve the problem of survival. But its growth is not chaotic. It has definite lines, purpose and structure. It has parts that are connected in purposeful and meaningful ways.

In short: there is meaning and intent behind the growth of a plant. Likewise, there is meaning and intent behind the growth of a software design. Kents Responsive Design Project is about uncovering and coming to grips with that meaning.

Form Follows Function

, ,

If form follows function then why do we do up-front design when we develop software?

My work place has, for some time now, repeatedly asked me for estimates and designs, and this has gotten me to think about how I feel about those artifacts. In this blog post I am going to try and put my feelings about up-front design into words.

Design is the detailed description of how something is suppose to be built, but software development is plagued by uncertainty to such a degree that any design conceived before the first line of code has been written, is bound to be wrong.

Design is a model and a description of a destination. A place we want to end up. A model and a description of what we want to end up with.

When one embarks on a new software development project, I would argue that such a destination is not a terribly valuable artifact to have. Kent Beck uses the metaphor of driving to describe software development; constantly adjusting the direction as we go, making sure that we don't fall off the road.

Kent Beck is spot on, in my opinion. We don't need a destination when we start a project. What we need is a starting point and a direction. And the people that need those things are the team members, not management. The team members all needs to be on the same page with regards to the starting point and the direction. This is even more so important with a distributed team, which is what I currently have at hand at work.

When the starting point and the direction is all agreed upon, then the destination, the design, will emerge as we go along, and become self evident when we at some point decide to stop. This is the "emergent design" idea from extreme programming.

But before I get ahead of myself here, I have already described how design is the destination in this metaphor, so what are the starting and the direction? Briefly, the starting point is the most pressing and important unimplemented user story. The direction is knowledge of the business problem and a vague conceptual idea of how a system might solve this. I suppose part of what the direction is, is described in the current set of unimplemented user stories, but the direction as a whole is more than just user stories. The direction is sense that all team members are "on the same page," so to speak.

So when I title this blog post as "Form Follows Function," what I really mean is that "Design Follows Implementation" and that this idea is emergent design. When we write code, we are also implicitly designing, and this design that emerges from our code is the real design, so to speak. It is the truth, as oppose to some up-front class diagram describing classes that don't exist and incorporating engineering trade-offs to problems that also don't exist (unless they are designed into the system).

The up-front design describes either something that we don't want, or something that we won't get, or both. And therefor, I think that working to the level of detail that is implied by it, is wasted effort. And I don't like wasted effort.