> Python is still the easiest to read when you come back to some old code
Lucky you. You must not have seen the "pythonic" monstrosities I've seen.
Python has such a low barrier for entry that one can "get stuff done" with absolutely atrocious and often very overly complicated OOP-ish code.
Ruby is not my favorite language, but I would bet real money that without dependence on libraries, nobody could show me Python code which I could not show more logical, consistent, and readable Ruby code which solves the same problem. I say Ruby because it's of the same "type" and follows similar methodologies.
Python suffers from far too many years under the leadership of one odd person. It has a cult-like following, whereby anyone who disagrees is an outcast. Where else could you hear comments like, "why would you ever need a switch statement? if/if else works fine!" That's just the tip of the iceberg.
Python is great for integration glue code, but only because of the libraries it has. But now it is becoming more Javascript like, and the dependencies are multiplying to the point where you're better off writing your own left-pad instead (or even re-evaluating your approach) instead of taking on new duct tape like django-database-view.
Sometimes the bar needs to be high enough to force the juniors to actually learn something before they start building "MVP" startups. On the other hand, who cares if the MVP is a horror show as long as you get that IPO and take your f-u money and leave.
So my real job is technical due diligence on companies being purchased. I get the keys to the kingdom when we do a diligence and trust me, there are just as many people making unmaintainable monstrosities that get bogged down in tech debt in Ruby. Looking at this scenario is literally my job, and the company I work for does more of these than anyone in the world.
Bad coders can make terrible stuff in any language, and with two as similar as Python and Ruby, the minor differences are a drop in the bucket in the grand scheme of things. Both Django-database code and RoR's Active Record have bogged down many a startup when they got big enough that DB size and query performance mattered.
None of which, as I pointed out, is relevant to the vast majority of scientists writing code.
In your experience, what are most buyers looking for when they get you to do technical DD? Is there a specific set of things they are worried about? Specifically looking to confirm, etc?
Typically they are looking to us to surface areas where they will have to make "disproportionate investment" (as they say) to allow the company to support a ramp up in growth. "What will be a problem when you have 2x as many customers? 10x as many DB entries? 10x as many customers?" etc. Because private equity funds buy companies that are growing and (usually) already profitable, this often equates to tech debt that happens once the DB is big. A very common scenario is that reporting, for example, has become a problem and it's time for the target (as we call them) to be using heavier weight architecture patterns like command query segregation or dedicated reporting databases or materialized views and such. So in the case of Ruby and Python shops, we will definitely be asking if their domain layer is working ok and trying to find out if they've written themselves into a corner by having the code assuming it will always be an RoR app or whatever. I have interviewed more than a few that were in serious trouble from not isolating their Active Record dependency and thus got themselves in a situation where efficiently fixing the database was going to be a lot of rewriting. We see this in other languages too, but Active Record is absolutely a smoking gun there.
The takeaway: always, always, have a domain layer that allows you to refactor your model access without changing tons of code. Data load grows in ways people don't predict. If your company succeeds, in five years you'll wish you had it!
Tech debt kills loads and loads of companies and most folks never hear about it because that's not the stuff that gets publicized or written about. We call it the silent killer...
That's really reassuring to hear. Whenever I say we should spend time on tech debt it's always greeted with "we can worry about that later when we're really successful" as if there will suddenly be an opportunity to completely rewrite everything (because that's what it will take).
Yeah, the idea that tech debt doesn't matter and can just be fixed later is the biggest bullshit myth out there in tech land. The thing is, no one notices or writes about when a startup does an "underwater sale", which is typically an investment firm's portfolio company (company they already own) buying up a competitor for less than the company was worth on the last round, done usually in order to buy the customers, staff, or IP. It happens tons. It's a "cut bait" scenario (i.e. let's lose less now instead of everything later) for the selling company/owners and is usually a result of technical debt.
> Ruby is not my favorite language, but I would bet real money that without dependence on libraries, nobody could show me Python code which I could not show more logical, consistent, and readable Ruby code which solves the same problem. I say Ruby because it's of the same "type" and follows similar methodologies.
I keep hearing all the stories about Ruby supposedly being more logical and sound than Python. I really would love to see actual source code being cited to back those claims.
- The OOP features of Ruby are consistent and ubiquitous (everything in Ruby is an object); Python depends on manual patterns to do OOP (self as the required first argument). Python also depends on special decorators to indicate what functions are instance vs static. Ruby does have a difference in definition, but it's simpler and more obvious (and requires one line fewer of code to define)
- Only finally has Python gotten a switch statement, and surprisingly it has adopted some Elixir-ish pattern matching features. Incidentally, some in the Python community are strongly against this new thing. "Why would you need that!?" Prior to 3.10, you would need more complicate if/else if structures in Python to do the same thing you could do in a concise and clear Ruby case (switch).
- Operations on collections: this is often described as functional programming, but it really is just "doing stuff on collections of data". And in that story, Python's list comprehensions are arguably less readable and less logical than Ruby's. Many of the tools you need in Python must be explicitly included from functools module.
- Ternary operator: many languages have `expression ? do_true_path : do_false_path`. It's a very common pattern which is concise and honestly quite clear. "This thing is true? then do this; else do that". But in Python you break that up into "do_true_path if expression else do_false_path".
- Everything in Ruby has a return value, but not so in Python. So in Ruby you can make assignments (or return values) from the result of if/case. For example, assume you want to return a specific value based on some series of conditions, such as handling an error and returning some enriched data based on the error code. In Python you will have to define a local variable and explicitly set that variable equal to some value in each branch of the conditional. Then afterward, you can use the value of the local variable. Or you would have multiple returns, one in each conditional branch. In Ruby you can simply do x = case ..., or because the last statement of a function is the return value, you wouldn't even have to return it. You just have 'case ...', and the value of the branch is what is returned.
There's a lot more. Some of it is subjective, but my belief is that once someone really knows both, they will prefer the Ruby way. And the more languages you know, the more you develop refined tastes. Ruby still holds up well after knowing 10 languages for me.
(added): the whole whitespace as code thing of Python. It does have one common pitfall, and that is when a line of code gets accidentally indented or unindented below a block which was indented. That line changes scope, likely changing the runtime result; but it may be technically valid, so the developer may not notice the mistake. This is just not a problem with languages that have { } or begin/end delimiters.
Lucky you. You must not have seen the "pythonic" monstrosities I've seen.
Python has such a low barrier for entry that one can "get stuff done" with absolutely atrocious and often very overly complicated OOP-ish code.
Ruby is not my favorite language, but I would bet real money that without dependence on libraries, nobody could show me Python code which I could not show more logical, consistent, and readable Ruby code which solves the same problem. I say Ruby because it's of the same "type" and follows similar methodologies.
Python suffers from far too many years under the leadership of one odd person. It has a cult-like following, whereby anyone who disagrees is an outcast. Where else could you hear comments like, "why would you ever need a switch statement? if/if else works fine!" That's just the tip of the iceberg.
Python is great for integration glue code, but only because of the libraries it has. But now it is becoming more Javascript like, and the dependencies are multiplying to the point where you're better off writing your own left-pad instead (or even re-evaluating your approach) instead of taking on new duct tape like django-database-view.
Sometimes the bar needs to be high enough to force the juniors to actually learn something before they start building "MVP" startups. On the other hand, who cares if the MVP is a horror show as long as you get that IPO and take your f-u money and leave.