Today I Learned

TIL, 2017-06-22

  • Iterm dark theme for black tabs
  • Strongly typed vs weakly typed: Ruby is strongly typed since 1 + “1” will not work, you get a Fixnum error, whereas JS is weakly typed, since 1 + “1” will work (“11”) ??? Strong types must match, only explicit conversion. Weak types does implicit conversion. Strict = type checked at compile time, dynamic = checked at run time. Duck typing = the set of methods and properties determine the valid semantics of a class.

Red Dot Ruby Conf 2017

Keynote - Matz

  • Goal is to create great software.
  • Ruby goal: Make the language better.
  • Ruby is popular and has helped many developers, and it has survived for 25 years. It is rare for software to survive for 25 years. So, compatibility matters.
  • Ruby has a lot of technical debt. In making Ruby, I made some mistakes.
  • 1.8 and 1.9, we need more than 5 years to migrate to 1.9 because of the breakage.
  • Second system syndrome: When we have trouble with the current system, we just throw away the first version and create a second version.
  • Simple goals. Case study: Ruby 3 x 3 (Ruby 3 must be 3x faster). (Though actually in the real world application, Ruby is not that slow.) Now the problem is that we have already done the low hanging fruit, so the things left are hard.
  • In general, software has a time-space trade-off. Generally, faster software consumes more memory. JRuby is faster than CRuby. But at the same time, JRuby consumes more memory. In micro-benchmarks, it consumes 100x more memory. 17x on optcarrot benchmark.
  • Since I work for Heroku, Ruby must at least work for a machine with 512 MB (smallest dyno). PCs usually have 2GB, and embedded systems have 1MB or less.
  • So we want to make Ruby faster, but we also want it to be configured as using less memory.
  • For Ruby, depending on an outside project is dangerous. So we have this possible dependencies like LLVM, libjit, GNU lightning, but we can’t control them.
  • Generational GC, incremental G, open address hash-table, other improvements. We have 5-10% improvement each year for the last 4 years. So Ruby 2.4 is faster and Ruby 2.4 consumes less memory, and we want to include these improvements.
  • No micro-benchmark. While benchmarking things like searching a binary tree is cool, it’s more of a game. What we want is a standard benchmark that reflects the real-world. One, web application benchmark since most programmers use Rails.
  • optcarrot benchmark: NES emulator. We want to do 60fps.
  • Turns out that Ruby 3 x 3 is nearly impossible. So I’m thinking of JIT/Just in Time compilation. So Rubinius, Crystal, Julia uses LLVM to do JIT. LLVM is portable, highly optimized.
  • Libjit: less widely used, hard? haha
  • MJIT: By Vladimir Makarov. He is the author of open-table feature in Ruby. Use RTL, GCC/Clang, and JIT. RTL: Register Transfer Language.
  • YARV - uses a Stack-based IR (instruction register). Stack-based IR is simpler and shorter. Register based IR creates less instructions, less memory traffic, and runs faster.
  • Vladimir replaced YARV by RTL VM.
  • Me: I DONT UNDERSTAND IT ANYMORE.
  • Default RTL faster than Ruby. Ahead of time compilation.
  • Micro-benchmarks: MJIT > JRuby > Ruby 2.0 runs faster but consumes more memory.
  • MJIT is promising. However it still has some issues, and we need more work.
  • Conclusion: We are trying to create something we haven’t seen. Software development is the process of making impossible possible.

Functional Architecture for the Practical Rubyist, Tim Riley

  • SOLID: “I have work to do, not architecture!” But not surprisingly, the longer I work the harder things are to change.
  • Design stamina hypothesis: Without design, features are fast to make at the start. With design, it’s slower at the start but faster at some point.
  • View your app as a series of transformations. We get our initial data (HTTP request), then transfer transfer, think of it as functional objects. We can model these as functional objects.
  • Separate data from behavior. Data - value objects. Behavior - service objects.
class ImportProducts
  def initialize(download_feed:, products_repo:) # Dependency injections
  end

  def call
  end
end
  • Dependencies – an object’s dependencies should be more stable than it is
  • App as a graph.
  • rom-rb, dry-rb.
  • how do you do things in Rails

Ruby on Weelchair, Daniel Bovensiepen

  • Used mirb/mruby
  • User devices, then RaspberryPI running MRI, and MRU (wheelchair microcontroller) running mruby.
  • Problems: touch interface is bad, how far can I still drive, redundancy for link failures, how steep is the ground?
  • To get battery status, you just do some calculations based on the current voltages when filled, and slowly run out of battery life.
  • Touch interface - get a game pad (Playstation controller).
  • Next step: wheelchair optimized navigation using Wheelmap and OpenStreetMap, vibration detection for mapping.
  • You can solve these problems with mruby, MRI, and JRuby.
  • How to improve: tagging and improving environments for PWD.

All I’d Wanted to Know about Ruby’s Object Model Starting Out…and Mooar!!!, Jun Qi Tan

  • What is it like a beginner learning Ruby?
  • class_eval, eigenclass, singleton method
  • Basic Object, Kernel.
  • Introspection: dog.class.
  • singleton_class.
  • C: objects are pointers to structs, structs are. RObject, RClass, RBasic.
  • RBasic: says what type of object it is, and if a singleton or not.
  • RObject: RBasic, and the instance variables.
  • RClass: RBasic, and what the superclass is.
  • For method dispatching, the way things work is that an object will try traversing the superclasses until it finds the method that was dispatch.
  • Bootstrap (object.c).
  • rb_define_class_id: Create an RClass specify the superclass.
  • Me: I DONT UNDERSTAND IT ANYMORE.
  • Study how to make meta_class and singleton_class.
  • Modules: When you include, you create a Saberteeth include class which has the method table of the backing module.
  • The module that is included later is called later.
  • ruby-hacking-guide

Keynote, Betsy Haibel

  • At the end of the day, all I want is boring code that I understand.
  • Tests are code and code is terrible so tests is terrible?
  • We write our tests and application code with incomplete information.
  • “Why don’t you try listening to your tests?” lol? People who say this should just say “I think we can fix this if we just try, I promise.”
  • Code is terrible because the world is complex. Complexity happening to you does not mean you are a bad developer, it just means that the thing that we are doing is hard.

  • Testing a private method: method might have indirect results, method is expensive to test using the pubic interface, and there are weird side effects elsewhere.
  • So, why not just make a method public, or extract a simple class?
  • Duplicate tests, something like testing if a phone number is mobile, and testing if a phone number is a home phone.
  • Shared examples–not really good? The problem with doing shared examples is that this will make you tie the test implementation to the code implementation.
  • Test duplication sometimes means functional duplication.
  • Inventing the universe: Creating the environment of the test first. This is like really slow. When you make test abstractions, you risk making parallel abstractions in the application code.
  • Shared contexts: Things like create_sample_match. Problem is, shared contexts hide dependencies from us.
  • Factory girl: “Dependencies” sometimes just mean “code you’re not looking at”. I suggest that you make your tests work such that they also show helpful information about the construction of a class. If you make it like a Java factory, that’s okay. Business logic is too important to delegate to framework magic.
  • The trick: this is a whole series of subjective judgments. Boring code: how do we decide this?
  • I think: code that minimizes assumptions is boring.
  • Sample happy path controller test for updating something: create the thing, send a request, invoke the thing.
  • If you do mocks, they are like super brittle.
  • Database: realistic = dynamic, persisted objects. Kinda realistic: pre-set features. Not realistic: test doubles.
  • Microservices: Use webmock library stub_request.
  • Application code influences test code, and test code influences application code.
  • Whatever boring means does to you, you can just make your tests and code more boring. Huh?

Writing Better Errors, Laura Eck

  • Not about writing error messages, but about how to go about going there.
  • The problem with some errors is that they tell you what the problem is, and is that really the thing that you want.
  • Since we are developers, we are not just receivers of error messages, but we are senders of error messages.

Audiences:

  • Developer: needs to figure out how to fix errors that shouldn’t happen.
  • API user: How to correctly call the endpoints and get the errors they expect.
  • App user: Needs to figure out bow to successfully use the app.

  • User errors: Expected, and we have rules for them. If you follow the rules, the error goes away. Things like uploading a picture that’s too big, or using an expired credit card.
  • Server errors: Unexpected, no rules, and need to investigate before fixing.
  • It’s a user that can fix user errors, not a developer. It’s a developer that can fix server errors, but not user errors.
  • Logging: we log errors that are interesting to us.
  • Developer: Input errors. You might want to selectively report these errors. If you notice a certain kind of error triggered by a user action happens a lot, rethink your interface, there might be something.
  • App User–Input error: Clear and readable error message layout, localize (meaning the language), provide a clear course of action to solve the problem, no matter what it is. “You uploaded something is too big.”=
  • API User–input error: matching HTTP status codes, specific error messages, make it clear what to do, and clear documentation.
  • Developer–server error: make sure your code has robust error handling, report and log at error level, include as much info as possible, ensure someone ACTUALLY gets notified, and communicate the fix e.g. in a public changelog.
  • User–server error: TELL THEM THAT ITS NOT THEIR FAULT, and provide a suggestion on what to do next.
  • Goal: Maximum problem solving, minimum frustration.

Keynote, Nick Sutterer

  • “Ruby is dead”–apparently it is slower, sucks at concurrency, and is OOP (not functional), is messy, and is the reason why Rails exists.
  • Proper engineering: maintainable, comprehensible, and has a good architecture.
  • The thing with Ruby is that at least the stacks for each application are mostly the same, not like PHP where there are things like different frameworks, implementing own MVC.
  • The problem with software development is not the programming language, but the level of granularity with architecture that the language provides.
  • The problem is that we have enough syntactical sugar and we keep on adding, when we need new abstractions.
  • PHP 6: Something that is like modules, anonymous classes, something that is like interfaces, and typing, both for method arguments and for return types.
  • Java: typing, interfaces, method overloading
  • Ruby refinements = ???
  • Safe navigator, the &. operator.
  • Trailblazer: Creating a blog post: create a blog post UUID, attempt to save, catch error, then update total_posts, then check if a counter_error exists. DSL thingie.
  • Strict typing pattern matching modern concurrency method overloading better keyword arguments macros real namespaces packages functions not closures an end to monkey patching insanity removal of autoloading

This project is maintained by daryllxd