Rambles around computer science

Diverting trains of thought, wasting precious time

Tue, 26 May 2020

Mission and marketing in computer science degrees

At lunch with colleagues some months ago (remember those days?), I provocatively suggested that our course offering would be improved if we eliminated marketing terms from the names and specifications of our taught programmes and modules. Depending on exactly what counts as a marketing term, this might mean doing away with “cybersecurity”, “Internet of things”, “cloud computing”, “big data” (thankfully not currently used here at Kent) and ideally also “artificial intelligence” (once respectable, but no longer). To replace them, there are perfectly good time-honoured and serious phrases for the same areas of study: “computer security”, “distributed computing”, “embedded software development”, “statistical inference” and even “machine learning” (usually what “AI” means nowadays, and while faintly marketing-y, still more descriptive of that).

Although my suggestion was rather tongue-in-cheek, there is an important issue lurking not far behind it. Serious study on any technical topic, even in primarily “applied” areas like CS, is very different from product development. It's not about “learning the latest technologies”. An academic degree should not be a “workplace simulation” or an apprenticeship; it's about developing skills that are more underlying, more general and more timeless. We need to give students the message that university study is about bulding those skills. We need to give ourselves, as academics, the same message. If we don't, and instead fool ourselves that our responsibility is something about “teaching what will help the students get a job” then as an institution we're not fulfilling the very function of a research university, and as individual academics we're undermining the long-term justification for our own jobs.

The paradox is that here at the School of Computing, even our own industrial panel is reported to emphasise, consistently, that they want us to teach principles rather than specific technologies. Certainly our degrees do contain a decent amount of principled content, even if there is room for debate on what fraction of our students come away really understanding those principles. Despite that, currently I'd say we don't give the “timeless skills” message to our students very much. But we do give out the “get a job” message all the time. We do this by endorsing marketing-speak in what we offer, but also by other messages we send far more subtly, pervasively and latently, in what we teach and how we teach it. We award good marks to relatively insubstantial final-year projects whose core is to implement CRUD functionality mimicking commercial web sites or apps, provided they show due allegiance to the hallowed engineering methods we teach. We teach “software engineering” by attempting to rote-instil good practice, but backed by relatively little critical or analytical content, and taught at a stage where we are inevitably asking the students to take this wisdom on trust. (That is undergoing overhaul for next year, but it's unclear whether the new version will change this. If not, I will be partly to blame, as a co-author of the module specification.) We abolished as superfluous a module on “people and computing”, when at least its title captures what ought to be the single biggest topic in the whole discipline. We teach very little that conveys the historical, cultural or political aspects of technology. We continue to downgrade our “unpopular” theoretical content below even a basic minimum level (and I'm no theory zealot). And we let our pedagogy be compromised by the unwisdom of student “feedback”, such as, in response to claims that a module was not “up-to-date”, de-emphasising principles in favour of technologies—a move which ultimately leaves students uninformed and confused, since it necessarily blurs the distinction between what is essential and what is accident.

Of course, in all this we are pushed along by external pressures. One message that circulates loud and clear among colleagues, at staff meetings and elsewhere, is that the market matters: bums on seats are our financial bottom line. This follows through: we find ourselves specifying new modules according to our perceptions of marketability. Let me say that again: we're guided not by actual marketability, but our perceptions about marketability. Maybe my colleagues are more informed than I am, but I don't think many would disagree that we have limited basis for these perceptions. We allow our fuzzy mental caricatures of “the job market”, “industry”, “applicants” and hence “what will sell” to determine what and how we teach.

These fuzzy beliefs are why, for example, I have to respond periodically to the question of “why teach systems, when hardly any of then will get a job writing operating systems?”. Meanwhile, teaching “AI” left, right and centre is not questioned at all. If we really believed in “principles” and degree skills as “long-term” we would be more interested in breadth and balance. Instead we have collectively imbibed the message “AI is big; AI is the future” and regurgitated it into our curriculum development. I've nothing against the longstanding field of artificial intelligence, and I fully expect us to teach from it. But this eagerness to exploit its current trendiness is a symptom of something far more toxic than pragmatic compromise. Putting trend-chasing at the heart of our endeavour, not just on the surface of our marketing materials, undermines the social purpose of a research-intensive university—supposedly an institution for the long-term.

The prevailing line is that this is a financial necessity. That might even be the case. But to me, as a relative newcomer, that seems to be an assumption rather than an established fact. Nominally, the selection of our curriculum still rests with us, the academics, as it should. But the current pressure to be “market-driven” reduces us to headless chickens: base reflexes fill in for a lack of informed thought. Having absorbed a belief that an unapologetically “long-term” degree course is “unmarketable”, we knee-jerkingly propose to do what we perceive to be marketable. Where's the basis for believing any of this?

In my more optimistic moments I believe that for the good of everyone—our students, our academics, and our fortunes as a credible research university—there are things we can and should do to change this. Although I'm not a marketing expert, it seems that what I propose is not about ignoring “the market”, but rather about more seriously “doing marketing”, as distinct from mere publicity. One message we could plausibly try to get across is something like the following. Yes, we will teach you all about hot topics like AI, cybersecurity or whatever else the current trends favour. But that's not all we'll do, and we're offering an education that will last. What we give you is substantial, durable and transferrable.

Trying harder for an approach that emphasises the transferrable over the short-term vocational would be a huge challenge. It is the exact opposite of following the line of least resistance. It would take creativity, skill and effort. Still, it's what we academics mostly believe to be the right thing. I've no reason to believe these efforts would not be forthcoming. What is really stopping us?

The real problem seems to be risk. Proposing any change in this direction brings worried-sounding replies. Trying such a revamp would be a risk—how else would we discover what is marketable than by trying something different? If our intake takes a hit as a result of such an experiment (which would necessarily take several years to run), our political and financial position within the university would suffer. This is why having a university sector that is market-driven and financially straitened is so toxic. Doing the very job your institution was set up for has been turned into a radical feat of “innovation” whose risk is too great to take on. The very purpose of the institution has been redefined as impossible.

Nevertheless, I believe we can do more than we are doing. More cleanly separating our taught programmes' specifications (what we set for ourselves) from their marketing pitches (for applicants) might be one small, simple but possibly significant measure. It would help us make a mental distinction between our mission and our marketing strategy. One way to re-spin that mission might be explicitly to contrast the flawed presumption of “preparing students for industry”; with a more forward-thinking “preparing students to prepare a better industry”. This matters especially in our field because much of the software industry is, regrettably, built on froth and fads. If we want the software industry to be better, we need to turn out students who know how to look for the substance underneath the froth; who have a questioning mindset; who aspire to be more than just hired guns (to borrow the words of Christopher Alexander). That's a tall order, and perhaps many of our students aren't especially inclined to ask these questions... but if universities don't make it clear that substance exists beneath the froth, what hope do we have?

We also need to remember that boom easily turns to bust. “Computer science” is currently attractive to students because software is perceived as a boom industry. In this sense, courting the market seems to work in our favour. But again, this is happening because our applicants think “job” when they should think “career”. We do nothing to correct this. “Cybersecurity? Artificial intelligence? Internet of things? Walk this way.” Our university is collapsing financially and compulsory redundancies are on the horizon in some subjects. But at the School of Computing, complacency rules because “we're doing well” and “this doesn't affect us [much, directly]”. Maybe not—this time. But one only has to go back to around 2008–09 we there was last a threat of compulsory redundancies among computer science academics here at the University of Kent. Something called a “credit crunch” was happening around then. Only a few years years previously there had been something called the “dot-com bubble” which burst in 2000–01, seeing many institutions' CS applications take a sudden dip, one which did not recover for about ten years.

These market lurches did nothing to diminish the importance of what we teach. Yet somehow they had a keen effect on the capacity of our institutions to support that teaching. That is a sign of the unquestionably appalling stewardship of our institutions in recent times, and sadly, in the ten years since, the grip of marketisation has only got stronger. But we cannot entirely blame external factors for our choice to emphasise froth, nor can we rely on what for us are “favourable market conditions” remaining so—and this ties back to the same problem. When an industry is based on froth, spooked investors are all it takes to bring the finances crashing down. The same goes for a computer science department and spooked applicants. What goes around comes around. If we believe that what we teach does not suddenly become irrelevant the moment “the market” takes its next lurch, we owe it not just to ourselves, or our colleagues, but to society at large, to doubt the wisdom of “the market” in deciding what passes for an education. Can't we at least try to make our case, rather than chasing what we think the consumers think they want?

[/teaching] permanent link contact

Tue, 09 Jan 2018

Undergraduate admissions in “computer science”: a plea

Dear Bogdan,

Thank you for this update on our undergraduate admissions testing, and very well done on what must have been a mammoth effort. Seeing the CSAT happening at the CL, I could see it did succeed in creating a friendly environment, and I was impressed by the organisation effort which had clearly been necessary to put on such a smooth operation over a fairly long period.

However, let me also sound a note of alarm.

Reading the CSAT web pages, it is (still) not even mentioned that the test is about mathematics. Rather, it is left implicit—as if it didn't even occur that it might be necessary to mention or justify this. The Frequently Asked Questions page repeatedly use phrases like “at A-level”, “at school” without even seeing fit to mention that school mathematics is what you're talking about. Your starting assumption has apparently been that mathematics skills are 100% of what we are looking for.

I believe this is completely wrong, and it really worries me that you are apparently not thinking about it at all. Computing needs a diversity of skills and viewpoints. It is a horrible mistake to assume that it is simply a question of mathematics. I've personally known many computer scientists whose interest in (natural) languages, philosophy, history, biology and other sciences has been far stronger than their interest in mathematics. Meanwhile, “systems thinking” is a large part of many areas of computer science and requires analytical skills in human domains as well as mathematical ones. Why can't we admit people based on their excellence in those areas?

I am also incredibly worried about the withdrawal of the 50% option, which will further narrow the horizons of our students. As we admit a larger cohort of students, we should be acquiring the necessary support staff to scale up our offering's diversity. We should not be perversely restricting it on the grounds that this is the only way to cope without any extra staff. Our admissions and intake are booming; we should be coming out with a better offering than ever. You might counter that few students have chosen it the 50% option this year, but that only points again to the narrowness of our selection criteria. (I realise that this decision was not yours, but am raising it because I'm sure you have more oversight of this than I do.)

Cambridge will not suffer directly from these mistakes, because we will always admit smart individuals and turn them out even smarter. But our discipline will suffer, in practice and in research. Consequently, society will suffer. I need hardly remind you of the huge power that technologists have acquired in recent years, and the cluelessness with which many wield it. This is one of the huge social problems of our time, and Universities are far from blameless in it. Technology shapes our society. Study of the historical, human, psychological, biological and other topics all provide necessary and complementary viewpoints. It is a recipe for disaster to make computer science a discipline of mathematical thinking alone.

I hope (albeit without optimism) that this will make some sense to you. I should mention that I have also posted this e-mail on my blog. Yours in desperation,


[/teaching] permanent link contact

Mon, 14 Mar 2011

Writing a Part II dissertation

Not that long after I did Part II of the Tripos in Cambridge, I wrote a piece about how to do a successful Part II project, based on bitter experience of having done a less-than-completely successful one. Now it's a few years later, and I've supervised four Part II dissertations and proof-read a couple more (and now left Cambridge!). I thought I'd write down some hints about what makes a good dissertation. As before, the pink book is well-meaning but misses a lot of this.

I should also add that this advice is not prescriptive---it's a mixture of my personal preferences as a reader of dissertations, and a conservative underapproximation of “known ways to write a good dissertation” according to my experience. Not being part of the examination process myself, I can't say it's the only way, nor that it's sufficient, nor even that it's always correct---only that these recommendations seem to have some correlation with good marks.


This chapter is for you to identify the problem space of the work, and what specifically your work seeks to achieve in that space. You should outline the technical background of the work here, but only at a high level---save details for next section. The emphasis should be on context: motivating use-cases, and covering a selection of differing alternative approaches to the problem. Once you've covered that, you can give a specific taster of the one you adopted---probably in the form of a simplified summary, perhaps a preview-style example or two (of the work you did and its supported use-cases) and an outline of the rest of the dissertation.


This chapter should consist mostly of technical background, at a level deeper than the introduction. Think of it as mirroring the preparatory reading (and perhaps experimentation) you had to do before beginning the project work proper. You should describe the specification of the system you built, outline its overall design, and mention any changes to proposal. It's particularly worth emphasising anything hard that you had to learn in order to undertake the project---such as unfamiliar tools, languages, libraries, programming styles, algorithms, bits of mathematics, and so on.

For pitching your work, my rule of thumb is to assume your reader knows basic computer science (say, an outline understanding of the first two years' Tripos content) but is a bit slow to catch on. In other words, try to make the reasoning in your write-up extremely clear and easy to follow. This is not because the examiners are slow to catch on. Rather, it's because they are probably in a hurry, and in order to counterbalance the fact that you're almost certain to underestimate the difficulty of understanding your own write-up.

Avoid assuming that the reader knows any particular language, tool or detailed technique that you use. For example, if your work is based on implementing some particular programming language, you can assume the reader has basic degree-level knowledge about programming languages in general, but you should use this chapter to give an outline introduction to this specific language and its peculiarities, with references to additional material.

This chapter is somewhat infamous for requiring that you write some “boring” stuff about development practices: what tools you used, your testing strategy, how you took backups, what development practices you followed, and so on. I say “infamous” because we researchers, when we are proof-reading dissertations, find this all a bit incongruous---most of a dissertation reads a bit like a research write-up, whereas this stuff doesn't. Since we're not accustomed to seeing this kind of thing written down, it thuds a bit. However, it's the researcher's perspective that's at fault here. Most dissertation authors are about to go off into industry, and from the perspective of professional software development, including this small amount of practice- and process-oriented content is a very reasonable requirement.


To a first approximation, this chapter should be describing the clever data structures and algorithms that appeared in your project. Think “meaty”---a really good Implementation chapter will come across as chock-full of interesting, nontrivial technical material, clearly described and comprehensible. It should also have reasoned discussion of how your techniques work and why they are well-suited to the problem.

When explaining how your system works, there is a question of what level of explanation is appropriate, and how much detail you should go into. I'd advise that you completely avoid descending to syntactic code-level details (e.g. names of particular classes and methods). There could be an exception if some class or method was so conceptually significant and pervasive that mentioning it by name is the clearest presentation, but this is relatively rare. Think of this chapter as providing descriptions sufficient for a reader to go away and reimplement your system algorithm-for-algorithm, but not identifier-for-identifier. Including a UML class diagram, or similar, is okay---particularly when it's showing something interesting!---but I'd advise against going any deeper than that.

Instead of code-level detail, explain your implementation using pseudocode, data-structure diagrams, flow-charts, time-sequence diagrams, and the like. A good project will have meat here that is outside the syllabus, or at least drawn from the more specialised end of Part II courses, so you should make these especially clear and assume your reader is unfamiliar.

You may well have used some third-party software as part of your system. You should explain how it fits in. Moreover, it's okay (and generally good) to include a summary of how it works, even though you didn't write it. This is to show that you could have implemented it yourself if you'd had to, but that there was no good reason to!

I would personally avoid talking about evaluation harnesses, methods or support coding here. That is best saved for the Evaluation chapter.

Look at existing technical writing, perhaps research papers in reading lists of your lecture courses, for more ideas about how to present technical content clearly and at the right level.


Couch your evaluation in terms of claims that your work supports, or goals that you claim your work has fulfilled. The chapter then becomes an exercise in substantiating these claims.

Explain your method of evaluation. This requires answering at least three questions. What data are you collecting? How will you be interpreting it? Finally, how are your claims decided by this interpretation of your data? That final question is the trickiest to get right---usually it involves an argument that the interpretation of the data soundly represents the abstract truth of the claim in some way. (However, you don't need to belabour the point on that last issue---as long as your approach is not completely off-the-wall, it's generally enough to show that show that you've thought about the validity of your evaluation method and that it's not obviously fatally flawed.)

There should be results, or data. Since these will hopefully be quantitative, they are usually presented as tables and/or graphs. Pay attention to precise presentation of results: units, appropriate precision, error bars, discrete vs continuous graph conventions, etc.. For each piece of evidence you present, say why you're interested in it (first!) and (then) what it shows and your confidence in that.

Present results so that they can be reproduced. So if you give program execution times, say what the machine you were running on was. If you can abstract this to something of more robust meaning than numbers relevant only to your particular experimental rig, then do so, although unless the mapping is absolutely trivial, include the raw data too. One example: if you measure execution times of some low-level code in CPU microseconds, say, then it might be worth abstracting that to CPU cycles if you have the relevant data---but keep the original measurement in there too. More importantly, explain what you are doing! One of the easiest ways to write a bad Evaluation chapter about good work is not to explain the origin or significance of the numbers or graphs you're presenting.

Have something to compare your system against. If this really doesn't seem feasible, you can sometimes get around this by defining your own goals up-front (e.g. “at least 70% precision...”--- including some argued justification for the number!), then showing that you satisfy them. In this case, the goal should be mentioned in the Introduction or Preparation sections. It is nevertheless nicer to show that your system does better than some other system or approach, even if it's a somewhat naive or trivial one. For example, comparing a query-routing algorithm against a random algorithm is better than no comparison at all.


Say what you did, in summary. It's okay to repeat yourself from earlier sections. Also, take the opportunity to talk about future work: what you learned, what could be done better, how your system could be extended to do new and wonderful things, or what better ideas you've had since about how to tackle your chosen problem and its close relatives.


The bibliography should consist of references to archival material. There are some things you'll want to “reference” that are not archival material. For example, you will want to reference software packages you've used. I personally avoid trying to “cite” these in the bibliography, for example, although some authors do this. So that point, and much of the following, is mostly personal advice.

Since URLs are not (under current web technology) stable enough for archival use, avoid URLs except as a last resort, when they're the only way of identifying a published document. Unlike paper publications, web pages are living documents, so if you use a URL, include the date on which you looked at the content (e.g. “retrieved on 2010-07-30”) so that a reader can (hopefully) use an archiving search engine to see the precise page that you saw.

I prefer to use footnotes for referencing software by URL. (But generally use footnotes sparingly---only for places where they'd really interrupt the main flow of text, but are nevertheless relevant and interesting.)

This is very personal advice, but I'd say: in the main text, avoid using citation markers as nouns. A lot of writers do this, but I find it jarringly bad style. Instead, use the author's name. For example, don't write “as shown by [42]”, but instead write “as shown by Smith et al [42]”. If you're using author--year citation markers (which I generally prefer to plain numbers), there are usually different citation styles you can use to avoid repeating the author's name, for example “as shown by Smith et al [1990]” is preferable to “as shown by Smith et al [Smith 1990]”.


Following are a few other pieces of advice on style that I've had cause to dispense on the past.

Don't feel the need to tell a complete, linear story. It's very tempting to write what you did as a narrative. However, this usually has two problems. Firstly, by emphasising the what, it's easy to understate the why, which can make the reader baffled by a succession of sentences saying “I did this, then I did this, then I did this...” but without much insight about the overall goal or the motivation behind each step. Secondly, some of the twists and turns that you took are probably not interesting at all---no matter how much of a struggle they were for you at the time---so can be left out. So, instead of a narrative, try to write instead in what I call a “progressive encoding” or “iterative deepening” style. Think about the most significant high-level points you want to make. As a rule of thumb, each of these should be stated concisely at the beginning of its own paragraph. The rest of the paragraph can fill in additional detail and back-story in successive sentences. This results in a structure where the fact and the explanation occur close together. Curiously, they usually turn up in reverse order (fact first, then explanation) and this is still very readable. It's a very common style in good scientific writing. It has the rhetorical benefit that you keep the reader interested. Making a contentious or surprising statement, then delving progressively deeper into a justification of it, is a trick that can keep the reader engaged when used judiciously.

As an example, instead of saying “I tried running the JVM with the default options, but this suffered from out-of-memory errors, so ran with an increased heap size of 384MB“, say “the JVM was configured with the larger heap size of 384MB. The smaller default heap size was discovered to be insufficient when constructing the intermediate representation for larger input files.” Again, you can hoist more significant facts sooner, and leave more peripheral matters until later in the paragraph. Note that there will still be a temporal progression to some extent, particularly between paragraphs. Note also that by this approach you will naturally end up leaving out the redundant twists and turns that are not interesting. If you think something interesting has been left out unfairly by this structuring, you can always put it in a paragraph towards the end of a section or chapter, clearly signposted as a curiosity rather than part of the main flow. (Sometimes, a paragraph will end with a bracketed note like this one, to further outline the distinction between more- and less-important content.)

Avoid editorialising, by which I mean expressing opinions (e.g. about particular designs, technologies, approaches, companies, products etc.) that you don't intend to scientifically validate.

Underneath any heading in the dissertation, it's good style to include at least a summary sentence before descending down a level of heading structure (e.g. between heading and subheading).

Finally, keep your writing grammatical. Every sentence should contain a verb!

That's all I have to offer---please do let me know any suggestions, queries, corrections, counterexamples or contrary experience you may have about anything in this post.

[Update, 2011-10-13: Andrew Moore supplies this very helpful set of notes from his duties as examiner in 2011!]

[/teaching] permanent link contact

Tue, 22 Feb 2011

Explaining covariance and contravariance by data flow

A few years ago when I was pressed by my students to give them a good explanation of Java's wildcard types, like Stack<? super Circle> or List<? extends Ellipse>, I came up with a simple code example concerning the direction of data flow. The idea seems both to be more general than I first thought, and to apply to more wide-ranging problems with subtyping relations than the case of Java wildcards. Since I've never seen it written down anywhere else, here it is.

In a nutshell, the idea is that direction of data flow is key. (If that was obvious to you already, you can probably stop reading now!) In object-oriented programming, all interactions across object interfaces can be seen as sending messages. In a procedural language like Java, each interaction will in general involve two messages---the call and the return value. In a parametrically polymorphic type system like modern Java's, one of the key roles of the type system is to check (conservatively, as always) that any invocation will not try to send the wrong kind of data, in either direction.

Suppose I have some code that works by pulling objects out of a queue. To work correctly, these objects have to be of class Circle or some subclass thereof. So, we need a queue whose designated element type is Circle or some subtype of Circle, i.e. ? extends Circle. We say that the type of the queue here is covariant in its element type, meaning the subtyping relationships go “the same way”.

Meanwhile, suppose the same code, after it processes the Circle, wants to push the object onto another queue for some other code to deal with. We want to ensure that this queue can accept the objects we give it, which might be Circles or instances of any subclass. So we need a guarantee that it can take any such objects. So, a queue of UnitCircle, say, would not be good enough---if we gave it a plain Circle this would be a type error. So our output queue has to have element type Circle or any supertype thereof, that is, element type ? super Circle. Here the type of the queue is contravariant in the element type, meaning the subtyping relationships go opposite ways.

I won't claim that this explanation covers all sane use-cases of wildcard types. On the other hand, if you know of any that aren't in some way similar, I'd like to hear about them. The idea is certainly more general than just code which processes items in queues, or just code that pushes data from one data structure to another.

This is also a neat way of considering a classic problem in typed object-oriented programming, called the “Circle--Ellipse problem”. The question is simple. We wish to define two mutable data types: Circle for representing circles and Ellipse for representing ellipses. Which way, if any, should the subtyping relation be between Circle and Ellipse?

The trick is to remember that a mutable object is not just a value: it is a container for a value that can be retrieved and replaced. In other words, we can put data in and get data out. The presence of these two distinct directions is the source of the problem. Put simply: when used in the “out” direction, for reading the parameters of the circle, Circle is a subtype of Ellipse (every valuation of a circle also represents an ellipse); but in the “in” direction, for updating the parameters stored in the object, Ellipse is a subtype of Circle, since we can give an ellipse any set of parameters that we might give a circle, whereas the converse is not true--circles cannot be updated with the parameters of ellipses having unequal minor and major radii.

An even simpler case which illustrates the in/out distinction is the usual subtyping rule for functions, which I will illustrate formal-style just because I can:

       s1 <= t1        t2 <= s2
          t1->t2  <=  s1->s2 

In English: a function expression's type t1->t2 is a subtype of another function expression's type s1->s2 if t2 (denoting the set of result values) is a subtype of its counterpart s2, and the type t1 (denoting the set of argument values) is a supertype of its counterpart s1. Intuitively (or Liskovly), this holds because to be a subtype, any term typed t1->t2 must be substitutable into any context where a term of type s1->s2 could be used, meaning the full range of argument values denoted by s1 must be acceptable as the call's content (and, optionally, other values may also be permitted), and the full range of return values denoted by t2 must be acceptable to the call context (and, optionally, (and possibly other argument values could be allowed also). I said “if” but turning the rule upside down is also valid, so “iff” would have been correct (but a stronger statement than the inference rule itself).

I'd like to add that this is the first time I've written down an inference rule in any of my writing.

None of this says anything about how Circle and Ellipse should be implemented. Abstractly, they share a lot, so in any sane implementation we would want to share whatever code we could. In many object-oriented programming languages, inheritance is provided as a code-sharing mechanism. Which way should the inheritance relationship go? It doesn't matter, as long we treat this as separate from the subtyping relationship.

Here is the real problem. Some languages, particularly Java, make this difficult for us by assuming that these two relationships should be the same. Most people who know a little about object-oriented programming will know that inheritance and subtyping are distinct concepts, although are often conflated. Historically, C++ can probably be blamed for this conflation, in that it popularised the overloading of a single mechanism (class derivation) for both. However, in C++'s defence, the fact that class inheritance is private by default is this way precisely because of this distinction. Sadly, most texts which teach the language use public inheritance nearly everywhere without ever explaining why this can be a bad idea. Java made public inheritance the default, so is far more culpable in my opinion.

Many people take this as an opportunity to lambast implementation inheritance. I won't do this. Inheritance is a useful language feature for capturing commonality of implementation. It's great that I can write a class C which shares a lot of implementation with a pre-existing class B, simply by describing what is different. It's very handy that there is no need to write forwarding functions to the code in B that can be used directly in C. It makes for readable code and discourages copy-and-paste code cloning.

Subtyping is more subtle, because it is a semantic property. It relates to the meaning of code, not the raw code itself. Things like direction of data flow don't turn up in the more syntactic matter of code re-use (inheritance's territory) but, as we saw, very much do in the semantic world of types.

I said I've never seen this explanation written down by anyone else. but actually, a bit of Googling reveals another blogger has covered similar ground. You can decide whose explanation you like best!

[/teaching] permanent link contact

Sat, 07 Nov 2009

Teaching despondency

I usually say I enjoy teaching---meaning supervising, since that's the main kind of teaching that I do. I certainly like the idea of teaching. When it goes well, it's satisfying. However, I've admitted to myself recently that I usually don't enjoy it in practice. It fragments my time badly, and as a result I usually don't prepare properly for it. It then puts me into the uncomfortable position of having the success of others dependent on my doing a good job, which would be fine if I was giving it my best, but it's really just a distraction from my main work.

To blame something aside from my own lack of conscientiousness, I also don't think the supervision format works very well for much computer science. I've already ranted here about how usually supervisions entail rushing through all the material, with students “sort of getting it” but mostly not gaining a visceral understanding. It's much harder to debug the students' mistakes and weaknesses in CS than in many other disciplines, particularly with on-paper exercises. It's doubly nerve-wracking when I'm teaching stuff that I don't fully understand myself, like a lot of concurrent programming material---my experience with concurrent programming is limited, and I've certainly never implemented a transaction commit manager or many of the other systems described in the course.

What's doubly disheartening is that there seems to be very little will to improve teaching in this department. The concurrent systems teaching has just taken a giant step backwards in reverting to a textbook-driven approach, whereas the previous course was much more a “look at the code, write the code”, and any new course should in fact have moved to something more practical, not less. The material could easily be made into something very hands-on, no more time-consuming, far easier to teach (running student code in test harnesses is far easier than trying to evaluate some jotted-down pseudocode) and far better for learning quality. There's just no will.As usual, support materials for supervisors are absolutely lacking, despite a decade-old resolution by the Head of Department (two heads ago) that every course should provide a supervisor's handbook. The very basic suggestion of a wiki for supervisors to share their original support materials, references, wisdom, was glibly rejected when I suggested it three years ago, and despite the promises that the department is “looking into ways” of improving things, hardly anything has changed. I will probably rant about this in the upcoming Teaching Committee meeting.

When I visited UMD recently, I caught the end of a first-year graduate-level class on type theory. It was a format that seemed like a far better compromise than our supervision system, and would work for a wide variety of courses. There were about ten students in the class---few enough to make the experience an interactive one, but sufficiently many to make it worth using an experienced faculty member rather than any old graduate student (including myself in that description). It was made very concrete by the use of the Coq proof assistant to mechanise the theory. Overall it just seemed to be offering a far better quality of learning. Cambridge needs to get over the complacency that results from attracting the best students---which it manages out of prestige and the peer-competitive admissions challenge, not because the quality of its courses is any better---and actually take seriously its moral obligations to provide high-quality teaching that answers the needs of the median student, not just the top five percent. Sigh. Rant over.

[/teaching] permanent link contact

Sat, 02 May 2009

Doing the mathsssss: supervisions

I just finished my supervising for the year (since I avoid supervising Easter term courses). As with so many things, there seems to be a major difference in how supervising CS is “supposed” to work and how it actually works. The usual rule of thumb is that there should be one contact hour of supervision for every three or four hours of lectures. What's “supposed” to happen is that the students do some self-study on the lectured material, attempt some exercises, hand in their answers, and let the supervisor go over the subset of material which they have revealed, by their attempts, that they didn't manage to understand by self-study. In my first year as an undergraduate, when I studied physics, physics supervisions followed exactly this pattern, and they were usually pleasant and relaxed, with time left over to talk about “interesting” discursive matters.

Unfortunately, during CS supervisions (both when I give them, and when I was the student), what usually happens is that the supervisor seems to go over almost everything in supervision. Why? Surely the students don't get nothing out of self-study? The whole supervising experience is much less pleasant because there's a constant feeling of a need to rush through the material to cover the necessary amount in an hour. Although the official advice that “it's better to cover a few things well than everything poorly” is undoubtedly true, it's hard to put this to the students, who can become anxious and/or somewhat indignant if their supervisor declines to cover a particular topic. So usually I end up rushing, and letting supervisions overrun, neither of which are particularly pleasant.

One problem might be that my students are (as my former self presumably was) lazy and don't put so much effort into self-study. Another is that, in a group of two or three, there's less overlap in what the students “didn't get” by themselves, so the union is close to the full set of course material. Related to this is the problem that, since computer science is mostly about concepts rather than techniques, learning failure modes are “softer” than, say, in physics---it's quite common for students to “almost get it”, but not quite well enough to avoid going over it in the supervision.

The problems I just mentioned are not easily fixable. However, another contributary one might be. CS students at Cambridge typically have (at least in their first two years) between 12 and (yes, sometimes) 15 hours of lectures per week. A cautious estimate would say that to keep pace with the lecture courses, a student needs two hours of self-study per hour of lecture time, so that's 24--30 hours of self study. There's typically three or four hours of supervision contact time. Suppose each supervisor sets three past-paper Tripos questions---these are supposed to take 36 minutes to answer for a fully-prepared student, so we have to add this on top of the self-study time: 108 minutes per supervision, so call it five to seven hours. Then there'll be at least two ongoing practical series or assignments, accounting for at least six hours per week in total.

What's the sum of all this? Well, it's between 50 and 62 hours... not a particularly pleasant workload for anyone, and especially not for students who, with good reason, will be wanting to have some time left over for socialising, getting involved with extracurricular interests and so on. Not to mention eating, sleeping and the rest of it. For a University consisting of, and allegedly run by, some very smart people, it's rather shameful that those in charge of teaching either haven't done, or are flagrantly disregarding, the basic arithmetic I've just describe.

More happily, I have a feeling that extending Full Term to nine weeks is being proposed at the moment, and would definitely be progress... but only if the extra time is used to spread out the workload rather than simply packing more in. I wouldn't count on this attitude prevailing, but I live in hope.

[/teaching] permanent link contact

Fri, 23 Jan 2009

There's something about CS

Within at least one University (the one I'm at), both teaching and research into computer science seems to have a very different feel and very different culture from that in other sciences. There are some obvious things: less regimented administrative structure, a fairly free-form (almost humanities-esque) “work anywhere, anytime” philosophy, and general laid-backness which springs understandably from the fact that most computer scientists are not Lab-bound, but instead working in the realm of “thought-stuff”.

It's not always a good thing though. We seem to have less teaching budget than other sciences, which might explain why practical classes are too few (though this appears to be improving slowly). In the research world, here's another peculiar way in which we lose out: unlike many other scientific disciplines, computer scientists are expected to typeset their own publications. As you probably know, this is not fun when you're camera-readying something for an exacting publisher (who may well not have bothered to provide a sufficiently complete LaTeX style file for their typesetting rules). Why do we have this responsibility, when in other disciplines (so I'm led to believe) the publishers take on much more responsibility for typesetting? Presumably because historically, computer scientists were almost universally also computer technicians of some sort or another, in the same way that the Computing Service here at the University of Cambridge used to be the same organisation as the Computer Laboratory. It's no longer true, of course, so a bit annoying that publishing anything means hours of LaTeX-twiddling pain.

There's a similarly bizarre phenomenon when doing any sort of practical computer science research: you are effectively your own technician. You're required to have a huge range of practical skills which you will not have learnt from being taught, nor even from practical classes. I'm thinking mainly about programming and Unix skills here. Everyone coming into my research group seems to have them, or at least the beginnings of them. I have them too, so I'm not complaining. But I imagine practically nobody learnt them by taking a degree, or even by doing a job. You could probably reach a reasonable level by combination of introductory programming courses and summer work, but it seems like a stretch. Instead, I'd bet that everyone coming into our group learnt them in their spare time by being a bit nerdy.

What other science displays this phenomenon? It can't be a good one, since it creates a big barrier to entry for people who would otherwise be good computer scientists, but aren't quite nerdy enough to have spent hundreds of hours of their life hacking around. This is perhaps blameable for the poor showing of women in CS research. Clearly, any practical CS researcher has to learn this stuff at some point, but given the high variance in nerdiness, will the non-nerds ever get enough experience to reach the required level? Summer jobs aren't long enough to teach programming -- I guess that any summer job which involves programming will expect you to have the skills already. So, clearly the universities have a big responsibility. But then, practical experience is a different animal from principled understanding. We clearly need some sort of scheme which ensures that incoming non-nerdy (but interested and bright) students can acquire the practical skills they need to do practical CS research, most likely by a combination of degree courses, summer work and summer/winter schools. I don't really have a solution, except “more of that”. Maybe systems research departments should have more encouragement or obligation to take undergraduate interns, and give them coaching (by paying PhD students, most likely)?

[/teaching] permanent link contact

Mon, 18 Aug 2008

This Is Cambridge

One of my main beefs with the Tripos is that it claims to “teach in three years what most Universities teach in four”. This is unfortunately a rather different statement from saying that the students learn in three years what they would learn in four at other Universities. Since exams are competitive affairs, there's no established mechanism for gauging the actual quality of learning that students acquire.

I get the impression that the exclamation “this is Cambridge!” is used as a blanket excuse for cramming lots of advanced material into courses. This is a shame, because such cramming can be counterproductive. The aforesaid statement can easily be used to gloss over any areas where the course genuinely fails to adequately serve most or all of its students. The response---“then they're not smart enough!”---is not good enough. Even if the top students do well by this approach, I'd rather have a teaching course that was optimised for the median student than for the top 5%. If a talented student isn't sufficiently stretched, there are always informal channels (taking [extra-curricular] Master's-level courses, research seminars, self-study) by which to gain more stimulation, and always higher courses of study (and/or research) to pursue afterwards. But if you're not hanging on even to the baseline of the course, you really are out at sea.

[/teaching] permanent link contact

Mon, 02 Oct 2006

Some thoughts and tips about Part II Projects

Part II projects are a decidedly tricky part of the Tripos course, and it's easy to unwittingly make mistakes early on which really compromise your chances later. It's also the case that the Lab's official advice, as contained in the "pink book" and meted out at the Project Briefing, is incomplete and in some cases misleading. Although much of it is good advice, a very few points are (in my humble opinion) not so good.

As someone who, despite being fairly conscientious and (I like to think) fairly competent, ended up with a decidedly average project mark when I took Part II in 2005, I've written up a few pieces of hard-learnt advice. Please don't take them as gospel: if you follow them and subsequently aren't as successful as you hoped to be, I won't be held responsible for your perceived failure. Nevertheless, I hope they're useful.

I hope some of the above proves helpful. If you have any questions, comments or disagreements, please contact me.

(You might cynically wonder why, after all these pearls of supposed wisdom, I'm not suggesting any project ideas this year. I guess it's because I consider finding suitable ideas a hard problem, and not one to which I'm prepared to claim any good solutions right now. Maybe next year....)

[Update, 2008-08-15: thanks to the netos list for a productive discussion about these topics. And this year, I have even put forward some suggestions, found on this page!]

[Update, 2011-10-13: Andrew Moore supplies this very helpful set of notes from his duties as examiner in 2011! It's worth reading ahead of time, but arguably even more useful when writing up---see my later blog post about that.]

[/teaching] permanent link contact

Wed, 19 Jul 2006

Thoughts on writing supervision exercises

As an undergrad I often bemoaned the fact that Computer Science lecturers at Cambridge, unlike their counterparts in Natural Sciences, did not generally provide exercises to accompany their lectures. Instead, most lecturers expect supervisors to set Tripos questions. I found this unhelpful, and still do, for reasons I will now explain.

For one, relevant Tripos questions are often few in number, either because a course is relatively new or because the syllabus has recently undergone significant changes. Secondly, even when a good number of questions are available, they often leave some parts of the course untouched -- but there is no guarantee that the upcoming year's questions will do the same. And finally, Tripos questions are often discouragingly difficult, or infuriatingly tedious, for a student who is learning the material for the first time.

All this has led me to conclude that questions which are good for examining a course are typically not good at helping students learn. (Note that I'm sidestepping the question of whether most Tripos questions actually are particularly good for anything.) So, as a supervisor, I've been having a go at writing some questions of my own. It's difficult! But nevertheless, I feel that the results are mostly half-decent as first attempts. The questions themselves are linked from my teaching section, but the following is a list of goals which I try to ensure are satisfied by the questions I write.

Clearly, some of the above goals are mutually reinforcing, while others are mutually conflicting. Striking the right balance is difficult, and one reason why good questions are more likely to be the result of a collaborative, incremental process than of a one-time effort. On that note, if you have any comments on my questions, please contact me!

[/teaching] permanent link contact

Powered by blosxom

validate this page