الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

المرحلة الثانية : تطوير وحدة i/o - الملفات .

بدأه فريق الأندلس في 11 أكتوبر 2009 · 35 رد · 4,539 مشاهدة · في قسم برمجة الألعاب و الرسوميات العام
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه ،،

- المرحلة الأولى : تطوير وحدة ( حزمة) I/O.

- الهدف : تطوير أصناف Classes مسؤولة عن القراءة والكتابة من و إلى مستودع بيانات ( ملفات - الذاكرة .. الخ ) .

- أصناف ( Classes ) هذه المرحلة ومواصفات ( Specification ) كل صنف :

( تحت التطوير )

- خطوات التطوير:

(جميع اللغات البرمجية يتم مناقشتها في هذا الموضوع بما في ذلك الخطوة الثالثة و الرابعة)

  1. التحليل الأولي للموضوع :
    - نناقش فائدة هذه الحزمة core , وماهو الهدف منها .
    - هنا تبدأ تتضح معالم Classes و Interfaces و Enumerations التي سنحتاجها .. والعلاقات بين الكلاسات Classes .
  2. كتابة مواصفات Specification للأصناف Classes التي سيستخدمها المستخدم النهائي :
    نختار جزء معيّن من الأصناف والواجهات Classes - Interfaces ، التي ستظهر للمستخدم النهائي , ونكتب مواصفاتها بالتفصيل , بحيث يمكن لأي مطوّر دعم هذه الأصناف والواجهات في أي لغة برمجية يريد ، مثال ( يجب اتباع طريقة كتابة المواصفات قدر الامكان ) :


    // Interface that read an image from specific file into ImageBuffer
    ImageReader <interface>
    {
    /// @Purpose : load an image from specific file and create new object of ImageBuffer
    /// that holds image info .
    /// @Parameters:
    /// - fileName : image file name ( full path ) .
    /// @return :
    /// on success :new ImageBuffer object holds image info
    /// on failure : NULL;
    /// @Exceptions :
    /// FileNotFoundException if the image (fileName) does not exist .
    /// FileFormatNotSupportedException if the image format is not supported.
    [byRef] ImageBuffer read( [iN] string fileName) <pure>
    };


    مثال اخر :

    // Class used to hold an image information such as ( width - height - format - data)


    ImageBuffer<class>
    {
    // array of char that contains image data (colors).
    byte [ ] data
    // image width
    int width
    // image height
    int height
    // bits per pixel
    int bpp
    // @Purpose : check if the image has alpha channel
    // @return :
    // true : if the image has alpha channel
    // false : otherwise
    [byValue] bool isAlpha().
    };


    - لا يتم كتابة مواصفات الدوال Methods و الأعضاء Members الشائعة مثل Setters و Getters .. مثال : setText .

  3. مناقشة الخوارزميات والأفكار وكتابة الكود Implementation .
  4. اختبار الكود .

تم تعديل هذه المشاركة بواسطة فريق الأندلس في 11 أكتوبر 2009 في 10:28

#2

الخطوة الأولى : التحليل الأولي للموضوع :

هل لازال الحافز موجود :D ..

- أي محرك ألعاب يحتاج لآلية للقراءة من وإلى الملفات .

- رأيي في هذا الموضوع أن يكون العمل بسيط وسهل في المرحلة الأولى 0.1 ، بحيث نركز على الأمور الأساسية التي سنتحتاجها .

- سنحتاج للتالي :

  • القراءة والكتابة من و إلى الملفات الثنائية Binary ، مثل قراءة وكتابة 4 بايتات - Integer - أو قراءة عدد كسري - أو كتابة بت واحد .. الخ .
    FileReader
    FileWriter
  • القراءة والكتابة من و إلى الملفات النصية - قراءة وكتابة حرف - كلمة - سطر نصي كامل .. الخ .
    TextReader
    TextWriter
  • القراءة والكتابة من وإلى الذاكرة ، لأنها أسرع من الملفات ، في الغالب نستخدمها مع الملفات الثنائية ، حيث نقرأ الملف دفعة واحدة ، نضعه في الذاكرة ، نستخدم الكلاسات التالية للقراءة والكتابة ، فتكون العملية أسرع .
    MemoryReader
    MemoryWriter
    ByteBuffer أو MemoryBuffer .. أو أي تسمية مناسبة .
  • القراءة والكتابة من وإلى ملفات XML .
    XmlReader
    XmlWriter

طبعاً تسمية الكلاسات ممكن نغيّرها ، هي فقط مثال ، قد توجد تسميات أفضل ، ليست مشكلة ..

Classes Or Interfaces - فئات أو واجهات ؟

لا أعرف .. هل نستخدم كلاسات بسيطة ، أم واجهات ؟ اذا استخدمنا واجهات فانه يمكن لاحقا تطوير هذه الحزمة ، ويمكن أيضاً الاعتماد على مكتبات أقوى و APIs أقوى كالخاصة بنظام التشغيل .. وممكن نعملها كلاسات بسيطة .. فتكون أسرع ، لكن سنضطر كثيراًً إلى الغاء بعض الميزات خوفاً من مسألة التوافقية مع نظم التشغيل الاخرى ، خاصةً عندما نتعامل مع لغة السي بلس .

رأيي أن نستخدم واجهات Interfaces لتمثيل هذه الحزمة ، ما رأيكم ؟

العلاقات :

يمكن للبعض أن يمثل الكلاسات السابقة على شكل علاقات - وراثة مثلاً أو Polymorphism .. على حسب ..

مثل أن يضيف كلاس عام اسمه DataReader يكون أب لجميع الكلاسات التي تقوم بالقراءة .

ويضيف كلاس اسمه DataWriter .. ليكون أب لجميع الكلاسات التي تكتب .

لكن رأيي ، أن هذا سيجعلنا نتلافى كثير من الدوال Methods الخاصة .. ويحصل لدينا تعارضات .. مثلاً : قد يكون للكلاس FileReader دالّة باسم open وهي غير موجودة عند MemoryReader ، أيضا XML قد يختلف بشكل كبير عن بقية الكلاسات ..

لكن سمع كثيراً عن العلاقة بين القراءة من والى الملفات أو الشبكات ... لا أعرف بالظبط عن هذه المسألة التي قد تغير من أسلوب تصميم الحزمة .

المجلدات Folders :

لا أظن أنه من المفيد أن نضيف شيء مثل : فتح مجلد - البحث عن الملفات والمجلدات - عرض خصائص المجلد .. كل هذا لايفيدنا في برمجة الألعاب .. هذا رأيي .

الملفات المضغوطة :

لا أظن انه أمر مهم دعم الملفات المضغوطة الان ... يمكن تأجيلها لنسخ قادمة من المحرك .. حتى لا تكون عملية implementation معقّدة .

مارأيكم ؟

( نحن الان في الخطوة الأولى وهي : استنتاج الكلاسات والواجهات والعلاقات بينهما Relationships . )

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

من وجهة نظري

يقسم التعامل مع الملفات الى ثلاثة اقسام

1- التعامل مع الصور : لتحميل اكساء

2- التعامل مع الاصوات : لتحميل اصوات للعبة

3- التعامل مع الملفات الخاصة بالمحرك و هذا القسم يندرج تحته عده افكار مثلا

* ملف حزمة باكيج لوضع صور و اصوات كثيرة في ملف واحد

* ملف اعدادات للمحرك مثل دقة الشاشة و جهاز العرض و ما الى ذلك

* ملف المراحل Level لتعبئة مواقع مرحلة ما

اخيرا طريقة كتابة و قراءة لكتابة اي شي الى ملف سواء Text او Binary

طبعا كلاسات التعامل مع الملفات مثل ما ذكرت اخي الشمري يفضل ان تكون واجهات

#4

ينهار ابيض ده انا لسه شغال فى الفئه Triangle و Circle و المرحله التانيه بدءت، ده انا متأخر قوى :o .

بس طبعا ده مش هيمنع انى اشارك معاكم فى المرحله دى برضه :D .

اقترح استخدام واجهات بدلا من فئات لتسهيل تعميم الكود فيما بعد لانظمة التشغيل الأخرى.

بالنسبه للملفات اقترح عدم جعل واجهات للقراءه و اخرى للكتابه لإن هذا سيجعلنا نكرر بعض العمليات مثل فتح الملف او غلقه او حساب مساحته او معرفة موقع المؤشر او تغيير مكان المؤشر و هكذا.

و حيث ان جميع الفئات ستكون واجهات امام المستخدم فلابد من وجود الفئه File و التى من خلالها يستطيع فتح ملف داخل stream معينه.

الواجهات المقترحه :

1 - Stream : و هى الواجهه الرئيسيه و التى يتم وراثتها من باقى الواجهات، و السبب فى وجودها هو دعم فئات خاصه يقوم المستخدم بعملها ليتم استخدامها مع دوال قمنا بتصميمها داخل المحرك.

1 - BinaryStream : تقوم بالكتابه و القراءه من ملف على مستوى البايت.

2 - TextStream : تقوم بكتابة و قراءة النصوص من الملفات.

3 - MemoryStream : و هى Buffer داخل الذاكره بمساحه معينه يحددها مستخدمها.

4 - XMLStream : تقوم بالقراءة و الكتابه من ملفات بصيغة XML. (هذه الفئه ستجعلنا نقوم بعمل مجموعه كبيره اخرى من الفئات الخاصه بـ XML حيث ان المستخدم لن يتعامل مع هذه الفئه بنصوص عاديه).

لا داعى من دعم فئات للمجلدات فمحركات الألعاب تتعامل مع ملفات و ليس مجلدات (طبعا هى تتعامل مع مجلدات من نوع خاص داخل نظام الملفات الذى يتم بنائه داخل ملف واحد).

لو تكلمنا عن ضعط الملفات سنحتاج ايضا للتكلم عن تشفيرها :D، طبعا الأمر خارج عن نطاق المحرك بالنسبه لهذه المرحله اما فى المراحل الأخرى و عند اضافة دعم المكتبات الخارجيه يمكن وقتها التكلم فى هذه النقطه.

بالنسبه لملفات الصوت و ملفات الصور فهى مجرد ملفات ثنائية يتم التعامل معها على مستوى البايت، لذا يمكن اضافتهم لاحقا ولكن بعد انتهاء العمل فى الفئات الأساسيه.

بالنسبه لأنظمة الملفات التى تكلم عنها الأخ الكون فأعتقد ان المحرك لا حاجة له بها فكل مبرمج يقوم بصناعة نظام ملفات خاص به و بوجد فئات التعامل مع الملفات السابق ذكرها يمكن بناء أى نظام ملفات نريده. بالنسبه للمحرك فهو يتعامل مع ملفات مجرده مثل ملفات wav او tga و هكذا و إذا اراد مبرمج ان يدعم نوع اخر فكما قلنا لديه الفئات الأساسيه يمكنه وراثة الفئه stream او الفئه BinaryStream للقراءه من و الى نوع الملف الذى يحتاجه.

بالنسبه لشكل الفئات السابق ذكرها فهو كالتالى

الواجهه Stream

 

[color= #0000ff;]class OperationNotSupported

[color= #000000;]{

	...

	...

[color= #000000;]};

 

[color= #0000ff;]enum SeekOption

[color= #000000;]{

	Begin,

	Current,

	End

[color= #000000;]};

 

interface IStream

[color= #000000;]{

	[color= #007f00;]// is stream allow reading

	[color= #0000ff;]virtual [color= #0000ff;]bool getCanRead[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// is stream allow writing

	[color= #0000ff;]virtual [color= #0000ff;]bool getCanWrite[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// is stream allow seeking

	[color= #0000ff;]virtual [color= #0000ff;]bool getCanSeek[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// get stream length

	[color= #0000ff;]virtual uint64 getSize[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// get/set current cursor position in stream

	[color= #007f00;]// from beginning of file

	[color= #0000ff;]virtual [color= #0000ff;]void   setPosition[color= #000000;](uint64 value[color= #000000;]) pure;

	[color= #0000ff;]virtual uint64 getPosition[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read count of bytes from stream from offset

	[color= #0000ff;]virtual ubyte[color= #000000;][[color= #000000;]] read[color= #000000;](uint64 offset, int32 count[color= #000000;]) pure;

 

	[color= #007f00;]// write bytes to stream

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](ubyte[color= #000000;][[color= #000000;]] value, uint64 offset, int32 count[color= #000000;]) pure;

 

	[color= #007f00;]// flush data without closing stream

	[color= #0000ff;]virtual [color= #0000ff;]void flush[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// put curent stream cursor in new position

	[color= #0000ff;]virtual [color= #0000ff;]void seek[color= #000000;](uint64 offset, SeekOption option[color= #000000;]) pure;

 

	[color= #007f00;]// free current stream resources and close it

	[color= #0000ff;]void close[color= #000000;]([color= #000000;]);

[color= #000000;]};

اعتذر لأخى الشمرى على وجود الدوال الـ set و الـ get حيث ان وجودهم اساسى داخل الواجهه الرئيسيه.

الواجهه IStream هى وصف عام لباقى الواجهات و تحتوى على العمليات التى تستطيع الفئات الأخرى ان تقوم بها او لا تقوم بها حيث تحتوى على الدوال CanRead و CanWrite و CanSeek و التى تحدد امكانيات الـ stream التى نتعامل معها و فى حالة استدعاء داله مثل seek و كانت الـ stream لا تجعم التحرك داخلها فيم رمى استثناء OperationNotSupported لتعريف مستخدم الـ stream انه استخدم داله غير متاحه لهذه للفئه التى يتعامل معها. باقى الدوال اعتقد انها واضحه.

نقطه اخرى سبب تسميتى للواجهه IStream بهذا الشكل هو اننا داخل الكود سنقوم بعمل الفئه Stream و بالتالى إذا كان اسم الواجهه بدون I فلابد من تغيير اسم الفئه الموجود داخل الكود.

الفئه BinaryStream

 

interface IBinaryStream [color= #000000;]: [color= #0000ff;]public IStream

[color= #000000;]{

	[color= #007f00;]// IStream methods goes here.

 

	[color= #007f00;]// read signed byte

	[color= #0000ff;]virtual byte read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read unsigned byte

	[color= #0000ff;]virtual ubyte read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read ascii char

	[color= #0000ff;]virtual achar read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read unicode char

	[color= #0000ff;]virtual uchar read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read boolean

	[color= #0000ff;]virtual [color= #0000ff;]bool read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read signed 16bit integer

	[color= #0000ff;]virtual int16 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read unsigned 16bit integer

	[color= #0000ff;]virtual uint16 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read signed 32bit integer

	[color= #0000ff;]virtual int32 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read unsigned 32bit integer

	[color= #0000ff;]virtual uint32 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read signed 64bit integer

	[color= #0000ff;]virtual int64 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read unsigned 64bit integer

	[color= #0000ff;]virtual uint64 read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read float-point number

	[color= #0000ff;]virtual [color= #0000ff;]float read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read double float-point number

	[color= #0000ff;]virtual [color= #0000ff;]double read[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read count of bytes

	[color= #007f00;]// IMemoryStream is instead of void*

	[color= #0000ff;]virtual IMemoryStream read[color= #000000;](count[color= #000000;]) pure;

 

	[color= #007f00;]// read object from current position	

	[color= #0000ff;]template [color= #000000;]<[color= #0000ff;]typename T[color= #000000;]>

	[color= #0000ff;]virtual T[color= #000000;]* read[color= #000000;]([color= #000000;]) pure;

 

 

	[color= #007f00;]// write signed byte

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](byte value[color= #000000;]) pure;

 

	[color= #007f00;]// write unsigned byte

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](ubyte value[color= #000000;]) pure;

 

	[color= #007f00;]// write ascii char

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](achar value[color= #000000;]) pure;

 

	[color= #007f00;]// write unicode char

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](uchar value[color= #000000;]) pure;

 

	[color= #007f00;]// write boolean

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;]([color= #0000ff;]bool value[color= #000000;]) pure;

 

	[color= #007f00;]// write signed 16bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](int16 value[color= #000000;]) pure;

 

	[color= #007f00;]// write unsigned 16bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](uint16 value[color= #000000;]) pure;

 

	[color= #007f00;]// write signed 32bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](int32 value[color= #000000;]) pure;

 

	[color= #007f00;]// write unsigned 32bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](uint32 value[color= #000000;]) pure;

 

	[color= #007f00;]// write signed 64bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](int64 value[color= #000000;]) pure;

 

	[color= #007f00;]// write unsigned 64bit integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](uint64 value[color= #000000;]) pure;

 

	[color= #007f00;]// write float integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;]([color= #0000ff;]float value[color= #000000;]) pure;

 

	[color= #007f00;]// write double integer

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;]([color= #0000ff;]double value[color= #000000;]) pure;

 

	[color= #007f00;]// write IMemoryStream content to current file

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](IMemoryStream value[color= #000000;]) pure;

 

	[color= #007f00;]// write object from current position

	[color= #0000ff;]template [color= #000000;]<[color= #0000ff;]typename T[color= #000000;]>

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](T[color= #000000;]* value[color= #000000;]) pure;

[color= #000000;]};

تحتوى هذه الواجهه على كل ما تحتاجه للتعامل مع الملفات على مستوى البايت فهى تستطيع قراءة و كتابة كل انواع اللغه الإفتراضيه بجانب قراءة قطع كامله من الملف داخل IMemoryStream كذلك تتيح لك قراءة و كتابة انواع خاصه بك (classes او struct او union كما تريد).

الواجهه TextStream

 

interface ITextStream [color= #000000;]: [color= #0000ff;]public IStream

[color= #000000;]{

	[color= #007f00;]// IStream members goes here

 

	[color= #007f00;]// read complete line

	[color= #0000ff;]virtual string readLine[color= #000000;]([color= #000000;]) pure;

 

	[color= #007f00;]// read some chars

	[color= #0000ff;]virtual string read[color= #000000;](uint32 count[color= #000000;]) pure;

	[color= #0000ff;]virtual achar  read[color= #000000;]([color= #000000;]) pure;

 

	[color= #0000ff;]virtual [color= #0000ff;]void writeLine[color= #000000;](string value[color= #000000;]) pure;

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](string count[color= #000000;]) pure;

	[color= #0000ff;]virtual [color= #0000ff;]void write[color= #000000;](achar value[color= #000000;]) pure;

[color= #000000;]};

لقد اقتصدت فى دوال هذه الواجهه حيث انه يمكن وضع الكثير بها و لكن كلما كثرت الدوال كلما زادت تعقيدا ايضا جعلتها تتعامل مع نصوص ascii فقط فى القراءة و الكتابه.

الواجهه IMemoryStream

 

interface IMemoryStream [color= #000000;]: [color= #0000ff;]public IStream

[color= #000000;]{

	[color= #007f00;]// IStream members goes here

 

	[color= #007f00;]// write current data to stream

	[color= #0000ff;]virtual [color= #0000ff;]void toStream[color= #000000;](IStream stream[color= #000000;]) pure;

 

	[color= #007f00;]// return current stream as array of bytes

	[color= #0000ff;]virtual byte[color= #000000;]* toArray[color= #000000;](int32[color= #000000;]& size[color= #000000;]) pure;

[color= #000000;]};

بالنسبه للواجهه XMLStream لا اعرف كيف سيكون شكلها، و ارجع تركها للإصدار القادم (من الممكن استخدام المكتبه tinyXML).

طبعا كما تلاحظ هذه الواجهات لا تحتوى على مشيد و ذلك لإنهم واجهات لذا سنصنع فئه رئيسيه تحتوى على مجموعه من الدوال تماثل فى عدد معاملاتها عدد المشيدات الموجوده بالفئات الخاصه بكل واجهه و من خلال هذه الدوال نستطيع انشاء نسخه من هذه الواجهات.

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 11 أكتوبر 2009 في 16:24

مدونتي: C++ Tips and Tricks

#5

رائع :) .

اقتباس
من وجهة نظري

يقسم التعامل مع الملفات الى ثلاثة اقسام

1- التعامل مع الصور : لتحميل اكساء

2- التعامل مع الاصوات : لتحميل اصوات للعبة

3- التعامل مع الملفات الخاصة بالمحرك و هذا القسم يندرج تحته عده افكار مثلا

* ملف حزمة باكيج لوضع صور و اصوات كثيرة في ملف واحد

* ملف اعدادات للمحرك مثل دقة الشاشة و جهاز العرض و ما الى ذلك

* ملف المراحل Level لتعبئة مواقع مرحلة ما

اخيرا طريقة كتابة و قراءة لكتابة اي شي الى ملف سواء Text او Binary

طبعا كلاسات التعامل مع الملفات مثل ما ذكرت اخي الشمري يفضل ان تكون واجهات

رأيي من رأي الأخ محمد وهي أن كل هذه الملفات هي ملفات ثنائية لذلك لو بدأنا ببناء قاعدة أساسية للملفات يمكننا بعدها استخدامها لقراءة صورة أو صوت .. لذلك سيأتي الحديث عن قراءة الصور .. والتي ستكون مبنية على كلاسات هذه المرحلة .

موضوع الباكيج ، هو الذي قصدت به ملفات zip ، أغلب المحركات تعتمد على الملفات المضغوطة ، لتطوير ما تفضلت به .

لكن المشكلة أن الفكرة قد تكون صعبة التنفيد .. لذلك التردد موجود .

في محرك irrlicht مثلا ، يدعم هذه الخاصية وهي جميلة .. وبأسلوب سلس .. لكن قد تحتاج لوقت لانجازها ..

أما أن تكون كلاسات الملفات هي واجهات فهو مقنع كثيراً .. لذلك سأحسم موقفي واؤيّد ذلك :-) .

@ الاخ محمد :

اقتباس
ينهار ابيض ده انا لسه شغال فى الفئه Triangle و Circle و المرحله التانيه بدءت، ده انا متأخر قوى

يمكن أن نعمل على جبهتين :-) .. لامانع .

الاقتراحات التي تفضلت بها :

@ نستخدم واجهات : موافق .

@ فئة واحدة للقراءة والكتابة : متردد قليلاً .. لكن أستطيع أن أقول موافق أيضاً .

@ الفئة File : ( هي هي فئة أو واجهة - ما فائدته ، لاتكتب كود .. فقط تعريف لفائدتها .. أظن أنها لن تحوي الا على اسم الملف المراد فتحه صحيح ؟ اذا كان كذلك يمكن أن نستخدم string عادي ، ما رأيكم ؟ ) .

@ بالمناسبة ، الان في الخطوة الأولى :D .. يعني لم يحن الدور بعد على النظر إلى محتوى كل واجهة .. المهم الان استخلاص الكلاسات والواجهات وطريقة عمل كل منها وفي الخطوة التالية سنناقش الدوال التي نحتاج ، تسمية الواجهات والكلاسات التي سيستخدم المبرمج النهائي لايجب أن تحوي على بادئة :) .. أعرف أنك وضعتها لهدف .. لكن يمكن أن نغير اسم الكلاس الداخل للمحرك ونضع فيه بادئة مثل C أو اي اسم تراه مناسب .

@ اقتراحك بتأجيل XML إلى 0.2 .. اقتراح أجده رائع .. وأوافق عليه .. إلا اذا كان يوجد مبرمج أو أكثر سيدعم xml ويصمم الكلاسات ويبرمجها في الجافا و/أو السي بلس ، فيمكن ضمّها في هذه النسخة .. ما رأي الأخوان ؟

بالنسبة للقراءة من الذاكرة مثلاً .. هل نستخدم مصفوفة عادية من البايتات أم نصمم كلاس بحيث يكون أكثر أماناً من المصفوفة وأكثر تنظيم ، نسميه مثلا ByteBuffer أو MemoryBuffer .. أجد أن الكلاس ينقذنا من بعض المخاطر التي سنقع به ، ويسهل علينا كثير من الأمور الروتينية .

حسب ما اقترح الاخ الكون + محمد علاء و سأضيف كلاسين من عندي كاقتراح فقط .. ينتج التالي :

- File : لا أعرف فائدته بالظبط

- MemoryBuffer : اقتراح لتسهيل التعامل مع الذاكرة كبديل للمصفوفة العادية

+ Stream <interface>

- BinaryStream :

- TextStream :

- MemoryStream :

- Manager OR Factory :

هذا سيكون أحد الكلاسات الأساسية في المحرك .. لانشاء الكلاسات .. حيث أننا نتعامل مع واجهات لاتحوي على مشيّد

Constructor

بانتظار المزيد من التنقيحات والاقتراحات

تم تعديل هذه المشاركة بواسطة الشمري في 11 أكتوبر 2009 في 19:29

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#6

بالنظر إلى الكود الذي كتبه الأخ محمد، لا أعلم لماذا أحسست أن لدينا هنا حالة من نوع "إعادة إختراع العجلة"، فكل المزايا المكتوبة مدعومة من مكتبة ++C القياسية (fstream وأصدقاؤها)، بالنسبة لجافا فأعتقد إنها تمتلك مكتبة قياسية مشابهه أيضاً لعل من الأفضل أن نفكر على مستوى أعلى ونترك المستوى المنخفض للمكتبة الخاصة بكل لغة... إقتراح فقط.

على سبيل المثال ننشئ مكتبة لقراءة وكتابة ملفات ini كخطوة أولى يليها XML عند الحاجة، وجعل XML مثلاً الوسيلة الرئيسية لحفظ وإسترجاع المعلومات.

أي ببساطة نحاول التوصل لطريقة مبسطة تبعد مستخدم المحرك عن الحاجة للتلاعب بالبايتات والبتات لكي يكتب عدداً أو يقرأ نصّاً.

أتمنى أن يكون إقتراحي في محله...

:hmm:

تم تعديل هذه المشاركة بواسطة SandHawk في 11 أكتوبر 2009 في 19:37

#7

هو كلامك صحيح .. خاصة في الجافا .. حيث الهدف فقط توحيد واجهة المحرك ، لكن في السي بلس .. سنحتاج إلى قراءة Interger و float و short .. الخ ، لايوجد في المكتبة القياسية شيء كهذا بوضوح ، لذلك يمكن أن نغلفها حتى تكون واضحة وسهلة .. فبدلاً من أن يمتلئ المحرك بشيء كهذا :

fstream s ..
s.write((char*) integer,sizeof(int));

نكتب

Stream s ...
s.writeInt32( integer);

لذلك ، الفكرة هي بتغليف وتوحيد وتبسيط المكتبة القياسية .

ما علاقتها بالمستخدم النهائي ؟

قد لايكون الهدف هو المستخدم النهائي حيث أن المستخدم النهائي سيتعامل مع فئات أعلى مثل Image أو XmlStream .. الخ .

بل الهدف هو أن يستخدم هذه الفئات مطوّري المحرك ، لقراءة ملفات ini وغيرها .

اضافة الى التفكير بشيء أبعد مثل Bit order :D .. عن القراءة و الكتابة ..

ما رأيك ؟

ما أفكر فيه ، هو لحظات التطوير .. مبرمج في الجافا قام بكتابة الكلاس TgaImageReader .. باستخدام كلاسات معينة من كلاسات الجافا .. ومبرمج اخر قام بكتابة BmpImageReader بكلاسات أخرى ( كلاسات الجافا كثيرة وبعضها يقوم بما يقوم به الاخر ) .. لذلك هنا نقع في مسألة عدم توحيد أسلوب كتابة الكود .

اضافة /

أنا لدي الكود جاهز تقريبا .. لذلك يمكن أن نتحرك بسرعة هذه المرة :-) .. حيث كتبته في المحرك الذري .. وهو سهل تقريبا ..

لكن ماذا تقصد بعمل فئة للتعامل مع ملفات ini .. هل يمكن أن تحدثنا عن هذه الفئة ، ماهي أهدافها بالظبط واسم الكلاس .. وبماذا سنستخدمه .. فكرة الاستعانة بـ ini كبديل مؤقت لملفات xml اجدها جيدة :-) .

كالعادة .. أختم الردود " بهذا رأيي :D " .

تم تعديل هذه المشاركة بواسطة الشمري في 11 أكتوبر 2009 في 20:52

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#8
اقتباس
ا أعلم لماذا أحسست أن لدينا هنا حالة من نوع "إعادة إختراع العجلة"، فكل المزايا المكتوبة مدعومة من مكتبة ++C القياسية

كلامك سليم اخي سلون الكلاسات من وجهة نظري من المفترض ان تكو اعادة تغليف لكلاسات ++C

#9
اقتباس
@ فئة واحدة للقراءة والكتابة : متردد قليلاً .. لكن أستطيع أن أقول موافق أيضاً .

كما تلاحظ داخل الواجهه stream توجد الخصائص canSeek و canRead و canWrite و التى تيح تحديد نوع الـ stream نفسها و حيث ان كل فئات الملفات سيتم وراثتها من stream لذا ما الدوال المشتركه التى سيتم وضعها داخل stream إذا قمنا بصنع فئات للقراءه و فئات للكتابه ؟

اقتباس
@ الفئة File : ( هي هي فئة أو واجهة - ما فائدته ، لاتكتب كود .. فقط تعريف لفائدتها .. أظن أنها لن تحوي الا على اسم الملف المراد فتحه صحيح ؟ اذا كان كذلك يمكن أن نستخدم string عادي ، ما رأيكم ؟ ) .

الفئه File هى فئه تحتوى على static methods و كل ما تفعله هو انشاء نسخه من الفئات الموجوده بالـ implementation و شكلها سيكون كالتالى على سبيل المثال:

 

[color= #0000ff;]class File

[color= #000000;]{

[color= #0000ff;]public[color= #000000;]:

	[color= #0000ff;]static IBinaryStream openBinaryFile[color= #000000;](string filename[color= #000000;]);

	[color= #0000ff;]static IBinaryStream openBinaryFile[color= #000000;](string filename, AccessMode access[color= #000000;]);

	[color= #0000ff;]static IBinaryStream openBinaryFile[color= #000000;](string filename, AccessMode access, ShareMode share[color= #000000;]);

 

	[color= #0000ff;]static IMemoryStream getMemoryStream[color= #000000;](uint32 size[color= #000000;]);

	[color= #0000ff;]static IMemoryStream getMemoryStream[color= #000000;](uint32 size, [color= #0000ff;]bool canseek[color= #000000;]);

	[color= #0000ff;]static IMemoryStream getMemoryStream[color= #000000;](uint32 size, [color= #0000ff;]bool canseek, [color= #0000ff;]bool canread[color= #000000;]);

	[color= #0000ff;]static IMemoryStream getMemoryStream[color= #000000;](uint32 size, [color= #0000ff;]bool canseek, [color= #0000ff;]bool canread, [color= #0000ff;]bool canwrite[color= #000000;]);

 

	...

	...

	...

[color= #000000;]};
اقتباس
لا أعلم لماذا أحسست أن لدينا هنا حالة من نوع "إعادة إختراع العجلة"، فكل المزايا المكتوبة مدعومة من مكتبة ++C القياسية

القراءه و الكتابه من و إلى المفات هى امر هام جدا و لابد ان يتم بأقصى سرعه ممكنه و حيث ان دوال الـ API للتعامل مع الملفات اسرع من الموجوده فى fstream لذا فقد اقترحت تلك الفئات، ايضا نقطة اخرى و هى مساحة الملفات، حيث fstream على ما اعتقد لا تدعم الـ 64bit و بالتالى سنجد مشكله فى التعامل مع الملفات الثنائيه الأكبر من 4 جيجا.

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 11 أكتوبر 2009 في 21:34

مدونتي: C++ Tips and Tricks

#10

@ File : أعتقد أنه من الأفضل أن يكون هناك كلاس موحّد في المحرك اسمه مثلاً Manager مسؤول عن انشاء مثل هذه الكائنات ، وكائنات أخرى .. سنصادفها مستقبلاً ، نريد أن يكون هناك كلاس واحد من خلاله يمكن أن نصل لبقية الكلاسات بشكل مباشر أو غير مباشر .. وجود كلاس واحد بمثابة المدير أو المصنع للمحرك ، سيجعل الأمور أسهل .

اقتباس
و حيث ان دوال الـ API للتعامل مع الملفات اسرع من الموجوده

سنناقش ان شاء الله في مرحلة implementation هذه الأمور ، لكن هل تقصد أنك تنوي استخدام Win32 APIs .

اذا كان الجواب بنعم ، فانه يجب أن نعيد تصميم بعض الجزئيات بحيث يكون هناك نسخة للعمل مع fstream مثلا ، ونسخة لـ Win32 APIs - بالنسبة للغة السي بلس - ، طبعا يمكن دعم Win32 API و المكتبة القياسية في السي بلس بسهولة .

لكن شخصياً لا أرى أهمية في استخدام غير المكتبة القياسية - fstream - .. حيث أنها كافية بشكل كبير ، ولكن كما قلت ، يمكن دعمها دون تعارض مع الامور الاخرى ، لكن أخشى أن يأخذ وقت في implementation ..

هل تقترح استخدام Win32 API في الويندوز ؟

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#11
الشمري كتب:
لايوجد في المكتبة القياسية شيء كهذا بوضوح ، لذلك يمكن أن نغلفها حتى تكون واضحة وسهلة .. فبدلاً من أن يمتلئ المحرك بشيء كهذا :

fstream s ..
		 s.write((char*) integer,sizeof(int));

كنت أفكر أكثر بهذه الطريقة عندما ذكرت fstream والتي أعتقد إنها فعالة لدرجة ما:

	 ofstream outfile;...
	   ...
	   outfile << somefloat << someint << sometext;

الشمري كتب:
ما أفكر فيه ، هو لحظات التطوير .. مبرمج في الجافا قام بكتابة الكلاس TgaImageReader .. باستخدام كلاسات معينة من كلاسات الجافا .. ومبرمج اخر قام بكتابة BmpImageReader بكلاسات أخرى ( كلاسات الجافا كثيرة وبعضها يقوم بما يقوم به الاخر ) .. لذلك هنا نقع في مسألة عدم توحيد أسلوب كتابة الكود .

لا شك إن هنالك فوائد لتوحيد الدخول للملفات بالنسبة لنا.

الشمري كتب:
اضافة /

أنا لدي الكود جاهز تقريبا .. لذلك يمكن أن نتحرك بسرعة هذه المرة :-) .. حيث كتبته في المحرك الذري .. وهو سهل تقريبا ..

لكن ماذا تقصد بعمل فئة للتعامل مع ملفات ini .. هل يمكن أن تحدثنا عن هذه الفئة ، ماهي أهدافها بالظبط واسم الكلاس .. وبماذا سنستخدمه .. فكرة الاستعانة بـ ini كبديل مؤقت لملفات xml اجدها جيدة :-) .

ملف الـ ini هو نوع الملفات المعروف الذي تستخدمه البرامج عادة لحفظ الإعدادات ويسمى أيضاً initialization file، شكله يكون كالآتي:

  ; This is a comment
	   [SECTION]
	   NAME=VALUE
	 ...

يمكن أن يستخدم لحفظ أي شيء بسيط، وليس فقط الإعدادات، ميزته إن القراءة منه والكتابة له عملية بسيطة جداً، سأعود لأحد المحركات الذي أعجبني فيه البساطة الشديدة، وهو HGE، يقدم هذا المحرك واجهة بسيطة للتعامل مع ini تتألف من هذه الإجراءات فقط:

   Ini_SetInt	 Writes an integer value to initialization file.
	 Ini_GetInt	 Reads an integer value from initialization file.
	 Ini_SetFloat	 Writes a float value to initialization file.
	 Ini_GetFloat	 Reads a float value from initialization file.
	 Ini_SetString	 Writes a string to initialization file.
	 Ini_GetString	 Reads a string from initialization file.

وقد أرفقت لكم كود ملف cpp الذي يحتوي على هذه الإجراءات (المكتبة مفتوحة المصدر برخصة zlib)، مع ملاحظة أن الكود يستخدم إجراءات من Windows API مخصصة لملفات ini، وهي GetPrivateProfileString و WritePrivateProfileString.

في حالتنا يمكن مثلاً قراءة الملف بأكمله مرة واحدة ثم حفظ البيانات في صورة map بحيث يمكن إسترجاع أو تعديل أو إضافة أي قيمة ثم يمكن كتابة الـ map الجديدة إلى ملف ini. (إقتراح)

هههههه... نسيت إرفاق ملف الكود... جيد إني تذكرت. :blush:

ini.zip

تم تعديل هذه المشاركة بواسطة SandHawk في 11 أكتوبر 2009 في 23:33

#12

@ راجعت قليلا ما اقترحه الاخ محمد علاء ، لكن لا يمكن أن تكون TextStream ابن لـ Stream لاختلاف المهام .. حيث يوجد دوال في Stream لاعلاقة لها بالـ TextStream والعكس .

لذلك TextStream يجب أن تكون مستقلة .. هل الامور واضحة ؟

اقتباس
كنت أفكر أكثر بهذه الطريقة عندما ذكرت fstream والتي أعتقد إنها فعالة لدرجة ما:

أظن هذا ينفع مع Text و ليس Binary صح ؟ حيث لايمكن استعمال المعامل >> مع الملفات الثنائية ، حيث لايمكن نعمل overload لهذا المعامل أكثر من مرة .. مثلاً للـ int32 و int16 .. لن يعرف يتعامل معها المترجم .

عموما سنناقش كيفية بناء TextStream ليكون بجمال fstream :) .. في السي بلس ، أما الجافا فلامشكلة لديها .

أما ini ، فأصوّت مع اضافته اذا كنت ستكتب مواصفاته لنا :-) في الخطوة التالية بعد أن ننتهي مما نحن فيه ، لكن هل يمكن أن يعمل على linux بطريقة ما ؟ اي هل يمكننا الاستعاضة عن Win32 APIs ؟ وما مصير لغة الجافا ؟

تم تعديل هذه المشاركة بواسطة الشمري في 12 أكتوبر 2009 في 00:54

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#13
اقتباس
@ راجعت قليلا ما اقترحه الاخ محمد علاء ، لكن لا يمكن أن تكون TextStream ابن لـ Stream لاختلاف المهام .. حيث يوجد دوال في Stream لاعلاقة لها بالـ TextStream والعكس .

لذلك TextStream يجب أن تكون مستقلة .. هل الامور واضحة ؟

اخى لا يوجد اختلاف فى المهام حيث انك داخل الـ textstream ستحتاج للحصول على النصوص اولا على شكل مصفوفه من char و بعد تقوم بمعالجتها و إرجعها و كما تعلم ان الداله read الموجوده داخل stream تعود بمصفوفه من البايت التى يمكن تحويلها بسهوله إلى chars، نفس الكلام ينطبق على الحفظ حيث انك ستقوم بحفظ chars اى bytes و ليس string و بالتالى لا يوجد تعارض بين دوال stream و دوال textstream حيث ان دوال textstream مبنيه على دوال stream.

مدونتي: C++ Tips and Tricks

#14

امم ، أنا كنت أقصد دوال مثل readInt32 ، و writeInt32 مثلا .

لايمكن ان تعمل في TextStream ، مثال :

TextStream s ....

s.writeInt32( 100000 ); // لايوجد مشكلة .. سيتم تحويل العدد الى نص وكتابته على شكل نص مكون من بايتات .. اي سنكتب 6 بايتات
.
.
.
int x = s.readInt32(); //  اذا حاولنا قراءة  4 بايتات لن نستطيع قراءة 100000 لأنه عبارة عن نص مكون من 6 بايتات اذا كان اسكي

std::string x= readString(); // هنا .. يمكننا قراءة كلمة كاملة .. أي يمكننا قراءة 100000

لكن ماذا عن المعامل >> و << مثلا .. قد نحتاج لعملها في السي بلس لـ TextStream أيضاً وهي لاتعمل جيدا مع Binary Files بسبب مشاكل overloading ؟

هل استطعت توصيل الفكرة ؟

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#15
اقتباس
امم ، أنا كنت أقصد دوال مثل readInt32 ، و writeInt32 مثلا .

اخى الشمرى الجوال التى ذكرتها موجوده داخل BinaryStream و ليس stream

اقتباس
هل استطعت توصيل الفكرة ؟

لم افهم ماذا تقصد، ارجو التوضيح.

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

#16
اقتباس
اخى الشمرى الدوال التى ذكرتها موجوده داخل BinaryStream و ليس stream

اه .. صحيح .. تبّاً لم أنتبه :D .. اسف على هذه اللخبطة .

لكن ماذا عن File الذي سينشئ هذه الكلاسات ، أم نجعل الكلاس Manager يقوم بانشاءها ، ليكون المسؤول عن هذا النوع من العمليات ونلغي File ؟ ، أميل إلى Manager ..

ما رأيكم ، أن نننتقل إلى الخطوة التالية .. ؟

لكن قبل ذلك ، ما رأيكم في الكلاس MemoryBuffer ؟ هل نعتمده أم نلغيه ؟ هل ترون له ضرورة أم لا ؟

- MemoryBuffer : اقتراح

+ Stream <interface>

---> BinaryStream : <interface> , inherits from Stream

---> TextStream : <interface> , inherits from Stream

---> MemoryStream : <interface> , inherits from Stream

- Manager OR File : اختلاف في التسمية

- IniFile : ما رأيكم في التسمية

تم تعديل هذه المشاركة بواسطة الشمري في 12 أكتوبر 2009 في 21:02

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#17
اقتباس
لكن قبل ذلك ، ما رأيكم في الكلاس MemoryBuffer ؟ هل نعتمده أم نلغيه ؟ هل ترون له ضرورة أم لا ؟

الـ MemoryStream هو الـ MemoryBuffer حيث يتيح لك حجز منطقه معينه من الذاكره و التعامل معها (بدلا من استخدام void*) هو يقوم باللازم.

بالنسبه للـ IniFile فأنا اوافق عليها، و بالطبع هذه الفئه لن يتم وراثتها من Stream حيث ان نظام القراءه و الكتابه من وإلى IniFile تختلف عن باقى الملفات.

بالنسبه للفئه Manager فأنا لا أويد فكره جعل فئه واحده فقط مسئوله عن انشاء نسخ من الواجهات الأخرى فيفضل تقسيمها حتى تصبح منطقيه كأن نجعل الدوال التى تقوم بإنشاء واجهات التعامل مع الملفات فى الفئه File و الئ27جهات المسئوله عن الرسم فى الفئه Graphics و هكذا، كل الفئات السابقه هى فئات Manager و لكن محتواها يختص بما تستطيع هى عمله.

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 13 أكتوبر 2009 في 09:27

مدونتي: C++ Tips and Tricks

#18

بارك الله فيك أخي محمد على المتابعة .

كلما أردت أن أبدأ بالخطوة الثانية أجد مشكلة ..

MemoryStream : يرث من الواجهة Stream ، أليس من الأفضل أن يرث من BinaryStream ؟ حيث يقوم بنفس ما يقوم به BinaryStream ، فقط باختلاف الوعاء ( ذاكرة بدلاً من ملف ) ؟

الهدف من MemoryStream : نقرأ كامل الملف في الذاكرة عن طريق BinaryStream ، بعدها نقرأ كما نريد مثل readInt32 ، من الذاكرة ، ثم يمكن بعدها أن نفعل العكس ، اي أن نعيد مصفوفة بايتات ، لنكتبها في ملف مرة أخرى .

هذا Diagram بعد أن جعلت MemoryDiagram يرث من BinaryStream :

post-42837-1255461637_thumb.png

بالنسبة للجافا هي مثل السي بلس باستثناء الغاء أي كلاس باسم Win32xxxx ( ذات اللون الرمادي )

* الكلاسات ذات اللون الرمادي والتي تبدأ بـ Win32 هي اختيارية وللغة السي بلس بلس فقط ( ليس للجافا مثلا ) ، وتعني امكانية عمل Implementation باستخدام Win32 APIs لمن أراد دعمها .

الكلاسات ذات اللون الأزرق ، والتي تبدا بـ Std وهي اجبارية وتعني عمل implementation باستخدام المكتبة القياسية للغة Standard io lib ، في السي بلس نستخدم مثلا fstream . في الجافا نستخدم الكلاسات المعروفة للملفات .

* Win32iniFile : اذا كان يمكن دعمها بالاستغناء عن Win32 APIs ، يتغير اسمها إلى StdIniFile .

* البادئة Win32 و Std أفضل من C .. اذا كان يمكن للكلاس أن يدعم أكثر من مكتبة أو نظام .

* اخر نقطة تتعلّق بالـ Exceptions الخاصة بهذه الحزمة ، مثل FileNotFoundException .. في الجافا لن نحتاج لتعريف كلاسات من هذا النوع لوجودها ، أم السي بلس فنحتاج لها ، وسنتعرف عليها في الخطوة التالية عند كتابة المواصفات .

هل كل شيء على مايرام ..؟ هل نبدأ الخطوة التالية ؟ أخشى أن الملل بدأ يسترّب إلينا .. اذا ترغبون أن نتحرك بشكل أسرع يمكن ذلك .. ولكن الهدف هو الاتفاق على كل خطوة .

تم تعديل هذه المشاركة بواسطة الشمري في 13 أكتوبر 2009 في 22:30

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#19

ما البديل لفئات الـ win32 في الجافا؟

هل ستكون الفئات القياسية في الجافا أم ستكون فئات الحزمة NIO و التي تعني (New Input Out Package)

الايميل غير صحيح

يرجى تصحيح الايميل برسالة لأحد مدراء المنتدى

#20
ahmad_n3na3 كتب:
ما البديل لفئات الـ win32 في الجافا؟

هل ستكون الفئات القياسية في الجافا أم ستكون فئات الحزمة NIO و التي تعني (New Input Out Package)

الفئات القياسية في الجافا سندعمها عن طريق عمل implementation مثل StdTextStream ، أو اي اسم ترونه مناسب .

الحزمة NIO لم أسمع بها من قبل ، اذا كنت ترى لها فائدة وتحب دعمها ممكن تضيف implementation أخرى باسم NioTextStream أو اي اسم تراه مناسب ، الـ implementation متروك لمطوّري المشروع ، المهم الاحتفاظ بنفس الواجهة . وعمل implementation أساسية يمكن أن يعمل من خلالها المحرك .

تم تعديل هذه المشاركة بواسطة الشمري في 14 أكتوبر 2009 في 16:04

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#21

الخطوة التالية : كتابة مواصفات Specification للأصناف Classes التي سيستخدمها المستخدم النهائي

- تقريباً الخطوة الأولى منتهية .. أعتقد لاتوجد مزيد من الاقتراحات ،

- قمت بتجميع وتصفيف المواصفات ، الشكر لله ثم للاخ محمد علاء ، كفانا شر كثير من الدوال .. ونقلت أغلب الدوال التي كتبها في مشاركاته السابقة ..

- قمت بتغيير بعض أسماء الدوال ، وبعض الكلاسات ، لعدة أسباب ،

- أهم التغييرات هي بتغيير هيكلية io بشكل بسيط ، حيث أصبحت هناك واجهة واحدة باسم DataStream للكتابة من والى ( ملف أو مصفوفة في الذاكرة ) .

هذه صورة توضيحية :

post-42837-1255545272_thumb.png

- اذا ، تلاحظون أنه لايوجد فرق بين الكتابة من والى ملف ثنائي أو من والى مصفوفة في الذاكرة ، بل ويمكن التحويل من ملف إلى الذاكرة والعكس .

- بالنسبة لتسمية الكلاسات الداخلية مثل StdMemoryStream يمكن تغييرها واختيار اسم أفضل ذو معنى .. لأن المستخدم النهائي لن يشاهد هذا الكلاس .

- الكلاسات المحاطة باللون الأصفر ، سنعمل لها implementation في الخطو الثالثة ان شاء الله ، كما تشاهدون ، العدد قليل و implementation في الغالب سيكون سهل ان شاء الله .. لذلك سننتهي قريباً اذا تحركنا سريعا الان :) .

- الكلاسات ذات اللون الرمادي اختيارية ، يمكن تجاهلها اذا لم يدعمها أحد .

- بالنسبة للواجهة DataStream يمكن تغيير اسمها الى BinaryStream لو رغب أحد بذلك .. شخصيا أتمنى تغييرها ولا أعرف لماذا كتبتها هكذا :) بحيث يكون اسم الكلاسات التي تقوم بعمل implementation لها : BinaryFileStream و BinaryMemoryStream او اي اسم جيد ..لايهم.

- اذا كان هناك اعتراض أو ملاحظة .. فبانتظارها :) .

- نأتي للمهم ، المواصفات :

http://andalus-engine.svn.sourceforge.net/...e/standards/io/

- لقد جعلت ملفات المواصفات كملفات جافا ، حتى تستطيع عرضها بشكل ملون وجميل في source forge أو في أي مكان :

Stream.java

DataStream.java

TextStream.java

IniFile.java

StreamManager.java

- أهم الواجهات هي Stream ، أرجو قراءة التعليق والشرح الموجود في الملف Stream ، حيث تم شرح الهيكلية المقترحة ، والعلاقات بين الكلاسات .

- ليس كل overloaded Methods موجودة ، حيث هناك مرونة في هذا الجانب ، متروكة للمطور .

- هناك اختلاف في نوع البيانات ، فمثلا في السي بلس بلس يمكن استخدام int32 أو int64 ، بينما في الجافا نستخدم long في الملفات ،

أيضا يوجد في السي بلس يوجد signed type و unsigned type بينما في الجافا أغلبها signed type ، لذلك ستجد مثلا دالة باسم :

void writeInt(int i);

في السي بلس تكتبها هكذا :

void writeInt32(int32 i);
void writeInt64(int64 i);

الخلاصة .. المواصفات لاتهتم كثيرا بكل overloaded methods أو كل الأنواع types للمتغيرات .. وذلك للاختلافات بين الجافا والسي بلس وغيرها من اللغات ، المهم عند Implementation ، تغطية جميع المتغيرات لكتابتها من والى Stream .. وعمل أي overload مهمة .

- المطلوب :D :

1- كتابة أي خطأ - مشكلة - ملاحظة - سؤال .

2- كتابة مواصفات الواجهة IniFile

تم تعديل هذه المشاركة بواسطة الشمري في 15 أكتوبر 2009 في 00:16

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#22

عمل ممتاز، :)

سوف أتولى كتابة مواصفات iniFile.

#23

ملاحظات :-

في الواجهة IStream إقتراح إضافة :

isOpened : للتاكد من أن الـStream مازال مفتوحاً

getOpenMode: لمعرفة الوضع المفتوح عليه الـStream

إقتراح دمج seek و setPosition إلى مثلا setCursorPosition ويكمن بعد ذلك عمل overload عند الحاجة

سؤال:-

هل يمكن تغير الـOpenMode بعد فتح الـStream

كيف تكون صلاحيات القراءة والكتابة و تحديد المؤشر هل عن طريق Enum أم شئ أخر

تم تعديل هذه المشاركة بواسطة ahmad_n3na3 في 15 أكتوبر 2009 في 14:13

الايميل غير صحيح

يرجى تصحيح الايميل برسالة لأحد مدراء المنتدى

#24

هل سيتم بناء IniFile بالإعتماد على دوال windows ؟؟

اقتباس
إقتراح دمج seek و setPosition إلى مثلا setCursorPosition ويكمن بعد ذلك عمل overload عند الحاجة

عموما الداله seek اعم و اشمل من setPosition حيث ان الأولى تتيح لك اتجاه الحركه اما الثانيه فهى دائما ما تجعل التحرك للمؤشر من الأمام فقط.

اقترح مراجعة الفئه File الموجوده فى هذا الموضوع

اقتباس
هل يمكن تغير الـOpenMode بعد فتح الـStream

اعتقد لا ينفع على الأقل فى بإستخدام دوال Win32API

و الله ولى التوفيق

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 15 أكتوبر 2009 في 14:29

مدونتي: C++ Tips and Tricks

#25
اقتباس
سوف أتولى كتابة مواصفات iniFile.

بارك الله فيك أخ سلوان :-)

اقتباس
هل سيتم بناء IniFile بالإعتماد على دوال windows ؟؟

نفس السؤال .. الأخ سلوان قد يفيدنا أكثر في هذه النقطة :-) .. علاقة Win32 APIs بهذه الملفات

اقتباس
isOpened : للتاكد من أن الـStream مازال مفتوحاً

getOpenMode: لمعرفة الوضع المفتوح عليه الـStream

مع هذا الاقتراح .. لامانع .

اقتباس
إقتراح دمج seek و setPosition إلى مثلا setCursorPosition ويكمن بعد ذلك عمل overload عند الحاجة

كما قال الاخ محمد علاء seek أعم من setPosition وايضا أكثر استخدام ، صارت كأنها بروتوكل ، حيث تجدها في كل المكتبات بهذا الاسم .

لذلك أرى الابقاء على نفس التسمية والغاء setPosition ، حيث رأيت الملف File الذي وضعه الاخ محمد ، وفكرته جيدة :

seek : تحرك المؤشر من بداية أو نهاية الملف أو من الموقع الحالي للمؤشر .

seek أخرى : تحرك المؤشر من بداية الملف .

skip : تحرك المؤشر من الموقع الحالي ، تسمية هذه الدالة جميلة ومعبّرة :-) .

مع تأييد اقتراح تغيير getPosition إلى getCursorPosition ، حيث الاسم أفضل وأكثر وضوح .

اقتباس
كيف تكون صلاحيات القراءة والكتابة و تحديد المؤشر هل عن طريق Enum أم شئ أخر

عن طريق Enum أفضل ..

هناك نقطة احترت فيها :

من المفترض أنه عند فتح الملف فإنه سيفتح للقراءة والكتابة معاً .. هل تقترحون اعطاء المستخدم الحرية في تحديد طريقة فتح الملف ، فلو اختار for reading مثلا .. فان write لن يكون لها أثر .

قد لايكون لهذه الحدود أهمية في محركنا ، لكن لو فرضنا أنه يحاول فتح ملف للقراءة فقط ، قد يواجه مشاكل حينها ، مش متأكد ، لكن أرى أن فكرة اعطاء المستخدم خيارات لفتح الملف هذا enum رايته في الرابط الذي وضعه الاخ محمد :

enum AccessOptions
{
	AO_Read  = 0x0000..,  // open for read
	AO_Write  = 0x0000.., // open for write
	AO_Both   = Read | Write   // open for read and write
};

// open file options
enum OpenOptions
{
	OO_Open	= 0x0000..,
	OO_Create  = 0x0000..
};

// seek options
enum SeekOptions
{
	SO_Begining= 0x0000..;
	SO_Current = 0x0000..;
	SO_End	  = 0x0000..;
};

قد لا تكون الخيارات تغطي كافة المتطلبات ، لكن يمكن أن نسمح بخلطها مع بعض باستخدام Bitwise Operators مثل OR .. على سبيل المثال :

AO_Both | SO_End | OO_Open

سيفتح الملف للقراءة والكتابة ويحرك المؤشر لاخر الملف واذا لم يجد الملف يرمي باستثناء

مسألة خيارات فتح الملف تحتاج لتطوير ..

@ الأخ محمد :

رأيت الملف File ، وهو منظم بشكل جيد ، أقترح اضافة هذه الدوال لأهميتها ( بعضها مقترحة من الاخ أحمد ) :

	bool Open(); // open file
	bool IsOpen();  // is current file is opened
	LONGLONG getCursorPosition(); // get current position
	bool IsBOF(); // is pointer in beginning of the file
	bool IsEOF(); // is pointer in end of the file
	long getFileSize(); // get file size

أهم دالة هي open ، المشكلة الان أن الملف نفتحه بمجرد انشاء الكائن ، ولو أغلقناه عن طريق close لايمكن فتحه مرة أخرى إلا بإعادة انشاء الكائن new .. هل ترون اضافة open لتعمل مع الملفات ؟

تم تعديل هذه المشاركة بواسطة الشمري في 16 أكتوبر 2009 في 14:37

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

مواضيع مشابهة