SESE vs SEME
SESE/SEME are terms of structural programming and were introduced at 80-s. Nothing new. However, experience shows that some programmers do not know about them till today. That’s why it makes sense to explain what it is all about.
I want to express my gratitude to Ruslan, Oleg, and Alex who actively helped me to work this theme out.
SESE = Single Entry Single Exit. SEME = Single Entry Multiple Exits. It is very simple: any function has a single entry but one or many exits. Consider this code as an example:
bool some_func()
{
void *p1 = malloc(1);
if (!p1)
return false;
void *p2 = malloc(1);
if (!p2)
{
free(p1);
return false;
}
void *p3 = malloc(1);
if (!p3)
{
free(p2);
free(p1);
return false;
}
free(p3);
free(p2);
free(p1);
return true;
}
As you see, there are many exits. If you miss any “free” in front of “return” you will get a memory leak. This situation could be much worse if not only memory has to get free but some other resources also. For instance, IRQL if you coding in a ring 0: any missed KeReleaseSpinLock might cost you many long hours of bug fixing.
The common sense of moving from SEME to SESE is simple enough: we release resources centrally, while SEME offers a wishy-washy model of release. I would like to emphasise that there is no intention whatsoever to start another holy war on the subject. Obviously, both techniques have “right to live” and each one of them has its own pros and cons; and it’s not smart to prefer only one of them. If you need to know more you might want to read http://c2.com/cgi/wiki?SingleFunctionExitPoint.
How we could do function refactoring to escape SEME model and go to SESE one? There are some options for that:
Use bigger nesting depth
bool some_func()
{
bool tmp;
void *p1 = malloc(1);
if (p1)
{
void *p2 = malloc(1);
if (p2)
{
void *p3 = malloc(1);
if (p3)
{
tmp = true;
free(p3);
}
else
tmp = false;
free(p2);
}
else
tmp = false;
free(p1);
}
else
tmp = false;
return tmp;
}
Obviously, the amounts of “free” have got lower but is it getting better? There is a definition of nesting depth. It is said (see "Code Complete" by McConnel) you will go nuts on the 3rd or 4th level of nesting. In the re-written variant “some_func” we already have the level 3. If a little bit more, the reason of re-writing becomes very doubtful. Moreover, we also should not forget about the readability: there are so many shifts to the right before you even get to the point...
There is one more option which increases the nesting depth, and probably... it’s not that ugly as the code above.
bool some_func()
{
bool tmp = false;
void *p1 = 0;
void *p2 = 0;
void *p3 = 0;
if ((p1 = malloc(1)))
{
if ((p2 = malloc(1)) != 0)
{
if ((p3 = malloc(1)))
tmp = true;
}
}
if (p3)
free(p3);
if (p2)
free(p2);
if (p1)
free(p1);
return tmp;
}
There is a bunch of advantages here. First of all, there is no so much ado with "bool tmp" as in the case above. Secondly, clear initialization of variables is needed, which without any doubts is the right manner of coding.
And one more option:
bool some_func()
{
bool tmp = false;
void *p1 = malloc(1);
void *p2 = 0;
void *p3 = 0;
if (p1)
p2 = malloc(1);
if (p1 && p2)
p3 = malloc(1);
if (p1 && p2 && p3)
tmp = true;
if (p3)
free(p3);
if (p2)
free(p2);
if (p1)
free(p1);
return tmp;
}
The nesting depth metric remains the same. But mentally code seems to be less complicated.
Using of "goto" or "do{}while(false) + break" fake cycle.
bool some_func()
{
bool tmp = false;
void *p1 = 0;
void *p2 = 0;
void *p3 = 0;
do
{
p1 = malloc(1);
if (!p1)
break;
p2 = malloc(1);
if (!p2)
break;
p3 = malloc(1);
if (!p3)
break;
tmp = true;
} while (false)
if (p3)
free(p3);
if (p2)
free(p2);
if (p1)
free(p1);
return tmp;
}
The nesting depth increase is so small (+1 only) so you can disregard it. The initialization of variables is also needed. The code coupling with "do{}while(false) + break" is less compare to "goto" approach. This option seems to be the optimal choice if one decides to go from SEME to SESE. Note however for some edge cases (huge nesting depth for example) goto may be preferable.
It is very important to mention that everything which has been described above is very true for C, but now it is С++, C#, and Java time. These languages have brought two things which make us to re-consider our traditional opinion about SESE vs SEME.
- More intelligent resources management
(constructors/destructors in C++ and garbage collector in C#/Java and so
on) - Exceptions
The resources management is another story which needs special consideration. However, constructors/destructors, STL auto_ptr, and boost scoped_ptr/shared_ptr and so on exist for C++.
Any way, you should not think that only one technique is preferable: everything depends on a particular situation. Happily, programming is still an art and not always has to obey and respect the formal methods and rules.
- Posted by: volodya 8.4.2009 at 05:33 0 comments
You're currently an anonymous user. Just browsing around? That's totally cool with us. We won't bug you until you're ready to write a comment. Otherwize you have to enter your OpenID credentials to log in. If you have not one, you can easily create it!
Example OpenIDs:
- http://openid.aol.com/yourname
- http://yourname.myopenid.com/
- https://me.yahoo.com/yourname (alternately, http://yahoo.com/ works too)
- http://claimid.com/yourname
- http://yourname.wordpress.com/
- http://yourname.blogspot.com/
- http://technorati.com/people/technorati/yourname
- http://yourname.pip.verisignlabs.com/
- http://yourname.livejournal.com/
- http://www.flickr.com/photos/yourname
WHAT'S NEW
- PEP8 validation script
- Modified PEP8 validation script with Nesting Depth additional validation.
- October 21, 2010
- PEP8 and nesting depth metric
- Company code style is one of the most essential policies to follow for any programming-related IT-organization. It helps to organize interaction between developers, especially for Agile teams, makes code more ...
- October 21, 2010
- CodeExample plugin for Trac
- The Trac plugin for code examples colouring. It supports three types of examples - a simple, a correct one and an incorrect. Further details see at
- September 29, 2010
- A couple of words about TDD
- Unit-test coding supposes to be one of the most significant methodological achievements of the industry, let’s say, for about last 15 years. The Internet is full of enthusiastic exclamations [1, ...
- February 21, 2010
- Metrics - LoC
- This is going to be a small set of articles devoted to metrics. The first one is about LoC - Line of Code. I think that the first reaction on ...
- May 11, 2009