layers pattern in practice - codeproject

Upload: quan-nguyen

Post on 14-Apr-2018

226 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    1/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Articles Platforms, Frameworks & Libraries Windows Presentation Foundation Applications

    Layers Pattern in PracticeBy Ciumac Sergiu, 23 Apr 2010

    Download executable - 916 KB

    Download setup executable - 1.25 MB

    Download sources - 0.99 MB

    Download additional libraries - 514 KB

    IntroductionBackground

    Technology used

    Conceptual integrity

    Objectives

    Data Access Layer

    Entity Objects

    Business Logic layer

    Presentation Layer

    Datagrid

    Disconnected Data Environment

    4.94 (52 votes)

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    2/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Styling the grid

    Chart

    Post release debugging

    Testing

    Source code

    Conclusion

    The main task of this article is to present a generic application's lifecycle, with problems and solutions to common issues which programmers face on a

    daily basis. Once you start building an application, you ought to take into consideration lots of things, mainly from different theoretical areas of

    programming. Of course, as an architect of a software product, you might bump into different problems, mainly related to understanding of the entire

    omplexity of the project, at the very beginning of the specification design. The aim of the text written below is to highlight key points which one nee

    ake into account at the start of the application conception. Herein, a simple WPF software product will be presented as an example, starting from its

    pecification design, going through the development of a 3-tiered class hierarchy (User interface design - GUI; Business Logic - further noted as BL; an

    Data Access Layer - DAL), and ending up with a setup project and post-release debugging. One can argue that "programming is an art" and there is n

    need to define generic rules beforehand, constraining the architect's mind. Indeed it is so, and the article will actually try to show solutions to common

    problems in Windows application design, leaving the choice of the lifecycle methodology to the architect.

    Where architecture tells what happens, implementer tells how it is made to happen" Blaauw

    The tutorial written below will try to encompass both the architect's and the implementer's mind by showing what and how problems are solved togetThe software example which is going to be presented is a BillsManager. The application's ultimate goal is to allow a client to manage his bills (simple

    traightforward).

    Technology used

    decided to build BillsManager as a Windows application based upon the rising in popularity Windows Presentation Foundation technology. I find it v

    prominent and really a step forward in Windows based development. The Data Access Layer will be constructed around XML files which will store the

    ser's bills. So, as it can be inferred, the minimal requirement is .NET 3.5 SP.1.

    Conceptual integrity

    Conceptual integrity is the most important consideration in system design" Frederick Brooks

    ndeed, as practice shows, in order to successfully build any software, one should clearly define written specifications (a necessary tool, although not a

    ufficient one). From theory to practice - below is a list of the main objectives which BillsManager is going to meet.

    Objectives

    Show how much money a person needs to spend this month

    Archive the payments

    Show the nearest deadline

    Chart the expenditures

    Chart the expenditures by an interval of time

    Show information about every bill

    Give the possibility to export the archive in a file for backup

    Assume that the target audience is not English-speaking

    BillsManager will try to accomplish these fairly straightforward objectives. Although one can argue that these specifications are not enough to build a

    uccessful application, I will leave them as they are in order, not to increase the complexity of the example on which all the explanatory part is built up

    ier applicationSoftware architecture encompasses the set of significant decisions about the organization of a software system, including the selection of the structural

    lements and their interfaces by which the system is composed; behavior as specified in the collaboration among those elements; composition of these

    tructural and behavioral elements into larger subsystems; and an architectural style that guides this organization. Software architecture also involves

    unctionality, usability, resilience, performance, reuse, comprehensibility, economic and technology constraints, tradeoffs, and aesthetic concerns" P.Kruchte

    ooch, K. Bittner, R.Reitman

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    3/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    As it is stated in the above self-descriptive paragraph, while designing the application, the software architecture team should have in mind a strong vie

    bout how the requirements will be projected into the real environment, and how this environment can be as generic as it is possible. Separation of

    nterfaces, business logic, and data access layer is a very important and also common need in software development. Essentially, nowadays, reusability

    plays a crucial role within the Object Oriented paradigm. The BillsManager application will implement the 3-layered structure using the Layers Pattern

    guidelines. Figure 1 below shows a general view of the systematization which is going to be used.

    A 3-layered pattern is used in order to build better organized software parts. It provides a mechanism of defining reusable business components,

    longside with deployment flexibility and smart resource connection management. All the components which are responsible for data visualization (e

    DataGrid) will be placed in the Presentation Layer. All business logic rules will be encapsulated in business components within the BL layer. Finally, al

    data related code needs to be defined within the Data Access Layer. Frequently, the DAL layer is responsible for database access. In the example prov

    n this article, the database will be an XML file (but that does not make a difference as long as the GUI and the BL are not aware of the underlying data

    ource). A more advanced explanation of this pattern can be found in Enterprise Solution Patterns using Microsoft .NET.

    ta Access Layern order to have a flexible architectural component, I will start with the contract (interface) which each DAL connection manager should implement in

    order to meet the requirements of the Domain Layer. Following is the code for the IDalBillsManager interface.

    ////// Interface for Bills' data source manager///publicinterface IDalBillsManager{ /// /// Read bills ///

    Bills Read(DateTime fromDate, DateTime toDate); ///

    /// Read a bill from datasource by its ID

    ///

    Bill ReadById(Guid id); /// /// Insert bills into the datasource /// void Insert(Bills bill);

    /// /// Delete a bill from datasource /// int Delete(Guid guid); ///

    /// Delete a enumeration of bills from the datasource

    ///

    int Delete(IEnumerable guids); /// /// Update the bill from database /// int Update(Guid billId, Bill newBill); /// /// Set settings for DAL Provider /// object[] Settings

    { get; set;

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    4/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    }}

    As it can be seen from the methods which need to be implemented, they define a very general contract which can be summarized in the following

    esponsibilities:

    Read bills from the data source (can be any data source: XML, Excel, SQL Server, network resource, etc).

    Delete bills from the data source.

    Update bills in the data source.

    Insert bills in the data source.

    Get or set the settings for the data source (e.g., connection string, path to archive file, etc.).

    t is important to point out that the contract should relinquish the following rule within [IN] and [OUT] parameters. It should have:

    Most general parameters at the input [IN] (E.g., IEnumerable interface)

    Most specific return types [OUT] (E.g., Bills)

    ubsequent to the interface definition, it is valuable to mention that the Business Logic programmer will access methods of the DAL Manager only

    hrough an interface instance.

    private IDalBillsManager _dalManager = XmlDalBillsManager.GetInstance();

    f in a future development cycle, you choose to switch the DAL Manager to another version or to an entirely new library, you will need to change only

    ne of code, which is the assignment operation written above. After doing this, the entire business logic library will work as it is supposed to, without

    equiring any other changes in the code. The responsibilities, defined in the IDalBillsManager interface will be held by the Data Access Manager. I

    our case, it will be an XML-based DAL Manager, meaning that all the bills information will be stored in an XML archive file. Below, you can see the XMLchema on which our archive will relinquish (this schema is located in BillSchema.xsd under the BillEntityLib project folder). It is very important to note

    our XML will use strongly established rules of composition.

    The XSD file describes the content that is allowed in an XML document in order for the last one to be considered valid (i.e., within the defined constraif you are not comfortable with XML schemas and their rules, please consult any available material on this topic. Our XML schema is formed from the

    ollowing elements:

    Bills (Root element)

    Bill (Will represent every bill)

    Name (Name of the bill)

    DueDate (Bill's due date)

    Amount (Bill's amount)

    AddedOn (When was the bill added on)

    Status (Bill's status)

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    5/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Our XML-based Data Access Manager will be a singleton object (meaning that where will be only one instance of the object in the entire application

    fecycle). If you are not familiar with singletons, please consult the Singleton pattern article for a better explanation. The following figure presents the

    diagram for the XmlDalBillsManager class. (Please notice that it implements the IDalBillsManager interface.)

    Consequently, our XML based manager should support thread-safe operations (so that the archive does not get corrupt if multiple threads attempt to

    write to the database at the same time - which could result in data loss or unpredictable behavior). Thus, the user is allowed to call the operations

    Insert, Read, Update, and Delete without a clue of how the archive is protected from corruption. As it is not difficult to observe, here we can

    mplement the Readers/Writers thread algorithm in order to solve the above mentioned problem. Herein, the manager will implement the following po

    If somebody reads the data from the archive, other readers are allowed to perform the same operation (access for writers is prohibited).

    If somebody writes the data into archive, no other thread (read or write) can perform any operation with the above mentioned data source.

    or a more detailed review, please consult any available material related to the Readers/Writers threading algorithm.

    tity ObjectsHaving the XML schema defined, we can now generate entity classes. These are the classes which do not hold any responsibility (do not have any

    methods). They are just binary representations of the data from the XML. The Bills and Bill classes will perform only the storage function within t

    Business Logic Domain (they will not have any additional methods except getters/setters for their properties). There are different approaches within th

    ayers pattern regardless of the entity and business logic elements. You can define the business logic methods (Insert, Read, Delete, Update) in t

    ame classes in the entity library (we'll see later what methods will actually be implemented in the business domain). The others can be separated in tw

    different classes. I've used the following separation of business components:

    Entity classes

    Manager class

    Don't worry if you do not understand the entire concept; you'll get it once you take a look at the actual implementation. I've decided to perform the

    eparation, because it is more natural to have exactly the same copy of a Bill item in the computer memory as it is in the data source (no matter wh

    data source: XML, text, Excel, relational database, etc.). At the same time, these entity objects will actually be serializable. This feature will allow any .NE

    programmer to extend the program functionality by adding a new layer within the Business Logic and the Data Layer and pass objects from the Busine

    Domain to the Data Domain in serialized state. Serialization allows to save an object's state (Bills and Bill) into any stream (memory, network, file,

    and pass it within the Application Domain or Remoting services.

    rom BillSchema.xsd, we can see that there will be only two entity classes: Bills and Bill. .NET provides an easy mechanism for generating .cs files

    xsdschemas. This mechanism is achieved through the XML Schema Definition tool. One can access xsd.exe through Visual Studio's command prompt

    by opening the command line and navigating to c:\Program Files\Microsoft Visual Studio 9.0\VC>. The command which needs to be applied is xsd [na

    of xml schema].xsd /c. By applying this command, the XSD tool will generate partial classes which correspond to the schema definition.

    //------------------------------------------------------------------------------

    //

    // This code was generated by a tool.

    // Runtime Version:2.0.50727.4926

    //

    // Changes to this file may cause incorrect behavior and will be lost if

    // the code is regenerated.

    //

    //------------------------------------------------------------------------------

    using System.Xml.Serialization;

    //

    // This source code was auto-generated by xsd, Version=2.0.50727.3038.

    //

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    6/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    ///[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.303")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true,

    Namespace="http://tempuri.org/billschema.xsd")][System.Xml.Serialization.XmlRootAttribute(

    Namespace="http://tempuri.org/billschema.xsd",IsNullable=false)]

    publicpartialclass Bills {/*Bills collection from the datasource*/

    private Bill[] itemsField;

    ///[System.Xml.Serialization.XmlElementAttribute("Bill")]

    public Bill[] Items { get { returnthis.itemsField;

    } set { this.itemsField = value;

    }}

    }

    ///[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/billschema.xsd")]

    publicpartialclass Bill {/*Each bill from the datasource, has exactly the same properties*/

    privatestring nameField;

    private System.DateTime dueDateField;

    privatedecimal amountField;

    private System.DateTime addedOnField;

    privatestring statusField;

    privatestring idField;

    ///

    publicstring Name {

    get { returnthis.nameField;

    } set { this.nameField = value;

    }}

    ///

    public System.DateTime DueDate { get { returnthis.dueDateField;

    } set { this.dueDateField = value;

    }}

    /// publicdecimal Amount { get { returnthis.amountField;

    } set { this.amountField = value;

    }}

    ///

    public System.DateTime AddedOn { get { returnthis.addedOnField;

    } set { this.addedOnField = value;

    }

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    7/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    }

    /// publicstring Status { get { returnthis.statusField;

    } set { this.statusField = value;

    }}

    ///[System.Xml.Serialization.XmlAttributeAttribute()]

    publicstring ID { get { returnthis.idField;

    } set { this.idField = value;

    }}

    }

    ollowing is the class diagram for the Entity objects. Please note that I've added some additional class members to those which were generated. (I wil

    xplain later why there was a need to implement the INotifyPropertyChanged interface by the Bill class).

    siness Logic Layerwill now discuss the Business Logic responsibilities and how they were materialized in the actual code. As in the case of the Data Domain, I've decided

    define an interface IBillsManager which is going to deliver the contract to all the classes which will implement that interface. Here is the definition

    he IBillsManager interface:

    ////// Interface for Bill manager business logic///publicinterface IBillsManager{ /// /// Read from data source ///

    Bills Read(DateTime fromDate, DateTime toDate);

    /// /// Reads a bill by its ID

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    8/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    ///Bill ReadById(Guid id);

    /// /// Insert a bill into the database

    ///

    void Insert(Bills bill);

    /// /// Delete a bill from database /// int Delete(Guid bill);

    ///

    /// Delete a list of bills with the specified guids ///

    int Delete(IEnumerable guids);

    /// /// Update a bill in the database /// int Update(Guid billId, Bill newBill);

    /// /// Settings /// object[] Settings

    { get; set;

    }}

    You can see that the aforementioned interface defines exactly the same methods as the Data Layer interface IDalBillsManager. Yes, indeed the

    methods are the same because the actual responsibilities are also the same. The only difference is that every manager (either from the Business Doma

    rom the Data Layer) is responsible for different logical operations on the data which passes through. As an example, see the following figure:

    As can be seen, even though the method signature for both the Business and Data Domain is the same, internally, they are responsible for different

    ogical interactions within the objects. In the above example, the Business Domain insertion operation is responsible for:

    Validation

    Sending the request to the Data Layer

    Checking whether the Insert operation occurred or not

    Throwing an exception if appropriate

    At the same time, the Data Layer is responsible for:

    The actual insert operation into the data source

    One can argue that there was no need to define two different interfaces with the same signature for the Business and Data Domains; instead, I should

    have used the same interface for both. I definitely consider this argument a mistake, because the client programmer would be able to cast Business an

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    9/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Data Logic objects into the same interface, without a clue of whether he accesses methods from one or the other domain. This approach breaks the en

    philosophy of layer separation and should never be used.

    sentation LayerThe last but not the least layer in the pattern is the Presentation Layer. It is actually responsible for the interaction between the user and the machine.

    There are plenty of topics which one might find useful while developing a GUI (Graphical User Interface). If you are building a WPF application, you mi

    nd it useful to check Sacha Barber's articles here at CodeProject. Anyway, I will cover several of them which I think are the most generic ones. We'll st

    with the DataGrid, a component which is responsible for presenting the data to the end user. Then we'll move to a more specific problem as charting

    data and localizing string resources.

    Datagrid

    By default, .NET 3.5 does not ship a WPF datagrid component. There are different viewpoints whether it is good or not. I will just point out that I decid

    ike many other developers) to use the WPFToolkit which can be freely downloaded from the CodePlex site (click here), in order to have a built-in

    DataGrid with all the bells and whistles. Personally, I find those components really useful, so I really encourage everybody to explore them.

    A core action one needs to define in a data grid is its binding to a data source. Binding is the concept of establishing a connection between a UI (use

    nterface) component and the business logic. There is a very nice article on the MSDN site which explains how binding works in WPF components (clic

    here). Typically, each binding has these four components:

    a binding target object

    a target property

    a binding source

    a path to the value in the binding source to use

    or example, if you want to bind the content of a TextBox to the Name property of an Employee object, your target object is the TextBox, the targ

    property is the Text property, the value to use is Name, and the source object is the Employee object. Here is the XAML code which declares and de

    he DataGrid for BillsManager with the necessary binding.

    As can be seen, each DataGrid column is bind to a specific property from our Entity's library Bill class.

    Name - Binding="{Binding Name}"

    DueDate - Binding DueDate, Converter={StaticResource DateConverter}Amount - Binding="{Binding Amount}"

    AddedOn - Binding="{Binding AddedOn, Converter={StaticResource DateConverter}}"

    Status - SelectedItemBinding="{Binding BillStatus}" ItemsSource="{Binding Source={StaticResource myEnum}}"

    t is worth mentioning that the Converter item from the DataGrid column definition will perform the formatting operation ofDataTime values (it

    how the date in short format DD.MM.YY). Shown below is the actual code for the converter item:

    [ValueConversion(typeof(DateTime), typeof(String))]publicclass DateConverter : IValueConverter{ /*

    * Convert each data item from the data grid into short format DD/MM/YY

    */

    publicobject Convert(object value, Type targetType,object parameter, CultureInfo culture)

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    10/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    {DateTime date = (DateTime)value;

    return date.ToShortDateString(); /*Show the date in the datagrid in Short format*/

    } /*Convert back*/

    publicobject ConvertBack(object value, Type targetType,object parameter, CultureInfo culture)

    { string strValue = value asstring;

    DateTime resultDateTime; if (DateTime.TryParse(strValue, out resultDateTime))

    { return resultDateTime;

    } return DependencyProperty.UnsetValue;}

    }

    The code above binds the data to Bills, following this logic:

    To bind the datagrid to data, set the ItemsSource property to an IEnumerable implementation. Each row in the datagrid is bound to an object in th

    data source, and each column in the datagrid is bound to a property of the data object. In order for the DataGrid user interface to update automatically

    when items are added to or removed from the source data, the DataGrid must be bound to a collection that implements INotifyCollectionChange

    uch as an ObservableCollection. In order to automatically reflect property changes, the objects in the source collection must implement the

    INotifyPropertyChanged interface". Click here for more details.

    Bills from the data source are represented in the computer memory via the Bills class. Afterwards, these items are embedded in the

    ObservableCollection collection. In this way, we can add, remove, edit elements of underlying list of bills without actually taking care of

    pdating the user interface to reflect the changes (.NET will perform this automatically). Click here for more details.

    As written above, we'll bind the data grid item source property to ObservableCollection.

    _collection = new ObservableCollection(bills.Items);//define the ObservableCollection class

    this._datagrid.ItemsSource = _collection;//bind the data to the datasource

    Disconnected Data Environment

    will now discuss the disconnected data environment approach which was implemented in our BillsManager application. This environment gives us an

    nswer to how updates, deletes, and inserts of bills objects to the data grid control are reflected in the actual data source. Generally, there are two bas

    mechanisms:

    Connected Data Environment - once an entity (Bill) is modified in the Business Domain, the actual modification is also performed in the Data

    Domain, meaning that a strong bidirectional relationship is defined within both layers.

    Disconnected Data Environment - entities (Bills) which are modified in the Business Domain are marked as updated, but no modifications are

    performed in the Data Domain. Once a crucial action is performed within the application (e.g., the application is closed), all the fields which are

    marked as updatedare modified in the Data Domain according to their new values.

    This second approach has a lot more advantages in its use. Mostly, these advantages relate to a lot more flexibility. Imagine a user changing a bill's sta

    rom Unpaid to Paid. Also, he might want to modify the Amount field of the same bill. In the connected data environment, these operations will resu

    he following method calls:

    Change bill's status property from Unpaid to Paid

    Change bill's amount property

    n a disconnected data environment, the aforementioned operation will result in the following:

    Mark the bill as Updated (please note, this operation will not call any method from the Data Domain).

    Once the Commit operation is called, update both bills' properties at once.

    The above mentioned mechanism was possible through the usage of the Publish/Subscribe event model. Every bill entity allows any client to subscrib

    ts PropertyChangedEventHandler PropertyChanged event. Once you've subscribed to this event, you'll receive a notification whether a bill's

    property was changed.

    Styling the grid

    The style of the grid is located in the resource dictionary (DataGrid.Generic.xaml). The interesting thing about the style of the grid is conditional

    ormatting. Once a bill's due date is overdue and a bill's status is Unpaid, the data row changes its color from transparent to yellow. This is done thro

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    11/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    onditional formatting. A developer can set the ItemContainerStyle property of the grid to an element which will dynamically change the

    background of the data row according to some logics defined in the code behind. So we'll define a new resource dictionary element and call it

    ItemContStyle:

    The DataRowBackgroundConverter class's Convert method will be invoked. According to the data which is set in the data row, it will return Yel

    or no color.

    [ValueConversion(typeof(object), typeof(int))]publicclass DataRowBackgroundConverter : IMultiValueConverter{ #region IMultiValueConverter Members /*

    * Check each element for the corresponding background color

    */ publicobject Convert(object[] values, Type targetType,

    object parameter, CultureInfo culture){

    if (values[0] is DateTime){

    DateTime dueDate = (DateTime)values[0]; string status = values[1] asstring; if (dueDate < DateTime.Now &&

    BillHelper.Convert(status) == BillStatus.Unpaid){

    returnnew SolidColorBrush(Colors.Yellow); /*Return Yellow if DueDate is overdue and BillStatus is unpaid*/

    }}

    returnnull;}

    publicobject[] ConvertBack(object value, Type[] targetTypes,object parameter, CultureInfo culture){

    thrownew NotImplementedException();}

    #endregion}

    As you can see, WPF offers great flexibility in terms of data binding and data formatting.

    Chart

    Charting is a topic which is definitely very often discussed on programming forums. Many people find it challenging, because lots of things need to be

    aken into consideration. I decided to use a third party charting tool rather than the one defined in the WPFToolkit. It can be freely downloaded from

    Visifire site. It is a framework which provides Open Source data visualization components. I find it very nice and easy to use. The things which I would lo point out are, that the chart itself draws the data according to a set of different parameters, which can be set in many ways ( DataSeries - series o

    data points which actually represent the pair X, Y, where F(x) = Y; Axis - pie, line, bar, 2D, 3D, etc., Title - the actual title text). In order to have an

    xtensible mechanism of drawing the chart using different Axis, I decided to use the Strategy pattern. The strategy is actually the way how axis will b

    epresented (this is done in order to have three different types of chart: Line, Bar, Pie). The following figure presents the class diagram for these items:

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    12/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Consequently, chart properties are set according to one of the methods of drawing it:

    //chartType object of type IChartingpublicstaticvoid SetChartValuesAsync(Chart chart, IEnumerable list,

    ICharting chartType, IntervalTypes interval,ChartValueTypes chartValueType, bool scrollingEnabled, bool erasePrevious)

    { if (chart != null)

    {chart.Dispatcher.BeginInvoke(new Action(delegate(){

    if (erasePrevious){

    chart.AxesX.Clear();chart.AxesY.Clear();chart.Titles.Clear();chart.Series.Clear();

    }

    // Add title to Titles collection

    chart.Titles.Add(chartType.GetTitle(list.First().Name)); /*Set Axis via interface instance*/

    chart.AxesX.Add(chartType.GetAxis(interval, list));chart.ScrollingEnabled = scrollingEnabled;chart.Series.Add(chartType.GetDataSeries(list, chartValueType));

    }), null);}

    }

    As we can see, the mechanism is maintainable and extensible, because even if we add new types of charts in the following versions of the application,

    only need to implement the corresponding ICharting interface and pass an object of its type to the SetChartValuesAsync method. In the figur

    below, we can see an example of the aforementioned settings adjustment:

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    13/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    Localization

    ocalization is the process of preparing an application to run in multiple locations. The .NET Framework provides very thorough support for localizing

    ypes of client applications. Culture information and manipulation in the .NET Framework is exposed through an instance of the CultureInfo class,

    which can be used to read culture settings for a given locale, as well as setting a specific locale in an application. Every thread maintains a set of cultur

    nformation stored as CultureInfo settings in the CurrentCulture and CurrentUICulture properties.

    WPF applications have two possibilities to set different locale statuses:

    LocBaml tool

    Resx approach

    n my application, I'll be using the Resx resource files approach (mainly because it is a classical way of setting different locales in Windows Applications

    Resx files are XML based f iles which are compiled into resource.dll libraries and can be loaded into the application via the ResourceManager class. T

    ollowing snippet shows the code which performs the actual load:

    CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;string culture = ConfigurationManager.AppSettings["Culture"];if (!String.IsNullOrEmpty(culture)) if(culture != "Default")

    currentCulture = new CultureInfo(culture);ResourceManager resx = new ResourceManager( "BillPayManager.Properties.Resources", typeof(App).Assembly);

    The currentCulture object will hold a thread's culture description. The resx object will allow us to query the .dll file with the actual cultural specifi

    nformation. The default culture is read by the BillsManager application from the application configuration file (Key = "Culture"). It is important t

    mention that if the App.config file doesn't explicitly set culture information, then the en-US culture will be used. Here is a query example:

    this._lTotalAmount.Content = resx.GetString("TotalAmount", currentCulture);this._lNearestDeadline.Content=resx.GetString("NearestDeadline",currentCulture);

    The resource files are stored within the folders with the same name as cultural info (en-US, ro-RO). Next, we can visualize how MainAssembly gets t

    esources from the corresponding directories (see figure).

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    14/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    n order to change the culture, please change the BillPayManager.exe.config file or change it via the Miscellaneous tab:

    Be attentive while changing the Culture key. You can explicitly set only cultures defined in the corresponding sub folders (en-US or ro-RO).

    st release debuggingThe importance of post release application debugging cannot be underestimated. Even though testing of the application can end up in a very small

    number of undetected bugs, once installed on user machines, the application behavior cannot be predicted. This might happen because of several

    easons: user has no admin privileges, the OS internal configuration is different of expected ones, or your application demands read/write operations t

    ritical regions as the root directory of the system drive (usually C:\), the HKLM (local machine) key in the Registry, etc. Yet, developers have a mechani

    which allows them to figure out problems which appear on the client-side machine, without the need to literally come to the client's office or home. Th

    mechanism is called Tracing.

    ven though we are unable to predict where and when the application is going to crash, we can assume that in some critical points, it might have

    problems of doing some sort of operations. These critical points can be marked as traceable. Once the application reaches these points, we ought to w

    he information about the current state (variables, stack trace etc.) in a file, which, if needed, can be shipped to developers in order for them to solve th

    problem. Having the application's log file will allow them to recall steps which caused the application to crash. This simple mechanism can save huge

    mounts of time and money. .NET Framework is shipped with the System.Diagnostics namespace, which has plenty of features that can help us t

    race, debug, and monitor the performance of our application. The class in which we are interested in order to meet the post-installation debugging

    purpose is the Trace class. Next, I will post a passage from here which best describes the purpose and usage of the aforementioned class.

    You can use the properties and methods in the Trace class to instrument release builds. Instrumentation allows you to monitor the health of your

    pplication running in real-life settings. Tracing helps you isolate problems and fix them without disturbing a running system. This class provides meth

    o display an Assert dialog box, and to emit an assertion that will always fail. This class provides write methods in the following variations: Write,

    WriteLine, WriteIf, and WriteLineIf. The BooleanSwitch and TraceSwitch classes provide means to dynamically control the tracing outpu

    You can modify the values of these switches without recompiling your application. You can customize the tracing output's target by adding

    TraceListener instances to or removing instances from the Listeners collection. The Listeners collection is shared by both the Debug and thTrace classes; adding a trace listener to either class adds the listener to both. By default, trace output is emitted using the DefaultTraceListener

    lass.

    The Microsoft Best Practices team advices developers to use the App.config file for the adjustments of trace listeners (this is pretty obvious, as long as

    hanges in application configuration file do not require recompilation). Anyway, I've decided to adjust the diagnostics objects in the code because of

    everal issues. As an example, consider you want to use DelimiterTraceListener as your main listener. Once you have specified in App.config the

    path to the file that will actually store the output messages, you have no way of checking whether the user has write privileges to that location or not.

    means that if the user doesn't have the required permissions, the application will throw an exception at startup once the CLR tries to instantiate the

    forementioned objects. Because of this, the BillsManager application adjusts Trace objects in the method which is written below.

    ///

    /// Initialize Delimited Trace listener

    ///privatevoid InitializeDelimitedTraceListener()

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    15/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    { bool enabled; string tracepath = ""; try

    {enabled = Convert.ToBoolean(ConfigurationManager.AppSettings["BooleanSwitch"],_currentCulture);

    tracepath = System.IO.Path.GetFullPath(ConfigurationManager.AppSettings["PathToTraceFile"]);

    } catch (FormatException)

    {enabled = false;/*Disable Boolean switch*/

    } this._chbTrace.IsChecked = enabled; string path = ProbeFilePermissions(tracepath, FileIOPermissionAccess.Write); /*Check if user has enough privileges to Write in the corresponding folder */

    if (path != tracepath){

    try{

    ModifyAppConfig("PathToTraceFile", path); /*Modify App.Config if another path is chosen*/

    } catch(ConfigurationErrorsException)

    {Debugger.Break();

    }}

    long maxSize = 1045680;/*1 MB*/ try

    {maxSize = Convert.ToInt32(ConfigurationManager.AppSettings["SizeOfTrace"]);

    /*Max Size of trace file*/}

    catch (FormatException){

    Debugger.Break();}

    finally{

    try{

    FileInfo fileInfo = new FileInfo(path); if(fileInfo.Length > maxSize)

    File.Delete(path);

    } catch(Exception)

    {Debugger.Break();

    }}DelimitedListTraceListener listener = new DelimitedListTraceListener(path)

    {Delimiter = "__",IndentSize = 4,TraceOutputOptions = TraceOptions.DateTime

    };Trace.Listeners.Add(listener);/*Adding listener to the collection*/Trace.AutoFlush = true;

    this._bSwitch = new BooleanSwitch("Switch", "Switch");_bSwitch.Enabled = enabled;

    this.TraceSystemSettings();/*Tracing system settings*/

    }

    The ProbeFilePermissions() method probes the location for FileIOPermissionAccess.Write, and if the user lacks the specified permissio

    eturns an alternative path to which the user has Write privileges.

    Testing is one of the most unpleasant parts of developing an application. There are different approaches to the way how testing is performed (Manual

    Automation testing, Unit tests). They depend mostly upon what methodology was used in software development. I prefer using Unit tests because the

    s a great way of visualizing the Data Flow, Exceptions, Assertions, etc. In order to write a unit test, we needs to install the NUnit framework, freely

    downloadable from their official website. Once installed, you can use features available in the NUnit.Framework namespace in order to test any pu

    method. For more information about writing Unit Tests, click here.

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    16/17

    ers Pattern in Practice - CodeProject

    2/5/2013 2:09//www.codeproject.com/Articles/75082/Layers-Pattern-in-Practice?display=Print

    rce codeve written the application using Visual Studio 2008 TS. The source code is structured as follows:

    BillManagerUninstallAction project. Custom uninstall action implemented in order to delete all the associated files (archive and trace output) on

    the application is uninstalled from the user's machine.

    BillPayManagerproject. This is the actual WPF application. The GUI was developed using the Expression Blend 3 IDE.

    BillsBusinessLogicLib project. The library contains all the necessary classes for Business Layer management (BL). Main class - BillsManager.

    BillsDalLib project. The library where all XML data access related code is located. The main class for DAL is - XmlDalBillsManager.

    BillsEntityLib project. Entity library.

    TestBillPayManagerproject. Several Unit Test fixtures are written in this project. I've deleted the project from the solution configuration in order

    people who don't have NUnit installed on their machines to be able to compile the solution without errors. If you want to build it, please add it

    the project.

    TestBillPayManagerManual project. Manual tests written for GUI testing. The project is also unloaded.

    SetupBillPayManagerproject. Setup for BillsManager.

    n order to successfully compile the project, we need additional libraries referenced in the BillPayManagement project. These libraries are:

    AvalonControlsLibrary

    WPFToolkit

    Visifire

    During my student's life, I've always had enough books on software design. Even if each of them provides very nice analysis of software architecture, of them speaks about issues related to practical implementation. This is due to the fact that authors are most likely to speak in abstract terms, in orde

    o tie themselves to a specific technology (.NET Framework in my case). This is of course great, but I've always wanted a guide which will have as an

    xample a complete product, starting from the specification design and ending up with the setup project. The aim of this article is to speak about the

    main issues related to .NET Windows application design, not in terms of theory, but in terms of practice. You can argue that architecture design is a to

    which differs from one product to another, and it's mostly impossible to speak about every tiny problem which you will encounter during an applicati

    fecycle. This is of course true, but the article's target audience is "computer science students" and not senior developers who already know all the stu

    written in here. That's why I've designed a simple WPF application in order to have a generic guide for students (or uninitiated WPF developers) who

    would like to build these types of applications. I've tried to keep the article's size as small as possible, but somehow it extended above initial expectatio

    Thanks for reading.

    Alex Railean - http://railean.net/ for helping me writing this article.Victoria - for being kind.

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    out the AuthorCiumac SergiuSoftware Developer

    Moldova (Republic Of)

    Member

    nterested in computer science, math, research, and everything that relates to innovation. Big fan of C# programming language, but don't mind

    developing under any platform/framework if it explores interesting topics. In search of a better programming paradigm.

  • 7/30/2019 Layers Pattern in Practice - CodeProject

    17/17

    ers Pattern in Practice - CodeProject

    ermalink | Advertise | Privacy | MobileWeb04 | 2.6.130204.1 | Last Updated 23 Apr 2010

    Article Copyright 2010 by Ciumac Everything else Copyright CodeProject, 1999

    Terms

    ments and Discussions31 messages have been posted for this article Visit http://www.codeproject.com/Articles/75082/Layers-Pattern-in-Practiceto post and view

    omments on this article, or click here to get a print view with messages.