tags:

views:

111

answers:

2

I've been considering how you would write a business application in only F# with WPF. Here's my thinking of a general outline of how to go about it, but I'm looking for whether or not it will work:

  1. Start with ADO.NET Entities to automatically generate a data access layer.
  2. Since F# doesn't support partial classes, use F# Extension Methods to create a BLL that extends the entity objects with extra members (these will have to mutate the entities)
  3. Instead of writing explicit ViewModels, write F# functions that build ViewModel objects on the fly using object expressions.
  4. Write an F# function that uses Active Patterns and Decision Trees to build WPF Views on the fly, given ViewModel objects as input. It would also take care of setting up bindings between the View and ViewModel objects.

So, opening a form or page would involve executing a function to generate a ViewModel object instance, and then passing that to the function that builds a View from the ViewModel, and then setting that as the content of your Window. From that point on, it executes in a normal "mutable" MVVM way.

My knowledge of F# is still limited, so I may be going down the wrong rabbit hole here.

Question(s):

  • Will this work (in general), or not?
  • Is there a better way that you know of?
A: 

This should work (tho I'm not sure about mutable entities, as I'm not an F# expert).

But my concern is the performance: F# uses a lot of recursion, especially in the case of decision trees, that will be a lot of work at runtime. I would consider pre-generating everything or a caching system. It's okay to generate at runtime using meta-programming, but why doing it every time when you can do it only once?

Kel
Can you expand on your second paragraph? I've read it a couple of times and I can't tell what technical point you're making.
Tim Robinson
I'm just starting on F#, but will offer the following two comments: 1. F# does use lots of recursion, but as long as you make your recursive calls using tail-recursion (http://en.wikipedia.org/wiki/Tail_recursion) there is not a performance/memory issue (the F# compiler optimizes these much more than C#). 2. By default entities in F# are immutable - they can be made explicitly mutable - but if you are doing it a lot, it's possible you are not doing things the "F# way".
Nathan
Why you think recursion is a performance concern?
Juliet
In (4), you're building XAML views on the fly. What you can do, is to make a caching system or pre-generate the XAML beforehand. Pre-generation means that you generate the XAML, compile it in your WPF application like any other app. On the other hand, a caching system would be something similar to a dynamic invocation (on each call, you first look if such view was generated already, if yes, get the view, otherwise generate it).
Kel
Tail recursion is just like loops, *but* it's not always possible to transform function calls into the tail recursion, it will depend on the actual function calls. Tail recursion and recursion is not the same thing ^^
Kel
@Kel: True. I think the power of this functional approach is that I can write it, and then if I need to improve the performance, I can add caching later without much hassle. I agree that the View is mostly static, but varies mostly by the user (due to security rights), which is an input to the function in (3). You could certainly cache both the output of (3) and (4) for a given user session.
Scott Whitlock
+3  A: 

I don't know much about ADO.NET entities, or MVVM, or WPF, so I can't offer much critique of the technical ideas personally. It sounds like you have experience with all those technologies and know what's going on there. So my only commentary is that it sounds like there are too many new things to try all at once. To mitigate risks and increase the chance of success, I'd stage this across a few projects. E.g. maybe start with a traditional data layer using existing tools, and just try out your ideas for the F# View & ViewModel. And once you've worked out the kinks and gotten more comfortable with F#, then try tackling the data layer.

Do also be aware of

http://blogs.msdn.com/b/dsyme/archive/2010/07/29/some-f-project-templates-available-online.aspx

which include e.g. MVVM starter templates for F#, in case they provide any ideas/value (I am unclear how much your strategy departs from tradition to know if this will be helpful).

Here's another random link that may or may not be valuable:

http://stackoverflow.com/questions/3085034/f-and-ado-net-idiomatic-f

Brian
Your final link is exactly what I was thinking. Hide the mutable stuff inside a computational expression and return nice immutable records. No need for the bloat that is ADO.NET Entities.
ChaosPandion
What I'm trying to get around is manually creating ViewModels and Views. I do have quite a bit of experience with doing that in C#, and you realize very quickly that "Boilerplate" doesn't do it justice. Particularly with ViewModels, you spent so much time writing repetitive glue logic, it's nuts. My thinking was that F# could generate these on the fly, since it so repetitive anyway.
Scott Whitlock
@ChaosPandion: there's no way I'll write something like this: row.["FirstName"]; because then when your schema changes, you're in big trouble. Also, the point is to mutate the entities and then call Save (most business screens are editing screens after all). It's nice to say "just write immutable wrappers" but a) can it be automated, and b) how do you track changes and update the database when the user clicks Save?
Scott Whitlock
@Scott... This is not my specialty, but how about instead of having mutable data types that know how to save themselves, you have immutable data types and a different type that knows how to save them?Your editing screen would start with the original data object, and make changes by replacing it with modified copies. Similar to .Net string "mutation". When editing is complete, it saves the final object.
Jason
@Scott - You shouldn't think imperatively if you really want to use F# to it's fullest potention. Think of it as a series of states `ReadDBData->DisplayData->ReadFormData->ValidateFormData->SaveFormData->...`. Why would you need to mutate the data in between states?
ChaosPandion
@Scott - With regards to changing the schema as long as you keep your data layer separate you really don't save much time by using an ORM. If you change the name of one field in a result set you go to your data layer, change the field on your F# record and you are done. To me the benefits of ORM seem to be very limited.
ChaosPandion
@ChaosPandion: I have considered building an entirely functional app from the DAL all the way to the GUI, but then I'm not re-using two very powerful frameworks in .NET: ADO.NET Entities and WPF. I also think a fully functional desktop GUI would have the responsiveness of a web app. I could automate the creation of the record type - I've done something very similar before. I'm trying to imagine how hard it would be to write a function that takes the existing data, compares it to the new data, and then creates a SQL statement for saving. Unless you think I should never UPDATE...
Scott Whitlock