<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lusta.hu &#187; Szakmai</title>
	<atom:link href="http://www.lusta.hu/category/szakmai/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lusta.hu</link>
	<description>Amíg a test renyhe, az elme dolgozik</description>
	<lastBuildDate>Tue, 07 Feb 2012 12:08:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Slice Forward</title>
		<link>http://www.lusta.hu/2012/02/07/slice-forward/</link>
		<comments>http://www.lusta.hu/2012/02/07/slice-forward/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 12:08:31 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1261</guid>
		<description><![CDATA[I am a big fan of developing an application in a way that I create a thin, working slice first, and then add the other functionalities to this slice one by one. Yet, there is still a question about creating the original slice. Should I do it from the backend to the frontend, or the [...]]]></description>
			<content:encoded><![CDATA[<p>I am a big fan of developing an application in a way that I create a thin, working slice first, and then add the other functionalities to this slice one by one. </p>
<p>Yet, there is still a question about creating the original slice. Should I do it from the backend to the frontend, or the other way around (UI first)?</p>
<p>I prefer the second one, as it suits me better, but also, I think it&#8217;s better aligned with the original intention: To implement something visible &#8211; at that moment it is pretty much like a prototype &#8211; and then extending it backwards: adding the communication layer first, then the server side, then the database. (or just filling in the already created empty objects)<br />
With a few notable exceptions, most of what we do must be visible for the/a user. Therefore, upfront UI development acts as a second layer of test driven development, with the developer as the testing framework. </p>
<p>Thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2012/02/07/slice-forward/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Everyday I&#8217;m shufflin&#8217;</title>
		<link>http://www.lusta.hu/2011/10/12/everyday-im-shufflin/</link>
		<comments>http://www.lusta.hu/2011/10/12/everyday-im-shufflin/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 12:10:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Szakmai]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1197</guid>
		<description><![CDATA[Az elmúlt hetekben pályafutásom egyik legérdekesebb feladatával foglalkoztam a munkahelyen. Konkrétumokat nem akarok írni, de egy Amazon-os példával szemléltetem, miről is van szó. Tegyük fel, hogy az Amazon be akar vezetni egy újféle rendezést: Ha a felhasználó úgy keres, hogy nem specifikálja, mi szerint akar sorbarendezni, akkor egy relevancia szerinti sorbarendezést kap. Az első feltétele [...]]]></description>
			<content:encoded><![CDATA[<p>Az elmúlt hetekben pályafutásom egyik legérdekesebb feladatával foglalkoztam a munkahelyen. Konkrétumokat nem akarok írni, de egy Amazon-os példával szemléltetem, miről is van szó.</p>
<p>Tegyük fel, hogy az Amazon be akar vezetni egy újféle rendezést: Ha a felhasználó úgy keres, hogy nem specifikálja, mi szerint akar sorbarendezni, akkor egy relevancia szerinti sorbarendezést kap.</p>
<p>Az első feltétele ennek, hogy meghatározzuk, a user milyen szegmens része: Ha korábban főleg technikai kütyükre keresett, akkor vsz. fiatal férfi, míg ha babaruhákat és melltartót vásárolt, akkor jó eséllyel családanya.</p>
<p>A következő lépés annak a meghatározása, hogy melyik szegmens mit szeret és mit nem. Ha például mobiltelefonokat nézünk, akkor a <span style="text-decoration: line-through;">nerd-öt</span> technikailag orientált férfit jobban érdekli a felbontás, mint a készenléti idő, míg a családanya inkább egy ütés, por és víz (nyál) álló telefont értékel, ami túléli a gyerekek támadását.</p>
<p>A fentiek meghatározása után elkészítjük az első komponenst, ami minden szegmenshez meghatároz egy ratinget az adott dologra. Pl. minden egyes telefonra megmondja, hogy az első szegmensnél a felbontásra kap X pontot, az ütésállóságra meg Y pontot, így az össz ratingje X+Y, és ez így tovább a többi szegmensre. Utána már csak annyi dolgunk van, hogy ha valaki rákeres a mobiltelefonokra, akkor &#8211; ha kb. tudjuk, ő milyen szegmensben van &#8211; akkor a találati listát az adott szegmenshez kapcsolt rating érték alapján csökkenő sorrendbe rendezzük (feltételezve, h a nagyobb rating a jobb).</p>
<p>Eddig nem túl bonyolult a dolog. Itt jön azonban a csavarás: Mi van akkor, ha a user &#8211; pl. amiatt, mert a héten minden HTC telefonra 10% leértékelés van &#8211; hirtelen csak HTC-ket kezd el látni a találati listában? Ez számunkra nem olyan kívánatos, mert mi azt szeretnénk, ha a felhasználó sokfélét látna ott &#8211; ugyanis simán lehet, hogy az adott felhasználó titokban utálja a HTC telefonokat, és tulajdonképpen Samsungot szeretne, de ezt nem tette bele a keresésbe valamilyen okból. Ez az, amit nálunk shuffling-nek hívnak, azaz keverésnek: Fogjuk a találati listát, és átrendezzük úgy, hogy a találatok változatosak legyenek.</p>
<p>Az első megfigyelés az, hogy ezt a keverést mindenképpen a találati listán kell megcsinálnunk, mivel ez keresésenként változik, és látatlanban nem tudjuk előre átrendezni a hasonló találatokat. A felhasználói szokásokat ismerve az is elég valószínű, hogy nem kell az összes találatot átrendeznünk, hiszen a felhasználó ritkán néz meg két oldalnál többet. Az is fontos, hogy ha a keresés pl. egy adott gyártóra történt (mondjuk Samsung) akkor ne erőlködjünk azon, hogy a gyártók szerint is sorbarendezzünk. Hasonlóképpen, ha a listának mondjuk 95%-a ugyanaz a gyártó, akkor szintén értelmetlen a keverés. Továbbá, feltételezhetjük, hogy a vásárló számára értékesebb az, ha minél változatosabb a lista, tehát azt is jó lenne elkerülni, hogy kétféle dolgot váltogassunk (HTC, apple, HTC, apple), ha a listában van mondjuk Samsung és Motorola is.</p>
<p>Van itt azonban egy érdekes kérdés: Ha már 1x berendeztük aszerint, hogy ezek az elemek milyen jók a usernek, akkor most nem vágjuk ezt teljesen felül azzal, hogy megkeverjük? A válasz kettős: Igen, alaposan megbolygatjuk a sorrendet, és nem, nem teljesen vágjuk felül. Lehetőség szerint úgy kell rendeznünk, hogy a találatok az eredeti sorrendhez a lehető legközelebb maradjanak. Ennek az eszköze lehet az algoritmushoz hozzácsapott maximum mélység, ami arról szól, hogy megmondjuk, hogy az átrendezendő elemekre &#8211; ami mondjuk a találati lista első 100 eleme &#8211; definiálunk egy %-ot, hogy ennél messzebbről ne rángassunk fel elemet semmiképp.</p>
<p>Erre alkottam egy algoritmust, amelyre a következő dolgok igazak: A rekord 1 mezőjére vizsgál, aszerint ha 2 azonos rekordot talál, akkor a találati listából maximum a meghatározott mélységen belül elővesz egy olyat, ami eddig arányosan a legritkábban volt használva. Ugyanolyan ritkaság esetén az eredeti halmazban gyakrabban előforduló elemből vesz. Az algoritmus szekvenciális, a feldolgozott elemeket már nem változtatja, csak a még keveretlen listát.</p>
<p>Hogy néz ki a végeredmény? 15 elemre, 20%-os mélységgel (max 3 elem) az alábbi előfordulásokkal az alábbi eredményeket kapjuk: (bal oldalon az eredeti lista, jobb oldalon a kevert)</p>
<pre>Value distribution:
<ul>
<li>HTC     : 60%</li>
<li>Apple   : 13%</li>
<li>Samsung : 26%</li>
</ul>
<pre>     Index   Make      Index   Make
      ------------------------------
       1, Samsung        1  Samsung
       2,   Apple        2    Apple
       3,     HTC        3      HTC
       4,     HTC        6  Samsung
       5,     HTC        4      HTC
       6, Samsung        5      HTC
       7,     HTC       10  Samsung
       8,     HTC        7      HTC
       9,     HTC       11    Apple
      10, Samsung        8      HTC
      11,   Apple        9      HTC
      12,     HTC       13  Samsung
      13, Samsung       12      HTC
      14,     HTC       14      HTC
      15,     HTC       15      HTC</pre>
<p>Hosszabb listákra nyilván sokkal hatékonyabb, de szerintem így is látszik a különbség.</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/10/12/everyday-im-shufflin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Schema TDD</title>
		<link>http://www.lusta.hu/2011/09/13/schema-tdd/</link>
		<comments>http://www.lusta.hu/2011/09/13/schema-tdd/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 11:59:37 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[schema]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1189</guid>
		<description><![CDATA[Az alábbi feladatot kaptam nemrég: Készíteni kell egy sémát egy új web service-hez. Maga a feladat nem túl bonyolult, de egy idő után belefutottam abba, hogy elkezdtem összekeverni, hogy melyik hierarchia szinten melyik adatot ábrázolom, mire hol van szükség. Ígyhát megszületett az ötlet: csinálok egy XML-t, ami formailag megfelel annak, amit szeretnék, és addig javítom [...]]]></description>
			<content:encoded><![CDATA[<p>Az alábbi feladatot kaptam nemrég: Készíteni kell egy sémát egy új web service-hez. Maga a feladat nem túl bonyolult, de egy idő után belefutottam abba, hogy elkezdtem összekeverni, hogy melyik hierarchia szinten melyik adatot ábrázolom, mire hol van szükség.</p>
<p>Ígyhát megszületett az ötlet: csinálok egy XML-t, ami formailag megfelel annak, amit szeretnék, és addig javítom a sémát, amíg validálható az xml. Ez meg is történt, utána nekiálltam a sémát szépítgetni, hogy megfelelő típusok, required attribútumok legyenek. Aztán nekiláttam a következő változtatásnak, először átírva az XML-t, &#8230;</p>
<p>Ekkor realizáltam, hogy gyakorlatilag a TDD lépéseit ismétlem. Írok egy tesztet &#8211; a formailag helyes XML.  Utána lefuttatom a tesztet &#8211; validálás &#8211; ami piros lesz. Utána addig javítom a sémát, amíg a validálás nem sikerül &#8211; development. Majd szépítgetem a sémát &#8211; refaktorálás. Végül iterálok.</p>
<p>Érdekes élmény volt <img src='http://www.lusta.hu/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/09/13/schema-tdd/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Securing NIO &#8211; Java SSL tutorial</title>
		<link>http://www.lusta.hu/2011/07/25/securing-nio-java-ssl-tutorial/</link>
		<comments>http://www.lusta.hu/2011/07/25/securing-nio-java-ssl-tutorial/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 14:18:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1160</guid>
		<description><![CDATA[Basic socket communication Writing a client/server application communicating over sockets is pretty easy in Java. The server creates an instance of the aptly named ServerSocket class, which waits for incoming connections. The client creates a Socket instance, which then connects to the server (thus creating another Socket on the server side via the accept method [...]]]></description>
			<content:encoded><![CDATA[<h2>Basic socket communication</h2>
<p>Writing a client/server application communicating over sockets is <a href="http://download.oracle.com/javase/tutorial/networking/sockets/clientServer.html">pretty easy</a> in Java. The server creates an instance of the aptly named ServerSocket class, which waits for incoming connections. The client creates a Socket instance, which then connects to the server (thus creating another Socket on the server side via the accept method of the ServerSocket), and that&#8217;s it. Although Sockets are normally blocking read operations, it is easy to emulate a single threaded non-blocking communication with simply checking the available bytes on the socket, and reading only that much.</p>
<h2>Blocking secure socket communication, the problem</h2>
<p>Switching to a secure socket connection is <a href="https://www.ibm.com/developerworks/java/tutorials/j-jsse/">very easy</a>: First, you need to <a href="http://code.google.com/p/keytool-iui/">create some keystores</a>, then some initialization in the code and then you can use some factory classes to create the secure sockets instead of the original constructor calls. Everything else is almost the same.. except..</p>
<p>Getting the number of available bytes are not reliable any more. The reason is simple: As your security and application data arrives in the same stream, the security engine is not able to tell the amount of available application bytes without trying to decrypt everything, but that is a complex operation. Probably more complex and requires more effort than you would like to have in an infinite loop.</p>
<p>Because of this, our workaround for blocking communication is not usable anymore. For a simple application with just one or a handful of clients it is acceptable to have a separate thread for all of the connected clients on the server side, but we need another solution for high user counts.</p>
<h2>SocketChannels</h2>
<p>Java NIO has a nonblocking socket solution. SocketChannels are designed for this. Because of the fundamentally different usage and the additional classes, such as Selectors, most people never uses them, but they are not overly complex, and with a little practice can be used easily. For beginners, I&#8217;d recommend reading this article: <a href="http://rox-xmlrpc.sourceforge.net/niotut/">Rox Java NIO Tutorial</a>. It&#8217;s probably not the easiest to understand, but contains very useful tips and explains typical pitfalls.</p>
<p>Using this, we solve the issue with the blocking channels, but security is still lacking. The bad news is: It is pretty hard to make SocketChannels secure. This is your second chance to turn back, and use the blocking solution, they say<a href="http://java.dzone.com/news/how-get-c-performance-java"> a few thousand threads are not really a problem</a> for a good server <img src='http://www.lusta.hu/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<h2>Securing SocketChannels</h2>
<p>Ok, you are desperate. You want &#8216;em non-blocking channels communicate securely. Here is what you need to add to the code:</p>
<ol>
<li>You don&#8217;t need to do anything with the ServerSocketChannel, and the way it accepts connections.</li>
<li>I prefer doing the reading and writing in a separate class, which &#8220;owns&#8221; the connection and the SSLEngine. (See Below)</li>
<li>Initialize your security.</li>
<li>On the server side, for every new socketchannel, create a new SSLEngine.</li>
<li>On the client side, do the same for your one channel.</li>
<li>Initiate the handshake.</li>
<li>After the handshake, wrap everything you want to send and unwrap everything that you receive on both sides.</li>
</ol>
<p>So far it is not too complex, right? Let&#8217;s dig deeper.</p>
<p>Initializing security:</p>
<pre>private void setupSecurity() {
	SecureRandom secureRandom = new SecureRandom();
	secureRandom.nextInt();

	KeyStore clientKeyStore = KeyStore.getInstance("JKS");
	clientKeyStore.load(new FileInputStream("client.jks"), "KeyStorePassword".toCharArray()); 

	TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
	tmf.init(clientKeyStore);

	KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
	kmf.init(clientKeyStore, "KeyInKeystorePassword".toCharArray());

	sslContext = SSLContext.getInstance("TLS");
	sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), secureRandom);
}</pre>
<p>Couldn&#8217;t be more straightforward. Creating an SSLEngine is just as easy:</p>
<pre>SSLEngine engine = sslContext.createSSLEngine();</pre>
<p>And now the handshake.. You can find a lot of explanations <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#SSLENG">here</a> (it&#8217;s a bit dry, but very useful). The scaffolding for the code can be found in the same article, but you are better off if you check the code here: <em>[jdk home]\sample\nio\server\ChannelIOSecure.java</em></p>
<p>It is very complicated, and there is a hidden &#8220;flaw&#8221;: It&#8217;s meant to be used with blocking channels. (See below). Also, some structures are a bit more complex than I&#8217;d usually like it, for example the 3 levels deep switch constructs. Anyway, for now you should just try to copy it as closely as you can, and if you can make it work, then you can improve the code as much as you want.</p>
<h2>The problems I faced</h2>
<p>Obviously, it didn&#8217;t work for me the first time I tried. Here are some tips:</p>
<ul>
<li>Don&#8217;t give up. It&#8217;s complex and ugly, but it can be done.</li>
<li>If the handshake doesn&#8217;t start, and/or the server complains about plaintext connection, insert the engine.beginHandshake() line before the handshake process. Sometimes the only issue that you see is that the clients sends the messages and the server simply absorbs them without any apparent effect.</li>
<li>If you get repeated buffer underflow errors on the server side, and using non-blocking communication, it&#8217;s time to add a new check for zero length reads. Trying to unwrap zero length ByteBuffers can cause this issue.</li>
<li>In case of unsupported record version problems or sequence violation (during the handshake) try to empty your buffers before you read/unwrap into them and after you have sent them to the other party. Leftover bytes can cause this issue. (<em>Unsupported record version Unknown</em>) (<em>Handshake message sequence violation</em>)</li>
<li>If the server/client complains about invalid handshake mac, check your flushing code. You may loose some important bytes. (<em>bad handshake record MAC</em>)</li>
<li>Google is your friend: There are a lot of people out there who solved the same issues and wrote an article about it.</li>
<li>It&#8217;s a good idea to add some logging to the code to see what is happening. It helps you to see the sequence of events on both sides.</li>
<li>There are some issues and solutions <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#Troubleshooting">here</a> I didn&#8217;t face. Still, you may see them.</li>
</ul>
<p>I hope this will help some of you to develop some great, secure applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/07/25/securing-nio-java-ssl-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Az Önbizalom Vására</title>
		<link>http://www.lusta.hu/2011/06/07/az-onbizalom-vasara/</link>
		<comments>http://www.lusta.hu/2011/06/07/az-onbizalom-vasara/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 09:44:04 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1153</guid>
		<description><![CDATA[Tegnap két extrém példán keresztül tudatosult bennem, hogy mennyire az önbizalomról szól a szakma. Nem csak arról, természetesen, de talán egy kicsit nagyobb a jelentősége, mint pl. a kézműves vagy szolgáltató iparban. Az első példa: Van egy ismerősöm (igen, N, rólad írok) akinek a CV-jét javítgattuk tegnap. 7 éve dolgozik az IT supporton, olyan technológiákkal [...]]]></description>
			<content:encoded><![CDATA[<p>Tegnap két extrém példán keresztül tudatosult bennem, hogy mennyire az önbizalomról szól a szakma. Nem csak arról, természetesen, de talán egy kicsit nagyobb a jelentősége, mint pl. a kézműves vagy szolgáltató iparban.<br />
Az első példa: Van egy ismerősöm (igen, N, rólad írok) akinek a CV-jét javítgattuk tegnap. 7 éve dolgozik az IT supporton, olyan technológiákkal dolgozik, amiről én még nem is hallottam, és a CV ennek megfelelően elég meggyőző. Az önbizalma azonban nem üti meg azt a szintet, amit én természetesnek gondolnék ennyi tapasztalattal, így megragadt egy olyan állásban, ami nem díjazza megfelelően a képességeit.<br />
A második példa: Olvastam egy cikket a <a href="http://thedailywtf.com/Articles/Divine-by-Zero.aspx">Daily WTF</a>-on, ahol egy szörnyű kódrészlet mellett ott szerepel ez a szöveg: &#8221; those who knew better (i.e. management) sang plenty of praise, of both the PHP God, and his clean, well-commented code.&#8221;, azaz nyers fordításban: A vezetőség viszont egyaránt dícsérte a PHP Istent (a fent emlegetett kód alkotója) és annak tiszta, szépen kommentezett kódját.<br />
Tehát, van egy hozzáértő de nem túl sikeres, és egy béna, de nagyra tartott szakmai dolgozó. Na, ez miért van így?<br />
Képzeld el, hogy kijön a burkoló, újraburkolja a fürdőszobádat. Bemész és körülnézel, a csempék ferdék, a színek rondán vannak összeválogatva, és elfelejtett lyukat hagyni a szellőzőnek. Viszont a vizet nem ereszti át, tehát ebből a szempontból tökéletesen megfelel a követelményeknek.<br />
Nyilvánvaló, hogy ezt nem hagynád annyiban, és meglenne a véleményed az illetőről. Viszont, képzeljük el, hogy vak vagy, és ugyanígy megnézed a dolgozó munkáját.. valamilyen módon meg tudsz győződni róla, hogy nem szivárog a víz (például úgy, hogy az alsó szomszéd nem jön fel), de azt már nem tudod megmondani, hogy rondák a színek, szóval örülsz, h kész a fürdőszoba és azt tudja, amit kell.<br />
Ez az utóbbi a helyzet a szakmánkban. A vezetőség a legtöbb helyen nem ex informatikia dolgozókból áll, így max annyit tudnak megmondani a kódról, hogy &#8220;de szép színes betűk vannak benne&#8221;. Ők csak annyit néznek, hogy a weblap megjelenik, az adatbázisszerver működik, az appszerver kiszolgálja a kéréseket, azt már nem tudják igazából felmérni, hogy a táblázattal formázott, nem valid html mennyire nem karbantartható, nem tudják, hogy az adatbázisszervert nem meri senki három éve kikapcsolni, mert nem bíznak benne, hogy újra bekapcsolódik, sít. Itt jön az, hogy a barátságos, mindenre bólogató, gyorsan szállító programozót mindenki kedveli, a rendszergazdát, aki csendben végzi a dolgát, senki észre sem veszi, amíg valami el nem romlik, akkor pedig lekiabálják a haját..<br />
Az Önbizalom Vására &#8211; a személyiség legalább annyit számít, mint a tudás.</p>
<p>A konstruktivitás világnapjának a jegyében nézzünk rá arra, hogy mi adhat nekünk okot az önbizalomra. A vezetőség elismerése? Nem, az nem szakmai elismerés. Nekem a következő dolgok adnak önbizalmat:<br />
- Sokféle helyzetben voltam már, és még soha nem kellett feltennem a kezem, hogy: &#8220;Ezt nem lehet megoldani, és fogalmam sincs, hogy mit kellene most csinálnom&#8221;. Volt, hogy sokat szenvedtem a megoldással, de mindent sikerült megoldani vagy megkerülni.<br />
- Tudom, hogy a szakma olyan széleskörű, hogy senki nem tudhat mindent, de ha bármire szükségem van, meg tudom tanulni, mert megvan a szakmai alapom hozzá.<br />
- Kapok pozitív visszajelzéseket a munkámról olyan emberektől, akiket magamnál okosabbnak, szakmailag tapasztaltabbnak tartok.</p>
<p>Minden kollégámnak ajánlom az IT bármely területén, hogy nézzen magába néha, és gondolkozzon el, hogy helyén van-e az önértékelése? Akár csak a fenti három pontot és gondolja végig őket őszintén. Sokat lendítene a szakma színvonalán egy kis tisztánlátás..</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/06/07/az-onbizalom-vasara/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Static Dependency Injection &amp; AOP</title>
		<link>http://www.lusta.hu/2011/06/02/static-dependency-injection-aop/</link>
		<comments>http://www.lusta.hu/2011/06/02/static-dependency-injection-aop/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 13:04:28 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[annotation]]></category>
		<category><![CDATA[aop]]></category>
		<category><![CDATA[apt]]></category>
		<category><![CDATA[dependency injection]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1139</guid>
		<description><![CDATA[Alapvetően két problémám van a DI-t és AOP-t megvalósító framework-ökkel: Hozzá kell adni egy extra jar-t a classpathhoz, amitől sokkal combosabb lesz az egész alkalmazás, és ha esetleg webstartozol, akkor még sign-olni is kell, valamint van egy performance hit &#8211; A DI a startupnál, az AOP pedig folyamatosan jelentkezik. Vannak ugyanakkor olyan problémák, amit így [...]]]></description>
			<content:encoded><![CDATA[<p>Alapvetően két problémám van a <a href="http://en.wikipedia.org/wiki/Dependency_injection">DI</a>-t és <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">AOP</a>-t megvalósító framework-ökkel: Hozzá kell adni egy extra jar-t a classpathhoz, amitől sokkal combosabb lesz az egész alkalmazás, és ha esetleg webstartozol, akkor még sign-olni is kell, valamint van egy performance hit &#8211; A DI a startupnál, az AOP pedig folyamatosan jelentkezik.<br />
Vannak ugyanakkor olyan problémák, amit így lehet a legszebben megoldani, például a logolás elválasztása a függvényeinktől, vagy egy Chain of Command pattern esetén a Command osztályok inicializálása és a chain-be rakása. </p>
<p>A minap, amikor a javas Annotation-ökről olvastam, belefutottam az általam korábban még soha (tudatosan) nem használt <a href="http://download.oracle.com/javase/1.5.0/docs/guide/apt/GettingStarted.html">apt (Annotation Processing Tool)</a> nevű eszközbe. Ahogy olvasgattam a képességeiről, felmerült bennem, hogy ezzel meg lehetne oldani azt, amit én statikus DI-nak és statikus AOP-nek hívok.</p>
<p>Az apt lényege, hogy &#8211; főként az annotációkat használva, de generálisan is &#8211; fordítás előtt átszalad az egész kódon, és meghív bizonyos, a felhasználó által specifikált feldolgozó egységeket, amik átalakíthatják a kódot, vagy hozzáadhatnak új osztályokat, etc. Gyakorlatilag beteszünk egy extra lépést a kód elkészítése és lefordítása közé.<br />
Valami ilyesmi a statikus AOP lényege: Bár kód szinten elszeparáljuk a különböző dolgokat, például a logolást, és pusztán egy annotationnel jelöljük, hogy ez a metódus kellene, hogy logoljon (@LoggingMethod, pl.), a lefordított osztályokban már megjelenik az a kód. Hasonlóan működik a DI is.</p>
<p>Például: Össze akarom gyűjteni az összes Command osztályt egy List<Command> -ba.<br />
Csinálok két annotációt és egy statikus függvényt, mondjuk <em>registerCommand(Command c)</em>. A függvény feladata mindössze annyi, hogy a fenti listába belerakja a Command osztályt (és csinál vele minden egyebet, amit csak akarunk), az annotációk pedig kb. így néznek ki:</p>
<p><code>
<pre>
@Target(ElementType.TYPE)
public @interface CollectionMarker {
    String collection();
    String enabled() default true; // erről meg ejtek pár szót
}</pre>
<p></code></p>
<p><code>
<pre>
@Target(ElementType.METHOD)
public @interface CollectionMethod {
    String collection();
}</pre>
<p></code></p>
<p>Az utóbbit elhelyezem a fenti függvényen, az előbbit pedig minden egyes Command osztályon, amit megírok.</p>
<p>Ezután a processzorok úgy működnek, hogy az egyik összegyűjt egy listát az összes CollectionMarkerrel megjelölt osztályról, a másik megjegyzi, hogy hol a CollectionMethod, majd a feldolgozás végén a megjegyzett osztályba berakunk egy static initializer blokkot, amibe belekerül egy csomó <em>registerCommand(new AkarmilyenCommand());</em>. S lőn, kész is van a chain.</p>
<p>Amit vesztünk ezzel, az<br />
- A dinamikusság: Nem elég átírni egy XML-t és újraindítani az alkalmazást, mint a Spring-nél, ha változtatni akarunk valamit a dependencián. Mindenképpen újra kell fordítanunk az alkalmazást.<br />
- Fordítási sebesség: A fordítás valamivel lassabb lesz<br />
- Rugalmasság: Nyilvánvalóan van egy csomó olyan DI alkalmazás, amit nem lehet megoldani statikus módon.</p>
<p>Amit nyerünk vele:<br />
- Némi performancia<br />
- Átlátható kód extra frameworkok nélkül<br />
- A Spring XML-hez viszonyítva: compile time ellenőrzés a dependenciákra<br />
- Automatizált taszk végrehajtás (Az új command hozzáadása esetén csak az osztály kell létrehoznunk és ellátnunk a megfelelő annotációval, nem kell még különböző ponton beszúrni listákba)</p>
<p>Említettem fent, hogy az enabled attribútumról még ejtek pár szót: ha a gyűjtő egység figyeli ennek is az értékét, és nem gyűjti be azokat, ahol az enabled értéke false, akkor ennek a kapcsolónak az átbillentésével ki-be kapcsolhatjuk a gyűjtését. Akár még azt is megtehetjük, hogy a true-false helyett szinteket definiálunk, és bizonyos osztályokat csak debug módban használunk, productionben nem (ezeket, ha jól sejtem, akár ki is törölhetjük a feldolgozás során..).<br />
Ez így magában még nem is annyira érdekes, de van még egy ennél is fontosabb szerepe: ha a fenti annotation definiciót (a Markert) megfejeljük egy @Inherited annotációval, akkor a leszármazottak is öröklik. Innentől elvileg minden leszármazottat begyűjtünk.. kivéve, ahol specifikusan kitesszük a markert a az enabled attribútum értékét false-ra állítva. </p>
<p>Akik az IDE integráció miatt aggódnak, azoknak sem kell igazából. Az Eclipse-t biztosan tudom, hogy támogatja ezt, a Netbeans és IDEA esetén pedig csak sejtem, hogy támogatják ezt a dolgot (vsz. 5 perc lenne kideríteni a google-lel).</p>
<p>Egyelőre csak a fejemben született meg ez a dolog, nem valósítottam meg, de a horizonton van. Ha lesz konkrétum, vsz kirakom valami elérhető helyre, mondjuk google code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/06/02/static-dependency-injection-aop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ezt mindig elfelejtem</title>
		<link>http://www.lusta.hu/2011/01/26/ezt-mindig-elfelejtem/</link>
		<comments>http://www.lusta.hu/2011/01/26/ezt-mindig-elfelejtem/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 10:06:40 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1030</guid>
		<description><![CDATA[Már többször szükségem volt rá, de mindig elfelejtem a konkrét formátumot, és kísérleteznem kell, h újra meglegyen, úh leírom most ide: set TT=%DATE:/=%%TIME: =% set TT=%TT::=% set TT=%TT:.=% Ez a három Windows Shell parancs összerakja neked a dátumot és az időt, majd kiheréli belőle a problémás karaktereket. Én jellemzően buildfile-ok elnevezéséhez szoktam használni, pl. így: [...]]]></description>
			<content:encoded><![CDATA[<p>Már többször szükségem volt rá, de mindig elfelejtem a konkrét formátumot, és kísérleteznem kell, h újra meglegyen, úh leírom most ide:<br />
<code>set TT=%DATE:/=%%TIME: =%<br />
set TT=%TT::=%<br />
set TT=%TT:.=%</code><br />
Ez a három Windows Shell parancs összerakja neked a dátumot és az időt, majd kiheréli belőle a problémás karaktereket. Én jellemzően buildfile-ok elnevezéséhez szoktam használni, pl. így:<br />
<code>ant tgt > build%TT%.log</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2011/01/26/ezt-mindig-elfelejtem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programozok a padlon</title>
		<link>http://www.lusta.hu/2010/12/15/programozok-a-padlon/</link>
		<comments>http://www.lusta.hu/2010/12/15/programozok-a-padlon/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 17:46:06 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[humor]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=1006</guid>
		<description><![CDATA[Megint olyan munkam van, hogy rengeteget buildelek, ugyhogy szamtalan, programozassal kapcsolatos cikket olvastam el az elmult napokban. Ime a legszorakoztatobb: http://www.junauza.com/2010/12/top-50-programming-quotes-of-all-time.html Vicces programozassal kapcsolatos idezetek. A kedvencem: 32. &#8220;The evolution of languages: FORTRAN is a non-typed language. C is a weakly typed language. Ada is a strongly typed language. C++ is a strongly hyped language.&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Megint olyan munkam van, hogy rengeteget buildelek, ugyhogy szamtalan, programozassal kapcsolatos cikket olvastam el az elmult napokban.</p>
<p>Ime a legszorakoztatobb: <a href="http://www.junauza.com/2010/12/top-50-programming-quotes-of-all-time.html">http://www.junauza.com/2010/12/top-50-programming-quotes-of-all-time.html</a></p>
<p>Vicces programozassal kapcsolatos idezetek. A kedvencem:</p>
<p><em>32. &#8220;The evolution of languages: FORTRAN is a non-typed language. C is a weakly typed language. Ada is a strongly typed language. C++ is a strongly hyped language.&#8221;</em></p>
<p><em>- Ron Sercely</em><span id="_marker"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2010/12/15/programozok-a-padlon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Másold elé</title>
		<link>http://www.lusta.hu/2010/11/30/masold-ele/</link>
		<comments>http://www.lusta.hu/2010/11/30/masold-ele/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 17:39:51 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=997</guid>
		<description><![CDATA[A programozok egyik kedvenc rossz szokasa a copy-paste. Nagyon konnyu vele hibat rakni a kodba, de mivel sokkal egyszerubb, mint ujragondolni es ujragepelni az egeszet, az emberek elnek vele. Az egyik tipikus eset, amikor en hasznalom, az az, amikor hasonlo feldolgozasi feladatot csinalok ket kulonfele objektumtombre. Pl. String lastname = null; for(Tipus peldany : peldanyLista) [...]]]></description>
			<content:encoded><![CDATA[<p>A programozok egyik kedvenc rossz szokasa a copy-paste. Nagyon konnyu vele hibat rakni a kodba, de mivel sokkal egyszerubb, mint ujragondolni es ujragepelni az egeszet, az emberek elnek vele.</p>
<p>Az egyik tipikus eset, amikor en hasznalom, az az, amikor hasonlo feldolgozasi feladatot csinalok ket kulonfele objektumtombre. Pl.</p>
<pre><code>
String lastname = null;
for(Tipus peldany : peldanyLista) {
  if(lastname == null) {
    peldany.valamilyenFuggveny();
    lastname = peldany.name();
  } else {
    peldany.masFuggveny(lastname);
    lastname = null;
  }
}
</code></pre>
<p>Majd ugyanezt meg akarom csinalni a MasTipusra is, de ott a szintenMas es a megintMas fuggvenyeket fogom hivni, emiatt a generics-es fuggveny sajnos nem megoldas. (ne foglalkozzunk azzal, milyen buta a kod, csak a pelda miatt van itt)<br />
Szoval fogom, atmasolom, atirom benne a dolgokat MasTipusra, es orulok.  A problema csak az, hogy mondjuk elfelejtettem kinullazni a lastname ojjektumot, es emiatt a masodik ciklus egesz mashogy fog viselkedni, mint kene. </p>
<p>Azon lusta programozok szamara, akik hozzam hasonloan elnek neha a copy-paste-tel, egy apro otlet: probaljak ilyen esetben a masik kod ele masolni az ujat. Ha a fenti peldaban a lastname ele masoljuk, akkor a lastname hasznalatat serelmezni fogja a fordito, es eszrevesszuk, hogy egy olyan dependenciat iktattunk be, amit nem kellett volna. Ez termeszetesen nem silver bullet, legfeljebb az esetek 20%-ban mukodik, de az se rossz. Persze, erdemes az egeszet kifaktoralni egy sajat fuggvenybe, es akkor meg olvashato is lesz.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2010/11/30/masold-ele/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mikor van ertelme a code coverage-nek</title>
		<link>http://www.lusta.hu/2010/11/23/mikor-van-ertelme-a-code-coverage-nek/</link>
		<comments>http://www.lusta.hu/2010/11/23/mikor-van-ertelme-a-code-coverage-nek/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 11:36:43 +0000</pubDate>
		<dc:creator>Vagabond</dc:creator>
				<category><![CDATA[Szakmai]]></category>
		<category><![CDATA[code coverage]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lusta.hu/?p=972</guid>
		<description><![CDATA[A code coverage szam, mint olyan, szerintem nem sokat jelent. Huu, 100%-an vegigfutott a kodnak legalabb 1 teszt.. de le is ellenorizte, mit csinal? Azonban a napokban rajottem, hogy mikor van ertelme ennek: A scriptnyelveknel. Csodalatosan ki lehet vele szurni a szintaktikai hibakat &#8211; az eloforditott nyelveknel erre nincs szukseg, hiszen ott a forditassal (gyakran [...]]]></description>
			<content:encoded><![CDATA[<p>A code coverage szam, mint olyan, szerintem nem sokat jelent. Huu, 100%-an vegigfutott a kodnak legalabb 1 teszt.. de le is ellenorizte, mit csinal? </p>
<p>Azonban a napokban rajottem, hogy mikor van ertelme ennek: A scriptnyelveknel. Csodalatosan ki lehet vele szurni a szintaktikai hibakat &#8211; az eloforditott nyelveknel erre nincs szukseg, hiszen ott a forditassal (gyakran a fejlesztessel) egyidoben megy a szintaktikai ellenorzes, de a scriptnyelveknel ez mar nem ilyen egyertelmu.<br />
En most eppen Pythonban irom a keszulo alkalmazasom szerver reszet. Egyszeru, gyors, de scriptnyelv. Erdemes pylint-et hasznalni, es erdemes tesztelni. Ha lenne webes felulete, vsz igen meretes javascript programok is lennenek hozza. Ugyanez a helyzet, van jslint, es kell irni teszteket. </p>
<p>Na, ilyenkor jo a coverage. </p>
<p>Update: Egy kis magyarazat, hogy mirol is beszelek:<br />
<code>public class A() {<br />
  private int a = 5;<br />
  public int getA() { return a; }<br />
  public void setA(int a) {this.a = a; }<br />
}</code></p>
<p>Erre a fentire igy is lehet 100%-os coverage-et csinalni:<br />
<code>@Test<br />
public testA() {<br />
  // given<br />
  setupStuff();</p>
<p>  // when<br />
  aInstance.getA();<br />
  aInstance.setA(8);</p>
<p>  //then<br />
  // ..who cares?<br />
}</code></p>
<p>holott valami ilyesmire lenne szukseg:<br />
<code>@Test<br />
public testA() {<br />
  // given<br />
  setupStuff();<br />
  int firstInt = 34;<br />
  int secondInt = 45;</p>
<p>  // when<br />
  aInstance.setA(firstInt);<br />
  int firstResult = aInstance.getA();<br />
  aInstance.setA(secondInt);<br />
  int secondResult = aInstance.getA();</p>
<p>  //then<br />
  assertTrue(firstResult == firstInt);<br />
  assertTrue(secondResult == secondInt);<br />
}</code><br />
Es akkor tudjuk is, hogy mukodik. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lusta.hu/2010/11/23/mikor-van-ertelme-a-code-coverage-nek/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

