Archive for December, 2006

Darcs — The source code management system of the future?

Dec 29 2006 Published by Salvatore Iovene under Software

Hav­ing already men­tioned some good prac­tices for source code ver­sion­ing and how impor­tant ver­sion­ing is, in any case, I would like now to review and com­ment about what I find the best source code man­age­ment sys­tem out there: darcs.

Darcs is a source con­trol sys­tem writ­ten in Haskell (a func­tional lan­guage), and fea­ture very solid math­e­mat­ics bases, being com­pletely enge­neered on top of a “patch the­ory”. Not only darcs is straight­for­ward and very easy to you, not only it’s very inter­ac­tive and min­i­mizes the chances of mis­takes, but it also gives out fea­tures that the pop­u­lar SVN doesn’t have. Here I’m going to show some use cases, and show how things are eas­ier with darcs.

A brief start up

Before ana­lyz­ing the key fea­tures, let’s have a brief start-up quick tuto­r­ial. The eas­i­est way to get darcs, is to down­load a binary pack­age. These pack­ages con­tain a pre­com­piled release of darcs, with every­thing needed sta­t­i­cally linked inside. You only need o copy that some­where in your $PATH, such as /usr/bin, /usr/local/bin, or what­ever you have in your $PATH. Of course you can down­load the source code and build it your­self if you want.

Let’s now cre­ate a sim­ple Hello World project, and use darcs to ver­sion it.

$ mkdir $HOME/projects/HelloWorld
$ cd !$
$ darcs init

darcs init will cre­ate all the files nec­es­sary to source-control the code. You will find a new direc­tory named _darcs.

Now we can write our HelloWorld.cc main file:

#include <iostream>

using namespace std;

int main(void) {
    cout << "Hello World!"<< endl;
}

Time to add the file to ver­sion control.

$ darcs add HelloWorld.cc

Alright, now we really get into darcs. First of all, in case you didn’t notice, darcs doesn’t really need any server at the other end, like SVN would need an SVN server, or CVS would need a CVS server. This means no has­sle in installing and con­fig­ur­ing a server. Later we will see how darcs man­ages col­lab­o­ra­tion with remote users.

Now it’s time to save our changes to the repository.

$ darcs record
Darcs needs to know what name (conventionally an email
address) to use as the patch author, e.g. 'Fred Bloggs
<fred@bloggs.invalid>'.  If you provide one now it will
be stored in the file '_darcs/prefs/author' and used as a
default in the future.  To change your preferred author
address, simply delete or edit this file.

What is your email address?
Salvatore Iovene <salvatore@invalid.com>
addfile ./HelloWorld.cc
Shall I record this change?(1/?)[ynWsfqadjkc], or ? for help: y
hunk ./HelloWorld.cc 1
+#include <iostream>
+
+using namespace std;
+
+int main(void) {
+	cout << "Hello World!" << endl;
+	return 0;
+}
+
Shall I record this change?(2/?)[ynWsfqadjkc], or ? for help: y
What is the patch name? First record.
Do you want to add a long comment? [yn] n
Finished recording patch 'First record.'

Some points worth inspec­tion here:

  • Why did darcs what to know my email address? That’s because every­thing you com­mit (they are named patches) will be known as com­ing from you. If you’re work­ing with sev­eral peo­ple, darcs has to know who is com­mit­ting what. Fur­ther­more, peo­ple down­load­ing your repos­i­tory can, e.g. make some changes and improve­ments, and then issue a darcs send which will send you the patch via email, and you can eval­u­ate it and decide if apply it.
  • What is a hunk?hunkis a piece of a patch, i.e. a cer­tain mod­i­fi­ca­tion in some source file. If you have a large file, foo.c, and mod­ify a cer­tain func­tion bar() at the begin­ning of the file, and then a cer­tain other func­tion tar() at the end of the file, this will result in two hunks. What’s the advan­tage of all this? Since darcs is so inter­ac­tive, you may decide to either apply both hunks in the same pathc, so answer ‘y’ to both, or real­ize that they log­i­cally belong to two dif­fer­ent patches, so you will say ‘y’ to one of them, and ‘n’ to the other. Then, after fin­ish­ing record­ing the first patch, you issue a darcs record again, and record the other hunk in a sep­a­rate patch, with a sep­a­rate name, that forms a log­i­cal unit per se.

Now let’s make a small change.

#include <iostream>

int main(void) {
    std::cout << "Hello World!" << std::endl;
}

As you can see, we have removed the using namespace std; dec­la­ra­tion, and added the std:: name­space pre­fix to cout and endl. A very impor­tant darcs com­mand is whatsnew, that shows us how the code dif­fers from the repository.

There are two hunks, as expected. Let's record the changes.

$ darcs record
hunk ./HelloWorld.cc 3
-using namespace std;
-
Shall I record this change?(1/?)[ynWsfqadjkc], or ? for help: y
hunk ./HelloWorld.cc 4
-	cout << "Hello World!" << endl;
+	std::cout << "Hello World!" << std::endl;
Shall I record this change?(2/?)[ynWsfqadjkc], or ? for help: y
What is the patch name? Removing the std namespace \
declaration.
Do you want to add a long comment? [yn]n
Finished recording patch 'Removing the std namespace
declaration.'

Obvi­ously those two hunks must form one sin­gle patch, because we don’t want any patch to leave the repos­i­tory in a bro­ken state. Now we get to the cool stuff. Darcs lets you unrecord your changes, i.e. inter­ac­tively roll­out the patches until you are sat­is­fied. We might change our mind about the last patch, and think that using namespace std; is not tha bad after all. No problem.

$ darcs unrecord

Fri Dec 29 12:53:32 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* Removing the std namespace declaration.
Shall I unrecord this patch?(1/2)[ynWvpxqadjk], or ? for help: y

Fri Dec 29 12:37:33 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* First record.
Shall I unrecord this patch?(2/2)[ynWvpxqadjk], or ? for help: n
Finished unrecording

Now there we are again, back as if noth­ing happened.

Imag­ine you want to have a copy of your repos­i­tory, maybe on a dif­fer­ent par­ti­tion of your disk, or maybe on a USB stor­age drive:

$ cd ..
$ mkdir RepoCopy
$ cd RepoCopy/
$ darcs init
$ darcs pull ../HelloWorld/

Fri Dec 29 12:37:33 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* First record.
Shall I pull this patch?(1/1)[ynWvpxqadjk], or ? for help: y
Finished pulling and applying.

Another direc­tory is not the only way you can move your repos­i­tory around, you can use SSH to copy it to another machine, and HTTP to fetch it. This is actu­ally the way you han­dle col­lab­o­ra­tion. Imag­ine you have a server some­where, named www.server.com, and there you want to have your cen­tral repos­i­tory, with which you can col­lab­o­rate with your devel­op­ment peers.

$ darcs push \
username@www.server.com:/var/www/htdocs/HelloWorld/repo

This will ask you which patches you want to push to that server, one by one, in the usual darcs inter­ac­tive mode. I’m assum­ing that the direc­tory /var/www/htdocs/HelloWorld/ on the server, hosts the http://www.server.com/HelloWorld/ web­site. Every­body can now get a copy of your project just by doing this:

$ darcs get http://www.server.com/HelloWorld/repo

And any­body with an account on that server, will be able to push patches, if they of course have write per­mis­sion to the direc­tory where the repos­i­tory is.

Where to go from here

Here fol­low some must-read links if you’re inter­ested in darcs. Prob­a­bly in the future I will write more about it. Thanks for reading.

4 responses so far

Getting a project done using clever design

Dec 27 2006 Published by Salvatore Iovene under Software

Some­times, when cod­ing a one-person-project at work or for fun, each one of us has found him­self stuck at some point, and then the project even­tu­ally died out. Let’s have a look at some design and dis­ci­pline rec­om­men­da­tions that can help us achiev­ing our goal.

Who doesn’t have a dream hid­den in a drawer? Some of us coders have dreams about pro­grams about which we’ve been think­ing for a long time and per­haps never found the time to write. Now that we finally decide to set­tle down with it and write the thing down, we bet­ter not hurry. There are sev­eral com­pli­ca­tions that might arise dur­ing the cre­ation of the project and most of them can be faced deal­ing with two issues: design and dis­ci­pline. Let’s exam­ine some of the pos­si­ble issues.

Tech­ni­cal difficulties.

Not very unlikely, at some point of the devel­op­ment, we might find some obscure obsta­cles, imper­son­ated by a very tough tech­ni­cal issue. I.e., we might think that it just can’t be done. Well some­times it really can’t, but usu­ally it’s a mat­ter of tech­nolo­gies and the proper use of them. To address this kind of prob­lem, there are basi­cally two ways.

  1. Read up.

    Once you’ve deter­mined what tech­nolo­gies you’re going to use, and what libraries, read up about them. “I’m going to learn them as I build up my project” is not a good strat­egy. You will prob­a­bly real­ize that those are not the right tech­nolo­gies after all, or that you’re not using the right libraries. Or, most com­monly, that you’re using your things in the wrong way. And that could be too late. This is a very com­mon case of project fail­ure. This is when you get to face an obsta­cle that seems insu­per­a­ble, so you’ll waste a lot of time, and even­tu­ally get unmo­ti­vated. Start read­ing the web­sites of the tech­nolo­gies and libraries you want to involve, then read their doc­u­men­ta­tion. You don’t need to read all the APIs of course, but at least you ought to read the tech­ni­cal overviews, the white papers and the gen­eral design per­spec­tives. Pos­si­bly, buy a book about them and read it. Of course this will delay the start off of your project, but that’s bet­ter than invest­ing 2 months in it and then have to trash every­thing. Typ­i­cal case involve start­ing a new lan­guage, or a new frame­work. If you’re new to Hiber­nate don’t expect to just start­ing using it read­ing the Quick Start Tuto­r­ial. Most things, espe­cially nowa­days, aren’t just about using them. It’s mostly about under­stand­ing the big pic­ture and know­ing what the right angle from which approach them. The details will always come after­wards. Never ever under­es­ti­mate the impor­tance and the power of a good book on a cer­tain mat­ter. After hav­ing read up enough, you’re ready to start think­ing about your application.

  2. Design.

    Never fail or omit to design your appli­ca­tion (thor­oughly) before hands. It might seem silly for small appli­ca­tions, but it never is. Draw down a scheme of the main com­po­nents of the sys­tem, and remem­ber: always divide and con­quer. Start by draw­ing off a very big pic­ture of the sys­tem. Ask your­self what com­po­nents are involved, what tech­nolo­gies you’re going to use, what libraries you’re going to inte­grate. Once you have a clear and state-of-the-art idea of what the big pic­ture is, you can start adding details. You can plan your data­base, for instance. Start that by indi­vid­u­at­ing what the main com­po­nents are, and how they inter­act with each other. Then you’re ready to design the data­base in more detail, i.e. spec­i­fy­ing each field and rela­tion. That will also help you enter­ing more detail into the big pic­ture of your appli­ca­tion design. Start now con­sid­er­ing all the com­po­nents and their inter­ac­tions. Define the objects you need and the way they com­mu­ni­cate. Draw mod­els and objects, pos­si­bly using UML. Be very care­ful and see to it that your model makes sense. Glitches and prob­lems might (and should) already come up at this point. If your appli­ca­tion takes less than 612 hours to be designed, than it’s either very sim­ple, or you’re being super­fi­cial. Of course if we’re talk­ing about Hello World, then you don’t need that much design, but this should be clear already!

If you’ve taken care of all this, the odds are with you and there are very lit­tle chances of fail­ing for tech­ni­cal issues. Now it should just be about writ­ing the actual code and you already know that it can be done, because you read up and designed the thing properly.

Scat­tered code.

Although Spaghetti Code was The Way, some long time ago, Object Ori­ented Pro­gram­ming has now been out there long enough so that we all should be able to write decent Object Ori­ented code. Seri­ously, if you’re still writ­ing pro­ce­dural Spaghetti Code, you should really read some Object Ori­ented Pro­gram­ming books and start liv­ing in the present. If you don’t even know what Spaghetti Code is, chances are that it’s what you do, so Google it up. Hav­ing well struc­tured, lay­ered and main­tain­able code will help you write less code, write bet­ter code, and fin­ish your project sooner. This should come out auto­mat­i­cally from a good design, but it’s worth spend­ing some words. The more you are able to do the fol­low­ing, the bet­ter your project will go on: write a class, double-check it, test it, never touch it again. This is the divide and con­quer par­a­digm. Once you have some parts of your project that are actu­ally fin­ished, you will find a lot more moti­va­tion in con­tin­u­ing. Hav­ing to con­tin­u­ously mod­ify parts of your code, going back and forth on those changes again and again, is not only frus­trat­ing, but dam­ag­ing the very struc­ture of your project. I’m sure you have run through more that one ses­sion of “refac­tor­ing” your code. Mov­ing pieces around, redesign classes, putting order, etc. This means that you’re wast­ing time that you could’ve used on adding new fea­tures or get­ting close to some­thing that’s releasable.

Lack of deadlines.

Even if you’re work­ing alone on an hobby project, set your­self dead­lines and a roadmap. Reserve your­self some time each day in which you can work at your project. If you already know what ver­sion 0.3 will have, and what ver­sion 0.4 will look like, it’s more likely that you will stick to that. Give your­self small objec­tives and fol­low them, one after the other. Don’t push your­self too much, though.

Lack of professionalism.

This is a very impor­tant point, even though you may think it’s not. Even if you’re work­ing all by your­self, whether it is a work project or a hobby one, always be pro­fes­sional. Remem­ber the fol­low­ing rules.

  • Use a source ver­sion­ing sys­tem.

    I don’t care if it’s CVS, SVN, Darcs, GIT or one of the many out there. Use one. Com­mit your work and keep track of the changes. This will not only help you not lose impor­tant code, and keep your work traced down cor­rectly: it will also give you dis­ci­pline and moti­va­tion. Read some best prac­tices for SVN and other ver­sion­ing systems.

  • Use a bug tracker.

    There’s a vast choice: bugzilla, trac and the Bug Genie are only few of them. Bug track­ing is ter­ri­bly impor­tant. Maybe not in the very ini­tial phase of your project, but as it becomes usable, bug track­ing can’t be neglected. Even if you’re work­ing alone. Track the bugs scrupu­lously and like you were work­ing on the most impor­tant project of the World. Bugs tend to be for­got­ten of after few hours. Few days in the best case. This is also some­thing that will keep you moti­vated. Act­ing professionally.

  • Keep a web­site and build up a com­mu­nity.

    I assume that your project would be inter­est­ing to some­one. The most moti­vat­ing thing ever, is receiv­ing encour­age­ment and feed­back from strangers. Keep a web­site of your project and let the com­mu­nity know what’s going on. Release it as soon as it’s ready and you’ll get feed­back, even­tu­ally help. This is really highly motivating.

Lack of discipline.

Another big hit for unfin­ished projects. Stay away from it for more than 1 months, and it’s over. Most of the times. After one month, you will have for­got­ten a lot of things about it, and just can’t get the focus again. Just can’t find your way through it again. The more the time goes by, the more you’ll get detached from it, and it will even­tu­ally end up in the well of the for­got­ten and unfin­ished projects. To find the right dis­ci­pline, force your­self to keep an eye on it at least two times a week, for 2 hours each time. Of course, this depends highly on how much you care about fin­ish­ing your project, but of course we’re dis­cussing this assum­ing that you care a lot.

Keep all of these hints in mind, and with a good dose of deter­mi­na­tion you can accom­plish everything.

No responses yet

Common mistakes when approaching OO design — Class dependencies

Dec 21 2006 Published by Salvatore Iovene under Software

Here we con­tinue with explain­ing some of the mis­takes com­monly made in Object Ori­ented design, and the good prac­tices that are often ignored. This arti­cle is focused on code main­tain­abil­ity and on improv­ing coöper­a­tion with peo­ple work­ing at the same project.

Encour­ag­ing class dependencies.

Hav­ing a lot of (mutual) depen­den­cies in the code is quite typ­i­cal of Spaghetti Code, and it’s def­i­nitely some­thing we want to avoid, in order to keep our design neat, improve main­tain­abil­ity and ensure ease of col­lab­o­ra­tion with col­leagues. What do I mean by “class depen­den­cies”? Let’s con­tinue the exam­ple from the last arti­cle, and sup­pose we have a cer­tain class GuiManager which, at some points, wants to gen­er­ate some reports. Let’s intro­duce now a cer­tain ReportManager, which is a class respon­si­ble for gen­er­at­ing reports. We have two types of report: TableReport, and ChartReport. They look like this:

class TableReport {
    public:
        void report()  {
            // do something
        }
};

class ChartReport {
    public:
        void report()  {
            // do something
        }
};

This means that the Report­Man­ager will have to look some­thing like this:

class ReportManager {
    public:
        void reportAll() {
            m_tableReport.report();
            m_chartReport.report();
        }

    private:
        TableReport m_tableReport;
        ChartReport m_chartReport;
};

There are sev­eral prob­lems in this imple­men­ta­tion. First of all, If the guy respon­si­ble for the TableReport one day wakes up, and decides that the method report() should rather be named generate(), he will not only be allowed to just change that and com­mit to the repos­i­tory, but this will break the ReportManager! So after a few hours, the guy respon­si­ble for the ReportManager checks out from the repos­i­tory, builds, and finds out that all the times he has used the TableReport need to be changed. Of course this is some­thing we don’t want to happen.

The usual approach to this, is using an Abstract Base Class (ABC), which is a very robust way to sort out prob­lems like this. Let’s see come code:

class Report {
    public:
        virtual void report() = 0;
};

class TableReport : public Report {
    public:
        void report()  {
            // do something
        }
};

class ChartReport : public Report {
    public:
        void report()  {
            // do something
        }
};

Report is our ABC, and with it we are lit­er­ally forc­ing the peo­ple who write TableReport and ChartReport to write a method named report(). So, this way we broke one depen­dency: the ReportManager doesn’t need to worry about the way every sin­gle report will call the method: it’s sure that a method named report() will exist.

There is, tho, another depen­dency. If some­body writes a new report, say XmlReport, this will need mod­i­fi­ca­tions to the ReportManager, because our logic so far implies that the ReportManager knows about all the reports. So, if we’re not the main­tain­ers of the ReportManager (because maybe it’s in some dif­fer­ent library, writ­ten by some­one else, and we don’t have access to the code), we will have to go ahead and ask the right­ful main­tainer to mod­ify the code. Hence, there’s an extra depen­dency, not struc­tural, this time, but log­i­cal. What if the main­tainer of the ReportManager gave us tools (read APIs) so that we can reg­is­ter our par­tic­u­lar report to the ReportManager? Con­sider the fol­low­ing code:

class ReportManager {
    public:
        void registerReport(Report const & r) {
            m_reports.push_back(r);
        }

        void reportAll() {
            std::list::const_iterator iter;
            for(iter = m_reports.begin();
                 iter != m_reports.end();
                 ++iter)
            {
                iter->report();
            }
        }

        private:
            std::list m_reports;
};

This way, the ReportManager doesn’t have to know any­thing about any Report.

No responses yet

Common mistakes when approaching OO design

Dec 19 2006 Published by Salvatore Iovene under Software

Today I want to talk about Object Ori­ented prac­tices, and 3 com­monly made mis­takes. Very often, when review­ing code writ­ten by other peo­ple, I find vio­la­tions of com­mon OO prac­tices, that make the code a lot less main­tain­able. Here fol­lows a list of the most com­mon ones, and, of course, some expla­na­tions about them.

Layer vio­la­tion.

While not the most com­mon, this appears to me as the most dan­ger­ous. What is layer vio­la­tion? Let’s show it with an exam­ple. Assume we have a GUI dri­ven appli­ca­tion that reads data from a data­base and shows the results on the dis­play. We might con­sider hav­ing some upper level Con­troller class, and man­agers for each com­po­nent, e.g. GuiManager, DbManager, ReportManager. Assume that the Controller class runs a loop, and in that loop we take care of refresh­ing the GUI. What I’m going to write now is really wrong:

this->guiManager().reportTable().update(this->reportManager().populate(
    this->dbManager().query(someSqlString)));

Well, there are many hor­ri­ble thing here, but the layer vio­la­tion hap­pens in this->guiManager().reportTable().update(…). Imag­ine the var­i­ous com­po­nents of this scheme as lay­ers on top of each other. We have the Controller, the GuiManager and a cer­tain ReportTable.

What we’re doing, is access­ing the ReportTable layer from the Controller one. Why is this bad? Hav­ing layer vio­la­tions will fill your code up with dis­tur­bance. You will rapidly lose track of what does what (e.g., who is updat­ing the ReportTable? The Controller or the GuiManager?), and this will end up into an inter­twined mess com­monly known as Spaghetti Code.
Doing that, you are per­form­ing actions from parts of the code to which those actions do not belong. Classes shouldn’t care about what other classes are, but only about what other classes do. Think about it: do you really want to let the Controller know that the GuiManager has a ReportTable, inside? Shouldn’t the Controller tell the GuiManager just what to do, rather than how to do it? Hav­ing classes access inner func­tion­ing of other classes will lead you to messy code, espe­cially when there’s more than one peo­ple work­ing on a project, as dis­cussed later in this arti­cle. Hav­ing all the com­mu­ni­ca­tion hap­pen­ing between adja­cent lay­ers will help us keep­ing the project con­sis­tent even in case of changes to com­po­nents. Imag­ine if one day I will decide that the GuiManager doesn’t need a ReportTable, but a ReportChart. My ideal sce­nario is the one where all the changes I need to make are only within the GuiManager. But if there was a layer vio­la­tion, such as the men­tioned one, I would have to mod­ify the Controller as well. When peo­ple in a group work on dif­fer­ent com­po­nents of a sys­tem, they don’t want to make a change that will break every­thing else. In order to avoid bro­ken code, it would be a good prac­tice to keep lay­ers comm­ni­cate with the adja­cent ones, accord­ing to well known interfaces.

Infor­ma­tion hiding.

This brings us to our next point. What does the Controller need to know about the mem­bers of the GuiManager? Ide­ally, noth­ing. Ide­ally, there would be no get­ters or set­ters, since the Controller doesn’t need to know any­thing about the GuiManager’s inner func­tion­ing. What needs to be done, in fact, is design­ing a well known inter­face for the GuiManager that the Controller can use. Once designed, such inter­face should never be changed, in order to ensure max­i­mum com­pat­i­bil­ity within the com­po­nents. Imag­ine you have just a cer­tain GuiManager::update() method, the Controller would just need to call this->guiManager().update() and, what­ever the GuiManager does, is none of the Controller’s busi­ness. Inside, the GuiManager might do some­thing like this->reportTable().update(), but in case this would change to a ReportChart, it wouldn’t break the Controller, and keep the peo­ple that work with it happy.

Abus­ing sin­gle­ton pattern.

Singletons are not a way to get your­self some global vari­ables. Think thor­oughly about the rea­sons why you really need a Singleton in your pro­gram. Is it just a way to access some vari­ables from every­where in the code? If the answer is yes, you should con­sider refac­tor­ing your code to get rid of the Singleton class. Keep also in mind that Singletons are ene­mies of unit test­ing. Have a Singleton class do some­thing, rather than con­tain some­thing. A typ­i­cal exam­ple of a class suit­able to be a Singleton is a Logger class. You need to access it from every­where in the code; the class doesn’t need to be aware of the appli­ca­tion it’s in; the class does (logs) and doesn’t just con­tain. If you write a Singleton class like the fol­low­ing, you’re doing some­thing wrong:

class AccessData : public Singleton<AccessData> {
    friend class Singleton<AccessData>;
    public:
        std::string username;
        std::string password;
};

This class seems to have the sole pur­pose of eas­ing the access to a cer­tain username and password from every­where in the code, with­out the need of pass­ing them around. You should con­sider pass­ing ref­er­ences and data around only when needed, or adopt­ing some sig­nal­ing framework.

No responses yet

5 SVN best practices

Dec 15 2006 Published by Salvatore Iovene under Software

Ver­sion­ing sys­tems like CVS, SVN or Darcs are very impor­tant tools, that no seri­ous pro­gram­mers can omit to use. If you started a project with­out using any ver­sion­ing tools, I really rec­om­mend that you start using one imme­di­ately; but I’m not dis­cussing this right now.

I would like to point your atten­tion to some best prac­tices that I rec­om­mend when work­ing in a team.

  1. Don’t use ver­sion­ing like it were a backup tool.

    I’ve heard this ques­tion too often: “Have you put your code safely on SVN?”. That’s a bad ques­tion. Stor­ing code to an SVN server is not meant for safety, i.e. for fear of los­ing it. You are talk­ing about some­thing else, and that’s called backup. Take Darcs, a not so pop­u­lar ver­sion­ing sys­tem. It can start with­out a server, and you can just run it locally on your machine with­out launch­ing any dae­mon what­so­ever. A faulty hard drive can still make you lose all your work, of course. That’s why you have to do back­ups, of course, but they don’t have any­thing to do with ver­sion­ing. Hence, com­mit­ting to the repos­i­tory once a day, before tak­ing off home, e.g., is not an accept­able prac­tice, espe­cially if you work in a team. Doing that would be like mak­ing a daily backup. An SVN com­mit, instead, has to have a mean­ing of some sort, not just “Ok, let’s store to the SVN server the work of today”. More­over, some­times, if the sched­ule is tough and the coöper­a­tion is tight, you need to com­mit very often so your peer will keep up with you all the time, and not just find out, at evening, that he’s got dozens con­flicts after check­ing out your code.

  2. Com­mit as soon as your changes makes a log­i­cal unit.

    How often should you com­mit? Theres no such thing as com­mit­ting too often, or too rarely. You should com­mit each time your changes rep­re­sent a log­i­cal unit, i.e. some­thing that makes sense. Usu­ally that hap­pens because you’re fol­low­ing a plan, when cod­ing (because you are, aren’t you?). So, you find out a bug in the trunk, plan a strat­egy about how to fix it, fix it, and then com­mit. This makes sense because that’s a com­mit that fixes a bug. So that revi­sion X is buggy, while revi­sion X+1 is not. Don’t be shy about com­mit­ting too often. Should you just find an insignif­i­cant typo in a debug string, or in a com­ment, don’t be afraid of com­mit­ting just to fix that. Nobody will be mad at you for being pre­cise. Con­sider the extreme sit­u­a­tion in which, after months and months, you may want to remem­ber “What was the revi­sion where I fixed that typo in that debug string?”. If you ded­i­cated one signle com­mit for the actual finite log­i­cal unit of cor­rect­ing the typo, you can just scroll back your changelog and find it. But what often hap­pens, is that peo­ple will be doing some­thing else, and, while doing that some­thing else, will notice the type, and cor­rect it, and basi­cally merge that cor­rec­tion with the rest of the com­mit, mak­ing that thing los­ing vis­i­bil­ity. To make it sim­ple: your SVN com­ments shouldn’t explain that you did more than one thing. If your SVN com­ment looks like “Fix­ing bugs #1234 and #1235″ or “Fix­ing bug #4321 and cor­rect­ing typo in debug sting” then you should’ve used two commits.

  3. Be pre­cise and exhaus­tive in your com­mit com­ments.

    The sec­ond most annoy­ing thing ever is com­mit­ting with blank com­ments. If you’re work­ing in a team, your peer devel­op­ers will be frus­trated about it and pos­si­bly mad at you, or will label you in a bad way; pos­si­bly pub­licly humil­i­ate you. If you’re work­ing alone, you will expe­ri­ence what you’re hypo­thet­i­cal devel­op­ment com­pan­ions would have: frus­tra­tion in not being able to eas­ily track down what a cer­tain com­mit did. Com­ments in com­mits are impor­tant. Please be pre­cise and explain in detail every­thing you did. In the opti­mal case, I shouldn’t need to read your code.

  4. Never ever break the trunk.

    This is prob­a­bly the most annoy­ing thing when deal­ing with peo­ple who can’t use ver­sion­ing. Break­ing the trunk is an habit that will quickly earn you the hatred of your col­leagues. Think about it: if you com­mit a patch that breaks the trunk, and then I check it out, what am I going to do? The project won’t build so I either have to fix it, or come to your desk and com­plain to you. In both cases I’m wast­ing some time. And con­sider the first case again: what should I do after fix­ing your bro­ken code? Com­mit it? Send­ing you a diff? If I’ll com­mit, chances are that you’ll have con­flicts when you check­out, and you’ll have to waste time in resolv­ing them. Maybe send­ing you a patch would be the best way, but still it’s a waste of time for the both of us. So the thing is: before com­mit­ting, ALWAYS dou­ble check! Make a clean build and make sure that it builds. And don’t for­get to add files! It’s a very com­mon mis­take: com­mit­ting good code, but for­get­ting to add a file. You won’t real­ize, because the thing builds, but when I’ll check­out, I’ll have trou­bles, because of miss­ing file(s). If you’re using Darcs, just make a “darcs get” in a new direc­tory, and then build.

  5. Branch only if needed.

    There are some ways to han­dle branches, but here’s my favorite. The most of the work should hap­pen in the trunk, which is always sane, as stated by the pre­vi­ous prac­tice, and the patches should always be small, so that they can be reviewed very eas­ily. If you find your­self in the sit­u­a­tion of need­ing to write a large patch, then you should branch it. In that way you can have small patches that will break your branch over the time, but they can be eas­ily reviewed. After the process is com­pleted, i.e. you’ve achieved your goal of fix­ing a bug or imple­ment­ing a new fea­ture, you can test the branch thor­oughly, and then merge it to the trunk.

7 responses so far

10 advice to write good code

Dec 14 2006 Published by Salvatore Iovene under Software

Hav­ing been cod­ing for 16 years now (I started quite young), I have seen a lot of bad code. Code is not good just because it works. So here’s a quick list of 10 advice that you’d bet­ter keep in mind while coding.

  1. Don’t sac­ri­fice code main­tain­abil­ity to per­for­mance, unless it’s strictly nec­es­sary.

    This hap­pens very often. You have to con­sider that your code is likely to be read by many per­sons, and some of them will read it after you might have parted from that com­pany. Remem­ber that you won’t remem­ber what your own code does after few weeks. So always try to put things in the most read­able and obvi­ous form, even if this will require writ­ing more lines of code, or hav­ing less per­form­ing code. Of course this is not so impor­tant if per­for­mance is your num­ber one issue. Try, for instance, to avoid use of the ?: oper­a­tor in C/C++. Every­body will under­stand it any­way, but a good old if state­ment will do it, so why not going for it?

  2. Be pre­cise as a Swiss clock, when it comes to nam­ing con­ven­tions.

    Nobody wants to read class names or vari­able names that look like gib­ber­ish. Don’t be mean on the key­board: when you type, remem­ber that some­body else will have to read it, so be extensive.

    1. Name your vari­able NumberOfItems rather than items_n. Don’t use cryp­tic pre­fixes to class name. Name your class ClientMessageOperationsBasicFunctor rather than CMOpFunctor. It’s a lot more typ­ing for you, but a lot less has­sle read­ing for the ones that will come after you.

    2. Don’t change your con­ven­tions. If you’re call­ing the iter­a­tors i, don’t call any of them n, ever. You will induce con­fu­sion to your reader. It doesn’t seem as impor­tant as it actu­ally is. If you call a class ClientMessageBlockContact, then do not have ServerMessageContactBlock. Be per­fect, be pre­cise, be obsessed.

  3. Use a good and con­sis­tent inden­ta­tion style.

    Never ever have more than one blank line. Don’t have trail­ing spaces at the end of the lines. Don’t have blank spaces or TAB char­ac­ters in blank lines. A blank line must be blank, that is.Be con­sis­tent: don’t use TABs to indent in one file, and spaces in another one. Pos­si­bly, use 8-chars wide TABs to indent. If you find your­self going beyond 80 rows too often, then that could be an indi­ca­tion that there might be some design flaws in your pro­gram. Tweak your edi­tor to show you the end-of-line char­ac­ter and the TABs.

  4. One class, one file.

    Don’t write files like ServerMessages.h where you write all the class that are ServerMessages. One class goes in one file. If you find your­self think­ing that you can’t do it, review your design.

  5. In C/C++, project includes use “”, depen­dency includes use <>.

    If you’re includ­ing a file that’s local to your project, use #include "file.h"; if it’s an exter­nal depen­dency, do #include <file.h>. Why? I’ve seen peo­ple includ­ing <file.h> and then just put things like /usr/includes/my_project in the inclu­sions search path, so that nobody will be able to com­pile before installing. That’s a bad assump­tion. And you don’t want to end up in that error.

  6. Always com­pile with -ansi -pedantic -Wall -Werror flags (or sim­i­lar, accord­ing to your com­piler).

    Let’s adhere to stan­dards. Let’s avoid warn­ings. A warn­ing might become an error in the future.

  7. Use TODOs and FIXMEs.

    If you know that you, or some­body else, will have to return on a cer­tain piece of code to add or mod­ify some func­tion­al­ity, please mark it with a TODO. If you know that a piece of code is buggy but you can’t fix it right now, add a FIXME marker. Later on, it will be easy to grep the source tree for TODOs and FIXMEs and ana­lyze them, espe­cially if they’re very well commented.

  8. Com­ment your own code.

    Seri­ously: you’re going to for­get, sooner than you think. Just invest 5% of your time in writ­ing com­mented code. Never assume that code is self-explanatory, just write a cou­ple of lines for every­thing you do. Com­ments are not only meant to gen­er­ate doxy­gen doc­u­men­ta­tion. You have to assume that some­body else will read your code and need to modify/extend it.

  9. Use a ver­sion­ing sys­tem even if you’re work­ing alone.

    Yes, ver­sion­ing is not just for work­ing in a team. Use Darcs or SVN even if you’re work­ing alone: you won’t regret it.Commit often and try to be pro­fes­sional all the time. Later on some­body else might join you. Or then you might find use­ful to revert to pre­vi­ous ver­sions of your pro­gram. And it will help you to keep trace of what you’re doing.

  10. Use a bug track­ing sys­tem even if you’re work­ing alone.

    Things like Bugzilla are EXTREMELY use­ful. Usu­ally you will for­get bout a bug after less than 2 days. Every­time you find a bug, either fix it imme­di­ately, or mark it to your per­sonal bugzilla. And always fix bugs first, and then write new code.

Com­mon errors:

  • It com­piles, so it works.
  • It works here, so it works everywhere.
  • Com­ment­ing? We don’t have time to waste, we gotta ship!
  • UML dia­grams are useless.
  • Plan code so that we can reuse it is use­less: we’ll end up writ­ing every­thing from scratch anyway.
  • Unit tests are a waste of time.


5 responses so far