Tagged: software

Developers Conference 2013

The Developers Conference took place in Brno this past weekend (February 23rd, 24th). The #devconf is an annual event organised by the Red Hat office in Brno with the members of the Fedora and JBoss.org communities. The convention targets primarily Linux and JBoss developers and admins and it covers a range of topics from the free software universe.

This year, there were three main tracks, one of which was focused primarily on JBoss and the remaining two on Linux-related topics, such as kernel, networking, security or virtualization/cloud technologies. Apart from that, the conference hosted a number of hackfests and lab sessions for people who wanted to learn something more practical, or have a more focused discussion on a certain topic.

Bryn M. Reeves talking at the Developers Conference

Bryn M. Reeves talking at the Developers Conference

I was there this year and it was amazing. According to the numbers posted to Twitter, the conference had at least 500 attendees on Saturday. There were so many great talks and the organisers had to even turn down presenters, only because there was no room for more. Actually, I don’t think that three tracks will be enough next year.

Saturday

I didn’t get up very early, so for me, Saturday started with a talk from Debarshi Ray about the Gnome Online Accounts. Debarshi talked about how the new Gnome 3.8 integrates with various online services, such as Google Docs/Mail, Facebook, Flickr, ownCloud and others. The integration is a very promising area in my opinion, because these services are used by millions of people. However, there are still some problems that need to be addressed and that are being worked on.

The track in the D3 room continued with Tom Callaway‘s talk on Fedora User Experience. Tom explained the design driven methodology; that we should think about the user experience, before we code. However, the community around Fedora has been focused on the contributors, which are quite often technical people who like to code first. He presented several mockups they have been working on. The first one is a sort-of a rich web interface for mailing lists called Hyperkitty. The goal of this project is to improve the collaboration in communities. At the moment, there are two groups of users, one preferring mailing lists, the second discussion boards.  People from these two group tend to miss each other. Hyperkitty should also provide a karma functionality, to help decrease the pollution of big mailing lists from chronically non-constructive people wasting everyone’s time with pointless discussions.

Hyperkitty

Hyperkitty Design (source: http://blog.linuxgrrl.com/)

The third presentation I saw, again in the D3 room was Negotiation theory for Open Source Hackers by Leslie Hawthorn. This was one of the less technical talks, but it was very insightful. Arguing takes up a fair amount of the time and effort technical people put into their work, especially in open source, and it is not always time well spent. The slides from this presentation are available here.

After Leslie’s talk, we moved to the kernel track in D1 to see Lukáš Czerner speak about what is happening in the local Linux Kernel File Systems. Lukáš summarized the new features from XFS (being the most suitable option for enterprise workloads), ext4 (great for general-purpose), and btrfs (still not stable). Based on the comparison of the number of commits made during the last year, the most active development is going on in btrfs. Its codebase also grows steadily while XFS have lost some weight during the last few years as its developers try to remove unnecessary things. He also discussed the challenges file system developers will need to deal with in the future. The rules of the game don’t change that much with SSD’s, but PCI-based solid-state drives can be problematic, as the current block layer doesn’t scale that well to storage technologies that fast. Similar increase of speed has already happened in networking, so the future development might be inspired by some ideas from that area.

After the file systems update, it was time for my talk about the Linux Network Stack Test project. LNST is a network testing tool designed to simplify testing of real-life scenarios with more than one computer involved. It provides some building blocks for test development and it also serves as a test management tool that will handle proper execution of your test cases. The tests created using LNST are then entirely automated and also completely independent from the underlying network infrastructure, so they can be migrated to a different network without any changes whatsoever. This is important when you want to share them with others.

Slides: You can download the slides I used for the LNST presentation here.

I took a short break from the presentations after that and I returned to see Daniel Borkmann with his presentation about the zero-copy packet capturing and netsniff-ng. At this point, I started to get really tired, so I certainly didn’t catch everything here. And finally, the kernel track was closed by three lighting talks by Jiří Benc on PTP, Jiří Pírko who gave us an update about what happened in the team driver, and Zdeněk Kabeláč who closed the room with his talk about LVM2.

If you came early enough to get a keyring at the entrance to the venue, you were in possession of a ticket to the after party, which took place approximately half an hour later at Fléda. The party was, just as the conference itself, awesome. There was beer and food for free, a live band, and most importantly hundreds of like-minded people and colleagues from Red Hat to talk to about Linux :).

Sunday

Sunday was again crammed with amazing talks. This time, I made sure not to oversleep (even though getting up after the party wasn’t easy at all). The very first talk in the morning in D3 was Evolution of Linux Network Management from Pavel Šimerda. Pavlix talked about the NetworkManager project, the things they improved in the 0.9.8 release (which happened just a few days prior to the conference).  He explained what they focus on at the moment. NetworkManager is going from desktops to servers and it should be used as the primary way of network configuration in Fedora and also in RHEL. This requires revising various things inside the NetworkManager and also implementing additional functionality, that is required in the enterprise area. Networking is absolutely crucial on servers, so they plan to test the code very carefully using multiple different methods (one of them might be a set of real-life test scenarios using LNST).

Thomas Wöerner continued the networking track in D3 with his presentation of firewalld, a dynamic firewall daemon that provides dynamic functionality over the static iptables. The daemon supports network zones, which represent the levels of trust for network connections. These might be public, home, work, etc. Firewalld also supports working with rules grouped into services, which are basically lists of ports that are required for some service to work. This way, you can handle all the rules in a group at the same time.

The last networking talk in D3 before the Core OS track was given by Thomas Graf. The presentation was focused on Open vSwitch, which is a software implementation of a switch similar to the Linux bridge. However, Open vSwitch is focused more towards the enterprise market. It is designed for virtualized server environments, so it comes with support of things, such as OpenFlow and VLAN tagging.

Preparations for What are we breaking now?

Preparations for What are we breaking now?

Probably the most crowded presentation at the Developers Conference was What are we breaking now? delivered by Kay Sievers and Lennart Poettering. They discussed several topics that (in their opinion) need fixing. The first one were persistent network interface names. This has been a problem for a long time, because the kernel names devices as it finds them and the order can change with every other boot. The plan is to use names based on some properties of the hardware, such as the position of the card on the bus, instead of just numbering them as they are recognised. Other than that, they would like to implement D-BUS in the kernel. There has been a couple of tries at this in the past, but they all failed. I personally liked the plan they mentioned next to modify the bootloader (GRUB2) and the kernelinstall script to work with drop-in config files when a new kernel is installed rather than with a convoluted set of self-replicating scripts. Finally, they mentioned app sandboxes that should provide some protection for the user from the actions of a potentially malicious third-party applications.

The Core OS track continued after a short break with a great talk from Bryn M. Reeves called Who moved my /usr?? – staying sane in a changing world. This talk was again a little bit lighter on the technical details, but as the last year’s presentation from Bryn, it was not only interesting, but very entertaining as well. The talk was focused on change. Bryn went through the historic releases of Red Hat Linux and described what happened where, and how did the users react.

I didn’t actually hear the whole talk that went after the previous one in D3, because my stomach was getting pretty unhappy at that time and I went down to get that extremely big hot dog. The leader of the SELinux project, Dan Walsh talked about and also demonstrated the creation of hundreds of secure application containers with virt-sandbox. The containers are much cheaper than virtualization, but they can provide the same amount of security.

Lennart Poettring had a one more talk in the Core OS track called Systemd Journal. This one was an introduction of the logging facility that will be a part of systemd. He explained the motivation, why they decided to go down this path and what are (in his opinion) the benefits of journald. In the second part of the presentation, Lennart did a small demonstration of what can be done with the journalctl tool for reading logs.

The very last talk I attended at this year’s Developers Confefence was the Log Message Processing, Formatting and Normalizing with Rsyslog from the main author of the rsyslog project Rainer Gerhards, but I was getting really tired and sleepy again, so unfortunately I wasn’t listening that carefully.

Summary

Long story short, this year’s #devconf was awesome! Lots of interesting talks, labs, and hackfests. If you missed a talk this year, the good news is, that all the presentations from the three main rooms were recorded. The videos should be soon available online.

Big thanks goes to the main organisers, Radek Vokál and Jiří Eischmann, for making this possible, but also to the many volunteers that were involved in the organising and making sure everything went as planned. For me, the organisation was flawless, as I personally didn’t encounter any difficulties. Man, I’m already looking forward to 2014. See you everyone next year!

If you liked this post, make sure you subscribe to receive notifications about new content on this site by email or a RSS feed.
Alternatively, feel free to follow me on Twitter or Google+.

Brief GDB Basics

In this post I would like to go through some of the very basic cases in which gdb can come in handy. I’ve seen people avoid using gdb, saying it is a CLI tool and therefore it would be hard to use. Instead, they opted for this:

std::cout << "qwewtrer" << std::endl;
DEBUG("stupid segfault already?");

That’s just stupid. In fact, printing a back trace in gdb is as easy as writing two letters. I don’t appreciate lengthy debugging sessions that much either, but it’s something you simply cannot avoid in software development. What you can do to speed things up is to know the right tools and to be able to use them efficiently. One of them is GNU debugger.

Example program

All the examples in the text will be referring to the following short piece of code. I have it stored as segfault.c and it’s basically a program that calls a function which results in segmentation fault. The code looks like this:

/* Just a segfault within a function. */

#include <stdio.h>
#include <unistd.h>

void segfault(void)
{
	int *null = NULL;
	*null = 0;
}

int main(void)
{
	printf("PID: %d\n", getpid());
	fflush(stdout);

	segfault();

	return 0;
}

Debugging symbols

One more thing, before we proceed to gdb itself. Well, two actually. In order to get anything more than a bunch of hex addresses you need to compile your binary without stripping symbols and with debug info included. Let me explain.

Symbols (in this case) can be thought of simply variable and function names. You can strip them from your binary either during compilation/linking (by passing -s argument to gcc) or later with strip(1) utility from binutils. People do this, because it can significantly reduce size of the resulting object file. Let’s see how it works exactly. First, compile the code with striping the symbols:

[astro@desktop ~/MyBook/code]$ gcc -s segfault.c

Now let’s fire up gdb:

[astro@desktop ~/MyBook/code]$ gdb ./a.out
GNU gdb (GDB) Fedora (7.3.1-48.fc15)
Reading symbols from /mnt/MyBook/code/a.out...(no debugging symbols found)...done.

Notice the last line of the output. gdb is complaining that it didn’t find any debuging symbols. Now, let’s try to run the program and display stack trace after it crashes:

(gdb) run
Starting program: /mnt/MyBook/code/a.out 
PID: 21568

Program received signal SIGSEGV, Segmentation fault.
0x08048454 in ?? ()
(gdb) bt
#0  0x08048454 in ?? ()
#1  0x0804848d in ?? ()
#2  0x4ee4a3f3 in __libc_start_main (main=0x804845c, argc=1, ubp_av=0xbffff1a4, init=0x80484a0, fini=0x8048510, 
    rtld_fini=0x4ee1dfc0 , stack_end=0xbffff19c) at libc-start.c:226
#3  0x080483b1 in ?? ()

You can imagine, that this won’t help you very much with the debugging. Now let’s see what happens when the code is compiled with symbols, but without the debuginfo.

[astro@desktop ~/MyBook/code]$ gcc segfault.c 
[astro@desktop ~/MyBook/code]$ gdb ./a.out 
GNU gdb (GDB) Fedora (7.3.1-48.fc15)
Reading symbols from /mnt/MyBook/code/a.out...(no debugging symbols found)...done.
(gdb) run
Starting program: /mnt/MyBook/code/a.out 
PID: 21765

Program received signal SIGSEGV, Segmentation fault.
0x08048454 in segfault ()
(gdb) bt
#0  0x08048454 in segfault ()
#1  0x0804848d in main ()

As you can see, gdb still complains about the symbols in the beginning, but the results are much better. The program crashed when it was executing segfault() function, so we can start looking for any problems from there. Now let’s see what we get when debuginfo get’s compiled in.

[astro@desktop ~/MyBook/code]$ gcc -g segfault.c 
[astro@desktop ~/MyBook/code]$ gdb ./a.out 
GNU gdb (GDB) Fedora (7.3.1-48.fc15)
Reading symbols from /mnt/MyBook/code/a.out...done.
(gdb) run
Starting program: /mnt/MyBook/code/a.out 
PID: 21934

Program received signal SIGSEGV, Segmentation fault.
0x08048454 in segfault () at segfault.c:9
9		*null = 0;

That’s more like it! gdb printed the exact line from the code that caused the program to crash! That means, every time you try to use gdb to get some useful directions for debugging, make sure, that you don’t strip symbols and have debuginfo available!

Start, Stop, Interrupt, Continue

These are the basic commands to control your application’s runtime. You can start a program by writing

(gdb) run

When a program is running, you can interrupt it with the usual Ctrl-C, which will send SIGINTR to the debugged process. When the process is interrupted, you can examine it (this is described later in the post) and then either stop it completely or let it continue. To stop the execution, write

(gdb) kill

If you’d like to let your program carry on executing, use

(gdb) continue

I should point out, that in gdb, you can abbreviate most of the commands to as little as a single character. For instance r can be used for run, k for kill, c for continue and so on :).

Stack traces

Stack traces are very powerful when you need to localize the point of failure. Seeing a stack trace will point you directly to the function, that caused you program to crash. If your project is small or you keep your functions short and straight-forward, this could be all you’ll ever need from a debugger. You can display stack trace in case of a segmentation fault or generally anytime when the program is interrupted. The stack trace can be displayed by a backtrace or bt command

(gdb) bt
#0  0x08048454 in segfault () at segfault.c:9
#1  0x0804848d in main () at segfault.c:17

You see, that the program stopped (more precisely was killed by the kernel with a SIGSEGV signal) at line 9 of segfault.c file while it was executing a function segfault(). The segfault function was called directly from the main() function.

Listing source code

When the program is interrupted (and compiled it with debuginfo), you can list the code directly by using the list command. It will show the precise line of code (with some context) where the program was interrupted. This can be more convenient, because you don’t have to go back into your editor and search for the place of the crash by line numbers.

(gdb) list
4 #include 
5
6 void segfault(void)
7 {
8   int *null = NULL;
9 *null = 0;
10 }
11
12 int main(void)
13 {

We know (from the stack trace), that the program has stopped at line 9. This command will show you exactly what is going on around there.

Breakpoints

Up to this point, we only interrupted the program by sending a SIGTERM to it manually. This is not very useful in practice though. In most cases, you will want the program stop at some exact place during the execution, to be able to inspect what is going on, what values do the variables have and possibly to manually step further through the program. To achieve this, you can use breakpoints. By attaching a breakpoint to a line of code, you say that you want the debugger to interrupt every time the program wants to execute the particular line and wait for your instructions.

A breakpoint can be set by a break command (before the program is executed) like this

(gdb) break 8
Breakpoint 2 at 0x4005c0: file segfault.c, line 8.

I’m using line number to specify, where to put the break, but you can use also function name and file name. There are multiple variants of arguments to break command.

You can list the breakpoints you have set up by writing info breakpoints:

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00000000004005d8 in main at segfault.c:14
2       breakpoint     keep y   0x00000000004005c0 in segfault at segfault.c:8

To disable a break point, use disable <Num> command with the number you find in the info.

Stepping through the code

When gdb stops your application, you can resume the execution manually step-by-step through the instructions. There are several commands to help you with that. You can use the step and next commands to advance to the following line of code. However, these two commands are not entirely the same. Next will ‘jump’ over function calls and run them at once. Step, on the other hand, will allow you to descend into the function and execute it line-by-line as well. When you decide you’ve had enough of stepping, use the continue command to resume the execution uninterrupted to the next break point.

Breakpoint 1, segfault () at segfault.c:8
8		int *null = NULL;
(gdb) step
9		*null = 0;

There are multiple things you can do during the process of stepping through a running program. You can dump values of variables using the print command, even set values to variables (using set command). And this is definitely not all. Gdb is great! It really can save a lot of time and lets you focus on the important parts of software development. Think of it the next time you try to bisect errors in the program by inappropriate debug messages :-).

Sources

Magical container_of() Macro

When you begin with the kernel, and you start to look around and read the code, you will eventually come across this magical preprocessor construct. What does it do? Well, precisely what its name indicates. It takes three arguments — a pointer, type of the container, and the name of the member the pointer refers to. The macro will then expand to a new address pointing to the container which accommodates the respective member. It is indeed a particularly clever macro, but how the hell can this possibly work? Let me illustrate …

The first diagram illustrates the principle of the container_of(ptr, type, member) macro for who might find the above description too clumsy.

Illustration of how containter_of macro works

Illustration of how containter_of macro works

Bellow is the actual implementation of the macro from Linux Kernel:

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

At first glance, this might look like a whole lot of magic, but it isn’t quite so. Let’s take it step by step.

Statements in Expressions

The first thing to gain your attention might be the structure of the whole expression. The statement should return a pointer, right? But there is just some kind of weird ({}) block with two statements in it. This in fact is a GNU extension to C language called braced-group within expression. The compiler will evaluate the whole block and use the value of the last statement contained in the block. Take for instance the following code. It will print 5.

int x = ({1; 2;}) + 3;
printf("%d\n", x);

typeof()

This is a non-standard GNU C extension. It takes one argument and returns its type. Its exact semantics is throughly described in gcc documentation.

int x = 5;
typeof(x) y = 6;
printf("%d %d\n", x, y);

Zero Pointer Dereference

But what about the zero pointer dereference? Well, it’s a little pointer magic to get the type of the member. It won’t crash, because the expression itself will never be evaluated. All the compiler cares for is its type. The same situation occurs in case we ask back for the address. The compiler again doesn’t care for the value, it will simply add the offset of the member to the address of the structure, in this particular case 0, and return the new address.

struct s {
	char m1;
	char m2;
};

/* This will print 1 */
printf("%d\n", &((struct s*)0)->m2);

Also note that the following two definitions are equivalent:

typeof(((struct s *)0)->m2) c;

char c;

offsetof(st, m)

This macro will return a byte offset of a member to the beginning of the structure. It is even part of the standard library (available in stddef.h). Not in the kernel space though, as the standard C library is not present there. It is a little bit of the same 0 pointer dereference magic as we saw earlier and to avoid that modern compilers usually offer a built-in function, that implements that. Here is the messy version (from the kernel):

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

It returns an address of a member called MEMBER of a structure of type TYPE that is stored in memory from address 0 (which happens to be the offset we’re looking for).

Putting It All Together

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

When you look more closely at the original definition from the beginning of this post, you will start wondering if the first line is really good for anything. You will be right. The first line is not intrinsically important for the result of the macro, but it is there for type checking purposes. And what the second line really does? It subtracts the offset of the structure’s member from its address yielding the address of the container structure. That’s it!

After you strip all the magical operators, constructs and tricks, it is that simple :-).

References

Errors as Part of Interface

I was writing this code the other day. It’s a very small program — a POP3 client that downloads messages. And I just couldn’t come up with an easy and consistent way to report errors. I wanted something lightweight, but what actually makes sense. I was looking through some code hoping, that someone else has a good strategy I could rip. From what I saw, the most common is none whatsoever. Well, I didn’t like that one bit …

But worry no longer! Steve McConnell came to aid a coder in distress once again. I looked into my new copy of Code Complete and here’s what I found:

Throw exceptions at the right level of abstraction.

This statement has a very interesting point. The errors that can occur in your code, regardless of whether it’s a exception thrown or a status code returned, should be at the same level of abstraction of the unit, class or even routine that they happen in. For example if function called downloadAndPrintReport() exits with MALLOC_FAILED. You see, this just isn’t right. The malloc failure is the cause of the problem, it’s not the problem itself and you (or the user) cannot react appropriately. I mean, which malloc() call failed? Does it mean the report wasn’t even downloaded or it was but wasn’t printed? What the hell is malloc anyway? User doesn’t know!

Conclusion

Your error reports should be informative and useful to the receiver (which can be either a user or some parent code that deals with the error). By sticking to the current abstraction, your chances of delivering a good report rapidly grow. When downloadAndPrintReport() returns with UNABLE_TO_DOWNLOAD_REPORT, you can try to reopen the connection and try again later. In case of UNABLE_TO_PRINT_REPORT you can store it somewhere in a file instead of printing it.

UML Class Diagram

Class diagram is a very important part of UML. It’s a structure diagram and it’s purpose is to display classes in the system with all the relationships between them. In my opinion it’s the most popular type of diagram in software development.

Drawing class diagram of your design really helps to see the problem in broader terms. By writing it down you free space in your head for new ideas :-). It is also easier to understand by others when you want to discuss the problem with someone else. The thing is, I often find myself wondering about the syntax when I read someone else’s diagrams. That’s why I decided to make a little cheat sheet here to remind me.

Class

Kind of a key component in a class diagram. Classes will be shown as nodes and usually as boxes. Here is a example of one. Each class can have methods and attributes defined. The convention is shown on Figure 1.

UML diagram: A class

Figure 1: A class

Inheritance

Class inheritance is in terms of UML a relationship of generalization. It represents “is a” relationship on class level. Figure 2 shows how to portray generalization.

UML diagram: Inheritance

Figure 2: Inheritance

Realization

UML has different relationship for interfaces. When you inherit from an interface you implement it, which is in terms of UML a relationship of realization. It’s visual appearance is similar to inheritance, but the line is dashed. Also the interface class should be marked as abstract (have name written in italic). See on Figure 3.

UML diagram: Realization

Figure 3: Realization

Association

Another form of relationship in class diagram is association. It’s a object-level relationship (i.e. happens between objects of associated classes). So the whole relationship represents a family of links. There are multiple types of association with stronger policies (composition and aggregation).

UML diagram: Association

Figure 4: Association

Aggregation

Aggregation is a stronger and more specific form of association. It’s “has a” relationship. Graphical representation of aggregation is shown on Figure 5.

UML diagram: Aggregation

Figure 5: Aggregation

 Composition

Even stronger form of aggregation is composition. Instead of “has a” it represents “owns a”. It’s suited for relationship when one object can only exist as a part of another. For example if a plane has a wing it’s a composition. What would you do with a wing alone, right? The plane owns it. But when a  pond has some ducks in it it’s an aggregation. The ducks will survive without a pond (only probably not that happy). And a pond will still be a pond with or without ducks. Graphical representation of composition is virtually the same as aggregation, only the diamond is filled (see on Figure 6).

UML diagram: Composition

Figure 6: Composition

Dependency

Last type of relationship is a dependency. It’s weaker then association and it says, that a class uses another one and therefore is dependant on it. The use of dependency is appropriate for example in cases where an instance of a class is stored as a local variable inside another classes’ method. Or some static methods are used, so the classes are not associated, but one depends on the other.

UML diagram: Dependency

Figure 7: Dependency

Cheat Sheet

I did all the examples in an open-source diagram editor called Dia. I recommend it by the way. And because it’s such a wonderful editor, here’s a complete cheat sheet (if you’d like to print it).

UML Class Diagram Cheat Sheet

UML Class Diagram Cheat Sheet

Interface Segregation Principle in Software Design

ISP, not Internet Service Provider, but Interface Segregation Principle is the last of the famous principles of SOLID object-oriented software design. It was introduced by Robert C. Martin in his series of articles in 1996. Intention of this principle is to avoid creation of “fat” interfaces.

A fat (or polluted) interface comes from extending current interface with some functionality that is useful only to a subset of entities that depends on it. This phenomenon leads eventually to creation of dummy methods just to be able to use the interface. And that’s bad. Dummy methods are dangerous and also violate the LSP. The ISP as wrote the author declares that

Clients should not be forced to depend upon interfaces that they do not use.

Each interface should have clearly defined purpose and make reasonable abstraction of a part of the current problem. The best practice (in my opinion) is to use multiple inheritance when implementing the interfaces. This method will separate things that don’t logically belong together on the abstraction level and clean wrong dependencies in our code. But it also allow us to couple them back together in objects, that cover multiple things and work on the same data.

Let me show an example of how it should not look like. This is an interface for a car.

/* Bad example */
class CarOperation
{
    public:
        virtual void steer(int degrees) = 0;
        virtual void pullHandbrake() = 0;
        virtual void accelerate() = 0;

        virtual void shift(int gear) = 0;

        virtual void toggleAirConditioning() = 0;
};

There are a couple common things you can do with a car. Every car usually has a steering wheel, an acceleration pedal and possibly even a handbrake. But what about those cars with automatic transmission? They don’t allow the driver to shift gears, so what should they do with the shift method? The interface enforces it’s implementaion. And again with air conditioning. Some cars don’t have an air conditioner. The way here is to split CarOperationinterface into a couple smaller ones.

class BasicCarOperation
{
    public:
        virtual void steer(int degrees) = 0;
        virtual void pullHandbrake() = 0;
        virtual void accelerate() = 0;
};

class GearboxCarOperation
{
    public:
        virtual void shift(int gear) = 0;
};

class AirConditioningCarOperation
{
    public:
        virtual void toggleAirConditioning() = 0;
};

class AlfaRomeo166 : public BasicCarOperation, GearboxCarOperation, AirConditioningCarOperation
{
    /* Implementation of all the interfaces. */
};

class SkodaFavorit136L : public BasicCarOperation, GearboxCarOperation
{
    /* No air conditioning for old cars. */
};

The clients that will use the concrete cars won’t look at them directly as AlfaRomeo166 or SkodaFavorit136L. They will operate them through the interfaces. If some client function wants to turn on a air-conditioning it will look like this

void beCool(AirConditioningCarOperation* vehicle)
{
    vehicle->toggleAirConditioning();
}

That’s the beauty of interface segregation principle. You get exactly what you need, nothing more and nothing less, which makes the code easier to maintain, reuse and saves you from a cascade of unpredictable errors, when you decide to modify existing code.

Sources

Liskov Substitution Principle

Another principle of object-oriented software design, the L in SOLID, the Liskov Substitution Principle! But first a little background and some theory (feel free to skip right to the practical part of the post). The principle is called after Barbara Liskov, who initially introduced it in 1987. Prof. Liskov first defined it like this

What is wanted here is something like the following substitution property: If
for each object O1 of type S there is an object O2 of type T such that for all
programs P defined in terms of T, the behavior of P is unchanged when O1 is
substituted for O2 then S is a subtype of T.

This definition is a little other way around. It says (at least I read it like this), “if you can substitute each O1 with some O2, it’s safe to say, that S is a subtype of T”. But there are cases (not that rare) in which S is subtype of T, but the objects aren’t substitutable (and that’s bad). It was later rephrased and published in a paper by Barbara Liskov and Jeannette Wing in 1994. The formulation changed to

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

This is a little better. Now it says that if something works for objects of type T, it should work for objects of type S as well in case that S is a subtype of T. And that’s the Liskov Substitution Principle. Robert C. Martin later described it in one of his articles like this

Functions that use pointers or references to base
Classes must be able to use objects of derived classes
Without knowing it.

Now, that’s how most of us like our software principles, right? No weird letters or signs — straight-forward and easy to understand. I like the theory though :-). Anyway, how is this good in practice in the regular everyday coding? Let’s have a look at some examples. One of the most typical violation is Square-Rectangle class hierarchy.

One would think that having a Square class that is a subclass of Rectangle could be a good idea, right? The relationship represented Square is a Rectangle seems to work, so let’s do it.

class Rectangle
{
    int width;
    int height;

    public:
        int getWidth() { return width; }
        int getHeight() { return height; }

        virtual void setWidth(int value) { width = value; }
        virtual void setHeight(int value) { height = value; }
};

Pretty straight-forward declaration. The square is a rectangle which width and height are equal. So we redefine the set methods.

class Square : public Rectangle
{
    public:
        void setWidth(int value)
        { width = value; height = value; }
        void setHeight(int value)
        { width = value; height = value; }
};

This modification will make sure, that our square has always all sides equal. Then consider having a function like this

bool test(Rectangle &rectangle)
{
    rectangle.setWidth(2);
    rectangle.setHeight(3);

    return rectangle.getWidth() * rectangle.getHeight() == 6;
}

This function tests the interface of Rectangle. But what happens when you pass a reference to a Square to it? It will break, because of the side effect of the set methods, that keeps the Squarea square. So, where’s the problem here?

The square is a rectangle, but does not share the same behaviour. And that’s a deal-breaker when it comes to inheritance in software. The LSP clarifies that in OOD the is a relationship applies to public behavior of objects.

Bertrand Meyer also explored the topic in Design by Contract. He states

…when redefining a routine [in a derivative], you may only replace its
precondition by a weaker one, and its postcondition by a stronger one.

Preconditions are something that must be true in order to the method to execute and postconditions are always true after the method has been executed. This rule really helps me when I design something. Basically it says, that you can only reduce the set of preconditions and only extend the set of postconditions. In other words, the new routine cannot require anything more than the original one (but can require even less) and cannot yield anything less then the original one (but can also return something on top of that).

In context with the square-rectangle problem, there were no preconditions, but there was one postcondition to the setHeight() method. The postcondition assumed, that the set method for height won’t change the width (that’s a perfectly justified assumption). And this precondition was broken by the redefined routine of Square.

Inheritance is very powerful and important concept in object-oriented design. But it’s also easy to get it dead wrong. The Liskov Substitution Principle should make you thing more about the relationship, when you create one and help avoid eventual oh-moment coming your way.

Sources

Single Responsibility Principle

Single responsibility principle, or SRP is another of the SOLID guidelines for software designers. It’s especially useful in object-oriented design. The name suggests, that it will have something to do with decomposing the problem up to the point, where each entity in the system has one and only one responsibility. The principle alone states,

“There should never be more than one reason for class to change.”

Right, but where, the heck, is the responsibility we’re talking about? You see, a responsibility can be pretty hard to define and using the word directly would have definitely started a couple of fights. So the author defined it precisely as a ‘reason to change’. Let’s have a look at some example.

Here is a definition of my old MySQL class. It has interface for establishing and closing connection to a remote MySQL server and sending a query and receiving and processing the query result.

class MySQL
{
    public:
        bool connect();
        void disconnect();

        bool executeQuery(std::string queryString);
        MySQLResult* getQueryResult();
};

This class  has two reasons to change (i.e. responsibilities). It handles the initialization and closing of a connection to database server and also communication with the server (executing SQL queries). The two reasons to change are:

  • MySQL server will now accept only encrypted connections
  • The server implementation changes and it will respond differently to some queries

This violates the single responsibility principle. It would be a bad design to put together two things that change for different reasons. It might not seem that bad now, but the system will evolve and change. What now seem reasonable solution might kill you later on. The way I would now design things is this:

class MySQLConnection
{
    public:
        bool open(); /* former connect() */
        void close(); /* former disconnect() */
};

class MySQLQuery
{
    MySQLConnection* session;

    public:
        bool execute(std::string queryString);
        MySQLResult* getResult();
};

While SRP is fairly simple principle, it’s pretty hard to get it right. Putting responsibilities together is something that comes naturally to us and the separation (e.g. splitting the class into several smaller ones) might not seem as elegant at first. When I look back at some of my earlier designs, well, to be honest, I rarely stumble upon a class that conforms to this principle. When I look again, I can really see, how would the separation help reduce the complexity of the design and made my code easier to read and understand.

Following this principle religiously is definitely not a good idea, but it’s good to know it’s there and sometimes (especially, when you see a 500 lines in my_class.h) think, ‘Hey, would splitting my class to a couple more help?’. Usually it does :-P.

Sources

The ‘Oh’ Moment

There’s a little thing in software development I like to call the ‘Oh moment‘. I first noticed it when I was working on my bachelor’s thesis (and I was getting those all the time). Let me explain the situation a bit. You’re working on a project, not particularly easy one and finally after a couple of sleepless nights and rather unspecified amount of coffee, you come up with a solution. It seems just perfect. Clean, elegant, looks cool due to all the fancy inheritance, Mum will be proud.

Then first thing tomorrow morning, you start to eagerly write the code. It’s all good until it comes, ‘Oh, man’. One more thing (there always is) that you didn’t take into account and it just won’t work this way. It might work eventually, after some further modifications, but the result won’t be nearly as elegant nor clean. Not even mentioning the sweet inheritance tree. And there goes your excitement. After experiencing an oh-moment, your goal is no longer to create a good piece of software, but to get it done as fast as you can and then run away from it as far as possible.

The excitement from your ideas, good feeling about your work and satisfaction with the results is, in my opinion a key component in software development. Everybody likes doing a good job. And it’s really bad (for you and the project), if you don’t find the results good enough. But how to enjoy the job from the beginning to end?

You need to eliminate the Oh-moments. The more experience you get, the less Oh-moments you experience. But you cannot take them out of the equation entirely. Sh*t happens, and when it does, you need to be ready to minimize the consequences. However, there are couple of methods, that I personally find very helpful in this matter.

Wait

Never and I mean NEVER implement your design right away. It’s good to do something else for a while (my personal favorite is re-factoring and documenting the existing code) and then get back to it. If you still can’t see anything wrong with it, your chances of encountering an Oh-moment in the future are decreasing.

Show It to Others

A great way of avoiding oh moments is explaining your design to a team-mate or a friend. You will see it from whole another perspective and this will help you discover any unwanted surprises wrapped in the design.

Design in Iterations

Generally the later you get the flaw the bigger issue it is, so if you’ve stumbled upon an Oh-moment after a year of development, well, may the force be strong with you. But If you sit back once in a while and think a little further into the future of your application, you might find the dead end fast enough, before you get surrounded in it by a group of guys with knives and baseball bats craving for your wallet.

Open/Closed Principle in Software Design

Open/Closed principle or OCP is one of the guidelines that help software developers achieve high quality software design. Well, it’s actually pretty hard to tell, what exactly does the term high quality software mean. Back to the OCP. Bertrand Meyer is credited as having originated the term Open/Closed Principle, which appeared in his 1988 book Object Oriented Software Construction. It goes like this:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

What does it mean? When you design some piece of software, it’s vital to keep in mind possible places for future extensions. Let’s face it, the customer specifications change with a speed of a guy, who just found out he had accidentally drunk a whole bottle of extremely effective laxative. So your code is most certainly going to be a subject of change and extension. And as we know, it doesn’t end well (in either case).

What the principle implies is, that you can think a little forward (build for today, design for future, right?) and design your software so no changes are necessary when it comes to adding a new features and functionality. Let the code speak for itself:

def area(geometric_entity):
    if geometric_entity.type() == SQUARE:
        return geometric_entity.a * geometric_entity.a
    elif geometric_entity.type() == CIRCLE:
        return PI * geometric_entity.r * geometric_entity.r
    else:
        raise UnknownEntityError("I literally have no idea.")

This is a really dumb example in the first place, but it shows the key aspect of OCP. If you decide, that it’d nice to have your neat area function work with triangles as well, you need to go here and add another elif clause. Then others will come with requirements on other geometric entities and before you know it, this 6 harmless, poorly coded lines will turn into 1500-line Riemann integral solving monster (seen it happen). And if the code monster won’t eat you, your project manager definitely will …

The point is, every time you change something in your software, something else can go wrong (and according to Murphy’s laws, it usually does). There are unit tests, which are designated specifically to discover such errors (if you don’t even write unit tests, you’re either doomed, a superman or a fellow, who enjoys a quality time with a gallons of coffee and GNU debugger). But even unit tests don’t get everything and it’s generally a good idea to avoid poking the bear, if you absolutely don’t have to.

Software quality might be a little subjective and generally hard to define formally. So are, as the software quality, this guidelines (that’s right, not rules). They cannot be enforced unconditionally. But it’s definitely good to know, that they’re there. And they might help you see flaws in your design before it’s too late and save your ass from getting fired :-P. Or not. Anyway, Open-Close principle is not the only one, so stay tuned for more premium 95 octane knowledge (ok, I probably watch How I Met Your Mother waaay to much lately).

Sources