Showing posts with label rumination. Show all posts
Showing posts with label rumination. Show all posts

2014-03-21

A Wrinkle in Time

You've built a prototype, everything is going great. All your dates and times look great, they load and store correctly, everything is spiffy. You have your buddy give it a whirl, and it works great for them too. Then you have a friend in CuraƧao test it, and they complain that all the times are wrong - time zones strike again!

But, you've got this covered. You just add an offset to every stored date/time, so you know the origin time zone, and then you get the user's time zone, and voila! You can correct for time zones! Everything is going great, summer turns to fall, the leaves change, the clocks change, and it all falls apart again. Now you're storing dates in various time zones, without DST information, you're adjusting them to the user's time zone, trying to account for DST, trying to find a spot here or there where you forgot to account for offsets...

Don't fall into this trap. UTC is always the answer. It is effectively time-zone-less, as it has an offset of zero and does not observe daylight savings time. It's reliable, it's universal, it's always there when you need it, and you can always convert it to any time you need. Storing a date/time with time zone information is like telling someone your age by giving your birthday and today's date - you're dealing with additional data and additional processing with zero benefit.

When starting a project, you're going to be better off storing all dates as UTC from the get-go; it'll save you innumerable headaches later on. I think it is atrocious that .NET defaults to system-local time for dates; one of the few areas where I think Java has a clearly better design. .NET's date handling in general is a mess, but simply defaulting to local time when you call DateTime.Now encourages developers to exercise bad practices; the exact opposite of the stated goals of the platform, which is to make sure that the easy thing and the correct thing are, in fact, the same thing.

On a vaguely related note, I've found a (in my opinion) rather elegant solution for providing localized date/time data on a website, and it's all wrapped up in a tiny Gist for your use: https://gist.github.com/aprice/7846212

This simple jQuery script goes through elements with a data attribute providing a timestamp in UTC, and replaces the contents (which can be the formatted date in UTC, as a placeholder) with the date/time information in the user's local time zone and localized date/time format. You don't have to ask the user their time zone or date format.

Unfortunately it looks like most browsers don't take into account customized date/time formatting settings; for example, on my computer, I have the date format as yyyy-mm-dd, but Chrome still renders the standard US format of mm/dd/YYYY. However, I think this is a relatively small downside, especially considering that getting around this requires allowing users to customize the date format, complete with UI and storage mechanism for doing so.

2014-03-13

On Code Comments

I've been seeing a lot of posts lately on code comments; it's a debate that's raged on for ages and will continue to do so, but for some reason it's been popping up in my feeds more than usual the last few days. What I find odd is that all of the posts generally take on the same basic format: "on the gradient of too many to too few comments, you should aim for this balance, in this way, don't use this type of comments, make your code self-documenting." The reasoning is fairly consistent as well: comments get stale, or don't add value, or may lead developers astray if they don't accurately represent the code.

And therein lies the rub: they shouldn't be representing the code at all. Code - clean, self-documenting code - represents itself. It doesn't need a plain-text representative to speak on its behalf unless it's poorly written in the first place.

It may sound like I'm simply suggesting aiming for the "fewer comments" end of the spectrum, but I'm not; there's still an entity that may occasionally need representation in plain text: the developer. Comments are an excellent way to describe intent, which just so happens to take a lot longer to go stale, and is often the missing piece of the puzzle when trying to grok some obscure or obtuse section of code. The code is the content; the comments are the author's footnotes, the director's commentary.

Well-written code doesn't need comments to say what it's doing - which is just as well since, as so many others have pointed out, those comments are highly likely to wind up out-of-sync with what the code is actually doing. However, sometimes - not always, maybe even not often, but sometimes - code needs comments to explain why it's doing whatever it's doing. Sure, you're incrementing Frobulator.Foo, and everybody is familiar with the Frobulator and everybody knows why Foo is important and anyone looking at the code can plainly see you're trying to increment it. But why are you incrementing it? Why are you incrementing it the way you're doing it in this case? What is the intent, separate from its execution? That's where comments can provide value.

As a side note (no pun intended), I hope we can all agree that doc comments are a separate beast entirely here. Doc comments provide meta data that can be used by source code analyzers, prediction/suggestion/auto-completion engines, API documentation generators, and the like; they provide value through some technical mechanism and are generally intended for reading somewhere else, not for reading them in the source code itself. Because of this I consider doc comments to be a completely separate entity, that just happen to be encoded in comment syntax.

My feelings on doc comments are mixed; generally speaking, I think they're an excellent tool and should be widely used to document any public API. However, there are few things in the world more frustrating that looking up the documentation for a method you don't understand, only to find that the doc comments are there but blank (probably generated or templated), or are there but so out of date that they're missing parameters or the types are wrong. This is the kind of thing that can have developers flipping desks at two in the morning when they're trying to get something done.

2014-02-06

You're Being Held Hostage and You May Not Even Know It

To me, net neutrality isn't about fair business practices between businesses. That's certainly part of it, but it's not the crux of the issue. To me, net neutrality is about consumer protection.

Your broadband provider would like to charge companies - particularly content companies - extra in order to bring you their content. Setting aside the utterly delirious reasoning behind this for the moment, let's think about this from the consumer's perspective. You're paying your ISP to provide you access to the internet - the whole thing. When you sign up for service, you're signing up for just that: access to the internet. Period. What your ISP fails to disclose, at least in any useful detail, is how they intend to shape that access.

For your $40, $50, $60 or more each month, you might get high-speed access to some things, and not to others. You don't get to know what ahead of time, or even after you sign up - the last thing your ISP wants is for you to be well-informed about your purchase in this regard. They'll do whatever they can to convince you that your service is plain, simple, high-speed access to the whole internet.

Then, in negotiations behind closed doors, they're using you as a hostage to extort money from the businesses you're a customer of. Take Netflix as an example: you pay your ISP for internet service. Netflix also has an ISP, or several, that they pay for internet service. Those ISPs have what are called "peering arrangements" that determine who, if anyone, pays, and how much, when traffic travels between their networks on behalf of their customers. This is part and parcel of what you and Netflix pay for your service. You pay Netflix a monthly fee to receive Netflix service, which you access using your ISP. Netflix uses some part of that monthly fee to pay for their own internet service.

Your ISP has gone to Netflix and said "hey, if you want to deliver high-definition video to your customers who are also my customers, you have to pay me extra, otherwise my customers which are also your customers will receive a sub-par experience, and they might cancel their Netflix account." They're using you as a bargaining chip without your knowledge or consent, in order to demand money they never earned to begin with; everyone involved is already paying their fair share for their connection to the global network, and for the interconnections between parts of that global network.

To me, when a company I do business with uses me, and degrades my experience of their product, without my knowledge or consent, that's fraud from a consumer standpoint. Whatever Netflix might think about the deal, whether Netflix is right or wrong in the matter, doesn't enter into it; I'm paying for broadband so that I can watch Netflix movies, I'm paying for Netflix so that I can watch movies over my broadband connection, and my ISP is going behind my back and threatening to make my experience worse if Netflix doesn't do what they want. Nobody asked me how I feel about it.

Of course, they could give full disclosure to their customers (though they never would), and it wouldn't matter a whole lot, because your options as a broadband consumer are extremely limited; in the majority of cases, the only viable solution is cable, and when there is competition, it comes from exactly one place: the phone company. The cable companies and phone companies are alike in their use of their customers as hostages in negotiations.

What about fiber broadband? It's a red herring - it's provided by the phone company anyway. Calling fiber competition is like saying Coke in cans competes with Coke in bottles - it's all Coke, and whichever one you buy, your money goes into Coke's pocket.

What about wireless? Wireless will never, ever be able to compete with wired service, due to simple physics. The bandwidth just isn't there, the spectrum isn't there, there's noise to contend with, and usage caps make wireless broadband a non-starter for many cases, especially streaming HD video. Besides, the majority of truly high-speed wireless service is provided by the phone companies anyway; see the previous paragraph.

Why aren't they regulated? The FCC is trying, in its own way, but there's little traction; the cable and telephone companies have the government in their collective pockets with millions of dollars of lobbying money, and We The People haven't convinced Our Government that we care enough for them to even consider turning down that money.

In the United States, we pay many, many times what people pay in much of the developed world, and we get many, many times less for what we spend. On top of that, our ISPs are using us as bargaining chips, threatening to make our already overpriced, underpowered service even worse if the companies we actually chose in a competitive market - unlike our ISPs - don't pay up. This is absolutely preposterous, it's bordering on consumer fraud, and you should be angry about it. You should be angry enough to write your congressman, your senator, the president, the FCC, and your ISP (not that the last will do you much good, but it can't hurt.)

Some excellent places to find more information:

2013-12-18

Engineers, Hours, Perks, and Pride

This started as a Google+ post about an article on getting top engineering talent and got way too long, so I'm posting here instead.

I wholeheartedly agree that 18-hour days are just not sustainable. It might work for a brand-new startup cranking out an initial release, understaffed and desperate to be first to market. But, at that stage, you can expect the kind of passion and dedication from a small team to put in those hours and give up their lives to build something new.

Once you've built it, though, the hours become an issue, and the playpen becomes a nuisance. You can't expect people to work 18-hour days forever, or even 12-hour days. People far smarter than I have posited that the most productive time an intellectual worker can put in on a regular basis is 4 to 6 hours per day; after that, productivity and effectiveness plummet, and it only gets worse the longer it goes on.

Foosball isn't a magical sigil protecting engineers from burn-out. Paintball with your coworkers isn't a substitute for drinks with your friends or a night in with your family. An in-house chef sounds great on paper, until you realize that the only reason they'd need to provide breakfast and dinner is if you're expected to be there basically every waking moment of your day.

Burn-out isn't the only concern, either. Engineering is both an art and a science, and like any art, it requires inspiration. Inspiration, in turn, requires experience. The same experience, day-in, day-out - interacting with the same people, in the same place, doing the same things - leaves one's mind stale, devoid of inspiration. Developers get tunnel-vision, and stop bringing new ideas to the table, because they have no source for them. Thinking outside the box isn't possible if you haven't been outside the box in months.

Give your people free coffee. Give them lunch. Give them great benefits. Pay them well. Treat them with dignity and respect. Let them go home and have lives. Let them get the most out of their day, both at work and at home. You'll keep people longer, and those people will be more productive while they're there. And you'll attract more mature engineers, who are more likely to stick around rather than hopping to the next hip startup as soon as the mood strikes them.

There's a certain pride in being up until sunrise cranking out code. There's a certain macho attitude, a one-upmanship, a competition to see who worked the longest and got the least sleep and still came back the next morning. I worked from 8am until 4am yesterday, and I'm here, see how tough I am? It's the geek's equivalent to fitness nuts talking about their morning 10-mile run. The human ego balloons when given the opportunity to endure self-inflicted tortures.

But I'm inclined to prefer an engineer who takes pride in the output, not the struggle to achieve it. I want someone who is stoked that they achieved so much progress, and still left the office at four in the afternoon. Are they slackers, compared to the guy who stayed another twelve hours, glued to his desk? Not if the output is there. It's the product that matters, and if the product is good, and gets done in time, then I'd rather have the engineer that can get it done without killing themselves in the process.

"I did this really cool thing! I had to work late into the night, but caffeine is all I need to keep me going. I kept having to put in hacks and work-arounds, but the important thing is that it's done and it works. I'm a coding GOD!" Your typical young, proud engineer. They're proud of the battle, not the victory; they're proud of how difficult it was.

"I did this really cool thing! Because I had set myself up well with past code, it was a breeze. I was amazed how little time it took. I'm a coding GOD!" That's my kind of developer. That's pride I can agree with. They're proud because of how easy it was.

This might sound like an unfair comparison at first, but think about it. When you're on a 20-hour coding bender, you aren't writing your best code. You're frantically trying to write working code, because you're trying to get it done as fast as you can. Every cut corner, every hack, every workaround makes the next task take that much longer. Long hours breed technical debt, and technical debt slows development, and slow development demands longer hours. It's a vicious cycle that can be extremely difficult to escape, especially once it's been institutionalized and turned into a badge of honor.

2013-08-04

Assumptions and Unit Tests

I've written previously on assumptions and how they affect software development. Taking this as a foundation, the value proposition of unit testing becomes much more apparent: it offers a subjective reassurance that certain assumptions are valid. By mechanically testing components for correctness, you're allowing yourself the freedom to safely assume that code which passes its tests is highly unlikely to be the cause of an issue, so long as there is a test in place for the behavior you're using.

This can be a double-edged sword: it's important to remember that a passing test is not a guarantee. Tests are written by developers, and developers are fallible. Test cases may not exercise the behavior in precisely the same way as the code you're troubleshooting. Test cases may even be missing for the particular scenario you're operating under.

By offering a solid foundation of trustworthy assumptions, along with empirical proof as to their validity, you can eliminate many possible points of failure while troubleshooting, allowing you to focus on what remains. You must still take steps to verify that you do have test coverage for the situation you're looking at, in order to have confidence in the test results. If you find missing coverage, you can add a test to fill the gap; this will either pass, eliminating another possible point of failure, or it will fail, indicating a probable source of the issue.

Just don't take unit test results as gospel; tests must be maintained just like any other code, and just like any other code, they're capable of containing errors and oversights. Trust the results, but not the tests, and learn the difference between the two: results will reliably tell you whether the test you've written passed or failed. It is the test, however, that executes the code and judges passing or failing. The execution may not cover everything you need, and the judgement may be incorrect, or not checking all factors of the result.

2013-07-04

Feature Disparity Between Web, Mobile, and Desktop

I understand that mobile is new territory, and that web applications have certain restrictions on them (though less and less so with modern standards and modern browsers), but it seems very strange to me that there are still such glaring disparities between the web, mobile, and desktop versions of some products - even products designed with mobile in mind.

Take Evernote as an example. It's been out for Android for ages, with regular new releases offering new features and functionality. Yet there are still basic features that are not available in the mobile client, including strike-through text, horizontal rules, alignment, and font face/size changes. If you have a note with these features, and you edit the note in the Android app, you get a friendly warning that the note contains unsupported features, and the editor forces you to edit paragraph-by-paragraph, like the old and irritating Google Docs app for Android. I find this more than a little bit ridiculous; why are you adding new, nice-to-have features when basic functionality is still unsupported?

Look at Google Keep for the opposite example. The mobile app allows reordering the items in a checklist with drag-and-drop. The web app doesn't allow you to reorder items. The only way to reorder items is using cut and paste. This is something you can absolutely achieve in a web app, and they've done it before, but for some reason that one, basic, important feature is just somehow missing.

The Mint mobile app allows changing budgets, but not changing whether or not the budget surplus/deficit should roll over month-to-month, which you can do in the web app. It's most of the feature, just missing one little part that can cause frustration because if most of the feature is there, you expect the whole feature to be there.

The GitHub web app doesn't even include a git client - the closest you can get is downloading a repo, but you can't actually check out and manage a working copy.

The Google Maps app for Android doesn't allow editing your "My Maps", or to choose from (or create) alternate routes when getting directions. It also doesn't include the web version's traffic forecasting. The Blogger web app is next to useless; editing a note created on the desktop gives you a WYSIWYG editor with the plain text littered with markup, and writing a post on mobile and then looking at it on desktop shows that there's some serious inconsistencies with handling of basic formatting elements like paragraphs. Don't even get me started on the useless bundle of bytes that is the Google Analytics Android app; it's such a pathetic shadow of the web application that there's no point in even having it installed.

These seem to me like cases of failure to eat your own dog food. If there were employees - especially developers or product managers - of these companies, using these applications on each supported platform, these issues would have been solved. They're the sorts of things that look small and insignificant on a backlog until they affect you on a day-to-day basis; those little annoyances, repeated often enough, become sources of frustration.

2013-06-11

Teaching a Developer to Fish

I write a lot about development philosophy here, and very little about technique. There are reasons for this, and I'd like to explain.

In my experience, often what separates an easy problem from an intractable one is method and mindset. How you approach a problem tends to be more important than the implementation you end up devising to solve it.

Let's say you're given the task of designing a recommendation engine - people like you were interested in X, Y, and Z. Clearly this is an algorithmic problem, and a relatively difficult one at that. How do you solve it? 

The algorithm itself isn't significant; as a developer, the algorithm is your output. The process you use to achieve the desired output is what determines how successful you'll be. I could talk about an algorithm I wrote, but that's giving a man a fish. I'd much rather teach a man to fish.

So how do you fish, as it were, for the perfect algorithm? You follow solid practices, you iterate, and you measure. That means you start with a couple of prototypes, you measure the results, you whittle down the candidate solutions until you have a best candidate, and then you refine it until it's as good as it can get. Then you deploy it to production, you continue to measure, and you continue to refine it. If you code well, you can A/B test multiple potential algorithms, in production, and compare the results.

How do you fish for a fix to a defect? You follow solid practices, you iterate, and you measure. You start by visual inspection, checking for code quality, and doing light refactoring to try to simplify the code and eliminate points of failure, to narrow down the possibilities. Often this alone will bring the root cause of the defect to the surface quickly, or even solve it outright. If it doesn't, you add logging, and you watch the results as you recreate the error, trying to recreate it in different ways, to assess the boundaries of the defect; if this is for an edge case, what exactly defines the "edge" that's affected? What happens during each step of execution when it happens? Which code is executing and which code isn't? What parameters are being passed around?

In my experience, logging tends to be a far more effective debugging tool than a step-wise debugger in most cases, and with a strong logging framework, you can leave your logging statements in place with negligible performance impact in production (with debug logging disabled), and with fine-grained controls to allow you to turn up verbosity for the code you're inspecting without turning all logging on and destroying the signal-to-noise ratio of your logging output.

You follow solid practices, you iterate, and you measure. If you use right process, with the right mindset, you'll wind up at the right solution.

That's why I tend to wax philosophical instead of writing about concrete solutions I've implemented. Chances are I wrote the solution to my problem, not your problem; and besides, I'd much rather teach a man to fish than give a man a fish.

2013-06-07

Code Patterns as Microevolution

Code patterns abide by survival of the fittest, within a gene pool of the code base. Patterns reproduce through repetition, sometimes with small mutations along the way. Patterns can even mate, after a fashion, by combining them, taking elements of each to form a new whole. This is the natural evolution of source code.

The first step to taming a code base is to realize the importance of assessing fitness and taking control over what patterns are permitted or encouraged to continue to reproduce. Code reviews are your opportunity to thin the herd, to cull the weak, and allow the strong to flourish.

Team meetings, internal discussions, training sessions, and learning investments are then your opportunity to improve both the quality of new patterns and mutations that emerge, as well as the group's ability to effectively manage the evolution of your source, to correctly identify the weak and the strong, and to have a lasting impact on the overall quality of the product.

If you think about it, the "broken windows" problem could also be viewed as bad genes being allowed to perpetuate. As the bad patterns continue to reproduce, their number grows, and so does their impact on the overall gene pool of your code. Given the opportunity, you want to do everything you can to make sure that it's the good code that's continuing to live on, not the bad.

Consider a new developer joining your project. A new developer will look to existing code as an example to learn from, and as a template for their own work on the project, perpetuating the "genes" already established. That being the case, it seems imperative that you make sure those genes are good ones.

They will also bring their own ideas and perspectives to the process, establishing new patterns and mutating existing ones, bringing new blood into the gene pool. This sort of cross-breeding is tremendously helpful to the overall health of the "code population" - but only if the new blood is healthy, which is why strong hiring practices are so critical.

2013-05-29

My Take on "Collective Ownership"/"Everyone is an Architect"

I love the idea of "collective ownership" in a development project. I love the idea that in a development team, "everyone is an architect". My problem is with the cut-and-dried "Agile" definition of these concepts.

What I've been reading lately is a definition of "collective ownership" that revolves around the idea of distributing responsibility, primarily in order to lift the focus on finger-pointing and blaming. A defect isn't "your fault", it's "our fault", and "we need to fix it." That's all well and good, but distributing blame isn't exactly distributing ownership; and ignoring the source of an issue is a blatant mistake.

The latter point first: identifying the source of an issue is important. I see no need for blame, or calling people out, and certainly no point in trying to use defects as a hard metric in performance analysis. However, a development team isn't a factory; it's a group of individuals who are constantly continuing their education, and honing their craft, and in that endeavor  they need the help of their peers and managers to identify their weaknesses so they know what to focus on. "Finding the source of an issue" isn't about placing blame or reprimanding someone, it's about providing a learning opportunity so that a team member can improve, and the team as a whole can improve through the continuing education of each member.

In regard to distributing ownership, it's all too rare to see discussion of distributing ownership in a positive way. I see plenty of people writing about eliminating blame, but very few speaking of a team wherein every member looks at the entire code base and says "I wrote that." And why should they? They didn't write it alone, so they can't make that claim. For the product, they can say "I had a hand in that," surely. But it's unlikely they feel like they had a hand in the development of every component.

That brings us around to the idea that "everyone is an architect." In the Agile sense, this is generally taken to mean that every developer is given relatively free rein to architect the component they're working on at any given moment, without bowing down to The Architect for their product. I like this idea, in a sense - I'm all for every developer doing their own prototyping, their own architecture, learning their own lessons, and writing their own code. Up to a point.

There is a level of architecture that it is necessary for the entire team to agree on. This is where many teams, even Agile teams, tend to fall back on The Architect to keep track of The Big Picture and ensure that All The Pieces Fit Together. This is clearly the opposite of "everyone is an architect". So where's the middle ground?

If a project requires some level of architecture that everyone has to agree on - language, platform, database, ORM, package structure, whatever applies to a given situation - then the only way to have everyone be an architect is design by committee. Panning design by committee has become a cliche at this point, but it has its uses, and I feel this is one of them.

In order to achieve collective ownership, you must have everyone be an architect. In order for everyone to be an architect, and feel like they gave their input into The Product as a whole - or at least had the opportunity to do so - you must make architectural decisions into group discussions. People won't always agree, and that's where the project manager comes in; as a not-an-architect, they should have no bias and no vested interest in what choices are made, only that some decision is made on each issue that requires consideration. Their only job in architectural discussions is to help the group reach a consensus or, barring that, a firm decision.

This is where things too often break down. A senior developer or two, or maybe a project manager with development experience, become de facto architects. They make the calls and pass down their decrees, and quickly everyone learns that if they have an architecture question, they shouldn't try to make their own decision, they shouldn't pose it to the group in a meeting, they should ask The Guy, the architect-pro-tem. Stand-up meetings turn into a doldrum of pointless status updates, and discussion of architecture is left out entirely.

Luckily, every team member can change this. Rather than asking The Guy when a key decision comes up, ask The Group. Even better, throw together a prototype, get some research together, and bring some options with pros and cons to the next stand-up meeting. Every developer can do their part to keep the team involved in architecture, and in ownership, and to slowly shift the culture from having The Architect to having Everyone Is An Architect.

2013-05-03

Be Maxwell's Demon

Source code tends to follow the second law of thermodynamics, with some small differences. In software, as in thermodynamics, systems tend toward entropy: as you continue to develop an application, the source will increase in complexity. In software, as well as in thermodynamics, connected systems tend toward equilibrium: in development, this is known as the "broken windows" theory, and is generally considered to mean that bad code begets bad code. People often discount the fact that good code also begets good code, but this effect is often hidden by the fact that the overall system, as mentioned earlier, tends toward entropy. That means that the effect of broken windows is magnified, and the effect of good examples is diminished.

In thermodynamics, Maxwell's Demon thought experiment is, in reality, impossible - it is purely a thought experiment. However, in software development, we're in luck: any developer can play the demon, and should, at every available opportunity.

Maxwell's demon stands between two connected systems, defeating the second law of thermodynamics by selectively allowing less-energetic particles through only in one direction, and more-energetic particles through only in the other direction, causing the two systems to tend toward opposite ends of the spectrum, rather than naturally tending toward entropy.

By doing peer reviews, you're doing exactly that; you're reducing the natural entropy in the system and preventing it from reaching its natural equilibrium by only letting the good code through, and keeping the bad code out. Over time, rather than tending toward a system where all code is average, you tend toward a system where all code is at the lowest end of the entropic spectrum.

Refactoring serves a similar, but more active role; rather than simply "only letting the good code through", you're actively seeking out the worse code and bringing it to a level that makes it acceptable to the demon. In effect, you're reducing the overall entropy of the system.

If you combine these two effects, you can achieve clean, efficient, effective source. If your review process only allows code through that is as good or better than the average, and your refactoring process is constantly improving the average, then your final code will, over time, tend toward excellence.

Without a demon, any project will be on a continuous slide toward greater and greater entropy. If you're on a development project, and it doesn't have a demon, it needs one. Why not you?

2013-04-17

Truly Agile Software Development


Truly agile software development has to, by nature, allow for experimentation. In order to quickly assess the best option among a number of choices, the most effective method is empirical evidence: build a proof of concept for each option and use the experience of creating the proof, as well as the results, to determine which option is the best for the given situation.

While unit tests are valuable for regression testing, a test harness that supports progression testing is at least as useful. Agile development methodologies tend to focus on the idea of iterating continuously toward a goal along a known path; but what happens when there's a fork in the road? Is it up to the architect to choose a path? There's no reason to do so when you can take both roads and decide afterward which you prefer.

Any large development project should always start with a proof of concept: a bare-bones, quick-and-dirty working implementation of the key functionality using the proposed backing technologies. It doesn't need to be pretty, or scaleable, or extensible, or even maintainable. It just has to work.

Write it, demo it, document what you've learned, and then throw the code away. Then you can write the real thing.

It may seem like a waste of time and effort at first.  You'll be tempted to over-engineer, you'll be tempted to refactor, you'll be tempted to keep some or all of the code. Resist the urge.

Why would you do such a thing? If you're practicing agile development, you might think your regular development is fast enough that you don't need a proof. But that's not the point; the point is to learn as much as you can about what you're proposing to do before you go all-in and build an architecture that doesn't fit and that will be a pain to refactor later.

Even if it takes you longer to build the proof,it's still worth it - for one thing, it probably took longer because of the learning curve and mistakes made along the way that can be avoided in the final version, and second because again, you've learned what you really need and how the architecture should work so that when you make the production version you can do it right the first time, with greater awareness of the situation.

This approach allows much greater confidence in the solutions chosen, requiring less abstraction to be built in to the application, which allows for leaner, cleaner code, and in less time. Add to that the value of building a framework that is flexible enough to allow for progression testing, and you've got the kind of flexibility that Agile is really all about.

Note: Yes, I understand that Scrum calls prototypes "spikes". I think this is rather silly - there are already terms for prototypes, namely, "prototype" or "proof of concept". I'm all for new terms for things that don't have names, but giving new names to things that already have well-known names just seems unnecessary.

Driving Algorithm

Yes, I drive by algorithm. I'm a programmer, and generally have an analytical mind. I can't help it. Here's what goes on in my head when I'm behind the wheel.

My top priority is awareness. I may drive like it's a video game, but I do realize it's the sort of game in which you only get one life. I'm constantly looking around as if I'm about to make a lane change. I try to have a picture in my head of where every car is, and how they're moving in relation to each other and myself, so I can predict where they'll be. If a car appears where I didn't expect it to be, I've already failed.

Beyond that, it's very much like a video game, in several different ways. Like many games, I need to assess my fellow players: who is being aggressive? They're likely to accelerate suddenly, and take advantage of small openings to make lane changes. I need to be careful around them and keep an extra close eye on them, but I also know they're not a bad person to be behind. Who is being cautious? They're likely to drive slower and leave more following distance. I don't want to be behind them, but I know their habits mean that they'll provide ample safe lane change opportunities in front of them. Who's being reckless, or not paying attention, or not maintaining lane? They're a hazard, and I need to keep my distance and pay close attention to them. I also pay attention to what they're driving: I know a sporty car is going to accelerate more quickly than an older car, a large truck, or a minivan.

I also need to know the map: is there an on ramp people will be merging from? Is there a lane that ends or becomes turn only? People will be leaving that lane, possibly suddenly if they aren't familiar with the area. Is there a lane that backs up due to people turning? That lane will be slower, and people are likely to dodge into the next lane to get around the traffic. Any situation with a split, where one lane goes one way and the next lane goes another way (a fork, a turn-only lane, an exit-only lane, etc.)? Both of those lanes will be slower the closer they get to the split, because of people making last-minute maneuvers when they realize their lane doesn't go where they want to be.

I also need to maintain tactical awareness. If a lane is slower, is there a reason? A slow driver or a big truck that's slow to accelerate? If a lane is faster, is there a reason for that? Is there genuinely less or faster traffic, or will the lane slow to the same speed after a few hundred feet? If two lanes are moving the same speed, will one become faster or slower? Maybe many people are leaving that lane, or entering that lane. One lane could have more gaps between cars; as those gaps close (I think of this as the traffic compressing), the lane will advance further than a lane without large gaps. One lane could also end up being slower, if there's a large truck, or a stalled vehicle, or an accident.

Generally, I try to avoid changing lanes unless there's some reason that the lane I'm moving to will end up being faster than the lane I'm moving from. All things being equal, I try to be in the lane I'm going to need to be in for my next turn/exit/etc. If I'm going to make a lane change, I'm going to take all of the above factors into account: will the lane actually end up being appreciably faster? Is there an opportunity to make a lane change, or will there be soon? Will there be an opportunity to get back into the lane I need to be in, by the time I need to be there? Or, if I'm moving into a lane that ends, will I be able to get out before it does? Would I be getting behind a slower driver that will keep me from advancing, even if the lane itself should be faster?

If I'm trying to get around one or two particularly slow vehicles, I try to plan the entire maneuver: getting out of my lane, getting ahead of them, and getting back into the lane once I've passed them. This requires awareness of my lane and the passing lane, and being able to line up both the lane exit and re-entry maneuvers.

Generally, in light traffic, knowing the other drivers and their cars tends to be the most important, because they have the biggest impact on speed of travel in each lane. In moderate traffic, all three factors are fairly equal, but map awareness has a bigger impact in general. In very heavy traffic, situational awareness becomes more important, in order to know which lane is (or will be) the least bogged down.

Yes, I honestly think this way while I'm driving. Also, I tend to sing along to the stereo. Be glad you don't have to hear it.

2012-11-17

A Programmer's Comparison of Java and C#/.NET

I've been developing in Java for almost ten years, and in C# for only a few months, so this comparison may not be as thorough as it could be. If I've missed something please feel free to comment.

Java is far more portable than C# for one. I've built applications on Windows, and ported them to Linux and Mac with minimal effort. With Android running on a Java-based platform, porting to Android is made far easier. There's no fussing with Mono and the like, no making sure you don't use any API functions that are only available in .NET.

Java also has a wide array of available IDEs with excellent features, and a huge, active community. There are libraries available for just about any technology you can think of, usually more than one, such that one of the options will likely fit your specific situation.

Java's runtime generics seem to be easier to learn and work with than C#'s compile-time generics; however, compile-time generics are likely better performing. Java's overridable-by-default scheme also makes development a lot easier in many cases. While I do understand the idea behind C#'s final-by-default scheme, I prefer a language that leaves those kinds of choices up to the developer rather than enforcing good development practices through language features.

The JVM is also now expanding to support other scripting languages, including PHP, Python, Ruby, Scala, and others.

C# has some excellent language features that I would like to see in Java, however. Extension methods are extremely useful for adding functionality to classes without having to subclass, particularly useful in adding functionality to library classes. C#'s delegate features are really excellent, and beat any workaround Java has for its lack of closures for callbacks and event handlers. The upcoming Java closure functionality looks like it will still pale in comparison to C#'s delegates.

LINQ is something I would love to see come to Java; the ability to query collections like databases is extraordinarily useful and eliminates a lot of tedious code iterating over collections. I've yet to use it for querying against a database, but it seems more than adequate for that purpose and likely much friendlier than JDBC. And while porting is more complicated, Mono is a very strong platform, and there's even a Mono module for hosting web applications through Apache.

Speaking of web applications, I have no experience so far with building web applications in C# .NET, but I have done some research. Based on that research, I have to say I significantly prefer JSP/JSTL/EL over ASP.NET. I prefer the syntax, the workflow, and JSP's tag library system over ASP.NET, which reminds me a little too much of PHP or old-school JSP (pre-JSTL/EL) for my tastes.

All in all, I can't say one is superior to the other; like any development decision, it comes down to which option is best suited to the situation and the developer. If you've had the opportunity to make that choice, please leave a note in the comments and let me know what you chose and why, I'd be happy to hear it!

2011-03-31

Dynamic Playlists

There is a feature I miss from Audion, which they removed before they retired the app entirely, that I have yet to see recreated in any other music player. It was simple. It was brilliant. I want it back.

Basically, Audion used to allow you to group tracks in your playlists into folders, and - this is the important part - check or uncheck folders to include or exclude them from the playlist, temporarily.

Big deal, right? iTunes lets you check or uncheck songs, and you can multi-select and do a bunch at once. Except that it unchecks them everywhere, not just in that playlist, and you still have to do your multi-select by hand every time.

The beauty of this was it gave playlists a sort of dynamic quality: I could have a playlist with folders for happy tracks, funny tracks, angry tracks, sad tracks, tracks with a good beat, tracks with a fast beat, etc. and so on. Then, depending on my mood, I could check, say, happy songs and songs with a good beat, when I'm in a good mood. Or angry songs and songs with a fast beat, when I'm looking to play some first-person shooters. And if my mood changes an hour later, I can uncheck parts and check other parts and it will just keep shuffling through whatever is active when it comes time to pick the next track. It was brilliant.

And I miss it, and I want it back. iTunes doesn't do it, WinAmp doesn't do it, Songbird doesn't do it, VLC doesn't do it... nobody does. And it doesn't seem like it should be necessary to write an entire music player just to get this one feature; maybe one day I'll get up the nerve to modify Songbird or VLC to do it. Or maybe, sometime between now and then, some kind-hearted developer will hear my pleas and implement it in their player. Who knows.

If anybody out there knows of a player that does have this functionality, please, let me know in the comments... I'd be forever grateful!

2009-01-08

DO WANT

Yes, both are still at the early-adopter, not-well-supported, haven't-gotten-all-the-kinks-out stage, but come on, how can you not want to combine a haptic full-3D controller with a high-def, full-color stereoscopic display? When I think about it I feel like Howard Hughes at the end of The Aviator - the way of the future, the way of the future, the way of the future.... 

Imagine a simple chess game, to take an easy example. You've got a 3D chessboard on screen, you click and drag to move pieces around, simple enough. Put on your 3D glasses, and you suddenly see the board with depth, as if its actually floating in front of you, just beyond the surface of the screen. Lose the mouse, and instead reach out and grab one of the pieces - touch it, it feels substantial, it has weight, and it has texture - feel the difference between wooden pieces and glass. Move the piece and set it down, and feel it connect with the board.

Don't like chess? Doesn't matter. Extrapolate to any game you like. See your favorite shooter in full 3D, and feel the recoil of your gun with every shot. Watch effects pop out of the screen, reach out and touch the environment you see. A whole realm of possibilities become available. It could completely change the level of 3D gaming.

While $200 for a game controller, $200 for a pair of 3D glasses, and hundreds more for a top-of-the-line LCD capable of operating stereo 3D may seem steep (especially considering that assumes you've already got a top-notch gaming rig with a recent NVidia graphics card) as early-adopter products go, that's really not bad -- it could be half the price in two or three years, if it catches on, production ramps up, and refinements are made. And if they can get developers excited about it, application support will speed its adoption and spur further improvement and innovation.

I can't wait to see what the next gen of gaming will look like. The way of the future, the way of the future...

2008-06-25

XML: No, it isn't.

XML, well, just isn't. It's a raging misnomer. XML is, in theory, the eXtensible Markup Language. I have a couple of problems with that idea.

First, it's not extensible. It just isn't. You can't extend it. I can't extend it. No one can extend it. You know how I know? Because there aren't any extensions. Not a single one. Go ahead. Go find an extension to XML. I'd love to hear about it.

But it's just as well - there's no reason to extend it. XML defines very little; it's a syntax definition, nothing more. DTDs and Schemas are what make XML useful. They aren't extensions to XML, they're applications of XML. What's more, the DTDs and Schemas can be combined in a single document, but even they can't be extended.

Second, while it can be used as a markup language, it almost never is. XHTML is a markup language based on XML. There are a few others that are (debatably) markup languages, like DocBook, but even the likes of DocBook are more on the side of data structure definition than markup. A database file isn't markup. A Java properties file isn't markup. It's a data structure. Per Wikipedia:
A markup language is an artificial language using a set of annotations to text that describe how text is to be structured, laid out, or formatted.
Does that sound like most of the XML formats you've encountered? How many XML config files have you had to deal with? Do they fit that description, even a little bit? Of course not. You don't care about the structure, layout, or formatting of the text in a config file. All you care about is getting at the particular block of text you want. So, what is XML then? Something of a generic hierarchical data file format - though I suppose GHDFF just isn't as catchy as XML.

Now, besides being aggregiously misnamed, it's also a wretched tool for nearly every purpose to which it is applied. It's a language that aims for the middle ground between human-readable and machine-readable, and while it achieves both, it does so very poorly. XML is annoying to read, tedious to write, and resource-intensive to process.

I'm not suggesting dumping XML entirely, not at all. The angle-bracket tax is a fee worth paying for actual markup - you need syntax to seperate the markup from the text. XML is a flexible and effective format for marking up text. What it isn't is an effective format for storing arbitrary data. It's usable, but nowhere near optimal. What's the solution? Something else.

Programmers have a tendency to cling to standards, to try to apply them as much as possible. "Don't reinvent the wheel," we say. And that's a perfectly reasonable mantra - but that doesn't mean all wheels are created equal. When's the last time you saw a bicycle wheel on a car? Would the world be a better place if every wheel were the same? Sure, they'd be interchangeable - but they wouldn't be anywhere near as effective.

We need to step back sometimes, and think about whether there is, or could be, a better wheel for any given situation.

More on this to come.

2007-07-30

Ultimate OS Wishlist

You'll find below my ultimate OS feature wishlist. This is from years of use of Windows and Mac OS, as well as some Linux use. Now, I know, some of these may be covered by one or more of the countless Linux distros out there, however, Linux isn't ready for my desktop (whether it's ready for the desktop is a matter for people smarter than I).

The ultimate operating system would feature:
• A completely vector-based UI with full transparency, allowing users to select not only a monitor resolution, but also a display DPI, so that large, high-density displays could be used to display the same size features at higher quality.
• An auto-update system that's open to all developers to use. Currently, modern OS's (Mac OS and Windows) supply a system auto-update feature that cannot be used by installed applications, forcing application developers to write their own, separate auto-update libraries.
• A bug/crash reporting system that's open to all developers to use. We sort of have this now, but it could get a whole lot better.
• A complete skinning/theming system that can be used to apply complete OS-wide interface makeovers, as well as skinning specific applications. Currently, operating systems typically require a seperate piece of software to skin the OS, and many individual applications provide a means to skin that application.
• Filesystem-level local revision control, and integrated access to remote revision control repositories. Revision control isn't just for programmers any more.
• A tightly-integrated, professional-quality Personal Information Manager (PIM), integrated into the system's clipboard and drag-and-drop functionality. Apple almost has the right idea here, except that the PIM applications themselves are dreck. It should be simple to use my computer, without any 3rd-party software, to store contacts, set reminders and appointments, create a to-do list, and so forth.
• Multiple clipboards and clipboard history.
• Solid remote command-line and remote desktop capabilities. Only *nix really has this nailed down. I want to be able to throw away my KVM in favor of my LAN.
• System self-optimization based on usage statistics. C'mon, guys, this can't be that hard. I shouldn't have to do much, if any, of my own optimization; operating systems should be smart enough to monitor how I use my PC and adjust system settings accordingly.
• Window-manager-level support for tabbed interfaces. It should be up to the user, not the developers, what windows and applications can be run in tabs rather than a slew of individual windows.
• A decent application launcher. Seriously, this is the core functionality of all operating systems - running applications. But still, with every OS I've ever used, I've had to install a 3rd-party application launcher to really get the most out of my system. I should have a customizable solution that completely eliminates the need for programs like QuickSilver, Colibri, Katapult, DragThing, and so on.
• Easy management of startup items. For crying out loud, this is still a pain in the ass on both Windows and Mac OS. Why?!?
• A cappuccino maker.

So, what's your OS wishlist? Post in the comments!

2007-07-27

Religion

Wow. I just found this (quite old) post from my apathosist days... although I consider myself to be an Atheist now, most of it still rings true, so I'm reposting it here.

Okay, time to cover religion. You've got your ideological religions - agnosticism, atheism, and apathosism. Atheists believe there is no god. Agnostics don't know if there is a god or not. And Apathosists don't care if there is or not, they'll find out when they get there. If you haven't guessed, I fall into the last category.

Then you've basically got three other types of religions - anglican, based around the Old Testament, the New Testament, or some Testament or another involving lots of guys with shabby clothing, unkempt beards, and a bit of an overzealous love for wine; and eastern, based around spending lots of time doing menial tasks or sitting very, very quietly for long periods of time to reach a state of personal enlightenment; and the Old Religions, which were mostly about farming, eating, killing, and procreating (and what else would you need in life?)

And then, of course, there are the Unitarian Universalists, who believe in stuff, and who evangelise door-to-door in comfortable shoes saying "Hello, I'm with the Unitarian Universalist Church, and I was hoping you could take a moment to hear the joys of, well, whatever you believe in, being, ah, really really good, and all." If you've ever been to a Unitarian church, you'll notice a lot of Birkenstocks and Ugg boots and other brand-name hippie footwear. In fact, as a kid, for a brief while, I went to a Unitarian youth program at Our Lady of Sensible Shoes - fantastic lot, lots of candles, cork sandals, sex ed is done every year 5th grade through high school at an anual sleepover weekend at the church (good planning...) Makes for an interesting childhood, lemme tell ya.

And Unitarian ministers are great - they all sound like announcers from NPR, or maybe subliminal tape voiceover actors from Canada. Very polite, always soothing tones, lots of talk about how pretty the trees and the sky and the flowers are. Very politically correct church, they try to keep it non-denominational - no, not easy in a church, but if it's not a challenge, it's probably not worth doing, right? Or maybe it's just not worth doing right? I always get those confused...

So anyway, and then there was the Unitarian Inquisition - "Excuse me? Ah, excuse me?" "Yes?" "Well, I was just wondering... what do you believe?" "What do you mean?" "You know, the whole god, devil, afterlife thing - what's your stance?" "Well, I'm a Pagan, as a matter of fact." "Ahhh, yes, very good. Good for you, that. Hope you're enjoying it." "Well, the orgies are nice..." "Ah, yes... Ahh.... Have some tea?" "Well, aren't you supposed to be putting me on the rack now?" "What? Oh, goodness no... that'd be terrible... we might light some candles later..." "Candles?" "Yes, candles, love the things, can't get enough of 'em. May I ask another question? Do you have a comfortable pair of shoes?"

So, yes. That's the UU Church. I also did the Old Gnostic Mass for a while, that's pretty interesting, a dozen drunken Jews in Southern California putting on a Shakesperian play set in Pagan Rome with nude women and oh, what the hell, we'll use whiskey for sacrement, can't find the wine, whiskey's better anyway, I always feel closer to God after I've had a few. "There is nothing in me that is not of the Gods." Unless you're Michael Jackson, in which case most of what's in you is synthetic anyway.

I've done pagan circles too - again with the whiskey. I find that the alternative religions tend to very quickly decide that hard liquor is much more religious than wine. And if those stale crackers are the body of Christ, I really have to worry about the guy. I understand people are supposed to taste like pork, not cardboard. He might want to have a quick chat with God about that one. "Excuse me, dad?" "Yes?" "Well, I was wondering.... why do I taste like crap?" "Ahh, well... Huh... Hadn't really thought of that... Ahhh... well, you see, it's... it's, ahh.... it's all Adam's fault, that bastard! He - he made me do it!Yes, that's it..."

So, yeah. That's religion in a nutshell for ya. If you're still having trouble choosing one, go with Apathosism, it's easier, and it lets you have a lot more fun.

2007-05-04

Wired vs. Wireless

I was talking to my mom today, and she wanted to set up a wireless network. I advised against it,
and her argument was that wired networks seem archaic.

Now, while I can certainly understand the idea that the same cables we've been using for decades are still just fine today may be hard to swallow, but in reality, wired networking is advancing far faster than wireless.

Wireless networking, over the last decade, has gone from 11mbit (802.11b) to 54mbit (802.11g) to "up to 700mbit" (802.11n; effectively 100 - 200 mbit). This bandwidth is per airspace - multiple clients on a network, and multiple networks in the same airspace, must share the available bandwidth.

Meanwhile, wired networks have gone from 10 to 100 mbit, then to 1 gbit and now 10 gbit, all on copper cable. And each client on a wired network gets a dedicated, full-bandwidth pipe all to its own.

So, while the cables may not have changed much (cat 6 is hard to tell from cat 5 to the average person), wired networks are advancing far beyond wireless, and all the while, they provide greater reliability, security, ease of use, and power efficiency.

All in all, I'll keep my wired network.

2007-03-14

Urgent Apps - Mac Development Kit

After yesterday's post, I got to thinking. I had pulled some items out of that list because they were highly developer-centric applications. However, that does mean that some really top-notch programs didn't make the list, and I think that's unfair. There are some apps that I really can't live without when it comes to development work.

Before we begin, I should point out that my particular development tasks typically include the administration of a MySQL database, editing PHP, Java, HTML, CSS, and JavaScript files, and operating revision control; the tools laid out here are centered around those tasks.

Now, without further ado, the list:

jEdit

jEdit calls itself "the programmer's text editor", but that's selling it short. jEdit is, to put it lightly, a god among executables. I've never seen another program come close to its level of flexibility, modularity, and customizability. The sacrifice for all this goodness is that it's a bit of a RAM-hog, particularly running under the MacOS JRE (I highly recommend updating to the 1.6 JRE available on apple's website, and completely switching over to 1.6; it provides some vast performance and footprint improvements.)

NetBeans
NetBeans is, of course, the Java IDE, unless you're one of those people that thinks that Eclipse is the Java IDE, but I'm not.

SmartSVN (payware)
The best SVN client I've seen for the Mac. Unfortunately, there aren't many good free options.

MySQL GUI Tools
The real deal, straight from the source.

Platypus
This nifty little app lets you take any shell or other script file and turn it into a Mac application package.

ArgoUML
Java-based UML designer.

Subversion
Revision control extraordinaire. Any box I do development on has a local Subversion server for anything I happen to want to keep a history for.

Trac
I've recently fallen in love with Trac, which is why it made the list. It's not exactly an application - it's a web application. However, it can be installed on a Mac, so it made the cut, and I do love it dearly. Go check out their page; the Trac site runs on Trac.


Anything I'm missing? Post in the comments!!