The problem with OSdeving…

…is that it doesn’t help against a depressive day.

My life is awesome. Even when not considering how it would be like if I was born in a ghetto. I’m healthy, I’m doing interesting studies, I have a fantastic girlfriend, and I have one of the coolest hobbies in the world, namely trying to solve a though problem whose solution could greatly benefit to my specie (or, at the very least, my relatives and the geeky part of my specie). But sadly, I’m still a human being, and when I’m tired enough or just got badly psychologically hurt, I manage to still be complaining about tiny parts of my life…

  • That I lose hours mindlessly browsing the web and going on my holy war against fanboys instead of spending this time doing something actually useful.
  • That I’m not sure I’ve done the best things in the past and have the best plans for the future (though I can’t think of a better idea) and other deep philosophical questions like that.
  • That even when I finally manage to sit and code, without getting distracted, I’ve recently got work done about as fast as a snail with a Pentium II on its back.

Well, the last one is particularly daunting and of interest for you, so let’s put some details. When I got some working physical memory allocation code, I was extremely happy and impressed that I made that thing work so quickly, and thought that I could just finish the whole memory management code before the end of vacations. Well, it’s the end of vacations today, and I’ve trashed a lot of design drafts, but the paging management code written so far is less than 100 LOC long. All in headers.

There are two explanations for this. The first one is that I took part of this time to carefully polish the physical memory management code, now that I’ve a working codebase that’s ready to be tortured. I tried and managed to make it faster without wasting a single extra bit of memory, and to make the code much cleaner through better consistency in variable naming and better use of line feeds. I also corrected some mistakes which would have been problematic in the long run, like some functions not checking the mutex before accessing a critical resource. I think I can’t make these ~600 lines of code any cleaner or better-performing without increasing complexity by an order of magnitude. Which would be silly, as I’ll explain later.

Then there’s the design hell. I’m not fast at designing things, because I always begin each design work by trying to find the most elegant and efficient solution to my problem. Even when I know that I’ll always end up using a linked list because it’s probably good enough, ultimately flexible, and easy to code. And because I can’t tell if I even need the extra performance of more complex solutions anyway.

The main problem in my opinion, the main thing which slows down my OS development work today, is that I have extreme difficulties to write dirty code now and fix it later, as I do on other projects. I must check all alternatives I may think of first. That’s because I have a frightening obsession of cleanness and doing things right the first time, and extreme difficulties to tell myself “hey, it’s okay, I just can’t tell if a solution is better as long as I don’t have seen how it compares on real-world use cases”. And by doing so, I make the time before those real-world use cases are available longer. This is where I’m ready to believe that perfectionism can become a disease.

On the other hand, this is the first time I ever write a kernel. So I’d better be extremely careful. If I stick a design defect deep in my OS and only discover it much later, I may have to break several things built on top of the defect while trying to fix it. So better doing it right the first time… And so on. There are justifications for this behavior sadly.

Hell… What a complicated and poorly written post just to say that I did nothing ! I really feel angry about myself right now. Sleeping more is probably the answer.

4 thoughts on “The problem with OSdeving…

  1. Amenel September 12, 2010 / 9:42 pm

    A few things that came to mind reading your post:
    – yes, perfectionism is a disease and a handicap.
    – design is indeed just that: design. i.e. ideas, which, when considered in a less abstract manner, will lead to a contract that code must implement. There are three levels of dependency here: ideas dictate contracts, and contracts dictate code. By contract, I mean the assumption, preconditions and postconditions. A little like the set of operations on an abstract data type. An example of this is the stack: you get the idea from a stack of dishes (for instance). The contract will lead to the five abstract operations: isEmpty, createEmptyStack, push, pop, getTopOfStack. Whatever the topic at hand, the implementation is not important if these operations are clearly defined. End of design. Seems like you’re pulling and mixing a dose of code at that level, which is beyond the pure scope of “design”.

    – I’ve been reading the book “Software Development” by Pilone and Miles in the past days. On page 168, there is a conversation between two fictitious characters (“good enough” design and perfect design). Somewhere in the conversation, perfect design goes like “people spend so much time on me they never meet deadlines”… and later, it says “by the time I show up, the team is running late”. In my opinion, you should not aim for anything perfect first. Aim for milestones then refine/test/stress test/second guess/impugn/etc. before moving forward. I believe that if your contracts are well defined, refactoring is always limited. Problems arise when the contracts have to be changed. We then fall into the “backward/forward compatibility” issues, which I have no expertise in.

    I don’t remember who sang the song but someone said “I did my best but I guess my best was not enough” in some lyrics. It happens all the time. And if all decisions including OS design-related ones were to be the best ever each time, we wouldn’t get far.

    Cheers!

  2. Emil September 13, 2010 / 6:42 pm

    Nonetheless, we’re still happy to hear about any progress you’re making! :-)

  3. Hadrien September 13, 2010 / 9:49 pm

    Yes, perfectionism is a disease and a handicap.

    Well, I don’t think I’m ill, since this is the only project where I have this obsession of perfection around, and it generally manages to remain a good thing rather than something which annoys me ;)

    design is indeed just that: design. i.e. ideas, which, when considered in a less abstract manner, will lead to a contract that code must implement. There are three levels of dependency here: ideas dictate contracts, and contracts dictate code. By contract, I mean the assumption, preconditions and postconditions. A little like the set of operations on an abstract data type. An example of this is the stack: you get the idea from a stack of dishes (for instance). The contract will lead to the five abstract operations: isEmpty, createEmptyStack, push, pop, getTopOfStack. Whatever the topic at hand, the implementation is not important if these operations are clearly defined. End of design. Seems like you’re pulling and mixing a dose of code at that level, which is beyond the pure scope of “design”.

    You know, I think that’s the kind of interesting things which I would have studied in school if I was not that stubborn about my studies orientation choices ;)

    Well, my current ideal method is something like this :

    1/Ask myself some basic questions : “What do I want to implement ? What problem is it meant to solve ? Do I need to solve this problem at this stage of development ? Is it required ? By which kind of use cases ?”

    2/”What public interface can I put on my class that helps solving those problems best while keeping the implementation reasonably small ? What methods are mandatory to do its job ? Are there other methods that could be useful in less common use cases, but are not an absolute requirement ? Discuss their inclusion.”

    3/Now that the interface part is done, go on with the actual implementation work. If something which sounded easy to implement proves to be a nightmare, consider changing the interface to something which still solves the problem optimally but makes the implementation easier (it’s pre-release code, we can do this till it’s release 1, make maximum profit from this dream situation !). When something starts to go horribly wrong, consider flushing the implemented code and starting over. We have a lot of available time, properly using it is best.

    4/When the final implementation is okay, it’s code checking time : first check all methods to see if they work. Put them under more load that they will ever endure in normal use (e.g. allocate 80’000 4 KB pages one by one and then free them all), see if they can do still do their work in a reasonable amount of time. Third check is trying to review the whole code module, wonder if the algorithms can be simplified or see their performance improved in some simple way, checking the code for non-obvious runtime flaws in the way. Fourth check is to try to make the code easily readable by someone else, through consistent variable naming and proper comments. In the way, solve every single mistake found, if possible.

    5/When the code has undergo all these checks, it’s ready to be left somewhere and forgotten, until we suddenly has some illumination and discover that we should do X and that it would make things much better at a low coding cost. This is what I would call a mature codebase : time to start work on the next milestone, but don’t neglect it right away because it’s when the code is fresh in your mind that brillant ideas are frequent and easier to apply…

    I don’t think there’s anything wrong in it. I just need to apply it every time care must be taken, since it’s obviously overkill for non-critical internal code that can be changed at will…

    I’ve been reading the book “Software Development” by Pilone and Miles in the past days. On page 168, there is a conversation between two fictitious characters (“good enough” design and perfect design). Somewhere in the conversation, perfect design goes like “people spend so much time on me they never meet deadlines”… and later, it says “by the time I show up, the team is running late”. In my opinion, you should not aim for anything perfect first. Aim for milestones then refine/test/stress test/second guess/impugn/etc. before moving forward. I believe that if your contracts are well defined, refactoring is always limited. Problems arise when the contracts have to be changed. We then fall into the “backward/forward compatibility” issues, which I have no expertise in.

    As said above, my answer to these interface issues is to try to prevent them as soon as possible, when the code is still not yet released and can be trashed or changed at will. Make testing and polishing extremely careful. But then, we must not reached the other extremity which I reached recently, namely caring too much about some robust code… It’s a difficult balance, managing it is only a matter of experience, I think. That’s not a problem, I’m acquiring such experience of OSdeving anytime I face such issues and manage to overcome them ;)

  4. Hadrien September 13, 2010 / 9:58 pm

    Thank you very much ;) That’s encouraging !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s