วันจันทร์ที่ 2 มกราคม พ.ศ. 2555

เขียนโปรแกรม Ruby บน Sketchup ใน Style C#

โดย
อ.ธนะพันธ์ อินทรเกสร
1/1/12

บทที่ 1 เริ่มรู้จัก Ruby บน Sketchup

ผมทำการสอน C# มาหลายปี พบว่า C# เป็นภาษาที่ง่าย และมี Syntax ที่เข้าใจง่าย แต่เป็น Syntax Strong Type ทำให้การเขียนโปรแกรมช้า แต่ถ้าทำโปรแกรม ขนาดใหญ่มีการควบคุม และตรวจสอบได้ง่าย
ผมเริ่มมาดู Sketckup เนื่องจาก มีโครงการคิดราคาจากแบบ 3D และมีคนแนะนำว่า Sketckup มีการใช้อย่างแพร่หลาย น่าจะมีโปรแกรม คิดราคาแบบเดียวกัน กับบน Autocad หรือ Revit

ผมจึงได้เริ่มดู Sketckup พบว่า ระบบภาษาของ Sketckup เป็นภาษาเก่าแก่ ภาษาหนึ่ง คือ ภาษา Ruby เป็นภาษา Object Oriented Programming ที่ดีในยุกต์เก่า ภาษา Ruby ที่มีชื่อเสียงมานาน คือ Ruby on Rails เป็นภาษาที่ใช้ ทำ Web แบบเดียวกับ ภาษา PHP เราก็จะพบตัวอย่างจำนวนมากที่ใช้ Ruby ในการสร้างโปรแกรมด้วย Ruby ใน Sketchup เป็นภาษาแบบInterpreter  ไม่ใช่แบบ Compiler วิธีการเขียนโปรแกรมก็จะพลิกแพลง ได้มาก เหมือน กับ ภาษาเว็บเพจ PHP ที่ใช้ Dynamic Code (โปรแกรมเปลี่ยนแปลง Code ระหว่างที่ทำงาน) ข้อเสียคือช้า และการ Debug จะไม่ค่อยมี Tool ที่ดีเมื่อเทียบกับ Compiler เช่น Visual Studio
ปัญหาคือ Ruby มี Syntax ที่ไม่ค่อยคุ้ยเคยกับโปรแกรมในปัจจุบันทั้ง
คนที่เป็น C# จะทำโปรแกรม บน Ruby โดยไม่ยากได้อย่างไร
มาดู Code แรกของ โปรแกรม Hello World ทั้ง 2 แบบ

C#
Ruby
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace helloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World");
        }
    }
}


puts Hello World

จะเห็นว่า Ruby เขียนแบบง่ายๆ สั้นๆ การจบคำสั่งใช้ขึ้นบรรทัดใหม่ ในการแสดง ผล ซึ่งเป็นธรรมชาติของโปรแกรม ชนิด Weak Type และ เป็น Interpreter ซึ่งเที่ยบกับ AutoLisp ก็จะเป็น (Print Hello World) คล้ายๆกัน

ข้อสังเกตุ ในโปรแกรมของ C# จะมีการแสดง Class สำหรับการเรียกใช้ ขณะที่ Ruby จะเป็นการเรียกโดยตรง มีลักษณะแบบเดียวกับภาษา  Basic ในยุกต์แรก
ที่น่าสนใจคือ Ruby มีการจัดการแบบภาษาสมัยใหม่มีการจัดการเรื่อง Class และ การจัดการ ตัวแปร (Variable ) และการจัดการ Function Method ใน Class หรือไม่ คำตอบคือ มี Ruby ได้มีการ กำหนด ในรูปแบบของ Class ได้เหมือนกัน แต่ขณะเดียวกันก็ทำงานแบบคำสั่งโดยตรง ก็ได้ หลายคนที่เขียนโปรแกรมครั้งแรกจะชอบแบบนี้มากเพราะสร้าง โปรแกรมได้เร็ว แต่ถ้าเขียนกันเป็น พันบรรทัดแล้วก็ ไม่สนุกแน่ เพราะการ ไล่โปรแกรมจะยากมาก

แต่ข้อดีของ Ruby คือความคล่องตัวในการคำนวน ปรับ syntax
ข้อเสียคือ ภาษาไม่ควบคุมการ เข้าหา ตัวแปร และ Function,Method ของผู้เขียนโปรแกรม จะยากในการ Debug

ข้อดีของ C# คือ เป็นภาษาที่มีการจัดระเบียบ อย่างดี ในเรื่องของ Class สำหรับการเขียนโปรแกรม ขนาดใหญ่ และมีตัวช่วยเขียน Debugger ที่ดีที่สุดในโลก(Microsoft ทำดีจริงๆ)
ข้อเสีย ต้องวางแผนการเขียนโปรแกรมให้ดี และโชคไม่ดีคือ Support Sketckup
มีคนถามเสมอว่าแล้วบน Mac Osx, Iphone มี C# หรือไม่ คำตอบคือมี  Mono project และฟรี ทดลองใช้แล้ว ใน Console Mode ใช้เหมือนกับใน Visual studio แต่ใน Form การเรียก control จะต่างกัน แต่ก็ทำงานแบบเดียวกัน

Syntax ภาษาของ Ruby

Syntax  ภาษาของ Ruby มีมากกว่า C# มากเพื่อความคล่องตัวของผู้ใช้งาน ดูได้จาก Wikipedia จะมีคำอธิบาย อยู่พอสมควร แต่ เพื่อความมีระเบียบ ในแบบ C# จะใช้ Syntax ที่เขียนโปรแกรมเพื่อใช้งาน ไม่มาก และจะเข้าใจได้ง่ายกว่า โดยที่ไม่ต้องเข้าใจทั้งหมด  เพราะการเขียนโปรแกรมที่เข้าใจง่าย ไม่ควรใช้เทคนิค ซับซ้อน

Note ข้อเข้าใจในภาษาเขียนของผม ถ้าผมใส่ <abc> หมายถืงตรง abc จะเป็นชื่อที่อาจจะเป็นชื่อ โปรแกรม หรือตัวแปรที่ตั้งเอง หรือชื่อใดๆ

ตัวแปร Variable
ตัวแปรใน ภาษา Ruby เป็นตัวแปรที่มีทั้งระบุและไม่ระบุ Type

ชนิดตัวแปร
รูปแบบ
ตัวแปร local สำหรับใช้ใน Function หรือ Method
ใช้ตัวอักษรตัวเล็ก อยู่ภายใต้ def..end
def <function>
len=10.0
end
len จะเป็นตัวแปรที่มีค่าเฉพาะใน
def <function> จนจบ ที่ end

ตัวแปร Global สำหรับส่งต่อ ระหว่างโปรแกรม หรือติดตลอดโปรแกรม
ใช้ $<ชื่อ>
$price =20.0
$price  จะมีค่า และแก้ไขได้ตลอดโปรแกรม มีค่าเดียว

ตัวแปร คงที่ หรือ constant
ตัวแปรนี้จะเปลี่ยนค่าไม่ได้ และ
มีค่าตลอดโปรแกรม
ใช้ตัวอักษรใหญ่ Capital
เช่น
PI=3.14159


ตัวแปร แบบ Instant ใช้ใน Class
ใช้ เครื่องหมาย @ นำหน้า
เช่น
@height=2.0


ปัญหาหนึ่งของ Ruby คือไม่ควบคุม เรื่องชนิด Type ของตัวแปร ทั้งเริ่มต้น และระหว่างทำงาน อันนี้เป็นปัญหาในการ Debug มาก เพื่อความเป็นระเบียบ
จะต้องกำหนด Syntax ต่อท้าย ให้ง่ายต่อการจดจำ เช่น _i,_r,_s

count_i หมายถึง ตัวแปรแบบตัวเลขเต็ม
dist_r หมายถึงต้วแปร ทศนิยม
name_s  หมายถึง ตัวแปรอักษร

ไม่นั้นเวลาแก้ไขจะงงมากเมื่อโปรแกรมมีขนาดใหญ่แล้วต้องแก้พร้อม Debug

การสร้าง Function หรือ  Method

การสร้าง Function เป็นแบบ ง่ายๆโดยกำหนด
def <ชื่อ Function>

<เนื้อโปรแกรม>

end
 ^ จบโปรแกรม

สำหรับการส่งค่าตัวแปร Parameter ให้ส่งด้านหลังใน วงเล็บ

def compute_volume(w,l,d)
W*l*d
End

เทียบกับ C#
private double compute_volumn(double w,double l,double d)
{
   return w*l*d;
}

การคืนค่าหรือ Return value จะต้องทำโดยเป็นค่าสุดท้ายของการคำนวน
ในกรณีนี้จะเป็น ค่าที่เกิดจากผลการคูณ ของ w*l*d อันเป็นปริมาตรลูกบาตร์
ถ้าต้องการคำนวนโดยการกำหนด ตัวแปร Local ก็สามารถทำในรูปแบบนี้

def compute_volume(w,l,d)
v_r=W*l*d
end_R


ตัวแปร v จะใช้ในโปรแกรม compute_volume เท่านั้น
เทียบกับ C#
private double compute_volumn(double w,double l,double d)
{
   double v= w*l*d;
   return v;
}


โปรแกรมที่เป็น function ทำงานโดยการ  Pass by value
คือส่งค่า แล้วไม่รับกลับ การส่งกลับ ดังนั้น Function จะรับค่ากลับได้เพียง
ครั้งเดียว ซึ่งอาจจะส่งกลับเป็น Class หรือ Array ที่มีหลายค่าก็ได้
เช่น

def area_perimeter( w , l)
  area_r = w*l
  peri_r = (w+l)*2
 [area_r,peri]
end

เวลาใช้งาน ค่าก็จะใส่ลงในตัวแปรตามลำดับ

myarea_r,myperi_r= area_perimeter( 2, 3)


ปัญหา คือ Ruby จะไม่เช็คว่า การรับค่า ครบหรือไม่ เป็นเรื่องของ ผู้เขียนต้อง ตรวจเอง

สำหรับ C# จะทำแบบนี้ไม่ได้ เนื่องจาก C# จะส่ง Return ได้ทีละตัว แต่ส่ง ค่าไป Reference จะได้กลับมา

double area_perimeter(ref double peri, double w, double l)
{
    double area= w*l;
    peri = (w+l)*2;
    return area;
}


การเขียนโปรแกรม Ruby แบบ C# เริ่มได้แล้ว
ถ้าไม่ต้องคิดถึงการสร้าง Class โปรแกรมง่ายๆ ก็สามารถทำงาน ได้แล้ว เช่น
ตัวอย่างโปรแกรมคำนวน พื้นที่รั้ว
มีโจทย์​อยู่ว่า มีพื้นที่เป็นรูปหลายเหลี่ยม ต้องการคำนวนพื้นที่รั้วถ้ารั้วสูง 2 เมตร เพื่อนำพื้นทีไปคำนวนงานต่อไป

มาดู Flowchart

[จำนวนจุด,ตั้งค่าระยะรวม=0]
    V
[เปลี่ยนเป็น LineSegment]
    V
<ทำที่ละ Segment จนจบ> --------à[พื้นที่=ระยะรวม*ความสูง]->จบ
   V           ^                
 [ระยะรวม+=คิดระยะทางแต่ละ LineSegment]


โดยการสร้าง Function ที่ชื่อว่า wdist สำหรับคำนวนระยะทาง
และให้ Loop หลักทำการคำนวนรวมค่า

ถ้าเป็น C# จะเขียนแบบนี้
class Program
    {
     static double wdist(double x1, double y1, double x2, double y2)
        {
          double dd = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
            return Math.Sqrt(dd);
        }
        static void Main(string[] args)
        {
            // x as 0 , y as 1 in second Array location
          double[,] pts = new double[5, 2] { { 0, 0 }, { 10, 0 },
 { 10, 5 }, { 0, 5 }, { 0, 0 } };
            double totaldist = 0;
            double wallh = 2.0;// wall height
            for (int i = 0; i =< 3; i++)
            {
                totaldist = totaldist + wdist(pts[i, 0], pts[i, 1], pts[i + 1, 0], pts[i + 1, 1]);

            }
            double area1=totaldist*wallh;
            Console.WriteLine("Total dist,area="+totaldist.ToString()+","+area1.ToString());
        }
    }


เราลองเปลี่ยนเป็น Ruby โดยใช้ Style C#

def wdist(x1,y1,x2,y2)
   dd_r=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
  Math.sqrt(dd_r)
end


pts = [[0,0],[10,0],[10,5],[0,5],[0,0]]
totaldist_r=0.0
wallh_r=2.0
i =0
for i in (0..3)
totaldist_r=totaldist_r+wdist(pts[i][0],pts[i][1],pts[i+1][0],pts[i+1][1])
end
area1_r=totaldist_r*wallh_r
puts "Total dist="+totaldist_r.to_s+","+area1_r.to_s


ข้อสังเกตุ

มีตัวแปรของ C# จะกำหนดเป็น Strong Type โดยกำหนดเป็นตัวแปร แบบ double และกำหนด ตัวแปรเป็น Array

Array ­ของ C# ต้องกำหนดการใช้งานโดย new
double[,] pts = new double[5, 2] { { 0, 0 }, { 10, 0 },
 { 10, 5 }, { 0, 5 }, { 0, 0 } };


การนำค่าตัวแปรมาใช้จะเป็น
x1=pts(0,0)

Array ของ ruby ไม่ต้องกำหนด type และขนาด
pts = [[0,0],[10,0],[10,5],[0,5],[0,0]]

การนำค่าตัวแปรมาใช้
x1=pts[0][0]

Flow control สำหรับโปรแกรม
ใน C# กับ Ruby เกือบจะเหมือนกัน

For loop ของ C#
for (int i = 0; i <= 3; i++)
{
   totaldist = totaldist + wdist(pts[i, 0], pts[i, 1], pts[i + 1, 0], pts[i + 1, 1]);
 }


For loop ของ Ruby
i =0
for i in (0..3)
totaldist_r=totaldist_r+wdist(pts[i][0],pts[i][1],pts[i+1][0],pts[i+1][1])
end



การควบคุม Flow โดยใช้ IF

ใน C# กับ Ruby เหมือนกัน จะ ใช้ if และตัวเทียบตรรก ได้แก่ <,>,==,!=,>=,<=
== หมายถึงเท่ากับ และ !=คือไม่เท่า

if(i<10)
{
 <เนื้อโปรแกรม>
}else
{
<เนื้อโปรแกรม>
}

ใน ruby
if (i<10)
<เนื้อโปรแกรม>
else
<เนื้อโปรแกรม>
end


การ Run โปรแกรม ใน Sketchup
เขียนโปรแกรม ลงใน Notepad แล้ว File->Save
c:\test.rb

ไปที่ เมนู ของ Sketup -> Window->Ruby console

พิมพ์ load c:/test.rb
สังเกตุ จะใช้ เครื่องหมาย / แทน \  ในการเรียกชื่อ File

โดยสรุป
การเขียนโปรแกรมด้วยภาษา ruby เริ่มต้นง่าย แต่การ เขียนโปรแกรมขนาดใหญ่ ต้องมีระเบียบมากกว่านี้ ซึ่งจะบอกในตอนต่อไป

2 ความคิดเห็น:

  1. ไม่ระบุชื่อ2 มีนาคม 2555 เวลา 22:24

    รับจ้างเขียนโปรแกรมไหมครับ

    ตอบลบ
  2. รับเขียน Ruby on Rails มีประสบการณ์ 5 ปี ติดต่อ 087-8242032

    อาร์ท

    ตอบลบ