July 2003 - Posts
Let me quote myself from a usenet posting I did on Edit & Continue in C#:
Afaik, E&C is not planned for vs.net 2004 [C#], and frankly I'm happy about it, because the [C#] devteam can spend that time on other, more valuable features :). (E&C IMHO creates bad debugging styles. Debugging isn't about trial & error which is the implication of E&C. It's about thinking through where teh bug can be, fire up the debugger to test your thoughts, then think about a fix, think through the change implications and fix it. Test it and if it fails again, start the debugger to see why. This way you save a lot of time, instead of poking around in the code inside the debugger :) )
In short: a good debugging-style doesn't need nor require Edit & Continue. If you do need it, it's time to take a step back and look at what you're doing when you're debugging. 10 to 1 you can save yourself a lot of time by thinking first and acting later instead of the reverse.
Tim Anderson interviewed Euan Garden, Microsoft's Product Unit Manager for SqlServer tools about Yukon. Read the whole interview [here].
Yesterday, Jimmy Nilsson blogged about an interesting dilemma. I'll quote a snippet from his blog:
Assume you have a domain model instance for a customer and the customer has a number of orders. In the user interface the user adds a new order for the customer, but doesn't press the save button. Then the user edits the customer instance and saves it, and finally the user decides not to save the new order. Without taking extra care in the application, the new order was probably saved too, even though the user never intended it. The reason is that the order was dirty and was in the object graph that was sent to the Service Layer to be saved when the customer instance was sent.
He comes up with a new method, ToBeSaved(), and that is the explicit save marker: if that method isn't called, the entity isn't saved. This got me interested. I wondered: "Why do you need to add this method, if the problem is somewhere else?". The core problem here is: what is the definition of a relationship between two entities?
A relationship between two entities is a semantic relationship: because two (or more, if you have a relationship over 2 or more fields per entity) fields (attributes) are related to each other as in: they hold the same semantic value, the entities they belong to have a relationship, over the field relationship. In the example above, quoted from Jimmy's blog, the order and the customer have a relationship. However will this relationship exist when the order and the customer entities are saved separately? Yes. The reason for this is that the relationship is, as said, semantic: the order entity will hold a value which is a foreign key to the primary key of the customer entity, linking them together.
The short solution would be: simply save the customer, and save all orders which have to be saved and you're done. Because the dirty, new order object doesn't have to be saved, it isn't saved, problem solved. However the problem which made Jimmy search for a solution is bigger: when you save the order and the customer separately, you don't have the order object in the orders collection in the customer object in memory. Now, is that a problem? It is, when you want to work with entities in memory, instead of in the central repository: the database.
Consider two appDomains with the same application. Both target the central database with customers and orders. Two appDomains in the same application isn't rare, when two instances of the same winforms application are run on two desktop machines, two appDomains are running the same application. User A works on one machine with the application, user B on the other. User A adds an order to the current customer and the application is set up in such a way that the order object is added to the orders collection of the customer object. A's application thus sees the new order object in the orders collection of the customer object. B is also working with the same customer (or at least, has it in memory), and doesn't see the change in the orders collection of that particular customer. Since the applications run in two appDomains, a global object cache per appDomain, which is often used by O/R mappers, is not solving anything.
The best way to do this is to rely solely on the shared repository, in this case the database. A should save the new Order when it is done adding it, and B should first consult the database before assuming what the current state of the orders collection of a given customer is. However, it will always be possible to setup a situation where this will fail too. Best of all: avoid multiple edits on the same data and/or implement signalling of mutations between appDomains or at least instances of the same application which all target the same database / shared repository. Yukon will offer this signalling. Till then, the developer should implement a central object cache which is shared among appDomains himself.
When VS.NET 2003 was announced, Microsoft made it clear that it wasn't a service pack for VS.NET 2002 you had to pay for, it was a new release and that they'd release a service pack for VS.NET 2002 'shortly' after the release of VS.NET 2003. Well... it's been 3 months now today, since VS.NET 2003 is on the market and no sign of any service pack for VS.NET 2002.
This got me thinking. First I thought: what if VS.NET 2003 is the service pack for VS.NET 2002? Then, VS.NET 2004 is the service pack for VS.NET 2003. This way, Microsoft can make money out of fixes. However, I don't think they make a lot of money on the upgrade kits they sell for 29$ a pop. No, the reason why the service pack isn't there must be something else. What I've concluded now is that Microsoft is not releasing a service pack for VS.NET 2002 at all. This will force people to migrate to VS.NET 2003 and thus .NET 1.1, because of the unpatched bugs in VS.NET 2002.
If that's true, I truly fear we'll not see any service pack for VS.NET 2003 either, because I think Microsoft will of course want to migrate the .NET developers to VS.NET 2004 and .NET 1.2 a.s.a.p. after the release of Whidbey. I hope I'm wrong and Microsoft proves me wrong by releasing the fixes for VS.NET 2002 and will commit themselves to us, customers, that they'll release fixes for the bugs in VS.NET 2003.
Of course, some people might wonder why on earth would anyone still want a service pack for VS.NET 2002. To those people I'd like to say: start talking to some VB.NET developers using VS.NET 2003 and use VS.NET 2003 yourself for 8-12 hours a day non-stop. If you ask me, I'd go back to VS.NET 2002 any day, but I can't, simply because bugs that are fixed in .NET 1.1 (and were already fixed last year!) like the bugs in the binary deserializer stop me from using .NET 1.0 in my current GUI application.
After reading Patrick Steele's blog about the failure of CLS Compliance testing in VB.NET, I thought he was wrong, because he uses UInt32 as type, which is a native system type (i.e. a .NET type: System.UInt32).
However, he was right. The C# compiler fails to compile a simple statement like (when CLS Compliance testing is turned on via an attribute):
public System.UInt32 Test;
Correct behaviour of the C# compiler? No. The reason why the C# compiler makes a mistake here is that I use a .NET type, System.UInt32, which is available to any .NET language (it's in the .NET System namespace after all). Therefor, if I specify a public identifier with this type, no matter what language is consuming the type, it can use it. Proof of this is VB.NET, which lacks an unsigned integer type, but can perfectly work with System.UInt32. Also, why would System.UInt32 fail CLS Compliance, but would another value type like System.Data.SqlTypes.SqlString not fail CLS Compliance testing (although it exposes implicit operators not usable in VB.NET!) ?
So is CLS Compliance testing of any use? Not that I'm aware of. If native .NET types, located in the System namespace, can't be used as types for public identifiers (like parameters, properties, return values etc.), why are these types defined in the first place? Because apparently some languages can't use them, otherwise these native, .NET types wouldn't cause a CLS Compliance violation!
Microsoft: or come up with valid rules, founded on solid reasoning, for CLS Compliance testing or stop with the CLS Compliance testing altogether, since at the moment it cries fool when compiling perfect usable code.
The conclusion of Patrick's article shouldn't be: why doesn't the VB.NET compiler test correctly, but why does the C# compiler test incorrectly.
Microsoft Research is busy using inkblobs to construct strong passwords that are easy to remember. Very interesting read. Go to the article by clicking [here].
Edit: when viewing the images, also read this slashdot posting which sums up the things that the slashdot readers have seen in those things. The list is extremely funny, so don't drink coffee at the same time while reading :)
After the recent sourcecode control debate I started thinking: why on earth are we still using the 'file' as the base unit to store sourcecode in? The whole 'file' concept is pretty bad and limiting when it comes to sourcecode control, code reuse and overall code management. Much better would it be if we could work with a code repository as the container for our sourcecode which would work with sourcecode elements like we know, e.g.: namespaces, classes, assemblies, resource objects etc. etc.
In your IDE, for example Visual Studio.NET, you then would work with solely a view on the sourcecode in the repository, thus a subset (or all) of the elements in that repository. The list of advantages of this approach is practically endless. First of all, because the repository contains elements, not files, you can include elements like classes or enums into your code without having to browse through files and wondering where a particular class is located. Second, you can enable sourcecode control on the element level rather than the file level. Also, sourcecode control can be build into the same medium you use to store the actual code in the first place: the repository itself. Of course you can think of many other advantages.
Why we're still using files for sourcecode, especially sourcecode written in OO languages, is beyond me: the concept of using an IDE for software development is very common, so offering a new way of looking at where sourcecode is stored should be considered in the IDE of at least tomorrow, but frankly, it should already be build into the IDE of today.
And the file focussed developer who's not using an IDE? He still can store his code in files, an IDE working with a repository can also use a file driver which reads all files in a project, and works with those files as one single repository. Let's hope at least in the Longhorn release of Visual Studio.NET, Microsoft considers this approach as an alternative to the 'file' concept. After all, the file system of longhorn is a database , so using that functionality for a repository would be the logical thing to do.
Lately, some people started blogging about a new source control system, Vault. I haven't used it, nor am I intending to do so. The reason is not that I don't like Vault or Eric Sink, but because I don't have problems with what I currently use, Visual SourceSafe (VSS). I personally believe Eric Sink knows what he's talking about big time, as his blogs are one of the few which truly show some vision on the total scope of software development, and therefore I think Vault must be a product that can live up the hype that is being build up around Eric's new source control system.
However (you knew there would be a 'however' somewhere, didn't you ;)), there is something that bothers me... a lot. It's not something new, because I've seen these remarks for years. It's about the quality of VSS. A lot of people seem to think it's crap: it should corrupt your files, it is slow, it can't keep up with the competition etc. etc. Well, I disagree. For the target audience VSS is meant for (and if you do not know what a target audience is, read Eric's marketing blogs or the books he mentions), VSS is an excellent product and works well. I'll tell you why. I'll also tell you why some people have problems with it.
VSS comes with visual studio enterprise and other enterprise variants. You can also buy it separately, however I don't think a lot of people do that. Most companies who have a team of developers use an MSDN subscription to save money and they'll receive a copy of VSS automatically. Microsoft didn't position VSS as a source control system which can be used to maintain the Linux kernel or other major software systems. It is positioned as a source control system for small to medium sized projects, you know, the average software project the average team of developers works on.
So we can safely (pun intended) conclude that VSS should be useful for the majority of software projects done with Visual Studio.NET. After all, loading a solution with 20 or more projects with a total of 1 million lines of code or more is no pick-nick either in Visual Studio.NET. A development team working on a project that falls into the 'average project' category should be able to work with VSS without any problem. How come a lot of development teams run into trouble with source control and VSS in particular and blame the problems on the tool with the most ugly and outdated installer on the planet: Microsoft Visual SourceSafe? Because they do not use it correctly, or better: they suffer from an organizational bug.
A while ago I blogged about concurrency control in databases and why functionality locking would be the best way to control concurrent access to database resources. Source control is not different: it also is about controlling access to shared resources, in this case source files, and maintaining a consistent state which can be called 'the current snapshot'. Be it source files or database records, it's all the same. But a lot of development teams do not understand this. They think a source control system can solve the problem of simultaneously made mutations to a shared resource element, like a source file. With tricks they can (most of the time), however in theory there always will be cases where simultaneously mutated source files can't be merged to a new consistent state. This is not the problem of the source control system, but of the users and the organization they're in.
I've seen development teams that check out everything when they arrive at the office in the morning and check in everything in the evening when they leave, even if they've changed just 1 file. Because everyone does this, multiple-checkouts has to be enabled. This is semantically wrong. If a file has to be mutated, one person should be scheduled to do that, another person who also wants to change that file should not be able to change the file also, he/she should delegate his/her changes to the person who is scheduled to change that file. This sounds theoretical BS and not usable in practise but that's not correct. It is useful in practise, and when delegation of work is done properly (and that's why project managers are paid that extra money, mind you!), more work will be done in less time: people should organize the work and thus the usage of the source control system, better. When you do so, a lot of problems with VSS will be gone and will not come back. Lesson learned: schedule work on shared resources properly.
Another problem a lot of development teams suffer from is the size of the VSS database. The documentation of VSS clearly states that the databases of VSS shouldn't be bigger than 1GB in size. If the database is bigger than 1GB, you should create a new database. This might be a little small, but 1GB of sourcecode and changes is a lot. I've been on a project where the VSS database the project was stored in was 8GB in size, it was stored on a 'left over' server (i.e. an old box with slow hard-drives) and the disks were almost full and heavily fragmented. It was slow and I mean really sloooo...oow. After I figured out the size of the database, I requested a new database for just my project. I exported the project, imported it in a new VSS database, on another server, and it was fast again. Lesson learned: keep VSS databases below 1GB
VSS databases are as any other database: if the disk gets corrupted, if hardware fails, if the server hardware isn't up to par, it will fall flat on its face. Admitted, VSS doesn't come with transaction support so you can't replay a transaction log to get a backed up database up to the state you were in prior to the crash. However you can work around this without much effort: backup the complete database regularly (that is, at least once a day), do consistency checks (with the tools that come with VSS, yes it has tools that help you administer the databases) regularly, weed out stale projects and move them to databases which are used for projects that are no longer in production, use proper hardware and OS and maintain that OS properly. Lesson learned: consider a VSS database vital to your organization and thus maintain it properly and use a dedicated machine for it or at least a machine that has a lot of power left for VSS, which also requires a system administrator who knows what VSS is and how to operate it properly.
When looking at other systems, VSS lacks some and gains some. If you consider it comes for 'free' for most development teams (because of the MSDN subscription), it's not fair to compare it to systems which cost thousands of dollars per developer. These systems are most likely worth every dime they ask you for it but do you need all the functionality of those systems when you can solve a lot of problems with the freebee system you get with your MSDN subscription (or other Microsoft subscription model)?
Do I think VSS sucks? Not at all. Personally I like it a lot and consider it more usable than for example CVS. Do I think Microsoft should update VSS? Oh yes. Not because it's not usable now, but because the integration with Visual Studio.NET can be better and VSS lacks some features which can be handy, like maintenance over the Internet (although you can solve that via VPN's for employees). Also some usability features could be added like multiple file merges instead of single file merges when you merge back a branche into the main tree.
I hope developers will look at the feature aspects of the source control systems, the price you have to pay for them and integration with popular IDE's when they talk about which source control system is better. I also hope those developers consider that, in theory, with proper management you don't need a source control system at all (although you'll loose change tracking). First get the management do their job, then get the tools in to streamline it, not the other way around.
A new LLBLGen v1.x has been released today! Version 1.21.2003.712 to be exact, is a QFE (Quick Fix Engineering) release, which means only minor new features are added and for the rest just bugfixes. This is the final release, no more updates will be released after this release, since the next version of LLBLGen, LLBLGen Pro, is in development and will be released later this summer. The sourcecode comes in a project that is compatible with VS.NET 2003 but not with VS.NET 2002. You need a converter to load it into VS.NET 2002.
I've decided to release this update to reward the tens of thousands of users who downloaded LLBLGen v1.x in the past year and to tell them all that they've made LLBLGen one of the most used tier generators on the planet. Thank you!
Get the executable (including the documentation) [here].
Get the sourcecode (including the documentation) [here].
Get only the documentation [here].
Changelog:
Version 1.21.2003.712
- ADDED: New property in base class: 'RowsAffected' (Int32), which contains the amount of rows affected after an Insert Update or Delete action. Will contain -1 when a Select action was called OR when the T-SQL option 'Include NOCOUNT' is checked, which effectually switches off row counting and thus no report can be given about the amount of rows affected by an action.
- ADDED: The generation of DeleteW<foreignkey>Logic routines. SqlServer 7 doesn't support cascading deletes so you'll need these routines. SqlServer 2000 does support cascading deletes and these are the preferred way to delete orphaned FK rows since it doesn't require a transaction on the .NET level, everything will run in the DELETE statement's transaction inside SqlServer.
- ADDED: Because LLBLGen v1.x can only deal with 1 schema, only the schema 'dbo' is supported, which is normally the schema of the database owner. All objects not part of this schema are not listed and no code is generated for these objects. The filter is added to prevent null pointer exceptions when an object of another schema was selected. If you do not see an object in the tables/views list, you either are not making connection as a dbo or the object itself is not owned by the dbo. Normally all objects should be created by the dbo so in most cases you are not affected by this change/addition.
- FIXED: Better folder browser. The new one now also lets you create directories. Still .NET 1.0 compatible.
- FIXED: Minor GUI glitches.
- FIXED: Slightly better exception viewer.
- FIXED: When a database connection failed, all tabs except the connection tab were removed. This was a leftover from the old v1.1 code base. Now all tabs stay in the GUI.
- FIXED: When 'Include ErrorCode' was not checked, the T-SQL generator would emit a dangling ',' at the end of the last input parameter in UpdateW<foreignkey>Logic stored procedures. This is now fixed.
- FIXED: The Tables/Views listview now has clickable column headers which sort the column ascending. Also fixed is the initially sorting of the listview: now the listview is sorted on object type (table/view) and then on table/view name.
- FIXED: Under SqlServer 7, the INFORMATION_SCHEMA.* views, which are part of a catalog (in SqlServer 2000 they're stored in the master catalog), were also listed. These are filtered out now, together with the sysalternates view which is also a system view.
- FIXED: Under SqlServer 2000 sp3 the query used by LLBLGen to determine which fields are in which tables/views is utterly slow. A new query is added which is much faster; it now avoids slow hashtable constructions which were constructed by the query optimizer of SqlServer the old query used an INNER JOIN statement.
- NOTES: This release contains some code borrowed from the upcoming LLBLGen Pro (some GUI classes). This code is written using the .NET guidelines as described by Microsoft in the .NET reference manual. Therefor it might be a little awkward to switch from the old LLBLGen v1.x code which is written using Hungarian Notation and the new code written in caMel/PasCal casing. The new code is located in the new folder browser and the new small form StringInput. All other new code is written in Hungarian Notation.
- NOTES: The sourcecode is for VS.NET 2003. You need a converter for VS.NET 2002 to load the project in VS.NET 2002. Blame Microsoft for their hardcoded linkage between a texteditor and a compiler version.
- NOTES: The documentation is updated, but only for the new features and a small section for VB.NET users.
- NOTES: Changes made by others in the gotdotnet.com workspace of LLBLGen are not included in this release.
- NOTES: No new updates will be made on this code base after this release. The next version will be LLBLGen Pro, the O/R mapper/code generator for .NET.
The .NET's garbage collector (GC) is a wonderful thing: you simply instantiate objects and when they're out of scope and / or no reference is known to those instances, they get cleaned up and you don't have to worry.
At least... in most cases. There are situations where you might think the objects you left behind get cleaned up but instead are kept in memory because there is still a reference known to those objects so the GC will not clean them up. In other words: the objects can't be 'marked for garbage collection'. When is this? Well, if you wire an event handler in class A to an event of class B and A gets out of scope. You might think: "A is out of scope, it gets cleaned up.", but that's not true. The event of B which is wired to a method (via a delegate) of A is in fact still referencing A and therefor A will be kept in memory via the delegate added to the event of B.
So, as a rule of thumb, always de-wire event handlers when you want the object which contains the event handler to go out of scope (and the object which holds the event does not) and to get cleaned up by the GC. Most of the time you'll need this in windows forms, where you'll wire an event handler in the form class to a given object which will eventually fire events which will have some effect on the form's contents. When you close the form and the object wired to the event handlers stays alive in another part of the application, the form is still in memory and will not be garbage collected due to the dangling event handler delegate. Add event handler cleanup code to the form closing event handlers to clean this up.
Of course a form itself doesn't have to do this with event handlers wired to events of its own controls. The reason why is left as an exercise to the reader ;) :)
More Posts
Next page »