2010-03-04
Checking events in VBNet
In Csharp raising an event goes something like this:
var ev = MyEvent;
if( null != ev ){ ev( this, args ); }
Just look through the snippets (look in the context menu in the editor) and you will find the correct way to raise an event in Csharp.
VBNet on the other hand hides the if statement and the temporary variable from the developer. It is enough to write
RaiseEvent Me, args
and the event will be raise if there is someone listening - no need to check for null.
But what if you want to check if someone is listening. In my case I needed to know if the custom control was properly wired into the scaffolding of the application; the user control sometimes whished for more information and I had to know if someone was listening.
In Csharp this would have been easy with a check for null. But VBNet...
The solution is hidden. Just check the variable "MyEventEvent". This means that your MyClick event has a hidden variable MyClickEvent that you can check for like this:
If MyClickEvent IsNot Nothing Then
I don't like to use hidden and unoffical solutions but this is the only way I know of.
Honor those who should.
2010-01-06
Catch property, field and method name changes compile time in dotnet
and have to write
class Customer
{
int Id;
string Name;
...
}
or
myDropdownListbox.DisplayMember = "Name";
myDropdownListbox.DataMember = "Id";
you really get a sour taste in your mouth.
myGridColumnCustomerName.DatatMeber = "Name";
Having magic strings like above spread in your code is really bad since it always compiles but might fail runtime. This means more manual tests. Which in turns means a certain friction against renaming properties while refactoring.
I have been in way too many projects where one table has a field ItemNumber when it should have been ItemCount and where some fields are called Nr while another Number and these names are spread up in the layers to reach the presentation layer where they surface as magic strings like the examples above.
Luckily there is a solution in Dotnet 3 with LINQ. It isn't the prettiest but it fails compile time when it should and that is considered a good thing.
( I won't bother with explanation - just read the code. )
Honor those who should.
// The Code.
class ReflectionUtility
{
public static string GetPropertyName<T,TReturn>(Expression<Func<T,TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
public static string GetMethodName<T,TReturn>(Expression<Func<T,TReturn>> expression)
{
var body = expression.Body as UnaryExpression;
var operand = body.Operand as MethodCallExpression;
var argument = operand.Arguments[2] as ConstantExpression;
var methodInfo = argument.Value as System.Reflection.MethodInfo;
return methodInfo.Name;
}
}
// The test code.
class MyClass
{
public int MyField;
public int MyPublicProperty { get; set; }
public string MyReadonlyProperty { get { return string.Empty; } }
public int MyMethod() { return 0; }
private MyClass() { } // To make sure the class doesn't need a default constructor.
}
class Program
{
static void Main(string[] args)
{
string fieldName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyField);
Console.WriteLine(string.Format("MyClass.MyField:{0}", fieldName));
Debug.Assert("MyField" == fieldName);
string propertyName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyPublicProperty);
Console.WriteLine(string.Format("MyClass.MyPublicProperty:{0}", propertyName));
Debug.Assert("MyPublicProperty" == propertyName);
propertyName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyReadonlyProperty);
Console.WriteLine(string.Format("MyClass.MyReadonlyProperty :{0}", propertyName));
Debug.Assert("MyReadonlyProperty" == propertyName);
string methodName = ReflectionUtility.GetMethodName<MyClass, Func<int>>((MyClass x) => x.MyMethod);
Console.Write(string.Format("MyClass.MyMethod:{0}", methodName));
Debug.Assert( "MyMethod" == methodName);
Console.Write(Environment.NewLine + "Press any key.");
Console.ReadKey();
}
}
Update: When copy-pasting through manoli.net some angle brackets got dropped. This is, hopefully, fixed now. Otherwise - get the source here: http://selfelected.pastebin.com/f77563a02
2009-03-22
truefalse
Personally I write xml comments on all my methods even though I am a fan of method names enough describing that comments really are unnecessary. By descriptive method names I mean that others also understand them.
In a project I stumbled upon this method:
private void ShowHideControl( bool truefalse ){...
Since I had the source code it didn't take much effort to find out what it did.
But a question remains - how do I present the problem for the original programmer without being rude?
Avoid code ownership
I heard a thing the other day I haven't heard for a long time. "That is not my code"
I believe no code and all code in your current project is Yours. There is nothing like finding a bug and leaving it be. If you can't correct it, flag it. Either in a bug tracking system, to the person currently working with that part or to wherever your project stores possible riscs.
This my code-your code mentality mentioned above lead to the bug being forgotten.
That is not considered good.
LINQ examples
Linq is sooo good.
The next time you loop a list or array to find a value or two; consider spending 15 minutes to learn some Linq; it is well invested. The syntax is somewhat like SQL but more straight forward. For instance the keywords are written "the normal" way. First what you have (from), then the filtering (where) and finally what you want (select).
var query =
from c in myCustomerList
where c.Age < 42
select c;
If you are looping two lists and compare them to get a new list, you should really look into Linq. It will save you lots of time.
I found an old site at MSDN with some good examples here: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
2009-01-05
List Find Delegate
Here is a short example of how to use the Find method together with an anonymous delegate in C#.
(there are plenty of examples on the web but most forget to use an external variable)
var myExternalVariable = "Cool"; if you want to be even hairier, translate to lambda var possibleWord = list.Find(s => s == myVariable);
List
var possibleWord =
list.Find(delegate(string s)
{ return s == myExternalVariable; });
2008-12-30
Code that is easy to read
An important code regarding programming is to write code that is easy to read.
I have many times written code, polished it and then rewritten it to the original text since it was easier to read. This is considered mature and a good thing.
A month ago I wrote code like this:
return AllControlsRecursively((Control)form
).FindAll( control => (null == control as IDirty) ? false : true
).ConvertAll( control => (IDirty)control );
I thought about it for several days and then decided to leave the code as it was.
My reasoning behind this is that once upon a time I had problem understanding Fn in BASIC. Later * and & in C. Then I had to learn inheritance, virtual methods and abstract. Today it is lambda methods, WCF and WPF.
One day one has to decide to get the fingers dirty. That day is every day.
2008-09-15
Select distinct is considered bad
Here is a good rule-of-thumb: If you have to write an SQL with Select Distinct, do adjust your chair, get a cup of coffee, walk around the office but above all talk to someone else because Select Distinct is a symptom of something being wrong, either in the database or in your solution.
/* Select Distinct is normally not needed when your database is lagom normalized. But if you do need a Select Distinct then this is a very good example of a situation that needs to be documented.*/
2008-07-03
Defensive programming and Fail at once
In defensive programming you recieve data and inspect it for flaws. When it is possible you manipulate the data so it is correct and usable again. This is good so as much your code works.
But when you are in a project where your code is just a cog in a bigger machinery this approach is not necessarily the best; by recieving and hiding flawed data a bug somewhere else is hidden.
In the example in Wikipedia a string limited to 1000 characters is manipulated. The suggested solution is to truncate the string and keep rowing as if there wasn't a leak in the first place. Depending on the circumstances the bug might be at the caller and by removing the very bug instead of the symptoms the very problem disappears.
According to Fail at once an error should surface as soon and close to the source as possible. The chances for data resulting of the bug to propagate, is then smaller and the bug tracking is probably faster.
In the example it would have been better to throw an exception than to just keep on with data, now faulty in another way than to start with.
Or like this: if a user writes an essay of 2000 characters he probably wants to know that it cannot be saved the very moment ctrl-S is pressed instead of 2 days later when proof reading, when the last 1000 characters are gone both from mind and binary space. Or an operator of a tube bending machine prefers to know if his machine is faulty when he is working at it instead of two weeks later when the tubes are buried inside a wall somewhere.
2008-06-29
Fail at once – an explanation
Automated tests tests things that can go wrong; but what if those things couldn't even go wrong in the first place?
Code that won't compile won't make it into production. Ever.
It is cheapest to not write any errors at all.
Today Fail at once does two things: It stops compiling when it notices something is wrong and at all other times it tries to help the programmer do the right thing.
Typical example of the first is to always use type safe variables and the latter to name things in such a way that there is one very natural way to write the code. By using this explicitly and intelligently you get a leverage for writing better code faster.
2008-06-18
Make sure your objects are fully populated – Fail At Once
public Customer()
{
}
is seldom needed while working with business objects. Honestly – how do you need an object that is not? Do you have a Customer or do you not? A few situations comes to mind where an almost-Customer is needed but they all smell of refactoring, i.e. base class, sub class and two constructors.
To make sure I don't have an object that is not fully populated I make sure the default constructor is not reachable. Either through creating other constructors or by making it private the times it is needed internally. Instead I create a constructor that takes all necessary parameters to fully populate itself. If there are variants I create more constructors. I am not afraid of writing code but I strongly dislike putting bugs into production. Hence Fail At Once.
Sometimes it is handy to have a void method taking all parameters and calling it from the constructor but this is just a variant of the pattern above that objects that are not correctly populated are very seldom useful.
Another advantage with this routine is when adding (or removing) another mandatory field. Then there is one and only one place to update to make the compiler give you all places to update.
I have noticed that it is hard to make handy lists without having a default constructor but this, I presume, is just the exception that confirms the rule.
Bugs that can't compile will not go into production.
2008-01-24
How to raise an event
But there is a caveat one should be aware of; especially since it probably will show itself intermittently and be hard to track down. It is when someone finishes his listening for the event between the does-someone-listen-for-the-event and the very firing.
The good news is that it is easily solved by a temporary variable like so:
internal event NavigateDelegate OnNavigate;
internal delegate void NavigateDelegate( NavigateTypes navigateType );
private void Raise_OnNavigate(NavigateTypes navigateType)
{
NavigateDelegate tempEvent = OnNavigate;
if (null != tempEvent)
{
OnNavigate(navigateType);
}
}
If the above is hard to remember there is a snippet
invoke
to use. Just write it at a line and press Tab.
2008-01-22
The simplest possible solution, but not simpler than that
När man inom Agile pratar om den enklaste metoden menar man inte den lösning man först kommer på eller den som går snabbast att implementera.
Med enklast innebär den lösning som löser uppgiften med minst extra information och avsteg från befintligt mönster.
Detta kan tarva en förklaring.
Med minst extra information menas möten, dokumentation och implicit och explicit kunnande. Om lösningen följer gängse mönster behövs antagligen ingen dokumentation, varken som explicita dokument eller inline-kommentarer. Om lösningen är "rätt" krävs mindre möten, diskussioner, dokumentation, rådfrågningar och redogörelser.
Enklast är inte nödvändigtvis den lösning som kräver minst tankearbete eller minst jobb.
För att vara ärlig talar jag inte för hela den agila rörelsen. Texten ovan är min tolkning av begreppen, metoden, livet, universum och allting.
When the agile development movement talks about the simplest solution; they do not mean the first solution that pops up in the head or is fastest to implement.
Simplest means the solution that solves the problem with least extra information and sidesteps from the chosen/optimal path.
This might demand an explanation.
With least extra information means meetings, documenation, implicit and explicit knowledge. If the solution follows the chosen path, colour and rythm of other well written parts of the solution; it probably doesn't need documentation, neither as explicit documents nor as inline comments. The "right" solution requires less meetings, discussions, documentations, questions and answers.
The simplest solution it not neccessarily the solution that requires the least amount of thoughts or work.
To be honest I cannot say I speak for the whole agile movement. The text above is my view of the terms, the method, life, universe and everything.
2008-01-17
Build list classes
(dotnet-kod)
Gör listklasser av dina klasser.
D.v.s. gör en egen klass
class UserList : List
{
...
}
För då blir anropen
UserList userList = new UserList( "whatever parameters" );
User user = userList.FindByName( userName );
istället för
List
User user = FindUserByName( userList );
Lika många rader kod och ungefär lika lättläst men bättre "information hiding" i de senare exemplet.
(dotnet code)
Make list classes of you classes.
Make it like
class UserList : List
{
...
}
Then you can have calls like
UserList userList = new UserList( "whatever parameters" );
User user = userList.FindByName( userName );
instead of
List
User user = FindUserByName( userList );
About as many rows of code and about as readable but better information hding in the latter example.
2007-12-11
Volta and Script# - type safe javascript
Så länge jag har känt mig själv har jag klagat på den svaga typningen i Javascript.
Jag kan förstå att implementationen är olika mellan olika webbläsare och nästan, men bara nästan, förstå Microsofts egocentriska volt med IE att göra en egen händelsemodell. Men jag kan inte förstå det strategiska beslutet av Netscape att göra ett svagt typat språk.
För några år sedan ramlade jag över en lösning, Script#, som kunde omvandla typsäker C#-kod till Javascript. Den var ett experiment så jag vågade aldrig ta in den i produktion och hade inte tid att leka med den. Vad jag inte visste förrän nyligen var att Microsoft har tyckt som jag.
Så nu har de lanserat Volta.
As long as I have known myself I have been irritated on the weak type model of Javascript.
I can understand that the implementation of Javascript differs between the web browsers. And I can almost understand Microsofts egocentric trick with Javascript in the earlier IE versions. But I have never understood Netscape's reasoning behind making a language weakly typed.
Some years ago I stumbled over a solution, Script#, to convert type save C# code to Javascript. It was an experiment so I never dared to bring it into production even though I wanted to. What I didn't know was that obviously someone at Microsoft thought like I.
So now they have launched Volta.
[Update: Bytte mjuk mot svag.]
2007-11-08
Fail At Once
Hur får man rättningar och funktionalitet så fort som möjligt genom dörren?
Hur får man så få buggar som möjligt i produktion?
Jag fick en gång kommentaren från en vän "Men du levererar väl aldrig otestad kod?". Det var en komplimang och en kommentar till att jag just då satt i ett projekt som skulle leverera den högsta kvaliteten jag levererat hittills, dessutom rakt ut i fabrik
Mitt svar förvånade honom "Jag testar inte." Jag lät honom hämta andan. "Rättning: jag testar så lite som möjligt och mycket kod går rakt ut i produktion otestad."
Sedan följde en förklaring. En förklaring jag har dragit för alla i projektet:
"Använd kompilatorn för att fånga fel."
Vanligtvis när man talar om system med hög kvalitet pratar man om testning. Massor med manuella tester med speciella konsulter man hyr in som är specialiserade på test. Dyrt. Men det blir dyrt med hög kvalitet.
Bullshit.
Manuella tester är dyrt och tar lång tid.
Modernare utveckling innehåller enhetstester.
Jag förespråkar Fail At Once för att slippa många enhetstester och manuella dito.
Det är viktigt att fånga fel så fort som möjligt. De allra bästa är att inte skriva dem alls.
Där är jag inte ännu.
How do you ship patches and functionality as fast as possible?
How do you get as few bugs as possible in production?
I once got a comment from a friend "But you never deliver untested code?" It was meant as a compliment and comment to my job then; I was working in a project that was delivering the highest quality I have ever delivered; right onto factory floor.
My answer surprised him "I don't test." I let him catch his breath. "Correction: I test as little as possible and as much code as possible goes into production untested."
I had to explain, the same explanation everyone in the project had heard.
"Use the compiler to catch errors."
Normally when one talks about high quality system one also mentions testing. Lots of manual tests with consultants specialised on testing. Expensive. But high quality is expensive.
Bullshit.
Manual tests are expensive and take lots of time.
The more modern unit testing is cheaper.
I recommend Fail At Once to get rid of many unit tests and manual ditto.
It is important to catch errors as fast as possible. The best is to not write them at all.
I am not there yet.
2007-10-24
Nettiers
Jag har jobbat med Codesmith i två projekt och Nettiers i ett av dem. Jag kan rekommendera.
Jag har inte jobbat med konkurrenter och kan inte jämföra. Någon?
Det har varit kritiskt att det är gratis i bägge fallen så sista Nettiers/Codesmith-kombinationen som är gratis är http://nettiers.googlecode.com/files/netTiers-2.2.0.zip och http://www.codesmithtools.com/freeware.aspx.
Det finns för- och nackdelar med automatgenererad kod.
Codesmith är closed source medan Nettiers-mallarna är GPL. Märk: resultatet av Nettiers-mallarna är inte GPLade utan dina.
I have worked with Codesmith in two projects and with Nettiers in one of them. Recommended.
I have not tried any competitors and cannot compare. Anyone?
In both projects it was crucial the price was zero so instead of you looking around just go to the last zero-price combination. http://nettiers.googlecode.com/files/netTiers-2.2.0.zip and http://www.codesmithtools.com/freeware.aspx.
There are pros and cons with automatically generated code.
Codesmith is closed source while Nettiers templates are GPL. Note: the result of Nettiers is not GPLd but yours.
2007-10-19
Fail At Once
Automatiska tester i all ära men hade det inte varit bättre om man inte hade behövt testa alls?
Jag kommer komma tillbaka i ämnet.
Automatic tests are great but hadn't it been better if one didn't have to test at all?
I will get back on the subject.
2007-10-18
Find the cause of the error
Häromdagen dök en konstig sak upp i testningen. Fel uppstod och försvann utan att vi gjorde något. Jag bygger system så att detta inte skall hända så det var dubbelt konstigt.
Jag satt med testaren på telefon och diskuterade vad han gjort och vad vi andra gjort; om något hänt mellan eller under hans tester. Vi diskuterade databaser, releaser, maskiner, applikationer, var han hämtar... Bingo! Testaren förutsatte att en installation var kompilerad innan han testade.
I efterhand kunde jag ha listat ut det eftersom jag var med och satte upp QA-reglerna men i min iver att få ihop den nya funktionaliteten och testa att leverera utan att testa glömde jag av testarens arbetsregler.
Så vi hittade felet; fel målbild. Målet var inte att ordna med ny funktionalitet utan att levererera denna nya funktionalitet till testaren.
The other day a wierd thing surfaced in testing. Errors sprung to life and disappeared without us changing anything. Considering me constructing systems so this will not happen made it double wierd.
I disussed this with the tester over phone. We discussed what he had done, what the others did; if something happened between or during his tests. We discussed databases, releases, machines, applications, where he fetches... Bingo! The tester fetched each new ready created installation and I hadn't supplied one.
Looking back I can know I knew I had to create the installation before handing over the new functionality; but eager to deliver and try to deliver without testing made me forget the environment of the tester.
So we found the error; the wrong target. The target was not to provide new functionality but to deliver this to a tester.
2007-09-21
Why is a primary key an int?
The reason for this is that computers are good at numbers and an integer is a very versatile and fast number representation.
But there are drawbacks in the business layer. A customerID can be compared to a orderID like so:
if( customerID == orderID ){...
this is not a good thing.
CustomerIDs should only be comparable to other CustomerIDs.
They should also not be addable, subtractable, multiplyable and being greater than anything else. A CustomerID is equal or not equal to another CustomerID. All other comparisions are not of this world.
I have yet to figure out how to implement this.