ไปที่เนื้อหา


รูปภาพ

[.NET] :: Develop Persistent Framework


  • กรุณาลงชื่อเข้าใช้เพื่อตอบกระทู้
มี 16 โพสต์ตอบกลับกระทู้นี้

#1 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 09 October 2007 - 07:58:09 AM

หลังจากห่างหายไปนานครับ กลับมาคราวนี้ก็มาพร้อมกับความรู้ใหม่ๆครับ
สืบเนื่องมาจากตอนนี้ผมกำลังพัฒนา Framework เพื่อใช้กับงานที่บริษัท
ซึ่งออกแบบระบบเป็น Object แต่ติดตรงที่ถ้าผมมีการเพิ่ม property ลง
ไปใน object ก็ต้องมานั่งแก้ SQLStatement ตอนสั่งให้ object บันทึก
ค่าลงในฐานข้อมูล เลยไปค้นหาข้อมูลใน CodeProject
มีคนเขียน persistent โดยการ map attribute เข้ากับแต่ละ property
แล้วเอาไปยัดใส่ stored procedure เลยปิ๊งไอเดียมาเขียนเป็น framework
ของเรา แบบของเราดีกว่า ยอมรับครับว่าลอกบางอย่างมา แต่บางอย่างก็คิดเอง
ไว้ผมจะมา post หลักการและ code เอาไว้ เผื่อมีเซียน VC# มาดูจะได้มาช่วย
optimize หุหุเล่นง่ายเลยนะ ไปล่ะค้าบ

#2 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 10 October 2007 - 08:02:55 AM

ก่อนอื่นเราก็ต้องสร้าง Attribute ของเราเองขึ้นมาก่อนครับ โดยใน C# นั้นจะมีคลาสอยู่ 1 คลาส
ชื่อว่า "Attribute" โดยที่คลาสนี้นั้นอยู่ใน namespace "System" ครับ เราต้องทำการ inherits
จากคลาสนี้มาเป็น attribute ของเราเองครับ โดยใน framework ของผมจะมี attribute อยู่ 2 ตัว
คือ 1.attribute ที่ map กับ Class และ 2.attribute ที่ map กับ property

ผมเลยตั้งชื่อไว้แบบนี้นะครับ


public sealed class PersistentObjectAttribute : Attribute
{
}


And


public sealed class PersistentPropertyAttribute : Attribute
{
}


ทั้ง 2 คลาสประกาศแบบ public หมายถึงสามารถเข้าถึงได้จากคลาสอื่นๆ
และประกาศแบบ sealed หมายถึงคลาสนี้ไม่สามารถสืบทอดต่อไปได้ ซึ่งก็คือมันเป็นหมันไปซะแล้ว
ไม่อาจจะมีลูกหลานสืบสกุลได้ แหะๆ ผมประกาศเอาไว้เพื่อไม่ให้ถูกนำไป inherit ต่อนั่นเอง

ไว้ใน Rep ถัดไปเราจะมาเริ่มเขียน attribute กันนะครับ

#3 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 10 October 2007 - 08:11:12 AM

ก่อนอื่นเราต้องจำกัด attribute ของเราซะก่อนว่าสามารถเอาไป map กับอะไรได้บ้าง
เพราะว่าถ้ามีโปรแกรมเมอร์ทะลึ่งเอา attribute ที่เขียนไว้เพื่อ map กับ object ไป
map กับ property ล่ะก็เดี้ยงเลย

เราเลยต้องพิมพ์คำสั่งเพิ่มลงไปนะครับ แบบนี้

สำหรับคลาส PersistentObjectAttribute

[AttributeUsage(AttributeTargets.Class)]


สำหรับคลาสPersistentPropertyAttribute

[AttributeUsage(AttributeTargets.Property)]


ซึ่ง Method AttributeUsage เป็นการกำหนดขอบเขตการใช้งาน
ของ attribute ครับโดยกำหนดจาก AttributeTargets ครับ

AttrubuteTargets.Class ===> ใช้ได้กับคลาส
AttrubuteTargets.Property ===> ใช้ได้กับproperty

ซึ่งจากขั้นตอนนี้ผลลัพธ์ใน code ของเราจะเป็นแบบนี้


[AttributeUsage(AttributeTargets.Class)]
public sealed class PersistentObjectAttribute : Attribute
{
}



[AttributeUsage(AttributeTargets.Property)]
public sealed class PersistentPropertyAttribute : Attribute
{
}


ใน rep ถัดไปจะเริ่มอธิบายจากคลาส PersistentObjectAttribute ก่อนนะครับ

#4 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 11 October 2007 - 08:07:41 AM

ในตัว object นั้นผมต้องการเก็บข้อมูลแค่ 2 อย่างเท่านั้นคือ ชื่อตารางในฐานข้อมูล
และเวลาทำ insert delete update นั้นต้องการให้มีการใช้ transaction หรีอไม่
ดังนั้นผมก็ต้องมีตัวแปรมาเก็บค่า 2 ตัวดังนี้นะครับ


private string _TableName;
private bool _UseTransaction;


ตัวแปร 2 ตัวนี้เป็นตัวแปร private ที่เรา encapsulate ไว้ คลาสอื่นๆไม่สามารถเข้าถึงได้
แต่ถ้าเข้าถึงไม่ได้จะทำยังไง ก็เลยต้องประกาศ property ขึ้นมาเพื่อให้เราสามารถเข้าถึงตัวแปร
เหล่านี้ได้ แต่ไม่ได้เข้าถึงโดยตรงแต่ทำผ่านตัว property นั่นเอง ดังนั้นผมเลยประกาศ property
ให้กับตัวแปรภายในที่เราอยากให้ภายนอกเข้าถึงได้ (ในการพัฒนาระบบจริงๆนั้น ถ้าตัวแปรตัวไหนเรา
ไม่อยากให้ class อื่นๆเข้าถึง เราก็ไม่จำเป็นต้องสร้าง property ให้ตัวแปรนั้นๆ) ดังนั้นผมจังสร้าง
property ขึ้นมา 2 ตัวตมนี้นะครับ


        public string TableName
        {
            get { return _TableName; }
            set { _TableName = value; }
        }

        public bool UserTransaction
        {
            get { return _UseTransaction; }
            set { _UseTransaction = value; }
        }


แต่ยังครับ มันยังไม่จบแค่นี้สำหรับคลาสนี้ ถ้าเราเขียนแค่นี้เวลาเราจะเอา attribute นี้ไป map กับ
คลาสอื่นๆล่ะจะทำยังไง นั่นแหละครับเรายังขาดอีก 1 ขั้นตอน นั่นคือการสร้าง constructor นั่นเอง
ซึ่ง constructure จะทำงานเมื่อมีการสั่งสร้าง object นั่นเอง ซึ่งใน constructure ส่วนใหญ่ก็จะ
เขียนให้ทำการ initialize ค่าของตัวแปรภายในคลาสนั้นๆนั่นเอง เรามาทำการสร้าง constructure
กันดีกว่าครับ


       public PersistentObjectAttribute(string tableName, bool useTransaction)
        {
            _TableName = tableName;
            _UseTransaction = useTransaction;
        }


ใน constructure ด้านบนนี้เราสามารถกำหนดได้ว่าต้องการใช้ transaction หรือไม่ได้ใน constructure
ได้เลย แต่บางคนอาจจะบอกว่ายังไงๆก็ใช้ transaction ตลอดแหละ ต้องมาประกาศค่าเป็น true ทุกคลาสเหรอ
คำตอบคือไม่ครับ เราจะใช้วิธีการทำ overloading constructure ครับคือเป็น constucture ที่ส่งตัวแปร
เข้าไปต่างกันนั่นเอง มาดูกันเลยครับ


        public PersistentObjectAttribute(string tableName)
            : this(tableName, true)
        {
        }


สังเกตมั้ยครับว่าใน constructure นี้ผมไม่ได้เขียน code อะไรเลย แล้วมันทำงานได้ยังไง
ดูตรงนี้นะครับ


    : this(tableName, true)


ความหมายของมันก็คือให้ทำตาม constucture หรือ method ที่เราอ้างถึง โดยส่งค่าตัวแปรของเรา
เข้าไปนั่นเอง ซึ่งความหมายใน code ของผมก็คือให้ทำ constructure ตัวแรกแล้วส่งค่า usetransaction
เป็น true เข้าไปนั่นเอง

ดังนั้นถ้าเวลาเรา map เข้ากับ object แล้วเราประกาศแค่ชื่อ tablename อย่างเดียวโดยไม่ได้ระบุค่าให้ตัวแปร
usetransaction นั้น มันก็จะทำการส่งค่า true ไปให้ตลอดนั่นเอง ดังนั้นถ้าเราไม่ต้องการใช้ transaction เราค่อยมา
ส่งค่า false เข้าไปเท่านั้นเอง



#5 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 11 October 2007 - 08:17:54 AM

ส่วนวิธีการนำเอา attribute นี้ไปใช้ทำอย่างไร ถ้าอย่ใน project เดียวกันก็
ไม่ต้องเตรียมการอะไรครับ แต่ถ้าเราอยากให้สามารถนำไปใช้กับ project อื่นๆ
ตาม concept reusable ของ OOP ล่ะก็เราต้องไปสร้าง project แบบ
ClassLibrary ครับ แล้วก็เอาไฟล์ cs ที่เราเขียน add เข้าไปใน project
หลังจากที่เรา build project แล้วเราจะได้ไฟล์ Assembly(DLL version ใหม่)
ที่มีชื่อเดียวกันกับโปรเจ็คที่เราสร้าง

เวลาเราจะเอาไปใช้กับโปรเจ็คอื่นๆก็คือ copy ไฟล์ DLL ไปไว้ในที่ใดที่หนึ่งที่เราจำได้
แล้วก็ add Reference เข้าไปใน project นั้นๆ โดยเลือก browse ไปที่ path ที่เราเก็บ
DLL ไว้นั่นเอง

แล้วใน code เรานั้นเวลาจะใช้เราจะต้องมีการอ้าง namespace ซึ่งถ้าเราไม่ได้เปลี่ยนอะไร
namespace นั้นจะมีชื่อเดียวกับ Project ของเรานั่งเอง

หลังจากเตียมการแล้วก็มาเริ่มเขียน codeกันเลย

ถ้าเราไม่ต้องการใช้ transaction ก็ประกาศแบบนี้

    [PersistentObjectAttribute("Products",false)]
    public class Products
    {
     }


แต่ถ้าต้องการใช้ก็ประกาศได้ 2 แบบคือ

    [PersistentObjectAttribute("Products",true)]
    public class Products
    {
     }


หรือ

    [PersistentObjectAttribute("Products")]
    public class Products
    {
     }


เรื่องของ ObjectAttribute ก็มีเท่านี้ ส่วน propertyAttibute จะมา post ใน rep ต่อไปคับ

#6 X CroSs

X CroSs

    Truebot Co-Developer

  • Root Administrator
  • 102427 โพสต์
  • Gender:Male

โพสต์เมื่อ 11 October 2007 - 12:54:35 PM

อ่านแล้วเข้าใจวิธีสร้างครับ แต่ยังมองภาพไม่ออกเลยว่าเอาไปใช้ทำอะไร ?

เท่าที่เข้าใจคือ ปกติ เป็น db - > sql -> object แล้ว object -> sql -> ลง db
ทีนี้ ถ้าเราเปลี่ยน object ก้อต้องเปลี่ยน sql ตัวกลางด้วย เลยจะหาอะไรซักอย่างมาแก้ปัญหา ใช่รึป่าวคับ ?

คือไม่เก็ตเรื่อง class attribute ด้วย >.< ยังไงก้อรออ่านตอนต่อไปอยู่นะคับ

ปล. ขอตัวอย่างการใช้งานอย่างง่ายๆด้วย จะดีมากเลยค้าบ laugh.gif
ปล2. เซียน C# ก้อคุณกิ๊กไงคับ อิอิ

ts.gif

manutd18wm.png


#7 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 11 October 2007 - 06:09:05 PM

(X CroSs @ Oct 11 2007, 12:54 PM) ดูโพสต์

อ่านแล้วเข้าใจวิธีสร้างครับ แต่ยังมองภาพไม่ออกเลยว่าเอาไปใช้ทำอะไร ?

เท่าที่เข้าใจคือ ปกติ เป็น db - > sql -> object แล้ว object -> sql -> ลง db
ทีนี้ ถ้าเราเปลี่ยน object ก้อต้องเปลี่ยน sql ตัวกลางด้วย เลยจะหาอะไรซักอย่างมาแก้ปัญหา ใช่รึป่าวคับ ?

คือไม่เก็ตเรื่อง class attribute ด้วย >.< ยังไงก้อรออ่านตอนต่อไปอยู่นะคับ

ปล. ขอตัวอย่างการใช้งานอย่างง่ายๆด้วย จะดีมากเลยค้าบ laugh.gif
ปล2. เซียน C# ก้อคุณกิ๊กไงคับ อิอิ


แหมคุณกิ๊กนี่เซียนแทบทุกภาษาเลยนะครับ อิอิ

จุดประสงค์ที่ทำคลาสแบบนี้ขึ้นมาก็เพื่อแยก programmer ออกจาก sqlstatement ครับ

เช่นเวลาจะสั่ง save ค่าจาก object นั้นก็สั่งแค่

Products p = new Products();
p.ProductID = "12345";
p.ProductName = "Test Product";
p.Save();


ซึ่งถ้าเราเขียนแบบเดิมๆใน method Save() ของคลาส Products ต้องเขียนแบบนี้


SqlConnection con = new SqlConnection(Constr);
SqlCommand cmd = new SqlCommand();
cmd.connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Insert INTO ....... ";
cmd.ExecuteNonQuery();


อะไรทำนองนี้ แต่เมื่อเรามีการเพิ่ม field ใน database เราต้องมาแก้ไข property แล้วก็ sqlstatement ใน
method Save() ด้วยใช่ม้า ถ้าลืมแก้ก็เสร็จเลย และยิ่งไปกว่านั้น programmer เองต้องมาเขียน sql ทุกๆคลาส
เลยไม่ค่อยได้ใช้ความสามารถในการ inherit ซักเท่าไหร่

ผมก็เลยจะเขียนคลาสต้นแบบมาคลาสนึงที่ทำหน้าที่ Gen SQLStatement จาก Attibute ที่เรา Map ไว้
โดยที่คลาสเราก็ map ไว้กับชื่อตาราง ส่วน property ก็ map เข้ากับ ชื่อ Field พอจังหวะสั่ง save ก็ทำการ
Gen SQL มันจากพวก attribute ที่ map เอาไว้นั่นแหละ แล้วก็เอาค่าจาก property นั้นๆ ยัดใส่ parameter
แล้วสั่ง save ครับ ต่างจากข้างบนตรงที่ผมสามารถเขียน method Save() ไว้ที่ Parent Class ที่เดียว ส่วน
Child Class ที่ทำการ inherit ไปก็จะได้รับความสามารถอันนี้ไป ก็สามารถสั่งเซฟได้โดยไม่ต้องเขียนอะไรใหม่เลยครับ

ผมได้ไอเดียมาจากการทำ O/R Mapping อะครับ ลองไปหาศึกษาดูน่าจะเข้าใจความต้องการของผมนะ

#8 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 11 October 2007 - 06:15:35 PM

ปล. ตอนนี้ผมเขียนสำหรับติดต่อ SQLServer อย่างเดียว ส่วนถ้าจะให้ติดต่อ DB เจ้าอื่นได้ด้วยคงต้องเขียนเป็นลักษณะของ Factory Design Pattern อะครับ แต่ว่าหลักการใช้ได้เหมือนกันในทุกๆเจ้า เพียงแค่เปลี่ยน object connectoin,command ,........ เท่านั้นเอง

#9 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 11 October 2007 - 06:24:06 PM

ในส่วนการสร้าง property attribute นั้นจะไม่อธิบายมากนะครับ เพราะ
ส่วนใหญ่จะเหมือน ObjectAttribute ครับ


using System;
using System.Data;
using System.Data.SqlTypes;

namespace Sabina.Framework.Persistent
{
    [AttributeUsage(AttributeTargets.Property)]
    public sealed class PersistentPropertyAttribute : Attribute
    {
        private string _FieldName = "";
        private SqlDbType _DataType = SqlDbType.NVarChar;
        private int _Size = 0;
        private byte _Precision = 0;
        private byte _Scale = 0;
        private bool _AllowNull = true;
        private bool _IsKey = false;

        public PersistentPropertyAttribute(string FieldName, SqlDbType DataType, int Size, bool AllowNull, bool IsKey)
        {
            if (_IsKey && _AllowNull)
            {
                throw new Exception("Primary Key not allows NULL value.");
            }
            _FieldName = FieldName;
            _DataType = DataType;
            _Size = Size;
            _AllowNull = AllowNull;
            _IsKey = IsKey;
        }

        public PersistentPropertyAttribute(string FieldName, SqlDbType DataType, byte Precision, byte Scale, bool AllowNull, bool IsKey)
        {
            if (_IsKey && _AllowNull)
            {
                throw new Exception("Primary Key not allows NULL value.");
            }
            if (DataType != SqlDbType.Decimal)
            {
                throw new SqlTypeException("DataType mismatch.");
            }
            _FieldName = FieldName;
            _DataType = DataType;
            _Precision = Precision;
            _Scale = Scale;
            _AllowNull = AllowNull;
            _IsKey = IsKey;
        }

        public PersistentPropertyAttribute(string FieldName, SqlDbType DataType, int Size)
            : this(FieldName, DataType, Size, true, false)
        {
        }

        public PersistentPropertyAttribute(string FieldName, SqlDbType DataType, byte Precision, byte Scale)
            : this(FieldName, DataType, Precision, Scale,true,false)
        {
        }

        public string FieldName
        {
            get { return _FieldName; }
            set { _FieldName = value; }
        }

        public SqlDbType DataType
        {
            get { return _DataType; }
            set { _DataType = value; }
        }

        public int Size
        {
            get { return _Size; }
            set { _Size = value; }
        }

        public byte Precision
        {
            get { return _Precision; }
            set { _Precision = value; }
        }

        public byte Scale
        {
            get { return _Scale; }
            set { _Scale = value; }
        }

        public bool AllowNull
        {
            get { return _AllowNull; }
            set { _AllowNull = value; }
        }

        public bool IsKey
        {
            get { return _IsKey; }
            set { _IsKey = value; }
        }


    }
}


ซึ่ง property ของคลาสนี้ก็จะมี FieldName,ขนาด,ชนิดข้อมูล แล้วก็ที่สำคัญคือบอกว่า
Property นี้เป็นคีย์หรือไม่?

เพราะถ้า property ไหนถูก set ว่าเป็นคีย์ล่ะก็ เวลา Gen Update กับ Delete Statement
นั้นผมจะเอาชื่อ field ใน property นั้นๆไปใส่ในเงื่อนไข WHERE ครับ เพราะเราถือว่ามันเป็นคีย์หลักไงครับ

ส่วนพวก AllowNull และขนาด กับชนิดข้อมูลยังไม่ได้คิดเลยว่าจะเอาที่ map มาใช้ยังไง แต่ก็เขียนๆเอาไว้ก่อน
เพราะ framework นี้คงต้องพัฒนากันอีกยาวกว่าจะ complete ครับ

#10 X CroSs

X CroSs

    Truebot Co-Developer

  • Root Administrator
  • 102427 โพสต์
  • Gender:Male

โพสต์เมื่อ 12 October 2007 - 01:34:42 AM

มีประโยชน์มากๆนะเนี่ย ... ถ้าพัฒนาไว้เสร็จคงได้หยิบมาใช้ง่ายขึ้นเยอะมาก
เด๋วจะลองพัฒนาดูบ้าง เผื่อไว้ใช้ทำโปรเจค ^^

มีคำถามที่ไม่เกี่ยวกับข้างบนอยู่นิดหน่อยครับ
อย่างแรก - นิยามของคำว่า framework คืออะไร หรอครับ ?

อย่างที่สอง

กรณีแรก
    public sealed class PersistentPropertyAttribute : Attribute
    {
        private bool _IsKey = false;

        public bool IsKey
        {
            get { return _IsKey; }
            set { _IsKey = value; }
        }
    }


กรณีที่สอง
    public sealed class PersistentPropertyAttribute : Attribute
    {
        public bool _IsKey = false;
    }


เกี่ยวกะ encapsulation ในกรณีแรกนี่ เราจะเขียนแบบที่สองแทนเลยได้มั้ย ?
ในกรณีที่เรารู้ว่า var นี้ไม่มีการ check อะไร แน่นอน คือ เขียนแบบ get > return , set > = แน่ๆ
อาจจะไม่ถูกต้องตาม OOD แต่ มันน่าจะทำให้ ประหยัดทรัพยากรณ์ขึ้นนิดหน่อย (รึเปล่า?)

อันนี้ผมคาใจมานานละงับ บางทีผมเขียน class ขึ้นมา แล้วมีตัวแปรที่ยินยอมให้ user เข้าถึงได้อย่างอิสระ
คือไม่มีการ verify range/type อะไรงี้ ผมก้อใช้ public มันซะเลย

ที่ผมไม่รู้คือ ต่อไปมันจะมีผลกระทบอะไรรึเปล่า ? แล้วมันมีข้อเสียอะไรบ้าง นอกจาก ผิดหลักของ OOD ??

ts.gif

manutd18wm.png


#11 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 12 October 2007 - 07:53:07 AM

(X CroSs @ Oct 12 2007, 01:34 AM) ดูโพสต์

มีประโยชน์มากๆนะเนี่ย ... ถ้าพัฒนาไว้เสร็จคงได้หยิบมาใช้ง่ายขึ้นเยอะมาก
เด๋วจะลองพัฒนาดูบ้าง เผื่อไว้ใช้ทำโปรเจค ^^

มีคำถามที่ไม่เกี่ยวกับข้างบนอยู่นิดหน่อยครับ
อย่างแรก - นิยามของคำว่า framework คืออะไร หรอครับ ?

อย่างที่สอง

กรณีแรก
    public sealed class PersistentPropertyAttribute : Attribute
    {
        private bool _IsKey = false;

        public bool IsKey
        {
            get { return _IsKey; }
            set { _IsKey = value; }
        }
    }


กรณีที่สอง
    public sealed class PersistentPropertyAttribute : Attribute
    {
        public bool _IsKey = false;
    }


เกี่ยวกะ encapsulation ในกรณีแรกนี่ เราจะเขียนแบบที่สองแทนเลยได้มั้ย ?
ในกรณีที่เรารู้ว่า var นี้ไม่มีการ check อะไร แน่นอน คือ เขียนแบบ get > return , set > = แน่ๆ
อาจจะไม่ถูกต้องตาม OOD แต่ มันน่าจะทำให้ ประหยัดทรัพยากรณ์ขึ้นนิดหน่อย (รึเปล่า?)

อันนี้ผมคาใจมานานละงับ บางทีผมเขียน class ขึ้นมา แล้วมีตัวแปรที่ยินยอมให้ user เข้าถึงได้อย่างอิสระ
คือไม่มีการ verify range/type อะไรงี้ ผมก้อใช้ public มันซะเลย

ที่ผมไม่รู้คือ ต่อไปมันจะมีผลกระทบอะไรรึเปล่า ? แล้วมันมีข้อเสียอะไรบ้าง นอกจาก ผิดหลักของ OOD ??


ความหมายของ framework ในภาษาไทยก็คือแผนแม่บท ซึ่งคือสิ่งที่เราเคยทำอะไรอยู่เป็นประจำ
เราก็มากำหนดวิธีการที่ชัดเจน และถือเป็นระเบียบปฏิบัติอะครับ ในความหมายของผมก็คือ สิ่งที่ผมต้องเขียน
ทุกครั้งที่พัฒนาระบบผมก็จับมันมารวมๆกันไว้ซะ แล้วเวลาจะสั่งผมก็อาจจะยุบ 5-6 method ไว้ในส่วนของ private
โดยที่ programmer ไม่ต้องรู้ว่าทำอะไรบ้าง รู้แค่ว่าสั่ง method นี้แล้วทำงานได้ ลักษณะเหมือน .NET Framework
แหละครับ ที่จัดหมวดหมู่และรวบรวมคำสั่งที่เมื่อก่อนต้องเขียนแบบยาวเหยียด ให้เหลือเพียงวไม่กี่คำสั่ง
เพราะว่ามันมีหลายคำสั่งที่ไปทำอยู่เบื้องหลัง


ส่วนที่ว่าตัวแปรภายในสามารถประกาศ public ได้มั้ย ตามความรู้ OOP เท่าหางอึ่งของผม ก็คงตอบว่าถ้าจะ
ทำก็ทำได้ แต่มันคงผิดหลักการเรื่องของ encapsulation เพราะหลักการนี้ระบุว่าจะต้องไม่มีคลาสใดๆ สามารถ
เข้าดึงส่วนของ data ของคลาสอื่นๆได้โดยตรง ถ้าสามารถเข้าถึงได้จะต้องเข้าถึงผ่านทาง Interface(property)
เท่านั้น เพราะไม่เช่นนั้นมันก็เหมือนกับ structure programming ที่ประกาศ global var อะครับ แต่เปลี่ยนที่มาอยู่ใน
คลาสเท่านั้นเอง สรุปในความคิดผมก็คือมันไม่ควรทำอะครับ ที่ถามว่ามีอะไรที่เป็นข้อเสียอีกบ้างก็คือในเมื่อมันอิสระ
user สามารถเข้าถึงได้โดยตรง อาจจะทำให้คลาสทำงานผิดพลาดได้


#12 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 18 October 2007 - 08:10:44 AM

ในการ map attribute ให้กับ class หรือ property etc..... นั้นสามารถ map ได้มากกว่า 1 attribute นะครับ
โดยที่จะประกาศแบบนี้

CODE

[AttributeOne(ParamOne)]
[AttributeTwo(ParamTwo,ParamThree)]
public class TestAttribute
{
}


หรือประกาศแบบนี้ก็ได้
CODE

[AttributeOne(ParamOne),AttributeTwo(ParamTwo,ParamThree)]
public class TestAttribute
{
}


และอีกสิ่งนึงที่ผมเพิ่งได้รู้มาเมื่อ 2-3 วันที่ผ่านมานี้ก็คือคำว่า "Named Parameter"
ตอนแรกไม่เข้าใจว่าคืออะไร แต่พอลองเข้าไปหาใน MSDN ก็พบว่าจริงแล้วมันก็คือ
property ของ class Attribute ที่กำหนดให้ทั้ง get และ set ได้นั่นเอง ซึ่งตัว Named Parameter
นั้นเราจะเอาไว้ใช้กับตัวแปรที่ไม่จำเป็นในการสร้าง Attribute ของเรานั่นเอง เหมือนเป็นตัว
Optional ที่ไม่ต้องประกาศ attribute ของเราก็ยังทำงานได้ครับ

ตัวอย่างนะครับ

CODE

namespace Sabina.Framework.Persistent
{
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,AllowMultiple=false,Inherited = true)]
    public sealed class PrimaryKeyAttribute : Attribute
    {
        private bool _Identity = false;

        public bool IsKey
        {
            get { return true; }
        }

        public bool Identity
        {
            get { return _Identity; }
            set { _Identity = value; }
        }
    }
}

ในตัวอย่างผมประกาศตัวแปรไว้1 ตัวชื่อ _Identity เป็น boolean แล้วก็มี property ขื่อ
Identity แต่ไม่มีประกาศ constructor นั่นหมายถึงให้ใช้ default constructor และ
ประกาศ property แบบ readonly มาอีกตัวนึง นั่นหมายถึง property Identity นั้นก็คือ
Named PArameter นั่นเองครับ

เวลาประกาศใช้งานก็ประกาศแบบนี้
CODE

       [PrimaryKey(Identity=false)]
        public string ProductID
        {
            get { return _productID; }
            set { _productID = value; }
        }


ข้อสังเกตที่ 1 ครับ Class ที่ผมเขียนคือ "PrimaryKeyAttribute" แต่ผมสามารถประกาศแค่ "PrimaryKey" ได้ครับ
อันนี้ทางตัว IDE จะตัดเอาคำว่า "Attribute" ออกไป แต่ก็สามารถประกาศแบบเต็มได้นะครับ

ข้อสังเกตที่ 2 การกำหนดค่าให้ named parameter ต้องประกาศชื่อของมันก่อนแล้วตามด้วย = ครับ
(ตัว intellisense จะ list ขึ้นมาหใองนะครับ)

P.S. ผมทดสอบแต่กับ C# นะครับ ส่วน VB 2005 ไม่แน่ใจว่าได้ผลเหมือนกัน หรือประกาศแบบเดียวกัน
ได้หรือเปล่า เพราะ 2 ตัวนี้มีรูปแบบการเขียนไม่เหมือนกัน

ช่วงนี้งานโปรแกรมเร่ง อาจจะไม่ได้เข้ามาโพสอย่างต่อเนื่อง แต่จะพยายามเข้ามาโพสให้ได้ทุกวันนะครับ
(เห็นใจคนรออ่าน...จะมีใครอ่านบ้างมั้ยน้อ เพราะคนที่เข้ามาบอร์ดนี้ส่วนใหญ่ก็จะมาหาข้อมูลบอทซะส่วนใหญ่ 55)

#13 KoRnRoom99

KoRnRoom99

    Exclusive Member

  • Exclusive Programmer
  • 10104 โพสต์

โพสต์เมื่อ 10 November 2007 - 12:54:18 AM

ขี้เกียจอ่าน มิมิ ตอนนี้เป็น Javaian เต็มตัว *0*
IPB Image
IPB Image
Works: KoRnBot Project,TSLoadDatFile
Thanks X CroSs, Truebot, TSBot, Solars, JackY, some1, Storm24, AssertionFailed from www.skjune.com
IPB ImageIPB ImageIPB ImageIPB ImageIPB ImageIPB Image

#14 JackY

JackY

    หนี Microsoft ไม่พ้นซักทีเรา

  • Exclusive Programmer
  • 10072 โพสต์
  • Location:ซอกเล็กๆในหัวใจเธอ

โพสต์เมื่อ 10 November 2007 - 10:28:56 PM

ช่วงนี้ต้องเร่งปั่นโปรแกรมให้เสร็จภายใน 2 อาทิตย์ครับ เลยไม่ได้มีเวลามาโพสต่อ ต้องขอโทษ
ทุกท่านที่รออ่านต่อนะครับ

แล้วลลองเข้าไปดูที่นี่นะครับ

โปรแกรมใครๆในบอร์ดนี้ไปอยู่ในเวบนี้บ้างเอ่ย

http://forum.gamevn....ad.php?t=250706

ของผมเองก็มีกะเค้าด้วยแฮะ

#15 KoRnRoom99

KoRnRoom99

    Exclusive Member

  • Exclusive Programmer
  • 10104 โพสต์

โพสต์เมื่อ 16 November 2007 - 09:57:04 AM

TSLoadDatFile ดังกว่า KoRnBot อีกแหะ
IPB Image
IPB Image
Works: KoRnBot Project,TSLoadDatFile
Thanks X CroSs, Truebot, TSBot, Solars, JackY, some1, Storm24, AssertionFailed from www.skjune.com
IPB ImageIPB ImageIPB ImageIPB ImageIPB ImageIPB Image

#16 KoRnRoom99

KoRnRoom99

    Exclusive Member

  • Exclusive Programmer
  • 10104 โพสต์

โพสต์เมื่อ 29 November 2007 - 04:17:00 PM

นั่งอ่านอยู่ 3 - 4 เที่ยวพอจะ get idea แล้วแหะ ถ้าเสร็จแล้วเอาโค้ดมาให้ดูมั่งน๊า
(กำลังเทียบอยู่ว่ามันจะคล้ายกับอะไรใน Java ก็คงจะคล้ายกับ EJB ใน Java แหล่ะมั๊ง *0* มั่ว แหะๆ)
IPB Image
IPB Image
Works: KoRnBot Project,TSLoadDatFile
Thanks X CroSs, Truebot, TSBot, Solars, JackY, some1, Storm24, AssertionFailed from www.skjune.com
IPB ImageIPB ImageIPB ImageIPB ImageIPB ImageIPB Image

#17 cfx_9850gb

cfx_9850gb

    ทหารศึกดาบแยก

  • Members
  • 15 โพสต์

โพสต์เมื่อ 11 December 2007 - 03:01:20 PM

ยังไม่ถึงขั้นนี้คับ ตอนนี้รู้แต่เลือกใช้ method ที่เค้าให้มา ให้เปนก็พอ
ส่วนใน method เปนไงไม่รู้ อิอิ ตึ๊บเลยตู ไว้จะกลับมาอ่านอีกทีคับเผื่อจะเข้าใจ

หมายเหตุ สอนเจาะ X-trap ให้ผมก่อง แงๆ C# คับ




0 สมาชิกกำลังอ่านกระทู้นี้

0 สมาชิก, 0 ผู้เยี่ยมชม, 0 ผู้ใช้งานที่ซ่อนตัว