Language Design Choices

Quick bit of background, I’ve used many programming languages over the years.  Though in general I would bias myself to being a procedural/object guy rather than a functional programmer.   Though I can say that I’ve done big projects in most of the popular languages at this point [C++, Java, JavaScript, Perl, PHP, Python, Ruby].   So, this post is more for trying to formalize a few of my thoughts, about some of what I’ve been working with/on.

One of the interesting things about languages is why they were created and then how did they evolve.  I might hold up awk as one of the first unixy interpreted languages, but I would sooner hold up Perl since it came from the open source world (you didn’t expect that AT&T was going to change awk, but Larry would change perl).  While we can look at perl and many people would happily talk about what is wrong with the language, myself included, fundamentally it was a great tool…  Most people forget that most of the original CGI programs on websites were written in perl – it got text in a way that no other tool did at the time (and most still dont).

I got into a discussion about how Ruby sucks, but realized later that this fundamentally was an origin problem.

Author Centered -

I keep on making lots of comparisons between Ruby and Perl, maybe it all started because they both have “unless” as a keyword.  But, in thinking about it deeper most of the idea is that Perl has a single parent Larry and Ruby is Matz, the majority of the design of the language came from their world view.  The challenge is that most people have a strong understanding of a specific problem set, but they miss other details due to lack of understanding.  In perl, the OO and Variable hiding (my vs. local) I think demonstrates this, while in Ruby “returning from lambda” and extending base classes show it in other ways.

Ruby Detail:  If you extend Hash with a “fizzle” method, the challenge is that in a large project you import 57 gems one of which implements a “fizzle” method and the programmer before you used it…  You now have to figure out which gem extended your Hash class and what does the fizzle method do…  Pretty much impossible.

Contribution Centered -

Just have to find a way to slip PHP in here.  It’s a kitchen sink, some of the language has OO style, some has procedural, sometimes the names change based on the phase of the  moon (look at the string functions).  It’s very clearly an open project where contributions are the primary driver, rather than strong design.

Committee Centered -

Python, Java, JavaScript, C++ all of these have a strong committee  driving the design of the language, some are more old school some are more new school (C++ vs. Python).  But, what’s interesting is that proposals for the language end up being consistent with the existing style (vs. PHP) and tend to have lots of world views taken into account.  There feels like a correctness to the idea that False/0/empty string/empty array are all “false”.

In the grand scheme of things they are all tools, they all get a job done, it’s just working through the nuances of the langues takes time.  What’s interesting is that if you spend time to really work with these you will learn something new about all of the others that you will work with now and into the future, but sometimes it’s helpful to have a framework to put the underlying design into.

A Few Final Thoughts -

  • Python – whitespace is great, but it makes adding/removing nesting hard.
  • Perl – You still rock for crunching a file quickly.
  • PHP – Visual Basic…  the early years.
  • Ruby – You’ve got more limits than you’ll admit to.
  • C – When you’re good, you’re great, when you’re not …. run.
  • C++ – Still teaching us tricks, separating the men from the boys.
  • Java – High hopes, not fulfilled.
  • JavaScript – Your second coming (nodejs) has promise
  • ActionScript – Why?
Tagged ,

Writing an echo server in libev and c++

Looking at event IO frameworks and found some really good comments about the “ev” library, the challenge is that I would rather work in C++ than pure C – I like methods.. Found that the documentation is lacking for the C++ side of the library and needed to build a test harness.

This is a very basic TCP Echo server using libev in c++. The C++ side is only using std::list and the ev side is playing with loop, signals and basic socket IO. It should be a useful bread crumb for anybody trying to build their own service, which of course is my next big activity.

#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <ev++.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <resolv.h>
#include <errno.h>
#include <list>

//
//  Buffer class - allow for output buffering such that it can be written out
//                 into async pieces
//
struct Buffer {
    char    *data;
    ssize_t len;
    ssize_t pos;

    Buffer(const char *bytes, ssize_t nbytes) {
        pos = 0;
        len = nbytes;
        data = new char[nbytes];
        memcpy(data, bytes, nbytes);
    }

    virtual ~Buffer() {
        delete [] data;
    }

    char *dpos() {
        return data + pos;
    }

    ssize_t nbytes() {
        return len - pos;
    }
};

//
//  A single instance of a non-blocking Echo handler
//
class EchoInstance {
private:
    ev::io      io;
    static int total_clients;

    // Buffers that are pending write
    std::list<Buffer*>   write_queue;

    // Generic callback
    void callback(ev::io &watcher, int revents) {
        if (EV_ERROR & revents) {
            perror("got invalid event");
            return;
        }

        if (revents & EV_READ)
            read_cb(watcher);

        if (revents & EV_WRITE)
            write_cb(watcher);

        if (write_queue.empty()) {
            io.set(ev::READ);
        } else {
            io.set(ev::READ|ev::WRITE);
        }
    }

    // Socket is writable
    void write_cb(ev::io &watcher) {
        if (write_queue.empty()) {
            io.set(ev::READ);
            return;
        }

        Buffer* buffer = write_queue.front();

        ssize_t written = write(watcher.fd, buffer->dpos(), buffer->nbytes());
        if (written < 0) {
            perror("read error");
            return;
        }

        buffer->pos += written;
        if (buffer->nbytes() == 0) {
            write_queue.pop_front();
            delete buffer;
        }
    }

    // Receive message from client socket
    void read_cb(ev::io &watcher) {
        char    buffer[1024];

        ssize_t  nread = recv(watcher.fd, buffer, sizeof(buffer), 0);

        if (nread < 0) {
            perror("read error");
            return;
        }

        if (nread == 0) {
            // Gack - we're deleting ourself inside of ourself!
            delete this;
        } else {
            // Send message bach to the client
            write_queue.push_back(new Buffer(buffer, nread));
        }
    }

    // effictivly a close and a destroy
    virtual ~EchoInstance() {
        // Stop and free watcher if client socket is closing
        io.stop();

        printf("%d client(s) connected.\n", --total_clients);
    }

public:
    EchoInstance(int s) {
        fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK); 

        printf("Got connection\n");
        total_clients++;

        io.set<EchoInstance, &EchoInstance::callback>(this);

        io.start(s, ev::READ);
    }
};

class EchoServer {
private:
    ev::io      io;
    ev::sig     sio;
    int         s;

public:

    void io_accept(ev::io &watcher, int revents) {
        if (EV_ERROR & revents) {
            perror("got invalid event");
            return;
        }

        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);

        int client_sd = accept(watcher.fd, (struct sockaddr *)&client_addr, &client_len);

        if (client_sd < 0) {
            perror("accept error");
            return;
        }

        EchoInstance *client = new EchoInstance(client_sd);
    }

    static void signal_cb(ev::sig &signal, int revents) {
        signal.loop.break_loop();
    }

    EchoServer(int port) {
        printf("Listening on port %d\n", port);

        struct sockaddr_in addr;

        s = socket(PF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;
        addr.sin_port   = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;

        if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
            perror("bind");
        }

        fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK); 

        listen(s, 5);

        io.set<EchoServer, &EchoServer::io_accept>(this);
        io.start(s, ev::READ);

        sio.set<&EchoServer::signal_cb>();
        sio.start(SIGINT);
    }

    virtual ~EchoServer() {
        shutdown(s, SHUT_RDWR);
        close(s);
    }
};

int EchoInstance::total_clients = 0;

int main(int argc, char **argv)
{
    int     port = 8192;

    if (argc > 1)
        port = atoi(argv[1]);

    ev::default_loop    loop;
    EchoServer          echo(port);

    loop.run(0);

    return 0;
}

Scrum without Objective

Waterfall bad, right?  Well, to an extent it is — the good part about waterfall is that you start with a objective and build a team around an objective.  The challenge is that the interm points and progress measurements get caught up in gantt charts, absolute assignments, critical paths, etc.etc.  Of course waterfall is all about time and deadlines, so when things fall behind it’s all about finger pointing and fall guys.

Scrum is good, semi-self organized teams working on short lists of tasks.  Continual measurement of progress, yadda yadda yadda.  But, then once you’ve released what happens…   You have a two week sprint, a bunch of things a product person, if you’re lucky an engineer, has added to the sprint queue…  Rinse and repeat — but somebody has forgotten the biggest piece.

What’s the Goal?

Waterfall – simple goal is a PRD … Scrum to a point is a PRD (yes, lean ideals, it changes).  What you need to remember to create in a series of sprints is a goal for the team — why are they doing this work, to what end… If it is just the features of the week, you need to take a step back and figure out if you’re in a conifer forest or a deciduous forest, since you’re not seeing anything except trees.

Blink Tag

Ended up wondering what it would take to create the blink tag in jQuery.  It was pretty easy, but the big catch is that $(this).is(“:visible”) is really checking “display == none”.

That said, here’s the code.

<p>test <span class="blink">HIHIHI</span> of blink</p>
<p>test <span class="blink">HIHIHI</span> of blink</p>

<script>
setInterval(function() {
    $('.blink').each(function() {
           $(this).css('visibility',
                 $(this).css("visibility") == 'hidden' ? '' : 'hidden'); });
     }, 500);
</script>

Crafting your education

In the movie Wordplay, all about NY Times Crossword Puzzles, they interview Will Shortz and he talks about how he crafted his own education (a degree in enigmatology).  I was thinking about how crafting  your education can take you many places.

For instance, ever now and then I’ve been know to go on an interview or two… In this day and age people are very focused on asking directed programming puzzles – the classic is the FizzBuzz problem.  Over they years I’ve done so many whiteboard/computer programming puzzles in interviews that I’ve lost track of them.  Everything from string sorting, to multi-threaded deadlock contention.

What I realized last night is that I did craft my education in college to help with these problems.  Sitting at the bottom of my resume is the often overlooked fact that I participated in two different International ACM Programming contests – the second year that I participated we got the Computer Science department to offer a for credit class in programming puzzles.  So, for an entire quarter we worked on short programming problems, under time pressure.  The only downside is that because of rote familiarity with the form, I can be viewed as a little cavalier to the topic…

Looking back, the ability to craft your education, leaves you with some very handy skills.

Tagged , ,

The never ending update

Modern technology is great…  Except that more and more things are connected to the network with auto update.

So, when I go and place music now my music player says “Update Required” and refuses to play until I update.  I can’t watch a movie until my PS3 takes two hours to update the software to the newest version.  My computer of course is always nagging that it needs an update, somewhere between optional and “broken” (^#*@$ Java on Windows).  If this trend continues, my refrigerator will refuse to accept new food items – that item isn’t in the inventory – please update, or my toaster will say “unable to accept toast” until I update the firmware to have the latest toast profile.

Yes, it is a better world than waiting for your car engine to heat up and your vacum tubes to warm before you can use a device.  But, now we’ve got these deferred time bombs waiting in our daily life.

Off to update my iPhone apps.