يوم أن كانت لغات البرمجة وأدوات التطوير غير مجانية

السلام عليكم ورحمة الله

مضت اﻷيام والسنوات بسرعة منذ أن كانت لغات البرمجة وأدوات التطوير لها سعر ينافس عتاد الكمبيوتر الذي يعمل فيه، وكانت اللغات محدودة التي تُستخدم في سوق العمل، والتي تُدرّس في الجامعات والمعاهد، كذلك قواعد البيانات. لم يكن هناك شيء مجاني. ثم كانت هناك كتب، مراجع ورقية كبيرة. ما زلت أذكر كتاب Turbo Pascal 5.5 الشهير وهي النسخة التي دعمت البرمجة الكائنية في لغة باسكال قبل أن تُدعم في لغة سي. وكان هذا الكتاب لا يُسمح باستلافه من مكتبة الجامعة، فقط يُقرأ داخل المكتبة لأنه مصنف ضمن المراجع، وكان كتاب ضخم يحوي أكثر من 500 صفحة كما أذكر.

ولا زلت أذكر في عام 1997م عن زيارتي لمدينة جدة في شارع خالد بن الوليد أو شارع فلسطين، وهي شوارع بها مكتبات ومحال كمبيوتر، وقفت حائراً بين شراء صندوق فيجوال بيسك أو إنكارتا 97، ولم يكن الوقت كافياً للتفكير، فاخترت إنكارتا. هذا الاختيار كان يمكنه تغيير مسيرتي من حيث لغات البرمجة، حيث شهد سوق العمل منافسة بين لغتي فيجوال بيسك من شركة ميكروسوفت العملاقة، و دلفي من شركة بورلاند الصغيرة لكن المتخصصة في أدوات التطوير، وانتهي الصراع بأن اشترت ميكروسوفت مطور لغة البرمجة وأدوات التطوير دلفي Anders Hejlsberg بمبلغ 3 مليون دولار كما سمعنا حينها، وهو من أميز المبرمجين حيث هو من طور توربو باسكال الشهيرة، ثم دلفي، ثم الدوت نت عندما ذهب لشركة ميكروسوفت، ثم اشترت بعدها ميكروسوفت من خلفه في تطوير الدلفي في شركة بورلاند التي كان لا يتعدى موظفيها ثلاثمائة موظف، لكن مع ذلك لم يتوقف منتج دلفي إلى اﻵن. و كدت أن أنسى أني راسلت مؤسس شركة بورلاند Philippe Kahn (وهو مخترع كاميرا الهاتف شاهدو فيديو قصته في هذا الموقع) سألته عن رأيه في لغة البرمجة دلفي، وكان قد ترك الشركة، فقال لي في رد مقتضب لا زلت أذكره: Delphi is a good product ثم سألته في بريد لاحق عن سبب تركه لشركة بورلاند.

مصدر الصورة emsps.com

عندما كانت لغات البرمجة غير مجانية كان المبرمجين أكثر ارتباطاً بالبرمجة، فتخيل أنك اشتريت أداة تطوير للغة برمجة معينة مثل دلفي أو C++Builder أو Visual Basic فلا بد أن تعمل بها سنوات عدة، كذلك شركات البرمجة كانت تنفق أموال مقابل شراء هذه الأدوات فتكون هي جزء من الاستثمار في هذه اللغة وهذه اﻷدوات، فلا يحدث تغيير للغة ثانية بسهولة، إنما اعتاد الناس شراء نُسخة جديدة كل عام أو كل بضعة أعوام من نفس المنتج، كان هناك انتماء كبير من المبرمجين لهذه اللغات. لكن كان هناك كثير من المستخدمين سواءً أفراد أو ممن يعملون في مؤسسات أو شركات برمجة يستخدمون البرامج المقرصة، فكانت أداة التطوير التي بها كل الميزات هي من تتوفر كنسخة مقرصنة. أما من يشتري فيختار النسخة المناسبة السعر، مثلاً standard edition أو حتى professional أما النسخة Enterpise أو Architect فنجدها بأغلى سعر يمكن أن يصل إلى 5 آلاف دولار أو توجد مقرصنة مثل نسخة Delphi Architect

بعد ظهور لغة جافا في عام 1995 كلغة برمجة مجانية حدث هناك تغيير كبير في السوق، أولها أنه أصبح الفصل واضح بين لغة البرمجة وبين أدوات التطوير، مثلاً في السابق كان لا يمكن الحصول على مترجم لغة باسكال لوحده، إنما لابد أن تشتريه مع أداة التطوير Turbo Pascal أو Borland Pascal أو دلفي مثل ما أصبح لاحقاً. كذلك Visual Basic لا يوجد مترجم للغة Visual Basic إنما هو برنامج متكامل يحوي على مترجم اللغة والمنقح Debugger والمحرر Editor وكل ذلك يسمى IDE اختصار ل Integrated Developoment Environment وكانت أداة التطوير دلفي تسمي نفسها RAD اختصاراً لجملة Rappid Development Tool. حتى لغة سي لم تكن متوفرة في بيئة وندوز كمترجم إنما كانت هناك أدوات تطوير أشهرها Visual C++ وكانت هناك C++Builder لكن لم تكن بنفس الشهرة والمنافسة للأداة اﻷولى التابعة لميكروسوفت.

بعد أن حدث هذا الفصل بين اللغات وأدوات التطوير، ظهرت محررات عديدة تعمل لأكثر من لغة مثل Eclipse المكتوبة بلغة جافا نفسها، لكنها يمكن استخدامها مع لغة سي ثم أندرويد عندما ظهر. كذلك أداة التطوير NetBeans تعمل لأكثر من لغة منها PHP. ثم مؤخراً نسخة مجانية من Visual Studio،. بالنسبة لللغات أصبح معظمها مجاني للاستخدام الشخصي والتعليمي والتجاري، ابتداءً من لغة جافا، ومروراً بلغة PHP و Go و Java script ولغة بايثون التي أصبحت اللغة اﻷولى من حيث الاستخدام، وأصبحت اللغات المدفوعة مع أدوات تطويرها إما في نهاية عمرها كمنتجات مدفوعة أو في انحسار.

استسلمت شركة ميكروسفت لهذا التيار من هذه اللغات المنافسة فأطلقت منصتها Net. بصورة مجانية ومعها لغات البرمجة ومعها مترجم #C مع محدودية في الاستخدام التجاري، لكن بعد ذلك تجاوزوا هذه المحدودية وأصبحت منصتهم ولغاتهم متوفرة للاستخدام التجاري مجاناً.

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

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

الجدير بالذكر أن بعض الشركات تطوير لغات البرمجة لاستخدامها الخاص، مثل شركة الفيسبوك التي طورت لغة Hack كبديل للغة PHP لاستخدامها الداخلي ثم جعلتها مفتوحة المصدر، كذلك شركة Google عندما طورت لغة Go كبديل للغة سي++ لاستخدامها الداخلي ثم جعلتها مفتوحة المصدر

لغة البرمجة Rust أصبحت واقع وبديل جديد لبرمجة اﻷنظمة

السلام عليكم ورحمة الله

منذ فترة كنت متابع تطورات وأخبار لغة البرمجة Rust وهي لغة برمجة جديدة للأنظمة System programming بديلة للغة C التي ناهزت الخمسين عاماً ولغة ++C. والمشكلة في هذه اللغات اﻷخيرة بها مشكلة عدم أمان في استخدام الذاكرة memory unsafe وهي تجعل البرامج معرضة للاختراق، كما ذكرت شركة ميكروسوفت أن 70% من مشاكل البرامج في السرية هي مشاكل عدم أمان في الذاكرة. والأنظمة مقصود بها البرامج التي تعمل مع العتاد مباشرة مثل أنظمة التشغيل، والبرامج التي تتطلب أداء عالي مثل محركات قواعد البيانات ومترجمات لغات البرمجة، وحتى المتصفحات، فهذه كلها تحتاج إلى لغة برمجة أنظمة ذات سرعة عالية في التنفيذ وتستخدم الموارد بصورة قليلة.

ظهرت لغة Rust في مؤسسة موزيلا التي تطور المتصفح FireFox. ثم في عام 2015 صدرت النسخة رقم 1 من مترجمها، ثم بعد ذلك أصبحت لغة بديلة عن لغة سي في تطوير البرامج الجديدة وبدأت مؤسسات مهمة في استخدامها كبديل مثل شركة ميكروسوفت وقوقل واعتمدت كلغة إضافية مع لغة C في اﻹصدارات اﻷخيرة من نواة لينكس. والجدير بالذكر أنه قد صدر بيان الشهر الماضي من البيت اﻷبيض باستخدام لغات برمجة بها أمان في الذاكرة memory safe languages والتوقف عن استخدام لغات ليس بها أمان في الذاكرة مثل لغة C و ++C . هذا هو رابط خبر البيان. والهدف هو التقليل من الهجمات عن طريق الإنترنت.

اللغات البديلة كانت مذكورة في تقرير سابق لوكالة اﻷمن القومي على هذا الرابط، ذكرت فيها هذه اللغات:

Python®, Java®, C#, Go, Delphi/Object Pascal, Swift®,
Ruby™, Rust®, and Ada

هذه اللغات معظمها لغات عالية المستوى، أي لغات تطبيقات وليست لغات أنظمة، ولغة اﻷنظمة المذكورة هنا هي Rust لذلك أصبحت هي الخيار الوحيد المستقبلي لتطوير اﻷنظمة وبديل مباشر للغتي C و ++C . أما باقي اللغات فيمكن استخدامها لباقي أنواع البرامج مثل برامج الويب وأنظمة الاتصالات والواجهات البرمجية APIs و خدمات الويب وغيرها من البرامج المختلفة ذات الاستخدام المباشر.

لغة سي تعدى استخدامها أنظمة الحاسوب المختلفة، حيث تُستخدم في المعالجات الدقيقة microcontrollers المستخدمة في اﻷنظمة المدمجة، وكمثال لها ما يُعرف بكمبيوتر السيارة، والمتحكم في الغسالات الآلية والثلاجات وكل جهاز يحتوي على معالج دقيق، لكن لا أدري هل هذه تشكو من نفس المشكلة (مشكلة عدم أمان الذاكرة) أم لا، فربما لا تتأثر إلا اﻷجهزة المرتبطة باﻹنترنت مثل الراوترات التي تحتوي على أنظمة تشغيل مكتوبة بلغة C. فلست متأكد إلى هذه اللحظة هل هناك خطة لتبديل لغات اﻷنظمة المدمجة بلغة برمجة ذات أمان في الذاكرة أم لا.

توجد مشكلة كبيرة في لغة البرمجة Rust وهي صعوبتها، حيث أن تعلمها والدخول لاستخدامها لأول مرة ليس سهل مثل اللغات الحديثة اﻷخرى، مع أن عمرها لم يتجاوز 9 أعوام لكن تُشابه قواعدها لغات البرمجة القديمة المعقدة مثل ++C. وهذا مثال لبرنامج به حلقة لإظهار التاريخ والوقت والانتظار ثانية في كل لفّة:

هذا برنامج لغة Rust:

use chrono;
use std::{thread, time};

fn main() {
  println!("RUST Language");
  for i in 1 .. 10 {
    println!("Time {}: {:?}", i, chrono::offset::Local::now());
    thread::sleep(time::Duration::from_secs(1));
  }
  println!("Finished")
}




يمكن تجربته وتشغيله والتعديل عليه في موقع Rust Playground على هذا الرابط. نجد أن لغة Rust تستخدم كثير من الرموز التي تحتاج لضغط مفتاح shift مثل !, : { وهذه من اﻷشياء المزعجة أثناء كتابة الكود.

وهذا نفس البرنامج بلغة البرمجة Go للمقارنة بين مقروئية اللغتين:

// You can edit this code!
package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("Go Language")
	for i := range 10 {
		fmt.Printf("Time %d: %s\n", i+1, time.Now().String())
		time.Sleep(time.Second)
	}
	fmt.Println("Finished")
}

كذلك يمكن تشغيله من هذا الرابط.

وهذا نفس المثال بلغة البرمجة C:

#include<stdio.h>
#include<time.h>

int main()
{
    struct timespec waitt = { 1/*seconds*/, 0/*nanoseconds*/};

    for (int i=1; i<=10; i++) {
      time_t t;
      time(&t);

      printf("Time %d: %s", i, ctime(&t));
      fflush(stdout);
      nanosleep(&waitt,NULL);
      
    }
    printf("Finished");
    return 0;
}

ثم ننتقل إلى برنامج أكثر تعقيداً، وهو برنامج سطر أوامر command line لعرض محتويات صفحة أو خدمة ويب، كذلك يعرض حالة الصفحة أو الرابط أي ما يسمى status code في حالة النجاح يكون 200 Ok وفي حالة أن الصفحة غير موجودة يرجع 404 not found بالإضافة إلى حالات أخرى.

المثال اﻷول بلغة البرمجة C:

#include <stdio.h>
#include <curl/curl.h>

int main(int argc, char **argv) {
  
  if (argc != 2) {
    printf("Please type URL parameter\n");
  } else {
    CURL *curl;
    CURLcode res;

    curl = curl_easy_init();
    if(curl) {

      curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
      /* example.com is redirected, so we tell libcurl to follow redirection */
      curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

      /* Perform the request, res gets the return code */
      res = curl_easy_perform(curl);
      /* Check for errors */
    	long http_code = 0;
	    curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
      fprintf(stderr, "Status: %d\n", (int)http_code);

      if(res != CURLE_OK)
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

      /* always cleanup */
      curl_easy_cleanup(curl);
    }
  }
  return 0;
}

نجد أن به تعقيد، ويحتاج للربط مع مكتبة clib وتحتاج إلى تثبيت مكتبة في نظام التشغيل، ثم إضافة الباراميتر التالي أثناء الترجمة وربط البرنامج: -l curl

وهذا نفس المثال بلغة البرمجة Go :

// getPageContent project main.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"time"

	"net/http"
)

func CallURL(aurl string) (result string, status string, err error) {

	timeout := time.Duration(time.Duration(10) * time.Second)

	client := http.Client{
		Timeout: timeout,
	}
	var response *http.Response
	var req *http.Request
	req, err = http.NewRequest("GET", aurl, nil)

	response, err = client.Do(req)

	if err == nil {
		status = response.Status
		var buf []byte
		buf, err = ioutil.ReadAll(response.Body)
		if err == nil {
			result = string(buf)
			response.Body.Close()
		}

	}

	return
}

func main() {
	fmt.Println("Call URL")
	if len(os.Args) > 1 {
		result, status, err := CallURL(os.Args[1])
		if err == nil {
			fmt.Println("Status: ", status)
			fmt.Println(result)
		} else {
			fmt.Println("Error:", err.Error())
		}
	} else {
		fmt.Println("Please type URL in parameter")
	}
}

نجد أن البرنامج طويل قليلاً، لكن يمكن ترجمته مباشرة ولا يحتاج إلى تثبيت أي مكتبة إضافية حيت تتميز اللغة بأن لها مكتبة run-time كبيرة مثلها مثل لغة Python .

وهذا مثال لغة Rust، وهو أكثر اختصاراً لكن أقل مقروئية، حيث أن به بعض القواعد غير المفهومة، وجدته في هذا الرابط مع برامج أخرى، لكن للأسف لم تعمل، نتج عنها خطأ مع أني امس حدثت نُسخة مترجم Rust إلى أخر نسخة وهي 1.74.1 ، لكن فقط عمل البرنامج اﻷول لكنه لا يحتوي على الـ status code ولا الـ command parameter.

extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::status;
use std::os;

fn main() {
    let request = RequestWriter::new(Get, FromStr::from_str(os::args()[1]).unwrap());
    let response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => unreachable!(), // Uncaught condition will have failed first
    };
    if response.status == status::Ok {
        println!("Oh goodie, I got me a 200 OK response!");
    } else {
        println!("That URL ain't returning 200 OK, it returned {} instead", response.status);
    }
}

إعادة كتابة البرامج القديمة والتي تبلغ ملايين اﻷسطر بلغة برمجة جديدة تتطلب وقتاً طويلاً وهو ليس موضوع سهل وأحياناً يكون غير مجدي، أتوقع أن تظل البرامج القديمة مكتوبة بلغة سي عشرات السنين، مثله مثل التحول إلى بروتوكول اﻹنترنت الجديد IP6 حيث مازال بروتوكول IP4 سائداً رغم مشاكله وبالرغم أن بروتوكول IPv6 قارب الثلاثة عقود من إصداره.

إصدار كتاب: Migration To Go Language

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

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

قبل يومين أصدرت الكتاب على أنه مسودة للمراجعة تحت ترخيص Creative Commons و يتطلب تدقيق لغوي (اللغة اﻹنجليزية) وتدقيق من ناحية المعلومات والتجارب والحقائق المذكورة في لغة البرمجة Go. لذلك كان الهدف الكتابة باللغة الإنجليزية أولاً قبل كتابة نُسخ منه باللغة العربية.

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

صفحة الكتاب

تحميل الكتاب مباشرة

بداية تركنا للغة البرمجة جافا، والانتقال للغة Go

السلام عليكم ورحمة الله

بدأت قبل أكثر من عشرة أعوام بدراسة لغة البرمجة جافا كبديل للغة البرمجة دلفي أو أبجكت باسكال، كما تكلمت في تدوينة سابقة في ذلك الوقت. ثم اعتمدت لغة جافا في عملي الخاص منذ بداية تأسيسه في عام 2012، وكانت لغة جافا مدعومة بشكل جيد في مجال الاتصالات الذي نستهدفه في برامجنا. وبعد عام من استخدامها كتبت عنها كتاب. وحققت لنا تلك البرامج نجاح كبير -بفضل الله تعالى- وساهمت في تأسيس جزء كبير من اﻷنظمة البرمجية والتي ساهمت في تأسيس عملي الخاص (كود لبرمجيات الكمبيوتر). لكن بعد مرور خمس أعوام تقريباً أصبحت تواجهنا مشاكل في البرامج المكتوبة بهذه اللغة بعد زيادة الاستخدام واستمرار تعقيد البرامج وتطويرها، والعمل لسنوات عديدة على نفس العتاد ونفس النُسخة من نظام التشغيل، لذلك بدأنا بدراسة بدائل وكان البديل المناسب للغة جافا هو لغة البرمجة Go، والتي تكلمت عن نجاحنا في تحويل بعض البرامج التي كانت بها مشكلة من جافا إلى لغة Go في تدوينة قبل عامين تقريباً.

بعد أن كتبنا عدد كبير من البرامج بلغة البرمجة جافا، مثل برامج الويب وخدمات الويب والتي تستخدم مخدم الويب Tomcat وبعض البرامج التي تعمل في الخلفية وبرامج متعددة المهام Multi-thread ، واجهتنا مشاكل في عدم الاستقرار وتوقف مخدم الويب Tomcat مما ينتج عنه توقف البرامج التي يفترض أن تعمل على مدار الساعة أو كما تُسمى 24/7 ، ولحل المشكلة يتطلب إعادة تشغيل لمخدم Tomcat، ومع التوقف المتكرر نتج عنه تذمر المستفيدين من البرامج، خصوصاً إذا لم نحل المشكلة في وقت وجيز. بعض المخدمات تعطل فيها تماماً مخدم Tomcat ولم يعمل بعد عدد من المحاولات لتشغيله. فكان الحل اﻷسرع هو تشغيل البرامج في أكثر من مخدم فإذا توقف اﻷول يحدث تحويل للمستخدمين تلقائياً للمخدم الثاني، لكن نجح هذا الحل فقط في برامج الويب، أمام خدمات الويب فلم تنجح معها تلك الطريقة، وفكرنا في حل جذري بإعادة كتابة تلك البرامج بلغة Go وكان أول مثال أو مثالين نجحا في العمل بدون توقف في نفس المخدم الذي كانت به مشكلة لبرامج الجافا كما ذكرت في المقالة السابقة. لاحقاً تعرفنا على مخدم أخف من Tomcat وبه إمكانات أقل لكنه أكثر استقراراً وهو Jetty واستخدمناه، لكن بعد أن بدأنا في تحويل عدد من البرامج إلى لغة Go

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

المشكلة الثالثة هي تعقيد بيئة ولغة جافا مقارنة باللغات اﻷحدث واﻷبسط مثل لغة Go و Node .JS – والتي تستخدم لغة جافا سكريب والتي ليس لها علاقة بلغة جافا-. حيث أن لغة جافا لغة قديمة ولها أرث كبير من المكتبات وطُورت في زمن مختلف وحدث فيها تغييرات لكن حافظت على بعض التعقيد منذ الماضي مثل تعقيدها في تعدد المهام، وهذه مقالة مفصلة لتجربة ومقارنة بين تعدد المهام (Multi-threading) في برنامج بلغة جافا وآخر بلغة Go واصفاً النوع اﻷخير بأنه Green Thread فهو يستهلك موارد أقل للمعالج. كذلك فإن برامج الويب تحتاج إلى مخدم ويب يدعم جافا، واللغة نفسها معقدة مقارنة باللغات الحديثة التي أصبحت أبسط.

المشكلة الرابعة هو اختلاف نُسخ جافا في المخدم واختلاف نُسخ المكتبات، فعندما بدأنا استخدامها كُنا نستخدم جافا 7 و نُسخة Tomcat 7، فكان هُناك نوع من الاستقرار لعدد من الأعوام، إلى أن ظهرت جافا 8 وأصبحت معتمدة في النُسخ الجديدة من أنظمة لينكس، كذلك أصبحت مطلوبة لتثبيت نُسخة NetBeans 8.2، وأصبح هُناك بعض الاختلاف في قواعد اللغة بين جافا 7 وجافا 8 وبعض المكتبات تتطلب جافا 8، ثم ظهرت جافا 11، وظهرت نُسخة قاعدة البيانات MySQL 8 بدلاً عن MySQL 5 والتي تتطلب مكتبات مختلفة، أي مكتبة للنُسخة 5 وأخرى للنُسخة رقم 8، وعندما بلغ عدد المخدمات التي نعمل عليها حوالي 70 مخدم عند مختلف العملاء و تحتوي على نُسخ مختلفة من نظام أوبونتو لينكس ونُسخ مختلفة من جافا ونُسخ مختلفة من قاعدة البيانات MySQL وبعضها MariaDB أصبحت الجافا مشكلة حقيقية للتوفيق بين هذا الاختلاف، وحتى بين جهاز لابتوب المبرمج نفسه، في المقابل برامج لغة البرمجة Go ليس لديها هذه المشكلة، فهي لا تحتاج إلى أي مكتبات خاصة في المخدمات، حيث يمكننا مثلاً تحميل إصدار ة جديدة من لغة البرمجة Go ثم مباشرة نستخدمها لإعادة إنتاج برامج وتثبيتها في أي مخدم بغض النظر عن نُسخة لينكس وبغض النظر عن نُسخة MySQL التي تعمل بها. و برامجها معتمدة على نفسها أكثر من اعتمادها على بيئة نظام التشغيل الخارجية، هذه الميزة تُسمى Self-contained وهي ميزة مهمة جداً كانت في السابق في لغة دلفي، لذلك تجدني لا أميل لأي لغة برمجة script مثل PHP, Node.JS وغير ها من اللغات المفسرة وليست المترجمة التي تحتاج لتثبيت مترجم اللغة ومكتباتها في أي مخدم، فهذا يجعل البرامج بها نوع من الهشاشة ولها ارتباط شديد بالبيئة مما يخلق مشاكل مستمرة في توزيع البرامج التي تعمل بها في المخدمات، بعكس اللغات المترجمة المعتمدة على نفسها Self-contained فهي ينتج عنها برامج ثُنائية قوية معتمدة على نفسها، لكن مشكلتها الوحيدة أن حجمها كبير تؤثر في سرعة تحميلها إلى المخدمات إذا كان الاتصال مع المخدم بطيء.

كتبت لغرض شرح استهلاك الموارد لهذه التدوينة برنامجين باللغتين للمقارنة في استهلاك الذاكرة لإظهار التاريخ والزمن كل ثانية، فبرنامج لغة Go استهلك حوالي 2 ميقابايت من الذاكرة، أما برنامج جافا فقد استهلك 18 ميقابات. كذلك أداة التطوير LiteIDE المُستخدمة لكتابة وتطوير البرامج للغة Go تستهلك حوالي 75 ميقابات، مقارنة بأداة التطوير NetBeans والمكتوبة بلغة جافا نفسها فهي تستهلك 618 ميغابايت حسب التجربة، وهي بطيئة في الإقلاع وتحتاج لجهاز ذو مواصفات أعلى. في نهاية المقالة سوف تجدون تفاصيل للبرنامجين واستهلاكهم للذاكرة والمعالج.

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

ما تزال قصة التحويل هذه في منتصفها، لا نستطيع الحكم عليها اﻵن بأنها ناجحة بالكامل، لكن بعد عام أو أكثر – إن مد الله في العمر- ربما نتكلم عن التجربة بعد تمامها لنرى كيف صار التحويل وهل ظهرت تحديات أخرى أم لا، وسوف تتضح الصورة بطريقة أفضل بإذن الله. أردت التوثيق لهذه النقلة لتكون كمرجع، وكذلك ليستفيد من هذه التجربة أو مجموعة التجارب هذه غيرنا حتى لا يقع في نفس الأخطاء التي وقعنا فيها. لكن الجدير بالذكر أن عدد من برامج جافا التي كتبناها طوال هذه الفترة كانت مستقرة وهي ذات استخدام معتدل وأبسط ولا تحتوي على تعقيد مثل تعدد المهام. كذلك فإن مخدم Tomcat ذو اﻹمكانات العالية عمل باستقرار في عدد من برامج الويب وخدمات الويب، لذلك نقول أنه ما تزال لغة جافا تصلح لعدد من التطبيقات ولا ننصح بالتغيير لأجل التغيير ما دامت البرامج مستقرة، ولا توجد لغة برمجة كاملة، وكل لغة تصلح لنوع معين من التطبيقات.

هذه هي البرامج ونتائج استخدامها للموارد، واستخدمت برنامج ps_mem في الرابط أدناه في نظام لينكس المكتوب بواسطة لغة بايثون لقياس استخدام الذاكرة لكل برنامج:

https://github.com/pixelb/ps_mem

برنامج لغة Go

func main() {
	for {
		fmt.Println(time.Now().String())
		time.Sleep(time.Second)
	}
}

برنامج جافا:

    public static void main(String[] args) throws InterruptedException {
        while (true){
            System.out.println(new Date().toString());
            Thread.sleep(1000);
        }
    }

وهذه نتيجة المقارنة بين استهلاك الذاكرة بين البرنامجين:

بعد عدد من الساعات لاستمرار تشغيل تلك البرامج زاد استهلاك برنامج Go إلى 2.5 ميقا، بينما تضاعف استهلاك برنامج جافا إلى 52 ميقا:

وهذه مقارنة لعدد الـ Threads المستهلكة من نظام التشغيل لتشغيل البرنامجين:

قصتي مع حاسوب صخر، الجزء الثالث

Sakhr

السلام عليكم ورحمة الله

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

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

عند استعدادي للامتحان للجامعة كان الهدف هو الدخول لأحد الكليات العلمية ولم يكن الحاسوب خياراً معروفاً حينها، حيث كان اﻷهل هم من يختارون لأبنائهم تخصصهم في الجامعة، و لم يكن لدينا الحرية الكبيرة كما هي الآن – إلى حد ما-  ولم يكن هُناك ارتباط بطموح الإنسان ورغبته مع نجاحه في تخصصه، لكن فترة اﻹجازة القصيرة هذه بعد الامتحانات سوف يتغير معها كل شيء كما سنرى.

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

بعدما اشتريت هذا الكتاب وكُنت قبله قد أقبلت على تعلم لغة بيسك بصورة مكثفة وكتابة برامج أكثر تقدماً بها وتسجيلها في المسجل، استفدت من الكتاب كثيراً حيث كتبت عدة برامج مشروحة في الكتاب، وكان أهمها برنامج لرسم أشكال تُستخدم في اللعب تُسمى أشباح sprite في لغة بيسك أو هي تابعة لنظام MSX2 وليست في لغة البيسك القياسي، هذه اﻷشكال يمكن أن تكون عربة مثلاً أو دبابة أو لاعب أو كُرة، يمكن التحكم بها للتحرك في الشاشة بواسطة اﻹحداثيات X, Y

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

صادف هذا الوقت كأس العالم 1994م وكانت لدينا مناسبة زواج – وقد أخذ التحضير له وقتاً طويلاً- في بيت العائلة الكبير والذي يقع جوارنا مباشرة، بل بيتنا مفتوح معه، ومع أني لم أكن من متابعي كرة القدم – مع إني كنت مدمن للعب الكرة قبل امتحان الشهادة- إلا أن المتابعة لم تكن مسلية، لكن شجعني وجود عدد من الناس يتابعون كأس العالم، وكان فيها اللاعب المشهور مارادونا، فحضرت مبارتين على ما أذكر، وكانت آخر مباراة أحضرها في التلفاز حيث أصبح اﻵن لدي هواية جديدة استمرت عقود دون توقف شغلتني عن أشياء أخرى غير مفيدة.

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

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

كان التسجيل في شريط كاسيت صعباً للغاية، حيث لابد من البحث يدوياً عن الملف المُراد تحميله، وإذا زاد حجم الملف لا يمكن إعادة تسجيله في نفس المكان حيث يكون أطول ويُمكن أن يمسح جزء من الملف التالي، كان لابد من حفظه في آخر الشريط، فاصبح حلمي محرك أقراص مرنة. في اﻷيام اﻷولى من دراستي في الجامعة وأثناء رجوعي للبيت وجدت في السوق جهاز صخر مستعمل لكنه أحدث به محرك أقراص صلبة وهو MSX AX 350 فبعت جهازي القديم وغامرت بشراء هذا الجهاز والذي كانت به مشكلة في لوحة المفاتيح وكانت به مشكلة في محرك الأقراص نفسه.

sakhr-350

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

msx-keyboard

أما محرك القرص المرن فكانت به مشكلة، فاشتريت محرك أقراص لكمبيوتر عادي ولم أكن متأكد هل سيعمل أم لا، وأثناء التركيب انقطع سلك التوصيل لمحرك اﻷقراص – لكن كان هذا في صالحي- فعندما أعدت توصيله لم يعمل محرك اﻷقراص، وبما أن السلك مقطوع، فجربت أن أعكس السلكين، فعمل محرك اﻷقراص بفضل الله، فكانت نقلة كبيرة في استكشاف تسجيل البرامج في القرص المرن ذو السرعة الفلكية مقارنة بالمسجل والذي يُسجل الرسمة مثلاً في دقيقتين، فلم أصدق هذه السرعة الهائلة. لكن مشكلة لوحة المفاتيح كانت عائقاً، في هذا الوقت بدأنا استخدام أجهزة الكمبيوتر العادية وكان المعمل في الجامعة به أجهزة من نوع 286 ذات سرعة 10 أو 14 ميغاهيرتز، وذاكرة واحد أو إثنين ميغابايت على ما أذكر، وكانت تعمل بنظام دوس، وبدأنا دراسة البرمجة بلغة باسكال، والتي لم تعجبني حينها مقارنة بلغة بيسك البسيطة فوجدت مع نظام دوس لغة QBasic فصرت أعمل بها ألعاب وبرامج، وكُنت أُفضلها على لغة باسكال، ولم أكن أعرف حينها أني في يوم ما سوف أكتب كتاب عن لغة باسكال اعتبرته بعض المواقع من أفضل كتب لغة باسكال. والذي تُرجم في ما بعد إلى اللغة البرتغالية في البرازيل.

cover

ساهم كمبيوتر صخر في تعلمي البرمجة مساهمة كبيرة، فحين كان الأستاذ يُدرسنا مباديء لغة باسكال كنت قد كتبت ألعاب بلغة بيسك، ثم انتقلت بعدها لتعلم لغة باسكال في فترة وجيزة وكتبت بها عدد من اﻷلعاب، وكان ممنوعاً اللعب في معمل الجامعة، لكن عندما كان يمنع المُشرف زملائي من هذه الالعاب التي انتشرت بينهم، كانوا يفتحون مصدر البرنامج بلغة باسكال و يقولوا للمشرف هذه لغة باسكال وليس لعب 🙂

تحصلت على جهاز كمبيوتر من نوع 486 وانتقلت إلى مرحلة جديدة من معمارية أجهزة MSX إلى معمارية Intel x86 المعروفة إلى اليوم،  وتعرفت قبلها على اﻷخ سفيان وهو يسكن بالقرب منا، وكان لديه جهاز صخر AX 350 وكانت به مشكلة في محرك  اﻷقراص، وعند حصولي على جهاز كمبيوتر 486 دمجنا الجهازين ليصبح كمبيوتر واحد ليست به أي مشكلة من ناحية لوحة المفاتيح ومحرك اﻷقراص، وأظن أن الجهاز لديه اﻵن، لا أعرف هل ما زال محتفظ به أم لا، كان هذا قبل أكثر من خمسة وعشرون عاماً. وودعت كمبيوتر صخر بعد أن قضيت ما يزيد عن سبعة أعوام معه في تعلم البرمجة، وساهم في تقدمي في هذا المجال حيث أنه من يبدأ مبكراً ولو بيوم واحد فقط في أي مجال يمكن أن يجعله هذا متفوقاً على أقرانه لأنه يكون دائماً سابقهم بيوم من الخبرة، شريطة أن لا يتوقف عن التقدم

بعد ما ذكرت في المقالة السابقة أنه لم يتبقى لدي أي أثر ملموس لحاسوب صخر، وجدت قبل قليل في المكتبة كتاب لغة البيسك لجهاز صخر من نوع AX 350 كُنت قد استعرته من اﻷخ سفيان، حيث صرنا نتبادل الكُتب والبرامج، أظن أن كتاب اﻷلعاب كان عنده لأني لم أجده في المكتبة. اختم هذه السلسلة من قصتي مع صخر بصورة للكتاب الذي يحمل معه ذكرياتي لصخر. اﻷخ سفيان، إذا قرأت هذه التدوينة فاعلم أن كتابك موجود معي.

أود بعد الختام إلى أن أشير لنقطة مهمة أرجو التفكير فيها بتمعن خصوصاً للآباء واﻷمهات والمربيين عموماً: عندما طلبت هذا الجهاز كان يمكن أن يُعتبر لعبة مثله مثل أي لعبة أخرى كان يمكن أن لا يشتروها لي أهلي أو يشتروا لي بديلاً عنها هم يروها مناسبة، وبعد أن اشتروا لي هذا الجهاز كان يمكن أن يمنعوني من استخدامه أيام الدراسة مثلاً، وهم في ذلك الوقت لا يعرفون وأنا نفسي لا أعرف أن هذا سوف يُصبح تخصصي ومجالي وهوايتي وموهبتي. فربما يحرم اﻵباء أبنائهم من شيء في الصغر فيكونوا قد منعوا معه مستقبل مشرق لأبنائهم. أن نوفر لأبنائنا ما يطلبوه إذا كان في متناولنا، خير من أن نمنعهم بدون سبب مقنع أو لا نوفر لهم طلباتهم بسبب الكسل، فلعل المستقبل أن يكون في شيء من اﻷشياء البسيطة وحتى اﻷلعاب التي يطلبوها. والتوفيق من الله هو قبل وبعد كل هذا، فقد يسر لنا كل هذه المصادفات والبيئة والتشجيع ثم النجاح في هذا المجال، فله الحمد أولاً وآخراً

هذا فيديو يختصر قصة صخر والعالمية، أرسله لي الصديق: محمد شمباتي:

تحويل بعض البرامج من لغة جافا إلى لغة Go

السلام عليكم ورحمة الله

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

في عام 2017 بدأت تعلم لغة Go وكتبت بها عدد من البرامج الصغيرة ، لكن لم أعد أذكر ماهو السبب الرئيس الذي دفعني لتعلمها واستخدامها، لكن على ما أذكر كُنت أتكلم مع أحد المبرمجين أظنه في أوروبا من مبرمجي لغة باسكال، وقال أنه يستخدم لغة Go في بعض البرامج بالإضافة إلى لغة باسكال، في نوعية معينة من البرامج أظنها خدمات الويب، فكان هذا دافعاً لتعلمها مرة أخرى، حيث جربتها مرة ولم تعجبني ولم استمر. ما لم يعجبني هو عدم توفر أداة تطوير ومحرر بقوة NetBeans الذي تعودت على استخدامه مع لغة البرمجة جافا، وكان هذا في عام 2015 فكانت تجربتي معها سلبية وذكرت ذلك في مقالة كتبتها كانت تتكلم عن أهمية المحرر واﻷدوات مع لغة البرمجة. لكن هذه المرة في عام 2017 وجدت محرر بسيط و مناسب لهذه اللغة اسمه LiteIDE فكانت تجربتي معه ناجحة وما زلت استخدمه مع لغة Go إلى اﻵن.

Liteide

بعد نجاح البرامج اﻷولى بلغة Golang ، حولت إحدى خدمات الويب التي كانت مكتوبة بلغة جافا إلى هذه اللغة الجديدة، وهي خدمة ويب نستخدمها في برامج مرتبطة بمقسم اﻹتصالات Asterisk لإدارته وربط البرامج التي تحتاج التخاطب معه، وقد وضعنا هذا البرنامج كبرنامج مفتوح المصدر في GitHub في هذا الرابط اسمه GoAgent

https://github.com/motaz/goagent

أحد ما يميّز برامج لغة Go هي خفتها، خصوصاً في مثل هذا النوع من البرامج : خدمات الويب أو ما يُعرف حديثاً Microservices وهي طريقة جديدة لمعمارية البرامج الكبيرة لتبسيطها إلى خدمات مستقلة قائمة بذاتها ويمكن استخدام أكثر من لغة برمجة في نظام واحد، حيث أن لكل لغة برمجة قوتها في مجال معين وفي كل زمان تكون هناك لغة سائدة يتوفر لها مبرمجون ودعم فني في اﻹنترنت، لذلك كانت هذه المعمارية الجديدة تتيح الاستبدال الجزئي لتقنيات الأنظمة الكبيرة بدلاً من إعادة كتابتها كاملة بلغة جديدة. وربما اتكلم عن هذه المعمارية في تدوينة منفصلة، حيث أقمت محاضرة لزملائنا عنها قبل عدة أعوام، ثم كانت لنا تجربة جيدة في تبني هذه المدرسة بدلاً عن الطريقة القديمة التي تُسمى Monolithic أي برنامج ذو قطعة واحدة غير المتجزيء إلى أجزاء صغيرة.

هذه صورة للبرنامج goagent الجديد يعمل منذ عام 2018 دون توقف في أحد المخدمات:

goagent

في عام 2018 كانت هُناك مشكلة في أحد برامج خدمات الويب المكتوبة بلغة جافا دائماً تتوقف عن العمل ويتوقف معها برنامج Tomcat المستضافة فيه، وكان هذه المخدم قليل الموارد ذو أربعة أنوية و 2 قيقابات من الذاكرة، وهو مخدم قديم  كان مع عدد من المخدمات في طريقه إلى مثواه اﻷخير في المخزن لكننا طلبنا أن يعطونا كل هذه المخدمات لمحاولة الاستفادة منها ولو مؤقتاً لإعادة تشغيلها بنظام لينكس وكان هذا في عام 2013 ومازالت تعمل إلى اﻵن. بعد استبدال خدمة الويب هذه من لغة جافا بإعادة كتابتها بلغة Go عملت بدون مشاكل وبدون أي توقف وذلك لأن خدمات الويب المكتوبة بلغة Go اقل استهلاكاً للموارد، مقارنة ببرامج جافا التي تسخدم الذاكرة بشراهة أكبر. ومازالت تلك الخدمة تعمل إلى اﻵن دون توقف ودون الحاجة إلى ترقية هذا المخدم أو حتى زيادة ذاكرته، وهذه هي مواصفاته: المعالج 4 أنوية و الذاكرة 2 قيقيا:

adapter

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

 

تعلم لغة بايثون عن طريق برنامج Thonny

السلام عليكم ورحمة الله

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

توجد عدد من اللغات تصلح كبداية للمتعلم الجديد خصوصاً اﻷطفال، لكن أحياناً ما يقف حجر عثرة هي اﻷدوات المستخدمة، حيث أن معظمها معقد ويحتاج لمستخدم متقدم ليقوم بالاعدادات اللازمة لتشغيل اللغة. لكن في جهاز راسبري باي ونظام راسبيان الموجه لتعليم اﻷطفال وجدنا برنامج اسمه Thonny استخدمه أبنائي في تعلم لغة بايثون وقد كانت النتيجة سريعة – بفضل الله- حيث أنهم في إسبوع فقط بدأو يكتبون برامج صغيرة باستخدام لغة بايثون، وقد تمكنوا من عمل برامج تقوم بالرسم في الواجهة الرسومية مشابهة لبرامج لغة Logo

thonny
محرر لغة بايثون Thonny

قام إبني إياس بكتابة برنامج لمعرفة رقم عشوائي من 1 إلى 100 يضعه الكمبيوتر في الذاكرة ويطلب من المستخدم تخمينه، ثم يخبر المستخدم بأن الرقم أعلى أو أقل إلى أن يعرف الرقم، ويحسب عدد المحاولات، وعدد المحاولات اﻷقل هي اﻷفضل.


from random import *
w=1
b=(100*random())
d=int(b)
while(w<100):
xs=input("Input a number from 0 to 100: ")

st=str(xs)
st=st.strip()
x=eval(st)
if(dx):
print("too low")
else:
print("win after ",w," tries")

break
w=w+1

بعد أن قام بتشغيل البرنامج بنجاح، قمت بتصحيح الجمل الإنجليزية التي يتخاطب بها مع المستخدم، حيث أن اختيار العبارات المناسبة للتواصل مع المستخدم هي مهارة تختلف عن مجرد معرفة الشخص باللغة اﻹنجليزية. كذلك كانت هُناك مشكلة في تحويل الرقم إلى عدد صحيح عن تشغيل البرنامج في سطر اﻷوامر فقمت بإضافة هتين الدالتين لتصحيح المشكلة:


st=str(xs)
st=st.strip()

كذلك اقترحت له كتابة عدد المحاولات في نهاية اللعبة

الكتاب الذي اختاروه للتعلم كان هو: تعلم البرمجة مع بايثون 3 ، لكن لاحظت بما أنه مترجم فإن النصوص داخل البرنامج كانت مكتوبة باللغة الفرنسية بدلاً عن اﻹنجليزية، لذلك وجدوا صعوبة في فهم بعض الأمثلة.

قصة برنامج للوصول لمخدم في المكتب من اﻹنترنت

السلام عليكم

بدأت هذه القصة في عام 2016م…

لدينا في المكتب خدمة إنترنت من نوع  ADSL وطريقة إتصاله بالإنترنت تختلف عن باقي خدمات اﻹنترنت اللاسلكية مثل 3G والـ 4G حيث أن أهم ما يميزه أن رقم الـ IP المستخدم لدخول النت يمكن الوصول إليه من أي جهاز في النت وهو يمثل رقم الراوتر أي أنه public، ويمكن عمل ما يُعرف بالـ port forwarding لتحويل رقم بورت معين إلى جهاز لابتوب المتصل مع ذلك الراوتر ، وفي حالتي لدي مخدم صغير في المكتب كنت أود الوصول إليه – وباقي زملائا في العمل- من الخارج من أي مكان في اﻹنترنت. لكن المشكلة أن رقم الـ IP الخاص براوتر الـ ADSL هو غير ثابت ، يتغير مع كل إتصال مع النت، أي أنه dynamic وليس static إلا أنه public.

مثلاً رقم الراوتر اﻵن هو 41.209.65.57 وعند كتابته في المتصفح يقوم مخدم المكتب بإظهار صفحته الرئيسة. لكن غالباً عند قراءتك لهذه التدوينة سوف يتغير إلى رقم جديد بعد يوم أو يومين أو وقت أقل إذا حدث إنقطاع للكهرباء.

لحل هذه المشكلة كان يجب استخدام إسم  domain name بدلاً من استخدام الرقم المتغير، وفي كل مرة يتم ربط هذا الإسم بالرقم الجديد، فبذلك يظل اﻹسم ثابتاً بالنسبة للأجهزة العميلة، مثلاً اﻹسم كان code-server.sd وهو إسم غير موجود في النت، إنما قمت بإضافته في ملف  /etc/hosts في نظام لينكس ، أو ملف

c:\windows\system32\drivers\etc\hosts

  في نظام وندوز. ثم نقوم بكتابة الرقم المتغيير معه، وكلما يتغير الرقم نقوم بتغيير تلك المعلومة في الملف، وبالنسبة للمستخدم لا يحس بأي تغيير لأنه يستخدم الإسم code-server.sd للوصول للمخدم بغض النظر عن رقمه الحالي.

مثلاً هذه محتويات الملف /etc/hosts في جهاز اللابتوب -ونظام تشغيله لينكس- استخدمه اﻵن، لاحظوا السطر اﻷخير به عنوان ورقم المخدم الذي نتكلم عنه:

127.0.0.1       localhost   global.com
127.0.1.1       L40-laptop
#192.168.0.105   L40-laptop
192.168.1.98     raspi2
192.168.0.101  mini-server mini-server.sd
0::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

41.209.65.57          code-server.sd

كانت فكرة الحل هي كتابة برنامج بلغة php في موقع في اﻹنترنت تابع لنا، مثلاً http://www.code.sd ليقوم بندائه المخدم في المكتب كل فترة ليعلمه برقمه الحالي، مثلاً كل ساعة، فيقوم هذا البرنامج أو صفحة php بإنشاء ملف نصي به رقم المخدم الحالي. الخطوة الثانية هي كتابة برنامج أكثر تعقيداً لقراءة هذا الرقم كل فترة ثم تحديث هذه المعلومة في ملف hosts  كما في الشكل التالي:

update-server

قُمت بتسمية البرنامج الذي سوف نضعه في جهاز المستخدم server-update واﻷجهزة هي: لينكس، وجهاز RaspberryPi، ثم لاحقاً بعد كتابة البرنامج تم اﻹحتياج إلى نُسخة تعمل في نظام وندوزأي أنها ثلاث منصات تحتاج لبرنامج تتم كتابته بلغة برمجة متعددة المنصات. كانت الخيارات هي: لغة باسكال، ولغة shell script و لغة جافا، وأخيراً لغة سي أو سي ++

بالنسبة لخيار لغة باسكال متمثلة في FPC/Lazarus كانت موجودة في لينكس وراسبري باي، لكن كانت نُسختان مختلفات من المترجم، ومكتبة التخاطب مع النت HTTP لم تكن موجودة مع المكتبة القياسية للغة، كان لابد من تثبيت ما يُعرف بالـ component وهي تحتاج إلى بيئة لازاراس كاملة أي GUI وبالنسبة لجهاز راسبري باي لم تكن هذه البيئة موجودة فقط المترجم FPC ، لذلك تم استبعادها لعدم إمكانية إنتاج ملف تنفيذي لمنصة RaspberryPi.

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

الخيار الثالث أو ربما اﻷول كان لغة جافا، لكن لا أتذكر بالضبط لٍم لم أختارها، – كان هذا قبل حوالي ثلاثة أعوام – فهي كانت مناسبة، حيث توجد آلة جافا اﻹفتراضية في كلا المنصتين باﻹضافة إلى أن نُسخة الملف التنفيذي سوف تعمل بدون أي تعديل في نظام لينكس ونظام راسبري باي. لكن ربما إحتياجها لتلك اﻵلة اﻹفتراضية أن تكون موجودة في اللابتوب الذي نريد تشغيل هذا البرناج البسيط فيه لم يشجعني على استخدام جافا، حيث أنها مكتبة كبيرة نقوم بتثبيتها عندما يكون البرنامج يستحق تثبيت آلة جافا اﻹفتراضية، لكن ليس لمثل هذه البرامج البسيطة التي لا تزيد أن تكون عبارة عن script

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

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

في كثير من المرات حاولت إعادة دراسة لغة سي والبحث عن استخدامها لكن كل مرة أفشل إما بسبب عدم وجود بيئة متكاملة مقارنة بدلفي أو بسبب عدم وجود تطبيق مناسب لاستخدامها. لكن هذه المرة وجدت تطبيق سهل مناسب وبيئة مناسبة NetBeans فقررت استخدامها لإنجاز هذا البرنامج البسيط.

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

في النهاية تمكنت – بفضل الله- من كتابة البرنامج وتشغيله بنجاح في بيئة لينكس، ثم إعادة ترجمته في جهاز الراسبري باي – حيث يوجد به مترجم سي أيضاً- فأصبحت هُناك نُسختان تنفيذيان من البرنامج تعملان مباشرة في أي جهاز يحتوي على لينكس أو راسبري باي ولا يحتاج البرنامج للغة سي أو أي مكتبة منها. لكن البرناج كان معقداً قليلاً وذو مقروئية متدنية تصّعب اﻷمر على من يريد فهمه أن تعديله.

في بداية العام الذي يليه قررت لسبب ما إعادة كتابة نفس البرنامج باستخدام لغة البرمجة Go حيث بدأت تعلمها في هذا الوقت، وكان أول تطبيق عملي هو برنامج server-update . فقمت بالبحث عن قراءة معلومة من صفحة في النت بهذه اللغة، وقد كانت سهلة ولا تحتاج لمكتبة خارجية إنما كل ما احتجت إليه وجدته في المكتبات القياسية لها. ولغة Go بها نفس ميزة لغة سي، حيث أنه ينتج عنها ملف تنفيذي يعمل في منصة التشغيل المستهدفة دون الحاجة لمكتبات إضافية أو منصة إضافية لتشغيل البرنامج. وفي النهاية كان البرنامج أكثر سهولة وأكثر وضوحاً من سابقه المكتوب بلغة سي. وكان أحد الميزات المهمة في مترجم لغة Go أنه يدعم ما يُعرف بالـ cross-compilation أي يمكن إنتاج برامج تنفيذية لمنصات مختلفة من منصة واحدة، مثلاً من بيئة لينكس يمكن إنتاج برامج تنفيذية لبيئة وندوز وراسبري باي وماكنتوش وغيرها، دون أن تقوم بنقل مصدر البرنامج إلى منصة أخرى لترجمتها وهذه الميزة لم أجدها في لغة سي أو لغة باسكال – مع أن مترجم فري باسكال به هذه الميزة لكن عملياً تطبيقها صعب.

بعد هذا البرنامج كانت إنطلاقة بالنسبة لي لاستخدام لغة Go في العمل في برامج صغيرة ثم برامج أكثر تعقيداً ومازلت استخدمها إلى اﻵن وكتبت بها عدد من البرامج التي تعمل اﻵن في ضمن عدد من اﻷنظمة. وكانت بديل جيد لعدد من برامج جافا حيث أن برامج Go أسرع في التنفيذ ولا تستهلك موارد كبيرة مثل الذاكرة إلا أن برنامجها التنفيذي أكبر بكثير من نظيرتها لغة جافا ولغة سي. فقد كان حجم الملف التنفيذي لبرنامج server-update حجمه 15 كيلوبايت فقط أما نظيره المكتوب بلغة Go فكان حجمه حوالي 6 ميغابايت!

لم أرجع أو أفكر للرجوع لاستخدام لغة سي بعد هذا البرنامج ولم أفكر باستخدام لغة سي++ واﻵن كلا اللغتين في تراجع مستمر بالنسبة للاستخدام حيث يميل كل من يريد الدخول للبرمجة لتعلم لغة أكثر سهولة كذلك فإن الشركات تستخدم اللغات الحديثة فقط في المشروعات البرمجية الجديدة. ويتم استخدام لغة سي وسي++ في المشاريع القديمة التي لها عشرات السنين والتي يتعذر نقلها إلى لغة برمجة جديدة، كذلك فإن لغة سي تُستخدم في اﻷنظمة المُدمجة والمعالجات الدقيقة micro-controllers.

وقبل الختام هذا مصدر البرنامج بلغة سي:

/* 
 * File:   main.c
 * Author: motaz
 *
 * Created on February 10, 2016, 1:35 PM
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

char *server;
char *localserver;

function_pt(void *ptr, size_t size, size_t nmemb, void *stream){
    
  //server = malloc(size);
    //strncpy(server, ptr, size);
    server = ptr;
}

// Local net
function_pt_local(void *ptr, size_t size, size_t nmemb, void *stream){
    
    //server = malloc(size);
    //strncpy(server, ptr, size);
    localserver = ptr;
}

int getURL(void){
    
  CURL *curl;
  curl = curl_easy_init();
  if(curl) {
    printf("Reading from site..\n");
    curl_easy_setopt(curl, CURLOPT_URL, "http://code.sd/..file.txt");
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_pt);
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
    return 0;
}


void copyFiles(){
    
    FILE *fp;
    FILE *output;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;   
    

    fp = fopen("hosts.tmp", "r");
    output = fopen("/etc/hosts", "w");
   
    while ((read = getline(&line, &len, fp)) != -1) {
        
        fputs(line, output);
    }
    fclose(fp);
    fclose(output);    
}

int main(int argc, char** argv) {

    FILE *fp;
    FILE *output;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;   

    char *myserver;
    char* ok = NULL;
    
    getURL();
    myserver = server;

    printf("Server: [%s] \n", myserver);
    fp = fopen("//etc//hosts", "r");
    output = fopen("hosts.tmp", "w");
    int found = -1;
   
    while ((read = getline(&line, &len, fp)) != -1) {
        
        char* ptr=strstr(line, "code-server");
        if (ptr != NULL) {
            fputs(myserver, output);
            fputs("      ", output);
            fputs("code-server.sd\n", output);
            found = 1;
            printf("Found\n");
                    
        }
        else {
          fputs(line, output);
        }
    }
    
    if (found == -1){
       fputs(myserver, output);
       fputs("    ", output);
       fputs("code-server.sd\n", output);
       printf("New\n");
    }
    fclose(fp);
    fclose(output);
    copyFiles();
   
    return (EXIT_SUCCESS);
}

وهذا نفس البرنامج بلغة Go ويزيد عليه إضافة ليعمل في بيئة وندوز

// server-update2 project main.go
package main

import (
	"bufio"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"runtime"
	"strings"
)

func isLinux() bool {

	return runtime.GOOS == "linux"
}

func getTempFileName() string {
	if isLinux() {
		return "/tmp/hosts.tmp"
	} else {
		return "c:\\windows\\temp\\hosts.tmp"
	}
}

func getHostsFileName() string {
	if isLinux() {
		return "/etc/hosts"
	} else {
		return "c:\\windows\\system32\\drivers\\etc\\hosts"
	}
}

func main() {
	ip := getIP("http://code.sd/..file.txt")
	if (ip != "") && (len(ip) < 100) {
		readIntoTemp(ip)
		copyFile(getTempFileName(), getHostsFileName())
	} else {
		println("Unable to read IP")
	}
}

func getIP(url string) string {

	resp, err := http.Get(url)
	if err == nil {

		body, err2 := ioutil.ReadAll(resp.Body)
		if err2 == nil {
			line := string(body[:])
			return line
		} else {
			println("Error: " + err2.Error())
		}
	}
	return ""
}

func readIntoTemp(ip string) {

	file, _ := os.Open(getHostsFileName())
	destfile, _ := os.Create(getTempFileName())

	var found bool = false
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "code-server.sd") {
			println("Found, IP = " + ip)
			found = true
			line = ip + "          code-server.sd"
		}
		destfile.WriteString(line + "\n")
	}
	if !found {
		println("New entry for code-server.sd")
		destfile.WriteString(ip + "       code-server.sd\n")
	}

	file.Close()
	destfile.Close()
}

func copyFile(source string, dest string) bool {

	sourceFile, err := os.Open(source)
	if err == nil {
		defer sourceFile.Close()
		destFile, err2 := os.Create(dest)
		if err2 == nil {
			defer destFile.Close()
			io.Copy(destFile, sourceFile)
		} else {
			println("Error: " + err2.Error())
		}
	}
	return err == nil
}

الجدير بالذكر أنه بعد فترة تعطل الراوتر، فاشتريت رواتر جديد من نوع DLink فوجدت به خدمة إضافية من الشركة المُنتجة له وهي خدمة Dynamic DNS حيث قمت بعمل حساب عندهم واختيار إسم دومين جديد ثم ربط هذا الحساب بالراوتر، فيقوم الراوتر بتحديث العنوان كلما تغير رقم الـ IP الخاص به، وبذلك اصبح هُناك حل سهل لا يحتاج لبرمجة أو توزيع برنامج للمستخدمين. لكن بقي البرامج الذي قمت بكتابته يعمل ليكون كإحتياطي في حالة تعطل الراوتر أو توقف الخدمة المجانية التابعة لشركة DLink

 

 

اﻹصدار الثالث من كتاب: رحلة استكشافية للغة البرمجة جافا

السلام عليكم ورحمة اللهsmallcover

اليوم بفضل الله قمت بإصدار النُسخة الثالثة من كتاب رحلة استكشافية للغة البرمجة جافا، حيث كان اﻹصدار الثاني قبل عامين تقريباً.

في هذا اﻹصدار لم تكن اﻷولوية لإضافة مواضيع جديدة، بقدر ما كان التركيز على إعادة صياغة بعض الفقرات واﻷمثلة وزيادة التوضيح للمفاهيم أو اﻷمثلة التي بها بعض الغموض، وكان ذلك بعد الحصول على إفادة من بعض القراء حول تلك النقاط التي تحتاج توضيح.

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

رابط تحميل الكتاب

 

اﻹصدار الثاني لكتاب: رحلة استكشافية للغة البرمجة جافا

السلام عليكم ورحمة اللهCover

قبل أربع أعوام قمت بكتابة كُتيّب للغة البرمجة جافا كان عنوانه “رحلة يوم مع لغة البرمجة جافا” وكانت إحدى اهداف كتابته هو أن اتعلم جافا بطريقة أعمق، حيث أن احدى طرق التعلم هو تعليم نفس المادة للغير، و ما يسبق اﻹعداد للتعليم هو إصباغ القراءة والفهم لهذا الموضوع بالرجوع للمراجع و عمل التجارب في حال أن الموضوع علمي.

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

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

ماتزال لدي خطة لكتابة مواضيع كثيرة، خصوصاً أن أكثر لغة استخدمتها طوال هذه الأربع أعوام كانت لغة جافا، وقد كتبت بها عدد كبير من البرامج، فأسأل الله تعالي أن يعينني على كتابة تلك المواضيع عسى أن تتم بها فائدة المسلمين.

هذه صفحة الكتاب