04/12/2008

Transformacje Xsl i przestrzenie nazw XML

Home

Przy używaniu transformacji Xsl należy pamiętać o przestrzeniach nazw Xml. Załóżmy, że mamy dokument Xml i transformację Xsl do jej przetwarzania:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type='text/xsl' href='Transformation.xsl'?>
<A>
   <B>
      bbb
   </B>
   <B>
      bbb
   </B>
</A>
Transformajca wygląda natomiast tak:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" standalone="no" omit-xml-declaration="yes" encoding="windows-1250" />

<xsl:template match="B" >
   <LI>
      <xsl:value-of select="current()"/>
   </LI>
</xsl:template>

<xsl:template match="A" >
   <HTML>
      <HEAD>
      </HEAD>
      <BODY>
         <UL>
            <xsl:apply-templates select="B"/>
         </UL>
      </BODY>
   </HTML>
</xsl:template>

</xsl:stylesheet>
Wynikiem działania przedstawionej transformacji na przykładowym dokumencie Xml powinna być lista:
  • bbb
  • bbb
Wynik będzie zupełnie inny jeśli zmodyfikujemy dokument Xml w następujący sposób:
...
<A xmlns="a.b.c">
...
Po tej zmianie otrzymamy taki, mało przyjazny rezultat transformacji:
bbb bbb
Aby rozwiązać problem należy zmodyfikować definicję transformacji poprzez jawne wskazanie przestrzeni nazw z jakiej pochodzą przetwarzane węzły dokumentu Xml. Po pierwsze należy podać definicję nowej przestrzeni nazw poprzez dodanie do węzla xsl:stylesheet atybutu xmlns:test="a.b.c". Oczywiście można podać inną skróconą nazwę przestrzeni nazw niż test. Następnie należy dodać przedrostek test: przed każdym odwołaniem do węzła z dokumentu np.:
...
<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="a.b.c">
...
...
<xsl:template match="test:B" >
   <LI>
      <xsl:value-of select="current()"/>
   </LI>
</xsl:template>
...

01/12/2008

LoadControl

Home

Czy poniższy kod zawierający wywołanie metody LoadControl wydaje się wam poprawny? Jeśli tak to zapraszam do dalszej lektury.

protected void Page_Load(object sender, EventArgs e)
{
    ...
    Control control = LoadControl("~/MySimpleUserControl.ascx");
    PlaceHolder1.Controls.Add(control);

    ((MySimpleUserControl)control).BackColor = Color.Yellow;
    ...
}
Niestety ale kod ten będzie działał poprawnie tylko do momentu kiedy dla kontrolki zostanie włączony mechanizm Output Cache, na przykład w następujący sposób:

<%@ OutputCache Duration="60" VaryByParam="None" %>
W takim przypadku, przy następnym ładowaniu strony, na której umieszczono kontrolkę, pojawi się wyjątek InvalidCastException z komunikatem: "Unable to cast object of type ‘System.Web.UI.PartialCachingControl’ to type ‘MySimpleUserControl’.". Dzieje się tak ponieważ metoda LoadControl, w przypadku kiedy włączone jest cache'owanie dla kontrolki, zwraca obiekt klasy PartialCachingControl, a nie klasy MySimpleUserControl jak mogłoby się wydawać. W takie sytuacji do kontrolki możemy się dostać przez właściwość PartialCachingControl.CachedControl. Poprawny kod powinien, więc wyglądać tak:

protected void Page_Load(object sender, EventArgs e)
{
    ...
    Control control = LoadControl("~/MySimpleUserControl.ascx");
    PlaceHolder1.Controls.Add(control);

    MySimpleUserControl c = control as MySimpleUserControl;
    if(c == null)
    {
        PartialCachingControl pc = control as PartialCachingControl;
        c = pc.CachedControl as MySimpleUserControl;
    }

    if(c != null)
       c.BackColor = Color.Yellow;
    ...
}
Dodatkowe sprawdzenie if(c != null) jest potrzebne ponieważ właściwość PartialCachingControl.CachedControl zwróci null jeśli kontrolka znajduje się już w cache'u. Innymi słowy wartość różna od null zostanie zwrócona tylko wtedy kiedy kontrolka nie została jeszcze umieszczona w cache albo zawartość cache przestała być ważna.

Należy również pamiętać aby odwołanie do PartialCachingControl.CachedControl było zawsze poprzedzone umieszczeniem kontrolki na stronie np.: PlaceHolder1.Controls.Add(control);. W przeciwnym wypadku właściwość PartialCachingControl.CachedControl zawsze zwróci null.

W przypadku kiedy korzystamy z cache'owania i mamy na stronie statycznie osadzone kontrolki również należy zachować ostrożność. Jeśli kontrolka zostanie pobrana z cache to nie zostanie zainicjowana i nie możemy w związku z tym odwołać się do niej w kodzie naszej strony. Oczywiście jest to jak najbardziej prawidołe zachowanie - na tym polega idea mechanizmu Output Cache.

28/11/2008

Modelowanie procesów biznesowych

Home

Ostatnio zainteresowałem się modelowaniem procesów biznesowych. Spodziewałem się istnienie kilku standardów ale rzeczywistość naprawdę mnie zaskoczyła. Świat BPM okazał się naprawdę bogaty. Sądzę, że porównanie do dżungli będzie nawet bardziej odpowiednie. Mamy więc: BPDM, BPEL4WS, BPML, BPMN, UML Activity Diagram, WSFL, XLANG, XDPL i sporo więcej. W poście tym chciałbym troszeczkę usystematyzować ten bałagan i wyjaśnić jak jak to rozumiem.

Wstęp

Zacznijmy od tego, że w procesie BPM należy wyróżnić dwa zasadnicze poziomy:
  • Poziom modelowania – poziom, w którym działają analitycy, konsultanci itd.
  • Poziom wykonania – poziom, w którym pracują inżynierzy oprogramowania itd.
Na styku tych dwóch (ale moim zdaniem bardziej na poziomie modelowania) poziomów znajduje się analityk procesów biznesowych.

Poziom modelowania

Użytkownicy pracujący na tym poziomie posługują się wysoko poziomowymi narzędziami i notacjami do zamodelowania procesów biznesowych. Odpowiednich narzędzi jest bardzo dużo ale niewątpliwie najpopularniejszą i najbardziej rozpowszechnioną notacją jest BPMN – Business Process Modeling Notation, która została zaproponowana przez BPMI – Business Process Modeling Initiative (od 2005 połączone z OMG).

BPMN to nie tylko notacja. Definiuje nie tylko elementy diagramu ale również ich semantykę. Specyfikacja BPMN nie określa natomiast sposobu w jaki stworzony diagram ma zostać zapisany (zserializowany). Do tego celu bardzo często używa się innej specyfikacji zaproponowanej przez IBM i Microsoft: XDPL – XML Process Definition Language.

W tym miejscu należy wspomnieć o najnowszym członku rodziny BPM czyli o specyfikacji zaproponowanej przez OMG: BPDM – Business Process Definition Metamodel. Finalna wersja tej specyfikacji jest bardzo świeża - pochodzi z czerwca tego roku. BPDM stanowi w pewnym sensie połączenie wymienionych wcześniej standardów: XDPL oraz BPMN ale nie tylko. Przyszłość tego rozwiązania nie jest jeszcze określona i należy poczekać czy zdobędzie popularność. Z pewnością pokłada się w niej duże nadzieje.

Istnieje również kilka innych rozwiązań ale odnoszę wrażenie, że są mało popularne dlatego nie przytacza, ich opisu w tym poście.

Poziom wykonania

Po zdefiniowaniu procesu chcielibyśmy zapewne zasilić nim jakiś silnik, ktory go wykona. W tym celu należałoby przetłumaczyć diagram do formatu/opisu zrozumiałego przez określoną technologię. W obecnej chwili najpopularniejsze wydają się dwie specyfikacje (oparte o XML): BPEL – Business Process Execution Language oraz BPML4WS – Business Process Modeling Language For Web Services. Pierwsza została zaproponowana przez BPMI, a druga przez IBM, BEA Systems oraz Microsoft. Należy zauważyć, że BPML4WS to następca BPML, który nie jest już wspierany. BPEL został oparty o WSFL oraz XLANG.


Rysunek pochodzi z: The BPMN-XPDL-BPEL value chain

Do poczytania

Zarządzanie procesami biznesowymi – standardy notacji i nie tylko

http://modelowanie.wordpress.com/category/bpmnbpml/

Business Process Modeling and Standarization

XPDL,BEPL,JPDL,BPMNS,BPDM et al.. Standards and More Standards

The BPMN-XPDL-BPEL value chain

BPMN, BPEL, BPML and XPDL, an attempt to make some order in the business modeling jungle

A Comparison of XPDL, BPML and BPEL4WS Cape Visions

Business Process Model and Notation (BPMN) 2.0 Request For Proposal


27/11/2008

throw; vs. throw ex;

Home

Nie każdy zdaje sobie z tego sprawę ale poniższe dwie konstrukcje mają inną semantykę:

         try
         {
            ...
         }
         catch(Exception ex)
         {
            throw;
         }
         
         try
         {
            ...
         }
         catch(Exception ex)
         {
            throw ex;
         }
         
Różnica jest taka, że stosując pierwszą z nich nie tracimy informacji zawartej w stosie wywołań (stack trace). To znaczy, że jeśli ponownie rzucony przez nas wyjątek zostanie złapany w kolejnym bloku try/cacth to będzie tam dostępna pełna informacja o stosie wywołań począwszy od pierwotnego źródła wyjątku. W drugim przypadku stos wywołań będzie zawierał ograniczoną informację - będzie wyglądał tak, jakby pierwotnym źródłem wyjątku była metoda, w której został on złapany i ponownie rzucony!

24/11/2008

Zakamarki Visual Studio 2005/2008 (cz. 2)

Home

Zapraszam do zapoznania się z kolejną porcją ciekawych i mało znanych funkcji Visual Studio.

Breakpoint w pętli

Bardzo przydaną funkcją jest możliwość postawienia breakpoint'a w definicji pętli for lub foreach. Załóżmy, że mamy taki kod:
for(int i = GetValue(); i < GetLimit(); i++)
{
  ...
}
Domyślne zachowanie środowiska jest takie, że po kliknięciu linii, w której znajduje się początek pętli i naciśnięciu przycisku F9 breakpoint zostanie ustawiony na części inicjalizacyjnej pętli czyli uzyskamy taki efekt:
for(int i = GetValue(); i < GetLimit(); i++)
{
  ...
}
Czasami, a nawet częściej niż czasami chcielibyśmy aby debugger zatrzymał się w części sprawdzającej warunek pętli. Nic prostszego. Wystarczy przesunąć kursor i ponownie nacisnąć F9. Uzyskamy efekt jak poniżej:
for(int i = GetValue(); i < GetLimit(); i++)
{
  ...
}
Oczywiście debugger możemy zatrzymać również w instrukcji interacji. Podobnie możemy postąpić z pętlą foreach.

Testowanie przy pomocy okna Immediate

Ciekawym sposobem na szybkie testowanie metod statycznych jest użycie okna Immediate. Jeśli nie jest ono standardowo widoczne to znajdziemy je w Debug -> Windows. Po pierwsze okno to pozwala w czasie debugowania wywoływać metody obiektów, zmieniać ich właściwości itd. Po drugie, co jest nawet ciekawsze, umożliwia wywołanie metody statycznej kiedy środowisko nie znajduje się w trybie debugowania. Wykonanie takiej operacji spowoduje uruchomienie debugera i o ile, w metodzie statycznej znajduje się breakpoint, jego zatrzymanie. Dzięki temu nie musimy tracić czasu na pisanie krótkich programików tylko po to aby przetestować daną metodę statyczną. Po trzecie co jeszcze ciekawsze okno Immediate pozwala również w podobny sposób testować zwykłe metody klas. Załóżmy, że napisaliśmy klasę Test i zdefiniowaliśmy w niej metodę Fun(). W oknie Immediate może wpisać:
Test t = new Test(); 
t.Fun(); 
Podobnie jak wcześniej. Jeśli w metodzie znajdował się breakpoint debugger zatrzyma się na nim. Jesli nie, metoda zakończy swoje działanie. Oczywiście technika ta pozwala testować tylko stosunkowe proste scenariusze ale tak czy inaczej ułatwia i przyspiesza tworzenie dobrego kodu.

Opisane techniki testowałem w środowiskach Visual Studio 2005 oraz Visual Studio 2008.