Sergey Mikhanov | |
Logging is the new commenting (July 3, 2013)Back in 1999, when I was in the university, I was studying the C programming language — just like every other CS major in the world. In our little programs, there were header files and implementation files and everyone in my class, myself included, learned quite early that the number of files in your project will grow twice as fast as you add what our mentor was calling “a new compilation unit.” Someone in the class — unfortunately, not me — pointed at this obvious design “flaw.” Really, why do you have to duplicate your effort? All the information compiler needs about your program is in the implementation file already. I have only learned later that this is the point where most of the programmers start their affairs with more concise programming languages. But the lesson of that day was clear — duplication is bad. One semester later everyone in class got their copy of 3rd edition of Bjarne Stroustrup’s “C++ programming language”. One quote I learned almost by heart. It was — this time, fortunately — not related to C++ itself (it’s from the chapter 6.4 Comments and Indentation):
As much as I dislike C++, the writing style of its author is excellent. For the next ten years or so of my programming career I was barely leaving any comments in the code I wrote. Of course I did understand that comments could potentially be useful in the future for anyone reading the code (myself included) but writing code seemed easy and no explaination was needed. Throughout the same years I discovered the usefulness of logging; it was so helpful that I stopped using debugger completely. Here’s an example snippet from a deliberately incomplete recent program. Note the amount of logging statements: - (NSArray *)unify:(GAClause *)query with:(NSDictionary *)base dynamicContext:(NSArray *)dynamicContext { DLog(@"Unifying query %@, dynamic context is %@", query, dynamicContext); NSMutableArray *result = [NSMutableArray array]; GATuple *selfUnified = [query selfUnify:nil dynamicContext:dynamicContext]; if (selfUnified) { DLog(@"Query self-unified, got tuple: %@ ", selfUnified); NSMutableArray *tuples = [NSMutableArray array]; for (GATuple *t in dynamicContext) { [t merge:selfUnified]; [tuples addObject:t]; } DLog(@"Merged self-unification result with dynamic context: %@", tuples); return tuples; } else { for (GAClause *left in [base allKeys]) { GAClause *right = [base objectForKey:left]; GATuple *tuple = [self unifySingle:query with:left dynamicContext:result]; DLog(@"Bindings after unifying: %@ (clauses were %@ and %@)", tuple, query, left); if (!tuple) continue; [result addObject:tuple]; DLog(@"Accumulated result: %@", result); if (![right isEqual:[GAConstant kTRUE]]) { Objective-C methods - (NSArray *)unify:(GAClause *)query with:(NSDictionary *)base dynamicContext:(NSArray *)dynamicContext { // Unifying query with dynamic context NSMutableArray *result = [NSMutableArray array]; GATuple *selfUnified = [query selfUnify:nil dynamicContext:dynamicContext]; if (selfUnified) { // If we reached here, query is self-unifyable NSMutableArray *tuples = [NSMutableArray array]; for (GATuple *t in dynamicContext) { [t merge:selfUnified]; [tuples addObject:t]; } // Merged self-unification result with dynamic context return tuples; } else { for (GAClause *left in [base allKeys]) { GAClause *right = [base objectForKey:left]; GATuple *tuple = [self unifySingle:query with:left dynamicContext:result]; // Finished unifying, variable bindings now created if (!tuple) continue; [result addObject:tuple]; // At this point we have partly accumulated result if (![right isEqual:[GAConstant kTRUE]]) { Once you’ve got the logging, the need in having lots of comments in code reduces dramatically. You don’t need to duplicate your effort. You even can get rid of the downsides described by Bjarne Stroustrup, because someone running a program and reading its logs will make sure the output is meaningful, descriptive and current. Logging therefore becomes a better commenting system, helpful both during runtime and when figuring out what a particular piece of code does. Given the flexibility and robustness of modern logging frameworks available in any language, there are very few reasons to use lots of comments. Just log more. If you could have infinite coding speed, what project would you work on? (October 3, 2011)I love contemporary art. It exists within its own universe, driven by the principles artists sometimes invent on the fly. It’s an incessant journey towards pure aesthetics while trying to ignore consumer, political, religious and social values, a constant search of meaning. Exciting stuff. It so happened that I’m a founder and a programmer and gallery visits and books usually limit my exposure to the art world. But every time I encounter some new insight on the artists’ way of doing work I try to make parallels with programming. For example, would a practice similar to one of copying masters’ work — it does exist in art schools — help a young programmer’s development? If you sit and rewrite, say, V8 (if you’re into hardcore C/C++) or Sinatra (if you’re a Ruby ninja) while peeking at the original periodically, would that make you a better programmer? While it’s not clear how useful this way of using your time is, we can afford another short thought experiment. Here’s a small quote of the very famous art curator, Hans Ulrich Obrist:
The most important context we, as developers, exist in, is the one scoped by code complexity (that increases as any project grows) and the actual time required typing those lines of code. What would be your project if you could get rid of those limits and have your project done and working as soon as you finish typing Let’s assume we don’t gain magic powers together with infinite coding speed. I.e. if your problem is not Turing-decidable or does not have a clear solution yet (like the task of high-quality speech recognition, for example) or belongs to NP, we still can’t solve it. Now that’s a tough one. I once started writing a Twisted-like protocol framework in Haskell — my pet project some time ago. Six years spent doing telco development where having time to market in the range of months and not years is a huge win, and where requirements of software uptime and reliability are insane made me think that having a platform written in more expressive and rigid language might be useful. While it would be nice having this framework in no time, it could only be proven useful with the real-world constraints in place. Can we develop useful applications on top of this platform quickly? Nobody can say in advance. In other words, even with infinite coding speed, this project might be both a hit or a miss. My current project, Scalar, mostly consists of UI/UX challenges. We’re trying to invent new way of doing complex calculation on iPad and as soon as we’re able to figure out how to present things on the device and how to allow users to interact with them, coding is pretty trivial. It’s clear that Scalar would greatly benefit from us having the infinite coding speed, but its total development time wouldn’t be reduced to zero. Moreover, its commercial success would be far from guaranteed even in this case. At this point I started to wonder: could you turn at least any project into a hit by having the infinite coding speed? You can build something marginally better than Square, but you still have to spend time wearing suits to meetings with bankers. You can quickly build something that will combine Lonely Planet with Gowalla and Instagram, but you can’t speed up travel writers taking data out of Quark Xpress files and putting them into your database. Even with systems programming, reducing implementation time to zero does not seem to help. Could you instantly build something better than VMWare and win their market, for example? Not so sure. Or can you profit from implementing a GFS-like file system in no time? It looks like even the wildest dreamers with will hit the wall here. If you could have infinite coding speed, what would your project be like? How did we get here (September 26, 2011)Well, that Feynman quote was on the top for very long — more than half a year, actually. In the meanwhile I left the world of large corporations to have a ride of my own. The project I work on now is called ScalarĂ‚Â², it’s an app that aims to disrupt the way people carry out calculations on iPad. How did all this happen? A year ago, when Esad and I at now defunct Critical Point Software were trying to invent an idea for a new app, we felt like we were running in circles. We have just tasted minor success with our subway maps app Transit and travel apps niche seemed promising. We tried thinking about local area guides, but nobody of us wanted to deal with well-funded too-Viennese Tripwolf. It turned out to be a good idea: despite attempts from big players, no company seems to create the mobile travel guide that would be truly great; what could two folks with day jobs have done? So in short, we stuck. And we decided to go for the idea that was on the surface: just write a better calculator for iPhone. The one built into the phone was definitely not good enough. There were virtually no competitors, except for Soulver, the old big player in this niche. The app would be data-independent: we learned the hard way with Transit that having an app that strongly depends on the external data you collect makes support a nightmare. So, according to We got modest sales, but people seem to love our tiny app. Reviews were very positive despite all the wrinkles, like, for example, the fact that calculations were almost set in stone after you enter them at that time (there was a backspace key, but you couldn’t modify anything in the middle of your calculations). After we decided to split the assets with Esad (won’t go into details here), I took the app with me because I loved the idea and I felt we could be onto something here. The Scalar development stalled for few months. When I decided to leave my day job, the competitive landscape was still almost clear. Tapbots released Calcbot but it was clearly a well-designed toy, not really an app for calculating. Soulver was now available on iPhone and iPad, firmly sticking to the initial vision of having everything in the app in text form — not the best form for touchscreens. Apple’s Numbers were now available on iPad, but heck, isn’t there a place for something new on this magical device, not just a remake of 30-year old killer app? I already had my sleeves up and was looking for the project to focus on, when I saw this Apple’s commercial (I encourage you to spend 30 seconds of your time and watch it): See? Nobody works with numbers, even the CEO! So I was about to make something people would love to use instead of the spreadsheets, something that’ll have no tiny cells or won’t force you to type In the middle of this summer I was full steam ahead with development. Convenient edit functionality: check. Built-in analytics for better understanding of users’ behavior: check. Multi-document support: check. Text handling to allow people to leave any annotations next to their numbers: check. I implemented and tried three different UI metaphors to allow selection of some parts of your calculations just to find out that no UI metaphor is needed. Simpler is better: one finger swipe means scroll, two fingers swipe means select. Storing parts of your calculation for referencing them later: check. Pinning them to have them always in sight: check. After all this was done, I moved my budget data from a Google spreadsheet to the working version of Scalar on my iPad and never looked back. This is where we stand now. Dogfooding is a key turn for a small company with a big vision: from this moment on you only embarrassed of what you’ve built if you can’t use it the way you envisioned. I, for one, only feel proud now. A quote from Surely You’re Joking, Mr. Feynman! (February 1, 2011)
Self-learning is overrated (in programming) (October 10, 2010)Few weeks ago I had series of interviews in two top-tier investment banks. I was applying for development position in similar departments, but the technology stacks those two banks were using varied wildly: from hardcore low-level multithreaded Java in one to Haskell/F# in another. The outcome of those interviews provoked some thoughts abouth whether self-education means that much when a well-paid position in a respectable company is at stake. First of all, banks are always a good indicator of the position’s value in business terms. Startups may hire people to explore the previously unknown areas, to experiment with products that might have very little or no monetary value at the moment. To the contrary, banks are dealing with the established business models and are rarely tolerating even short-term decreases in the added value that every person brings to the company. They hire people to earn money for the bank, not to experiment, and they pay those people accordingly. This usually sets the interview direction from the very beginning. I have around 10 years of industrial experience with Java, interruped by few years of enterprise C# development. So despite being exhaustive (two people on the other end of the phone line asking one question after another in the course of hours), interviews for the Java position went pretty smooth. How to implement a fair lock? What’s a GC generation and what are they used for? What would you do if you need soft-realtime Java system? How to avoid resource contention? Deadlock? Livelock? Can you implement locking without using synchronized keyword? Synchronized container that will use locking less often than a standard one? And so on and so forth. Fortunately, most of those question constitute part of my day job, so it was nice to have this brain excercise. Not so with Haskell/F# interviews. I didn’t had a chance to gain any industrial experience with functional programming — I bet lots of people practically interested in FP didn’t. I was asked about type inference results for some specific function combinations, possibility of Haskell program to be as fast as C program, type covariance and contravariance in .NET, the way to control state and side effects with monads, existential types, a bit about the way Haskell supports multithreading, short “what is STM?”, and so on. Shortly after the interview I found a polite “no” in my mailbox. I myself wasn’t satisfied with my performance, so this wasn’t a surprise. At this point I was happy that my experience with resolving all sorts of problems in the real industrial environment gave me a chance to learn what I know about Java. I felt what it is like to be in shoes of self-learner. One bright guy who fleed from the enterprise development to the AI-related work wrote this:
Real industry does not work like that too. I can’t imagine a self-learner to know the nuts and bolts of Java GC, just as I didn’t felt too confident about existential types. I simply never had an external pressure that would throw me into the necessity to know ins and outs of Haskell by heart, and pragmatic books (Haskell, as all you know, have one) no matter how good, do not help with that. Self-learner is like a fresh college graduate: he simply has to start his way from the lowest positions again. No amount of self-learning can come near years of work in a mission-critical environment when company’s revenue is at stake. |
|
Entries (RSS) | © 2007–2017 Sergey Mikhanov | |
|