830 karma · joined December 3, 2008
1. Everything looks difficult the first time. The hardest step is always the first one. Take a deep breath and just "begin".
2. Never give up. Even impossible tasks are just lots of easy, smaller tasks. Learn to break things down into manageable pieces.
3. When in a time crunch (e.g. a test), learning to triage is a very important skill. Don't get stuck. Just skip and move on. Come back later. Learn to prioritize, etc.
4. Don't be scared. Everyone gets it wrong sometimes. You'll never succeed if your too afraid to fail.
5. Trust your gut. If something seems wrong, then it very well may be. Don't just accept someone else's answer because you don't happen to know the answer.
6. Always verify your answers. Don't just finish a problem and assume it's right. And learn to verify the answers of others as well.
Finally, never ever ever say "I'm not good at that." Say "I'm not good at that YET!" That little difference over time is reminding yourself that you could learn/do it if you wanted, you just haven't learned to yet.
1. Compiled (native) vs. interpreted (bytecode/VMs). It's this forever cycle of "performance required" that shifts to "portability required", which lacks performance, and gradually shifts back, and repeat.
2. Local processing vs. dumb terminals and shared computing. The current "dumb terminal" phase being the idea that you can buy a $100 Chromebook and working entirely online.
That said, PUT and PATCH can be quite useful if you're dealing with CRUD operations. If you want or need your API to be idempotent, use POST for creation and updating. If being idempotent isn't a requirement - or even a negative - then adhere to the convention: POST for creation and PUT/PATCH for update.
PATCH is really nice to support when your objects are even moderately large or you want to reduce bandwidth costs. For example, let's say you have a user object in a NoSQL DB and each user is a JSON object with 100 keys. If you use POST or PUT to update, you're basically requiring that the user of your API...
* Perform a GET to actually fetch the entire user object * POST/PUT the entire object back with the changes
In addition, you're likely going to want the API to track the version of the object, otherwise you run into issues with multiple clients trying to update at the same time. This can be very problematic when updating the entire object. So you're basically wasting cycles on the server fetching data, wasting bandwidth for data that isn't going to be used at all, and possibly writing extra code to handle conflicts.
With PATCH, you don't need to GET anything. You can update fields pretty easily w/o even knowing what's already there:
PATCH /user/12345 { "age": 10 }
Very little bandwidth is used. If you still need versioning along with that (yes, you do if this is more than a pet project) to resolve conflicts, then you can use a HEAD request for the user and return the version of the object in an HTTP header. Multiple patches from different versions can all be successfully applied on top of each other until a conflict arises. But, then you're getting into vector clocks or other solutions that are outside the scope of the question.
Circling back, yes, PUT and PATCH can be very useful. ;)
HTH
Some UI suggestions:
* When adding a custom format, allow for an "X" to remove it as well.
* Clicking on any of the output formats should automatically copy the text to the clipboard. I like that it selects it, but it also selects the label as well (at least on FF). A straight copy would be more useful.
And some date/time suggestions from someone who's had to deal a LOT with dates and times. I realize you're using libraries for a lot of the heavy lifting, and maybe some of the ideas below aren't what you want to do with it, but they are real needs:
* Allow setting a custom epoch for both input and output.
* Allow setting a location other than the current location for output. Likewise, allow enabling/disabling of daylight savings for the user-provided location.
* It's currently impossible to represent any date before Jan 1, 100 AD.
* Non-Gregorian calendar support would be really, really nice, too (e.g. it's currently 4718 AH using the Chinese calendar and 1442 in the Islamic calendar).
To date I've just been using https://www.epochconverter.com/ for a lot of my day-to-day work, but I like your input more. You may find some ideas there as well.
Sometimes you'd get interviewers who were at least smart enough to realize that maybe the most you'd get out of it is "can this person break down a seemingly impossible problem into manageable pieces?" That's fine, but then state that or at least give them something real they'll actually run into if hired instead of trying to estimate how many gas stations there are in LA county in their head.
And while those suck[ed], companies having been doing similarly ridiculous things for a very long time to try and save themselves from hiring the wrong people. IBM's infamous "lunch interview" (false on Snopes, but the concept is true and I've seen played out) or asking candidates to take a personality type test to determine if they'd be a good fit before hiring (yes, I did this once early in my career and would just walk out if asked to do one today).
The most difficult I've found is getting fellow programmers to realize that they _don't_ want to hire another "you." Yes, you're an expert in networking and security. Don't interview for that so you can show off your own skills or "teach" in an interview. Interview _for the position_.
You want a diverse set of knowledge, skills, experiences, communication styles, etc. at your company. And - while it can be scary - you always want to hire people who are better than you (esp. if you're a manager!). But that is so hard to get people to do.
There's definitely a difference between hiring Sr. vs. Jr. programmers. When it comes to Sr, the best place I ever worked had a pretty great process:
1. Phone interview that was 100% identical for all candidates. It was basically a "take me through your work history, answering these 5 questions for each job." It worked wonderfully and gave a really good indication of what the person learned at each position and how they were able to apply that knowledge at the next job. And, if there was some obvious red flag at each step (e.g. "all my bosses have been jerks"). It also had the benefit of being more fair. I don't know how many places I've worked where if person A conducted the phone interview it was a shoe-in, and if person B did it was impossible to get through.
2. While doing #1, make a mental note of a couple things along they way they worked on (esp. if they seemed proud of them) and then - in a follow-up interview with a couple programmers on the call - really dig in deep on the technical details. Ask questions. You'll learn rapidly if they actually did the work and understand the problem or simply worked on it w/o understanding. What were the major challenges? What would they change now if they could go back? And here it's awesome if you get someone who can give answers that aren't always technical things (e.g. "I wish I knew early on how best to deal with X").
3. At this point, you're ready for an on-site and have already proven to yourself and the team "this person can code and solve problems." What's left is any final details you want to be sure of. Any odd personality quirks that won't work for the culture the company is going for? Let non-technical people they'd have to interface with interview them.
The best we ever came up w/ for Jr people was a test with some basic college class stuff like big-O and for problems 1-3 would you prefer linked list, hash table, or tree and why? And then try and do #1 and #2 above, but using their college classes/team projects as work experience. But that didn't always work out all that well.
By that I mean, would it be possible that 2 different people download the app from the Play store, one of them gets an unmodified version of the app and the other (perhaps based on the user's race, country of origin, etc.) gets an on-the-fly modified version of the app.
The developer - and likely 99+% of all users - would never know or even be able to tell because most copies of the app in existence are 100% what the developer created. But, for a few rare birds, backdoors are aplenty.
Regardless, I'm 100% against this. But, my thinking above is this is possibly far worse than I initially imagined.
* Internal, non-technical users; what does the code do, why was it written, who currently owns it, when should it be run, how to run it, and what to do in case of failure. The more accessible, brief, and direct the better.
* Technical users; this is your README that usually doesn't need to be updated all that often. What is this code for? A quickstart for install/loading, dependencies, and the bare-bones set of functions, arguments, etc.
* Fellow implementers; the above README, but likely with a few additional notes of how the code is (high-level) broken up, and where to go for the most common things. This is where documented code is really good as well. I usually find the best code comments have always been A) NB: here's a drawn-out explanation of why the code does this, it's for a reason, do not question the code first unless you understand this and/or the above reason has changed, and B) in the future, you may want to do X, in which case you'll need to do J, K, and L and update M. Comments like those have saved me (from myself, even) so much grief and time.
* 3rd party users; this is where real documentation gets to be a monumental PITA and any company worth its salt will hire a technical writer or two. This is a very different skill than what's required for any of the above.
The biggest concern I see brought up again and again with documentation is that it becomes out of date quickly as soon as it's finished being written. This needn't be true. Internal documentation is just enough info for whoever is using it to know what it is, how/when to use it, what to do if it fails, and who to go to for more information or help.
Honestly though, the biggest problem with documentation has always been where it lives and how it's edited. Is it all repo READMEs and markdown? Are they google docs? A wiki/confluence? This is always where the breakdown happens. Programmers are comfortable with just being pointed to a repo and text files, while non-programmers want WYSIWYG docs somewhere central, which is the last place most programmers even think about. Wikis/confluence attempts to be a compromise that (IMO) no one likes. This - like task tracking - is a unicorn of software development.
The room is $25. Everyone paid $25 for the room + a $2 "tip" to the bellhop.
That said, I'm going to have fun emailing it to my parents. ;)
But, doesn't hacker news actually have implicit down voting by way of time? HN isn't designed to be a searchable Q&A or forum. It's a "what's a currently popular" site. If something isn't good, it just disappears faster than the opposite.
Have I wished I could down vote things sometimes? Sure. But then I just wait 5 minutes, refresh, and it's gone.
As a programmer, I love reading blog posts about why someone made something, how they made it, and what tools they chose to use/create to facilitate their end-goals. Some of the frustrations the OP had with respect to Ocaml are some I - and many others - have experienced as well. Enumerating those constructively can potentially benefit the Ocaml community as well.
However, as a possible target user...
Reading blog posts like these are _scary_. It is very rare that I want to read a "hey, that service you use regularly? yeah, we decided to rebuild it from the ground up using entirely new tools 'just because'".
Will I still be able to work? Should I postpone signing up/paying? What new bugs will appear? Which features I currently rely on will change or outright disappear/cease to work? What edge cases that are currently handled will be forgotten? The list goes on...
There are often very legitimate answers to these questions, and sometimes taking a HUGE step back in order to meet demands you didn't know existed before is what's required. But those requirements, and how this step back will address them, should be clearly laid out to your users.
More importantly, work such as this postpones any current roadmap features (potential) users may be waiting for and have been previously promised. Presumably an analysis has been done on how much they'd be postponed by, and why those features will benefit greatly once done. Sharing that would also be extremely helpful in assuaging concerns.
Edit: I was thinking of pulling the RIFF/WAV code out into its own package. Let me know if this is something you'd find useful.
From my perspective, though, the largest annoyance of PR reviewing is that diffs are alphabetical instead of conceptual.
For example, a large change ends up affecting 26 files named A, B, ... Z. The PR diff/review lists the changes starting with A and the last changes reviewed are in Z. But, conceptually, often it'll be that - if you made the PR - you'd rather the reviewer start with Z: the high level, this is why the PR was even needed, then jump to F: the data structure change enabling this, then off to B: initialization code that needed to account for the structure changes, etc, etc.
Currently, the only way around this - that I know of - is with the comments section and just noting for whoever reviews it what to look at in what order.
Having a tool that fixed that problem would be heaven to me.
First, my retirement funds are things I'm _very_ protective over. Aside from a blurb saying "We use a third party service with bank-level encryption to connect your accounts," I don't have any reason to trust this site. What's the 3rd party? Can you link to them? Why should I trust you _and_ them? The idea of giving your site access to my bank accounts is... scary to say the least. You need something on the landing page to walk-through how this wouldn't allow someone at your company to somehow empty my accounts. ;-)
Second, the site seems to imply knowledge of actions possible that aren't obvious. For example, my employer sets up a 401K through an investment firm (like Fidelity). I have no choice in that. Likewise, Fidelity charges a set rate, of which there's nothing I can do. My choice is to either participate or not. Unless the site is potentially looking into extra charges (by fund?) that I can switch, or multiple 401K accounts from past jobs that I can roll-over or do something else with, I'm not sure what this service offers besides telling me what I already know?
Assuming there is plenty of choices I do have control over (re: second comment), it would be nice to enumerate what some of those would be on the landing page or even put together a little animated video describing the problem, what options an employee may not know they have available to them, how the site (read-only, and hopefully not saving anything) collects information about the accounts, and can present me with information and options that "with a click of a button" can save me money.
Great idea! Hope these comments help.
Code cleanup can mean many things. When talking about architecture, it could be a legit argument that due to requirement changes there needs to be a rethink. But that's not debt. That wasn't a conscious decision made in the past to do A instead of B knowing that B was the right choice, but not realistic at the moment.
When talking about large code bases that have been around, code cleanup is a young person's term that tends to imply they are smarter or know more than the previous set of programmers who worked on it. That's possible, but a bad argument. And it's insulting. Obviously the code has worked for quite a while successfully, so it can't be as bad as it's being made it to be (that's management playing devil's advocate). If it hasn't been working, the schedule should reflect fixing it. Maybe that requires a massive recoding, but maybe not.
This is wrong. Technical debt is almost always incurred because of the business requirements. They need to be made aware the debt is being incurred at that time so they are aware it will need to be paid down ASAP.
Example: a startup is asked by an investor for a particular feature to be implemented for a trade show a week from now. That feature - if done properly - would require a database schema change otherwise the queries will be abysmally slow. Luckily, for the trade show the amount of data being queried is small enough that it won't matter. But as soon as it starts getting used, whoa boy.
Management needs to be made aware that there is technical debt being incurred here. Yes, the deadline will be met and the show will go well. But there better be time on the schedule to do it right afterwards.
Most of the time I hear programmers talk about technical debt, what they really mean is profiling and performance (because over time requirements change and code size increases) or code "cleanup" which is usually a catch-all for "not how I would have done it".
Performance issues are real, but those should just be scheduled and tackled as needed. Code cleanup is quite often a red herring.
But technical debt is entirely different. It's exactly what the name implies: debt. We would have done X to implement a given feature or customer request, because there are many conditions and other systems to take into account. But there wasn't time to do it that way before the required deadline, so we did something else instead that would get by for now, but we all know won't last.
That is technical debt.
Sadly, often times management just see the issue as done on the schedule and there should therefore be no need to go back and "do it again".
Always pay down technical debt when you can. It will be paid eventually, it's just a question of how painful it will be when you do.
Sometimes, this can quickly lead to a downward spiral effect at the company. Productivity falls and whatever issues the layoff was intended to remedy end up being magnified instead. This is usually the case when - before the layoff - there was either "writing on the wall" (that typically management wouldn't admit to publicly) or an inherent distrust of management.
What really sucks is the pile on. Recruiters watch for these moments and jump on them like piranhas. They notice a sudden spike on LinkedIn of resume updates by people all working at the same company and hone in on those still there, reaching out to see if they want to take a look at other possibilities. Simply put: no one wants to be the last one to go down with the ship.
Whatever project you're building/working on, please remember those who weren't laid off, too.
Statements such as these are very academic and concerning - to me - when it comes to new languages. And they make me wary of whether or not the language will ever move out of the land of theory and into practice.
Continuing with the "strings are cons lists" theme... Other, very notable languages have tried this in the past: Erlang and Haskell immediately come to mind. And - without exception - they all end up regretting that decision once the language begins being used for real-world applications that require even a moderate level of performance.
Lisp programmers (among which I count myself) are very fond of pointing to new languages and identifying all their "features" that were implemented in Lisp decades ago (so not "new"). And they also bemoan when a language design doesn't take a moment to learn from the mistakes of those that came before them. Strings as lists is very much in the latter case.
The above said, the idea of streams as a fundamental type of the language (as opposed to a base class, type class, or what-have-you) is quite intriguing. Here's hoping they are more than just byte streams.
My only comment is on the article. This line:
> Nu would not have been possible without Rust.
That's just patently false.
Perhaps you wouldn't have chosen to code it in another language. Or perhaps Rust had one or two benefits that assisted in the development of Nu. But you don't word it that way or go into any details as to what made Rust special/better than X, Y or Z language (not that you need to, but if you're going to make a wild statement, you should be prepared to back it up). The only 3 points made following that were about features that have widely existed in other languages well before Rust came along: async/await, async streams, and serde.
Rust is cool and is still exploring some really great ideas in making programs safer and more maintainable. But, it's not the greatest language ever (at least not yet), nor does it make the impossible possible. It can merely make some things easier at the cost of something else.
I'm glad you were able to use it effectively to create a tool you - and others - find useful.
1. Correlation != causation.
2. Confirmation bias.
There was no comparison mentioned in the article (or just about any similarly purposed article). The author has no - or at least did not state any - insight as to whether or not _this_ particular bullet point (Elixir) had any impact what-so-ever on the quality of the candidates that applied. There were no controls or comparisons made. Just a blind assumption that anyone who applied _must_ be better because of the language choice.
I have no doubt that the esoteric stack did have one major impact on the recruiting process: they had a far smaller pool of candidates to draw from. They weren't wading in resumes, trying to pick out ones that somehow stood out. And the highly specific details of their stack meant they weren't trying to ascertain whether or not a given candidate with no direct experience would be able to "pick it up". They were able (and had to) pay much more attention to each application. They read each resume carefully. And they were probably less strict about which candidates got that initial phone screen/test.
There is a likely a bit of correlation between programmer "quality" and esoteric language knowledge. My experience has been that polyglot programmers are so because they love to program and do so at work an in their spare time. They love learning concepts, ideas, patterns, etc. And they have a lot of tools and (often superficial) knowledge to draw from to solve problems. But, I've also found that often polyglot programmers are terrible at completing. Once the perceived, initial, "fun" problem is "solved" their interest and motivation levels to work through the details, customer feedback, and bugs tanks.
All that said, I'm glad they were able to hire Carlos, and I hope he turns out to be the superstar they are looking for!
> You might say that surely that additional cost would be compensated in reducing the cost of maintenance later. Maybe but I'm not sure.
I am sure. 100%. From many years of experience.
Yes, static types come at an initial cost at initial development time. But they pay that time back in spades. This is exponentially true the larger the code base is (more to keep in one's head), the longer the project lives, and the more people are on it.
Having worked on very large C/C++, Scala and Python projects, when it comes to add a major feature or perform a serious refactor, I always want the static typing and the compiler to inform me when I've missed something. Far too many times has code been checked into a large Python code base that breaks something (completely unbeknownst to the programmer), because there's a code path that's rarely executed or arguments to a function flipped, etc.
That all said. There are major benefits to being able to prototype very quickly in a dynamically typed language, too.
> What prevents one importing each CSV in a postgres db as tables, creating indexes and then start running queries?
There are many reasons:
* Experience/knowledge. Many labs don't have anyone experienced with databases.
* Security. Without proper dev ops a local DB is often out of the question. And when dealing with PII genetic data, [cloud] security can be a major concern.
* Funding. Machines cost money. AWS RDS instance cost money. Maintaining them costs money. Dev ops costs money. etc.
* Often times the queries being done are simple. For example, you may have a giant CSV with cross-ethnic trait data, but only need samples of African decent with a beta value > 0.1. Sure, you could spin up a database, load the entire thing into a table (O(N) + disk space + time), then index it (now it's O(2N) + more disk space + more time), and then finally run your query. Or you can just O(N) run over the CSV once and output the results with no extra disk space or "wasted" (perception of the researcher) time.
Finally, don't fool yourself about the capabilities of researchers. Many are code-savvy, but lack experience. Writing a SQL query is easy. Loading multiple TB of data into a relational database, indexed properly, and done in a manner that won't take days of time is a level higher.
It's also important to remember that some of the reasons AWS, Google, and other cloud services are often NOT used are legal in nature. For example, some EU laws prohibit any personally identifiable (genetic) data from studies being put in the cloud. So, even if summary statistics - or data with PII data removed - can be put in the cloud, work has to be done on that data to remove it.
I work in genetics (as a software engineer).
If there was a major flaw in current scientific research (that involves software), it's that most labs care more about getting published than they do about the reproduce-ability and validation of their work. This means most of the software written in research is ad-hoc, write once, and often never looked at again. It was put together for the sole-purpose of producing some output that could be put in a paper and then lost to time.
A current "holy grail" of software in research would be to fix that: empower other labs to validate and reuse the software written and reproduce the work of other labs with different data sets. And it is actively being worked on in a couple places (that I know of, perhaps more):
* https://genepattern-notebook.org/
* https://software.broadinstitute.org/wdl/
Some of these are just about giving the community a common framework to use for their software (CWL, WDL, Jupyter), others are about data storage and making it easily accessible for others to use in the cloud for reproducing results.
If you want to have a impact, joining one of these groups would probably put you in a much closer position to doing that.
If you just wanted to work on something in your spare time that would be incredibly valuable, then might I suggest this:
It's amazing how much work is done in the scientific community using CSV/TSV files (usually gzipped). And most of that work is done via perl, sed, and awk. And often these are huge I'm working with a VCF file (TSV) right now that's 2 TB in size ZIPPED! It's crazy. Researchers often don't have the time, resources, or know-how to put together a simple Spark cluster and use it.
A command line tool that allowed someone to run SQL (or SQL-like) commands on a gzipped CSV file FAST would be invaluable. And if it could JOIN across CSV files ... wow!