How can I get away with dynamic typing?
I lost motivation to all the Unity/C# projects I started during the warm summer days. It feels like any deployment gains are erased by the development pains these tools put you to suffer.
I am sure that many people have no idea of what I'm talking about. Chances are you're already aware of the things that drove me away. There are likely many who wonder how can I get away with python.
How come I haven't sticked up with Haskell, or even that Julia -language that is supposed to exactly cater my kind of people?
How can I get away without compile-time type checking?
I mostly can get away without compile-time type checking, because I make sure that the code I am interested at any time is capable of reloading and running immediately whenever I want to check the correctness.
Oftentimes this means that my programs are written in a manner that the actions I am interested about observing behave in repeatable manner and can be displayed on the screen. My programming style automatically catches all kinds of locally appearing errors, not just type or syntax related.
Since I am used to this kind of programming style, I feel troubled if I need to recompile the whole program to test something. I also feel abused if the compiler prevents me to run a program because of an error that is unrelated to the current piece of code and problem I'm trying to solve.
It's commonly quipped that each error detected at compile-time prevents a runtime error. Few people notice that runtime error that was "prevented" isn't the "error" that was detected.
I don't feel very straitjacketed into single type either. In practice the actions that I do over the certain value flow limit what the values can be.
And it turns out that it's often what you want. C++ programmers love template metaprogramming so much that their hello world takes a whole second to compile. In python I can use metaprogramming for cooler things.
How come someone's straitjacket can be other persons cotton bras?
How can I get away without 10x code coverage in unit tests?
I don't use unit tests much at all. They often don't seem to gain anything I already get by other means.
One of the reasons why I can fare with dynamically typed languages is that I follow the principle described in Joe Armstrong's "Making reliable distributed systems in the presence of software errors". The principle is: Let the program fail when it is pointless to proceed. I code my programs in a way that they fail whenever things start to go wrong.
Sometimes I write code with sole purpose to do a consistency check into other code. This is the same method mathematicians use to verify they didn't do an error. This kind of cross-checking often eliminates any errors I may do into complex piece of code.
You may wonder what do I do if the code is mission critical and I can't test it prior the real deal? Well.. in that case neither the compiler or even proof-checking is able to deal with it. That's because you know.. you actually need prior information to produce predictions.
For a lot of error checking I rely to just notational clarity and documentation. The code tends to be cleaner better I understand it.
How can I get away without automatic code refactoring tools?
I mainly maintain my code by scoping rules and visibility. I tend to make sure only the program sections that really have to access it, will access it. This gives me lot of freedom in rewriting code locally.
On global changes I usually solve this problem by rewriting enough, and keeping the old interface aside until the rest of the code has been revised around it. Additionally the change rarely is just change of variable names because change for just sake of change isn't usually relevant.
In commercial software you can't always rewrite on others turf. You potentially have third parties that will get pissed if API of your system suddenly renames methods as commonly proposed. In practice you end up with duplicated interfaces anyway.
The difference is that I tend to eliminate the old interfaces eventually and document changing interfaces. I don't pretend that redundant and ancient APIs aren't potentially damaging.
How can I get away without intellisense?
The common trait I saw between C# software are inbearably long method names with occassional arbitrarily selected CamelCase. This is one of the things that keeps causing short-term burnouts when I try to code in that language.
I tend to prefer names that have been used to name same things before. I use
dot(a, b) instead of
Vector3.Dot(a, b), because GLSL denotes it that way.
Unsurprisingly become great at picking names when you practice giving names. It helps if you have a healthy writing hobby and a proper mechanical keyboard that is actually meant for typing.
There's still the problem of what do I do if I don't know the name? Well there the scope visibility comes to help. In python your program only sees what it imports, and you can easily trace down to what is actually imported from that file's location.
Given that the modules contain functionality that is relevant together, a quick peek into concise reference reveals two or three names I need to remember.
With intellisense it's not exactly any simpler, except that the intellisense bothers you even if you remember the names. It's a crutch for handicapped from my perspective.
Besides, if I have no source or documentation available, I still can run an introspection with
dir -command onto some code, giving me a customizable 'intellisense' when nothing else works.
How can I get away with garbage collection, runtime type information and slowness of python?
I can translate python into faster code variants whenever there's a need. But I usually just tolerate that the code isn't "fast" when I write it the first time because I prefer gaining understanding of the problems before optimizing anything.
Some profiling often reveals that I can get away with just being smarter inside python.
Also, performance tends to matter only on programs that run for prolonged periods, and the problems concentrate on short pieces of code. I suppose there will be time when pypy outperforms C in performance because it optimizes what is needed rather than the whole thing.
What would I actually need?
Treating things with graphics, I mostly yearn for good computer algebra systems that I can use to interactively study massive computations.
sympy partially delivers that to me, within the same language I commonly use for all my programming tasks.
I need tools to translate my nice python programs into ugly but efficient programs. Pypy has partially delivered that to me and I suppose it will eventually succeed to deliver the whole set for translating python programs
Languages that default to static typing, in my opinion, do not bring anything of significance to the table. They are really good at introducing new and additional complexities though.
You know there was one cool thing in C#. That was the runtime type introspection. Basically the things that copycat dynamic language features in C# to reduce the amount of useless boilerplate code you have to write. That was the greatest time-saver that C# ever provided to me.
But it was still insufficient...