ROUTES

۸ اسفند ۱۳۹۲

گیرهای روبی

خیلی از تازه‌کارهای Ruby on Rails شیفته‌ی کار کردن با این فریم‌ورک قدرتمند میشن و بدون اطلاع دقیق از زبان روبی شروع به ساخت برنامه‌هاشون باهاش میکنن. و البته که هیچ اشکالی تو این قضیه نیست. مگر اینکه این تازه‌کارها روی روش‌هاشون پافشاری کنن و تبدیل به یک توسعه‌دهنده ارشد بشن، بدون اینکه بازم از زبان روبی اطلاعی داشته باشن.

به‌هرحال، دیر یا زود، تازه‌کارها یا توسعه‌دهنده‌های باتجربه، هر دو به گیرهای روبی برخورد میکنن. پیچیدگی‌های خیلی کوچیکی که توی زبان مخفی هستن و ساعت‌ها دیباگ طاقت‌فرسا آخرش منتهی به «مشکل همین بود؟!!» میشه.

اینجا یک لیست از این گیرهای کوچیک روبی رو گذاشتم که توسعه دهنده‌های روبی باید ازشون مطلع باشن. برای هر مورد یک مثال و راهکار قرار دادم.

and/or مثل &&/|| نیستند

surprise = true and false # => surprise is true
surprise = true && false  # => surprise is false

عادت خوب

همیشه از &&/|| استفاده کنید.

جزئیات

  • and/or نسبت به &&/|| الویت کمتری دارن
  • and/or نسبت به = الویت کمتری دارن ولی &&/|| الویت بالاتری دارن
  • and و or هر دو الویت یکسان دارن، درصورتی که && الویت بالاتری نسبت به || داره

میتونیم مثال اول رو با گذاشتن پرانتز روشن‌تر کنیم، که نشون خواهد داد چطور استفاده از and از && متفاوت هست:

(surprise = true) and false # => surprise is true
surprise = (true && false)  # => surprise is false

eql? مثل == نیست (حتی مشابه equal? و === هم نیست)

1 == 1.0   # => true
1.eql? 1.0 # => false

عادت خوب

فقط از == استفاده کنید

جزئیات

==، ===، eql? و equal? رفتارهای متفاوتی دارن، که برای شرایط و استفاده متفاوت بکار میرن. برای مقایسه‌ی چیزها باید همیشه از == استفاده کنین، مگر اینکه واقعا احتیاج به موارد خاصی داشته باشین (مثل اینکه بخواین واقعا بین 1.0 و 1 تفاوت بزارین) یا اینکه هر کدوم از اینها رو بیاین بازنویسی کنین.

بله، eql? هوشمندتر از == عمل میکنه، ولی آیا این واقعا اون چیزی هست که بهش احتیاج دارین؟

super مشابه super() نیست

class Foo
  def show
    puts 'Foo#show'
  end
end

class Bar < Foo
  def show(text)
    super

    puts text
  end
end

Bar.new.show('test') # ArgumentError: wrong number of arguments (1 for 0)

عادت خوب

این یکی، یکی از مواردی هست که برداشتن پرانتزها نه تنها سلیقه‌ای نیست، بلکه منطق برنامه رو عوض میکنه.

جزئیات

  • super (بدون پرانتز) متد والد رو با دقیقا همون متغیرهایی که به متد اصلی ارسال شدن صدا میزنه (بنابراین super در Bar#show تبدیل میشه به super('test') که اینجا باعث خطا میشه چون متد والد هیچ متغیری رو نمی‌پذیره)
  • super() (با پرانتز) متد والد رو بدون هیچ متغیری صدا میزنه

exceptionهای شما نباید Exception باشند

class MyException < Exception
end

begin
  raise MyException
rescue
  puts 'Caught it!'
end

# MyException: MyException
#       from (irb):17
#       from /Users/karol/.rbenv/versions/2.1.0/bin/irb:11:in `<main>'

(در این کد عبارت rescue برای MyException هیچ‌وقت اجرا نمی‌شود و پیام 'Caught it!' هم نمایش داده نخواهد شد)

عادت خوب

  • وقتی که کلاس exception خودتون رو تعریف می‌کنید، از StandardError یا هر کدوم از نوادگانش :))) (descendants) ارث‌بری کنید. هیچ‌وقت از Exception استفاده نکنید
  • هیچ‌وقت از rescue Exception استفاده نکنید. اگر میخواید یک rescue کلی انجام بدید، عبارت rescue رو خالی بزارین (یا اینکه از rescue => e استفاده کنید)

جزئیات

  • وقتی عبارت rescue رو خالی میزارین، ینی اینکه exceptionهایی که از StandardError ارث‌بری کرده‌اند گرفته میشن و نه Exception
  • اگر از rescue Exception استفاده کنین (که نباید بکنید)، شما خطاهایی رو catch می‌کنید که نمی‌تونید کاری براش بکنید (مثل خطای out of memory). همینطور سیگنال‌هایی مثل SIGTERM رو هم گیر میندازین که باعث میشه نتونید اسکریپت رو با CTRL-C متوقف کرد.

class Foo::Bar مثل module Foo; class Bar نیست

MY_SCOPE = 'Global'

module Foo
  MY_SCOPE = 'Foo Module'

  class Bar
    def scope1
      puts MY_SCOPE
    end
  end
end

class Foo::Bar
  def scope2
    puts MY_SCOPE
  end
end

Foo::Bar.new.scope1 # => "Foo Module"
Foo::Bar.new.scope2 # => "Global"

عادت خوب

همیشه از نسخه طولانی‌تر و با جزئیات بیشتر استفاده کنید:

module Foo
  class Bar
  end
end

جزئیات

  • کلیدواژه‌ی module (در کنار class و def) یک scope جدید تعریف میکنن. بنابراین، module Foo یک scope جدید Foo ایجاد میکنه که مقدار ثابت MY_SCOPE با مقدار 'Foo Module' درش هست
  • داخل این module ما یک کلاس class Bar تعریف کردیم، که یک scope جدید به نام 'Foo::Bar' ایجاد میکنه، که دسترسی به scope والد ('Foo') و تمام ثابت‌هایی که درش تعریف شدن داره
  • وقتی شما Foo::Bar رو با میان‌بر :: تعریف می‌کنین: class Foo::Bar، یک scope جدید ساخته میشه، که باز هم Foo::Bar نام داره، ولی اینجا دیگه والدی نداره، بنابراین دسترسی‌ای به scope با نام Foo نداره
  • بنابراین در داخل class Foo::Bar ما فقط دسترسی به ثابت MY_SCOPE داریم که در ابتدای اسکریپت با مقدار Global تعریف شده

اکثر متدهای bang! وقتی کاری نمی‌کنن مقدار nil بر می‌گردونن

'foo'.upcase! # => "FOO"
'FOO'.upcase! # => nil

عادت خوب

هیچ‌وقت به خروجی متدهای bang! پیش‌ساخته وابسته نباشین مثلا:

@name.upcase! and render :show

کد بالا میتونه یکسری رفتارهای غیرمنتظره ازش سر بزنه (یا اینکه یک رفتار کاملا قابل انتظار وقتی که @name از قبل uppercase باشه). همینطور این یک مثال دیگه‌اس که نباید از and/or استفاده کنین. هیچ درختی قطع نخواهد شد اگر این دو خط رو اضافه کنید:

@name.upcase!
render :show

متدهای attribute=(value) همیشه مقدار ارسال شده رو به عنوان خروجی برمی‌گردونن

class Foo
  def self.bar=(value)
    @foo = value

    return 'OK'
  end
end

Foo.bar = 3 # => 3

دقت کنید که این متد bar= مقدار 3 رو برمی‌گردونه با اینکه به مشخصا return 'OK' رو استفاده کردیم.

عادت خوب

هیچ‌وقت بر اتفاقاتی که در این نوع متدها میافته وابسته نباشید. برای مثال در عبارت‌های شرطی مثل این:

puts 'Assigned' if (Foo.bar = 3) == 'OK' # => nil

مشخصا این کار نخوهد کرد.

private متدهای self.method رو private نخواهد کرد

class Foo

  private
  def self.bar
    puts 'Not-so-private class method called'
  end

end

Foo.bar # => "Not-so-private class method called"

دقت کنید اگه private بود عبارت Foo.bar خطای NoMethodError بر می‌گردوند.

عادت خوب

برای اینکه متدهای کلاس‌تون رو private کنید باید از private_class_method :method_name استفاده کنین یا اینکه متدهای private رو درون class << self بزارین:

class Foo

  class << self
    private    
    def bar
      puts 'Class method called'
    end    
  end

  def self.baz
    puts 'Another class method called'
  end
  private_class_method :baz

end

Foo.bar # => NoMethodError: private method `bar' called for Foo:Class
Foo.baz # => NoMethodError: private method `baz' called for Foo:Class

پایان

فهرست بالا در ابتدا شاید چیز خاصی به نظر نیاد، ولی بعدا میاد خرتون رو میگیره. پس بهتره که در موردشون اطلاع داشته باشین. اطلاع داشتن در مورد اینها، ساعت‌ها وقت شما رو برای دیباگ کردن کدها زنده می‌کنه و از سردردهای آتی می‌کاهد :D

(منبع)

۲۷ بهمن ۱۳۹۲

داک داک گو برای برنامه‌نویس‌های وب بهتر است - با رسم شکل

ایده اصلی از Virtuous Code

DuckDuckGo is better for web developers

۱۷ بهمن ۱۳۹۲

باسیلیسکِ روکو، عجیب‌ترین و خطرناک‌ترین ایده در وب

نوشته‌ای از Andrew Smales در BN2B

دوست دارم یکی از چیزهای عجیبی که تو وب بهش برخوردم رو با شما درمیون بزارم. بهش میگن باسیلییکِ روکو، بعضی‌ها معتقد هستن حتی شنیدن درباره‌اش میتونه زندگی‌تون رو خراب کنه. چیزی که میگم مجازی نیست؛ ایده اینه که حتی فهمیدن باسیلیسکِ روکو، و نه حتی عمل کردن بهش، میتونه به این معنی باشه که تمام سوپرکامپیوترهای دنیا به شکل فیزیکی شما رو تا آخرین لحظه عمرتون عذاب بدن. پس... تا وقتی که مشکلی با این موارد ندارین. میتونید به خوندن ادامه بدین.

باسیلیسکِ روکو مفهومی هست که در جامعه‌ی Singularitarians و Transhumanists شکل گرفت. این افراد آدم‌های جالبی هستن. برای تازه‌کارهایی مثل من خوندن در مورد transhumanism میتونه خیلی خسته‌کننده باشه؛ به سرعت تبدیل به یک مسئله فکری پیچیده میشه، و همیشه یک مقدار مسائل علمی تخیلی هم توش هست که نمیشه ازش جداش کرد. من سال گذشته با یکی از کسانی که به Singularity اعتقاد داشت چت کردم، و گفتگوی ما در حالی تموم شد که من نمی‌دونستم ایشون ۱۰ برابر من باهوش‌تر هست یا اینکه کلا دیوانه‌اس. ایده باسیلیسکِ روکو اولین بار در LessWrong منتشر شد، یک جامعه تحت وب که شامل افراد زیادی هست که به Singularity/Transhumanism علاقه دارن. و البته سریعا جلوی ادامه بحث‌ها در این مورد گرفته شد، به دلیل اینکه باعث پریشانی شدید اعصاب و روان تعدادی از اعضا شد.

دیگه کم کم دارم وارد قسمت‌های ترسناک و خانه‌خراب کن قضیه میشم. هر مقاله‌ای که من در این مورد خوندم، همه شامل یک هشدار بودن، من هم نمی‌خوام بر خلاف جهت آب شنا کنم، بنابراین اگر با کمی عذاب فیزیکی که توسط یک روبات هوشمند به شما وارد میشه مشکل دارید، می‌تونید همین الان اینجا رو ترک کنید.

ایده پشت باسیلیسکِ روکو اینه: یک روزی، احتمالا یک روز در آینده، شاید یک علم خیلی کامل در مورد هوش مصنوعی( AI ) وجود داشته باشه. در واقع یکسری افراد هستن که معتقدن این مسئله غیرقابل اجتناب هست. این هوش مصنوعی انقدر باهوش و قدرتمند خواهد بود که می‌تونه بفهمه چه کسی در ساخته شدنش مشارکت کرده، حتی در زمان‌های خیلی قبل. این هوش‌مصنوعی علاقه خاصی به کسایی که در موردش تحقیق کردن و کسایی که روش سرمایه‌گذاری کردن داره (و اگر یکجورایی شک دارین، الان کسایی هستن که روی این نوع هوش‌مصنوعی کار میکنن و راه‌هایی هم برای سرمایه‌گذاری توشون وجود داره)، ولی با کسایی که این نوع مقاله‌ها رو میخونن، متوجه‌شون میشن، و بعد هم تصمیم میگیرن کاری نکنن به همون اندازه حال نمی‌کنه (حتی لینک مطلب رو هم تو یک سایت اجتماعی شیر نمی‌کنی؟ واقعا که!)

به نظر ربات باحالی میاد نه؟ مسئله جالب اینجا اینه که ما داریم در مورد یک هوش‌مصنوعیِ خوب یا دوست صحبت می‌کنیم. ایده اینه که به وجود آمدن یک هوش‌مصنوعی خدا مانند اجتناب‌ناپذیر هست، بنابراین محقق‌ها باید خیلی سریع یک نمونه‌ی خوب بسازن که برای انسان ارزش قائل باشه و به‌طور اتفاقی انسان رو نابود نکنه. به این ربات می‌گیم هوش‌مصنوعیِ دوست. واقعا هم چی بیشتر از نابود نکردن انسان‌ها دوستانه‌تر هست؟

خب برگردیم به فهرست افرادی که مشارکت کردن یا نکردن. برای اینکه این هوش‌مصنوعی زودتر به وجود بیاد، این ربات باید اونهایی که تو لیست بدها هستن رو تنبیه کنه و اینکار رو به خاطر ظالم بودنش انجام نمیده؛ این تنبیه فقط به خاطر اینه که هوش‌مصنوعی زودتر ساخته بشه. یادتون هست هوش‌مصنوعیِ خوب، که ساخته شده تا در کنار انسان‌ها وجود داشته باشه، باید قبل از یک هوش‌مصنوعی رندوم دیگه ساخته بشه که ممکنه به همون اندازه مراقب انسان‌ها نباشه؟ حالا، اگر شما برید و تمام پولتون رو بدید به محقق‌ها که روی این هوش‌مصنوعی کار کنن، مشکلی برای شما پیش نمیاد. اما اگه این مسئله رو متوجه شدین (به خوندن ادامه بدین، هنوز در ادامه چیزهای جدیدی هست)، اما هیچ‌کاری در این مورد نمی‌کنید، پس... انواع تنبیه و شکنجه در انتظار شماست.

حالا، شاید گیج بشین که چطور رباتی که ممکنه تا سال‌های بعد از مرگ شما وجود نداشته باشه شما رو شکنجه کنه. منم این موضوع رو تا مدتی بعد از اینکه در مورد باسیلیسکِ روکو خوندم متوجه نشدم، ولی وقتی فهمیدم، متوجه شدم که این قسمتش بدترین و ترسناک‌ترین قسمت قضیه‌ست.

این هوش‌مصنوعی انقدر پیشرفته است که میتونه یک کپی تقریبا کامل از شما رو بسازه، و شکنجه‌اش کنه. یک هوش‌مصنوعیِ پیشرفته‌ی خدا مانند، که ذهن ضعیف ما نمی‌تونه متوجه‌اش بشه، احتمالا در شکنجه کردن این کپی شما کارش رو خوب بلده. ما داریم در مورد سال‌ها درد فیزیکی صحبت می‌کنیم؛ غم و اندوه روحی بی‌پایان؛ حتی ممکنه حشرات موذی هم باشن، یا مثلا مار. خیلی خیلی چیزهای بد.

اما حالا چرا اصن باید مهم باشه که یک کپی شما در آینده شکنجه بشه، نه حتی خود شما؟ نکته اینجاست: کپی شما مثل شما فکر می‌کنه، تجربه‌های مختلف زندگی رو مثل شما پشت سر میزاره (قبل از اینکه شکنجه بشین)، و مثل شما هم احساس میکنه. اون کپی فکر میکنه شماست. تنها تفاوت بین شما کپی‌تون اینه که شما به آخر عمرتون میرسین و می‌میرید، ولی کپی شما در یک نقطه‌ای از زندگی گیر اون هوش‌مصنوعی میافته و شکنجه میشه. تا رسیدن به اون نقطه، کپی شما هیچ ایده‌ای نداره که در واقع خود واقعی شما نیست، و مشکل اینجاست:

شما ممکنه که اون کپی باشید.

پ.ن: تا حالا فکر کردین دژاوو چیه؟

۱۱ بهمن ۱۳۹۲

همیشه زمان برای رسیدن به آرزوهاتون دارید

نوشته‌ای از David Heinemeier Hansson در Signal vs. Noise

«دوست داشتم یک شرکت بزنم / یک برنامه‌نویس عالی بشم / یک وبلاگ خفن بنویسم، ولی زمان کافی در روز ندارم!» چیز شعره. همیشه زمان کافی هست، شما فقط درست ازش استفاده نمی‌کنین.

یکم سنگ دلانه جلو رفتم، ولی کلا از شنیدن «نبود زمان» به عنوان یک عذر برای اینکه نمیشه عالی بود خسته شدم. واقعا اونقدری زمان نمی‌بره که شروع کرد، ولی واقعا لازمه که از ته دل بخواید. خیلی از مردم واقعا از ته دل این رو نمی‌خوان و نفس‌شون رو با عذری مثل زمان توجیه میکنن.

این عذر وقتی کاملا افسرده کننده‌اس که از زبان دانشجو/آموزها می‌شنویش.

آخه، من خیلی کلاس دارم. آخه، من خیلی مشق دارم. هیچ وقتی برای یاد گرفتن بعد از مدرسه/دانشگاه نیست.

اگر اینطوریه، پس اشتباه دارید میرید!

یک آقای باهوشی یک زمانی گفت، هیچ وقت نگذارید مدرسه/دانشگاه رفتن‌تون پروسه یادگیری‌تون رو دچار اختلال کنه. اینکه بخواهید در زمانی که لازم هست یکسری چیزها رو فدا کنید، یکی از مهمترین مهارت‌هایی هست که یاد خواهید گرفت.

من تعداد زیادی B و C از کلاسهایی که به شدت به خاطر حضور درشون افتخار میکنم دارم، فقط به خاطر اینکه اصلا زمانی براشون صرف نکردم. زمان‌هایی که می‌تونستم بجاش برنامه‌های خودم رو بخونم، پروژه‌های خودم رو شروع کنم و کسب و کار خودم رو اجرا کنم.

و اینکار رو کردم. در دوران دانشجویی‌ام، من Instiki ،Rails و Basecamp رو ساختم و مسیری رو رفتم که یکی از شرکا در شرکت 37Signals شدم. فکر می‌کنید با همه اینها می‌شد نمره‌های ۲۰ رو ردیف میکردم و هنوز هم زمان کافی برای بازی World of Warcraft داشته باشم؟ نه.

اگر واقعا از ته دل چیزی رو بخواید، زمان لازم رو براش درست می‌کنید، بدون درنظر گرفتن مسائل دیگه. خودتون رو با عذرهای مختلف گول نزنید. اینکار خیلی راحته و، حقیقتش، برای هیچکس هم مهم نیست.

این کاملا وظیفه شماست که به آرزوهاتون برسید.