migrate_to_frozen_string_literal

[20220613 update] better use robocop auto-correct to handle this issue.
[20220728 update] bundle exec rubocop -A **/*.rb --only Style/FrozenStringLiteralComment

I’ve read a blog post written by Mike Perham introducing the Magic Comment, and I tried it out in my project.

The # frozen_string_literal: true

STEP-1: add this “magic comment”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Find all ruby files.
# Iterate through them.
# Add two lines if the file doesn't have those magic comment.

basedir = Rails.root.to_s
filenames = Dir["#{basedir}/**/*.rb"]
target = "# frozen_string_literal: true"

filenames.each do |filename|
lines = File.foreach(filename).first(2)

if lines != ["#{target}\n", "\n"]
`gsed -i "1i#{target}" "#{filename}"` # Use gsed on macos.
`gsed -i "1G" "#{filename}"` # Use sed on linux.
end
end

STEP-2: do automated/manual tests

This is important, since your project code may have a situation for manipulating Mutable String.

STEP-3: deploy and pay extra attention to production state

Be ready to rollback your deployment. You know, shit happens.

Exception occurred: FrozenError

Yes, it happened…

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"class": "ScanAlertingAndPendingWorker",
"args": [],
"retry": 1,
"queue": "default",
"jid": "0a48de6e85b383432760b013",
"created_at": 1646124005.491867,
"enqueued_at": 1646124034.8366895,
"error_message": "can't modify frozen String",
"error_class": "FrozenError",
"failed_at": 1646124035.9765105,
"retry_count": 0,
}

Occurrence No.1

1
2
3
4
5
# frozen_string_literal: true

content = ""
content << 'world'
content << 'hello'

solution

1
2
3
4
5
# frozen_string_literal: true

content = String.new
content << 'world'
content << 'hello'

Occurrence No.2

1
2
3
4
# frozen_string_literal: true

body = 'Roses are red Mud is fun'
body.force_encoding('utf-8')

solution

1
2
3
4
5
6
# frozen_string_literal: true

body = 'Roses are red Mud is fun'
body.dup.force_encoding('utf-8')
# or
String.new(body).force_encoding('utf-8')

At Last

But to my disappointment, I didn’t see significant memory reduction.

It might be related to the size of the system.(Is it?)

Tradeoff Collection

I observed a lot of trade-offs.
I would call Trade Off some kind of Art.
Tradeoff collection therein.

Space | Time Tradeoff

A space–time Tradeoff or time–memory trade-off in computer science is a case where an algorithm or program trades increased space usage with decreased time.

Here, space refers to the data storage consumed in performing a given task (RAM, HDD, etc), and time refers to the time consumed in performing a given task (computation time or response time).

Code Changeability/Simplicity | Code Readability Tradeoff

hint from “99-bottles-of-oop”

  • abstraction -> changeability(hard to understand)
  • concrete -> easy to read(hard to change)

Security | Effiency Tradeoff

cryptography

  • The more complex the encryption algorithm is, the more secure it will be, while it’ll take more time to encrypt/dencrypt

even good (or trendy) solutions add complexity

Use sidekiq or use sidekiq with rails activejob

  • sidekiq: powerful/simple
  • activejob: more rails-favored features

ease of use | feature rich

  • beginners want programs/interface to be easy to use

  • advanced users want programs/interface to be more powerful

top -> down design | bottom -> up design

“the art of unix programming” ch4.3.1

接口复杂度 | 实现复杂度

“the art of unix programming” ch13.1.2

features/performance | price

“Fast and resilient web apps: Tools and techniques - Google I/O 2016”

Event-carried state transfer

  • more decoupling

  • more availablity

  • less data consistency(eventual consistency)

having-so-much-fun-enjoying-cmdline-emoji

命令行里加个小表情足以愉悦自己
当git工作区不是”working tree clean”状态时 放出小表情

实现方法:

1
2
3
4
5
6
7
8
# $HOME/.zshrc
# env: MacOS

ZSH_THEME="ys"
function parse_git_dirty {
command git rev-parse --is-inside-work-tree &> /dev/null && [[ $(git status 2> /dev/null | tail -n1) != "nothing to commit, working tree clean" ]] && echo "🤣"
}
export PS1='%n@%m:%1~%$(__git_ps1 " (%s)")$(parse_git_dirty)$ ' # with git branch, 配合 iterm的(smart selection)

根基不稳

2022-05-15 15:50:10 updated

Ruby version < 2.7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Demo
def run
foo # 正常
self.foo # 报错: private method `foo' called for #<Demo:0x00007fd39e80c2e8>
end

private

def foo
puts __method__
end
end

Demo.new.run

今天遇到这个问题的时候, 我这才意识到我的OOP基础有多薄弱…

继续努力

遇到这个问题的原因是, 使用的ruby版本小于2.7, 这时候不能这么用