2005 6 7 8 9 10 11 12
2006 1 2 3 4 5 6 7 8 9 10 11 12
2007 1 2 3 4 5 6 7 8 9 10 11 12
2008 1 2 3 4 5 6 7 8 9 10 11 12
2009 1 2 3 4 5 6 7 8 9 10 11 12
2010 1 2 3 4 5 6 7 8 9 10 11 12
2011 1 2 3 4 5 6 7 8 9 10 11 12
2012 1 2 3 4 5 6 7 8 9 10 11 12
2013 1 2 3 4 5 6 7 8 9 10 11 12
2014 1 2 3 4 5 6 7 8 9 10 11 12
2015 1 2 3 4 5 6 7 8 9 10 11 12
2016 1 2 3 4 5 6 7 8 9 10 11 12
2017 1 2 3 4 5 6 7 8 9 10

ホーム

2012年12月11日

あのコード、Androidのですよね?Androidだったらデフォルト
値はリソースで持つのが王道ですけど。

まぁ、いいか。ちょっと面倒なんでRubyで書きますけど:

text1 = TextView.new(context)
text1.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
text2 = TextView.new(context)
text2.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
text1.setTextColor(Color::RED)
text2.setTextColor(Color::BLACK)
text1.setText(@name)
text2.setText(@title)

こういうコードをどう整理するかっていう話ですよね。で、
やっぱり、自分は、コンポーネントごとに整理します。

text1 = TextView.new(context)
text1.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
text1.setTextColor(Color::RED)
text1.setText(@name)

text2 = TextView.new(context)
text2.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
text2.setTextColor(Color::BLACK)
text2.setText(@title)

そうすると、メソッドに切り出したくなる。

text1 = newText1(context)
text2 = newText2(context)

def newText1(context)
  text1 = TextView.new(context)
  text1.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
  text1.setTextColor(Color::RED)
  text1.setText(@name)
  return text1
end

def newText2(context)
  text2 = TextView.new(context)
  text2.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
  text2.setTextColor(Color::BLACK)
  text2.setText(@title)
  return text2
end

そうすると、今度は似た部分を切り出したくなる。

text1 = newText1(context)
text2 = newText2(context)

def newText1(context)
  return newText(context, Color::RED, @name)
end

def newText2(context)
  return newText(context, Color::BLACK, @title)
end

def newText(context, color, text)
  text = TextView.new(context)
  text.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
  text.setTextColor(color)
  text.setText(text)
  return text
end

そうすると、今度は引数をパラメータ化したくなる。

text1 = newText1(context)
text2 = newText2(context)

def newText1(context)
  return newText(context, {:color => Color::RED, :text => @name})
end

def newText2(context)
  return newText(context, {:color => Color::BLACK, :text => @title})
end

def newText(context, params)
  text = TextView.new(context)
  text.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
  text.setTextColor(params[:color]) if params.key?(:color)
  text.setText(params[:text]) if params.key?(:text)
  return text
end

そうすると、今度はパラメータをまとめたくなる:

texts = [ 
  {:color => Color::RED,   :text => @name},
  {:color => Color::BLACK, :text => @title}
]

text1 = newText(context, texts[0])
text2 = newText(context, texts[1])

def newText(context, params)
  text = TextView.new(context)
  text.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
  text.setTextColor(params[:color]) if params.key?(:color)
  text.setText(params[:text]) if params.key?(:text)
  return text
end

lots of small piecesからonce and only onceへと流れて
いくわけです。

パラメータを別ファイルにしてrequireすれば、それも一種の
リソースファイルということになります。Rubyのような
インタプリタ言語ではよくやるんじゃないかと思います。

やっちゃいけないのが、横に切るやり方:

text1 = TextView.new(context)
text2 = TextView.new(context)

text1.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)
text2.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)

text1.setTextColor(Color::RED)
text2.setTextColor(Color::BLACK)

text1.setText(@name)
text2.setText(@title)

一見これもlots of small piecesにできそうなんですけど、
実は非常にリファクタリングしにくいんですね。このまま
リファクタリングしていくと:

textViews = [TextView.new(context), TextView.new(context)]
textViews.each{|text| text.setTextSize(TypedValue::COMPLEX_UNIT_DIP, 24)}
colors = [Color::RED, Color::BLACK]
texts = [@name, @title]
textViews.each_with_index{|text, i| text.setTextColor(colors[i])}
textViews.each_with_index{|text, i| text.setText(texts[i])}

みたいな形になって、新しいTextViewを増やすのが面倒に
なるんです。パラメータをまとめたくなるようなコードにも
ならない。


本家Permlink


2012年12月01日

AndroidのEditTextがアンドゥをサポートしてなくって。
自前でやるしかない。TextWatcherでイベントは拾える。
それがまたわかりにくいAPIなんだけど。ハマったのはそこ
じゃなくって、エミュレータでの動き。

たとえば"ab"と入力した後にアンドゥすると"a"になる。
そこまでは思惑どおり。でも、その後、"c"を入力すると、
"abc"となる。アンドゥで消したはずの"b"が、キーボード
から入力するとなぜか復活する。

なんでだろう、なんでだろう?Spannableとか関係してる?
他のエディタはどうやってるんだろう?あれ?EditText
使ってないエディタが結構多い?あれ?やっぱりこの
エディタのコードでも復活しちゃうな。おいおい、4.2にも
なって、まだこんなマヌケなバグが残ってんのかよ?

はい、エミュレータのバグでした。Nexus7で試すと、そんな
現象は起きませんでした。

https://github.com/tkojitu/UndoDemo

最初は「アンドゥといえばCommandパターンだろ、jk」
みたいな感じで実験してたんだけど、それだとコンテキスト
メニューからの編集には対応できないわけで。

TextWatcherでイベント拾って。TextWatcherっていうのは、
beforeの部分がafterに置き換えられるというイベント。
なので、アンドゥはその逆置換をやってやればいい。
リドゥは、もう一度同じ置換をやってやればいい。ただし、
アンドゥもリドゥもTextWatcherがイベントを拾うので、
それは無視しないといけない。

--

しかし、Androidのアプリでソースが公開されてるのは、
そのまま持ってきてもビルドできないのが多い。

--

Googleは、Androidのドキュメントをそろえるつもりが
ないらしい。developer.android.comは、MSDN並みに
よく変わり、MSDN並みに役立たず。APIドキュメントは
しっかり書かれているのが救いなんだけど。

ちょっと前まではチュートリアルがあったんだけど、
一掃された。ガイドはあるけど、ボンヤリした話しか
載ってない。コード見たけりゃSDKのサンプル見ろって
方針らしい。ところが、そのサンプルも、1つのプロジェクト
にたくさん詰め込みすぎてて、何が何やら。

ググれば引っかかるのはStackOverflowばかり。それを
信じていいかどうかもよくわからない。そういえば、
MSDNもまた変わって、StackOverflowを検索する
オプションがついた。ウザいだけ。

StackOverflowのようなQAサイトは、いってみればバッド
ノウハウの集積所なわけで、Javaチュートリアルのような
正当性や全体としての整合性というものがない。日本でも
後追いサイトがいくつか出てきたけど、そんなことやる
くらいならStackOverflowの日本語化に協力したほうが
まだしも建設的じゃないのかね。ニコ動ほど市場が広い
わけでもなかろうし、日本固有の事情があるわけでもないし、
さほど差別化ができると思えないし。


本家Permlink


Copyright © 1905 tko at jitu.org

バカが征く on Rails