Saturday, December 22, 2007

Microsoft and ACL permission changes

An article about ACLs and using MetaACL for metabase ACL permission changes has an interesting text. Quote:


Microsoft recommends that you only use ACCESS_ALLOWED_ACE because Microsoft does not extensively test ACCESS_DENIED_ACE.



This is from an official Microsoft support page - http://support.microsoft.com/kb/326902/

Friday, December 21, 2007

Quartz.Net composite keys

At the moment I'm trying to integrate Quartz.Net scheduler with our business rule engine. Quartz.Net is very promising, as it has a comprehensive set of scheduling capabilities, and, what is more important "Quartz.NET can be instantiated as a cluster of stand-alone programs (with load-balance and fail-over capabilities)

Clustering and load balancing is what we really need, and do not want to invest my precious time doing same bicycle again.

So far so good, until you come to database, and notice that all Quartz.Net database structure has taken a somewhat strange way to define primary and foreign keys.

Let us have an example :



CREATE TABLE QRTZ_JOB_DETAILS (
JOB_NAME VARCHAR(60) NOT NULL,
JOB_GROUP VARCHAR(60) NOT NULL,
DESCRIPTION VARCHAR(120),
JOB_CLASS_NAME VARCHAR(128) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
IS_STATEFUL VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB,
CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY (JOB_NAME,JOB_GROUP)
);



Everythin is sping'n'span except two columns "JOB_NAME" and JOB_GROUP, which apparently describe an ID of JobDetail. And it goes for all tables like this where JobDetail, Trigger (which is the main concept of whole scheduler), and listeners.

Why do I care about it? Because it makes more difficult to use such database in our project:

  1. Having a composite primary key (name and group) makes mapping of tables to POCO more compliated

  2. Primary key is not auto-generated by database, but rather controlled by client-side, which puts more responsibility on it.

  3. More responsibility means more code. More code means more stuff look after and more time spent on maintaining it

  4. Primary keys should NOT have any business meaning attached to it. Now properties Name and Group definetely carry meaning

  5. Say, you have a group of triggers. That group contains 1000 triggers. If business situation changes, and new business rules require you to immediately pause 100 of those triggers, what you have to do is to change group name for those triggers. Now if you change the group of a trigger, you will get unexpected behaviour, since your foreign keys will become incosistent. One example would be TriggerListeners not referencing those 100 triggers

  6. A name of a jobDetail should be it's name, and not a primary key. It's like saying that Darius is an ID of my person. Who knows, maybe I will change my name in some distant future



That's the first impression that pops in my mind when I see such database structure. (Yes, impression change in the long run, especially if someone gives very strong arguments of why I should do so)

Tuesday, December 18, 2007

Again Ayende writing about Boo. A very helpful insight of why Boo is good language: What makes Boo a great language

Monday, December 17, 2007

Generic collection and argument matching

Given that ConcreteRule implements IFilterRule interface, is this code valid?


FilterResults(List < object> objects, IList < IFilterRule> filters)
{
...
}

IList < ConcreteRule> filters = new List < ConcreteRule>();
FilterResults(..., filters);



Is it possible to pass IList as a paramater for IList ?

Wednesday, December 5, 2007

Gues what does it mean?

Gues how can 1 not be equal to 1?


Failures:
1) SourceGrid.Tests.TestRangeData.WriteData_FromSourceGridToSourceGrid :
expected: <1>
but was: <1>
at SourceGrid.Tests.TestRangeData.WriteData_FromSourceGridToSourceGrid() in e:\Projects\csharpexamples\SourceGrid\trunk\SourceGrid4\SourceGrid.Tests\TestRangeData.cs:line 122


p.s.
And yes, it is not the case when one one is string, another one is int

Monday, December 3, 2007

TDD anti patterns

I've compiled a presentation on TDD anti-patterns. It is just a collection anti pattern name and description. All stuff was taken from James Carr blog.

Here is a link to presentation, and link to code, illustrating those anti patterns.

Monday, November 26, 2007

ETL

ETL stands for Extract, transform, load as is described in wikipedia article.

I was reading many of Ayende Rahien posts about ETL, but never understood what's is that ETL about. Now I know it:

Extract, Transform, and Load (ETL) is a process in data warehousing that involves
* extracting data from outside sources,
* transforming it to fit business needs (which can include quality levels), and ultimately
* loading it into the end target, i.e. the data warehouse.


Basically what ETL stands is a process of getting oen source of information into destination. This might be an integration of two systems, say a CMS system and a Payment system, or that might be just importing data from spreadsheet into your database.


We have started doing our own implementation of import/export tool a month ago. I don't think this is a waste. The insight we gained from creating our own solution is very valuable, and now we have a choice of either stick with our solution, or use Rhino.ETL . Before that we had no choice, and that's bad

Rhino.ETL can be found here

A vision of enterprise platform Hot & Distributed Deployment

I am to lazy to write my own ideas, but I am not lazy to share _good_ ideas.

Ayende now has a month of a vision of enterprise systems I think it's really cool what he writes.

Please read it: A vision of enterprise platform Hot & Distributed Deployment

Sunday, November 11, 2007

Scheduling solutions

Just for my own reference:
Scheduling solutions @ Ayende Rahien

He puts his opinion about four solutions:

* Castle.Components.Scheduling
* Quartz.NET
* Rhino Scheduling
* Task Manager

Tuesday, October 9, 2007

How to build a document plugin system

Currently we are building a documnt plugin system for our app.

Which way do you prefer to specify documents:
Example number 1:


[DocumentRepository]
public class DocumentRepository
{
[Documents]
public void RegisterSheets()
{
m_documents.Add(typeof(Client[]), "ClientBook.odt", "Books/second level book", "Client book", "Print client book");

m_documents.Add(typeof(Contact), "ClientSheet.odt", "Sheets", "Contact sheet", "Print contact sheet");
}
}



Or number two:

[DocumentAttribute(typeof(Client[]), "ClientBook.odt", "Books/second level book")]
public class PrintClientBookClone2 : BasePrintingCommand
{
public PrintClientBookClone2() : base("Client book", "Print client book")
{
}

protected override void Invoke(object sender, EventArgs e)
{
WindowOpener.Default.OpenDocument(new DLC.Core.UI.Documents.GenericBookDocument(this, DataRoot));
}
}

[DocumentAttribute(typeof(Contact), "ClientSheet.odt", "Sheets")]
public class PrintContactSheetClone2 : BasePrintingCommand
{
public PrintContactSheetClone2()
: base("Client sheet", "print client sheet")
{
}

protected override void Invoke(object sender, EventArgs e)
{
WindowOpener.Default.OpenDocument(new GenericDocumentForm(this, DataRoot));
}
}



Both examples achieve the same functionality: two print buttons are created. One is placed under menu "Books/second level book/Client book", the other under "Sheets/Client sheet". Slash here denotes that the menu is composed of some sub-menus.

So which do you choose?

I choose both cases, since the first one is extremely short, and allows you to add documents very quickly. However, the other, while being cumbersome and ugly, allows you to achieve maximum flexibility in case you need it. And we know bussiness people need it alot.

Thursday, October 4, 2007

Microsoft to release source code of part of .Net libraries

Today throughout whole world was sent a message that Microsoft will release the source code to the class libraries that make up .NET.

We'll begin by offering the source code (with source file comments included) for the .NET Base Class Libraries (System, System.IO, System.Collections, System.Configuration, System.Threading, System.Net, System.Security, System.Runtime, System.Text, etc), ASP.NET (System.Web), Windows Forms (System.Windows.Forms), ADO.NET (System.Data), XML (System.Xml), and WPF (System.Windows). We'll then be adding more libraries in the months ahead (including WCF, Workflow, and LINQ).


You can deep-scan slashdot and google for the details. I just want to state my opinion about this:

First, it is not an open source license at all. You can SEE the source, but you can not do anything with it. It's just for your eyes, studying, debugging, etc.

If there were programmers who did not get what are the differences between open source and free software, now can see it that here is a big coneyed meaning difference. In essence, open source and free software are 99 percent the same.

However, when people talk about free software, they tend to think that this is about
the cost of the program, which is not true. Free software is about freedom.

When business men talk about open source, they often convey deliberately or mistakenly that open source is all about source code, that is, if you see source code, then it is open source. That is SO untrue. Open source is also about freedom. You not only see source code, but also can modify it, ehance it, fix bugs and release the code to the world.

Sorry folks, but .Net libraries are not open source. But i still hope they sometimes will be.

Second, you can not copy-paste code from .Net libraries to your projects, since .Net source is not released under open source, or free software license.

Third, it still a good thing

Fourth, I strongly believe that Mono will soon reach such a level, that we could move away from .Net platfrom and go into Mono platform. Why to do this? Simple - I see bussiness value in it. And the value comes primarily from the ability to choose. With Mono, our customers will get more options as where to run their software. Should they choose Linux or Windows, it will run on both machines.

Fifth, open source profoundly increases both productivity and research in IT industry. Personally, I can not see myself programming with libraries, where I can not see the code, and all of our libraries except .Net framework are open source.

Saturday, September 29, 2007

Why use NHibernate?

In NHibernate users forum i got a question

"To summarize, what I want is ability to construct queries using ICriteria API, and to bypass hydration - instead of real objects i want to get a raw sql result table"

Yeah for that you do want projection. But I'm wondering why you'd bother with NHibernate then? If you really, truly want to avoid all objects and want a table result-set, why not just use ADO.NET (or other database) directly?


Why do we use NHibernate

1. Surprisingly as it is, OOP is middle solution between functional programming and aspect programming. I want to use objects in my database aware application too. Unfortunately, object oriented databases still are not as evolved as relational databases. And it happens so that we are not working on Zope platform and cannot take advantage of ZODB (Zope Object DB). I want objects, not some random bits of data.

2. My first acquiantance with ORM solution was Neo .Net. The project is no longer in development, but it served very well for learning what is ORM. Neo is decent tradeoff of power and flexibility to ease of use and very low footpring of learning it.

If you happen to be new to ORM world, don't try NHibernate first (even with Castle.ActiveRecord), take some simple ORM tool, and use it. Get to know what the pros and cons are for ORM solutions. Then take NHibernate, since, IMHO, that's the only really flexible and powerful solution.

Here you can find NEO with generics support

3. Our way of programming is strictly object oriented. And having to work with objects allows us to make very incredible functionality in very short amount of time.

4. NHibernate is database agnostic. To explain this: NHibernate is not tied to any datbase. You create your model and the use it ony practically any databse exists. NHibernate is not a 80% solutions. It is 100% solution, and you can have big confidence that NHibernate will support database you need.

In our project, everything runs on FireBird, but tests run on SQLite. Unfortunately there's one problem with SQLite - it does not support database roles. Too bad.

5. NHibernate ir powerful. You can execute your direct sql against the databse, or use powerful ICriteria API. You can both fetch a result set containing object propertiess, and the objects themself.

6. NHibernate is free software, thus we have the source code. The free software license does not deny the right to bundle NHibernate library with your proprietary code.

Performance upgrade month 2

We use hibernate projections for a performance gain, and a very big performance gain.

Projections work this way: instead of loading real objects, we can tell NHibernate to load a specific property instead. So what we did was instead of loading an object with necessary objects pre-fetched, we build an ICriteria query and a projection for each property we need to display in the grid.

The gains are these:
1. We bypass hydration process, so that we get an array of columns, which we can databind to specific datagrid. Databinding process does not involve reflection code to extract data from objects, that's a side effect :)
2. We still have ICriteria interface to specify whatever filters we might need.
3. If one look at NHibernate projections, one would see that projections contains some nice things such as AVG, MIN, MAX, group by, COUNT etc. Do you see the possibilities? Tree views, additional helpful info for various reports, etc.

After making projections, so that it instead of loading 15k object graphs, we select only the properties we display in the grid, the time went down to 3-5 seconds from 15 seconds. That is, the performance gain was 3 to 5 times. That's alot.



Disclaimer
We still have many problems with performance, but at the moment the UI responsiveness is satisfactory.

Here are the other problems we have and what we could improve:

1. We use Sourcegrid as our datagrid solution. It is much much better than System.Windows.Forms.DataGridView, since it provides a rather solid MVC separation and extensibility mechanism. However, it has it's own problems. Some of them might be solved easily, and some might be rooted deep in the sourcegrid itself.

Yes, you guessed it. One of the problems is performance :). SourceGrid has a problem of managing many cells (i.e. > 50k). Maybe that might be solved using VirtualGrid (a class in SourceGrid), have not delved alot into, so can not tell much, now.

P.s. for 15k objects default SourceGrid solution might add 3 to 5 seconds delay solely for constructing cells.

2. Every time we edit an object, we create and destroy a form. Forms could be cached and reused.

3. Object loading might be put on a separate thread, and instead of loading whole 15k rows, a thread could small chunk first, display it in grid, then load the other rows. This would increase UI responsiveness.

4. Sometimes some forms fail to open in 3 seconds. This happens when for example object Group has a collection of Students (count > 50), a collection of Companies (count > 50), a collection of other stuff, etc. All those collections we put into separate tabs in the form. We could make that each tab load the data incrementaly, and make the form responsive to user actions as soons as it has minimum amount of data. I.e. something like ajax thing, but for desktop. We might call it Desktop 2.0 :D

Performance upgrade month

Last month for our product was performance upgrade month. Wise men say: "for beginers - do not optimize. For experts - do not optimize, yet". So we did not optimize for a very long time, but the time has come to do it.

For this various random thoughs popped, and some posts were written to NHibernate users forums. The first post and the second.

The problem:
We have a program where you can choose whatever columns you want to view in a datagrid. And those columns can be chosed whatever you can trace in the object graph, having that you only go only via one-to-one relationships (i.e. the "one" side of the "one-to-many" relationship).

Say, we are viewing a collectin of Teaching Group objects. Then in the grid we can choose any properties from the object graph, for example:


group object properties
Group.TeachingProgramme properties
Group.GroupLeader properties
Group.GroupLeader.Company properties
etc.



The problem is that if we have very big object graph, the it gets extremely slow to load all object graph.


We did tests withs 15k objects (which is not much), and we had around 15 seconds delay to load all those objects, and then display in the grid (having selected around 30 properties, with relationships, which results into select with 9 joins)

In another test we selected absolutely all properties to show in the grid (I did not count them, but the list was long, I believe something more than 50 columns in the grid). The NHibernate generated sql query was a few pages long, and it had 22 joins. Now if we count how many objects NHibernate has to create every time you want to refresh the grid. Say we have 17k objects, and each object has 22 subobjects. One left join is one subobject. So NHibernate would have to create 17k*22 ~> 400k objects. It's not the memory consumption that matters, it is the hydration process that matters. Just imagine how many lookups NHibernate has to do in order to set-up references for all those 400k objects. To add more, we still use Ayende's NHibernate.Generics package, even though it was deprecated with NHibernate 1.2. That library with its automatic association handling between objects adds some overhead too, though I can not say how much.

Then we thought what was the problem.
The first though was that joins cause that lot of problem, since we checked that with zero joins our grid fetches 15k objects and display them in 6 seconds, and 4 joins in 9 seconds, and 9 joins in 14 to 16 seconds.

It was reasonable to blame associations, but the problem was not actually in the joins.

Next test was we took the select statement generated with NHibernate with 22 joins and executed against our database (which happened to be FireBird). The result was promising - 17k objects with all properties where fetched in less than 4 seconds. (P.s. time measurement was done with eye-movement precision, that is, we just watched at the clock and counted the seconds).

The results suggested that it is not the database with many joins perform slow, but NHibernate. Most probably the hydration process gets slower as the depth of our fetched object graph increases. That is, whenether we add a column witch adds a new patch in object graph, the process becomes a lot slower, since it increases exponentialy the amount of objects NHibernate has to hydrate for us.

So the answer is clear - we have to bypass hydration process.

Friday, September 28, 2007

Web application unit testing

How to test applications on .Net

The thing that popped into my mind is "User Interface testing is not stable". Period.

Any time I tried to test user interface, everything ended up in recycle bin next week, if not next day. If you want to tage huge advantage of unit testing your code, you must write it clean and separated. That's true both for web and desktop applications.

If you ask what is clean and separated code I would describe it like this: your code must be written in as small chunks as possible. Your functions should only one single thing, your classess should have only one responsibility, your namespaces should be grouped by behaviour.

It's like in orchestra - if you have a violin, a guitar and a maestro, then you have three responsibilities - play violion, play guitar and act as a maestro.

If you happen to write a Web application, do not follow blind examples of putting together your data loading, decision and presentation logic into one single code-behind (or whatever) class. It's allways the same three letters - Model / View / Controller - MVC.

It's as important to separate M from C, as to P from M and C. Your presentation can NEVER be together with your controllers. Clean separation is both a prerequisite for unit testing, and a result of it.

Web unit testing could check your model and controller classes. hammet, maintainer of Castle Project also tests ViewComponents.

As for unit testing tools, one of the more popular are watin and Selenium. You also check my presentation about selenium: pdf format odp format

Friday, September 21, 2007

How to get perfect code

macournoyer is a good guy.

Read his blog about 5 ways to achieve perfect code


I would correct him - not five ways, but five things you have to do contstantly

Sunday, August 12, 2007

Decomposing systems

Today I begin decomposing our system into separate components. I felt that I will have to do it sometime, but I was reluctant to do it because I never did it before.

What I learned thinking about decomposition is this:

  • Never postpone things you have to do. Always remember - You have to do what you have to do.

  • Castle.Windsor is great.


    Castle.Windsor is a IoC container (Inversion of Control), which helps build system from small components. I found it to be very simple, and easy to use.

    Now, as I have moved all generic controls and helper stuff from UI to Core, and concrete stuff from Core to UI, ia have 50 tests not running.

    Probably, most of them are ActiveRecord.InitializationExceptions, but anyway, unit tests again help me make good pace without worrying of damaging my system





Wednesday, August 8, 2007

The best part of Unit Testing

The best part of unit testing is that it gives confidence that the code is yet again maintanable!

Sadly, but my code is falling apart just at the moment. The parts that worked before are not working for some mysterious reasons. And the worst thing is that i discover those bugs by sheer accident!

I mean - there's no testers in our team. And there's no way the bugs can be found when they bring up, except unit testing.

When i write a unit test, i feel a very strong feeling, that my code is secured from future bugs, which pop out unnoticably. It gives me confidence, and allows me to further refactor and expand the system

Interesting Undo/Redo solution

A few weeks ago i found a very peculiar Undo/Redo solution here .

The way it was written surprised me. It even took me 2 or 3 minutes to get the idea how the code works :).

All the magic is hidden inside a UndoRedo class. The idea is that instead of creating your variables directly, you wrap them with UndoRedo class like this:


readonly UndoRedo name = new UndoRedo();
public string Name
{
get { return name.Value; }
set { name.Value = value; }
}



This solution is very interesting, but, from my perspective, it asks too much from the programmer. To use this UndoRedo mechanism you would require to rewrite all your classes, which needs capabality of UndoRedo.

What is more, you could not make TextBox undoable, without overriding the TextBox class. And of course we know, that some classes in M$ field are for some mysterious reason sealed, so you can not inherit.

But overall, the solution is interesting, and it does work :)

Unit testing is leaking into me slowly but constantly

Finally I start to embrace test-driven-development.

Whenether I fix a non-trivial defect, I first write a unit test to catch that error, and then fix the bug.

Even now, for example, I have to create a new command which creates a new contract for each student. Instead of writing immediatelly whole working code, I make a sketch of what my working code might look like, then I write unit test to test that my sketch code does not work.

Finally, (in a few minutes or hours) i implement the feature and the tests pass. Then I run all my tests (64 right now), and commit the code to svn.

That's my life.

Saturday, July 14, 2007

EuroPython 2007

EuroPython 2007 just finished. It was in Vilnius, Reval Hotel Lietuva.

Some comments about talks i attended:


Seamless object persistence with ZODB - a talk by Mr. THEUNE, Christian, who presented an object oriented Zope database. It was an interesting to see it in action. I still wonder the performance of object databases. This aspect was not touched.




The Storm Object-Relational Mapper by NIEMEYER, Gustavo (Canonical).

I really did not like this post. Basically,

  • The point that Storm was built because they could not fix SQLAlchemy to work nice for them is not justified. In the end, the bug which was bothering Gustavo was actually fixed

  • So basically it means that Storm has no killer features against other Py ORM mappers

  • Storm reminds me of a .NET Entity Objects Framework Neo.






There was a very interesting talk about KSS, Ajax development with style.

They showed a simple wiki page which worked with no page reload at all, and all ajax stuff was done using KSS, not a single line of direct java script.




An interesting project was PyPy

I could not grasp to the roots, but basically it's something in beetween about converting any code to a python , and to converting python to any other code.

For example, you write simple python code, and then translate it into C, which results in performance gains. The difference between PyPy and CPython is that PyPy is a much more sophisticated project, capable of optimizing code and jitting the resulting code.


Another example is you write a java script code (or schema code, or whatever), and then convert this code to python and then convert it to CLR bytecode and execute it in CLR environment.

The whole PyPy project is more a scientific research, than a concrete product.

Look also at RPython



GROK - No comments about this one :) Just watch the trailers :D






Also about EuroPython here

I'm switching to English

I'm switching this blog language to English. It seems that blogging on software programming stuff is not that much popular. And I need to interact with the rest of 6 zillion population around the world.

So everybody please sharpen your teehts and start posting comments in English ;)

BTW, blog name will be changed too. Probably to "Code Ruins".

Monday, June 25, 2007

Euro Python 2007

It's summer time and time to go to conferences.

Though we do .Net development, i doubt programming skills in pythong are that much different than .Net skills.

The conference is from 9th July to 11th July. Following three days will be a sprint run (brainstorming code for one or another Python community project).

Please attend.

Euro Python page

Monday, June 11, 2007

NHibernate Performance Bottlenecks

Vakar buvo atnaujintas straipsnis codeproject.com puslapyje apie NHibernate perforamce bottleneck'us.

Straipsniai čia :
Pirma dalis

Antra dalis


Pirma dalis iš tiesų tik pasako, kokie gali būti bottleneck'ai. Paprastai tai būna:
  • Programa yra "chit-chat", t.y. per daug siunčia užklausų į DB

  • Programa prašo duomenų daugiau negu reikia


  • Antrojoje dalyje pasakoma keletą gerų dalykų:
  • Kaip dirbti su keliomis duomenų bazėmis vienu metu

  • Kaip dirbti su skirtingais tranzakcijų tipais

  • Casche'inimas





  • Čia dar vienas straipsnis: NHibernate Best Practices with ASP.NET, 1.2nd Ed

    Thursday, June 7, 2007

    Boo su DSL

    Labai įdomus straipsnis apie DSL Friendly syntax in BOO


    Nekantrauju išbandyti tai generuojant odt dokumentus :)

    Tuesday, May 29, 2007

    .Net biblioteka video montavimui

    Neseniai programming@konferecijos.lt mailing liste kažkas prašė bibliotekos garso kodavimui.

    Šiandien užtikau Auckland'o blog'e Splicer įrankį.


    Ką gi jis gali daryti:
    * Encode video or audio suitable for use on a website.
    * Create slideshows from images, videos and audio.
    * Apply effects and transitions to audio and video.
    * Grab System.Drawing.Image clips from a video at certain times.
    * Add new soundtracks to existing video clips.
    * Watermark videos.
    * Build a video editing suite, if you were so inclined.


    Splicer galite rasti čia : http://www.codeplex.com/Wiki/View.aspx?ProjectName=splicer

    Monday, May 28, 2007

    Dokumentų spausdinimas

    Vienas klausimas yra kokį būda naudoti ataskaitoms generuoti, o visai kitas, kaip į dokumentą duomenis sudėti.

    Pirmasis variantas (kurį prieš pusę metų dariau) buvo paprastas switch / replace sakinių rašymas.

    Rezultas - dėl kiekvieno menkniekio reikia programuoti. Tikrai nepavydinėtina.

    Ką gi, naudojame kitą būdą, juk vis dėlto, gyvename .Net aplinkoje, ir skirtingai nei java yra daug ir įvairių kalbų. Tuo ir pasinaudokime.

    Galbūt dar mažai kam žinoma, bet greitai auganti kalba Boo :)

    Boo yra dinaminė kalba, pagrįstas pytono sintakse. Ką gi mums duoda Boo.
    Ogi du dalykus:
  • Boo turi interpretatorių
  • - kurį galime įtraukti į programą
  • Įdomiau gyventi



  • Taigi, dabar vietoje skurdžių sakinių

    ...
    if (m_node.InnerText = "Studento vardas">)
    m_node.Text = student.Name + student.Surname
    ...



    galime rašyti taip:
    kode:


    Interpretator m_interpetator = new Interpretator()
    m_interpratator.setValue ("RootEntity", student);

    ...
    m_interpretator.Eval(node.InnerText);
    m_node.Text = m_interpretator.LastValue
    ..




    dokumento šablone tuomet galima rašyti ką tik norime.
    Pavyzdžiui, dokumento pradžioje galime įdėti paslėptą tag'ą (jei konkrečiau - tai input field'ą) su tokiu kodu "Mokinys = RootEntity".

    tuomet tose vietose, kur turi atsidurti tekstas įdedame tokius paslėptus tag'us:

    vardas = Mokinys.Name + Mokinys.Surname; vardas.ToUpper();


    Šiais dviem sakiniais sujungėm mokinio vardą ir pavardė ir padarėm juos upper string'ais. Kadangi tai yra .Net aplinka, tai praktiškai galima naudotis absoliučiai visomis funkcijomis, kurias duoda .Net


    Daugiau jokių switch replace! :)

    Ataskaitų generavimas

    Yra užduotis : programa turi spausdinti įvairius dokumentus - sutartis, objektų sąrašus ir pan.

    Yra keli atsakymo variantai:
  • HTML templeitai
  • - net nepradėsiu kalbėti apie tai. Visi žinome kaip daryti replace'us.

  • CrystalReports
  • - teko naudoti porą kartų. Geri, greitai veikia. Bet širdies nedžiugina. Traukti ir kišti duomenis per datasetus nėra labai jau gudrus dalykas.
    Be to, už visą tą darbą gauni tik paprastą neredaguojamą dokumentą.

  • SharpReports
  • - tas pats kas crystal reports, tik laisvas produktas. Laisvė yra gerai, bet reportai ir afrikoj reportai. Ne.

  • Automatizuoti wordą
  • - mintis visai nebloga. Turint omeny, kad gauname begalę formatų, galimybę redaguoti duomenis po atspausdinimo. Tik nežinia kaip tuo wordu programuoti. Turbūt kažkokiu bibliotekų reikia. Be to, kažkas sakė, kad stabdo.

    Bet gal melavo

  • Automatizuoti OpenOffice
  • - kodėl gi ne? Formatas aiškus, visiems prieinamas. Bibliotekų yra
    OpenOffice į programą įdėti galima.

    Undo / Redo galimybės programoje (2 dalis)

    Ankščiau rašiau apie tai, kad mūsų kuriamoje desktop programoje reikia galimybės atšaukti naudotojo padarytus veiksmus.

    Nors API undo atžvilgiu dar nėra iki galo nusistovėjusi (tiesą sakant, undo mechanizmas šiek tiek *nervina*, nes jam *palaikyti* reikia tam tikrų pastangų), sprendimas yra.

    Sprendimas veikia, ir štai kaip jis maždaug atrodo.

    Undo mechanizmui užtenka turėti sąrašą objektų, kurie gali atstatyti naują būseną į seną būseną. Tarkime, IMemento:


    ///
    /// An interface for all undo / redo actions
    ///

    public interface IMemento
    {
    ///
    /// Restores the state of the object.
    ///

    /// A new memento, which performs the Redo action
    IMemento Restore();
    }


    Kiekvienas IMememtno Restore() metode atstato kokią nors informaciją į prieš tai buvusį būvį.

    Man kol kas prireikė dviejų memento tipų:
    PropertyMenento - atstato bet kurio properčio reikšmę į prieš tai buvusį
    DelegateMemento - lengvai kustomizuojamas memento per delegatus

    Saturday, April 21, 2007

    hammet apie Domain Driven Design Castle

    Užvakar hammet rašė įdomų straipsnį apie Domain Driven Design ir Castle.

    Rekomenduoju paskaityti.
    hammet ir Domain Driven Design

    Wednesday, April 4, 2007

    Kolekcijos su event'ais

    Bandau implementuoti UndoHistoryRepository ir susidūriau su tokia problema, kad UndoHistoryRepository turi žinoti, kada nauji objektai yra sukuriami, ir kada pašalinami.

    Microsofto System.Collections namespace'e jokių kolekcijų su eventais neradau, tad leidausi į kelionę ieškoti. Rezultatai tokie:

    * PowerCollections - Wintellect kompanijos(?) gaminama biblioteka. Kiek tikrinau, visos nuorodos į biblioteką yra mirusios. Be to, biblioteka neduoda reikiamo dalyko.

    * IESI.Collections - JasonSmith'o kolekcija. IESI pagrindins tikslas yra ISet (aibės) kolekcijos realizavimas. Vėlgi, eventai nerealizuoti, tačiau IESI.collections yra gana žinomas dalykas, paplitęs per NHibernate projektą


    * OpenDocument4All - Lars Behrmann'o parašyta OpenDocument generavimo biblioteka. Nors tai nėra kolekcijų biblioteka, bet jos viduje yra naudojamos kolekcijos su event'ais. Kodas nėra gražus, standartizuotas, ir tuo labiau tinkamas naudoti kituose projektuose.

    * C5 biblioteka - Niels Kokholm ir Peter Sestoft parašyta biblioteka, Kopenhagos universitetas. C5 is a library of generic collection classes for C# and other CLI languages and works with Microsoft .Net version 2.0 and Mono version 1.1.16 and later.

    Taip pat ši biblioteka turi neblogą (258 puslapių) manual'ą, kurio 8.8 skyryje parašyta : "Events: observing changes to a collection".

    Būtent to mums ir reikia.

    Monday, April 2, 2007

    Undo / Redo galimybės programoje

    Šiuo metu kuriame paprastą biuro programą.

    Reikia sukurti tokius langus: mokymo dalyko langą, ir mokymo pamokų langą.
    Be visų duomenų įvedimo laukų, langas turi turėti mygtukus išsaugoti ir uždaryti. Jei paspaudžiamas mygtukas išsaugoti, tai visi esami pakeitimai išsaugomi. Jei paspaudžiamas uždaryti, tai neišsaugoti pakeitimai turi būti atmesti ir langas uždarytas. Išsaugoti pakeitimai turi likti nepakitę.

    Registruojant arba redaguojant mokymo pamokas, visi pakeitimai paspaudus mygtuką "išsaugoti" turi būti išsaugoti tik atmintyje. Į duomenų bazę pakeitimai siunčiami tuomet, kai saugomas pats dalykas.


    Taigi, klausimas (labai jau daug išsiplėčiau apie probleminę sritį):
    Kaip galima kokybiškai realizuoti Undo mechanizmą?


    Ieškojau porą dienų sprendimo. Kol kas atsakymas matau yra toks: Memento design pattern'as.

    Gerą pavyzdį radau čia:
    Generic undo redo

    Autorius siūlo tokį sprendimį: "an object that is capable of restoring a target object to one of its previous states".

    Pavyzdys su c# būtų toks:

    interface IMemento
    {
    ///
    /// Restores target to the state memorized by this memento.
    ///

    ///
    /// A memento of the state before restoring
    ///

    IMemento Restore(T target);
    }



    Sprendimas su Memento būtų turėti kiekvienam veiksmui atstatymo veiksmą. Atstatymo sprendimai gali būti dviejų rūšių -
    1 - Atsatyti objektą darant jo deep-copy, ir vėliau originalą pakeičiant kopija
    2 - Kiekvienam objekto keitimo veiksmui generuoti anti-veiksmą, t.y. veiksmą, atsatantį objektą į buvusią būseną. Tokių veiksmų būtų dvi rūšys - properčių atstatymas, ir ryšių atstatymas (objekto kūrimo ir šalinimo atveju).

    Aš labiau linkstu prie antrojo varianto. Daryti objekto deep-copy gali sukelti daug problemų dėl ryšių. Atsatant objektus naudojant anti-veiksmus, viskas vyktų atvirkštine tvarka, negu tuomet, kai objektas buvo keičiamas.

    Šiandieną bandysim implementuoti tokį sprendimą, žiūrėsim, kas gausis

    Wednesday, March 14, 2007

    Castle.Windsor IoC konteineris

    Vakar 1900 MiF'e dariau pristatymą apie Castle.Windsor IoC konteinerį.

    Skaidrės:
    pdf
    odp


    Gavau keletą įdomių klausimų:
    * Castle licenzija yra Apache Software Foundation License 2.0. Vadinasi, galima laissvai naudoti komerciniuose projektuose nebijodami, kad visas kodas turės taip pat tapti atviru

    * Aspektinis programavimas yra visai nauja tema man. Žiūrovai labai teisingai pastebėjo, kad order.Trasnfer(..) metodas tikrai neturi jokio cross-cutting interest.
    Kol kas nesugalvojau, kokį tinkamą pavyzdį pateikti, kad būtų aiškus ir tikslus. Justino pasiūlyta probema "pridėti jau esamai sistemai teisių tikrinimą ant kiekvieno mygtuko paspaudimo" yra tikrai cross-cutting, tačiau kaip tą išreikšti gražiai prezetnacijoje neturiu idėjų. Gal kas turite minčių?

    * Buvo pasakytas vienas komentaras, kad rašant gerą kodą parašomos blogos programos. Dėstytojas taip pat pritarė minčiai ir siūlė nepriimti visko kaip panacėjos.

    Tas tikrai svarbu - netobulinti kodo vien dėl pačio tobulinimo. Esminis tikslas - veikianti programa. O jeigu ji dar yra kokybiška, tai yra iš viso labai gerai.

    Dabar iš kitos pusės nereikėtų ir savęs nuvertinti ir bijoti kažką keisti ar tobulinti. Pasakymas, kad nemokamas kodas yra blogas kodas yra tiesiog neteisingas, lygiai kaip pasakymas, kad rašant gerą kodą neparašomos geros programos. Nemanau, kad tokie teiginiai turi rimtą pagrindą. Taip pat toks požiūris neturėtų būti formuojams (netiesiogiai) MiF'e, tai yra labai neigiama įtaka.

    Wednesday, February 28, 2007

    Komentarai

    Ayende@Rahien bando spėti, kas bus NHibernate ORM įrankiui, kai bus išleistas Linq.

    "ADO.Net for Entities <...> is the usual 80% solution, with a hood welded shut in all the interesting locations."
    Labai teisingai pasakyta. Skirtingai negu dauguma laisvų projektų, kuriuose visa valdžia atiduodama programuotojui, Microsoft ir kituose uždaruose produktuose yra tas pats apribojimas - kodas negali būti modifikuotas ar išplėstas. 80% atveju tai yra gerai, tačiau likę 20% bus nepatenkinti.
    <...> an ORM that comes from Microsoft is probably going to be popular because it comes from Microsoft.
    Taip pat visiška tiesa. Ir tai yra didelė programa. Daug programuotojų tiesiog bijo įvertinti savo galva naudojamą technologiją ir įvardyti jos trūkumus ir minusus. Jei kažkokia technologija yra Microsoft gaminama, ji nebūtinai yra geriausia. Taip, tikrai Microsoft produktai yra geri, tačiau yra ir geresnių.

    Tas pats yra ir duomenų bazių sferoje. Oracle yra absoliutus lyderis nesvarbu kokiu aspektu nagrinėsi. Programuotojai tiesiog nelygina duomenų bazių. Oracle yra de facto lyderis visose srityse. Taip, Oracle yra galingas, tačiau turi būti ir poreikiai dideli.

    Beje, kalbant apie kodo kokybę. Vakar VU MiF paskaitose išgirdau įdomų teiginį. Teiginys buvo toks - niekas kodo nedokumentuoja. Kai pabandžiau tam paprieštarauti, jokio palaikymo nesulaukiau, net iš dėstytojo. Kasžin kaip VU MiF gali studentus išmokyti būti gerais IT specialistais, jei net patys dėstytojai nesupranta elementaraus dalyko - norint rašyti geras ir tikrai kokybiškas programas kodo komentarai tiesiog gyvybiškai svarbūs, nekalbant apie testus ir gerą OOP suvokimą.

    Ayende@Rahien straipsni - What would happen to NHibernate after Linq ships

    Tuesday, February 27, 2007

    Selenium testavimo įrankis

    Šį vakar 1800 baltupiuose esančiose MiF patalpose skaitysiu pranešimą apie automatizuotus internetinių programų testavimo įrankius.

    Apžvelgsiu Selenium įrankį

    --
    Pranešimas įvyko, tačiau auditorija liko nesupratusi, ką aš pristatinėjau.

    Teks laukti jūsų, skaitytojai, komentarų prezentacijai ir taisyti pagal pasiūlymus ;)

    Prezentacija : pdf odp

    Friday, February 23, 2007

    Object/Relational mapping tools

    Object Relational Mapping tools - įrankiai, susiejantys reliacines duomenų bazes ir objektus. Nesu guru šioje srityje, bet kiek žiūrėjau, yra keli variantai:

    * Naudoti kokį nors savo rašytą O/R mapping įrankį
    * Naudoti kitų parašytą.

    Pirmuoju variantu viskas paprasta - jūs miręs, jei norite savo rašyti, nebent norite pralenkti jau esamus produktus. Sėkmės tokiu atveju!

    Antruoju - galima išsirinkti begalę variantų iš čia: http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software

    Pats esu susipažinęs su keliais variantais:
    - Neo - http://neo.codehaus.org/
    - NHibernate - http://www.hibernate.org/343.html
    - Castle.ActiveRecord - http://www.castleproject.org/activerecord/index.html


    Neo yra neblogas variantas tuom, kad
    * lengvai išmokstamas,
    * saugomus objektus apibūdini XML aprašu, kuris nėra sudėtingas,
    * galima rašyti "enterprise distributed systems".
    * Be to, sėkmingai naudojome kuriant paprastą desktop aplikaciją.

    Neo minusai:
    * objektus galima traukti tik tik per paprasčiausias užklausas. Jokių grupavimų ar agregavimų
    * Jokių tiesioginių SQL vykdymo galimybių,
    * duomenų bazių palaikymas nedidelis (FireBird, MSSql, MySql, ir kitos).

    Asmeninė nuomonė - labai šaunus variantas pradiniam susipažinimui su O/R įrankiais




    NHibernate yra monstras, trumpai tariant. Sunku sugalvoti kokių galimybių jums reikia, kurių jis netūrėtų.

    * Kešavimas pirmo lygio
    * Kešavimas antro lygio
    * Lanksti užklausų kalba įskaitant agregavimo ir grupavimo funkcijas
    * Tiesioginių SQL sakinių ar procedūrų vykdymas.
    * Naujų objektų kūrimas grąžinant užklausą
    t.y. tarkime jūs turite Mokinius ir turie Supermenus. Galima rašyti tokią užklausą: select new SuperMokiniai (Mokiniai.Name, Mokiniai.SuperAbility) from Mokiniai, Supermenai where ....
    * Duomenų bazių palaikymas didelis.
    * Galimybė turėti "composite" pirminius raktus, t.y. pirminį raktą gali sudaryti keli atributai.
    * Galimybė gauti objektų savybes, o ne pačius objektus.
    * Didelė bendruomenė
    ir taip toliau. Turbūt praleidau dar pusę jo savybių.

    Minusai:
    * NHibernate yra monstras
    * Sunku išmokti
    * Objektus reikia parašyti xml'u, kuris yra labai komplikuotas ir painus

    Pastaba. NHibernate yra .net'inis Hibernate klonas.



    Castle.ActiveRecord yra trečias, ir, žinoma, geriausias variantas.
    Catsle.ActiveRecord yra ActiveRecord projektavimo principo įgyvendimas .net'inėje aplinkoje naudojant NHibernate kaip pagrindą.

    Pliusai:
    * Paprasta išmoki
    * Galimybės tokios pačios, kaip NHibernate
    * Nereikia rašyti XML'ų
    * Auganti bendruomenė

    Minusai
    * Jei reikia tikrai įmantrių galimybių, geriau dirbkite su NHibernate, bet jei reikia greičio, naudokite Castle.ActiveRecord