כמה דברים שכדאי לדעת כשמתחילים פרוייקט חדש בReact Native

וודאי שמעתם על הפרימוורק היחסית חדש של פייסבוק: ReactJS שיודע להתקמפל גם לאפלקיציות נייטיב באנדרואיד וiOS. כנהוג במוצרים חדשים, הם לא ממש עובדים Out of the box. הנה מה שהייתי צריך לעשות כדי שזה יעבוד בקונפיגורציה של: מכונת פיתוח לינוקס (אובונטו), מכשיר אנדרואיד מחובר, וכרום שמשמש כדיבאגר (זה הכלי בברירת המחדל).

לאחר שהרצת את ההתקנה כך:

https://facebook.github.io/react-native/docs/getting-started.html

תתקלו במספר שגיאות. הדבר הראשון שצריך לעשות הוא ליצור קובץ בשם local.properties במיקום של הפרוייקט בmy_project/android. לקובץ הזה צריך להוסיף את השורה: sdk.dir=/path_to/Android/Sdk

לאחר שהרצתם בהצלחה sudo react-native run-android האפליקציה תופיע במכשיר. ניעור של המכשיר יקפיץ לכם תפריט מפתחים על המכשיר אך הפעלה של start remote debugging תכשל.

על מכונת הפיתוח יש לפתוח console חדש ולהריץ: sudo react-native start

כמו כן, בחלון נוסף יש להפעיל reverse proxy של הADB על מנת שהבקשות ינותבו למחשב ולכרום דיבאגר: adb reverse tcp:8081 tcp:8081

כעת פותחים דפדפן כרום. יש להכנס לכתובת: http://localhost:8081/debugger-ui

ולהכנס לתפריט המפתחים ולסמן את pause on exceptions:

עכשיו אפשר להתחיל לדבאג ולעבוד.http://localhost:8081/debugger-u

בהצלחה!

הצלת Amazon Cloud AWS EC2 Instance אם במקרה דפקת את ההרשאות

אז אם עשיתם משהו טפשי כמו sudo chmod -R 777 על תיקיית הhome או chown למשתמש הלא נכון או משהו דומה, יש סיכוי טוב שלא תוכלו להתחבר למכונה בssh. אל תטרחו לפנות לתמיכה של אמזון, הם יטענו שמבחינתם כל עוד המכונה למעלה ומגיבה זה לא בעיה שלהם (ובצדק מסויים).

יש פתרון פשוט:

  1. עוצרים את המכונה ומנתקים את הVolume
  2. מקימים Instance חדש
  3. מחברים את הvolume של המכונה הבעייתית (שאותו ניתקנו) למכונה החדשה כvolume נוסף
  4. נכנסים בssh למכונה החדשה ועושים mount לvolume
  5. עכשיו אפשר להריץ עליו פקודות כמו למשל chmod ולהחזיר את המצב לקדמותו
  6. כשסיימתם, מנתקים את הvolume, מחברים אותו למכונה המקורית ואפשר למחוק את המוכנה החדשה ששימשה לתיקון

הוראות מדוייקות אפשר למצוא כאן:

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html#TroubleshootingInstancesConnectingMindTerm

אודות שלמה שוורץ, מפתח תוכנה ומנכ"ל מגהסופט

קצת עליי – אודות שלמה שוורץ

שלמה שוורץ
Shlomo Schwarcz

הגעתם הנה כי אתם מחפשים איש פיתוח חזק ובעל נסיון במספר רב של עולמות ודומיינים. וזה אני 🙂

לי קוראים שלמה ואני אוהב לכתוב קוד. למעשה, אני כותב קוד למחייתי ב17 שנה האחרונות אבל מי סופר. כיום אני פרילנסר עצמאי, מעורב במספר פרוייקטים וגם מעסיק צוות קטן של מתכנתים נלהבים. אני אוהב קוד פתוח וכשאני מתכנת משהו זה בדרך כלל יהיה Full Stack, כלומר פתרון מקצה לקצה. פעם המושג הזה התייחס למי שיודע סרבר וקצת web קליינטי. היום אני מאמין שfull stack הוא הרבה יותר: זה לבחור את הלוח והחיישנים בפרוייקט IoT, לחבר אותם בפרוטוקול תקשורת מתאים, לתפור פתרון ענן כמו שצריך עם AWS וEC2 או כל ספק אחר. המידע יזרום מהDevice וכמובן מאפליקציית אנדרואיד וiOS, משם הוא יגיע לשרת. את השרת אני בדרך כלל אכתוב בnode.js אבל ב12 שנה האחרונות כתבתי בעיקר בג’אווה עם כל הפרימוורקים החביבים: Spring, Hibernate בילדים עם Maven ואני אפילו ביליתי כמה שנים עם J2EE, JSP, GWT הודעות עם JMS וגם EJB הזכור לטוב (או לרע…).

אז היום אני אעדיף node או פיתון או שילוב של שניהם. Node כי הוא קליל ומהיר וpython כי הוא פשוט מהנה לכתיבה. וגם כמובן כי יש עושר של ספריות ויכולות באופן חסר תחרות כמעט.

את המידע אני אשמור בdatabase מטבע הדברים. שנים עבדתי עם MySQL ואורקל על שלל גרסאותיו. לאחרונה העברנו הרבה פרוייקטים לmongoDB שם נהנים מהיתרונות של NoSQL ובעיקר משוחררים ממגבלות הschema והACID שיש שRDBMS רגיל. תענוג!

כמובן שביג דאטה (Big Data באנגלית נשמע טוב יותר) בשימוש אצלינו. מhadoop ומערכות Map Reduce אחרות, דרך Neo4J עבור גרפים, ועד Elastic Search ובשמו הקודם: Lucene.

הקליינט הוא סיפור בפני עצמו. אני מאלה שאוהבים גם את הצד הזה ומקדישים לו חשיבות רבה (בניגוד לנטיית חלק ממתכנתי הסרבר שמזניחים את ה"סקריפטים האלה"). בעבר כתבנו עם Jquery ורפימוורקים שונים ומשונים כמו YUI, DOJO, Sencha Ext-JS ומה לא. בשנתיים האחרונות עברנו לאנגולר 1 ומבחינתי זו ספריה מעולה. לאחרונה עברנו לangular 2 עם לא מעט חששות ובחלק מהפרוייקטים גם React JS אז אני די משייט בין העולמות האלה.

כמובן כמובן שאני כותב את הפוסט הזה על מחשב לינוקס. כל מכונות הפיתוח שלנו הם לינוקס וכך גם השרתים, מכונות הטסטים (כן, אנחנו כותבים Unit tests, חשבתם אחרת?).

אם הגעתם עד לכאן כנראה שחפרתי מספיק ואם אתם רוצים לראות כמה מהפרוייקטים והלקוחות שלי אתם מוזמנים להציץ בדף הבית או פשוט לפנות אליי בלינקדאין או במייל.

אני תמיד שמח לקבל פניות בכל עניין: התיייעצויות, שותפויות, שיתופי פעולה, פרוייקטים והצעות מעניינות אז תרגישו חופשי לפנות.

תודה,

שלמה

shlomo@megasoft.co.il

https://il.linkedin.com/in/shlomoschwarcz

Build Version אוטומטי באמצעות Maven

רוצים שכל קומפילציה/Deploy תקדם את מספר הבילד? שתמיד יהיה מספר גרסה עדכני בכל בנייה של הקוד? הנה הדרך עם Maven.

ראשית, נשתמש בפלאגין בשם buildnumber. התוסף הזה מיועד ליצור משתנה בזמן הרצת הסקריפט ולשמור אותו במשתנה סביבה (בתוך maven) לשימוש בהמשך.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>buildnumber-maven-plugin</artifactId>
    <version>1.4</version>
    <configuration>
        <revisionOnScmFailure>no.scm.config.in.pom</revisionOnScmFailure>
    </configuration>
    <executions>
        <execution>xml
            <id>create-timestamp-id</id>
            <phase>validate</phase>
            <goals>
                <goal>create-timestamp</goal>
            </goals>
            <configuration>
                <timestampFormat>yyyy.MM.dd.HH.mm</timestampFormat>
                <timestampPropertyName>buildNumber</timestampPropertyName>
            </configuration>
        </execution>
    </executions>
</plugin>

כעת ניצור את הקובץ שבו נרצה לשתול את המספר הבילד שאותו נציג באפליקציה. ניצור את /static/js/version.js בספריה הראשית של הweb של הפרוייקט.

בקובץ נשים את השורה הבאה:

var version = ‘1’;

כעת נשתמש בתוסף נוסף בשם replacer שיודע להחליף טקסט בקובץ לפי RegEx:

<plugin>
    <groupId>com.google.code.maven-replacer-plugin</groupId>
    <artifactId>replacer</artifactId>
    <version>1.5.3</version>
    <executions>
        <execution>
            <phase>prepare-package</phase>
            <goals>
                <goal>replace</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <file>${project.build.resources[0].directory}/static/js/version.js</file>
        <replacements>
            <replacement>
                <token>(["'])(?:(?=(\\?))\2.)*?\1</token>
                <value>'${buildNumber}'</value>
            </replacement>
        </replacements>
    </configuration>
</plugin>

שימו לב שאנו משתמשים במשתנה buildNumber ובביטוי רגולרי שמשמעותו להחליף את הערך שבין הגרשיים הבודדים (‘’).

5 פיצ'רים שישכנעו אתכם להתחיל לכתוב בES6

כולם מדברים על זה, כולם עושים את זה, אמנם לא כל הדפדפנים תומכים והתקן לא לגמרי סגור אבל חייבים להתחיל. למי שמפתח בג'אווה סקריפט ועדיין לא כותב בES5/6 (קיצור לEcmaScript) להלן 5 סיבות למה כדאי להתחיל להשתמש בתקן החדש לשפה.

1. פונקציות חץ Arrow Functions

כמה פעמים כתבתם קוד כזה:

var that = this;

myService.doSomething(x, function(res){
 console.log(res);
that.val = res;
});

שני דברים מטרידים: הכתיבה המסורבלת עם המילה function (נסו להזכר בכל הפונקציות האנונימיות המקוננות…) והקטע הבלתי נסבל הזה בJS שבו הthis מצביע לסקופ של הפונקציה במקום ל"אובייקט" ועל מנת לפתור זאת צריך לשמור רפרנס לאובייקט או להשתמש בbind.

בES6 הפתרון פשוט:


myService.doSomething(x, (res)=>{
 console.log(res);
this.val = res;
});

פונקציות חץ אוטומטית עושות bind לthis שקרא להן. זה הגיוני בהתחשב בכך שהן תמיד פונקציות אנונימיות ולכן אין סיבה שמישהו ירצה להשתמש בthis הפנימי של הפונקציה.

2. איטרטורים

כן, סוף סוף JS נכנסת לסטנדרט של המילניום. יש! לא עוד לולאות for מסורבלות עם אינדקסים ומשתנים שמטיילים על מערכים. מעכשיו זה נראה כך:

myArray.forEach(function (value) {
    console.log(value);
});

ובשרשור עם פונקציית חץ מהסעיף הקודם מקבלים את הקוד האלגנטי הבא:

myArray.forEach((value)=> { console.log(value); });

3. הגדרת משתנים לוקאליים לscope

בג'אווה סקריפט למי שטרם שם לב ברגע שמגדירים משתנה עם var הוא יהיה תקף עבור כל הבלוק של הפונקציה הקרובה. זה בניגוד למצופה הרבה פעמים. למשל:

for (var i=0; i<10; i++){
// do something
}

// will print 10
console.log(i);

דבר זה יכול לגרום לבלבול והתנגשות שמות משתנים כיוון שמשתנים שמוגדרים בבלוק מצומצם חיים למעשה בבלוק הרבה יותר נרחב ועלולים להתנגש עם משתנים אחרים. בES6 ניתן להגדיר משתנה באמצעות let (במקום var) שמשמעותו הוא שהמשתנה מוגדר רק לבלוק הקרוב ביותר ולא לפונקציה.

for (let i=0; i<10; i++){
// do something
}

// exception: i is not defined
console.log(i);

4. משתני const

אתם מתכנתים? יפה, אז לא צריך להסביר מה זה const ולמה צריך את זה. בכל זאת הנה דוגמא ופרס למי שינחש מה היא מדפיסה

const x = 10;
console.log(x);

5. וגולת הכותרת למי שרגיל לשפות OOP: קלאסים!

ES6 מציגה את הclass. לא מדובר חלילה במהפכה בשפה, עדיי JS נשארת prototype based וכמובן weakly typed אבל זה מאפשר כתיבת סינטקס נוחה וקריאה למי שרגיל לחשוב באופן של קלאסים, אובייקטים, מתודות, ירושה וכו':

class Fish {
    constructor () {
        this.weight = 4;
        this.color = 'blue';
    }

    eat (kg) {
        this.weight += kg;
    }

    swim (km) {
        this.weight -= km*0.1;
    }
}

var fish = new Fish();
fish.eat(3);
fish.swim(2);
console.log(fish.weight);

הרעיון פשוט: הconstructor מתרגם לגוף הפונקציה למקרה שהיינו כותבים פונקציית-קלאס JS רגילה. המתודות הופכות למעשה לפונקציות prototype והthis מצביע לגוף של הפונקציה הראשית כשם שהיה קורה בפונקציית prototype רגילה. אז למעשה זה JS רגיל לגמרי רק עם סינטקס OOP נוח ומוכר. וכן, יש גם static למי ששואל 🙂

פירצת אבטחה חמורה שמצאנו בספריית sql-injection לnode

מדובר בספריה: https://www.npmjs.com/package/sql-injection
הפירצה היא חור בביטויי RegEx שמאפשר הזרקה של שאילתות Select באמצעותן ניתן לגשת לכל המידע בדאטהבייס. פתחנו קריאה כאן:
https://github.com/socialradar/sql-injection/issues/new

בנתיים לא נענינו.

מדריך בזק לתכנות א-סינכרוני בnode.js

אחד היתרונות המובהקים של Node הוא השימוש הרב בפונקציות אסינכרוניות. זה אחד המאפיינים המאפשרים את המהירות והסקלאביליות של שפה זו. אסינכרוניות פותר את צוואר הבקבוק של מערכות רבות ובפרט מערכות web ושרתים: ההמתנה של Thread לפעולת I/O. למשל אם הרצתי שאילתה לDB ואני ממתין לתשובה זה יכול לקחת שניה, או 30 שניות. בזמן הזה הthread תפוס ומבזבז משאבי מערכת למרות שהוא לא עושה כלום (לא מבצע שום פעולה מלבד המתנה).
אמנם בתכנות "רגיל" אפשר ברוב השפות לכתוב קוד אסינכרוני אבל רבים לא טורחים לעשות זאת וספריות וAPI רבים לא תומכים בכך. Node מאלץ את המתכנת לכתוב אסינכרוני כיוון שהקוד רץ בthread אחד ואם תהליך כלשהו ימתין אז כל הפרוסס יהיה תקוע.

כתיבת קוד בסגנון אסינכרוני יכול להיות מבלבל ולא אינטואיטיבי. הבעיה העקרית היא שכמתכנתים אנו רגילים להסתכל על ביצוע שורות קוד לפי סדר כתיבתן. כלומר, שורה 3 תתבצע אחרי שורה 2 וכו’. בתכנות אסינכרוני בדומה לתסנות Multi Threaded המצב שונה.

האתגר הגדול הוא לוודא שהקוד שלנו רץ במקום הנכון ובזמן הנכון. בnod יש לנו 3 אפשרויות לטיפול בפונקציות אסינכרוניות ובפוסט זה ובפוסט הבא נעסוק בהן:
שימוש בפונקציית Callback
שימוש בpromise
שימוש בyield (כשיש תמיכה בES6)

במקור, הדרך הנפוצה היתה שימוש בcallback. הרעיון הוא להעביר פונקציית חזרה לפונקציה האסינכרונית על מנת שזו תקרא לה כשהיא מסיימת את פעולתה. לדוגמא:

db.insert(‘hello’, function(err,res){
	console.log(‘Completed inserting to DB’);
});

בקוד הנ"ל אני מכניסים אובייקט (רשומה) לדאטהבייס של MongoDB. כאשר הפעולה מסתיימת פונקציית הcallback תקרא ותדפיס את ההודעה.
הבעיה בשיטה הזו היא מה שמכונה callback hell שמתרחש כאשר רוצים לשרשר כמה תגובות אחת לשניה. כלומר, אם היינו רוצים לקרוא לפונקציה אחרת כשהראשונה מסתיימת, ולאחריה
לעוד אחת וכו’ וכולן תלויות זו בזו בסדר זה היה נראה בערך כך:

db.insert({str:‘hello’}, function(err,res){
	console.log(‘Completed inserting to DB’);
	var id = res._id;
	db.update({id:id, data:’aaa’}, function(err, res){
		http.send(‘http://server.com/’ + res, function(err,res){
			db.insert({id:id, response:res},function(err, res){
				console.log(‘Done!’);
			});
		});
	});
});

בעיה נוספת היא שקשה להפריד פונקציונליות למודולים או אפילו פונקציות שונות. פונקציה אסינכרונית אינה יכולה להחזיר ערך. כלומר, היא יכולה אבל הערך יוחזר לפני שהפונקציה תסתיים ולא תתקבל התוצאה הרצויה. המצב הרצוי הוא שהפונקציה תסיים את פעולתה ותחזיר את הערך למי שקרא לה אבל כשפונקציה אסינכרונית מסיימת היא קוראת לפונקציית callback וזו הדרך היחידה להגיב בסיום הפעולה.
לכך המציאו את הpromise. זהו אובייקט שעוטף את הפונקציה האסינכרונית וחושף פונקציה בשם then שאפשר לקרוא עם callback. עדיין יש להעביר callback על מנת שזו תקרא בסיום הפעולה אבל האובייקט Promise ניתן להעברה (שכן זהו אוביקט רגיל לכל דבר) וכך פונקציות אסינכרוניות יכולות להחזיר Promise ולאשר מידול בצורה סבירה.
בדוגמה הקודמת שלנו בשימוש בpromises:

db.insert({str:‘hello’}, function(err,res){
	console.log(‘Completed inserting to DB’);
	var id = res._id;
	return db.update({id:id, data:’aaa’}).then(function(err, res){
		return http.send(‘http://server.com/’ + res).then(function(err,res){
			return db.insert({id:id, response:res}.then(function(err, res){

			});
		});
	});
}).then(function(res){	
	console.log(‘completed’);
});

בפוסט הבא נדבר עם yield עם EcmaScript 6 וכיצד ניתן לסנכרן קוד באמצעותו.

רקורסיה + תכנות אסינכרוני בNode.js

בעקבות באג שמצאתי אצל לקוח החלטתי לפרסם פוסט מאתגר בעניין רקורסיה ותכנות אסינכרוני. הבעיה היא שרקורסיה היא גם ככה עניין מסובך והתכנות האסינכרוני מוסיף לזה עוד מימד של בעייתיות כיוון שכשהפונקציה קוראת לזו שלאחריה זה לא עובר בstack המסורתי אלא כל פונקציה רצה בקצב שלה.

הנה דוגמה לסדרת פיבונאצ'י הידועה. מימוש רקורסיבי רגיל ולאחריו מימוש עם Promises.

אנחנו נשתמש בrouter של Express לצורך הדוגמה אבל כל אובייקט אחר יתאים גם:

var router = express.Router();

עכשיו לצורה הרקורסיבית הסטנדרטית:

router.fib = function(n) {
	if(n <= 2) {
		return 1;
	} else {
		return this.fib(n - 1) + this.fib(n - 2);
	}
};

והנה המימוש הרקורסיבי-אסינכרוני:

router.fibAsync = function(n) {
	return new Promise(function (resolve, reject) {
		if(n <= 2){
			resolve(1);
		}else{
			var sum = 0;
			router.fibAsync(n-1).then(function(res1){
				sum += res1;
				router.fibAsync(n-2).then(function(res2){
					sum += res2;
					resolve(sum);
				});
			});
		}
	});
};

כפי שניתן לראות המימוש משתמש בPromises והערכים המוחזרים הם הסכום שחוזר בthen של הpromise הרקורסיבי. הדבר היחיד שצריך לזכור בעבודה עם Promises הוא שהערך לא חוזר מהפונקציה כמו בכתיבה רגילה אלא בתוך הthen שהוא למעשה החלופה לCallback המסורבל. הפונקציה fibAsync בעצמה מחזירה Promise כך שיש לקרוא לה בצורה אסינכרונית עם then.

בפוסט הבא נלמד להריץ רקורסיה על עץ כשיש להפעיל לולאה על הבנים והכל כמובן… אסינכרוני!

הStack שלנו בשנתיים האחרונות MEAN – Node.js, Express, Angular.js, MongoDB

עבר זמן מאז כתבתי פה ודברים קצת התעדכנו. אז בשנתיים האחרונות החבילה המומלצת שלנו מתבססת על Node.js. מהיר, פשוט, קל להתקנה לתחזוקה ולדיבוג, הרבה פחות מסורבל לעומת ג'אווה ומאפשר תאימות וחלקי קוד משותפים בין השרת לקליינט. כמובן שJava עדיין מככבת בפרוייקטים שלנו, במיוחד בפרוייקטים הוותיקים וגם סתם אצל לקוחות שבוחרים לפתח בשפה זו אבל כשאנחנו נדרשים להקים מערכת מאפס ולבחור ארכיטקטורה node הוא בהחלט הבחירה שלנו. בפוסטים הבאים נעלה טיפים, רעיונות, פתרונות וPatterns לבעיות נפוצות.