(Web) Standards actually do matter a lot

Jan 17 2007 Published by Salvatore Iovene under Software

A week ago I stum­bled upon this arti­cle from Stu­art Brown, which actu­ally even got a fair amount of Diggs. As soon as I read it, I felt obliged to reply exten­sively to it, as I think it mostly rep­re­sent every­thing which is wrong in the cur­rent web design trends (or should I say all time web design trends?).

Some­thing that really annoyed me about the arti­cle, was the lack of seri­ous points and the abun­dance of use­less words like “some stan­dards evan­ge­list”, “Obsess­ing over seman­ti­cally cor­rect markup”, “a few stan­dards zealots”, “zealotry accom­plishes noth­ing but a col­lec­tion of smug faces and a col­lec­tion of ‘XHTML 1.1 Com­pli­ant’ bylines”. Those were only fruit­less diver­sions and not real arguments.

The authors gets one thing right, though, and it’s that

your users don’t care about XHTML, they care about how your site appears.

Alright, we all can agree that most of the aver­age Inter­net users com­pletely ignore every­thing about words like HTML, CSS, JavaScript, PHP and so on. We can’t, at these point blame the users: I don’t know any­thing about the inner work­ings of most of the things I use on a dally basis myself, so no big deal. In spite of this, serv­ing the user is not quite equiv­a­lent to fool­ing him. Giv­ing the user some­thing that actu­ally works, but whose inner work­ings are totally crip­pled, is absolutely wrong. The author of the men­tioned arti­cle fur­ther­more says:

If you can sat­isfy the usabil­ity needs of 100% of your users, yet your code doesn’t val­i­date, then arguably you need do no more.

I’m really strong about my dis­agree­ment here. Val­i­da­tion serves a pur­pose: that is to min­i­mize dif­fer­ences when ren­der­ing the web­site in dif­fer­ent browsers. A well val­i­dated page doesn’t need any guess-based cor­rec­tion by the browser. And Stu­art talks about usabil­ity, whereas a web­site that doesn’t val­i­date will have a harder time in meet­ing usabil­ity require­ments for impaired per­sons. On Feb­ru­ary 2006 there was a story about Tar­get (a retailer), being sued because its pages were unac­ces­si­ble by visu­ally impaired users. The retailer was accused of vio­lat­ing the Cal­i­for­nia Unruh Civil Rights Act, the Cal­i­for­nia Dis­abled Per­sons Act and the Amer­i­cans with Dis­abil­i­ties Act. Need­less to say, the web­site still doesn’t val­i­date (it doesn’t even have a DOCTYPE).

So, why else stan­dards (and espe­cially web stan­dards) are needed?

  1. Stan­dards make it eas­ier for your browsers to ren­der the pages.

    HTML or CSS are, in a way, stan­dards. I.e. a set of rule, meant as a markup lan­guage spec­i­fi­ca­tion, to be fol­lowed in order to design a web page. On top of these spec­i­fi­ca­tions, peo­ple who write browsers have done their work. Unfor­tu­nately, though, not all devel­op­ers are able to, or care to, be strict regard­ing stan­dards. That means that the browsers must have a way to cor­rectly inter­pret some code even though it’s fun­da­men­tally incor­rect. What’s the result of this? Browsers devel­op­ers have to waste time into tak­ing care of cor­rect­ing the mis­takes of web devel­op­ers. This, in turn, gives web devel­op­ers the chance to relax and write worse and worse code. And this makes browsers devel­op­ers’ life worse, and their work slower. In the end the users get noth­ing but worse and worse products.

  2. Stan­dards make life eas­ier for users.

    We can take this off the Web Stan­dards exam­ples, and move to some “real life” cases. Iron­i­cally enough, the other day I was star­ing at my toi­let seat for a while, and noticed that the holes in the toi­let in which you can screw your seat in, are at a fixed dis­tance, and just slightly larger than longer, so to give a lit­tle mar­gin: i.e. if you want to buy a new toi­let seat, the dis­tance between the screws with which you attach it to the toi­let must be between X and X+1 cm. So, when I went to the shop to get a new toi­let seat, I didn’t have to worry about the size. Ven­dors of toi­lets and ven­dors of seat had just agreed on a stan­dard size. The result? No has­sle for the user (me).

  3. Search engines like standards.

    Search engines don’t like find­ing errors. If they have trou­ble pars­ing your pages, they may not get to your care­fully cho­sen key­words, won’t be able to find all those tightly focused meta tags. Your site will be crip­pled on any search engine results page. This is not good. A well designed web­site cre­ates a clear chan­nel, a road map, for search engines, so they know to go exactly where you want them to go and see exactly what you want them to see.

End of the list? Yes. This is all that mat­ters, in the end, to the final user. He doesn’t care how, but in the end he gets bet­ter prod­ucts. Of course there are lots of side effects, e.g.:

  • Stan­dards min­i­mize the dif­fer­ences in the way your pages appear in dif­fer­ent browsers.
  • Stan­dards improve the qual­ity of your code, hence the qual­ity of your product.
  • Code that adheres to stan­dards is eas­ier to maintain.
  • Val­i­dat­ing your code dur­ing the devel­op­ment process eases the dis­cov­ery of flaws and mistakes.
  • Stan­dards increase your value.

Before any­one could say that nobody needs a new arti­cle about web stan­dards, let me remind you that the fol­low­ing web­sites won’t validate:

This means that the standards-aware devel­oper are just a tiny minor­ity. The rest, obvi­ously, don’t think that qual­ity is a good asset for their web­sites. Writ­ing non-validating code is a big step back­wards, on the path of perfection.

Bib­li­og­ra­phy

One response so far

How to write robust code

Jan 13 2007 Published by Salvatore Iovene under Software

As soft­ware is one of the most impor­tant issues in our era, writ­ing good robust pro­grams is essen­tial. This arti­cle is an in-depth essay focused on Object Ori­ented soft­ware and large projects. Every­thing said here, though, scales well to good direc­tives for small projects as well.

Our time is dom­i­nated by soft­ware. There is basi­cally soft­ware every­where around us; most of the object you can see right now around you, have some­thing to do with soft­ware, prob­a­bly because they were cre­ated using some sort of machine. Given the impor­tance of soft­ware nowa­days, I just have to find bugs unac­cept­able. Of course you might argue that a small and rare bug is a minor soft­ware won’t harm any­one, and is not nearly as impor­tant as a bug that could affect the soft­ware of an air­plane, and I’m going to agree with that. But as time goes by, every­thing has to be going towards per­fec­tion, and cur­rent trends about soft­ware seem to be going nowhere: there were bugs in soft­ware 30 years ago, and there are today. There was a time, in the begin­ning, where sci­en­tists thought that it would be rel­a­tively easy to write bug free pro­grams right away, but then they real­ized pretty soon that it wasn’t quite so. After all, soft­ware is writ­ten by us human beings, and we are doomed to make mis­takes or omis­sions. The point of this arti­cle is not that soft­ware should be always bug free, but that we, coders, should always get them to the min­i­mum, and here I’m going to present some ways to deal with pro­gram­ming in general.

One huge prob­lem, as I’ve faced quite often, is that as a pro­gram grows in size and depen­den­cies, its devel­op­ers start los­ing trace of its com­po­nents, get fur­ther away from the big pic­ture, and ease the intro­duc­tion of bugs. Note, I’m not talk­ing here about bugs caused by a sin­gle human error that can be labeled as a cheap error by any­one who would look at the code. I’m talk­ing about the sort of nasty bugs that nobody can spot right away with a glance at the code. I’m talk­ing about sys­tem wide bugs, usu­ally emerg­ing as a result of hardly related sub­sys­tems of the pro­gram. Usu­ally con­nec­tions between depen­den­cies and libraries.

Any­way, the path to write bug free code, is the one you step when you write robust code. What do I mean by that? Robust code has some features:

  • Well designed
  • Neat and tidy
  • Well named
  • Well com­mented
  • Well tested
  • It never segfaults

As a result of some of these, robust code is also:

  • Exsten­si­ble
  • Reusable
  • Last­ing in time

Well designed.

Hav­ing already talked about this some­where else, I’ll be brief on this sec­tion. Writ­ing a com­plex pro­gram, a pro­gram made of hun­dreds of thou­sands lines of code, is a damn com­pli­cated thing: it takes many peo­ple and a lot of time. Usu­ally, the more peo­ple you involve in the project, the less robust code you’ll get in the end. Peo­ple will use dif­fer­ent con­ven­tions and dif­fer­ent styles. For this rea­son, not only it’s cru­cial to hire the right devel­op­ers, but it’s essen­tial to have a very strict and detailed spec­i­fi­ca­tion of the project. Pro­gram­ming is a cre­ative work, no doubt, and coders need to have free­dom so they can breathe. A con­strained coder is a chained coder, hence a dead coder and a threat to the qual­ity of the end prod­uct. But, in spite of how much we care for the free­dom and open­ness of ini­tia­tive from the devel­op­ers, we have to be aware that loos­ing con­trol means low­er­ing the qual­ity. A large project must be designed thor­oughly and care­fully, in every sin­gle details. Even though pro­gram­mers love free­dom, most of them also love exhaus­tive doc­u­men­ta­tion. If you want to make a good coder happy, and get the best out of him, flood him with docs and specs. Noth­ing pisses off the good coder as the lack of doc­u­men­ta­tion: it tears his moti­va­tion apart. “Why should I start to read their minds and run by guesses” — he thinks, “when they didn’t even get the time to write good specs?”. Fur­ther­more, a project with­out good specs looks super­fi­cial, des­tined to fail­ure and with­out a future. A very good coder is hardly going to stay in a com­pany that doesn’t make good design for the projects. He will think that it’s a loser com­pany, and start look­ing around.

But what does good design mean? A good design is:

  • Exhaus­tive
  • Non redun­dant
  • Non con­tra­dic­tory
  • Easy to understand
  • Related 1:1 to the implementation

We want to cover every pos­si­ble out­come in our spec­i­fi­ca­tion, let be them exhaus­tive so that noth­ing will be left to case. We don’t want to repeat the same infor­ma­tion more than once, and be redun­dant for sev­eral rea­sons, e.g. infor­ma­tion should be retriev­able in exactly one place, and it would ease up con­tra­dic­tions. Doc­u­men­ta­tion should be for the devel­op­ers, i.e. writ­ten in the most straight­for­ward way for the right audi­ence: sim­plic­ity of lan­guage and straight­for­ward­ness of tables and schemes will spare some curses from the devel­op­ers. Fur­ther­more, as a spec­i­fi­ca­tion is just a way to put a pro­gram in words before it’s writ­ten, devel­op­ers should be eas­ily able to trans­late what they see on paper to code. Think about a shop­ping list: when I get one, I just go to the shop and take care of trans­lat­ing each item on the list to a phys­i­cal item in my shop­ping cart. Direct and easy.

Neat and tidy

A good def­i­n­i­tion of neat is: in a pleas­ingly orderly and clean con­di­tion. How does that apply to soft­ware? What is neat soft­ware? One nice word that I like in that def­i­n­i­tion is “pleas­ingly”. Neat soft­ware pleases the eye and the mind. Don’t want to be cocky here, but neat soft­ware is some­thing writ­ten by a good pro­gram­mer, and will be appre­ci­ated by another good pro­gram­mer. If some­body known as a good pro­gram­mer points at some soft­ware and says “That’s neat” and you find your­self look­ing at it and reply­ing “Huh? That’s just code”, I’m sorry but chances are that you are not a good pro­gram­mer. A good pro­gram­mer appre­ci­ates the beauty of some code, both on a small scale and on a large scale. Neat­ness of soft­ware on a small scale means that you’re able to look at one func­tion and appre­ci­ate the sim­plic­ity of it. Neat pieces of code are eas­ily read­able and use good name con­ven­tions. Please read this arti­cle if you want to know more about good code on a small scale. Neat code on a larger scale, on the other hand, means neat inte­gra­tion between com­po­nents and sub­sys­tem of a project. A bad inte­gra­tion would mean, e.g., hav­ing a project-wide global vari­able that points to a cer­tain sub­sys­tem, and using it every­where in the project. Or hav­ing two sub­sys­tems that, in a messed and inter­twined way, mutu­ally call each other’s meth­ods vio­lat­ing sev­eral lay­ers of abstrac­tion. Prov­ing what neat code is, turns up to be very dif­fi­cult. It’s a bit like the oppo­site of what hap­pens with com­mon logic: if I want to prove you that, say, lions exist, I can just go to Africa, pick one and show it to you, then say “That’s a lion, ergo lions exist”. But how can I prove that uni­corns or dragon don’t exist? You prob­a­bly agree that it’s much more dif­fi­cult. It’s just the oppo­site with neat code. I can show you bad code, and you will eas­ily agree that it’s bad. But look­ing at neat code doesn’t it prove it neat right away. It takes prob­a­bly years and years of expe­ri­ence, writ­ing a lot of code and read­ing a lot.

Well named

This topic has already been dis­cussed here, but repetuta juvant. As code is man­aged by pos­si­bly dozens or more peo­ple, being under­stood is an impor­tant key to increase robust­ness of the code. Writ­ing robust code also means writ­ing code that will eas­ily stay robust when other peo­ple will mod­ify of expand it, unless they have no clue, of course. The most your code is under­stood by oth­ers, the most likely they will not break your ideas, and keep the code robust. There are sev­eral ways of mak­ing own code eas­ily under­stood, and hav­ing a good, con­sis­tent and solid nam­ing con­ven­tion is one of them. Of course, as dis­cussed later, code needs to be well doc­u­mented also.

Well com­mented

I know, I know. Every­body says that you should com­ment your code. That’s what I say and that’s what I’ve been told. Still I’m now com­ment my own code enough as I should. Before you can then tell me “Who are you, then, to tell me to com­ment my code, if you don’t do it enough with yours?” let me remind you that we learn from mis­takes. What they don’t tell you about the impor­tance of com­ment­ing code, is some sub­tle and psy­cho­log­i­cal lit­tle thing. If you are a bad pro­gram­mer, you’ll never pro­duce good code. But if you are a good pro­gram­mer, some­times being in a hurry will make you pro­duce really bad code. There are two rea­sons why this can hap­pen: 1) you are in a hurry because you’re late with your dead­lines. With this, there’s noth­ing to do. 2) you are in a hurry because you’re just cod­ing fast, on the rush of some ideas that flashed you. In this case, com­ment­ing your code a lot will improve dras­ti­cally the qual­ity of your code. Always write your com­ments before writ­ing the actual code. This will make you real­ize it, if your func­tion is not really going to do what it’s sup­posed to do. Writ­ing the com­ment will also help you think more about what you’re doing, and being more con­scious about it. It will keep your state of mind clear and pre­cise. I strongly rec­om­mend using Doxy­gen to gen­er­ate a browseable HTML ver­sion of your com­ments, espe­cially if you’re writ­ing a library. Oth­er­wise, it’s still going to keep you on a pro­fes­sional line, which is always a good thing.

Well tested

Write and use unit tests. If your code is well designed, there are good chances that each func­tion in your code, or each class, per­forms a spe­cific task in a cer­tain way, and noth­ing more. Given a cer­tain input, it will reli­ably return the same out­put. Right? You have to make sure of that, by writ­ing test cases. Test­ing the small­est units of your pro­gram doesn’t ensure that the whole is work­ing per­fectly, but helps. Pos­si­bly, append a hook to your Source Code Ver­sion­ing Sys­tem (SVN? Darcs?) so that the auto­matic test­ing suite will run auto­mat­i­cally on the server that hosts your repos­i­tory, before it accepts your patch. This is quite easy with Darcs.

It never segfaults

Of course this point applies to the lan­guages that allow seg­men­ta­tion fault, or Null­Point­erEx­cep­tion (in Java). It’s easy to get: if your code seg­faults, there are no excuses. No mat­ter how stu­pid the pro­vided input was, your pro­gram should not seg­fault. A good prac­tice, is that each and every function/method would check it’s argu­ment before doing any­thing. A solid excep­tion han­dling struc­ture is required. Again, you can object that I’m not really say­ing any­thing use­ful here: “Of course pro­grams shouldn’t seg­fault, I knew it!”, but think about it: it’s a mat­ter of atti­tude. You want to write a per­fect pro­gram, and there are some things you have to keep in mind. Be para­noid with seg­faults will implic­itly and secretly improve the gen­eral qual­ity of your code, with­out you even noticing.

Con­clu­sion

Writ­ing per­fect code is impos­si­ble. Espe­cially as the code grows in size and num­ber of pro­gram­mers. Achiev­ing the impos­si­ble, then, is beyond any good inten­tioned coder. What we can do, though, is just try to have the right atti­tude, which is about pre­ci­sion, care and, some­times, para­noia. Writ­ing com­plex pro­grams is not an easy thing, and, as such, should be han­dled with extreme care.

One response 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

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