|
| d4mi3n wrote:
| This reflects my experience working with Ruby over the years as
| well. I find it a perfectly pleasant language, but as with many
| other scripting languages, things get difficult as a project
| increases in size, complexity, and number of contributors.
|
| Types are a great way to remove certain classes of issues. It's
| my hope that newer versions of Ruby really push gradual typing
| features I've been hearing about forward into common use. The
| productivity gains of preventing all silly Nil and type errors
| will be enormous.
| valcron1000 wrote:
| Setting aside all the dynamic stuff that you can't statically
| check, what does Ruby offer fhat makes it so "pleasant" to use?
|
| I'm trying to understand what a statically typed Ruby could
| bring to the table.
| andrewzah wrote:
| There essentially already is a statically typed ruby:
| Crystal.
|
| https://en.wikipedia.org/wiki/Crystal_(programming_language)
| chrisseaton wrote:
| Crystal has a look-alike syntax to Ruby. But the semantics
| (the important bit) aren't even remotely the same.
| andrewzah wrote:
| What semantics is crystal lacking? Obviously it's not a
| 1:1 replacement as the ecosystem is different, gem
| management (shards) is different, etc. Crystal also has
| union types and concurrency.
|
| For people who want a syntax like ruby +
| performance/concurrency, but are willing to deal with a
| different ecosystem and having to do more stuff by hand,
| Crystal is a nice choice.
| chrisseaton wrote:
| Local variables, method calls, basics like that are
| basically entirely different. Take the Ruby specification
| test suite and try to run it on Crystal, even with adding
| typing and other minor changes, and see how far you get.
|
| (Ruby also has full concurrency, by the way.)
| sethrin wrote:
| Your criticism does not seem rigorously considered. Toy
| programs can often simply be renamed from .rb to .cr and
| be compiled and run as Crystal code. Crystal is not,
| however, trying to be a drop-in replacement: among other
| things, an enforced type system is not a minor change.
| Compilation is not a minor change to a language either.
| It's valid to say that you don't like the tradeoffs (and
| of course ideally you would have a full understanding of
| what those are), but it's incorrect to suggest that these
| languages are not extremely similar.
| andrewzah wrote:
| Crystal has local variables. I didn't mean to imply that
| ruby & crystal are 1:1 drop-in replacements, but there
| are a great many similarities. Enough for me as a
| ruby/rails dev to start on crystal projects with
| relatively little issue once I learned a bit about the
| standard library and the ecosystem.
|
| Ruby's way of handling types is abhorrent compared to
| Crystal, though. Sorbet/RBS are unfortunate systems
| tacked on after people realized that type systems are
| actually really good and not really that verbose.
| thr0wawayf00 wrote:
| The block syntax is a wonderful way to build and chain
| flexible iterative logic, the object model is fairly
| straightforward and the standard library strikes a good
| balance between functionality and brevity. Once you start to
| pick up on ruby idioms, the language is pretty fun to use
| IMO.
| pqdbr wrote:
| It's a shame the article ends with "So as usual, consider not
| writing Ruby, but if you do, ...". That's worthless advice and
| many people, myself included, have Ruby as their most beloved
| programming language.
| afandian wrote:
| I've not written Ruby since about 2006 except with a stint in a
| Rails codebase which did nothing to give me any faith. How do
| you go about e.g. extracting a group of fields and renaming
| them? Or reorder function arguments? Is there a static tool
| that can do this, or do you have to do some kind of text search
| and hope you got them all?
| dymk wrote:
| There's basically no tool for doing that, aside from relying
| on tests to tell you a callsite is now incorrect. "find and
| replace" is... okay, up to a point, but obviously that has
| its limitations (especially once you start metaprogramming).
|
| That being said, I still love Ruby. I have all sorts of
| little tools written in it that would have been a pain to do
| in another language.
| afandian wrote:
| Coming from a Clojure background which is ... different.
| But I understand the enthusiasm around similar language
| features.
|
| But to borrow words from another comment I find Kotlin
| "ruthlessly productive". Apart from the lambdas, functions,
| data classes and immutably, it's the ability to quickly and
| correctly refactor that makes me feel like I can work at
| speed and try stuff out.
| bestinterest wrote:
| There is a gap between languages at the moment imo. Ruby is
| just ruthlessly productive.
|
| Compare
| https://github.com/benhoyt/countwords/blob/master/simple.rb
| with
| https://github.com/benhoyt/countwords/blob/master/simple.go
|
| Hoping new age compiled languages like Crystal & Nim fill the
| gap of performance, types & productivity. But compile speeds
| need to be factored in.
| andrewzah wrote:
| Comparing a trivial <500 LoC program between languages
| doesn't tell you anything that's useful other than the
| terseness of the syntax. You might as well chain unix
| utilities together at that point.
|
| Maintaining a 5k+ LoC java/c#/go/rust/crystal codebase is
| orders of magnitude simpler than standard ruby. Sorbet/RBS
| bridge that gap now, but are a pita to use compared to
| natively implementing a type system. I know with rust/go I
| get a simple binary at the end to copy over. Rust,
| unfortunately, has slow compilation times still compared to
| go, but I really can't stand error handling in go compared to
| rust.
|
| That said, "ruthlessly productive" is an apt description. I
| just don't want to have to maintain a large rails codebase
| again without sorbet/rbs. I'm hoping phoenix/elixir or
| something in rust catches on.
| lawl wrote:
| > Hoping new age compiled languages like Crystal & Nim fill
| the gap of performance, types & productivity.
|
| Yes, go is verbose at times. But the go language server for
| example lets you not write a lot of the boiler plate you see
| there.
|
| E.g. instead of typing out a for loop, i'd just (start)
| typing `foo.range!`, or for sorting `foo.sort!`.
|
| I'm not going to argue that writing it in go even with those
| would be more terse, just that I think it _looks_ worse than
| it is.
| gedy wrote:
| > Ruby is just ruthlessly productive.
|
| Not disagreeing, but the nuance is productive for writing new
| code/features. It really feels counter productive once you
| have a large codebase/team and you need to refactor existing
| apps.
|
| Spent 5 years at a Rails shop and it's crazy how much
| engineering effort was spent on keeping this app going.
| Adding typing seems like a nice step to help here.
| klardotsh wrote:
| Yeah, I disagree with "ruthlessly productive" as a blanket
| statement because of this. I tend to find that a huge chunk
| of the time I save at write-time in Ruby
| (Rails)/Python/etc., I end up repaying at either runtime
| (nil exceptions) or read/explain-to-other-dev/refactor
| times, sometimes in multiplicative form (chasing down why
| something became nil, or a string, or an elephant, but only
| if the ORM did X, Y, and Z to the DB response, etc. gets
| ridiculous quickly)
| pphysch wrote:
| Is Ruby "ruthlessly productive" for building a fast, highly
| concurrent program that can be deployed to X platforms with
| minimal fuss? No.
|
| Is Golang "ruthlessly productive" for interfacing with
| complex relational databases? No, not even with generics.
|
| Tradeoffs, every language has 'em.
| recuter wrote:
| Well, the go one would compile to an easily deployable binary
| and actually be able to, you know, count a whole lot of words
| quickly. But the ruby one is much more terse and quicker to
| write.
|
| I say we go back to awk and get the best of both worlds:
| '{num+=NF} END{print num+0}'
| lambdaba wrote:
| Ironically half that code (END...) is valid Ruby!
| latenightcoding wrote:
| The Perl solution would be significantly smaller tho.
| rco8786 wrote:
| > Ruby is just ruthlessly productive.
|
| This is the best description of Ruby I've ever read.
| princevegeta89 wrote:
| +1. After working on Elixir for a long time I missed the
| simple ruby way to do things and found myself running in
| circles to troubleshoot some basic 3rd party libraries.
| Going back to Ruby for my next side project.
| rattray wrote:
| Just because you disagree with it doesn't mean it's worthless
| advice.
|
| I always have a fond flutter whenever I see Ruby (which I used
| to write, and really enjoyed) but absolutely wouldn't start a
| new project with it, for practical reasons. It's slow, it can
| turn into a big ball of mud as applications scale (there's no
| named imports for crying out loud, everything is just in a
| global namespace with side-effects everwyhere), etc.
|
| Certainly there are still people/projects where, upon
| consideration, Ruby is still the best choice (eg; small Rails
| shop has a standard CRUD app to build quickly that will not
| likely ever scale to be huge). But you should still _consider_
| not using Ruby.
| ecshafer wrote:
| Absolutely agree. Ruby is a great and beautiful language, and
| Rails is imo the best web framework for getting things done.
| RTFM_PLEASE wrote:
| Rails is frankly a double-edged sword, though. While it
| helped propel Ruby, and is a great framework, it also seems
| to have permanently marked the language with a notion that
| its simply a vehicle for Rails.
|
| Ruby is probably one of the more coherently designed general
| purpose programming languages (in my opinion, much more so
| than Python, a language that dominates the industry) but
| doesn't seem to get much use in that domain, which is a
| shame.
| chris24680 wrote:
| As a rails developer I really believe if Ruby had at least
| one more 'Killer App' it would lead to a much healthier
| overall community.
| mpweiher wrote:
| The idea that refactoring requires static types is ahistoric and
| simply incorrect.
|
| The first automatic refactoring tool was the Refactoring Browser,
| in Smalltalk.
|
| https://refactory.com/refactoring-browser/
|
| https://www.researchgate.net/publication/220346807_A_Refacto...
| recuter wrote:
| I don't understand why this is the bottom comment instead of
| the top one.
| a1445c8b wrote:
| The PDF[1] that the second link points to gives a very good
| background on why a refactoring tool should be part of any
| software engineer's toolkit.
|
| Thanks for sharing!
|
| [1] https://www.researchgate.net/profile/Don-
| Roberts-4/publicati...
| alberth wrote:
| NIM
|
| I'm still surprised more startups don't use NIM. It has all of
| the productivity benefits of Python but performance of C.
| brigandish wrote:
| Did you come to Nim from a Ruby background? I've been using
| Crystal and am very happy with it but would be interested to
| know what the jump to Nim might be like.
| [deleted]
| DerArzt wrote:
| I get what the author is saying, but static analysis aside I
| would do all that I can to avoid a 178 file update. I get that
| sorbet is allowing them to do this with higher confidence but
| even in a language that's compiled (thus performing a similar
| role to Sorbet) that much change is asking for trouble.
|
| If making a single update touches that many source files, then
| they may want to take a look at their code organization and
| architecture as that is a whole heck of a lot!
| shoo wrote:
| the most productive i have ever been working as a software
| engineer was in a smaller company where roughly all of the
| company's product and library code was in a monorepo, and we
| had a reasonable culture of writing automated tests (although
| not at 100% branch coverage). sometimes you realise the
| abstraction in a core library used by all the product code is
| wrong or limiting, and if your test suite gives you confidence
| that you're going to catch any potential regressions, you can
| rework the library with a breaking change & fix everything that
| transitively depends on that library in a single atomic commit.
| DerArzt wrote:
| The rub for me here is that making one change in a core
| library ideally wouldn't touch 100+ other source files. This
| feels like a separation of concerns issue in which a module
| is being over used.
|
| Perhaps I'm just in the wrong headspace, as I have never had
| to work in a monorepo fashion. That being said just because
| your code is in a monorepo, does that directly mean that you
| aren't versioning your libraries?
|
| To my understanding most package management tooling in most
| echo systems allow for versioning. With that said, wouldn't
| you slowly roll out the version to the downstream projects
| Monorepo or not?
| swatcoder wrote:
| Refactoring doesn't just mean optimizing the inside of an
| implementation.
|
| With a monorepo and good test coverage, I can improve the
| signature of a function on some library, and use a full-
| featured IDE to confidently update the usage myself without
| making it a 10-ticket task that spans 12 teams and 18
| meetings.
| striking wrote:
| > This feels like a separation of concerns issue in which a
| module is being over used.
|
| It's not always modules. Libraries and patterns and
| frameworks and so on, they will come and they will go.
| Sometimes you want to just change something across the
| whole codebase, and having complete type and test coverage
| over a codebase ensure that you can do so _fearlessly_.
|
| > wouldn't you slowly roll out the version to the
| downstream projects
|
| No need. The upside of doing so is that you generally
| prevent breakage, but at the cost of having to support
| multiple older versions of everything. In a monorepo, you
| can change your codebase from one language to another in a
| single commit, and everything should work just fine.
| (Speaking from experience.)
| shoo wrote:
| > having complete type and test coverage over a codebase
| ensure that you can do so fearlessly.
|
| here's a bit of hard-won wisdom. if you have a company
| codebase in a monorepo where the different components
| (products, libraries) in the monorepo have a fairly
| uniform level of quality standards, and there is a
| uniformly high level of test automation & tooling to
| detect regressions and enable confidence when making
| sweeping changes, it is incredibly productive.
|
| however, if you have a company codebase in a monorepo
| where some regions of the code have wildly different
| quality standards, and test automation may be patchy or
| missing from some components, the lack of flexibility and
| coupling caused by how a monorepo resolves internal
| dependencies can produce a miserable experience. low-
| quality code without a good automated test suite or other
| tools to detect regressions needs to be able to pin
| versions of libraries, or some other mechanism to
| decouple from the rate of change of the high-quality
| components.
|
| E.g. a single developer may be the sole person allocated
| to a project to attempt to build a prototype to try to
| win a new customer, so they may be bashing out a lot of
| lower quality code -- often for a good business reason --
| without much peer review or test automation. If that
| lower quality codebase is in the monorepo and depends on
| core libraries in the same monorepo, then you get a
| situation where core library developers expect to be able
| to make breaking changes to core libraries, and if the
| test suite is green, merge -- but the low-quality
| prototype codebase doesnt have any tests and just gets
| increasingly broken (the consultingware prototype code
| test suite is always vacuously green). Or conversely, the
| developer trying to get their consulting project over the
| line might end up telling the core library developers
| that they're not allowed to make breaking changes as it
| keeps pulling the rug out from underneath business-
| critical prototype project delivery, and then you're in a
| situation where it is no longer possible to refactor the
| core libraries.
| shoo wrote:
| > just because your code is in a monorepo, does that
| directly mean that you aren't versioning your libraries?
|
| If you are living the monorepo trunk-based development
| dream, you version all of your product and library code
| with the commit of the enclosing monorepo. The product code
| contained in monorepo commit X depends on the versions of
| the libraries also contained in that same monorepo commit
| X. Maybe another way to say it is that library dependencies
| are resolved to whatever is checked out in version control,
| without going through an abstraction layer of versioned
| package releases pushed to some package repository.
|
| > To my understanding most package management tooling in
| most echo systems allow for versioning
|
| correct. but that doesn't mean adopting a decentralised
| package-based versioning strategy is the most productive
| way for a team to operate!
|
| > With that said, wouldn't you slowly roll out the version
| to the downstream projects Monorepo or not?
|
| Perhaps! I can think of some arguments why you might prefer
| a gradual rollout: to reduce effort and split the work into
| smaller pieces that can be delivered independently, to
| reduce risk of the change breaking one of N products it
| touches, forcing the entire change to be rolled back.
|
| But on the other hand, you don't have to -- you can choose
| to do the refactor atomically, which is not a choice you
| have if the product and library code is scattered across N
| different source control systems that depend on each other
| through versioned package releases.
|
| If you are working in a monorepo & all your internal
| library dependencies are fulfilled by the coupled library
| version in the monorepo commit checkout, not decoupled
| through versioned package releases, then you would need to
| use different techniques to allow flexibility of some
| products to depend on version V1 of a library at the same
| time as other products depend on version V2. The most
| obvious one is creating a copy of the entire V1 library,
| giving it a new name, making the V2 change, checking it in
| to the monorepo as a sibling library, then rewriting some
| of the products to depend on V2. See also
| https://trunkbaseddevelopment.com/branch-by-abstraction/
| swatcoder wrote:
| Yup.
|
| A project that can absorb refactors safely has a lot more
| headroom than one where every change has to be an incremental
| one near the leaves.
___________________________________________________________________
(page generated 2022-04-25 23:00 UTC) |