It sounds like this is the case with this guy. He may not be the one running the company, but he's discovered (like so many) that what started out as a simple "I need to write a script to X" has turned into an actual department, with him in charge.
I won't bang on the same drum as everyone else. No, actually, I will. It bears banging on. For the past year and a half I've been developing Ghost SEED, a location-based MMO for Android. It's a fair-to-large sized project with basically only me as the active developer, so it's really very similar in situation to yours. I do all of these things (in fact, my day job is worse at this than I am, and it really shows in terms of increased fire drills and general chaos requiring late nights). In order of importance:
1. Set up a test environment. If you don't have the machines for it (and you can replicate your environment on it), sign up for an AWS account. Write good tests that actually exercise all the various code paths in your scripts. *Run your tests*.
2. Pick a version control system. Any version control system is better than none. Lots of folks (myself included) like Git. It's easy to use, reliable, and there are cheap hosting solutions for it that don't require you to have to think about backups or setting up a machine for it. The better hosts also have integrated ticket tracking (so you can keep track of problems and changes) which integrates into the repository (so you can just type something like '[Completed: 451] added support for gzipping responses' in your checkin comments, and it will automatically update the ticket with a link to the commit). Lots of folks like Github. I personally use CloudbaseHQ.
3. This is a distant third. If you can develop your tests to a point where you can run them with an automated system and have it give you an at-a-glance status, you'll be in really good shape. I have a Jenkins environment (an automated build system) set up to deploy my game server from my Git repository to my test server every night and then run all the unit tests on it. I can look at the Jenkins dashboard and see at a glance if it's okay or not. There's a big green light if everything ran fine, and a big red light if they didn't.
Setting all this up took me a couple of days, which were mainly just me learning how to use the various tools (Git, Jenkins, AWS, etc). In the intervening year it's saved me immense amounts of time. I have had only three minor and one major server issues during that year, and they all could be traced back to me being in a hurry and shortcutting the system I'd set up.
I'll second the Porta Pros. I bought a pair for $45 a few years ago and was amazed at how good they sound. They're also very comfortable (they have an adjustable pad that rests on your temples and takes the pressure off your ears), and have a lifetime warrantee (they replaced the cords on mine after my daughter destroyed them for the cost of shipping).
I'm personally an in-ear guy - I mainly use a pair of Etymotic Labs MC5 earphones and a headphone amp with my iPod. The MC5s can be found for $50, and they sound awesome. They are not bass-heavy, especially with a portable media player, hence the headphone amp. I use a cmoy amp that JDS labs built for about $60. This will all take you over $50, but you don't have to spend it all at once - I used the Porta Pros for a few years, then switched to the MC5s, then bought the headphone amp a few months later.
If you do go for the JDS amp, be sure to tell them what you're listening to, and with. They'll tweak the amp to sound best with your gear and your music.
That's an easy solution, assuming that debt collectors are infallible. This is not the case. My wife got a phone call from a debt collector trying to collect on a hospital debt we knew nothing about. We talked to the hospital, and they admitted that we were not the people they were trying to collect from. Turns out the collector simply looked in the phone book for someone with the same name as the debtor (I have a common name). It took the hospital about 3 days to convince the debt collectors to lay off, with the collector leaving increasingly abusive and threatening messages.
The way the debt collection industry works, there is almost no incentive for the collections agency to actually make sure they are targeting the right person. So long as they can bluster and threaten their target into paying, they're happy.
When I was a kid, I read this TAB book about amateur radio telescopes. This was the 70s, so it was all completely analog - no DSP required. The main technique they suggested was to plot the signal strength over the course of a day to get a strip of sky, then adjust the telescope to map the next strip, etc. Their plotter suggestion, IIRC, was a homemade strip-plotter, but it would be easy enough to write a simple data logger using a computer's line in.
I'll just speak from personal experience here, without bringing in any of my philosophical views on DRM and copy protection.
I'm a programmer for a large software company, mostly working on various versions of a well-known encyclopedia. Piracy has been a concern of various manager-types off and on over the years. I've personally worked on three different copy protection schemes for the encyclopedia, and have experience with a fourth, a timed trial system. Each of those schemes has caused headaches for legitimate users - some did not validate correctly with certain drives, some did not work with certain systems, some simply did not work for no reason I could figure out. One, using a well-known copy protection library, failed so often that I had to write a special "unlock" program at the last minute, to be shipped on the CDs with the encyclopedia, so that our product support folks could just tell people "run this program from the CD".
At the same time, I saw no evidence that any of this did more than slightly annoy [i]real[/i] software pirates. I recall seeing a cracked version appear literally the day that our encyclopedia came out in stores.
In the end, after all of this, I'm convinced that the most effective copy protection we ever did was to simply print "Please do not make illegal copies of this disc" on our CDs.
IvyMike is spot on with this. I'm going to go even farther and suggest that this sort of commenting should be the default, with inline comments sprinkled sparingly, and only where really needed.
I know lots of people consider inline commenting the way to go, but they can be hellish during maintenance. If you're going to maintain a piece of code more than a couple of years old, you want to know that the comments are germane to the code. If the code is part of a consumer application (i.e.: it changes every year like the wind, yet includes code from version 1.0), chances are most of the code has been changed several times as the apps feature set or feature behavior has changed. Sure, you can "expect" programmers to change the comments to reflect the code changes, but this isn't realistic. It's bad enough to expect someone who really understands a piece of code to keep the comments up to date with it. If you have someone who has never seen a particular piece of code before going in to make a change - especially an inexperienced programmer, possibly under severe time constraints, they're not going to take the time to make sure all the comments reflect the code. It sure would be nice, but it's just not going to happen. At least, it's not going to happen often enough to give later maintainers a sense that they can trust the comments.
However, if a programmer approaches a piece of code with an understanding of what it is doing, then they won't need a bunch of inline comments to follow along. Especially if the code is written for clarity. Traditionally, if you're going to work on an unfamiliar piece of code and you really don't know what it is doing, you'll find someone who does to give you a brain dump. That's the purpose of a block comment in front of the code. Functions rarely change their purpose enough to invalidate a general brain dump about the function, while the internals can change quite radically over time. Put a nice, clear block comment in front of the function (or chunk of code), and it will still be useful in the future.
The Apple Newton is another machine with a database "filesystem". Instead of a traditional filesystem, it uses freeform object databases. The slickest thing about them are the way they integrate with NewtonScript (the high level Newton programming langauge), and the way they handle integration between multiple stores.
To appreciate how well the databases (called "soups") integrate with NewtonScript, you'd need to understand a little about it. NewtonScript is an object-oriented langauge based on parent- and proto- inheritance, rather than class-based inheritance (there are subtle differences, but the basic point is that it is object oriented and supports inheritance). The NewtonScript objects (called "frames") can be written directly to, and read from, the soups. Instead of going through a serialization layer, where the object is "flattened" for writing to the database, you can just feed the frame directly to the soup. You don't need to define the format of the frame ahead of time, either, except for the slots (object members) that you will be indexing. This means you don't have to write identical cookie-cutter objects to the soup.
Newton soups also handle multiple storage devices in a slick way. Each storage device on the newton is considered to be distinct (i.e.: you have the internal store, plus additional external stores for each memory card you stick into the Newton). On a low level, a soup exists on a single store. However, you can have identically named soups on several stores, and they will be automagically combined at a high level into a single "union soup". This happens transparently, even at the query level. If, for instance, you've queried a soup and gotten back a cursor (a regular database cursor, i.e.: effectively an array of frames from the soup), this cursor will always reflect the contents of the union soup you're querying in real time. If you eject a card that contains some of the entries in your cursor, they will disappear from your cursor. If you stick in a new card that has entries that would match the query that returned your cursor, they will appear in your cursor.
This, combined with a rather free form linking mechanism between frames, made the Newton "filesystem" a pretty interesting and powerful database.
Vaguely reminiscent of the old Mindlink controller for the Atari 2600. That had a band you stuck on your head which would detect facial muscle movements. I think it was probably more fun to watch someone else playing with it than to do so yourself...
It sounds like this is the case with this guy. He may not be the one running the company, but he's discovered (like so many) that what started out as a simple "I need to write a script to X" has turned into an actual department, with him in charge.
I won't bang on the same drum as everyone else. No, actually, I will. It bears banging on. For the past year and a half I've been developing Ghost SEED, a location-based MMO for Android. It's a fair-to-large sized project with basically only me as the active developer, so it's really very similar in situation to yours. I do all of these things (in fact, my day job is worse at this than I am, and it really shows in terms of increased fire drills and general chaos requiring late nights). In order of importance:
1. Set up a test environment. If you don't have the machines for it (and you can replicate your environment on it), sign up for an AWS account. Write good tests that actually exercise all the various code paths in your scripts. *Run your tests*.
2. Pick a version control system. Any version control system is better than none. Lots of folks (myself included) like Git. It's easy to use, reliable, and there are cheap hosting solutions for it that don't require you to have to think about backups or setting up a machine for it. The better hosts also have integrated ticket tracking (so you can keep track of problems and changes) which integrates into the repository (so you can just type something like '[Completed: 451] added support for gzipping responses' in your checkin comments, and it will automatically update the ticket with a link to the commit). Lots of folks like Github. I personally use CloudbaseHQ.
3. This is a distant third. If you can develop your tests to a point where you can run them with an automated system and have it give you an at-a-glance status, you'll be in really good shape. I have a Jenkins environment (an automated build system) set up to deploy my game server from my Git repository to my test server every night and then run all the unit tests on it. I can look at the Jenkins dashboard and see at a glance if it's okay or not. There's a big green light if everything ran fine, and a big red light if they didn't.
Setting all this up took me a couple of days, which were mainly just me learning how to use the various tools (Git, Jenkins, AWS, etc). In the intervening year it's saved me immense amounts of time. I have had only three minor and one major server issues during that year, and they all could be traced back to me being in a hurry and shortcutting the system I'd set up.
I'll second the Porta Pros. I bought a pair for $45 a few years ago and was amazed at how good they sound. They're also very comfortable (they have an adjustable pad that rests on your temples and takes the pressure off your ears), and have a lifetime warrantee (they replaced the cords on mine after my daughter destroyed them for the cost of shipping).
I'm personally an in-ear guy - I mainly use a pair of Etymotic Labs MC5 earphones and a headphone amp with my iPod. The MC5s can be found for $50, and they sound awesome. They are not bass-heavy, especially with a portable media player, hence the headphone amp. I use a cmoy amp that JDS labs built for about $60. This will all take you over $50, but you don't have to spend it all at once - I used the Porta Pros for a few years, then switched to the MC5s, then bought the headphone amp a few months later.
If you do go for the JDS amp, be sure to tell them what you're listening to, and with. They'll tweak the amp to sound best with your gear and your music.
That's an easy solution, assuming that debt collectors are infallible. This is not the case. My wife got a phone call from a debt collector trying to collect on a hospital debt we knew nothing about. We talked to the hospital, and they admitted that we were not the people they were trying to collect from. Turns out the collector simply looked in the phone book for someone with the same name as the debtor (I have a common name). It took the hospital about 3 days to convince the debt collectors to lay off, with the collector leaving increasingly abusive and threatening messages.
The way the debt collection industry works, there is almost no incentive for the collections agency to actually make sure they are targeting the right person. So long as they can bluster and threaten their target into paying, they're happy.
When I was a kid, I read this TAB book about amateur radio telescopes. This was the 70s, so it was all completely analog - no DSP required. The main technique they suggested was to plot the signal strength over the course of a day to get a strip of sky, then adjust the telescope to map the next strip, etc. Their plotter suggestion, IIRC, was a homemade strip-plotter, but it would be easy enough to write a simple data logger using a computer's line in.
I'll just speak from personal experience here, without bringing in any of my philosophical views on DRM and copy protection.
I'm a programmer for a large software company, mostly working on various versions of a well-known encyclopedia. Piracy has been a concern of various manager-types off and on over the years. I've personally worked on three different copy protection schemes for the encyclopedia, and have experience with a fourth, a timed trial system. Each of those schemes has caused headaches for legitimate users - some did not validate correctly with certain drives, some did not work with certain systems, some simply did not work for no reason I could figure out. One, using a well-known copy protection library, failed so often that I had to write a special "unlock" program at the last minute, to be shipped on the CDs with the encyclopedia, so that our product support folks could just tell people "run this program from the CD".
At the same time, I saw no evidence that any of this did more than slightly annoy [i]real[/i] software pirates. I recall seeing a cracked version appear literally the day that our encyclopedia came out in stores.
In the end, after all of this, I'm convinced that the most effective copy protection we ever did was to simply print "Please do not make illegal copies of this disc" on our CDs.
Sure, but when you have to drill this far down the discussion page to learn that the word "science" is used as jargon...
That said, it still sounds like a slick mission, other ion-driven missions notwithstanding.
IvyMike is spot on with this. I'm going to go even farther and suggest that this sort of commenting should be the default, with inline comments sprinkled sparingly, and only where really needed.
I know lots of people consider inline commenting the way to go, but they can be hellish during maintenance. If you're going to maintain a piece of code more than a couple of years old, you want to know that the comments are germane to the code. If the code is part of a consumer application (i.e.: it changes every year like the wind, yet includes code from version 1.0), chances are most of the code has been changed several times as the apps feature set or feature behavior has changed. Sure, you can "expect" programmers to change the comments to reflect the code changes, but this isn't realistic. It's bad enough to expect someone who really understands a piece of code to keep the comments up to date with it. If you have someone who has never seen a particular piece of code before going in to make a change - especially an inexperienced programmer, possibly under severe time constraints, they're not going to take the time to make sure all the comments reflect the code. It sure would be nice, but it's just not going to happen. At least, it's not going to happen often enough to give later maintainers a sense that they can trust the comments.
However, if a programmer approaches a piece of code with an understanding of what it is doing, then they won't need a bunch of inline comments to follow along. Especially if the code is written for clarity. Traditionally, if you're going to work on an unfamiliar piece of code and you really don't know what it is doing, you'll find someone who does to give you a brain dump. That's the purpose of a block comment in front of the code. Functions rarely change their purpose enough to invalidate a general brain dump about the function, while the internals can change quite radically over time. Put a nice, clear block comment in front of the function (or chunk of code), and it will still be useful in the future.
The Apple Newton is another machine with a database "filesystem". Instead of a traditional filesystem, it uses freeform object databases. The slickest thing about them are the way they integrate with NewtonScript (the high level Newton programming langauge), and the way they handle integration between multiple stores.
To appreciate how well the databases (called "soups") integrate with NewtonScript, you'd need to understand a little about it. NewtonScript is an object-oriented langauge based on parent- and proto- inheritance, rather than class-based inheritance (there are subtle differences, but the basic point is that it is object oriented and supports inheritance). The NewtonScript objects (called "frames") can be written directly to, and read from, the soups. Instead of going through a serialization layer, where the object is "flattened" for writing to the database, you can just feed the frame directly to the soup. You don't need to define the format of the frame ahead of time, either, except for the slots (object members) that you will be indexing. This means you don't have to write identical cookie-cutter objects to the soup.
Newton soups also handle multiple storage devices in a slick way. Each storage device on the newton is considered to be distinct (i.e.: you have the internal store, plus additional external stores for each memory card you stick into the Newton). On a low level, a soup exists on a single store. However, you can have identically named soups on several stores, and they will be automagically combined at a high level into a single "union soup". This happens transparently, even at the query level. If, for instance, you've queried a soup and gotten back a cursor (a regular database cursor, i.e.: effectively an array of frames from the soup), this cursor will always reflect the contents of the union soup you're querying in real time. If you eject a card that contains some of the entries in your cursor, they will disappear from your cursor. If you stick in a new card that has entries that would match the query that returned your cursor, they will appear in your cursor.
This, combined with a rather free form linking mechanism between frames, made the Newton "filesystem" a pretty interesting and powerful database.
Vaguely reminiscent of the old Mindlink controller for the Atari 2600. That had a band you stuck on your head which would detect facial muscle movements. I think it was probably more fun to watch someone else playing with it than to do so yourself...