Symphonious

Living in a state of accord.

Swift

Apple have released Swift, their new programming language – designed to be familiar to Objective-C programmers and work well with the existing Cocoa frameworks. It’s far too soon to make substantial judgements about the language – that can only come after actually using it in real projects for some time. However, there’s nothing that stands out as incredibly broken, so with Apple’s backing it’s extremely unlikely that it won’t become a very commonly used language. After all, there’s plenty wrong with every other programming language and we manage to make do with them.

What I find most promising about it though is that many language design choices are justified by them preventing common causes of bugs in Objective-C or C (and many other languages).  For example:

“The cases of a switch statement do not “fall through” to the next case in Swift, avoiding common C errors caused by missing break statements.”

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks

They’ve replaced many common checkstyle/lint errors with better language design that the mistakes impossible (what a good idea). It could be argued that they could have taken more extreme approaches to find solutions or prevented more sources of errors with additional cleverness but my initial take is that it has likely found a good balance between fixing common causes of bugs while still being familiar to Objective-C coders (it’s target audience) and working well with the existing frameworks and libraries.

We’ll likely find plenty to complain about, as always, but overall I suspect it will be a very nice language to work with.

Static and Dynamic Languages

I do a lot of coding in Java and JavaScript and it’s never bothered me that one has static types and one dynamic (and I’ve used plenty of other languages from both camps as well – it amuses me slightly that the two I use most often tend to be viewed as the worst examples of each type). I can see pros and cons of both approaches – static typing detects a bunch of common errors sooner which saves time but there are inevitably times where you wind up just fighting the type system which wastes time again. Better statically typed languages waste less of your time but at some point they all cause pain that’s avoided with dynamic languages. It winds up coming down largely to personal preference and is a little affected by what you’re building.

What I have learnt however is that using static and dynamic languages too closely is a recipe for pain and frustration. LMAX develops the main exchange in Java and recently started using Spock for unit tests. Spock is amazing in many, many ways but it comes with the Groovy programming language which is dynamically typed. There isn’t, or perhaps shouldn’t be, any tighter coupling than a class and its unit test so the combination of static and dynamic typing in this case is extremely frustrating.

It turns out that the way I work with languages differs depending on the type system – or rather on the tools available but they are largely affected by the type system. In Java I rename methods without a second thought, safe in the knowledge that the IDE will find all references and rename them. Similarly I can add a parameter to an API and then let the compiler find all the places I need to update. Once there are unit tests in Groovy however neither of those options is completely safe (and using the compiler to find errors is a complete non-starter).

When writing JavaScript I’m not under any illusion that the IDE will find every possible reference for me so I approach the problem differently. I explore using searches rather than compiler errors and turn to running tests to identify problems more quickly because the compiler isn’t there to help. I also tend to write tests different, expecting that they will need to cover things that the compiler would otherwise have picked up. The system design also changes subtly to make this all work better.

With static and dynamic typing too closely mixed, the expectations and approaches to development become muddled and it winds up being a worst-of-both-worlds approach. I can’t count on the compiler helping me out anymore but I still have to spend time making it happy.

That doesn’t mean that static and dynamic languages can’t co-exist on the same project successfully, just that they need a clearly defined, and relatively stable, interface between them. The most common example being static typing on the server and JavaScript in the browser, in which case the API acts as a buffer between the two. It could just as easily be server to server communication or a defined module API between the two though and still work.

Automated Tests Are a Code Smell

Writing automated tests to prove software works correctly is now well established and relying solely or even primarily on manual testing is considered a “very bad sign”. A comprehensive automated test suite gives us a great deal of confidence that if we break something we’ll find out before it hits production.

Despite that, automated tests shouldn’t be our first line of defence against things going wrong. Sure they’re powerful, but all they can do is point out that something is broken, they can’t do anything to prevent it being broken in the first place.

So when we write tests, we should be asking ourselves, can I prevent this problem from happening in the first place? Is there a different design which makes it impossible for this problem to happen?

For example, checkstyle has support for import control, allowing you to write assertions about what different packages can depend on. So package A can use package B but package C can’t. If you’re concerned about package structure it makes a fair bit of sense. Except that it’s a form of testing and the feedback comes late in the cycle. Much better would be to split the code into separate source trees so that the restrictions are made explicit to the compiler and IDE. That way autocomplete won’t offer suggestions from forbidden packages and the code won’t compile if you use them. It is therefore much harder to do the wrong thing and feedback comes much sooner.

Each time we write an automated test, we’re admitting that there is a reasonable likelihood that someone could mistakenly break it. In the majority of cases an automated test is the best we can do, but we should be on the look out for opportunities replace automated tests with algorithms, designs or tools that eliminate those mistakes in the first place or at least identify them earlier.

 

Finding Balance with the SOLID Principles

Kevlin Henney’s talk from YOW is a great deconstruction of the SOLID principles, delving into what they really say as opposed to what people think they say, and what we can learn from them in a nuanced, balanced way.

Far too often we take these rules as absolutes under the mistaken assumption that if we always follow them, our software will be more maintainable. As an industry we seem to be seeking a silver bullet for architecture that solves all our problems just like we’ve searched for a silver bullet language for so long. There is value in these principles and we should take the time to learn from them, but they are just tools in our toolkit that we need to learn not only how to use, but when.

Don’t Get Around Much Anymore

Human Resource Executive Online has an interesting story related to my previous entry:

Ask yourself this question: If you were offered a new job in another city where you have no ties or networks, and you suspected that the job would probably not last more than three years (which is a good guess), how much of a raise would they have to give you to get you to move? Remember, you’d likely be trying to find a new job in a place where you don’t have any connections when that job ended. I suspect it would be a lot more than most employers are willing to pay.

Again though this should be driving up the number of remote jobs, but where are they all?