将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
見栄えがよく、デザイン性の高いコードを書くことは、それほど難しいことではない。主なルールを知り、それをコードに使うだけだ。そして、一度にすべてを同じようにする必要はなく、1つのことに慣れたと感じたら、別のことを考えるようにする。
まず、SOLIDと呼ばれる最も基本的なルールを紹介しよう。SOLIDとは、優れたサッカーを実現するための設計原則をまとめた言葉である。 コード これはロバート・C・マーティンが考案したもので、どのようなものなのか:
クラスが変わる理由はひとつだけであるべきだ。言い換えれば、クラスがやるべき仕事はひとつだけであるべきで、多くの責任を持つ大きなクラスを書くのは避けるべきだということだ。もしクラスが多くのことをしなければならないのであれば、それぞれを別のものに委譲すべきである。
クラス Notification
def initialize(params)
params = params
終了
def call
メール送信者.new(メッセージ).call
終了
プライベート
defメッセージ
# いくつかの実装
終了
終わり
これは、クラスの振る舞いを変更することなく拡張できるようにすべきであるというものだ。言い換えれば、クラスに変更を加えることなく、そのクラスを簡単に拡張できるということだ。例えば、strategyパターンやデコレーターを使うことでこれを実現できる。
クラス Notification
def initialize(params, sender)
params = パラメータ
送信者 = 送信者
終了
def call
sender.call メッセージ
終了
プライベート
defメッセージ
# いくつかの実装
終了
終わり
クラス EmailSender
def call(message)
# いくつかの実装
終了
終わり
クラス SmsSender
def call(message)
# いくつかの実装
終了
終わり
この設計では、コードを変更することなく、新しい送信者を追加することが可能です。
派生クラスは基底クラスと置換可能でなければならない。言い換えれば、同じ祖先に由来するクラスの使い方は、他の子孫クラスに置き換えることが容易でなければなりません。
クラス Logger {
info (メッセージ) {
console.info(this._prefixFor('info') + message)
}
error (メッセージ, err) {
console.error(this._prefixFor('error') + メッセージ)
if (err) { { コンソール.エラー(err)
console.error(err)
}
}
_prefixFor (type) { // 何らかの実装
// いくつかの実装
}
}
class ScepticLogger extends Logger { { { ScepticLoggerはロガーです。
info (メッセージ) {
super.info(message)
console.info(this._prefixFor('info') + '以上です。')
}
error (message, err) { エラー
super.error(message, err)
console.error(this._prefixFor('error') + '大変だ!')
}
}
どちらもまったく同じ使用インターフェイスを持つので、クラス名を置き換えるのは簡単だ。
クライアントに特化したきめ細かなインターフェイスを作るべきだとしている。インターフェースとは何か?それは、コードのある部分の使用方法を提供するものである。つまり、このルールに違反する例としては、メソッドが多すぎるクラスや、引数のオプションが多すぎるメソッドが挙げられる。この原則を視覚化する良い例は、リポジトリ・パターンです。なぜなら、私たちはしばしば1つのクラスに多くのメソッドを置くだけでなく、それらのメソッドは多すぎる引数を受け入れるリスクにさらされているからです。
# 今回は最良の例ではない
クラス NotificationRepository
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
終了
終了
#と、より良いもの
クラス NotificationRepository
def find_all_by_ids(ids:)
Notification.where(id: ids)
終了
def find_all_by_ids_info(ids:)
find_all_by_ids(ids).where(type: :info)
end
end
これは、具体的なものではなく抽象的なものに依存すべきだというものだ。言い換えれば、他のクラスを使用するクラスは、そのクラスの実装の詳細に依存すべきではない。
クラス Notification
def initialize(params, sender)
params = パラメータ
送信者 = 送信者
終了
def call
sender.call メッセージ
終了
プライベート
defメッセージ
# いくつかの実装
終了
終わり
送信者オブジェクトについて知っておく必要があるのは、引数としてメッセージを受け取る `call` メソッドを公開しているということだけだ。
コードを書いているときに絶対に避けるべきことを知ることも非常に重要である。そこで、コードを保守しにくくし、テストしにくくし、再利用しにくくする愚かな原則を集めた別のコレクションを紹介しよう。
シングルトンはアンチパターンとみなされることが多く、一般的には避けるべきである。しかし、このパターンの主な問題は、グローバル変数/メソッドの言い訳のようなもので、開発者がすぐに使いすぎてしまう可能性があることです。
あるモジュールの変更が、アプリケーションの他の部分の変更をも必要とする場合、それは維持される。
もしあなたのコードが優れているなら、テストを書くことは悪夢ではなく、楽しいと思えるはずだ。
ここで重要なのは「時期尚早」という言葉だ。今すぐ必要でないのなら、それは時間の無駄だ。微細な最適化をするよりも、良質でクリーンなコードに集中したほうがいい。
良いコードを書く上で最も難しいことであるが、このことは、あなたの他の部分だけのためではないことを忘れてはならない。 チーム メソッドの名前は、短くて謎めいたものよりも、長くて、でもそれがすべてを物語っているものの方がいい。
コードが重複する主な原因は、密結合の原則に従っていることだ。もしコードが密結合であれば、再利用することができず、重複したコードが現れてしまう。
そして、しばしば省かれがちな2つの非常に重要なことにも触れておきたい。一つ目は、「YAGNI(ヤグニ)」、つまり「必要ない」という意味だ。コード・レビューをしているときや、自分でコードを書いているときにも、時々この問題を目にすることがある。今この瞬間に必要なコードを正確に書くべきで、それ以上でもそれ以下でもない。すべてのものは非常に速く変化する(特にアプリケーションの要件)ことを念頭に置くべきだ。時間を無駄にしてはいけない。
そして最後のことは、あまり目立たないかもしれないし、賛否両論あるかもしれないが、記述的なコードだ。クラス名、変数名、メソッド名を正しく使うという意味だけではない。コード全体が一目で読めるというのは、本当に本当に良いことだ。非常に短いコードが謎めいていて、書いた本人以外には何をやっているのか誰もわからないようなコードの目的は何でしょうか?私見では、次のような文字列を書く方がよい。条件文そして、昨日は座って、「結果はどうなったんだろう、どうしてこうなったんだろう?
const params = [
{
movies: [
{ title: 'ショーシャンクの空に' }、
{ title: 'カッコーの巣の上で一羽' }, { title: 'カッコーの巣の上で一羽' }.
]
},
{
movies: [
{ title: 'Saving Private Ryan' }、
{ title: 'パルプ・フィクション' }、
{ title: 'ショーシャンクの空に' }、
]
}
]
// 最初の命題
関数 uniqueMovieTitlesFrom (params) { // 第一の命題
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(movie => movie.title)
return [...new Set(titles)]]。
}
// 第二の命題
関数 uniqueMovieTitlesFrom (params) { // 第二命題
constタイトル = {}。
params.forEach(param => {)
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(タイトル)
}
見ての通り、覚えるべきルールはたくさんあるが、冒頭で述べたように、いいコードを書くのは時間の問題だ。コーディングの習慣を1つ改善しようと考え始めれば、別の良いルールが後からついてくるのがわかるはずだ。
続きを読む
Ruby on Jetsとは何か、それを使ってどのようにアプリを作るのか?