Fontos PDO módosítások

Ezúton (is) felhívjuk partnereink figyelmét, hogy adatbázis kezelő rendszerünkben módosításokat hajtottunk végre. Felhasználóinkat ez nem érinti, ők nem vesznek észre semmit, de fontos, hogy azok a partnerek, akik a mi PDO-nkkal dolgoznak, olvassák el figyelmesen a bejegyzést!

Text és Binary külön. A nagy mennyiségű adatok betöltését a rendszer automatikusan késlelteti, de ezen belül is ketté kellett választani a bináris és szöveges jellegű adatok betöltését. Egy olyan adathalmazban, ahol képek és szövegek is vannak, egy-egy szöveg mező tömeges módosítása az összes termék képének betöltését hozta magával. Ez így nem (volt) jó. A módosítás tesztelése folyamatban van.

Adatmódosulás feliratkozások. Az adatok módosulása esetén a feliratkozott más adatok feleslegesen kaptak nagyon sok értesítést (delegates and events), amely általában csak a kód minőségét rontotta, némely esetben – komoly – erőforrás problémákat is okozhatott.

Adatok trimmelése. Akár ügyviteli, akár egyéb adattárolási oldalról nézzük, logikus lépés az adatok trimmelésének (kezdő szóközök és szöveg közbeni többes szóközök kezelése) beállítása. Felhívjuk partnereink figyelmét, hogy ez az adatátadásban körültekintést igényel, emiatt konzultációt biztosítunk.

Hazánkban már több, mint 10 cég használja keretrendszerünket szoftvereinek egyszerűbb és gyorsabb fejlesztésére.

Hangok a Symbol Ügyvitelben

A kezdetek kezdetén elhatároztuk, hogy nem lesznek hangok a Symbol Ügyvitelben, de most eljött ez a pillanat is. Elmesélek egy történetet, ami megvilágítja, hogy miért félek a hangoktól.

Pályafutásom kezdetén, a CCS Hungary Kft-nél szoftverrendszert fejlesztettünk, amely a légitársaságokat és a Malév-ot szolgálta ki. Egyik funkciója volt a csomagok gépre rakása. Ha a gép indulása előtt negyed órával volt még függőben lévő csomag, akkor különleges figyelmeztetést kellett megjeleníteni.

Jött a korszakalkotó ötlet, hogy ne csak vizuális, hanem “audiális” is legyen a figyelmeztetés. A villogó piros mellett 5mp-enként hangot is adott. Kis sípolós kattanás. A szoftver rendben volt, vittük telepíteni.

A telepítésnél ott voltam, ezért én kaptam az első “pofont”. Az automatikus frissítő rendszer kb. 30 gépre lerántotta az alkalmazást és a felhasználó tényleges feladatától függetlenül minden gépen jelzett a csipogó. 5mp-enként szólalt meg ugyan, de 30 számítógép esetén ez 6csipogás/mp-es ütemezést jelentett. Egy nagy terem, ami csipog. A csipogás mellett már sikítottak is a kollégák. Nagy zűrzavart okoztunk :)

Szóval ezért nem szeretjük a hangokat. De az üzleti felhasználás most megkövetelte. A felugró emlékeztető (Partnerkapcsolat modul) és az átküldött jegyzet (Sticky-note) hangot ad, amikor megjelenik. Reméljük, nem lesz belőle hangorkán.

SaaS – Akkor ez most a Symbol Ügyvitel API?

SaaS működésünk megjelenése előtt számos céggel beszélgettünk róla, hogy ez a működés, akkor most mennyire van kész, ez most akkor gyakorlatilag egy API? A válasz az, hogy ez egy DynamicAPI. Teljes API-t nem lehet csinálni, de bármely része percek/órák alatt implementálható.

Mi is az API?

Az API egy függvénytár, amely egy rendszer kívülről elérhető funkcióit engedi megszólítani. Kis vagy közepes funkcionalitás esetén az API annyi megszólítható “dolgot” tartalmaz, amennyit két kezünkön meg tudunk számolni. Példaképpen említhetjük a POP3 vagy IMAP parancsokat, amelyek a levelek letöltését, üzenettörzs letöltését, üzenetek törlését valósítja meg. Nem is kell többet.

Ugyanilyen a Google Docs API, amely dokumentumok tárolását szolgálja. A műveleteknél nem is vágyunk többre, mint dokumentum feltöltése, letöltése, törlése, áthelyezése és egy gyors keresőszolgáltatás a dokumentumok tartalmában (ez utóbbi nem is biztos, hogy része a rendszernek, de ha már Google, akkor talán igen)

SaaS

Egy összetett (nem bonyolult, hanem komplex) rendszer esetében egy teljes API legalább annyi műveletet tartalmaz, mint ahány főmenüpontja van, a paraméterek száma is több tízre tehető. Ez nyilvánvalóan nem valósítható meg, pontosabban olyan mértékű ráfordítást igényel, amely nem térül meg.

Ehelyett a dolog méregfogát úgy húztuk ki, hogy egy önálló programozási platformmal lehetővé tettük bármilyen API megírását. És mindezt ingyenes eszközökkel. Egy SaaS kompatibilis SyX megírása ahhoz hasonlítható, mintha a Google Docs adatbázisához hozzáférünk (saját adataimat nem rejtsék el előlem) és saját lekérdezéseket írhatunk. A lekérdezéseket egy szabványos hozzáférési rétegen (HTTP) kivezetjük, hogy az azt felhasználó kollégáknak ne kelljen valami újat megtanulniuk.

Nézzünk erre egy példát!

Szükségünk lenne egy termékhez tartozó készletinformációra. Ezt egy külső program (amely a weboldalt frissíti) fogja felhasználni. Programozási nyelve lehet PHP, Delphi, C++ vagy C# is. Triviális megoldás, ha az adatbázisból közvetlenül lekérdezzük ezeket az információkat. (Ügyfélszolgálatunk támogatást nyújt a szükséges adatok helyének megismerésében). Ez a megoldás azonban közvetlen adatbázis kapcsolat igényel, amely közepes méretű cégeknél nem megoldható. Emellett külön kell azzal foglalkozni, hogy a fent jelölt programozási nyelvek miként kapcsolódnak az adatbázishoz. Helyette valósítsuk meg a dolgot két lépésben!

1. lépés: SaaS funkció létrehozása.

Hozzunk létre ingyenes fejlesztőeszközzel egy SyX-et, amely SaaS működésre alkalmas. A fenti művelet kiszolgálására készítsünk egy metódust, amely egy termékkódot vár és egy opcionális dátum paraméterrel hívható meg. A metódus “magja” kb. 8-12 programsor segítségével a beérkezett kérést ki tudja szolgálni a megfelelő táblákból történő lekérdezéssel. Végeredményként visszaadja az összes raktárt és benne a készletet, ahol a termék eddig megfordult. Fontos megjegyezni, hogy a bemenő URL feldolgozását nem nekünk kell elvégezni, sőt az eredmény formátumát sem nekünk kell meghatározni, azokat a SaaS definiálja (XML lesz).

2. lépés: SaaS funkció hívása.

Következő lépésben a Symbol Ügyvitel által használt webszervertől le tudjuk kérni a https://localhost/GetWarehouseBalance meghívásával a raktárkészlet információkat. Az URL meghívása szinte programozási nyelv függetlenül megtehető, minden nyelv tartalmaz weboldalról való letöltést megvalósító funkciókat. A visszaadott érték lehet XML formátumú, esetleg JSON, sőt teljes HTML weboldal is, ha az URL-t böngészőn keresztül kívánjuk elérni.

A fenti példán keresztül jól látható, hogy miért nem egy teljes API-t valósítottunk meg, mennyire szerteágazó lenne az ügyfelek minden igényét egy API-ban kielégíteni. Helyette azt a megoldást választottuk, hogy szabványos platformot hoztunk létre, amelyben mindenki a saját API-ját elkészítheti a saját adatai feletti rétegben.

APEH nyomtatványok – Valaki ezeket is megtervezte…

Már eddig is sokat hallottunk róla, hogy az ABEV nevű program itt-ott botladozik. Főleg akkor, amikor SZJA bevallás van és az átlag polgár (aki alap informatikai ismeretekkel rendelkezik) nem találja felhasználóbarátnak. Informatikus szemmel furcsa, hogy ott az a Console ablak, amiben a JAVA JRM ír ki nekem információkat. Felhasználói szemmel még furcsább, hogy egy kitöltött mező értékébe nem tudok belemódosítani, csak az egész törlésével.

A biztosítékot az csapta ki, hogy az ESZIG nyomtatvány mezőnevei az IMP/XML fájlban ugyanolyan véletlenszerűen vannak, mintha egy jó véletlenszám generátort készítenének az adóhatóságnál. (Bocs, helyesen NAV). Néha láttunk benne szabályszerűséget, de a végén nem sikerült semmilyen elvet ráhúzni. Maradt a kódtáblázat, azaz sor+oszlop-hoz hozzárendeltünk egy számot, ami az azonosítója lett a mezőnek.

Kérdésem az, hogy milyen szabályok alapján határozták meg a mezők azonosítóját. Esetleg több lépcsős módosítás során álltak elő a számok? A lényeg, hogy egyelőre sikerül megvalósítanunk a dolgot, de egy publikus API ennél okosabb/logikusabb is lehetne…

Adatbázisunk felhasználása web-es célokra

A Symbol Ügyvitel adatbázisa egy sokat próbált, ingyenesen diszributálható, de fizetős változattal is rendelkező Firebird 2.1 adatbázis motor. Ez egy SQL adatbázis motor, bár sokan azt gondolják, hogy csak a Microsoft-nak van SQL-je, pedig az alábbiak is SQL motorok: Firebird, PostgreSQL, Oracle, MySQL.

Felhasználható-e a Firebird web célokra?

Mivel a Firebird szervernek létezik Linux-os változata (ez is kompatibilis a termékünkkel), telepíthető olyan számítógépre, ahol egy web kiszolgáló (Apache 2.2) is telepítésre került. A két komponens PHP-n keresztük jól megérti egymást. A web-es adatokat lehet Firebird adatbázisban tárolni és onnan kiszolgálni, de nem célszerű.

Alkalmas-e a Symbol Ügyvitel adatbázisa web célokra?

Amennyiben WEB célok alatt olyan működési módot értünk, ami néhány felhasználó számára az összes adat irányába elérhetőséget biztosít, akkor a válasz IGEN. Példa lehet erre egy Ticketing rendszer, ahol cégének ügyfelei belépnek a web-es felületre, ahol azonosítják magukat, majd megnézhetik, hol tart a rendelésük vagy a kért javításuk. Ennek kiszolgálására rendszerünk alkalmas.

Természetesen UTF8/Unicode üzemmódban tároljuk a szöveges adatokat,
így web-es környezetben sem merülhetnek fel ékezet problémák.

Alkalmas-e a Symbol Ügyvitel adatbázis portál célokra?

Ha portál célokra használnák a Symbol Ügyvitel terméktörzsét, NEM javasoljuk a használatot. Egy portál egyetlen oldalának felépítése során sok (>10) lekérdezés fut le. Köztük termékképek, termékcsoportok, készletinformációk, stb. Ezek kiszolgálására nem elég a Firebird adatbázis kezelő. Nem erre találták ki. Pláne, ha 10-20 konkurens felhasználót feltételezünk az oldalon, akik eszeveszetten kattintgatnak egy termék után kutatva.

Az adatbázis állandó?

Külön ki kell térni arra, hogy a Symbol Ügyvitel adatbázisa NEM állandó. Fenntartjuk magunknak a jogot, hogy adatbázisunk formátumát átalakítsuk. Általában bővíteni szoktuk a tárolandó adatok körét, ritkán használunk új mezőként valami olyat, amit kötelező kitölteni (NOT NULL), illetve kivételes esetben szüntetünk csak meg mezőket. A fentiek figyelembe vételével kicsi az esély, hogy egy jól megírt lekérdezés egy új verzióban ne fusson le, de elképzelhető.

Az adatbázis formátumáért külső felhasználási célból felelősséget nem tudunk vállalni,
még akkor sem ha adatbázisunk nyitott, a felhasználók adatait nem rejtjük el.

Akkor mi a megoldás?

Sok helyen (>50) jó megoldást jelent egy saját webáruház működtetése saját adatbázis motorral és ehhez egy illesztőfelület megvalósítása. Mikből lehet választani?

  • osCommerce
  • Joomla + VirtuaMart webáruház motor
  • Saját fejlesztés (PHP, Java, stb.)

Az illesztőfelületre nemsokára elkészül az általános megvalósításunk, aminek segítségével minden webfejlesztő saját webes megoldását (vagy valamilyen ingyenes megoldást) hozzáilleszthet a Symbol Ügyvitelhez. Ehhez cégünk közreműködésére nincs szükség. Szabadon letölthető WebSyX beépülőnk (nemsokára elérhető) szabadon tesztelhető, az általa küldött XML fájlok nyílt formában elérhetőek.

További információk: syx.symboltech.hu

QuickSort – ismét felfedeztük

Elméleti szinten oktatják a rendező algoritmusokat. Sok geek (megszállott) ennek jelentősséget is tulajdonít, pedig már nem számít. Gondoltuk a múlt hétig.

Elmúltak azok az idők, amikor 64kB RAM állt rendelkezésre és nagyon hatékony, gyakorlatilag kihegyezett algoritmust kellett írni mondjuk 200 dolgozó bérszámfejtési adatainak kezelésére. És nem mindenki tudta ezt megcsinálni.
Jelenleg az igazán sok adatot adatbázisokban kezeljük, nem számít a memória, a szerverben legyen sok.

A fejlesztők pedig 4-6 éve (Java-sok régebben) már túlléptek azon, hogy a numerikus analízisben megismert elveket kelljen ismerniük, hogy használható programot készítsenek. Mert beköszöntött a keretrendszerek kora. Ebben minden általánosan használt funkció már megírásra került, sőt eszközök is vannak arra, hogy a hiányzó részeket se tudjuk rosszul megírni (Generics, Interface, etc.)

Jó lenne ha emlékeznék, de nem fog menni. Valamikor a keretrendszer által támogatott rendező algoritmusok (Generic List Sort()) helyett sajátot készítettünk. (Ennek oka, hogy a BindingList-ben nincs sort, de ez mellékes). A saját pedig – minden bizonnyal – “pár napig jó lesz kipróbálni” szemlélet alapján egy gyors buborék rendezés lett. 4 sor, lehetetlen tévedni. Működött is. Majd a pár napból egy év lett.

Nem is lett volna baj, minden szépen működött, az SQL szerver rendesen kezelte a 80.000 terméket ügyfelünknél. Egészen addig, míg a 80.000 termék több, mint 5000 (!!!) gyártó alá került besorolásra. Ekkor a termékkiválasztó ablak megnyitása 30-50mp-et vett igénybe. A konzulens kollégák jelezték, hogy ez nem fatális hiba, emiatt nem kell azonnali verziót közzétenni, de minket mégis izgatott a dolog…

Quick Sort

És kb. egy órába telt, mire kiderült, hogy nem az adatbázis műveletek lassúak, nem is az 5000 gyártó combobox-ba feltöltése (valóságban más felületi elem, de példaképpen legyen combobox), hanem valahol belül egy adatátadás. És ekkor jött a homlokhoz csapás. A bubble-sort 5000 elem esetén statisztikailag 5000 x 2500 = 12.5M összehasonlítást végez és ennyi cserét is, ha kell. Ennek pedig ideje van. Egész számok helyett objektumok esetén még inkább.

A dolog sikerrel zárult, mert 3 órányi munka után a keretrendszerünk egy operáción esett át és a gyomor (körülbelül ez felel meg a rendező algoritmusoknak) újra egészségesen viselkedik. Persze újra felidézve tanulmányainkat rájöttünk, hogy a már rendezett adatokat a QSort nem is rendezi be újra, azaz még hatékonyabb lesz a működés.

Kis adatmennyiségek esetén nincs szerepe a fentieknek, de ott sem árt egy kis performancia-tuning.

Konkurencia elemzés – Ki honnan veszi az ötleteket?

Van, aki kíváncsiságból és van aki tudatosan pásztázza a konkurenciát. Pontosabban hívjuk versenytársnak! A végén kiderül, hogy miért inkább ezzel a jelzővel illetjük őket. Mi is néha napján körbenézünk.

 

És, hogy mit látunk?

  • Van olyan cég, amely 2009. év közepe óta nem jelentetett meg hírt magáról. A saját weboldalán! Leszálló ág, vélelmezhető, hogy csökkenő Incoming Cash-sel rendelkeznek…
  • Van, aki szépen csendben fejleszt, 2 havonta kiad egy új verziót, benne apróbb gombok, kis kényelmi funkciók. Lelkes csapat, Csendes folyó, 1-et fizet x-et kap (x>=3) akcióval…
  • Van régi motoros, régi V12-es. Sokat fogyaszt (termékkövetés), már nem annyira hatékony és a kasztni is itt-ott kopott. Slusszkulcsának pörgetésével, kapuzárás előtti sofőrjével még bejön néhány hölgynek…
  • Van, aki újként indult, rögtön v3.0-ként jelzi rendszerét. Szépen felépített koncepció, egyszerű kezelhetőség, 4 számjegyű árak. (És valahol máshol már látott működési modell, ismerős MsSQL instance név, ablakok) Naturalisztikus bulvártermék, csak bírja ügyfélszolgálattal… szurkolunk.
  • És még sokan mások…

 

Ki mutat újat?

Örömmel tölt el minket az a fellelhető irányvonal, hogy tudunk még nekik is újat mutatni. Több megvalósult fejlesztésünk köszön vissza a versenytársak termékeiben. A maguk módján. Biztos, hogy nem napi szinten foglalkoznak velünk. Ez nem is lenne jó. De néha észreveszik, hogy mit csináltunk és ötletet merítenek belőle/belőlünk.

Több forrásból értesültünk, hogy fejlesztéseinket elemzik is. Tudjuk, hogy az egyik cég a Symboogle és a Symbol Suggest megoldásainkat nem tartja jó ötletnek. Mások a jelenlegi CRM+ rendszerünkre ráharaptak, jelenleg 12 hónapos fejlesztési feladatként még kicsit halogatják. (Nemsokára CRM+ rendszerünk még nagyobb tudású lesz)

Fontos megjegyezni, hogy ez nem tilos, sőt jó. Mert előre viszi a világot. És két dolgot bizonyít számunkra:

  1. Jó úton haladunk, ötleteink nem csak számunkra bírnak értékkel.
  2. Többedik alkalommal elemezve azt, ahogy minket követnek, azaz INNOVATÍV PIACVEZETŐK vagyunk.

 

Mitől versenytárs?

Itt álljon egy kis magyarázat arra vonatkozóan, hogy mitől versenytársak. A konkurens ugyanazt adja más köntösben, talán apróbb paramétereiben eltérően (nagyobb internet sávszélesség, nagyobb GB, +25% a samponos flakonban, ugyanaz a mobiltelefon olcsóbban WiFi nélkül), de végeredményben ugyanarra jó. Itt azonban versenytársakról beszélünk, akik egy pályán haladnak, versenyeznek. De nem ugyanazzal a járművel mennek, sőt valaki tankkal tör előre, van aki versenybiciklivel hagyja le a tankot a kanyarban.

De nincs célszalag, nincs győztes, nincs a legjobb. Ez egy folyamatos verseny…

Van, aki 100m után hagyja abba, van, aki fut még 3 kört és valaki lefutja a fél-maratont. Mert mást akar elérni a pályán, a piacon.

Emiatt nem a megtett körök (=megszerzett ügyfelek) száma a fontos, sokkal inkább a futás stílusa és főleg az, hogy ki fut legelöl, kit követnek a többiek. Mi ezek szeretnénk lenni, sőt mi ezek vagyunk. Jelenleg. Lehet, hogy jön egy új versenyző, tele erővel és ötletekkel. De addig maradunk elöl. Köszönjük a megtisztelő figyelmet!

Kérem kövessenek!

 

ps: régi feladvány a ’80-as évekből

Hányadik leszel, ha futóversenyen megelőzöd a második helyezettet?
Általános válasz, hogy első, de a helyes válasz a második :)

Típus létrehozása futásidőben – RuntimeTypeFactory

“Azok a programozók, akik a régen “szabványos”, úgynevezett procedurális programozáson nevelkedtek egy évtizede megtanulták az objektumorientált programozást. Mert meg kellett.” – graffity 2004-ből.

Aztán, amikor a Java 1.1 beköszöntött és hozta a java.lang.reflect névteret, akkor néztünk nagyokat, hogy mi értelme van egy osztályt felderíteni futásidőben? Pláne, amikor programozás közben ott vannak a property-k és metódusok. Aztán csak-csak hasznát vettük, de a címben említett megoldásra még rémálmunkban sem gondoltunk volna. De a Symbol LAB összefogott és megoldotta ezt is…

1. Keretrendszer

Adott a keretrendszerünk, amiben sok helyen használjuk a reflection-t. Például listáink szűrőablakai nem léteznek önállóan, hanem szűrőosztályokat definiálunk (közös ősből interfésszel). Az osztályok feltérképezésével pedig létre tudjuk hozni a szűrőablakokat. Ha találunk egy property-t, aminek DateInterval a típusa, akkor kikerül két dátumválasztó, amelyek a property-be írnak, onnan olvasnak (DataBinding). A property-k attributumokkal rendelkeznek, amik magyar nevet adnak a mezőknek.
Szép, kidolgozott technológia, meg is számolom… (2 perc eltelik itt) … a Symbol Ügyvitelben jelenleg 103 szűrőobjektum van.

2. Probléma

A feni technológiát kényelmes használni, nem is akarunk letérni az útról, de egyedi fejlesztéseink (SyX) esetén külső fájlból jönnek az osztályok, amelyek nem az 1-es pontban említett ősosztályból származnak. Mi tévők legyünk? Az ügyfél várja a megoldást, ki kell valamit találni…

3. (Egyelőre még nem elégséges) Megoldás

Fejlesztési vezetőnk pénteken már említett valamit, de csak hétfőn állt elő az ötlettel. Ha fel lehet térképezni egy osztályt, akkor miért ne CSINÁLNÁNK egyet, csak úgy futásidőben. Még jó, hogy van Google, mert volt honnan információt meríteni, de hideg zuhanyként ért minket a találatok listája.
Létre lehet hozni típust futásidőben, de a következő lépéseket kell végiggondolni:

  1. Minden property-nek van egy lokális változója
  2. Kell, hogy legyen egy GET és egy SET metódus, amely a property értékét olvassa és írja a lokális változóba/változóból.
  3. A GET és SET metódusok törzse, lényegi része nem C#-ban írandó, hanem a köztes MSIL/IL nyelven, ami a .NET-ben megvalósított Assembly nyelv, azaz szinte gépi kód.

Itt egy kis szomorúság jött, mert ilyet nem oktatnak az egyetemen, nem hétköznapi a felhasználási módja és nincs róla még “MSIL 21 nap alatt” könyv sem.
Viszont a fejlesztési vezetőnk ellentmondást nem tűrve a megoldás útjára lépett és saját maga valósította meg. Ilyenkor kis csendet szokott kérni, de ez most 4 órán át tartott. Megszületett egy már működő megoldás. De ez még nem volt elég jó a felhasználásra.

4. Jó megoldás

További 2 órába telt, hogy megoldjuk a problmát, ugyanis az újonnan létrehozott osztálynak van egy őse, amelynek van egy két paraméteres konstruktora. MSIL nyelven kellett megoldani a base konstruktor hívását és a paraméterek átadását.

5. Összefoglalás

Keretrendszerünk már ezt is tudja, általános osztályt csináltunk belőle, amelyet alant közzéteszünk. Hogy izgalmasabb legyen, egy hibát rejtettünk el benne a 32-33. sor környékén. Aki a hibát kijavítja, +1 pontot kap önéletrajza leadásakor a HR osztálytól. :)

using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection.Emit;
using System.Reflection;
namespace SymbolTech.BaseProject.FrameWork.Common
{
    public class RuntimeTypeFactory
    {
        private TypeBuilder tb;
        public RuntimeTypeFactory(string assemblyname, string typename, Type baseclass)
        {
            AssemblyName assname = new AssemblyName(assemblyname);
            AssemblyBuilder assbuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assname, AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder mb = assbuilder.DefineDynamicModule(assname.Name, assname.Name + ".dll");
            tb = mb.DefineType(typename, TypeAttributes.Public, baseclass);
            //Override base constructors
            if (baseclass != null)
                foreach (ConstructorInfo ci in baseclass.GetConstructors())
                {
                    List<Type> types = new List<Type>();
                    foreach (ParameterInfo pari in ci.GetParameters())
                        types.Add(pari.ParameterType);
                    ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, types.ToArray());
                    ILGenerator ctorIL = ctor.GetILGenerator();
                    for (byte i = 0; i < types.Count; i++)
                        ctorIL.Emit(OpCodes.Ldarg_0, i);
                    ctorIL.Emit(OpCodes.Call, ci);
                    ctorIL.Emit(OpCodes.Ret);
                }
        }
        public static CustomAttributeBuilder CreateCustomAttributeItem(Type attributetype, Type[] constructorparametertypes, object[] constructorparameters)
        {
            return new CustomAttributeBuilder(attributetype.GetConstructor(constructorparametertypes), constructorparameters);
        }
        public void AddProperty(string name, Type type)
        {
            AddProperty(name, type, null);
        }
        public void AddProperty(string name, Type type, params CustomAttributeBuilder[] customattributes)
        {
            if (String.IsNullOrEmpty(name) || type == null)
                return;
            PropertyBuilder newprop = tb.DefineProperty(name, System.Reflection.PropertyAttributes.HasDefault, type, null);
            if (customattributes != null)
                foreach (CustomAttributeBuilder cab in customattributes)
                    if (cab != null)
                        newprop.SetCustomAttribute(cab);
            FieldBuilder newfield = tb.DefineField(name.ToLower(), type, FieldAttributes.Private);
            MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
            MethodBuilder methodget = tb.DefineMethod(String.Format("get_{0}", name), getSetAttr, type, Type.EmptyTypes);
            ILGenerator methodgetil = methodget.GetILGenerator();
            methodgetil.Emit(OpCodes.Ldarg_0);
            methodgetil.Emit(OpCodes.Ldfld, newfield);
            methodgetil.Emit(OpCodes.Ret);
            MethodBuilder methodset = tb.DefineMethod(String.Format("set_{0}", name), getSetAttr, null, new Type[] { type });
            ILGenerator methodsetil = methodset.GetILGenerator();
            methodsetil.Emit(OpCodes.Ldarg_0);
            methodsetil.Emit(OpCodes.Ldarg_1);
            methodsetil.Emit(OpCodes.Stfld, newfield);
            methodsetil.Emit(OpCodes.Ret);
            newprop.SetGetMethod(methodget);
            newprop.SetSetMethod(methodset);
        }
        public Type CreateType()
        {
            return tb.CreateType();
        }
    }
}

A 64bit mára már természetes

Brandom LeBlanc összefoglaló értekezése világosan szemlélteti, hogyan terjednek a 64bites Windows operációs rendszerek. Ennek oka lehet a tudatosság. De ismerve a honi és külhoni társadalom hozzáállását, inkább az OEM-nek köszönhető a terjedés.

Ezek szerint az új számítógépet vásárlók már nem biztos, hogy tisztában vannak vele, mit is vásárolnak. A népszerű programok futnak a számítógépükön, de mi lesz az ügyvitellel?

A Symbol Ügyvitel minden változata alkalmas 64bites operiációs rendszeren való futattásra:

  • Windows XP 64
  • Windows Vista 64
  • Windows 7 64
  • Windows 2008 x64

És természetesen Linux kiszolgálót választva minden 64bites Linux disztribúciót támogatunk, ami fut a Firebird adatbázis-kiszolgáló.

A LAB folyamatosan hegyezi a terméket

LAB csapatunk 12 emberhónapig készítette a keretrendszert, de időről-időre újra előveszik azt. Az összegyűjtött tapasztalatok alapján minden alkalommal találnak a rendszerben valamilyen gyorsítási lehetőséget.

A. Rendszerünk jelenleg több, mint 130 adatbázis táblában tárolja az adatokat (1347 mezőt számoltunk össze, persze nem kézzel kockás papíron). Adatbázis műveleteink központosítottak, bármilyen adatkezelési/adatelérési változás a módosítás után a programunk minden pontján megjelenik.

Számos alkalommal finomítottunk:

  • a nagy mennyiségű adatok lekérésének módján
  • a megszakítható lekérdezéseken (pl: véletlenül rosszul beállított szűrőfeltétel)
  • Large Object (BLOB = maximum 2GB-os adat, például video vagy tárol PDF) mezők lekérdezésein

B. Javítottuk a felesleges adathozzáféréseket. Többször előfordult, hogy egy-egy rendelkezésre álló adatot újból elértünk, újból áthoztuk a hálózaton. Ezen hibák kiküszöbölésére a LAB a fejlesztők rendelkezésére bocsátott egy SQL napló felületet, ahol a fejlesztő kolléga már munka közben látja, hogy az általa megvalósított funkció (pl: számla stornózás) hány alkalommal fordul a kiszolgálóhoz és milyen válaszidőkkel kell számolnia. Így a tesztelésre kerülő alkalmazás nem vagy csak ritkán küzd sebesség problémákkal. A tesztelőknek pedig nem ezzel kell foglalkozniuk.

C. Az SQL napló mintájára a fejlesztők figyelemmel kísérhetik, hogy a program adott állapotban milyen memóriafoglalási mérőszámokkal fut. Konkrétan hozzáférnek a betöltött (és betöltve maradt) például 43 vevőhöz, amelyek mindegyikéről minden adat lekérdehező és látható az is, hogy mikor és hol került betöltésre. És főleg miért maradt bent, mi használja?

D. Az architektúrából adódóan eddig is volt egy ún. “felpörgési ideje” a rendszernek. Az ablakok első megnyitása – “hála” a Microsoft-nak – az inicializálás (runtime compiler) miatt kicsivel lassabb volt. Mostantól azonban a ritkán változó adatok állandóan memóriában tartása miatt a felpörgési időt sikerült csökkenteni. A törzsadatok és egyéb statikus információk a változási valószínűségük alapján egyre ritkábban töltődnek újra. Kb. 30 percnyi programhasználat után már csak a ténylegesen változó adatok elérésekor van szükség hálózati forgalomra.

Konklúzió.

A sikeres, gyakran két embernek is több napos, hetes munkát jelentő mögöttes fejlesztések során eljutottunk odáig, hogy az alkalmazott technológia képes kiszolgálni a következő felépítésű céget. Gyakorlatból állítjuk, hogy:

  • 50 helyi felhasználó, call-center (gyakori, rövid műveletekkel)
  • 5-15 távoli felhasználó 2Mbit up/down bérelt vonalon
  • 5 nagyon távoli (külföldi) felhasználó a fent említett bérelt vonalon
  • átlagos, szerver célokra tervezett, de nem több milliós számítógép, 64bites Fedora Linux operációs rendszert futtatva.

Büszkék vagyunk a teljes egészében általunk tervezett és épített keretrendszerre, amely az elmúlt egy évben sok-sok felhasználónál, különböző platformokon is jól teljesített. Hajrá LAB!