Mufid's Code blog

Thermofidz: Membaca Temperatur dengan Raspberry PI

| Comments

Latar Belakang

Pada kesempatan kali ini saya iseng luar biasa ingin membuat termometer yang tersambung ke cloud. Istilah kerennya, “Internet of Things.” Ide ini muncul karena akhir-akhir ini suhu udara tidak menentu. Terkadang saya gerah sekali ketika malam hari. Saya memiliki termometer “offline” yang selalu memberi tahu saya saat ini suhu udaranya berapa. Saya memiliki hipotesis, saya akan sangat gerah dan berkeringat luar biasa jika suhu udara di atas 32 derajat celcius dan saya akan merasa sejuk jika suhu udara di bawah 28 derajat celcius.

Untuk memvalidasi hipotesis saya, tentu saja saya perlu memiliki catatan berapa suhu saat ini pada setiap waktu. Sayang sekali, termometer offline seharga Rp30.000an ini tidak memiliki catatan. Andai ada sebuah termometer yang memiliki catatan dan disimpan ke berkas, itu akan sangat membantu. Akhirnya tercetuslah ide membuat termometer sendiri.

Peralatan

Saya mengikuti tutorial dari Adafruit mengenai cara membaca temperatur dengan Raspberry. Di tutorial tersebut, mereka menggunakan sensor DS18B20. Saya segera mencari sensor tersebut di Bukalapak. di sana kita akan menemukan banyak produk, tetapi banyak pelapak yang tidak aktif juga. Saya kemarin membeli di lapak yang ini. Dan iya, harga sensornya Rp30.000an — sudah sama mahalnya dengan termometer offline yang saya beli.

Kemudian saya membeli breadboard di toko elektronik dekat kantor. Harganya Rp27.000. Saya juga membeli satu paket resistor Sparksfun di Famosa Studio. Dengan peralatan yang sudah siap di tangan, saya bisa mengikuti tutorial dari Adafruit. Skematik yang diberikan cukup straightforward. Tada, ini dia hasilnya.

!!!!!!!!!!!!!!!!!! photos goes here

Konfigurasi Raspberry

Selanjutnya adalah menyiapkan Raspberry. Saat itu saya mencoba dengan Raspberry generasi awal tipe B dengan memori 256 MB. Kemudian agar tidak lambat updatenya, saya memasang Raspbian versi terbaru ke SD Card dengan Win32DiskImager. Begitu saya tancap kabel power, Raspberry tidak tersambung ke jaringan. Bahkan dia tidak hidup, hanya ada 1 LED merah yang menyarah (power) dabntidak ada tanda-tanda kehidupan. Ups.

Penasaran, saya pindahkan SD Card ke Raspberry PI saya yang satu lagi yang berukuran 512 MB. Hidup! Ada aktivitas disk! Ada aktivitas jaringan, tetapi gagal saya ssh. Ups. Saya coba login manual dengan menancapkan kabel HDMI ke monitor dan menancapkan kabel keyboard USB. Usut punya usut, ternyata SSH daemon harus diaktifkan secara manual. Oh. Oke, perkara sederhana.

Meski demikian, saya masih penasaran mengapa versi terbaru tidak jalan di model 256 MB. Oleh karenanya saya coba memasang versi yang berbeda di SD Card dan mencoba menancapkannya di masing-masing Raspberry yang saya miliki. Berikut hasilnya:

Model/Konfigurasi 2016-03-18-raspbian-jessie-lite 2017-01-11-raspbian-jessie-lite
Raspbery PI B (Gen. 1) 256 MB Jalan Tidak mau hidup, layar boot tidak muncul
Raspbery PI B (Gen. 1) 512 MB Jalan Jalan

Hmmmm. Cukup. Aneh. Entah saya yang terburu-buru, atau memang ada galat di versi terbaru. Saya tidak yakin yang terakhir. Tapi saya sudah melakukan rewrite berulang-ulang ke SD Card saya dan hasilnya sama saja. Oke, kita settle-kan saja dengan yang 512 MB dulu.

Tutorial dari Adafruit cukup straightforward. Akan tetapi script Python nya terlalu panjang untuk saya. Saya akhirnya membuat Bash Script sederhana seperti ini:

$ cat worker.sh
#!/bin/bash

TARGET=$(find /sys/devices/w1_bus_master1/28* | grep w1_slave)
TEMP=$(cat $TARGET | grep -o 't=.*')
echo "Temperature reading is: $TEMP"

Mari kita lihat hasilnya

$ bash worker.sh
Temperature reading is: t=29250

Woow berjalan dengan sempurna! Baiklah, seharusnya, saya tinggal membuat Cronjob kemudian menyimpan hasilnya ke berkas file. Jadilah sebuah pencatat temperatur. Kendati demikian, saya ingin membuat hal yang lebih menarik yaitu menyambungkan perangkat ini ke Cloud. Oleh karena saya malas membuat basis data yang kompleks, saya memilih untuk menggunakan Git saja.

Sementara, hasil bacaan dari temperatur dapat dilihat pada akun Github saya:

mufid/thermofidz

Btw, ini hasil rangkaiannya. Tidak jauh berbeda dengan yang ditunjukkan oleh Adafruit:

Hasil Utak Atik

Yak, begitulah.

Benchmarking ActiveRecord Load: #find_in_batches (or #find_each) and #each For Processing Bulk Records

| Comments

Currently i am building a small enough Rails application, but somehow on some endpoints, we process and iterate 10k records on a single request. Sure i am caching all of those requests, but 870ms response time for first request is still unacceptable for me.

Some says it is problem with the JSON rendering. Then i installed oj gem, but the request didn’t get a noticable faster rendering. And then i deleted all JSON rendering, the request still on 800-ish ms response time. All of these findings suggest me that the problem is in the model / query itself.

When processing much records, it would be very easy to get out of memory problem if it is being done incorrectly. By default, when using #each method, Rails will load all records with specified filters (where, scope, etc) into memory. Thus, Rails’ recommendation is to use find_each command, which internally using find_in_batches method. find_in_batches will not try to load all matched records in memory. Instead, it will load records by batch.

The thing is, i was using find_each, but somehow, i was stuck on 2 seconds request. I think the problem was the find_in_batches so i changed the implementation to use find_in_batches. However, this way didn’t help me. I still got 800-ish ms response time.

Somehow, i was curious, was the problem is inside the find_in_batches? Or is it in the Ruby yield and loop? I am not sure since computer nowadays have gigahertz of computing power. However, i did the benchmark and the benchmark looks like this:

class Metadata < ApplicationRecord
  def build_summary
    points = Metadata.where('retrieved_at > \'2000-01-01 00:00:00\'')

    logger.info 'Benchmark: #find_in_batches'
    logger.info begin
      Benchmark.measure do
        points.find_in_batches do |dp|
          logger.info "End finding batches. Found: #{dp.count}"
        end
      end
    end

    logger.info 'Benchmark: #all'
    logger.info begin
      Benchmark.measure do
        points.each do |dp|
          # yield nothing
        end
      end
    end

    logger.info 'Benchmark: 10k loop'
    logger.info begin
      Benchmark.measure do
        (1..10_000).each do |i|
          # yield no one
        end
      end
    end
  end
end

I added ‘normal’ loop, just curious if the problem is inside the Ruby’s interpreter.

Here is the result. I did this on Dual Core 4 GB RAM Virtualbox inside Intel Core i5 with 16 GB RAM. I used Ruby 2.3.1 and Rails 5.0.0.1. For database, i use PostgreSQL 9.6.

I, [2016-12-15T14:56:37.463516 #28376]  INFO -- : Benchmark: #find_in_batches
I, [2016-12-15T14:56:37.511837 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.516353 #28376] DEBUG -- :   Metadata Load (3.2ms)
I, [2016-12-15T14:56:37.550252 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.553774 #28376] DEBUG -- :   Metadata Load (2.8ms)
I, [2016-12-15T14:56:37.596984 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.603011 #28376] DEBUG -- :   Metadata Load (5.4ms)
I, [2016-12-15T14:56:37.645731 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.652892 #28376] DEBUG -- :   Metadata Load (6.5ms)
I, [2016-12-15T14:56:37.692978 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.696923 #28376] DEBUG -- :   Metadata Load (3.1ms)
I, [2016-12-15T14:56:37.738265 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.742807 #28376] DEBUG -- :   Metadata Load (3.5ms)
I, [2016-12-15T14:56:37.787560 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.792086 #28376] DEBUG -- :   Metadata Load (3.1ms)
I, [2016-12-15T14:56:37.828058 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.836220 #28376] DEBUG -- :   Metadata Load (7.2ms)
I, [2016-12-15T14:56:37.907940 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.911302 #28376] DEBUG -- :   Metadata Load (2.8ms)
I, [2016-12-15T14:56:37.943847 #28376]  INFO -- : End finding batches. Found: 1000
D, [2016-12-15T14:56:37.945335 #28376] DEBUG -- :   Metadata Load (0.9ms)
I, [2016-12-15T14:56:37.949258 #28376]  INFO -- : End finding batches. Found: 157
I, [2016-12-15T14:56:37.949421 #28376]  INFO -- :   0.330000   0.010000   0.340000 (  0.485759)
I, [2016-12-15T14:56:37.949613 #28376]  INFO -- : Benchmark: #all
D, [2016-12-15T14:56:37.991020 #28376] DEBUG -- :   Metadata Load (40.9ms)
I, [2016-12-15T14:56:38.218292 #28376]  INFO -- :   0.220000   0.000000   0.220000 (  0.268597)
I, [2016-12-15T14:56:38.218840 #28376]  INFO -- : Benchmark: 10k loop
I, [2016-12-15T14:56:38.219272 #28376]  INFO -- :   0.000000   0.000000   0.000000 (  0.000362)

Sure it is not the Ruby’s interpreter problem since vanilla 10k loop only took 0.3 msec. Comparable to native speed, huh? But we found several interesting findings:

  • using #each is faster than using #find_in_batches (480 ms to 260 ms)
  • … What “{Model} Load (some ms)” means? It does not even reflect the real load time. “Metadata Load 40.9 ms”, meanwhile the real load time is 268 ms. If we compare from logger timestamp, it is also around 268 ms (38.218 – 37.949). Seems like internally they use different measurement tip.
  • For each group in find_in_batches, the “Metadata Load” itself does not reflect the real time to yield the method. If we compare each DEBUG line, it will be around 40ms (e.g.: Look 37.550252 – 37.516353), pretty far from 3.2ms.

So what is my solution for processing 10k records? I don’t know. The page itself will rarely change, so caching the request will help it much. But i am still curious, why processing only 10k records can took up to 800ms.

Also, i am still curious why “Model Load” says faster than the time it is actually need. It took 40ms between yield but it says loaded in 3.2ms.

Lembar Kerja dalam Tiga Puluh Baris Javascript

| Comments

Spreadsheet

Saya menjelajahi kembali beberapa tautan yang ada di penanda saya. Saya menemukan tautan yang sangat menarik beberapa tahun lampau: membuat lembar kerja dalam 30 baris di Javascript. Woh!

Baiklah, untuk membuat cerita lebih pendek, saya melihat kembali dimana keajaiban baris kode tersebut. Anda dapat melihat kode sumber aslinya di Codepen (via HN). Pertanyaan saya ada dua:

  • Bagaimana menyelesaikan formula di sana?
  • Bagaimana dependency resolution antar sel di lembar kerja tersebut?

Mari kita bahas yang pertama. Ini menjadi hal yang menarik bagi saya karena penyelesaian formula berarti Anda membuat DSL sendiri, menerjemahkannya, dan mengeksekusinya. DSL yang digunakan oleh semua program lembar kerja serupa. DSL yang digunakan juga dekat dengan bahasa pemrograman pada umumnya. Ya, menguraikan formula menjadi hal yang dimengerti dan dieksekusi oleh mesin bukanlah hal yang sederhana.

Ternyata, program Javascript ini tidak memiliki DSL sendiri. Alih-alih, program ini menggunakan perintah eval sederhana untuk menguraikan dan mengeksekusi formulanya. Yup, tentu saja jika Anda memasukkan perintah Javascript yang aneh-aneh —– bukan bentuk formula lembar kerja pada umumnya —– Anda akan menemukan sedikit kejanggalan. Anda dapat memberikan perintah alert pada perintahnya dan alert akan bena-benar muncul. Tentu saja bukan suatu hal yang akan Anda lakukan pada mesin produksi, tetapi ini sudah sangat baik sebagai sebuah PoC.

Mari kita bahas yang kedua: bagaimana dependency resolution dilakukan? Anggap saya memiliki sel A1 berisi =B2 * 5 dan B2 yang berisi =100*C2 dan C2 yang berisi 99? Bagaimana penyelesaian keterkaitan formula yang berbeda sel? Ah, “keajaiban” bahasa yang interpret di sini.

Anda dapat melihat di kode tersebut: ada perintah yang membuat property. Lihat pada bagian ini:

var getter = function() {
    var value = localStorage[elm.id] || "";
    if (value.charAt(0) == "=") {
        with (DATA) return eval(value.substring(1));
    } else { return isNaN(parseFloat(value)) ? value : parseFloat(value); }
};
Object.defineProperty(DATA, elm.id, {get:getter});
Object.defineProperty(DATA, elm.id.toLowerCase(), {get:getter});

Ini adalah dokumentasi dari MDN:

Object.defineProperty(obj, prop, descriptor)

Parameters

  • obj
    The object on which to define the property.
  • prop
    The name of the property to be defined or modified.
  • descriptor
    The descriptor for the property being defined or modified.

Jadi, pada dasarnya, eval akan dilakukan dengan property di dalam object bernama DATA. Property-nya sendiri bersifat dinamis, di dalam fungsi. Properti baru benar-benar didapatkan nilainya apa ketika dieksekusi. Jadi, sebenarnya yang melakukan dependency resolution adalah eval itu sendiri. Program ini tidak benar-benar membuat dependency graph seperti yang saya bayangkan sebelumnya.

Sebagai contoh, ada formula =A9*Math.cos(B2). Yang terjadi adalah Javascript eval akan mengevaluasi A9 * Math.cos(B2) ke dalam sel tersebut. Math.cos adalah fungsi bawaan Javascript sehingga tidak perlu dipertanyakan. Bagaimana dengan A9 dan B2? Dua variabel tersebut adalah property dalam objek DATA yang dapat diakses tanpa mengetikkan DATA berkat idiom with. Apa nilai A9 dan B2? Belum tahu. Akan tetapi, karena A9 dan B2 itu sendiri merupakan property yang memiliki getter sendiri, maka kemudian eval akan mengeksekusi DATA.A9 dan DATA.B2 — yang mana di dalam property tersebut akan melakukan eval lagi jika diawali dengan =.

Bagaimana jika ada circular reference? Ini diakali dengan try-catch sederhana berikut:

INPUTS.forEach(function(elm) { try { elm.value = DATA[elm.id]; } catch(e) {} });

Jika terdapat circular reference, call-stack akan menjadi sangat panjang. Bayangkan B2 menggunakan nilai dari A1 dan A1 menggunakan nilai dari B2. Akan terjadi sebuah pemanggilan fungsi getter terhadap dua sel berbeda yang tidak ada habisnya. Ketika call stack sangat panjang, interpreter akan menghasilkan exception, yang ditangkap, dan diabaikan.

Saya rubah kode asli agar menangkap exception dan mencetaknya. Beriktu hasilnya:

Recursion

Resolusi Monitor dan DPI

| Comments

Saya sudah berencana sejak lama sekali untuk mengganti monitor saya dari 17” dengan resolusi 1440x900 yang menurut saya cukup kekecilan untuk mata saya. Jika resolusi 17” tersebut kekecilan, berapa yang “tidak kekecilan” bagi saya? Untuk itu, saya perlu mendefinisikan apa itu “kekecilan.”

“Terlalu kecil” terkait dengan ukuran teks-teks yang ada di layar. Itu definisi “terlalu kecil” yang cukup jelas. Baiklah, question time! Pastinya akan muncul pertanyaan, “kalau teksnya kekecilan, ya yang digedein teksnya! Bukan monitornya!” Tepat sekali. Itulah yang dilakukan para pengguna Mac Retina Display. Di MBPr, ada setting bernama “scaled resolution” yang melakukan emulasi resolusi layar ke resolusi “yang diinginkan”. Sekali lagi, ini emulasi. Yang di-render sebenarnya tetap resolusi native. Oleh karena itulah, kalau mengembangkan aplikasi untuk Mac, kita perlu menyertakan raster untuk DPI yang berbeda — agar hasil rendernya optimal.

Sayang sekali, emulasi resolusi (“scaled resolution”) hanya ada di Mac. Android memang memiliki fitur membesarkan ukuran teks, tetapi hanya teks. Untuk memperburuk suasana, tidak semua aplikasi respect dengan setelan ukuran teks ini. Alasannya karena layout nya nanti rusak, katanya.

Windows juga memiliki fitur “membesarkan ukuran”. Sayang sekali, pengaturan ini tidak berjalan dengan semestinya. Beberapa program malah rusak dan tidak respect dengan setelan ini.

Oleh karena itu, daripada bergantung dengan software dan saya belum bisa mengafford Mac, jadi lebih baik saya mencari monitor yang menghasilkan teks yang lebih besar. Dan tentu saja, space yang lebih lega — akan tetapi ukuran teks yang lebih besar menjadi penting.

Ukuran teks bisa dinilai dari ppi. Makin tinggi angka ppi, maka makin kecil piksel yang dihasilkan, maka makin kecil ukuran teksnya. Oleh karena itu, saya perlu mengukur berapa “ppi” yang pas untuk saya. Setelah melihat banyak sekali monitor, saya layar 19” dengan resolusi 1440x900 sangat cocok untuk mata saya. Ukurannya enggak bikin sakit untuk dilihat dalam waktu lama. Akan tetapi, ruang 1440x900 terlalu kecil untuk saya, maka saya perlu mencari ruang yang lebih besar.

Jadi, saya akan mencari monitor dengan ppi yang lebih rendah / mendekati ppi monitor 1440x900 di 19” dengan resolusi yang lebih tinggi. Awalnya, saya sangat kesemsem dengan layar 2K di ukuran 27”. Akan tetapi, setelah mengetahui harga monitor 4K tidak jauh berbeda, saya jadi kesemsem juga.

Sayang sekali, ketika melihat ppi nya, saya kecewa. Berikut rangkuman kalkulasi PPI nya:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

1440x900
  - 17: 99 <--- Terlalu kecil
  - 19: 89 <--- Ideal

1920x1080
  - 22: 100
  - 23: 95 <-- Terlihat acceptable
  - 24: 91 <-- Sepertinya cukup
  - 25: 88 <-- Ideal
  - 27: 81 <-- Terlalu besar? Kecuali meja saya juga panjang

2560x1440
  - 25: 117
  - 27: 108
  - 32: 92

4K
  - 34: 86

Untuk kondisi sekarang, ukurang yang ideal adalah 24-25 dengan resolusi FHD. Lebih tinggi dari itu, memang space nya cukup lapang (resolusinya lebih tinggi), namun sayangkan ppi terlalu kecil untuk saya.

Ya begitulah.

Tentu saja, ppi yang nyaman untuk setiap orang berbeda-beda :D

Cara Googling

| Comments

Beberapa orang mengeluhkan kepada saya karena gagal menemukan masalah pemrograman apa yang ingin dicari di Google. Berikut adalah panduan singkat berdasarkan keluhan-keluhan yang coba saya pahami.

In Ruby, Everything is Evaluated

| Comments

So if i write

1
2
3
def hello
  puts 'world'
end

It will evaluate def, to which Ruby will “create a method named hello in global scope, with puts ‘world’ as a block”. We can change “global scope” to any object we want.

1
2
3
4
5
class Greeting
  def hello
    puts 'world'
  end
end

The class “Greeting” is actually EVALUATED, NOT DEFINED (e.g. In Java, after we define a signature of a class/method, we can’t change it, except using reflection). So actually, we can put anything in “Greeting” block, like

1
2
3
4
5
6
class Greeting
  puts "Will define hello in greeting"
  def hello
    puts 'world'
  end
end

Save above script as “test.rb” (or anything) and try to run it. It will show “Will define hello in greeting” EVEN you don’t call “Greeting” class or “hello” class or you don’t even need to instantiate “Greeting” class. This language feature allows meta programming, like what we see in Rails.

This time i will use Class Attribute within active support. If you ever run Rails, you should have it, but you can gem install active_support if you don’t.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
require 'active_support/core_ext/class/attribute'

module Greeting; end

class Greeting::Base

  class_attribute :blocks

  def hello(name)
    self.blocks[:greeting].call(name)
    self.blocks[:hello].call(name)
  end

  protected
  def self.define_greeting(sym, &blk)
    self.blocks ||= {}
    self.blocks[sym] = blk
  end
end

class Greeting::English < Greeting::Base
  define_greeting :greeting do |who|
    puts "Hi #{who}, Ruby will greet you with hello world!"
  end
  define_greeting :hello do |who|
    puts "Hello World, #{who}!"
  end
end

class Greeting::Indonesian < Greeting::Base
  define_greeting :greeting do |who|
    puts "Halo kakak #{who}, Ruby akan menyapamu dengan Halo Dunia!"
  end
  define_greeting :hello do |who|
    puts "Halo dunia! Salam, #{who}!"
  end
end

x = Greeting::English.new
x.hello "Fido"
# Hi Fido, Ruby will greet you with hello world!
# Hello World, Fido!
x = Greeting::Indonesian.new
x.hello "Fido"
# Halo kakak Fido, Ruby akan menyapamu dengan Halo Dunia!
# Halo dunia! Salam, Fido!

Previously i want to move the class attribute logic to above code, but after i see the Active Support code, it is pretty complex, so i just require it : /


Previously, i posted this in Reddit

Using Class with Generics <T> Without the T in C#

| Comments

So lately I have been developing a C# application with Xamarin. Then I faced a design problem where I should be able to call a function inside a class with generic type, but I don’t know what is the generic type. Furthermore, I don’t care what is the type of the generic.

Imagine a situation like this: I have a class like this:

1
2
3
4
5
Wrapper<T> where T : IDestroyable
{
  T RetrieveValue() { /* body */ }
  void Destroy() { /* body */ }
}

Let’s go straight to the point: What if I want to call Destroy, but I don’t care what is T? So I have

1
object x // instance of Wrapper

object x is an instance of Wrapper. But I can’t cast it into wrapper without knowing the exact value of the generic type. I can’t do something like this:

1
2
Object x = something;
(X as Wrapper<?>).Destroy();

Also, generic is tightly coupled in C#. Meanwhile, in Java, generic is optional. If you don’t specify the generic, Java just simply treat the generic type as Object. In java you can write the code like below, but not in C#:

1
(X as Wrapper).Destroy();

So how do I call Destroy without knowing the T? Surprisingly, the solution is pretty simple. Just extract the Destroy method to an interface:

1
2
3
4
5
6
7
8
9
10
interface IWrapperDestroyer
{
  void Destroy()
}

Wrapper<T> : IWrapperDestroyer where T : IDestroyable
{
  T RetrieveValue()
  void Destroy()
}

So that I can simply call this:

1
(X as IWrapperDestroyer).Destroy()

Perhaps the next question is, why we get x as an object type at the first place? Why don’t we just simply make it stronger type to Wrapper with known T? I don’t know. Perhaps because I am working too much with reflection since I am creating Xamarin-based Android and iOS application with MvvmCross.

Having Fun with Java’s Null

| Comments

So lately i have been diving really deep (or not really) into Java. I found Java’s null is interesting. I think, i hate NullPointerException very much. And most of the time, i hate my own way to deal with those things.

Btw, if you hate compiling Java’s code just to test a one-line command, you may use JavaRepl, which will give you an interactive mode of Java compiler.

String Concatenation

This is interesting. If you run

String result = object + " is cool";

will invoke toString of the object only if the object is not null. If the object is null, toString will not be invoked and it will be replaced with null instead

String result = new Object() + " is cool";
java.lang.Object@55c8a526 is cool

String result = new Object().toString() + " is cool";
java.lang.Object@55c8a526 is cool

String result = null + " is cool";
null is cool

But, you can’t really invoke toString :))

Object o = null;
String result = o.toString() + " is cool";
java.lang.NullPointerException

Object Unboxing

Well, since my code may be executed at another machine, serializing is very usual. And sometimes, i find it is also interesting how Java’s boxing and unboxing work.

This routine will always work:

long l = ...;
Long boxedLong = l;

But how about this?

Long boxedLong = ...;
long l = boxedLong;

Yes, as you might expect, it may throw NullPointerException. Let’s play with it:

long l = (Long) null;
java.lang.NullPointerException

It is not fun. Really. For primitive-in-boxed object, we may want to use itsTypeValue. But in fact, you can’t do that with Long. Meanwhile, you can do that with Boolean.

long l = ((Long) null).longValue();
java.lang.NullPointerException

long l = new Long(null).longValue();
java.lang.NumberFormatException: null

new Boolean(null).booleanValue();
false

What really happened to those? I don’t know.

if not null and not null

Sometimes, my flawless code merely run into this horrible lengthy operators:

if (provider != null && provider.getGlobalInfo() != null) {
    InfoBase globalInfo = provider.getGlobalInfo();
    doSomethingWith(globalInfo);
}

Well… what if i have something longer than that? Simply add null check before doSomethingWith(that)!

if (provider != null && provider.getProviderCoordinate() != null && provider.getProviderCoordinate().getLatidudeBase() != null ) {
    Coordinate c = provider.getProviderCoordinate().getLatidudeBase();
    doSomethingWith(globalInfo);
}

Well.. still too long. You don’t really need to get into that detail. Take care of your object’s contract. Why don’t we give a default value instead of null?

class ProviderBase {
  InfoBase globalInfo;
  InfoBase getGlobalIInfo() {
    if (globalInfo == null) {
      return InfoFactory.getDefaultInfo();
    }
    return globalInfo;
  }
}

But still, if null is expected, then handle it with a better way. Just because i hate NPE, it is just better to give default value because most of the time null data is caused by serialization of not-yet-completed data model migration. You might have a better way other than default value (like, Annotation?), but you get the idea.

Instant Messaging (Including Whatsapp) Is Not For Mobile

| Comments

Well, it’s been a while since i broke my smartphone. Since communication is very important these days, i should get a new phone ASAP. Fortunately i only need calling and texting, so i can simply buy a dumbphone to fullfill my need.

What? A dumbphone for today’s communication? What on earth am i actually doing? Because i only need SMS and GSM call. Even though my friends is actually on LINE, Whatsapp, Telegram, Skype, etc; those are actually a decoy to a more horrible communication. Let me tell you why i am doing this.

The first one, i am still able to contact my friend via phone call. So, no big deal.

The second one, i constantly use Slack for office-related communication. Release, hotfix, bug, “random chit-chat”. And since i use my office’s notebook with real keyboard, typing feels very convenient. Copy-paste log into Slack and let my coworker see them. Screenshot? Simply drag and drop. Need to notify someone about your new deployment? Private message her/him. Still does not work? We can switch back communication to email anytime we want.

The last one and the most important thing, i don’t need IM in my phone. Seriously. It is very handy to consume content on mobile, but not for producing it, including typing in it for 30 minutes or more. If we need to get something serious, we should do it within a big keyboard, where we can respond it fast and type it fast. But that’s just one problem.

Another problem is its distraction. Enough is enough. Even though i use Slack on my computer, i don’t need Slack on my mobile phone. When i had my smartphone, i didn’t install it too. A simple notification “Hey your build is broken,” to my phone simply could break my mood when it comes in weekend. Also, if it is really important thing, people won’t message me. They will call me. So, who need IM in mobile, anyway?

How about last-minute notification when i have a meetup? “Hey Mufid, i am sorry, the venue was changed. Now we are in Coffee shop, no more in Cafe. See you soon!” NO. If we plan it well, we will never have a last-minute information or last-minute-to-do-asap. Remember when we didn’t have a phone and/or when we were still using a pager? Remember how we planned everything very well so we minimize last-minute communication since at that time it was very hard to notify someone if we changed our plan in the last minute?

I will using my dumbphone, at least until i know why IM in Mobile is actually good for me.

Edit: sorry for my English. Feel free to give feedback. I will very happy if someone could help improve my English. I am not a native unfortunately : (