Thursday, October 15, 2009

The Open University's approach to plagiarism

I spent the day at an OU internal conference on plagiarism. Until now, most of my engagement with this subject has been people coming to the Moodle Quiz Forum expecting technological magic bullets. There seems to be a depressing assumption in some quarters that preventing students from copying or pasting during a quiz attempt, or from using a spell checker, in some way helps the validity of an assessment. And using Google during a quiz attempt is surely cheating, it couldn't possibly be a valuable study skill for the 21st century?

Anyway, it is just not possible to enforce these kinds of restrictions from a web server application like Moodle. Image, for a moment, what would happen to the web if any advertiser could stop you leaving their horrible web site and going to Google to find something better. If you really want to set up a restricted environment (akin to the traditional invigilated/proctored exam hall) you need client-side software installed on the computer the student will be using. If you are looking for something like this, take a look at Safe Exam Browser, and open-source effort built on Firefox, which is now integrated into Moodle 1.9.6 (due for release soon). See MDL-19145.

I am pleased to say that the OU approach is diametrically opposed to this wishful chasing after technological magic bullets. The conference today started with two keynotes by Jude Carroll from Oxford Brookes University, who has been thinking about these issues for the last nine years, and who is an excellent speaker. She has the very clear summary of the issue: Universities have the responsibility/duty/privileged to accredit student's learning. They give the student a bit of paper saying that they have learned something, and in our society that bit of paper has a certain amount of value. So universities need to measure learning, and that is where assessment comes in. The real problem with plagiarism is that it breaks the link between what the student submits for assessment, what they have learned. If a student writes something in their own words, then that writing is good evidence of the extent to which they have taken in the ideas of a course. If they have just copied and pasted someone else's words, you cannot assess what they have learned. Also, teachers do not set assessment tasks just to measure students. We hope that performing the tasks helps the student to learn.

Jude also made the point that exactly is plagiarism does depend on the context. For example the level of experience of the student, the learning that is being assessed, what you are allowed to assume as common knowledge. Also, not all plagiarism is cheating, and not all cheating is plagiarism. Dealing with plagiarism must be done in an appropriate and proportionate way. To start with, understanding issues of academic honesty is an important learning outcome from a degree course, but it needs to be taught, it is not innate. It cannot be taught as an optional add-on ("the plagiarism lecture") but instead it must be embedded in the context of the subject early in a degree program. (By and large the OU does this in its introductory course.) When plagiarism happens, the response has to be proportionate. Early in a program of study, students need to be given feedback to help develop good academic practices. Later on, students should be expected to understand these issues, and plagiarism becomes a disciplinary issue, but still their need to be a range of fair and proportionate penalties.

The OU has clearly had a group of people thinking hard about this over the last few years, and that has resulted in a new plagiarism policy that was adopted last June. This conference was part of disseminating that policy more widely. There are now a range of penalties for various types of plagiarism, and a new role, 'Academic Conduct Officers' who can deal with most issues of plagiarism that go beyond what the student's individual tutors can deal with. This lets many cases be dealt with quickly, so that only the most serious cases have to be referred to the Central Disciplinary Committee.


Another part of the OU's response to this issue is a new web site Developing good academic practices, which I am afraid you will only be able to see if you have some sort of OU login, student or staff. That is a Moodle site in our VLE. It is a mixture of text to read, with a few audio clips, with a quiz at the end of each section. There is also a summary quiz at the end which draws questions randomly from all the other quizzes. The estimated study time for the whole site is 2 hours. It seems to be well done, and for me it is pleasing to see the quiz module used well, even if it is only multiple-choice and matching questions. The course has about 2300 quiz attempts at the moment.

Finally, the OU does use two technological means to detect plagiarism, CopyCatch and Turnitin, on a proportion of submitted work. However, this is only used to flag up possible cases that are then reviewed by a human. The third form of detection is that tutors marking the students' work can often spot problems. However, overall, the amount of plagiarism detected at the OU seems to be lower than that reported elsewhere. It is interesting to speculate why that might be.

Wednesday, October 14, 2009

What I'm working on

I've been meaning to post here for a while about what I am working on, but I keep posting in the Moodle Quiz Forum instead, because what I have to say seems more relevant there.

Anyway, the short answer is that I am rewriting the Moodle Question Engine. That document explains the what and the why. I want to post here about the how.

The question engine is the part of Moodle that processes what happens as a student attempts questions as part of a quiz (or other activity). What makes this a relatively difficult problem is that there are two independent degrees of variation. A question may be one of many different question types (multiple choice, short-answer, essay, ...) and there are various ways that a student may interact with it (adaptive mode, non-adaptive mode, manually graded, ...). Plus, people seem to think that when quizzes are used for summative assessments, it is quite important that there are no bugs and that performance is good ;-).

The complexity of the problem, and my natural bias, means that I am taking a very object-oriented approach. More so than is normally used in Moodle. Separate objects, with clearly defined responsibilities, helps me understand the problem and have confidence that what I am doing will work.

If you read the document linked to above, you will learn that I have been dissatisfied with this part of the quiz code for years, however it is really only within the last year that I have worked out the overall approach to solving this problem nicely. The key realisation is that you need to apply the strategy pattern twice, once for the bits that vary with the question type, and once for the bits that vary with the interaction model. The other important part of the plan is a cleaner database structure that more closely maps to data we need to store.

However, to implement all that requires quite a lot of code. I need to build the core system that can support all the different interactions and question types. Then I need to create all the interactions to replicate Moodle's existing functionality and the new features we want to add (Certainty Based Marking, and what we are calling the Interactive mode). Then I need to modify all the existing Moodle question types to fit into the new system. And I need to do all this with robust bug-free code that we can confidently use for summative assessment.

Over the last year I become increasing coverted to test-driven development. Certainly I wrote a lots of tests while eating my elephant, and this time round I am being very thorough with testing, although I must admit I still don't always write the tests first.

I am also proceeding very iteratively. I started with a test that took a single true-false question through being attempted according to the simplest of the interactions, and wrote some code that used roughly the right classes to make that test pass. Then for about a week I did little more than refactor that code.

It turned out that most of my variables and classes had the wrong name. For example, at one point I had classes called question_state and question_states, which was clearly a recipe for confusion. It was only after I had working code that I was able to think of the name question_attempt_step (one step in a question_attempt) for one of those. I also came to realise that grades were stored in three separate ways in different places, and so I ought to make sure I was using a consistent naming scheme for my variables. Then I did a bit of moving methods between classes as the exact boundaries of responsibility of different classes became clearer. Should I have been able to get all that right first time? Well I think that would be impossible.

I also started gradually removing simplifying assumptions that worked for my initial test true-false question, but not more generally. That was the point at which I started extending my code to other question types and interactions. For example I wrote a test case a walking an essay question through the manual grading interaction, and exposed some new issues that had to be accounted for; and just today I introduced multiple-choice questions, which randomise the order of the choices when you start an attempt, but then you have to store that random order somewhere so it can be used throughout the attempt. I have also already implemented the certainty based marking interaction.

There is still much to do. My code that outputs the HTML for a question is still a rough hack of the current code that lets the tests pass. I need several rounds of refactoring before that will be cleaned to my satisfaction. There are sill five more interactions to write, although each one is getting quicker than the one before. Then I have to convert all the existing question types. I need code that stores the current state of everything in the database and later reads it back. Finally, the nasty bits, which are upgrading from the current database structure to the new one, and re-implementing backup and restore, including restore of old backups.

If you were paying attention in that last paragraph, you will have deduced that my code does not yet store anything in the database! I am taking an approach with the domain objects completely unaware of the database (which makes testing very easy) and I am planning to use the data mapper pattern to coordinate loading and saving the necessary data efficiently. I am pretty sure I know how to do that, however, I have not tried to write it yet because I want to re-read the relevant chapters of Patterns of Enterprise Application Architecture, and my copy only recently got back from Australia, and I won't be able to retrieve it from my parents' house until this weekend.

In terms of time-scales, I am really hoping to get this done by about Christmas, and in time to go into Moodle 2.0, since it breaks a number of APIs. However, I first have to implement this in the OU's Moodle 1.9 code-base and then port it to Moodle 2.0, so no promises. This may have to wait until Moodle 2.1.

Anyway, that is what I have been doing, and so far it has been very enjoyable. Write tests, make them pass, then refactor aggressively with the tests as a safety net is an approach that is working really well for me. These are quite big scary changes, but right now I am feeling confident that it will all work out, and we will end up with a really solid question engine upon which to base an enhanced quiz and other Moodle activities.

Monday, August 24, 2009

Herding cats

Just before I left Perth, Martin advertised for a Project Manager for Moodle HQ. I think this is probably a good thing, if a good person applies and is appointed. However, I also think it will be a very difficult job to do.

Martin always has too much to do, and any time he can identify some tasks that can be delegated, it is a good thing. Early in the history of Moodle HQ he found Mike and Darlene who run a lot of the commercial side of the Partners network. More recently he appointed Helen to act as community co-ordinator, and Jordan as system admin. All those were successful appointments, and having watched form the sidelines I have seen that Martin will not recruit someone unless he is sure they are right for the job (important when you are running a small business) and Martin is a good judge of people.

The other reason a project manager would be a good idea is clear to anyone who had been following the Moodle 2.0 development, which still has a long way to go until it is finished. Someone with more time than Martin has to ride herd on the process can only help us get 2.0 out of the door.

However, it is not quite that simple. On the one hand, I have studied the Open University Project Management course from their Postgraduate Computing program. That is an excellent course, and as a result I know a bit about and am interested in what project managers do. On the other hand, I also know the fairly independent way that I and other core developers like to work. That is why I chose the title of this blog post. (Not because of some people's user profile pictures!)

To start with, the Moodle project is not even a project in the sense that Project Managers use the word. A typical definition is "A project is a temporary endeavor, having a defined beginning and end," but Moodle itself will not end (we hope). Still, some of the things we do, for example, the Moodle 2.0 release, are projects in this sense. However, we know there will also be another project called the Moodle 2.1 release later. Therefore, if we contemplate a short-cut that would let us release Moodle 2.0 sooner, we have to balance the short-term benefits with the long-term costs of cleaning things up in a later release. Classic project management tends to think about one project at a time.

That ties in with Moodle's choice of feature-driven, not date-driven releases. We will pick a set of features to be included in a release, and we will release when they are done, tested and bug-fixed, however long that takes. Well that is the general policy, but a certain amount of pragmatism is applied when interpreting it. This is a fairly unusual way to run a project. For example, with the Open University's Moodle-based VLE we operate the other way. We have date-based releases, with the dates announced a long way in advance, but we do not guarantee what features will be an any given release very far in advance.

Then there is the the nature of the work. One area where project management is generally successful is in construction projects. The cliché old maths problem "If it takes 2 men 7 hours to dig a trench 6 metres long ..." has at least some relevance to reality there. There is even the Bluebook cost guide that has established estimates for certain types of construction work.

In contrast, as that classic of software project management "The Mythical Man Month" says, "adding manpower to a late software project makes it later." What software developers do is much closer to an architect drawing the plans than to a builder laying bricks. The compiler (or PHP interpreter) is the builder. This is hardly new, and is why agile software-development methodologies were invented. If Moodle's new project manager is going to adopt a Methodology, I hope the choose an agile one.

Another difficulty is that software developers are not fungible. If there is some tricky job involving security you probably want Petr to do it. If it is to do with the quiz, it would be best if I did it. If it is related to backup and restore, no one wants to do it, and so it ends up with Eloy ;-). If those people do the job, it will be quicker. On the other hand, sometimes you want to give the job to someone else, to increase the bus number of the project. While this sort of think makes the project harder to manage, it is the sort of thing that a good project manager knows how to deal with - once they get to know the people involved.

Another consideration is that developers are highly distractible. That is, while they are working on one thing, they may suddenly notice that something is a bit messy, and decide to rewrite it or refactor it, even if that was not part of the original plan. When considering the long-term health of the moodle, that might be the right thing to do, even if, in the short term it delays the next release. At other times, it might just be self-indulgance and cause bugs. Would a project manager be able to tell the difference? Anyway, as some-time tiddlywinks world champion Andy Purvis once told my, after thrashing me soundly, "Strategy should be a mixture of planning and opportunism."

A final potential problem is that the Moodle core developers are a highly motivated group of people. We care a lot about Moodle, and have demonstrated that over the years. We don't need to be told what to do, and a project manager who tried could piss a lot of people off very rapidly and do a lot of harm to the project. Fortunately, I think the chance of Martin appointing someone like that is tiny. However, I think is an important point to make, that the Moodle Project Manager should be a colleague and peer of the developers (with a particular set of skills). That is, they should manage the project, not the developers.

So, I have said that I think a Moodle Project Manager is a good idea, but I have also said why I think it would be a very difficult job to do. So what do I think the Moodle Project Manager can usefully contribute (that I, as a developer, would not object to ;-)).

A good project manager is always a good communicator, and in multiple directions. The Moodle Project Manager will need to communicate with the developers to track as clearly as possible what development is going on, and what still needs to be completed before the next release. They then need to communicate that picture of where we are to all the Moodle administrators waiting for the next release, including the Moodle Parters. They also need to communicate it back to the developers to help them see what progress is being made and what the priorities. Naturally they will be working closely with Martin. They also need to communicate progress to Translators and third-party plugin authors, to help translators have their translations ready as soon to the main release as possible.

A project manager is also good at extracting clarity from a confusing situation, which is really another part of what I just wrote. They can take reports from a lot of people, and a more-or-less vague list of outstanding tasks, and combine that into a picture of where we are now, and where we are going that other people can understand.

Once you can communicate well, and as a result derive a clear picture of where we are and where we are going, then the actually project planning - getting the right people to work on the right tasks next - is relatively easy, but still requires some knowledge of the people and the tasks. Then there are the people skills to help keep people motivated and focussed on the next release without trying to over-manage them.

Finally, and particular around the release time, a project manager can improve the processes. For example, does Moodle need string and user-interface freezes in the run up to the release, to help translators and theme designers? (The answer needs to be a consensus of all involved, so more communication.)

The project manager will also be one of the people in a position to hear what new features people are most desperate to have next, and so will be able to contribute to planning the scope of future releases.

So, it is a challenging job, but I think someone is needed to do it.

Thursday, August 13, 2009

On the busses

On Monday I was privileged to to accompany Jo, Linda and Mary on two of their busses. Jo and I made our way to the middle of a street by the Thames in Pimlico, just opposite the old Battersea Power station, meeting Mary at one end of Vauxhall bridge, and Linda at the 24 head stop. Apparently that is the proper name for the bus stop at the end of a bus route.

The plan had been to get the 24 all the way to the other end at Hampstead Heath, and then get the 168 back all the way south to Old Kent Road. However, it turned out due to an accident in Tottenham Court Road, the 24s were not going beyond Victoria. We got kicked off there, and were faced with a potential rules crises. Jo, displaying a frightening knowledge of the London bus network, almost immediately suggested that we could get the C2 from Victoria to the other side of the Heath, and then walk across to the 168 head stop and so salvage some of the day.

Speaking of the rules of their busses odyssey, they can do other busses out of order, but are only allowed to add them to the blog in order. So, since the C busses will only appear after all the numbered busses, and the As and the Bs, that bit of the trip will probably get blogged in about 5 years time. Who know what the rules say if the route if modified in the mean time?

Having walked across the park, we found not only 168 busses, but also plenty of 24s, and the news that the route was now clear. (Actually, the busses going south use Gower street, not Tottenham Court Road.) So, in the event we were able to complete the rest of the 24 route in reverse, finishing at Victoria, from where Jo and I went to Oxford Circus for a very nice Curry at the Kerala.

It's a strange hobby, but it keeps my mother out of mischief of a Monday and it was nice to be able to share it with her. Being a geek, I hope I can be there when they do the 42 route. And I am pleased I persuaded my mother to blog. Now that I have added a hit counter to their site (thanks to http://www.statcounter.com/) we will be able to see whether anyone is interested, or whether the only visitors are friends and family, or people trying to find travel information. I have now also added a little search form to let people easily find TfL bus route maps from the blog.

Tuesday, July 14, 2009

One step at a time

An important thing to realise about Open Source development is that nothing is ever finished and nothing is ever perfect. (If it was, we would all be out of a job ;-)). Open source is never a project [1], but an eternal quest, and the relevant questions for planning are only ever: "What should we do next?" "What are the biggest problems now?" with the focus on next and now. The quest can only proceed one step at a time, and you know there will be more steps in the future.

Of course, you must have a bold vision of where you are all heading, so everyone is moving in roughly the same direction, but that should not involve details. The details of what you will work on next year are better left until next year. You will be a year older and wiser then, and the state of the art will have moved on.

An important aspect of "what should we do next?" is that it must be somewhere you can get to in one step from where you are now. (Some of the steps in Moodle 2.0 have been quite large.) Open Source proceeds best by accumulating incremental change. That is my belief anyway.

1. A project is a temporary endeavor, having a defined beginning and end ...

(This evolved out of a message I was writing to my Google Summer of Code mentee Olli Savolainen. Thanks Olli.)

Monday, June 22, 2009

The geeks don't really matter

I was just reading this criticism of Moodle, and the thing that strikes me about Bryan Ollendyke's criticisms are the reactions of a software geek. They are also very familiar. I had a similarly horrified reaction the first time I saw the Moodle code (and got into trouble with my boss at the time for speaking my mind at an inopportune moment ;-)) and three and a half years later the same criticisms still apply.

But what I have come to learn over the last three and a half years is that it does not really matter. That is somewhat humbling. I am a professional software developer. I have worked hard to learn to write good code; to build and appreciate elegant and powerful software architectures; to design usable interfaces with modern UI idioms; and so on. However, as I say, that seems not to be very important. Teachers all over the world use Moodle to create great (and ordinary) learning experiences; teachers who move from other learning management systems tend to like Moodle better than whatever they were using before; and all sorts of people from all over the place seem to be able to write plugins. All that, despite Moodle not being a text-book example of software design.

So, are Bryan and I and others with similar opinions just software engineering snobs? Well, probably yes, up to a point, but it is our job to care about these things. Other things being equal, we should do things the right way. The point is that some of the other things are much more important than the cool (or not) technical things going on behind the scenes. The most important thing is education. Moodle's genesis was in Martin Dougiamas's postgraduate studies of online education; but more important is that the Moodle project, led by Martin, has always focussed on engaging teachers, as well as developers, in the Moodle community. To use the HCI jargon, Moodle has always practiced user-centred design.

Screenshot of the Moodle quiz settings form.
Now, if you are an expert in HCI design, and you have seen parts of Moodle like the quiz settings form (screen-shot right), then that last sentence might make you laugh. That form is a typical long Moodle form with a million fields you can fill in. In the technical details it does not follow recent user interface best practice. However, suppose you really want to simplify it. The best approach would be to find some options that nobody really needs, and remove them. Well, believe me, I have tried on several occasions. I have convinced myself that some feature is pointless and posted in the quiz forum. Of course, I quickly get a lot typical 'How dare you! I love it that feature. I'll throw my toys out of the pram if you remove it.' responses. Then, invariably, someone will make a well reasoned post that explains a compelling educational situation where that feature really makes a difference, and I will realise why that feature was added in the first place, and why it would be a mistake to remove it.

That is the thing. All those features that bloat the interface are there because someone wanted them badly enough to implement them. Even if they were not a professional developer, and even if their code is not first rate. On the whole, it is probably better for Moodle to have those features than not, even if that means that the interface is not great. We are not here primarily to build beautiful interfaces. We are here to let teachers build beautiful learning experiences. Of course, that is not an excuse to just ignore defects in the interface. We should, and do, go back and apply HCI know-how to improve the interfaces of existing features; and these days we do try to think about UI design for new features before we implement them. We are learning.

To reiterate my main points in summary: While we developers should strive to do the best job we can, technically, we should not be snobbish about it. We must remember that the most important people for Moodle are the teachers and learners, and it is our job to serve them. We should not reject contributions from people who know lots about education, even if they do not write code as well as we do.

Friday, April 17, 2009

PHP global variables are not necessarily evil

Global variables in software are generally a bad idea. They serve to magically teleport information from one place in a program to another in a way that is very hard to follow. Thus they cause subtle bugs, make maintenance difficult, and kill kittens.

In a simple program, it is normally easy to avoid global variables. When you call a function or method to get it to do something for you, you can probably just pass all the necessary inputs to the function as parameters, and get all the results back in the return statement. The flow of data is easy to follow.

However, in a large, complex system, that may become untenable. For example many, but not all functions in Moodle need a database connection to get information or update it. Does that mean all functions in Moodle end up taking a $db parameter, whether they need them or not, just so they can pass it on to any functions they in turn call? Well, we don't do that, because that way lies madness. Instead we have a 'global' $DB object, and that is not all. We also have $CFG, $COURSE, and so on. Imaging if you needed many of those inside your function. Calling it with all those parameters would be a pain.

Now, I just put the word 'global' in quotes, why was that? Well, Moodle is a web application, so the process that is running is a web server, probably with multiple threads executing simultaneously. A true global variable would be accessible from all threads, and last forever. Something you declare in PHP as a global is only accessible for the duration of one server request, and not accessible from any other thread. In Java, that would be called a ThreadLocal, not a global.

So, a PHP global is not truly a global. However, if abused, it can still be a way to teleport data from one place to another during the processing of a single request. The point I want to make is that there are non-evil ways to use it. In Patterns of Enterprise Application Architecture Martin Fowler describes the Registry pattern (sorry, that online summary is inadequate). That is an object in your program which all the other parts can get hold of, and from which they can get the service objects, like the database connection, that they must depend on. In web applications, you often want dependancies with thread local scope. My argument is that the PHP global keyword is a language feature that implements a thread-local registry for you with no effort. Thus it is a good thing if used properly.

What is using it properly? Well it all depends on the kind of things you store there. Are you making common dependancies easy to find, or are you magically teleporting information. I think that Moodle does mostly use this feature properly. Our global variables like $DB, $CFG and $COURSE are things that can legitimately be stored in and accessed from a Registry. However, we have some horrors, like $CFG->pagepath and $CFG->stylesheets, which I am currently trying to exorcise from Moodle 2.0.

One advantage of storing your dependencies in a Registry, as opposed to, say, making them singletons, is that it makes them substitutable. This becomes important when you try to write unit tests. When unit testing, you often need to switch in a test double in place of one of the dependencies. Well, with a Registry you can swap one in during test set up, and switch it back out during tear down. I have been doing that a lot recently in Moodle, and it works. (You could not do it, for example, when you accessing the database in Moodle 1.9. There, the database connection was hidden in functions like get_records, and could not be substituted. Now we have $DB->get_records with $DB in the 'global' registry where it can be substituted.) Some other global-like mechanisms, like static methods or singletons are not substitutable, and so make testing much harder, if not impossible.

Of course, some people would argue that you still should not use the global keyword, that instead you should implement your own Registry class (an example). I disagree. Appropriate use of language features tends to create more idiomatic code.

Wednesday, April 8, 2009

How do you eat an elephant?


Conductors say the funniest things some times. Shaun uttered the above gem at a rehearsal recently, seemingly apropos nothing. The answer is, of course, one bite at a time. It turned out that he was trying to tell us that we would one day get to grips with the first movement of the César Franck symphony in D minor, if we rehearsed it a bit at a time - yes, even the cellos.

The symphony I think I can cope with. (Those bits I can't play properly, I will be able to fake ;-)) Instead, my personal elephant is currently the Navigation changes for Moodle 2.0. Although it is described as Navigation changes, it is much, much more than that. Blocks / themes / filters / rendering / pagelib / navigation changes would be more apt, and that is at least an African elephant, if not a mammuthus sungari.

Fortunately, I have Shaun's advice to guide me, so I sharpened my metaphorical butcher's knife and started trying to dissect it into manageable chunks. Unfortunately I only got part way, because I started thinking about the filters bit of it, which I had previously designed in detail. Since it is more fun to write code than to write documentation, and because I had been reading a book about unit testing and test driven development, and wanted to try some, I got seduced. Still, it is a worthwhile feature and the implementation is going well. You can follow the development in MDL-7336.

Of course, once that is done, I must get back and finish the breakdown of all the Navigation work, especially as some of it needs funding, and so we need some estimates. That summarises what I have been working on in Moodle land recently.

By the way, the book I mentioned (xUnit Test Patterns) is excellent, if you want to read an 800 page book about unit testing. If you want a lighter introduction to the topic, Pragmatic Unit Testing, or the Unit Testing chapter of PHP in Action, are probably better bets.

Wednesday, February 18, 2009

Avoiding duplication and increasing flexibility in software: what about version control?

These thoughts were catalysed by Section 4.2.4 "Once and only once" of PHP in Action where they preach the evils of duplicated code. This is something I strongly believe in. (My best exorcism to date is this Moodle commit.)

Unfortunately, the example they pick to illustrate their point utterly fails. Their example of what not to do is making a custom version of an application in a hurry by copying the whole thing and editing a few lines. Well, duh! Put the code in git and make a branch for the custom version. And, of course, when you do have time, come back and refactor, at which point git diff/merge/rebase ... will probably be a big help.

Now, this is a form of software engineering that open source developers do all the time (while having wild flame wars about which version control system is best). But, when computer scientists dream about paradigms like object orientation, design patters, refactoring, and so on, as ways to reduce the need for code duplication and increase the flexibility of software designs, do they consider the role of version control systems? I don't recall reading anything.


The point about flexibility is particularly interesting in the context of opens source software written in in an interpreted language. Given my background, I am of course thinking about Moodle, which is a PHP web application. Suppose, by way of example, you want to change some part of the processing that occurs when a student submits a quiz, and Moodle works out what score they deserve. The 'proper' design patterns way to do this is:
1. Check: Is the processing algorithm factored into a separate class, as recommended by the Strategy pattern? If not, refactor.
2. Subclass the default Strategy to implement your customisations.
3. Configure things so the factory methods instantiate your Strategy class, rather than the default one.

Alternatively, you could just hack the code. Preferably as a custom branch in your version control system. When a new Moodle version is released, just upgrade and merge (or pull and rebase). One could even try to claim that this way is better, because if the code you hacked changes between releases, the merge may fail, helping you realise that you need to rework your customisation. If you don't notice the problem until you get to testing (which may happen anyway) it will be much harder to find and diagnose.


Another example is this post in the Moodle quiz forum. Someone wanted to tweak something in Moodle, they were told to change the definition of a constant in a library file. Note that because there is no duplication of magic numbers throughout the code, it was only necessary to change the number in one place, so there is some proper design going on here.

One could, of course, have a separate configuration file for all the settings like this in Moodle, but does that really make anyone's life easier? If you think of all the things people might want to tweak, that would be one big file. Also, it would move the constant definition further from where it is used, reducing the cohesion in the code. You could also handle this by making this number an admin setting, stored in the database, and editable through the web interface. In this case, I would argue that that is bad UI design. 3 is a perfectly good default for almost everyone, and Moodle already has more than enough configuration settings. Sufficiently few people need to adjust this, that telling those that do to edit the code is an adequate interface.

You could call this approach "The whole code is a configuration file". In the abstract, you would not say it was good design, but for obscure configuration options like this, it may be the best way.


So, in a world with version control and interpreted languages, what is flexible and easy-to-modify software?


(To head off the obvious comments, I had better re-enforce that I do like nice clean software design, and design patterns, and so on; but I also spend most of my life working on Moodle where parts of the code are not like that; and somehow, most of the time, it just does not seem to matter. Millions of people around the world happily use and customise Moodle despite the lack of design patterns in the code. Should I be sad, or happy?)