tangible architect provides a clear architecture for your applicationYou are looking for a great way to structure an information system that is intuitive for the whole team? We found that most programmers are familiar and comfortable with the way Microsoft Office Applications expose their functionality to programmers in form of an object model.
An object model has one root object, e.g. MyApplication, from which all other objects are accessible by navigating object relationships. The following diagram shows an object model for an addressbook application. The object model is used by some client code, and the object model automatically stores its data in a database - hiding the details of SQL programming from the developer. Each class in an object model is described by a C# interface from which it can be generated.
Using the navigational approach to retrieve objects from a database is natural when you think of business logic code that modifies an order and related items, or a treeview that displays a hierarchy of items. In addition, an object model provides query functionality so that specific objects can be retrieved directly just by specifying the desired object characteristics.
Writing client code against an object model is easy as the object model is completely strong-typed so that Intelli-Sense and the XML Code Commments feature can help the developer. Have a look at a code snippet that opens a database connection and creates a few objects:
private CRM.IAddressBook theAddressBook;
// instanciate the object model and connect to the database create
theAddressBook =
new CRM.AddressBook(new ConnectionSettings(
"CRM_DB");
// Create a named Customer and a named Employee
CRM.ICustomer theCustomer1 = theAddressBook.Customers.CreateCustomer(
"Mr. Mayer");
// Create a service request bi-directionally linked to the customer
CRM.IServiceRequest theServiceRequest
= theCustomer1.RequestedServiceRequests.CreateServiceRequest(
"Problem " +
"with TV in room");
theServiceRequest.IssueDate = System.DateTime.Now;
theServiceRequest.PriorityLevel = 2;
// link Employee to CustomertheCustomer1.ContactPersons.LinkEmployee(theEmployee1);
Having hidden the database access code - so that the application model itself gets more focus - the next step is to design the business logic of an application. It is industry's best practice to separate business logic code and user interface code for two major reasons: First, the application is easier to maintain if business logic is concentrated in one dedicated layer rather than being distributed or hidden in event handlers of user interface elements. Second, in a Web and Client/Server enabled application, business logic must be commonly available and shared between WinForms and WebForms. The persistent object model is extensible and provides an ideal location for your business logic: User Classes. A User Class is generated for each C# interface description and inherits from a generated persistent base class, which provides the methods and implementation for data-access. You can override the default implementation of the data-access methods or add your own methods and event handlers to realize the business logic of your application as outlined in the following samples.
Sample Business Rules:
- Customer account numbers may only be assigned once
We realize this by overriding the property AccountNumber in the User Class.
- Customer's average discount must be calculated
We realize this by adding a method to the Customer User Class and Interface.
Here is the code for the User Class "Customer":[Persistent]
public class Customer : Persistence.PsCustomer, ICustomer
{
// Internal Constructor of the AddressBook User Class
internal Customer(object RootObject)
: base(RootObject)
{
}
public int AccountNumber
{
get
{
return base.AccountNumber;
}
set {
if (AccountNumber != 0 )
{
throw new Exception("Account number may only be set once");
} else {
base.AccountNumber = value;
}
}
}
public double GetAverageDiscount()
{
double averageDisc;
// TODO: calculate average discount
return averageDisc;
}
}
Sample Business Rule 3: account numbers are assigned by an external systemWe will realize this rule by adding a Customers_AfterCustomersCreate event handler to the parent class "Addressbook" using the tangible architect class wizard. Here is the implementation for the User Class Addressbook:
/// This is the User Class for AddressBook
/// you can add your business logic here.
[Persistent,RootObject]
public class AddressBook : Persistence.PsAddressBook, IAddressBook
{
// Constructor of the AddressBook User Class
public AddressBook(ConnectionSettings connSettings)
: base(connSettings)
{
}
// The OnInit Method was automatically added by the Class Wizard
// when you attach to the AfterCustomersCreate Event
override public void OnInit()
{
AfterCustomersCreate += new CRM.ICustomerContainsCol.AfterCustomerCreateHandle
(Customers_AfterCustomersCreate);
}
// This event handler assigns a valid AccountNumber that is requested from a ERP System
private void Customers_AfterCustomersCreate(ICustomer inCustomer)
{
inCustomer.AccountNumber = ABAPHelper.getFreeAccountNumberFromSAP();
}
}Implementing your business logic directly in the user classes has several advantages. One of the biggest benefits is that your business rule implementation is directly attached to the object it relates to. The User Classes represent the hand-written code of your business logic. This way, business logic can be clearly identified as it is not mixed up with data-access code or user interface code.
tangible architect generates the database access code and schema As already mentioned, User Classes inherit from generated base classes that implement the data-access. In contrast to most other frameworks, tangible architect doesn't use DataSets for data access and there is good reason for that: DataSets use optimistic locking. Optimistic locking basically assumes that there is only one user changing the target data at any given time. If there is a conflict because data has been changed by another user, changes must be rolled back and the user must be notified that his work is lost - a very annoying experience for that user. Therefore tangible architect uses by default pessimistic locking. That way, if a user tries to edit data which is currently being edited by another user, he gets notified of this circumstance and is asked to try again later. This way users get notified of potential conflicts on time - before any work is lost. With this additional reliability even complex object models with 200+ relationships can be modified safely in one transaction.
But there's more: The tangible architect runtime is even able to generate and install the database schema based on the interface definitions that you provide. So there is no need to create a DDL Script by hand. Based on this mechanism, tangible architect also provides you with an object-oriented database browser that makes debugging database applications noticeably easier.
To summarize, a persistent object model has advantages in regards to clarity, reliability and maintainability. Furthermore, it can be generated from your UML model or C# interface descriptions.
tangible architect helps you communicate architectureYou like to document in UML. But some of your team members are in love with code or wizards? Then tangible architect is exactly what you need: With tangible architect your UML model and C# interface descriptions are kept in sync. In addition, the interface descriptions are also displayed in the tangible architect class view, where they can also be edited using wizards.
Let's look at an example UML Diagram that is synchronized with round-trip engineering:
All information that is represented in the UML Diagram is also preserved in the synchronized C# interface definitions using .NET Attributes. Additional source code comments are generated to enhance readability:
/// <summary>
/// Summary description for IEmployee
/// </summary>
[Persistent]
public interface IEmployee : tRepository.PsIObjectIdentity
{
[Size(40)]
[ObjectName]
[DefaultValue("")]
[UMLModelID("{3DC267CB-5B4D-429d-9649-B7E0863AA4A0}")]
string LastName
{
get;
set;
}
/// <summary>
/// A Employee may contain any number of Payroll.
/// A Payroll may be contained in at most one Employee.
/// </summary>
[tRepository.UMLModelID("{AE62E238-AE36-4563-A50F-B887355C1811}")]
[Contains("Employee_gained_payrolls", typeof(IPayroll),RelationFlags.SOURCE|
RelationFlags.ORDERED, 0,-1)]
IPayrollContainsCol Payrolls
{
get;
}
[...]} Users who navigate large amounts of source code might prefer using the tangible architect class view to view and edit the object model. It provides a good overview at a glance:
Using tangible architect you can share your system vision with colleagues and empower your team to work togehter efficiently - no matter which media is preferred by a team member: UML, C# Code or Wizards.
tangible architect accelerates user interface development The industry's best practice for implementing complex graphical user interfaces in record time is the use of data-binding. Data-binding is a mechanism defined by Microsoft where a data-source is providing its information properties by implementing a set of interfaces. Intelligent controls like a Grid View, a data-bound Tree View, the Property Grid and Textboxes are then able to automatically display, and let the user edit, the information in the objects, thereby executing the business rules defined in your object model. Binding a control to a data source is as easy as setting its data source property to the business object.
Here is the code: // Binding an editable data grid and an editable tangible treeview
treeview1.DataSource = AddressBook;
dataGrid1.DataSource = AddressBook.Customers[0].RequestedServiceRequests;
See the screenshot with the editable controls:

Use tangible architect to generate business objects that implement data-access, your business logic and data-binding - and boost your team's productivity enormously!