4 ms·
You MUST have an insane amount of test coverage to trust something like this to Ruby. I'm new to Ruby, with 13 yoe as a SW engineer. Personally, I find it a v
by WirelessGigabit 4y ago
You MUST have an insane amount of test coverage to trust something like this to Ruby.
I'm new to Ruby, with 13 yoe as a SW engineer.
Personally, I find it a very hard language to master. Writing tests often feels like I'm settings variables left and right without seeing them being used in the current context. But that then happens to be part of the let() way in rspec.
Now you might say: why use rspec? I inherited this codebase, so gotta do what you gotta do.
I do really miss my compiler. I am not a fan of writing a block somewhere that can be invoked 2 weeks later for the first time and then fail, because someone passed in a number where a string was expected.
I went from PHP to Java to C# to F# to JS to Rust. F# and Rust stand out in terms of hardest to write, but easiest to trust.
I don't have that feeling with Ruby, and RoR.
But, again, my personal opinion. Good friend of mine started with Ruby, and he loves it. He says that he accepts the magic things for what they are, and uses them. My brain doesn't allow that. I have to understand.
- winrid 4y agoMaybe some day Ruby will get type hinting. I'm loving it in Python. In terms of the "I wrote a block somewhere and it broke when executed for the first time two weeks later" - don't do that in a scripting language. Use the REPL to build/test the block. That's the trade off - instead of a compiler you get a fast REPL - use it! :)
- ok123456 4y agoit already does
- willlma 4y agoPlease say more. What's your setup?
- teaearlgraycold 4y agoSorbet exists, but it’s worse than what Python offers, which is dramatically worse than what TypeScript did to JS.
- ZephyrBlu 4y agoMy experience with Sorbet has been way better than mypy with Python. Sorbet is way more useful.
- teaearlgraycold 4y agoThat’s good to hear. I only ever tried Sorbet years ago when it was pretty new.
- ZephyrBlu 4y agoOh that's interesting. You mentioned that Sorbet is dramatically worse than TS, but working with a modern RoR/React stack I don't have that opinion. TS is a bit more flexible and expressive than Sorbet, but I find Sorbet very ergonomic even with strict typing. I rarely have to use T.let or T.must. Sorbet's typed data structures like T::Struct and T::Enum are also great.
- aledalgrande 4y agoHave you used tapioca with it? Apart from some edge cases, it makes it very smooth to use once you learn it.
- flats 4y agoRBS (https://github.com/ruby/rbs https://github.com/ruby/rbs) + Sorbet (https://sorbet.org https://sorbet.org) in Ruby 3!
- a-user-you-like 4y agoIt’s… not ready for prime time. I’m optimistic that it can get there but right now the tooling is quite immature and the type system flexibility is not there for such a dynamic language as ruby.
- Rafert 4y agoHave you tried Tapioca (https://github.com/Shopify/tapioca https://github.com/Shopify/tapioca) with Sorbet? Typing in general has ways to go sure, but I find this combination quite usable in my day to day.
- a-user-you-like 4y agoYes, but in dealing with parsing JSON in a dynamic way, we took a bunch of time to try to get things working elegantly and it didn’t go so well. Same with trying to set up a base class for a service object that could return any number of things. Maybe I’ll check back in 3 years? But it seems to be A pet toy of Shopify, and for their needs.
- kayodelycaon 4y agoI’m a long time Ruby and Rails developer. I know how the magic works from reading source code. A lot of stuff uses method_missing and define_method. There’s also instance_eval, which is used to create DSLs like rspec. Once you know what they do, stuff makes a lot more sense.
- WirelessGigabit 4y agodefine_method is so weird. Breaks searching through source code.
- jacobsenscott 4y agoRuby tells you where methods are defined - it is worth your time to learn how explore ruby code from the REPL - this is the ruby way. For example (I have pry installed, but you can do it without pry) [5] pry(main)> $ user.first_name From: /Users/.../.asdf/installs/ruby/2.7.7/lib/ruby/gems/2.7.0/gems/activerecord- 6.0.6/lib/active_record/attribute_methods/read.rb:15: Owner: User::GeneratedAttributeMethods Visibility: public Signature: first_name() Number of lines: 4 def #{temp_method_name} name = #{attr_name_expr} _read_attribute(name) { |n| missing_attribute(n, caller) } end Tells me exactly where this "magic" method is defined, and I can pop open that file and read all the source.
- neon_electro 4y agoCan you point to where this is documented? Thanks for sharing!
- jacobsenscott 4y agohttps://pry.github.io/ https://pry.github.io/ - also a lot of features from Pry have made it into the default IRB these days, but I still use pry. I don't know the equivalent commands in IRB.
- insane_dreamer 4y agoI prefer less opinionated frameworks to RoR, but Ruby is still my favorite language; a pity the ecosystem is so much smaller than Python (esp in the data science space)
- hanley 4y agoYou don't have to use `let` in specs. I prefer setting instance variables inside a `before :each` block.
- CoffeeOnWrite 4y agoInstance variables, you mean those beloved things in Ruby that cannot be distinguished between not having been defined versus having being assigned the value `nil`? :p
- weaksauce 4y agothere are many ways to lookup if something is defined or not instance_variable_defined? defined? are two common ones but if you are using something before defining it you are going to crash so that's definitely one way of distinguishing it. using fetch is another way to provide a default value to something that may have a nil value as a meaningful value.
- CoffeeOnWrite 4y agoThanks for correcting me (sincerely) > but if you are using something before defining it you are going to crash so that's definitely one way of distinguishing it. Would you clarify? Like that was my point, casually using something where `nil` is a possible assigned value, or maybe the variable hasn't been defined, makes possible the (sadly common) category of bugs where the program does not crash, but proceeds as though the variable was assigned `nil`, but actually the variable was never defined. In contrast to local variables where the program will crash if you reference the variable but it hasn't been defined. My comment meant "bare instance variables in Ruby are not great [and we might not want to recommend them as a solution to people complaining about Ruby/Rails quirks]". Do you disagree and actually love the behavior of Ruby instance variables? Or are you simply technically correcting me? (which, again, I appreciate)
- weaksauce 4y ago> Do you disagree and actually love the behavior of Ruby instance variables yeah I wouldn't say i love it and i'm not sure why they did that but i imagine they had a reason for it originally. i would say it should have crashed instead of return nil as a default. they did tend to try to make the programmer happier and maybe they did it to that end but i don't see a large upside to it... not too much we can do about not using instance variables though... at the end of the day you just have to be a little more careful. tests are a pretty good thing to have though and can catch this kind of error.
- q845712 4y agoI've written in python, C++, Ruby, and Go. I hear you on the compilers, and I do miss them at least a little whenever I don't have them. But my goodness, there's really something fun in Ruby. I think it shines in smaller codebases, situations where you can have some hope of understanding 90% of everything that's going on as a single developer (and honestly part of the sales pitch of microservices is that you know there's no funny business crossing the wire, so you only need to know the magic bits of the services you work in). But there's really so much joy in stringing together a few functions in a single line, knowing that there might be a few different types being passed around depending on context but knowing that all the functions can handle all the types, and not pausing after every line to check whether an err was nil... Honestly when I have a compiler i miss the magic, and when I have the magic I miss the compiler.
- papito 4y agoHow many environments are really out there where developers blissfully work in their microservices silo? There are a lot of happy promises and sunny-day theories, but in reality it's an awful mess, and you can't really get anything done without understanding the services hairball. How are you supposed to fix a bug in your own service if you don't know how to set up a specific permutation of services locally in order to reproduce it?
- q845712 4y ago^ all of this is true. I just meant that there's much less likely to be the RESTful equivalent of "method missing" or accessing somebody's __private_field__, hijacking their vtable pointer to redefine the method, etc. And by all means tell me your horror stories :) or maybe put it this way: the big-ball-of-mud formed by metaprogramming tricks feels like it has boundaries that are permeable in a particularly arcane way, whereas the big ball of mud formed by microservices has boundaries that are permeable "merely" by distributing or spanning of both humans and logic.
- jacobsenscott 4y agoMetaprogramming in ruby is not magic. It is fairly simple, but if you come from a language where metaprogramming is difficult or not possible it can seem like magic. Good metaprogramming levels up a language's power in the same way going from a hammer to a nail gun levels up your building power. Creating a DSL in ruby is mostly just creating well named class methods, often that take blocks, and calling them without parens. Sprinkle in a little `method_missing` overrides and a few `define_methods` and that's it. I don't know why people seem to actively avoid learning it, but a day of study, and stepping through a few "magic" methods with a debugger should reveal how simple and non-mysterious it is. And also how useful it is.
- weatherlight 4y agoI've created many DSLs in Ruby. The issue is later debugging said "magic" methods, when said method is throwing an error and you can't find said method in your codebase. Metaprogramming is pretty amazing for gems and DSLs in a limited domain. When I see business logic that has metaprogramming in it, I kinda freak. I know in the future that business logic will change and debugging the very clever code in that business logic may become a nightmare. I say this a person who adores Ruby.
- jacobsenscott 4y agoI agree that metaprogramming should be used with care, and mostly makes sense in frameworks and libraries, and not application code. But any ruby programmer should take the time to learn how it works - and a few sprinkles of it here or there can make otherwise hard things easier.
- aledalgrande 4y ago> I do really miss my compiler. I am not a fan of writing a block somewhere that can be invoked 2 weeks later for the first time and then fail, because someone passed in a number where a string was expected. Problem solved by using Sorbet in your codebase. I know at least Stripe and Shopify do. Also forces you to keep magic at the minimum (which any sane dev would do anyway). https://shopify.engineering/adopting-sorbet https://shopify.engineering/adopting-sorbet
- RangerScience 4y agoFYI, and very late to the game so the short version: the thing to use `let` for that'll make it click is doing things like setting up all the fixtures for "correct" / "normal" execution, and then piecemeal overriding them in nested describe/context blocks to show what should happen in abnormal situations. Basically, "here's what normal looks like, and then here's a deviation from that". Ofc, you'll shoot yourself in the foot doing that if you let individual test files get to big, but that's a bad idea anyway sooo.