How Apollo 11′s 1.024MHz guidance computer did a lot with very little

 

early 44 years ago computer hardware was in an entirely different place than it is now. The levels of performance don’t even fit on the same scale. The anniversary of the Apollo 11moon landing is upon us, and those brave space pioneers got by without a 3GHz multi-core CPU. The guidance computer used on the Apollo 11 mission ran at only 1.024 MHz.

The moon landing was the height of technological achievement at the time, and some of the rocket technology is still relevant today. That computer, though, has been left in the dust. In fact, it was well and truly obsolete a few years after the landing.

The Intel 8086 came about roughly ten years after the Apollo landing, marking the beginning of x86. Apollo 11’s computer had 4 registers — essentially slots for holding numeric values. The 8086 boosted that to eight 16-bit registers.

The IBM PC XT ran the next version of that chip, the famous 8088. This computer ran at 4.077MHz, which sounds incredibly slow by today’s standards, but is still four times faster than the Apollo 11computer. The XT also packed in eight times the memory used on Apollo 11.

The Apollo 11 guidance computer actually had some impressive software features for a system that didn’t even run a graphical interface. It could multitask up to 8 different operations, but it didn’t work the way we think of multitasking. Today’s operations use preemptive multitasking that allows the OS to distribute computing resources as needed. On Apollo 11, programs were in charge and had to give control back to the OS periodically. A kind of virtual machine was used to allow developers to mix hardware-level instructions with virtual machine commands within the same assembler code.

Inputting commands required translating the English words into “verb noun pairs,” which could be input as numbers. There was a handy sign in the cabin as a reminder. To top it all off, none of the computer’s systems were software upgradeable. All the code was stored in read-only memory. Several years after Apollo 11, Apollo 14 was forced to manually input the code to patch a system malfunction — it took 90 minutes just to type it in.

Maybe your computer is a little sluggish, and your smartphone is a couple years old, but you have it better than those astronauts

Microsoft Denies Spying Issues Skype

CALIFORNIA – Microsoft has denied allegations that the government says it gave the United States (U.S.) direct access to a number of Microsoft products, including SkyDrive, Outlook.com, Skype, for the U.S. government (U.S.).

Reported by Read Write, Tuesday (16/07/2013), the software giant’s rebuttal to respond to a report in The Guardian, which has channeled suspect Skype user data into the monitoring program PRISM National Security Agency (NSA) since 2011.

Microsoft confirmed the company has clear principles in responding to government demands for user information related to law enforcement and national security issues. Perusahana consumers insist only provide data in response to legal process and only permitaan adhere to certain accounts or identification.

“We appreciate our commitment to the user and in accordance with applicable law very seriously, so we provide only to respond to consumer data due process. To be clear, Microsoft does not give the government direct access to SkyDrive, Outlook.com, Skype, or Microsoft products the other, “explains Microsoft.

In the end, Microsoft said, when companies update product liability law, may in some circumstances have to retain the ability to provide information in response to requests by law enforcement or national security.

“That’s why, we argue that additional transparency will help everyone understand and debate the important issues,” said Microsoft.

Smartphone Advan Vandroid S5

Unggulkan Big Screen

The success of one of the Korean manufacturer to sell millions of smartphone unit have made a great sailing inspired many other manufacturers. However, to be sold at more competitive prices, various gadgets “rival” comes with fewer features. This is carried by Vandroid S5 from Advan.

u4-435-S5 AdvanAdvan Vandroid by PCplus quite on par with ZA987 OneScribe of Zyrex that appeared almost simultaneously. ˝ 5.3 capacitive screen with a resolution of 480 × 800 pixels here look quite a contrast and not inferior to similar products from leading brands. Advan S5 Vandroid called as “Smart Note” which is interpreted as a smart gadget with a variety of features that support mobile activities. This seems to be a campaign to educate consumers.

Smartphone MediaTek MT6575 is powered by a 1GHz processor (ARM v7) plus 512MB of main memory is actually not very special and still like most other large screen smartphones. Booting the system fairly quickly became hallmarks Vandroid Advan S5.

Here also 4GB of internal memory available. Unfortunately, only 2.2 GB of available capacity that can be used. It was only by the system / application alias can not be accessed directly by the user. As a result, users must add a microSD card (up to 32GB) as a storage media to store data.

The process of exploration in the menu Vandroid Advan S5 with Android 4 systems is quite smooth because of the PowerVR SGX531 GPU to handle graphics side. Advan smartphone also includes six important sensor that is not provided other competitors. With all those fittings plus dual SIM support, he can be had for less than Rp. 2 million. This makes it an attractive alternative products in the ranks of the many large screen smartphones on the market today.

Maybe not as perfect Advan S5 Vandroid similar smartphones from popular brands. When held casing feels slippery. However, to simply live day-to-day activities of this product is sufficient. At more competitive prices, even compared to other local brands, this smartphone is certainly attractive alternative option for on a budget.

Software Equity Group’s Client, Cougar Software, Receives Growth Equity Investment From dmg information

Software Equity Group, LLC (SEG) announced today its client, Cougar Software, the leading provider of budgeting, planning and forecasting solutions for the real estate industry, has received a growth equity investment from dmg information (dmgi), a business division of Daily Mail & General Trust (DMGT) that manages and develops a portfolio of high-growth, innovative companies that provide business-to-business information to the property, education, energy and commodity and structured finance markets.

dmgi’s investment in Cougar Software represents SEG’s seventh transaction in the real estate software segment. SEG’s prior real estate transactions include the sale of clients providing application software for commercial facilities/property management, facilities design, integrated workplace management, multi-family property vendor compliance management, commercial building construction, public sector housing and long-term care facilities. Acquirers of SEG’s real estate software clients include RealPage, Yardi, Accruent and Bentley Systems.

Cougar is well known in the property sector as a leading provider of budgeting, planning and forecasting solutions exclusive to the Real Estate Industry, and enables its users to easily make strategic decisions using sophisticated financial modeling.

“The timing of this investment couldn’t be better,” said Oren Rosen, CEO, Cougar. “Over the last five years we have been building a foundation for growth by steadily increasing market penetration in North America, Europe and Asia Pacific. With the strategic and financial backing of dmgi, we can continue our demonstrated track record of customer-driven product innovation and put our foot on the accelerator to increase penetration in these markets.”

About Software Equity Group

Software Equity Group is an investment bank and M&A advisory serving the software and technology sectors. Founded in 1992, the firm has guided and advised companies on five continents, including privately-held software and technology companies in the United States, Canada, Europe, Asia Pacific, Africa and Israel. SEG has represented public companies listed on the NASDAQ, NYSE, American, Toronto, London and Euronext exchanges, and also advises several of the world’s leading private equity firms.

Integrating C++ with QML

Introduction

Qt Quick’s QML language makes it easy to do many things, especially fancy animated user interfaces. However, some things either can’t be done or are not suitable for implementing in QML, such as:

  1. Getting access to functionality outside of the QML/JavaScript environment.
  2. Implementing performance critical functions where native code is desired for efficiency.
  3. Large and/or complex non-declarative code that would be tedious to implement in JavaScript.

As we’ll see, Qt makes it quite easy to expose C++ code to QML. In this blog post I will show an example of doing this with a small but functional application.

The example is written for Qt 5 and uses the Qt Quick Components so you will need at least Qt version 5.1.0 to run it.

Overview

To expose a C++ type having properties, methods, signals, and/or slots to the QML environment, the basic steps are:

  1. Define a new class derived from QObject.
  2. Put the Q_OBJECT macro in the class declaration to support signals and slots and other services of the Qt meta-object system.
  3. Declare any properties using the Q_PROPERTY macro.
  4. Call qmlRegisterType() in your C++ main program to register the type with the Qt Quick engine.

For all the details I refer you to the Qt documentation section Exposing Attributes of C++ Types to QML and the Writing QML Extensions with C++ tutorial.

Ssh Key Generator

For our code example, we want a small application that will generate ssh public/private key pairs using a GUI. It will present the user with controls for the appropriate options and then run the program ssh-keygen to generate the key pair.

I implemented the user interface using the new Qt Quick Controls since it was intended as a desktop application with a desktop look and feel. I initially developed the UX entirely by running the qmlscene program directly on the QML source.

The UI prompts the user for the key type, the file name of the private key to generate and an optional pass phrase, which needs to be confirmed.

The C++ Class

Now that have the UI, we will want to implement the back end functionality. You can’t invoke an external program directly from QML so we have to write it in C++ (which is the whole point of this example application).

First, we define a class that encapsulates the key generation functionality. It will be exposed as a new class KeyGenerator in QML. This is done in the header file KeyGenerator.h below.

#ifndef KEYGENERATOR_H
#define KEYGENERATOR_H

#include <QObject>
#include <QString>
#include <QStringList>

// Simple QML object to generate SSH key pairs by calling ssh-keygen.

class KeyGenerator : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
    Q_PROPERTY(QStringList types READ types NOTIFY typesChanged)
    Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
    Q_PROPERTY(QString passphrase READ filename WRITE setPassphrase NOTIFY passphraseChanged)

public:
    KeyGenerator();
    ~KeyGenerator();

    QString type();
    void setType(const QString &t);

    QStringList types();

    QString filename();
    void setFilename(const QString &f);

    QString passphrase();
    void setPassphrase(const QString &p);

public slots:
    void generateKey();

signals:
    void typeChanged();
    void typesChanged();
    void filenameChanged();
    void passphraseChanged();
    void keyGenerated(bool success);

private:
    QString _type;
    QString _filename;
    QString _passphrase;
    QStringList _types;
};
#endif

Next, we need to derive our class from QObject. We declare any properties that we want and the associated methods. Notify methods become signals. In our case, we want to have properties for the selected key type, the list of all valid ssh key types, file name and pass phrase. I arbitrarily made the key type a string. It could have been an enumerated type but it would have made the example more complicated.

Incidentally, a new feature of the Q_PROPERTY macro in Qt 5.1.0 is the MEMBER argument. It allows specifying a class member variable that will be bound to a property without the need to implement the setter or getter functions. That feature was not used here.

We declare methods for the setters and getters and for signals. We also declare one slot called generateKey(). These will all be available to QML. If we wanted to export a regular method to QML, we could mark it with Q_INVOCABLE. In this case I decided to make generateKey() a slot since it might be useful in the future but it could have just as easily been an invocable method.

Finally, we declare any private member variables we will need.

C++ Implementation

Now let’s look at the implementation in KeyGenerator.cpp. Here is the source code:

#include <QFile>
#include <QProcess>
#include "KeyGenerator.h"

KeyGenerator::KeyGenerator()
    : _type("rsa"), _types{"dsa", "ecdsa", "rsa", "rsa1"}
{
}

KeyGenerator::~KeyGenerator()
{
}

QString KeyGenerator::type()
{
    return _type;
}

void KeyGenerator::setType(const QString &t)
{
    // Check for valid type.
    if (!_types.contains(t))
        return;

    if (t != _type) {
        _type = t;
        emit typeChanged();
    }
}

QStringList KeyGenerator::types()
{
    return _types;
}

QString KeyGenerator::filename()
{
    return _filename;
}

void KeyGenerator::setFilename(const QString &f)
{
    if (f != _filename) {
        _filename = f;
        emit filenameChanged();
    }
}

QString KeyGenerator::passphrase()
{
    return _passphrase;
}

void KeyGenerator::setPassphrase(const QString &p)
{
    if (p != _passphrase) {
        _passphrase = p;
        emit passphraseChanged();
    }
}

void KeyGenerator::generateKey()
{
    // Sanity check on arguments
    if (_type.isEmpty() or _filename.isEmpty() or
        (_passphrase.length() > 0 and _passphrase.length() < 5)) {
        emit keyGenerated(false);
        return;
    }

    // Remove key file if it already exists
    if (QFile::exists(_filename)) {
        QFile::remove(_filename);
    }

    // Execute ssh-keygen -t type -N passphrase -f keyfileq
    QProcess *proc = new QProcess;
    QString prog = "ssh-keygen";
    QStringList args{"-t", _type, "-N", _passphrase, "-f", _filename};
    proc->start(prog, args);
    proc->waitForFinished();
    emit keyGenerated(proc->exitCode() == 0);
    delete proc;
}

The constructor initializes some of the member variables. For fun, I used the new initializer list feature of C++11 to initialize the _types member variable which is of type QStringList. The destructor does nothing, at least for now, but is there for completeness and future expansion.

Getter functions like type() simply return the appropriate private member variable. Setters set the appropriate variables, taking care to check that the new value is different from the old one and if so, emitting the appropriate signal. As always, please note that signals are created by the Meta Object Compiler and do not need to be implemented, only emitted at the appropriate times.

The only non-trivial method is the slot generateKey(). It does some checking of arguments and then creates a QProcess to run the external ssh-keygen program. For simplicity and because it typically executes quickly, I do this synchronously and block on it to complete. When done, we emit a signal that has a boolean argument that indicates the key was generated and whether it succeeded or not.

QML Code

Now let’s look at the QML code in main.qml:

// SSH key generator UI

import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.0
import com.ics.demo 1.0

ApplicationWindow {
    title: qsTr("SSH Key Generator")

    statusBar: StatusBar {
    RowLayout {
        Label {
            id: status
            }
        }
    }

    width: 369
    height: 166

    ColumnLayout {
        x: 10
        y: 10

        // Key type
        RowLayout {
            Label {
                text: qsTr("Key type:")
            }
            ComboBox {
                id: combobox
                Layout.fillWidth: true
                model: keygen.types
                currentIndex: 2
            }
        }

        // Filename
        RowLayout {
            Label {
                text: qsTr("Filename:")
            }
            TextField {
                id: filename
                implicitWidth: 200
                onTextChanged: updateStatusBar()
            }
            Button {
                text: qsTr("&Browse...")
                onClicked: filedialog.visible = true
            }
        }

        // Passphrase
        RowLayout {
            Label {
                text: qsTr("Pass phrase:")
            }
            TextField {
                id: passphrase
                Layout.fillWidth: true
                echoMode: TextInput.Password
                onTextChanged: updateStatusBar()
            }

        }

        // Confirm Passphrase
        RowLayout {
            Label {
                text: qsTr("Confirm pass phrase:")
            }
            TextField {
                id: confirm
                Layout.fillWidth: true
                echoMode: TextInput.Password
                onTextChanged: updateStatusBar()
            }
        }

        // Buttons: Generate, Quit
        RowLayout {
            Button {
                id: generate
                text: qsTr("&Generate")
                onClicked: keygen.generateKey()
            }
            Button {
                text: qsTr("&Quit")
                onClicked: Qt.quit()
            }
        }

    }

    FileDialog {
        id: filedialog
        title: qsTr("Select a file")
        selectMultiple: false
        selectFolder: false
        nameFilters: 
        selectedNameFilter: "All files (*)"
        onAccepted: {
            filename.text = fileUrl.toString().replace("file://", "")
        }
    }

    KeyGenerator {
        id: keygen
        filename: filename.text
        passphrase: passphrase.text
        type: combobox.currentText
        onKeyGenerated: {
            if (success) {
                status.text = qsTr('<font color="green">Key generation succeeded.</font>')
            } else {
                status.text = qsTr('<font color="red">Key generation failed</font>')
            }
        }
    }

    function updateStatusBar() {
        if (passphrase.text != confirm.text) {
            status.text = qsTr('<font color="red">Pass phrase does not match.</font>')
            generate.enabled = false
        } else if (passphrase.text.length > 0 && passphrase.text.length < 5) {
            status.text = qsTr('<font color="red">Pass phrase too short.</font>')
            generate.enabled = false
        } else if (filename.text == "") {
            status.text = qsTr('<font color="red">Enter a filename.</font>')
            generate.enabled = false
        } else {
            status.text = ""
            generate.enabled = true
        }
    }

    Component.onCompleted: updateStatusBar()
}

The preceding code is a little long, however, much of the work is laying out the GUI components. The code should be straightforward to follow.

Note that we import com.ics.demo version 1.0. We’ll see where this module name comes from shortly. This makes a new QML type KeyGeneratoravailable and so we declare one. We have access to it’s C++ properties as QML properties, can call it’s methods and act on signals like we do withonKeyGenerated.

A more complete program should probably do a little more error checking and report meaningful error messages if key generation fails (we could easily add a new method or property for this). The UI layout could also be improved to make it properly resizable.

Our main program is essentially a wrapper like qmlscene. All we need to do to register our type with the QML engine is to call:

    qmlRegisterType<KeyGenerator>("com.ics.demo", 1, 0, "KeyGenerator");

This makes the C++ type KeyGenerator available as the QML type KeyGenerator in the module com.ics.demo version 1.0 when it is imported.

Typically, to run QML code from an executable, in the main program you would create a QGuiApplication and a QQuickView. Currently, to use the Qt Quick Components there is some additional work needed if the top level element is an ApplicationWindow or Window. You can look at the source code to see how I implemented this. I basically stripped down the code from qmlscene to the minimum of what was needed for this example.

Here is the full listing for the main program, main.cpp:

#include <QApplication>
#include <QObject>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQuickWindow>
#include <QSurfaceFormat>
#include "KeyGenerator.h"

// Main wrapper program.
// Special handling is needed when using Qt Quick Controls for the top window.
// The code here is based on what qmlscene does.

int main(int argc, char ** argv)
{
    QApplication app(argc, argv);

    // Register our component type with QML.
    qmlRegisterType<KeyGenerator>("com.ics.demo", 1, 0, "KeyGenerator");

    int rc = 0;

    QQmlEngine engine;
    QQmlComponent *component = new QQmlComponent(&engine);

    QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));

    component->loadUrl(QUrl("main.qml"));

    if (!component->isReady() ) {
        qWarning("%s", qPrintable(component->errorString()));
        return -1;
    }

    QObject *topLevel = component->create();
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

    QSurfaceFormat surfaceFormat = window->requestedFormat();
    window->setFormat(surfaceFormat);
    window->show();

    rc = app.exec();

    delete component;
    return rc;
}

In case it is not obvious, when using a module written in C++ with QML you cannot use the qmlscene program to execute your QML code because the C++ code for the module will not be linked in. If you try to do this you will get an error message that the module is not installed.

Plugin Dynamo Announces the Release of an Upgrade to the Dynamo ONE Plugin – The Easy Button for WordPress

Dynamo ONE Plugin, known as the easy button for WordPress , which is owned and supported by Plugin Dynamo, is excited to announce the release of an upgrade to the Dynamo ONE Plugin. The upgrade enhances the amazing Dynamo ONE Plugin making it even more seamless and effective at setting up WordPress blogs. The Dynamo ONE Plugin allows users to configure and set-up their WordPress site into a highly optimized SEO site in less than 90 seconds.

This upgrade improves how the Plugin syncs with the user’s account for activation and the new layout is a simple 6 click process. This new process will allow users to set-up their WordPress site in less time with less mistakes.

Wesley Williams, Plugin Dynamo’s Managing Partner said, “The Dynamo ONE Plugin was the 1st Plugin to integrate the SEO settings and basic Plugin requirements into one Plugin to make the entire process easy for the user. This update demonstrates our continued support and push to simplify the WordPress set-up process.”

About the Dynamo ONE Plugin:
Dynamo ONE Plugin was created by Plugin Dynamo and is a one of a kind tool that enables users to save time when configuring and setting up WordPress sites. For people who want to configure and set up their WordPress sites quickly and effectively, Dynamo ONE Plugin is the most ideal tool. It allows users to make their WordPress sites SEO friendly and highly optimized in a matter of seconds.

About Plugin Dynamo:
Plugin Dynamo is owned and operated by dotCOM Interactive based in Dallas Texas. Since 2010, Plugin Dynamo has been producing easy to use Plugins. Its Plugins are regularly updated to incorporate new ideas from users, and also to ensure that they are in harmony with the latest versions of WordPress. Plugin dynamo is committed to offering valuable support to its customers.

Cool, Indonesian People Make “Printer” 3D

Starting from his love for the graphic design world, John Djauhari now assembling machines printer (printer) 3D. By leveraging open source technology, 3D printers that can print documents assembled Johanes digital into three-dimensional objects.

John worked as a product designer. Some clients who want to make a product sometimes is not satisfied if only to see the design in the form of digital documents. They want physical shape despite the small size.

“Well, from there, why do not I make a 3D printer itself,” he said when met at the show Popcon KompasTekno Asia 2013 in Jakarta Convention Center, beginning last July.

John also likes the toys (toys). Many colleagues who designed character toys and wanted to realize his ideas into tangible form. Some of them use the services of John for 3D printing.

Starting from his love for the graphic design world, John Djauhari now assembling machines printer (printer) 3D. By leveraging open source technology, 3D printers that can print documents assembled Johanes digital into three-dimensional objects.

John worked as a product designer. Some clients who want to make a product sometimes is not satisfied if only to see the design in the form of digital documents. They want physical shape despite the small size.

“Well, from there, why do not I make a 3D printer itself,” he said when met at the show Popcon KompasTekno Asia 2013 in Jakarta Convention Center, beginning last July.

John also likes the toys (toys). Many colleagues who designed character toys and wanted to realize his ideas into tangible form. Some of them use the services of John for 3D printing.

Keseriusan Johanes merakit printer 3D dimulai pada 2011. Ia mendirikan Bikin Bikin 3D Print dan aktif ikut pameran untuk memperkenalkan teknologi ini. Kala itu, desain luar printer buatannya masih berupa kerangka. Setelah melewati beberapa kali pengembangan, kini printer 3D-nya semakin akurat dan didesain menggunakan casing. “Akurasinya sampai 0,2 mm,” tutur Johanes.

Akurasi itu dibuktikan dengan mencetak replika arca yang penuh detail dan lekukan. Johanes terlebih dahulu memindai seluruh bagian arca asli yang tersimpan di Museum Nasional. Setelah mendapat filepindainya, mulailah Johanes mendesain 3D lalu mencetak dengan printer buatannya sendiri.

Memanfaatkan “open source

Dalam mengembangkan printer 3D, Johanes memanfaatkan teknologi open source untuk driver dansoftware. Ia ikut dalam forum internet yang khusus membahas teknologi printer 3D.

“Di forum ini, kita bisa tahu kalau ada algoritma yang lebih baik dan memberi struktur lebih mudah. Bukan cuma soal teknis, dari sana juga kita tahu soal materi yang mudah dicari dan lebih terjangkau,” jelasnya.

Untuk mendesain bentuk 3D, Johanes menggunakan software Pronter Face dan Repetier. Komputer yang dipakainya terhubung ke motherboard printer melalui kabel USB. Motherboard inilah yang memerintahkan gerakan koordinat X, Y, dan Z, menerjemahkan dokumen digital menjadi obyek nyata 3D.

Printer 3D yang dibuat Johanes masuk dalam tahap pengembangan akhir. Ia membuka pre-orderdengan harga Rp 10 juta. Setelah masa pre-order berakhir pada September 2013, printer 3D bakal dibanderol Rp 12 juta.

Facebook Testing New Navigation Menu

California – Facebook amid redesign navigation bar for iOS and Android app for easy use. Some Facebook users reported that the new navigation bar has appeared at the bottom of the screen.

But, it was not all users can get the new navigation bar that is still a beta version of it. With the addition of the menu at the bottom, the side navigation bar is now no longer in the beta version of the Facebook application.

Android users who already have a new navigation bar using Facebook beta version of Google Play Store. While the Apple iPhone users who see the new navigation bar that has installed the regular version of Facebook.

Android users who have installed the Facebook application is given a link to download the beta version of Facebook when they install updates. This all shows the changes coming from the server.

There is no warranty on the features of the new navigation bar. Current navigation bar is still considered to iOS or Android app.

Seven signs of dysfunctional engineering teams

I’ve been listening to the audiobook of Heart of Darkness this week, read by Kenneth Branagh. It’s fantastic. It also reminds me of some jobs I’ve had in the past.

There’s a great passage in which Marlow requires rivets to repair a ship, but finds that none are available. This, in spite of the fact that the camp he left further upriver is drowning in them. That felt familiar. There’s also a famous passage involving a French warship that’s blindly firing its cannons into the jungles of Africa in hopes of hitting a native camp situated within. I’ve had that job as well. Hopefully I can help you avoid getting yourself into those situations.

There are several really good lists of common traits seen in well-functioning engineering organizations. Most recently, there’s Pamela Fox’s list of What to look for in a software engineering culture. More famous, but somewhat dated at this point, is Joel Spolsky’s Joel Test. I want to talk about signs of teams that you should avoid.

This list is partially inspired by Ralph Peters’ Spotting the Losers: Seven Signs of Non-Competitive States. Of course, such a list is useless if you can’t apply it at the crucial point, when you’re interviewing. I’ve tried to include questions to ask and clues to look for that reveal dysfunction that is deeply baked into an engineering culture.

Preference for process over tools. As engineering teams grow, there are many approaches to coordinating people’s work. Most of them are some combination of process and tools. Git is a tool that enables multiple people to work on the same code base efficiently (most of the time). A team may also design a process around Git — avoiding the use of remote branches, only pushing code that’s ready to deploy to the master branch, or requiring people to use local branches for all of their development. Healthy teams generally try to address their scaling problems with tools, not additional process. Processes are hard to turn into habits, hard to teach to new team members, and often evolve too slowly to keep pace with changing circumstances. Ask your interviewers what their release cycle is like. Ask them how many standing meetings they attend. Look at the company’s job listings, are they hiring a scrum master?

Excessive deference to the leader or worse, founder. Does the group rely on one person to make all of the decisions? Are people afraid to change code the founder wrote? Has the company seen a lot of turnover among the engineering leader’s direct reports? Ask your interviewers how often the company’s coding conventions change. Ask them how much code in the code base has never been rewritten. Ask them what the process is for proposing a change to the technology stack. I have a friend who worked at a growing company where nobody was allowed to introduce coding conventions or libraries that the founding VP of Engineering didn’t understand, even though he hardly wrote any code any more.

Unwillingness to confront technical debt. Do you want to walk into a situation where the team struggles to make progress because they’re coding around all of the hacks they haven’t had time to address? Worse, does the team see you as the person who’s going to clean up all of the messes they’ve been leaving behind? You need to find out whether the team cares about building a sustainable code base. Ask the team how they manage their backlog of bugs. Ask them to tell you about something they’d love to automate if they had time. Is it something that any sensible person would have automated years ago? That’s a bad sign.

Not invented this week syndrome. We talk a lot about “not invented here” syndrome and how it affects the competitiveness of companies. I also worry about companies that lurch from one new technology to the next. Teams should make deliberate decisions about their stack, with an eye on the long term. More importantly, any such decisions should be made in a collaborative fashion, with both developer productivity and operability in mind. Finding out about this is easy. Everybody loves to talk about the latest thing they’re working with.

Disinterest in sustaining a Just Culture. What’s Just Culture? This post by my colleague John Allspaw on blameless post mortems describes it pretty well. Maybe you want to work at a company where people get fired on the spot for screwing up, or yelled at when things go wrong, but I don’t. How do you find out whether a company is like that? Ask about recent outages and gauge whether the person you ask is willing to talk about them openly. Do the people you talk to seem ashamed of their mistakes?

Monoculture. Diversity counts. Gender diversity is really important, but it’s not the only kind of diversity that matters. There’s ethnic diversity, there’s age diversity, and there’s simply the matter of people acting differently, or dressing differently. How homogenous is the group you’ve met? Do they all remind you of you? That’s almost certainly a serious danger sign. You may think it sounds like fun to work with a group of people who you’d happily have as roommates, but monocultures do a great job of masking other types of dysfunction.

Lack of a service-oriented mindset. The biggest professional mistakes I ever made were the result of failing to see that my job was ultimately to serve other people. I was obsessed with building what I thought was great software, and failed to see that what I should have been doing was paying attention to what other people needed from me in order to succeed in their jobs. You can almost never fail when you look for opportunities to be of service and avail yourself of them. Be on the lookout for companies where people get ahead by looking out for themselves. Don’t take those jobs.

There are a lot of ways that a team’s culture can be screwed up, but those are my top seven.