Posts

Showing posts from December, 2006

Delegates

I just remembered another technique for calling methods discovered via reflection! It is possible to convert a MethodInfo to a delegate and call it, this is just as fast as calling the method directly. So if you have a method that you call often which was discovered via reflection you should try this.... private delegate bool DoSomethingDelegate(object a, object b); MethodInfo methodInfo = type.GetMethod(.........); DoSomethingDelegate method = (DoSomethingDelegate) Delegate.CreateDelegate(typeof(DoSomethingDelegate), methodInfo); for (int i = 0; i method(this, this);

Onion, more on signals

I've been trying to think through every type of feature I can that people might want in an application, and then seeing if I can think up a way of implementing it using signals. A couple of days ago I thought up something I couldn't implement using the exact approach I had. I once wrote an app that had a treeview on the left hand side, the user could drill down to a customer of their choice and then when they clicked on that customer the display would update and show their details. This made me realise that a simple "SelectCustomer" signal would not be sufficient, what I actually needed to do was to have multiple SelectCustomer signals and indicate which customer to select. The changes I have decided to make are as follows: I will introduce a struct called SignalCreateParameters. This will hold a string property "Parameters" which may be used to automatically populate some of the properties of the created signal, ie the customer identity. The signal facto...

Onion, part 3

Image
Women can multitask No matter how many times you might be told "women can multi-task!" it's just not true, humans can only do one thing at a time. I don’t doubt for a second that my wife's brain can keep track of multiple subjects much better than my single task brain, but at any one point her brain is only concentrating on a single task! It's exactly the same for software. People may wish to deviate from their current task in order to fulfil some adhoc requirement, but that task is an interruption, it does not occur in parallel to what they were doing before. Once that interruption is over the user of your software wants to pick up where they left off. This is what a process driven (or "task oriented") approach to writing software is about. Process driven work flow A process in this context is a single task performed within an application in order to achieve a specific goal. The goal may be just about anything such as "Delete customer", ...

Onion, part 3 (teaser)

Image
Seeing as I haven't had enough free time to write part 3 recently I thought I'd post this little teaser. Would it surprise you to know that this very diagram generated into code and I was able to run it? The signals on the ShowWelcomeMessage had to be hand coded, but hopefully I will be able to get some kind of custom code generation plugin to get the signals auto generated in future.

Seven deadly sins of application development

Here is a list off the top of my head 1 - Ugly code! Why do some people set local variables to null when they have finished with them? This is .NET! The garbage collector will collect "unreferenced" objects when it is ready, an object is unreferenced if you no longer use the variable that holds the reference to it! Why do people name variables so poorly? Firstly I *hate* Hungarian notation. C# is a strongly typed language so I cannot multiply a boolean by a string, so why do people use variable names like "bIsMale" and "iAge"? 2 - Catching all exceptions An exception is something you expect to happen, but shouldn't happen if all goes well. If such an exception occurs you might know how to solve the problem and enable your application to continue, but if the exception type was unexpected how can you possibly know the cause of the error or what state your application is now in? Therefore I hate code like this try { DoSomething(); } catch { } 3 - ...

Onion, part 2

Going beyond wizard interfaces If someone had said to me "Process oriented application", in the past I would have thought to myself "Wizard-like interface". Whereas I find "Wizards" very useful in certain situations I also find that they are too time intensive for a user who knows what they want to do, how to do it, and just want to get on and do it! The thing is, I think an application layer should be process driven. The business objects layer is there in order to represent the logical business entities of the application, and the application layer should be there to drive the logical flow of the users' interaction with those objects. So, the question is "How do we implement a process oriented framework without enforcing a wizard-like interface?" The answer I think is to use Signals. Signals The process may imply that there is always a specific path through an application. Although the user may influence that path by selection options ...

Onion

An onion has layers... ...Shrek In the beginning When I first started writing applications they would typically be a single program editing a single datasource. As time went on this changed because people wanted to share data, so client/server applications appeared. It didn't stop there though, N-Tier applications became much more common. Applications were typically split up like this: RDBMS--DAL--Business classes--UI Due to the fact that I use ECO for my business layer , and that ECO has the DAL built in, the illustration for me would look something like: RDBMS--Business classes (ECO)--UI Thinking of business problems as classes instead of tables really helps to simplify your design, so I have been very happy writing applications this way for some time now. The application layer In December 2005 I was tasked with the job of writing quite a complicated Compact Framework application. Although this application was going to be complicated it needed to be very simple to use, as the ...

OutOfMemory, or maybe not?

I've been writing an app for the compact framework for some months now. It's quite a complicated app that includes an object persistence framework, a task oriented application layer and a loosely coupled GUI which is generated through factories (the app only has 1 form, but lots of user controls + factories). The app has been experiencing apparently random OutOfMemoryExceptions, no matter how hard I have tried I have found it impossible to reproduce one of these errors. I have spent quite some time really optimising the memory useage of my OPF so that it works on the bare minimum of memory yet still operates quickly enough (and I'm very pleased with its performance too). However, the OOM exceptions persisted! I wrote a logging tool which records the last X actions the user performs, when an unexpected exception occurs this log is written to disk along with a stack trace of the exception. I noticed that the top of the stack trace always read... at Microsoft.AGL.Com...

OCL aliases

This is just a copy/paste of a reply I made in a newsgroup, but I think it is quite informative so here it is.... KEY Square brackets denote a class [Person] Rounded brackets denote a role (Pets) Let's say you have a Car class and a Garage class, an individual car is regularly serviced at a specific garage so you have the following association [Garage] (Garage) 1----0..* (ServicableCars) [Car] Car.allInstances->select(Garage.Code = '1234') The above OCL will fail because "Garage" is a class so the parser is expecting stuff like "allInstances". So you might think this should work Car.allInstances->select(self.Garage.Code = '1234') but it doesn't because "self" refers to the root object and not the object at the parsed node where it is specified. This is what aliases are for: {aliasname} + {pipe} Car.allInstances->select(currentCar | currentCar.Garage.Code = '1234') This was possible in Bold too (native wind...

Ye olde C64

I've been reliving my childhood and playing with WinVice, a Commodore 64 emulator. A friend and I were working on a game at the point the C64 died and it never got finished. We recently dusted off those old 5 1/4" disks and finally worked out how to get it working again! If anyone fancies taking a look you can find it here http://noname.c64.org/csdb/release/?id=33963 Be warned though, it really was unfinished. Some rooms lead to dead-ends and there is no way to quit the game, so the occasional reset (of the C64) + reload is required!

WeakReference woes!

Take a look at the following code if (myWeakReference.IsAlive) (myWeakReference.Target as SomeClass).DoSomething(); Do you see the mistake? The WeakReference may return "true" for IsAlive, but because the garbage collector runs within its own thread the value may actually get collected before the next line (because WeakReference.Target does not prevent the GC from collecting the value). I've been using WeakReferences quite a lot recently so I was happy to see that the following changes fixed the occasional NullReferenceException occurencies I had been seeing which were quite difficult to track down! SomeClass myInstance = (SomeClass)myWeakReference.Target; if (myInstance != null) myInstance.DoSomething(); The IsAlive property in my opinion is utterly useless (it is the same implementation as Target). I think MS should just remove it, you could say it would break existing code, but I say it would force people to fix it!

Validating XML against an XSD schema

I have a new job. Well, I say "new" but I actually started in December 2005. Anyway, this "new" job requires me to develop compact framework apps. Seeing as Delphi doesn't support CF I am developing my application in VS2005, it's a really nice tool but I miss ECO so much! One thing I had to do was to write an XML importer routine. This would retrieve an XML file detailing tasks due for the next seven days and then import it into the PPC's database. Because I am not responsible for generating the XML, and because it is good practise anyway, I decided to create an XSD file to validate the XML. PDA's have very little storage resources (the flash card is shared between disk and memory) so I decided to read the XML file a line at a time using the XmlReader so that the contents don't exist on the flash memory twice (disk + memory), another benefit of this approach being that I can read it directly from a ZIP file too! In dotnet V2 the class XmlVa...

Roles

Image
What is a Customer? If you are some kind of business service provider then it will be a Company, if you are a window cleaner then it will be a Person, but if you are a travel agent it could be either. What about a Supplier? You could argue the same as for a Customer, but you could also argue that a Company/Person could be both a Supplier and a Customer. This is where Roles come in. A Supplier isn't something you are, it is something you do, you supply something; just as a Customer consumes something. I find that it is much better to enable "Things" to perform more than one action, it is rare that life is simple enough for everyone to perform only a single role in life. The typical solution to this is the Party/Role pattern. A good point to make here is that this is a pattern, not a set of classes intend for inheriting from! This means that when you have a Company (alias "Party") you should create a CompanyRole class and associate them, descending Custome...

ECO is so fast!

I spent the day (March 2005) training someone how ECO works. Between 9:30 and 12:30 we went through the basics, how to create a model in a package (and why). We then covered the different component types, whilst making a simple client/server app. Between 13:45 and 17:00 we went on to Create a server application Convert the client to connect to the server instead of directly to the DB Make the client synchronise with the changes from the server Create a web service which connected to the server for persistence Create a website which connected to the server for persistence That's a lot of work to get done in 3.5 hours at the best of times, but when you are also explaining why everything is done the way it is then this is surely a reflection of just how quick it is to develop applications using ECO. Everything we did was adhoc. I had no idea what the trainee wanted to cover before he arrived so everything was written from scratch. I'm quite frankly surprised that we managed to ...

What is ECO?

This question has been asked so many times. Jesper (one of the developers) recently explained it like this... ECO, Enterprise Core Objects, is a model driven framework. In essence, it allows you to specify your application using a UML class model. This model is then transformed to source code, decorated with enough information to re-create the model information at run time. The framework uses the model information (as contained in and re-created from the source code) to drive persistence, presentation, maintain the technical integrity of the business objects, manage bi-directional relations, derived associations and attributes, maintain constraints, offer services like undo/redo, object versioning and quite a bit more. The value added proposition for you is that you can design your application on a 'higher level', without worrying about implementation details. Use the model not only for communication of ideas, but also as a part of your application. You can code your business ...

Adding runtime error messages to page validation

One of the requirements when writing a website I once created was the ability to model object constraints in OCL and then validating the current page against those constraints. The problem with normal validators is that they are designed to validate individual controls rather than a list of constraints on an object. The approach I took was to create a validator which I can place on any web form and add as many errors to as I required. The first step was to create a WebControl which supported IValidator public class MultiValidator : WebControl, IValidator { } I then added a list of strings to hold the error strings, and a method to add an error. private List Errors = new List (); public void AddError(string message) { Errors.Add(message); }//AddError When ASP .net validates a page it enumerates all IValidators within its own Validators property, and called IValidator.Validate(). To determine if the page is valid or not it then checks IValidator.IsValid. To add cu...

Reverse derived columns

The focus of this post will be "Event derived columns". Jan Nordén (Borland) pointed me in the direction of these things recently when I asked him how to solve a GUI problem I had. When I used Bold for Delphi there was this really nice GUI component called a BoldSelectionListBox. This component would let me show a list of items with a CheckBox next to each row, ticking / unticking a box would add / remove an association between the object selected and some other object of my choice. Using this BoldSelectionListBox I would be able to specify a User (for example) as the context and then have a list of all Groups in a kind of CheckListBox. Ticks would appear in all CheckBoxes where the User is belongs to the group listed, and no tick where they are not part of the group. The extra clever part of course is that by ticking a CheckBox Bold would create the link object required to tie the User to the Group, and add it to User.Groups (and of course Group.Users). Seeing that ECO ...

Moving home

This is my first blog entry on this site. I'm moving from my previous blog address over to here. At first I'll be reposting some of my more interesting entries from my old blog.