in
Forums
Blogs
Files
Devexpress.Com
ClientCenter
Support Center
DevExpress Channel

Gary's Blog

  • XAF RWA Refactor #1

    In my last post we created the code to satisfy the first use case and JIT design document. Now that our users have had the application for a while, they have sent us a number of issues that need to be addressed, they are:-

    1. The fields in the GUI need to be re-ordered to be more “sensible”.
    2. A Course name must be mandatory and unique.
    3. A CourseDiary name must be mandatory and unique.
    4. Start and End dates are mandatory on CourseDiary and Outage.
    5. The date range on an Outage must be with the range of the CourseDiary dates.
    6. Where an object has a start date and an end date; end date must be greater than start date.
    7. An Outage is related to a specific CourseDiary and should not be displayed in the navigation bar.
    8. The error message for the CourseDiary reference rule is the default one and has not be inverted like the rule itself.

    Okay, let’s take these issues in order. To fix the ordering of the fields in the GUI, open the model editor, expand the “views” node, expand the “Course_DetailView node”, select the “layout” node and in the property pane right click and select “Customize Layout”. Now, drag the elements into the order you feel happy with. Repeat these steps for the CourseDiary and Outage detail views.

    Next, let’s deal with making the Course and CourseDiary name mandatory and unique. This is done with the use of two rule attributes, RuleRequiredFieldAttribute and RuleUniqueValueAttribute. So let’s go ahead and add these attributes to the Course and CourseDiary classes:

    private string _Name;
    [RuleRequiredField("Course name required",DefaultContexts.Save,"A name is required!")]
    [RuleUniqueValue("Course name must be unique",DefaultContexts.Save,"Course name already exists!")]
    public string Name {
        get {
            return _Name;
        }
        set {
            SetPropertyValue("Name", ref _Name, value);
        }
    }

    Having done that, let’s add tests for these rules:

    [TestMethod]
    public void TestCourseMustHaveName() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow);
            CourseDiary diary = new CourseDiary(uow);
            course.Diary = diary;
            RuleSet ruleSet = new RuleSet();
            RuleSetValidationResult rsvr = 
                ruleSet.ValidateTarget(course, DefaultContexts.Save);
            Assert.AreEqual(false, rsvr.IsValid);
        }
    }
    
    [TestMethod]
    public void TestCourseNameMustBeUnique() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow) { Name = "Test" };
            CourseDiary diary = new CourseDiary(uow);
            course.Diary = diary;
            uow.CommitChanges();
        }
    
        using (UnitOfWork uow = new UnitOfWork())
        {
            Course course = new Course(uow) { Name = "Test" };
            CourseDiary diary = new CourseDiary(uow);
            course.Diary = diary;
            RuleSet ruleSet = new RuleSet();
            RuleSetValidationResult rsvr = 
                ruleSet.ValidateTarget(course, DefaultContexts.Save);
            Assert.AreEqual(false, rsvr.IsValid);
        }
    }

    Add similar tests for CourseDiary, then add the attributes and tests to ensure the start and end dates are mandatory on the Outage and the CourseDiary. Having done that, we can now add tests to ensure that the start date is greater than the end date. To do this decorate the class with the RuleCriteria attribute, like so:

    [RuleCriteria(
            "Outage end date must be greater than start date",
            DefaultContexts.Save,
            "EndDate > StartDate")]

    And create a test to go with it:

    [TestMethod]
    public void TestOutageEndDateMustBeGreaterThanStartDate() {
        using (UnitOfWork uow = new UnitOfWork()) {
            DateTime now = DateTime.Now;
            Outage outage = new Outage(uow) { StartDate = now, EndDate = now };
            RuleSet ruleSet = new RuleSet();
            RuleSetValidationResult rsvr =
                ruleSet.ValidateTarget(outage, DefaultContexts.Save);
            Assert.AreEqual(false, rsvr.IsValid);
        }
    }

    Follow the same pattern to create rules and tests to ensure that the Outage start date is after the CourseDiary start date, to ensure that the Outage start date is before the CourseDiary end date and to ensure that the Outage end date is before the CourseDiary end date.

    To ensure that the Outage object does not appear in the navigation bar, decorate the Outage class with the NavigationItem attribute as follows:

    [NavigationItem(false)]
    public class Outage : BaseObject

    Lastly, we need to fix the error message for the CourseDiary by providing a specific message in the Rule:

    [RuleIsReferenced(
        "No delete if referenced",
        DefaultContexts.Delete,
        typeof(Course),
        "Diary",
        "A Course Diary cannot be deleted if it is being used!",
        InvertResult=true)]

    Right, now that we’ve done all the refactoring work, let’s make sure our tests still pass:

    image 

    They do! Well that about wraps it up for this post, in the next post we’ll start the next use case, in the meantime you can find the refactored solution here.

    Technorati tags: ,
    Digg This
  • XAF RWA Code #1

    Now that we’ve done our design, it’s time to code it up. So first thing to do is to add an empty solution to Visual Studio. Next, add to that a new test project (yes we’re going to to a bit of TDD). Now we are going to add the following test

    [TestMethod]
    public void TestDiaryHasName() {
        using (UnitOfWork uow = new UnitOfWork())
        {
            CourseDiary diary = new CourseDiary(uow);
            diary.Name = "Test Diary";
    
            Assert.IsNotNull(diary.Name);
        }           
    }

    This test will test whether or not our CourseDiary is capable of storing a name variable. When you type / paste this code then you will notice lots of problems with it in the first instance and the code will not compile. Let’s carry out some steps to ensure that it does build – using the TDD philosophy of doing the least thing that will make the test pass.

    Firstly add an XAF Windows Forms Application and in the Solution1.Module project add a domain object named CourseDiary. In CourseDiary add a string property (CR shortcut xps) named “Name”. Now go back to your test project and add references to the following assemblies:

    • Solution1.Module
    • DevExpress.Data.V8.2
    • DevExpress.Persistent.BaseImpl.v8.2
    • DevExpress.Xpo.v8.2

    Now add any using statements required. Having done that your test should compile, run and pass. If not, then fix any problems that the compiler or test runner throws your way and try again. Once you have gotten this test working we can move on to the next test.

    The next test will test the CourseDiary’s ability to store a description variable and it looks like this:

    [TestMethod]
    public void TestDiaryHasDescription() {
        using (UnitOfWork uow = new UnitOfWork())
        {
            CourseDiary diary = new CourseDiary(uow);
            diary.Description = "Description";
    
            Assert.IsNotNull(diary.Description);
        } 
    }

    Again the test will not compile until you add the Description property to the CourseDiary object. Having done the simplest thing that will make the test pass, your test should now compile, run and pass. Now repeat this process for the StartDate, EndDate and Outages properties, creating the following tests (The CR shortcut for a DateTime property is xpd8):

    [TestMethod]
    public void TestDiaryHasStartDate() {
        using (UnitOfWork uow = new UnitOfWork()) {
            CourseDiary diary = new CourseDiary(uow);
            diary.StartDate = DateTime.Parse("01/04/2009 00:00:01");
    
            Assert.IsNotNull(diary.StartDate);
        }
    }
    
    [TestMethod]
    public void TestDiaryHasEndDate() {
        using (UnitOfWork uow = new UnitOfWork()) {
            CourseDiary diary = new CourseDiary(uow);
            diary.EndDate = DateTime.Parse("31/10/2009 23:59:59");
    
            Assert.IsNotNull(diary.EndDate);
        }
    }
    
    [TestMethod]
    public void TestDiaryHasOutages() {
        using (UnitOfWork uow = new UnitOfWork()) {
            CourseDiary diary = new CourseDiary(uow);
            
            Assert.IsNotNull(diary.Outages);
        }
    }

    The Outages property is a special case because we first have to add a new domain object named Outage and then add a collection property to the CourseDiary (CR shortcut xpcl) like so:

    [Association("CourseDiary-Outages")]
    public XPCollection<Outage> Outages {
        get {
            return GetCollection<Outage>("Outages");
        }
    }

    And an attribute property to the Outage pointing back to the CourseDiary (CR shortcut xpa) like so:

    private CourseDiary _CourseDiary;
    [Association("CourseDiary-Outages")]
    public CourseDiary CourseDiary {
        get {
            return _CourseDiary;
        }
        set {
            SetPropertyValue("CourseDiary", ref _CourseDiary, value);
        }
    }

    Once you have complete this work, place the cursor in the test class name in the editor, right click and select “run tests”. All your tests should now run and pass, like so:

    image

    Now add the following test for the Course Object:

    [TestMethod]
    public void TestCourseHasName() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow);
            course.Name = "Test Course";
    
            Assert.IsNotNull(course.Name);
        }
    }
    
    [TestMethod]
    public void TestCourseHasDescription() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow);
            course.Description = "Test course description";
    
            Assert.IsNotNull(course.Description);
        }
    }
    
    [TestMethod]
    public void TestCourseHasDiary() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow);
            CourseDiary diary = new CourseDiary(uow);
            course.Diary = diary;
            
            Assert.IsNotNull(course.Diary);
        }
    }

    Add the appropriate properties to allow the tests to pass, remembering that CourseDiary has a 1:M relationship with Course which is expressed as follows on the Course:

    private CourseDiary _Diary;
    [Association("CourseDiary-Courses")]
    public CourseDiary Diary {
        get {
            return _Diary;
        }
        set {
            SetPropertyValue("Diary", ref _Diary, value);
        }
    }

    and as follows on the CourseDiary:

    [Association("CourseDiary-Courses")]
    public XPCollection<Course> Courses {
        get {
            return GetCollection<Course>("Courses");
        }
    }

    Now that we have built our Course and our CourseDiary classes, it’s time to look at the Outage that we stubbed out in order to complete the CourseDiary class. Let’s go ahead and create tests and properties for Name, Description, StartDate and StopDate following the pattern above.

    Now we can turn out attention to the constraints we had on our objects. One of constraints we had was that a Course had to have a CourseDiary. So to enforce that we can decorate the Diary property on the Course with the RuleRequiredField attribute, like so:

    private CourseDiary _Diary;
    [RuleRequiredField("Course must have Diary", DefaultContexts.Save)]
    [Association("CourseDiary-Courses")]        
    public CourseDiary Diary {
        get {
            return _Diary;
        }
        set {
            SetPropertyValue("Diary", ref _Diary, value);
        }
    }

    Having added a reference to the appropriate assembly (DevExpress.Persistent.Base.v8.2),  we can write a test to ensure that rule is enforced like this:

    [TestMethod]
    public void TestCourseMustHaveDiary() {
        using (UnitOfWork uow = new UnitOfWork()) {
            Course course = new Course(uow);
            RuleSet ruleSet = new RuleSet();
            RuleSetValidationResult rsvr = ruleSet.ValidateTarget(course, DefaultContexts.Save);
            Assert.AreEqual(false,rsvr.IsValid);
        }
    }

    Another constraint that we had was that we can’t delete a CourseDiary if it is referenced by a Course object. The first thing we have to do to enforce this is to add the RuleIsReferenced attribute to the CourseDiary class, like so:

    [RuleIsReferenced("No delete if referenced",DefaultContexts.Delete,typeof(Course),"Diary",InvertResult=true)]

    Notice the use of the InvertResult parameter which makes this rule “say” IsNotReferenced, which is what we want in this case. Now that we have decorated the class with this attribute, we can go ahead and write a test for it:

    [TestMethod]
    public void TestDiaryCantBeDeletedWhenReferenced() {
        using (UnitOfWork uow = new UnitOfWork())
        {
            Course course = new Course(uow);
            CourseDiary diary = new CourseDiary(uow);
            course.Diary = diary;
            RuleSet ruleSet = new RuleSet();
            RuleSetValidationResult rsvr = ruleSet.ValidateTarget(diary, DefaultContexts.Delete);
            Assert.AreEqual(false, rsvr.IsValid);
        }            
    }

    Another constraint that we had was that we cannot edit a CourseDiary in such a way as to invalidate a Booking. At this point in time we don’t have the Booking class as this UC does not cover it. In such a scenario the developer, using TDD, would seek to mock out the the Booking class. In this case, however, I feel that to go off into the realms of mocks might cloud what we are doing here (if anyone feels strongly that I’m wrong, feel free to comment and I will consider using mocks in a later post), it would certainly make this post, which is now reaching epic proportion, significantly longer.

    So having decided to leave any dependency on the Booking class until we actually have that class, we are finished with our constraints. All that remains now is for us to add tests to Create, Edit and Delete our Course, CourseDiary and Outage classes (in the appropriate test classes of course) and we are done. I shan’t bother describing the tests here, they follow the pattern already set, I will link to the solution from this post and you can download and examine the these tests at your leisure.

    Having created these tests, let’s run all the test to see if our code is still working

    image

    Seeing that it is, we are now safe to run our solution and see what happens:

    image

    Yep, seems to be working fine!

    Okay so we’ve completed our use case and it’s time to ship our code to the testing server where our users can play with it. Is our code perfect? Well no, there are a lot of things I’ve left for our users to “find” and we will fix those in the refactoring phase. In the meantime, why don’t you leave a comment with the things that you find that need to be fixed? To do that you’ll need the solution of course. Have fun, and I’ll see you next time!

    Technorati tags: ,
    Digg This
  • XAF RWA Just in Time Design #1

    Now that we have our first use case, it’s time to do a little design work. The first task we have to complete is to identify object candidates, that is things that might be coded up as objects in our solution. The easiest way, I find, to do that is to list the nouns in the use case, so let’s do that now.

    The nouns are:

    1. Administrator
    2. Diary
    3. Course
    4. Booking
    5. Outage

    Examining the list above it is clear that the nouns 2 through 5 are good candidates for objects but Administrator is not so clear because, at this point, it is not obvious if Administrator should be an object or if it is an attribute of another, as yet undefined, object (Employee say). So, for now, we’ll not include it as an object, safe in the knowledge that if we change our minds, we can fix it during the refactoring phase.

    Booking too, though an obvious candidate, is not really part of this use case. Certainly both Diary and Outage objects have a dependency on Booking, as we’ll see later, but this dependency can be mocked during testing of this use case solution and so, for now, we can afford to ignore it.

    The next task we have to complete is to decide what behaviour our objects are going to have. A good way to get a “first pass” at object behaviour is to look at the verbs in the use case, so we’ll go ahead and do that.

    The verbs are:

    1. Select
    2. Create
    3. Logs on
    4. Edit
    5. Delete

    Now that we can see them clearly, we notice that we don’t have to pay them a lot of notice as the CRUD will be handled by XPO (the orm tool under XAF) and the “logs on” element we can assume we can handle via the security module (again safe in the knowledge that if we are wrong we can fix it in the refactoring phase).

    Now we need to look at what constraints we have on our objects. From the use case we can see that we have a constraint around tee-time bookings with regard to the fact that we can’t create or edit an outage, nor can we edit a diary if it is going to invalidate a tee-time booking. So let’s decide that we are not going to allow those processes to occur and let’s document that decision.

    Business Rule: 001

    Use Case Reference
    001 paragraphs 2.1.4, 2.3.3 and 2.4.4

    Rule
    Tee-time bookings cannot be invalidated by the creation or editing of an outage, nor by the editing of a diary.

    Action to be Taken
    On the aforementioned events a search will be made for affected bookings, if there are any then an error message will be presented to the user and the event cancelled.

    There is also a constraint around the deletion of course diaries in as much as they cannot be deleted if they are assigned to a course, so let’s go ahead and document that decision too.

    Business Rule: 002

    Use Case Reference
    001 paragraph 2.2.4

    Rule
    A course diary cannot be deleted if it is currently assigned to a course.

    Action to be Taken
    On the aforementioned event a search will be made for affected courses and if any are found then an error message will be presented to the user and the event cancelled.

    Having identified the objects, their knowledge (the properties they have) and their behaviour (the functions that can be called on them) and having documented certain business rules, the above post, along with the Use Case, represents a minimal set of documentation that an agile team (in this case us) can use to go ahead and create some code. And that is just what we’ll do in the next post.

    Digg This
  • XAF RWA Use Case #1

    It’s time to create our first use case, so where to start? Well it seems clear to me that a top down approach is needed here, after all you can’t book tee times on a course that doesn’t exist and you can’t book tee times on a course when you don’t know when it opens, right? So our first use case has to be for the administration system and has to be around the maintenance (create, read, update and delete functions) of our course diaries. The use case follows below. You will notice that I don’t favour the fully dressed style of use case for this project as I think it is “too much” for blog posting. Readers who wish to find out more about use cases should read the excellent book Writing Effective Use Cases by Alistair Cockburn (Wikipedia). Readers may also wish to read about (the more fashionable) user stories.

    Now I know this is going to upset the architectural fundamentalists, but I’m going to roll up related functionality into a single use case. I’m doing this for purely aesthetic reasons, to enable me to adhere to the four post policy that I described earlier. Just to keep us on the straight and narrow though, it is worth pointing out to our less experienced readers that, under normal conditions, each use case would deal with only one… well, use case :-)

    As an aside, for those of you who are unfamiliar with the business area (and I’m assuming that’s the majority) the course diary describes what day of the year the course opens and closes and the first and last tee times, as well as any “outages” (for competitions etc). This is because it takes time (say 5 hours) to complete a round of golf and the times at which you tee off, and thus the time you are expected to return to the club house, are set up so that you are playing in day light during both winter and summer. Okay, so let’s get on with it.

    Use Case: 001 Maintain Golf Course Diaries

    Primary Actor
    Administrator

    Priority
    High

    Frequency
    2/year

    Trigger
    Course diary maintenance required

    Main Success Scenario
    1. Administrator logs on to the system
    2. Administrator elects to create a new course diary
    3. Administrator creates a new course diary

    Extensions
    2.1.1 Administrator elects to edit a course diary
    2.1.2 Administrator selects a course diary
    2.1.3 Administrator edits a course diary
    2.1.4 Course diary is edited if it does not invalidate future tee time bookings

    2.2.1 Administrator elects to delete a course diary
    2.2.2 Administrator selects a course diary
    2.2.3 Administrator deletes a course diary
    2.2.4 Course diary is deleted if it is not in use

    2.3.1 Administrator elects to create an outage
    2.3.2 Administrator creates an outage
    2.3.3 Outage is create if it does not invalidate future tee time bookings

    2.4.1 Administrator elects to edit an outage
    2.4.2 Administrator selects an outage
    2.4.3 Administrator edits an outage
    2.4.4 Outage is edited if it does not invalidate future tee time bookings

    2.5.1 Administrator elects to delete an outage
    2.5.2 Administrator selects an outage
    2.5.3 Administrator deletes an outage
    2.5.4 Outage is deleted

    Digg This
  • XAF RWA – How we Will Proceed

    I just thought I’d drop you a short note to let you know how I propose to proceed with the XAF RWA. Each feature that we add will be done over four posts, the first post will contain the use case for the feature, the second post will contain the architectural decisions (as requested by some readers, more experienced readers may wish to skip this post), the third post will contain the build phase and finally, the fourth post will deal with any refactoring required.

    Digg This
  • The Real World App

    As I hinted at before I left for the MVP Open Day, I am now ready to start the “Real World App” (hereafter referred to as RWA). To ensure that it is indeed a real world app. I have decided to re-create a system I have worked on previously, that way everyone can see that indeed it is real word and the scenario has not been artificially constructed in order to show XAF in the best light. So, without further ado, here is the scenario we will be working on:-

    The coastal town of Duncodin-by-the-Sea (referred to as Duncodin from now on) lies in the north east of Scotland, not far from the historic home of golf at St. Andrews. Recently, a wealthy tycoon purchased several hundred acres of coastal property and intends to build three links golf courses there, one of which he hopes will be selected to be part of The (British) Open circuit.

    You have been selected to provide the Tee-time Booking System for this resort, and in particular you are to provide:-

    • A web  based tee-time booking system for use by visitors
    • A win forms based tee-time booking system for use by a small call centre
    • A win forms based administration system

    The requirements for this system are fluid and you are to use an agile approach to constructing this software to more easily facilitate the changes which will be required as the requirements firm up.

    I’ll publish the first use case for this system tomorrow.

    Digg This
  • UK MVP Day and Evangelism the “Old Fashioned Way”

    So I’m back from the MVP Open Day, did you miss me? Whadda ya mean no?! LOL. Anyway, on the plane home I was sitting behind a woman from Edinburgh and a gentleman from the US. As they conversed during the journey, it became apparent to them both that they had once lived in the same small town in the US. “Wow, that’s amazing” proclaimed the woman; not really thought I, if you’d come to my “Science of Social Networking” talk then you’d have known that the work of Milgram et al, makes it quite likely actually.

    Speaking of my talk, I turned up running a little late, as the chap before me had over run by 10 minutes, to find that the projector had taken umbrage at the very thought of a Mac being connected to a piece of Microsoft equipment, and point blank refused to speak to it at all. Not to worry, the AV tech. soon arrived on the scene, putting my mind at ease. However, my ease was to be short lived as we had the following conversation:

    Him: “Having problems getting connected mate?”
    Me: “Yeah”
    Him: “Not to worry, we’ll have you set up in a jiffy”
    Me: “Good, as we’re running a bit late and I should have started by now”
    Him: “Umm, hang on, this is a Mac”
    Me: “That’s right, it is”
    Him: “Umm, yeeeeeeeees, well you see…. sorry mate, no idea, bye!”
    Me: “Okay, anyone got a white board marker?”

    I then proceeded to deliver my talk the “old fashioned” way, just chalk and talk (well white board, pen and talk, but you get the idea). As it happens the audience seemed pretty happy with that approach as the day had been a little like “death by Powerpoint” up until then, and I only really needed to “chalk” up my equations. Just to add a little bit of pressure (‘cos otherwise it would have been easy right?) Toby Richards (General Manager, Community Support Services for Microsoft) was in the room. I think it must have gone okay though, as he asked me to send him my slide deck. Of course, he maybe wanted to check that I had one in the first place and wasn’t just conning everyone. :-)

    Digg This
  • UK MVP Open Day

    Tomorrow I’m off to the UK MVP Open Day where I’ll be speaking on the topic of “The Science of Social Networking” if you are UK based and going to be there then don’t forget to come and say hello.

    On a different note, I’ve decided what our “Real World Application” is going to be; it’s a real “real world” application, I’ve just changed some of the names to protect the innocent, that way no one can accuse me of making the scenario fit the strengths of XAF. But this is just a teaser of course, there’ll be more information on this front on Monday when I’m back from the Open Day. Until then, happy coding! :-)

    Technorati tags: ,
    Digg This
  • The Curious Case of the Ketchup and the Missing Booth

    So the BASTA conference wound down with a party and, as with every conference, the organizers tried to give the speakers and exhibitors a gimmicky gift with which to remember the conference by. Now, since the party had a BBQ theme, what better gift that your very own, personalized, bottles of Heinz Tomato Ketchup? And so now, I am the proud owner of my very own ketchup (pictured below).

    P5230084

    At the end of the conference, Oliver and I headed off to the airport. We checked in the Booth (pictured below) and a case containing some left over T-Shirts, CDs and brochures. We duly boarded our flight to London and then caught our connection flight to Edinburgh (ah it was nice to be back in Bonny Scotland). A quick trip to the luggage carrousel, however, showed that our booth was missing. Apparently the baggage handlers and Frankfurt Airport decided that, whilst we probably did need our T-Shirts etc, we could manage without our booth for an extra day or two. So, our booth has been enjoying a couple of days R&R in Germany before deciding to come back home. :-)

    597485

    Digg This
  • Basta Germany Day 3 - XAF, and the Erica Bomb

    Well day three of the conference was good; the delegates seemed a little tired (possibly due to the long hours that they worked at the conference) and they didn't seem much interested in hearing about just how fantastic XAF and XPO are (of course we know that already, right?). So what should a good evangelist do in this situation? We turned on the DevExpress Channel and ran Erica's videos on the plasma screen.

    The effect was almost immediate; people stopped chatting and looked around to watch the screen. I have named this effect the "Erica Bomb", anyone caught in the "blast radius" is compelled to stop what they are doing and watch. I think we'll be using this tatic again in the the future. Wink

  • BASTA Germany Day 2

    It was another brisk day on the booth yesterday. There was a lot of interest in XAF and XPO, as there was on the first day. However, yesterday also saw a lot of interest in our WPF grid, with many people leaving the booth, after the demo, to go and search out the beta version. There was a little interest in the Silverlight grid also, but not so much as in WPF.

    One difference between this conference here in Germany, and events I've attended in the US, is that here in Europe there doesn't seem to be much interest in components for Sharepoint, where as I noticed that was a "big deal" in the US.

    Yesterday afternoon saw quite a bit of interest in CR/R! after one of the speakers (speaking on pragmatic C sharp) told his audience that no one should be programming these days without a tool like ours! Quite a recommendation that sent a number of interested people to the booth.

    Well that is about it from me for now, it's time to get going on day 3 - bye for now.

  • BASTA Germany Day 1

    I am back on the DevExpress booth at the BASTA conference. As I write this Oliver is demo'ng XAF to an eager crowd. I say he's demo'ng XAF, but since it's in German, and I don't speak the language, he could of course be giving them a run down of his favourite bars in the area; hey, maybe that's why they are so interested do you think? Nah, I'm sure it's XAF. Smile

    Seriously, the crowd here just seem to "get" the whole application framework, ORM "thing". Yesterday, whilst Oliver delivered his sessions, I demo'd XAF and a few of our other products (CR/R! always go down well) and even though I was speaking english, the crowd were impressed with the products we have. A couple of them were going to trial XAF on small projects when they got back to their day jobs.

    So, that was yesterday - a pretty fruitful day. Tune in tomorrow to find out what today brings.

  • XAF and XPO in Germany

    Oliver and I are off to the BASTA conference in Germany where we’ll be flying the DevExpress flag. So, as always, if there are any of our customers attending the conference, don’t forget to stop by the booth and say hello – oh, and collect a coveted DevEx T-shirt of course. :-)

    I’m not sure what the connectivity will be like at the conference or at the hotel, so blog postings may be a bit light next week, but if they are, don’t forget you can still keep in contact with me via Twitter at http://www.twitter.com/garyshort

    Anyway, until we return, sit back, relax and help yourself to a beer from the fridge.

    Technorati tags: , ,
    Digg This
  • XAF, XPO and the Squeaky Wheel

    I love my granny, as all of us who are fortunate enough still to have one alive do I’m sure. My granny hails from Highland Perthshire and is, as we say in Scotland, of farming stock; that is to say that, before retiring, she worked a farm, as her forebearers before her did. This means, amongst other things, that she has a wealth of homespun advise, neatly packaged up into handy little sayings, each one perfect for a particular set of circumstances. For example

    “Oh, look at the time and there’s no’ a carrot in the pot!”

    Meaning that the day is slipping away and it looks like I might not get through all the tasks I had allocated to do today, and

    “Behave yersel’ else I’ll come in aboot yer wa’s wi a tarry stick”

    Which means if you do not moderate your bahaviour I’ll beat you about the ribs with the stick I use to stir the molasses for the cattle feed. However, one of my favourites, and one which is somewhat applicable to the situation I now find myself in, is

    “It’s the squeaky wheel that gets the oil”

    Meaning it’s the thing (or person) that makes the most noise (or complains loudest) that gets dealt with fastest. I say it is somewhat applicable to the situation that I now find myself in because, whilst taking my habitual morning “stroll” through our forums, I came across a post, in which the writer was praising Mark’s recent set of posts, showing how to write a plugin using DXCore, and wondering aloud why the XAF team couldn’t be more like Mark, and produce such real world examples.

    Of course, if the writer had appreciated that DXCore and XAF/XPO cannot be compared like for like, he would have been a long way to answering his own question. You see, DXCore is an enabling technology facilitating the creation of a certain type of plugin, it does one thing, and it does it very well and so writing a real world example is easy, as each user’s view of the “world” is the same.

    XAF however, is an application framework, allowing a developer to create winform or webform (or both) applications; it is strategic software that lays out the architectural steps for a developer, the tactical code that the developer then adds to that base, to form the solution to his business problem, is utterly dependent upon a myriad of things:- the industry, the sector of the industry, his company’s view of their market place, financial constraints on his company, financial constraints on his customers, etc, etc, etc; the list goes on and on.

    The point being that there is not one “real world” from which to construct a “real world” example, instead the term takes its definition dependent upon the context of the individual developer. Take me as an example, before joining DevExpress I worked, for 18 years, as a programmer and architect in a number of industries including: Banking, Utilities, FMCG, Pharmaceuticals and Local Government. I can tell you that if you took an application from each of those industries and compared them, they would have little in common. In fact you would have to distil them down to their architectural parts (object persistence, reporting, etc.) before you would find much similarity. So any “real world” example, if it were to be of use to all of our customers equally, can only contain examples of how to use these architectural parts (or product features if you will). It’s no coincidence then, that our MainDemo application demonstrates these product features in a somewhat isolated way, it has to be that way to be of use to our customers as a whole. Again, it is no accident that our documentation takes the same approach of explaining the product features in this way.

    But the “squeaky wheel” says “it’s hard to find information in your documentation”, so I begin a series of cookbook style posts that state a problem, in very simple terms, and then show the solution and a discussion of that solution. The “squeaky wheel” says “these posts are too simplistic” so I suggest a more advanced series, still in the cookbook style, to make it easy to find, called Black Belt XAF and I ask for topic suggestions. The majority of suggestions I receive are not XAF topics but general architectural topics (which I have no objections to covering if that is of benefit to our customers). The “squeaky wheel” says “these examples are not real world”. Although I’ve explained above how it is nearly impossible for us to provide “real world” examples, I decided to start a “Starring You” section in my blog so that actual real world customers can post actual real world examples and they are starting to come through now and yet the post above calls for the XAF team to provide more “real world examples”.

    I contemplated this for a few minutes before I dismissed the idea, I mean how ridiculous. If I were to write a series of blog posts showing how to build a solution from the Banking industry or from the Utilities industry, for example, it would only be useful for a vanishingly small percentage of our customers. Then I thought, wait a minute, maybe this is where I’m going wrong, making assumptions about how useful something would be, why not just ask them? So here we are; the “squeaky wheel” says we need to write a “real world” application and I’m asking you, if I were to create such an application, from start to finish, and even though the chosen industry may have little in common with yours, would that help you? If so, leave a comment below.

    Technorati tags: ,
    Digg This
  • XAF Cookbook #7 – Add Scrollbars to a TextBox in DetailsView

    Problem

    You add a text property to a BO, but you require the user to input a number of lines of text, for example in a description field. By default the DetailsView provides a Textbox showing one line of text entry, you wish to show a number of lines of text entry and have scrollbars if required.

    Solution

    Decorate the text property with the [Size(SizeAttribute.Unlimited)] attribute or set the RowCount property to an appropriate value in the ApplicationModel or, via the Model, change the PropertyEditor type to Memo or RichText.

    Technorati tags:
    Digg This
More Posts Next page »
Copyright © 1998-2008 Developer Express Inc.
ALL RIGHTS RESERVED