piątek, 19 grudnia 2014

The pitfall of teaching C++

Preface

Many years ago I read a book from Prentice-Hall about object oriented programming. I don't remember exactly when that was - either shortly before starting studies at university or at the very start of the first year there. I read about methods and messages and I analyzed diagrams on which object A was said to be passing a message to object B by the means of calling one of B's methods.

Objects then seemed to me like active, almost living entities able to communicate through this mechanism of message passing (calling each other methods). I was disillusioned to learn later that this was not true. Objects didn't have concurrent lives and the so called message passing turned out to be ordinary, synchronous function call.

(The book contained examples in C++ and Smalltalk; I ignored Smalltalk examples while reading it; I realize now that my first impression of how objects communicate through message passing was, to great extent, true for Smalltalk).

That was the first bad thing I learned about C++.

Now after I've used several different languages based on different paradigms, I learned another bad thing about C++ (and so far that's the latest one): it is still being taught at universities and sometimes it is even the first or the only language being taught (I'm thinking here of studies in general, not necessarily computer science studies).

Is it the right choice to teach this particular language? Especially, if it is chosen just for an introduction to programming and, for some, the only language they will ever program in? In next short paragraphs I will try to persuade you that the answer is: no, it is not the right choice.

Lots of learning related to the language itself, not to programming in general

How constructors are called? In what sequence, when there is inheritance? Why do we have virtual destrutor and how it differs from regular destructor? When a class is abstract and when do we need one? What happens when some of the methods are virtual while some others are not? What results from weird combinations of access modifiers and/or mutliple inheritance?

The knowledge needed to answer all of these questions (and many others) does not allow anybody to actually write a useful piece of code. I agree this knowledge (or at least part of it) is needed to write a decent C++ program, I'm just saying it is not essential to write it, in the sense that there are other pieces of C++ knowledge that are essential, like flow control, and must be learned too in order to write anything useful. In languages like C or Python one only needs to learn the essential things to start programming, there is no or very little things related to the language itself that are necessary to write decent programs.

It takes away all joy

A student tasked with a problem to be solved by implementing an algorithm enjoys the task when he or she can jump instantly to doing a series of experiments, code one part, integrate it with another and run with different input data to test that it finally works.

With C++ it's difficult to do that: there is plenty of things one must care about, like memory management, that one must focus on, apart from focusing on the problem itself. This phenomenon is very clearly visible and can be experienced when one tries to solve a simple algorithmic problem in C++ and then Python or Lisp.

It creates false belief of what programming is about

For those who study something else than computer science using C++ for an introductory course creates an impression that a programmer must take care of a great number of small, complicated, yet very important things to achieve even an easy task (e.g. implement a queue in C++). Consequently, It makes it difficult to imagine that programmers are capable of creating much more advanced applications, web services and graphical interfaces. How do they do it, if even my simple queue implementation had several surprising deficiencies?

It is enough to read this fantastic article by Peter Norvig: http://norvig.com/spell-correct.html
to see that such an amazing thing as a spelling corrector can be written concisely and can be accessible and easy to comprehend to anyone who wishes to learn how it works. It wouldn't be as accessible (and would actually scare off many people), it were implemented in C++, or even in C, in this particular case.

Closing comments

Most of the criticism I expressed against teaching C++ is directed to doing a C++ course on studies other than computer science. It may be a valid course on CS studies, although I know that Carnegie Mellon University removed object oriented programming from CS introductory curriculum.

Many things that I listed could be said about teaching JAVA as the only language on non-CS studies, but JAVA is definitely less complicated both in terms of possible semantics (e.g. no multiple inheritance), has garbage collection and set of tools and libraries is immensly rich and easy to use.

C++ has lost its position that it had in late 90's. For all reasons listed above, I don't think it deserves to be taught such widely as it is today. I believe much more truth about programming can be conveyed with languages such as Python or even "old good" C.

sobota, 6 grudnia 2014

Common NonSense

I am very upset when common sense is mentioned during discussions about Scrum and generally about software development. It is usually used in sentences like: "yes, we use Scrum, but we are not erthodox about it, we just use common sense".

Why would I be so angry about it? Isn't it good that people actually use common sense to make decisions? After all, Scrum is also said to be "based on common sense".

This is the question to everyone who claims that the use of common sense is a virtue: what brought you to where you are now? Wasn't that common sense?

  • Wasn't that common sense that told you to separate programmers from testers?
  • Wasn't that common sense that told you to separate analysts or architects from development team?
  • Wasn't that common sense that helped you invent "iteration zero" in which you are excused for not delivering anything useful?
  • Wasn't that common sense that helped you invent "hardening sprint" in which you execute all the tests you did not care about over the course of the project?
  • I also suspect you used common sense to determine that TDD makes projects too expensive and should be abandoned
  • It was probably common sense that whispered to your ear when you named numerous roles in your team, for every member of the team to feel special
  • And wasn't it nice when common sense provided you with so simple solution to the problem of an iteration falling into the holiday season? And you just made it one week longer...

Even if somebody else used common sense and made decisions quite opposite to those above, it was your common sense that told you to make these mistaken decisions. And therefore, don't trust your common sense. Talk to people who are wiser and more experienced. Search for options on the web. Learn what solutions people implemented in the industry. But don't trust your common sense.

This post wouldn't be here, if it were not for Michal Rosolowski, whose views on common sense blew my mind. There is a video available with Michal's lightening talk on this subject:

http://vimeo.com/album/1977617/video/44244699

piątek, 31 października 2014

Michael Feathers' visit

In May this year I had the pleasure of hosting Michael Feathers at Motorola Solutions in Krakow. We invited Michael to do a kind of extension, in the form of workshop and a lecture, to his great and well-known book "Working Effectively with Legacy Code".



Michael's skills are very rare as not only is he skilled in teaching the methods of dealing with legacy code, but he also feels comfortable with doing so in C++, in addition to Java and C#, which both are more pervasive among XP professionals.

It was a great experience and I think many of us will remember some of the ideas we learnt during this visit.

piątek, 24 października 2014

Agile in metaphores: angle of repose

This is my latest idea for a nice exercise that could be used during an Agile / Scrum or XP training for a development team. You are welcome to copy this idea and use it in your training, especially if you give me the credits :-)

Introduction:
Every loose material has a property known as the angle of repose. It is the angle that is naturally formed when a material is loosely spilled out, for example to be stored:

The task:
Give the development team an amount of loose substance such as salt of sugar and ask them to produce a measurement of the angle of repose of that substance. Then leave the room. Give them a protractor and leave the room.

Conclusions after the task is executed:
When you are back in the room, the engineers will have hopefully measured the angle in the experiment of spilling out the substance and measuring the angle more or less accurately. Explain to them that although a theoretical computation of the angle is possible, it would be extremely complex, compared to simply doing the experiment they have just done.

Then, this metaphore could be extended to cover topics like:
  • empiricism as the method for solving (complex) problems (even if this particular is just complicated)
  • TDD - experimenting with the production code to see when it passes a test, rather than trying to mentally execute it
  • developing a story based on unclear or incomplete knowledge of scope, in order to get feedback, rather than struggling to understand and "lock" all of the story first

czwartek, 16 października 2014

Career advice: where do you want to be (and in what order)?

In one of Capers Jones' books (I think this was "Estimating software size") I came across a categorization of software projects that looked interesting to me. It put kinds of software projects in relation with the ability to perform the same tasks without a computer. Although I'm not able to cite it, it was something like this:
  • all tasks can be performed without a software system; computers are used only to make it easier or faster
    • bookkeeping in a small company could be an example 
  • tasks can theoretically be performed without a software system, but they would require so much time and involve so much risk of human error, that it would be extremely impractical or close to impossible to perform them without using computers
    • finding items in an extremely large collection (e.g. a huge library) could be an example
    • some banking operations could be even better example
  • tasks cannot be performed by a human by their very nature; there must be a software system in place in order to perform them
    • controlling an embedded device or processing physical phenomena are examples of this
One could ask oneself which category would be good one to work on projects in. Probably the brightest and most ambitious would aim at the third category or, if they are not able to get there, at least the middle one.

But we can look at the domains and the categorization from a different angle. Some projects require deep domain knowledge that takes years of hard work to build, others have rather simple, self-explanatory domain, known from everyday life to everybody. Would it sound logical that people working on this latter category tend to focus more on programming skills (languages, patterns, XP practices), whereas those working in a complex domain focus more on the domain itself and as long as the system works, they do not aim to become world class clean coders? It definitely sounds logical to me. It may simply be explained by the amount of effort and energy that is needed to understand the domain, so that no time is left to focus on programming skills. Or there may be other reasons. Regardless of that, one can expect that the simpler the domain is, the more chances of bettering the programming skills will be available.

We can join these two views to say that a programmer is likely to advance their programming skills working on a project that is supposed to help users in something that is generally doable without a computer. Conversly, those working on a system that can do things of which human is incapable, will not be capable to extend their programming skills much.

Where do you want to be and in what order?

sobota, 11 października 2014

You need to know: tail end recursion

A few years ago I did a small quasi-prepared-Kata exercise to demonstrate differences between programming in (and thinking in) different programming languages. I chose a simple state machine as an example and implemented it in Common Lisp, Java and C.

Having programmed in each of these languages at some point in my life, I deliberatly used approach typical for each of the languages. I even exaggerated a little to emphasize the characteristics of languages and how they influence our thinking. For example, I used a little more than needed classes and objects in Java and avoided recursion, whereas in Common Lisp, the state machine was transitioning from one state to another by a recursive tail call.

One of the observers questioned the Lisp implementation saying that it would quickly result in stack overflow. Although I intuitively felt that was not true, I was not able to explain why. Right after that session, I searched for information about recursion in functional languages and I learned about tail end recursion. A nice summary is given here: http://en.wikipedia.org/wiki/Tail_call

I recommend reading this Wikipedia entry, it explains really well things that are often not known by programmers focused on imperative languages.

czwartek, 9 października 2014

Beware of theoretical problems

Anybody who was a change agent or acted as one knows this too well. You meet a development team of 15+ engineers and do an introductory talk on Scrum. Even before you are one third through the talk, there is a question or an interruption from the audience - similar to one of the following examples:
  • this is all very interesting, but how it [Scrum] would deal with a situation when half of the team quits their job on one day?
  • this may work in an experienced team, but imagine that you have a team where there is just one experienced developer and all others are fresh graduates
  • I don't understand why you are against my idea of recording the stand-up meetings; sometimes the amount of input from the team may be too large for the Scrum Master to remember
If you hear that (and it could be on any meeting you talk about change, not necessarily about Scrum), don't engage into discussion.They are all extremely theoretical questions that will NEVER happen in real life. What's more, whatever process / approach / tool is used today, it is most likely unable to resolve these theoretical problems either. As a change agent, you just have to hear it out, but don't begin discussing it.

wtorek, 23 września 2014

The (unpleasant) truth about concurrency

As Robert C. Martin writes in his wonderful book "Clean code", concurrency is hard. Concurrency is indeed so hard that most software developers do not know how to deal with it properly. Please don't feel offended. I myself thought I was quite good in writing concurrent programs at my first job, around the year 2000. But now I recognize I was rather lame about it back then and I'm only very very slightly better in understanding it. Honestly, the part I am really somwhat better at is the understanding of how many of concurrency aspects I still don't understand.

If you believe I am talking nonsense, let me just ask a simple question: have you  every read and understood this fundamental work about concurrent systems by C.A.R. Hoare? I think most programmers have never read it.

Is it so bad and should we all go back to a classroom and study CSP deeply? Not necessarily. I believe that most programmers (here I think of programming as a profession) do not really need profound understanding of concurrency. Unless we do some serious systems or concurrent embedded programming, this skill is really not terribly necessary, because we very often use a frameworks, application servers and such that have standard concurrency mechanisms already built in and the whole trick is to just use it. For many regular development tasks, it is really not necessary to know all odds and ends of concurrency. A proof of this is, in my opinion, simply the proliferation of CPython and Ruby MRI: these implementations use GIL and they do not offer real concurrency, even if someone who uses threads there imagines something different. And yet they are highly popular, successful and useful.

For the remaining 10% of programmers, who really have to have deep understanding of concurrency: they already know that it takes10+ years to develop profound understanding in this area.

środa, 25 czerwca 2014

Code Kata: Crazy letter delivery

Imagine you live in a crazy town inhabited entirely by mathematicians. Each day a postman delivers some letters to the citizens. There are no street names in town, just house numbers. Because the traditional delivery seemed boring to the mathematicians, they invented a kind of game and talked the postman into playing it: the postman changes the original numer of house on a letter to an alternate number (read below how) and delivers the letter to the alternate house. The mathematician that lives in that house knows both the alternate and original house number from the postman. He indulges in the task of converting the original number to the alternate and only when he knows the proper conversion does he deliver the letter to the proper receiver. Example:

Original house number: 139.
Alternate house number: 126

Conversion: 139 - (1 + 3 + 9) = 126; original number minus the sum of its digits.

Another example:

Original house number: 222
Alternate house number: 8

Conversion: 2 * 2 * 2 = 8; digits of original number multiplied.

The task is to write a piece of code that helps to find the conversion, based on the original number, the alternate number and a set of rules. You can choose the rules as you like and extend them gradually. You can start with + and - operations on the original number and its digits. You can take multiplication into account, as in the second example. You can choose to apply division. You can restrict the rules to always use all of the digits or extend them to use any combination of the digits, with or without repetitions. The program may give an exact answer, or simply answer "conversion unknown", in some cases.


czwartek, 15 maja 2014

Agile in metaphores: cars cleaning

Last Saturday I decided to clean our cars, both mine and my wife's. They really needed cleaning. A few days before I bought a nice, industry-grade vacuum cleaner, better suited for this job than the one we use at home. Basic set of tasks that I have to work through to clean a car is this:

  • vacuum the car
  • take out foot pads and clean them with water and a detergent
  • clean the inner sides of windows
  • clean the cockpit with a special detergent so that it looks glossy
The weather on that day was not bad, though pretty windy and when I was about half way through the job, it looked like it was going to rain.

What is the best way to complete as much cleaning as possible, if there is the risk of rain? Should I vacuum both cars first, because I already have the vacuum cleaner running? But would anybody consider a car that has been vacuumed, but still has lots of dust on the cockpit clean? I wouldn't and, what's more, my wife certainly wouldn't either. What is the best way then, again, to achieve the most value during the job of cleaning the cars when it might start raining any minute? Clean the cars one by one, complete all the tasks for one of them and then start another. Then, even if it starts raining when I work on the second car, I will have at least one car completely clean. Even more value could be achieved, if I chose the right car as first to be cleaned and I think you already know which I would choose to gain the most value...

The same thing is with implementing Agile and working within Scrum framework. This actually also shows that Scrum and Kanban are not that far from each other as we sometimes think. In an iteration, it is always best to keep WIP (Work In Progress) strictly limited. It does not make sense for 6 developers to start working on 6 user stories at the beginning of an iteration and finish their work at the end. Ideally, they would all work on one user story at a time, completing one after another. In practice, there will often be some overlap and the team will work on two, sometimes maybe three user stories concurrently, but they must not work on many at once and those that are in-progress at the same time should not be at the same stage (i.e. second user story will often be started when first is nearing completion).

This is what I often advise the teams I work with. Don't start all your user stories at once. Start one, maybe two or three at most. I prefer going to a sprint review at which I learn that 2 of 6 user stories have not been started, than to one where I learn that 3 of 6 user stories are half-done.

niedziela, 27 kwietnia 2014

An opinion on code review

Code review is often seen as a way to enhance code quality. My personal views on code review are quite different. I will try to summarize them in a short list. You are welcome to disagree.

  • code review frees the author from the responsibility for the code; "I don't have to care so much, since others are looking at it as well"
  • code review fits very very poorly into Scrum framework; it delays the completion of tasks and backlog items and produces an inclination in teams to aggregate the reviews into a several-days-long "phase" placed at the end of an iteration (making it effectively a wateration)
  • code reviews are much easier as a process to learn than TDD or SOLID, so developers do them gladly and receive in exchange a feeling of accomplishment (unfortunately):
    • "I give my code to others to review, because I care for code quality"
    • "I review the code of others, because they value me as a knowledgeable person"
  • code reviews drag the feedback to the very last moment, instead of asking for feedback early and continuously
Your code can be better without code reviews.

środa, 5 lutego 2014

Code Kata: toy fleet management

Background: there is an infinite grid with one point selected as a fleet management centre. There is a number (> 1) of cars that move through the grid, one step at a time, only in up, down, left and right directions. The cars periodically send their position on the grid to the management centre.

The task: we are to write a program that accepts coordinates sent by the cars and then can tell us the current total distance travelled by a car.

Points to consider: we assume that the coordinates are send periodically, regardless of the car's movement. Thus, a car may send various series of coordinates that our program must be able to interpret. Tip: the calculated total distance will be an approximation, not an exact value.

Additional functions (to be done as a next step, do not bring it outright into the design): if a car travels away from the management centre farther than N units, the program will signal that fact. Just use any method you wish to signal this, but remember that it should not be annoying, in case a driver took a long trip on the countryside.