Showing posts with label Software Development. Show all posts
Showing posts with label Software Development. Show all posts

Feb 27, 2012

2 ways to make estimations in the software world.



I've watched a presentation held by Joel Semeniuck. As his LinkedIn profile states, he is currently "Executive VP at Telerik", anyway, this post is not about Joel himself but about estimating how much does it take to complete a given software project.

I was thinking about this over and over again.
Actually - each time I gave an estimation while I was at Telerik - my team lead used to double it in order to get somewhat accurate estimation.
And I was pretty ashamed in the beginning. I always push as much as possible in order go be a great software developer, I stay night, I work weekends, whatever it takes. And still I can hardly meet my deadlines.
(Note: I wasn't working night / weekends @Telerik, this is a generalization of my whole life as a software developer.)

Why would that be? I am trying so hard and still no result.
(to be honest - there are lots of cases that I was able to meet deadlines, but they were about things I already knew how to do step by step so they don't count. Or do they?).

And it's the bolded sentence above that got me thinking.
And I came up with yet another software development law. Maybe it only applies to me so it is not actually a law that will cover the whole software development industry, but let me first say it and then I'll discuss it:

"You can estimate a software project using two algorithms - the algorithm that all Windowses prior Vista used to estimate file copy time and the way all Windowses including Vista and later use to estimate the time it will take to copy a file."

First of all what's the difference?
In Windowses prior Vista the way explorer will tell you how much time will it take to copy file / files would be somewhat random, then it starts to fluctuate during the copy progress. Ever started with 2 minutes, gone to 10 minutes? Well that's what I'm talking about.
In Windowses starting from Vista - the system will be much more acurate, except for one thing - it will not tell you how long will take to calculate how long would it take to copy the files. So you first wait for Windows to do some estimations by chunking the data it has to deal with. And then it will be more accurate in saying how long will you wait.
(Note: I probably miss a lot from their algorithms but this is the end user impression it leaves).

So basically if you start estimating like older Windowses - you will be looking at one large chunk of work and you will be able to estimate that chunk roughly.
If you give your estimation the way Vista and newer Windowses work - you will have much more acurate estimation as you would have chunked all the data upfront. And there will be much less room for errors. So in the ideal case you will have to split the big chunk into really really small tasks you know you can do in an hour.
The bad thing using the second approach is that when asked "What's your estimate on this?" you will need to say "Gee, I don't know, I will first need to take my time to estimate it, I'll then be more acurate.", "How much time would you need to estimate this?", "Gee I don't know. You'll have to wait for me.".

So to summarize:
Estimating like old Windows: "It will take 2 months and it may go up to 10 months. I may be able to complete it in 2 weeks though."

Estimating like new Windows: "Come back later. Or better - I'll call you when I have an estimation. I know you have a decision to take but I can't do anything about it yet.".

I am leaving you decide which one to use :). Maybe a mix of both?

P.S. If you think about it - this applies to known projects. Add some third party black box integration and you will fluctuate the same way windows fluctuates when it downloads a file - it tries to take into account a variable that is changing randomly - the speed of your internet connection. For such projects you can go from 1 hour to 1 year or even to work 1 year and understand that the project cannot be completed (well guess what - although Windows states it will get your file in 1 hour, it doesn't tell you what will happen if you decide to disable your internet adapter).

Jun 10, 2011

Convert string to a known type (using its default converter)

I was in a need to get a type, instantiate it and then fill its properties (I'm currently doing an engine that will give me an instant CRUD UI).

So what I basically needed was to be able to fill a new object instance out of a Hashtable (the key is the name of the property and the value is its string representation).

I wanted to be able to convert that string value into the type it needs to be.
Here is some code to help you get it:

foreach(string strPropertyName in htValues.Keys)
{
PropertyInfo pi = entity.GetType()
.GetProperties()
.ToList()
.FirstOrDefault(property => property.Name == strPropertyName);
}
(this is kind of pretotype so don't blame me if you don't like the code :).

In the above code I am iterating in the keys of the hashtable, so if I have an user object it will strPropertyName will hold "FirstName", then "LastName".
So far so good, I am able to fill the object and send it to the EntityFramework for DB Persistance.

The problem was when the strPropertyName was holding "BirthDate" as it is a DateTime and the EntityFramework or the Reflection (not quite sure which one) was crying it can't Convert the string to the respective type for me.

Here is how I solved the problem:
// Create a new Instance of the given type.
object entity = Activator.CreateInstance(this.EntityType);
// Iterate through all the properties.
foreach(string strPropertyName in htValues.Keys)
{
// Get the property with that name:
PropertyInfo pi = entity.GetType()
.GetProperties()
.ToList()
.FirstOrDefault(property => property.Name == strPropertyName);
// Get the default type converter for the given property type:
TypeConverter converter = TypeDescriptor.GetConverter(pi.PropertyType);
// Set the value by converting non-values to the given type
// and setting null where it is a null value.
pi.SetValue(entity, htValues[pi.Name] == null ? null : converter.ConvertFromString(htValues[pi.Name].ToString()), new object[] { });
}

Basically the thing you (and I!) need to remember is that the TypeDescriptor class has a GetConverter() method that takes a type and returns a TypeConvertor for that type.

Now in order to be able to convert from string to that type you just need to call .ConvertFromString(string value) of the TypeConverter returned by the TypeDescriptor.

Hope this helps someone out there. To me it seems it can give you a great deal of abstraction and I (for some reason) believe this is heavilly used in nowadays OR/M's.

Jun 9, 2011

Check if a type is Nullable or not

I was in a need to determine if the type of PropertyInfo is a nullable or not.
Here is what I've found on MSDN about this:

property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)

So you basically need to determine if the type is generic (makes sense as nullable is a type that takes T (Nullable)) and then to check if the type is a Nullable then.

Now, I really wondered do I really need both checks?
As it was coded that way at MSDN I first didn't look at that, but I wanted to tackle it a bit more.

First I thought that the first one is needed to protect you from the null value returned by the GetGenericTypeDefinition() method.
But what's the problem even if it does?
Well, you get InvalidOperationException saying "This operation is only valid on generic types.".

So you definetelly need both checks ;).
It is kind of ugly for me, maybe it will be better to create an extender to the Type type. Something like "IsGeneric()", but the Is prefix always suggests property while this is a method.

Anyway, I'll go with that.
In the next post I'll show you how to get the type out of a Nullable<>.

Sep 9, 2010

It's time to vote again!


It is again time to vote for your best tools in the software development.
Don't waste time, showing some love to one vendor or another will help that vendor push harder in the right direction.

So click on the image and show some love to your favorite vendor.

Jul 19, 2010

Site is recycled + ThreadPool.QueueUserWorkItem


Just to let you know that you may experience this issue.

If you have an unhandled exception it may be because of a job queued using ThreadPool.QueueUserWorkItem method.

Actually it appears that although the exception is not affecting the main thread (it was in another one) - the .NET will kill the running process (w3wp in our case).

As far as I read this behavior is implemented since .NET Framework 2.0.
It is because you may miss unhandled exceptions in a child thread (if it's in the main thread the process will be terminated in a windows application).

I imagine each request to a web server as a separate thread so I am kind of worried why unhandled exceptions aren't killing the W3WP process as well.
It only seems to be killed if you create another thread in the request thread and this another child thread exits with unhandled exception.

Will need to investigate a bit more about that.

Dec 3, 2009

Introduction to programming with C#

As Vesko Kolev stated in his blog - a new bulgarian book about C# programming is in progress.
I decided to take part because it seems very interesting. I haven't much experience in publishing so it will be very beneficial for me to work on this.
Actually I was author in a software magazine few years ago (as far as I remember I was about 17 years old so it must have been about 6 years ago). It should help me as I took the first chapter - introduction to programming where I will show the readers how to install Visual Studio 2010, how to start their first project and how to write their first program, some diagrams of the .NET framework 4.0 will also be included in this chapter.

We decided not to include any advanced features in this book, just core programming language, no extensions, no lambda expressions, no var, no automatic properties, no nothing.
This is because this book targets potential software developers and not software developers. It should show the developer how to code, how to think etc. We decided that if a man / lady without any software experience may think that auto property won't take memory after it doesn't involve variables (at least visualy :).
That is why we do only core things.

Wish us luck. We would really love to expand bulgarian software development community with few more people :). After all if even one guy / gal of all the people that will potentiall read the book becomes an expert - our mission would be completed (we are dreaming for more impact ofcourse :).

As Svetlin Nakov and Vesko Kolev said - telerik is sponsor for this book so it should be published easilly than their prеvious book - "Introduction to programming with Java" and would probably joy some more marketing efforts.

That was it about the book.
Now about my motivation to join the project no matter my personal engagements and all the work I have at telerik and at the university.
The first reason is that I am a self - taught (almost) developer.
I never had degree that will help me find my work, join some society of developers that will help me when I hit a difficult problem.
There wasn't even internet in my hometown. A friend of mine gave me a book on programming with Delphi (that Sams 21 days brick :).
The Delphi help also helped me and I also downloaded html files to read later when I was at school.

Then I applied for a job in the city where I was studying (Veliko Tyrnovo).
It was all my collegues that helped me improve my skills.
I don't feel as a worldwide recognised expert or something but getting to the intermediate level from nowhere is achievement to me.
So reason #1 to join this book is to give something back.

Another reason is that I would like to see how a book is written, are there different proccesses than in the software development. It has something to do with the blog posts I guess :)
So reason #2 is to steal some knowledge :)

And some kind of nostalgy would be the last reason to join :).As I said, I was an editor in a software magazine, it was very nice thing to do. The article, then the readers asking for some more information. I miss this a bit :)
Reason #3 - to feel the old days when I was an editor :)

The specified service has been marked for deletion error message when removing a service

If you receive this message while trying to delete a windows service - check if the Services.msc application is open.

You will need to restart in order to delete the service, but you will know to first close the Services.msc application the next time PRIOR uninstalling the service (using installutil /u service_exe_name).

Hope this helps someone outthere...

Edit : I found another scenario when this can happen and it seems to be more .NET specific and common to software developers - if your service creates some worker threads, Windows will attempt to kill the main thread, the main thread will attempt to kill the main thread but the worker threads if not marked as BackgroundThreads via the IsBackgroundThread property will remain. The GC will wait for them to reach a safe point so they can be terminated and the service will most probably be only marked for deletion, requiring you to restart windows.

Please note - if you are using the ThreadPool class you will probably not hit this problem as the ThreadPool internal threads are automatically marked as background threads.

Edit 2: Another case when you will receive The specified service has been marked for deletion error message is when you try to uninstall service which wasn't stopped first or it was marked as unstopable.
This is done if you have this.CanStop = false in your service code.
Windows knows this service shouldn't be stopped and it will only mark it for deletion but will not delete it right away.
Be careful with CanStop property.

Nov 24, 2009

Limiting your Internet connection speed with Fiddler.

In some cases you may need to limit your connection for testing purposes.
This is / should be extremely easy using Fiddler.
Here is a simple walkthrough on how to do this:

1. Go to Fiddler site and download Fiddler latest version (http://www.fiddler2.com/fiddler2/)
2. Install it and start it.
3. Click on Rules -> Customize Rules:

4. An instance of notepad should open. Find the line that says something like "oSession["request-trickle-delay"]":

This setting tells Fiddler how much milliseconds should halt the request. (not quite sure how a request halt will help you though)
5. Find the line that says "oSession["response-trickle-delay"]" and change it:


Save the file.
You should have a connection limitation.
Now, when you want your connections slowed down, you will need to check the following option:

6. Rules -> Performance -> Simulate Modem Speeds (should be checked):


Please do not forget to switch off fiddler when you don't need it as you may find yourself wondering why is your connection significantly slower than usual ;).
Hope it helps someone out there.

Mar 12, 2009

tinyMCE has the sup - sub issue too

Just to inform you that tinyMCE cannot handle the sup / sub correctly also.

Here is a video:

Dec 14, 2008

Nice little tool to help me with twitter.

I created a small twitter software what it does is to check each hour if I am listening to Winamp, get the song if possible and write it in twitter for me and the people who are eventually interested in what I am listening.
Here is the deal:



You can download it from here:
TWamp - Nice little twitter software

You can follow me on twitter from the following url:
My twitter profile

Please note: TWamp isn't very user friendly. You need to get along with it in order to use it ;).

Dec 1, 2008

Microsoft Office Word automation in C# - How to add table to the document?

The following C# code will create a new document, add a table to it and ask the user to save it. Document will look like this:



The following code will add a table in word and then ask the user to provide a filename to save the document:
        Microsoft.Office.Interop.Word.
Application app = new Microsoft.Office.Interop.Word.ApplicationClass();
        app.Visible =
false;

        
object start = 0;
        
object end = 0;
        
object oNull = System.Reflection.Missing.Value;

        
Document doc = new DocumentClass();
        doc = app.Documents.Add(
ref oNull, ref oNull, ref oNull, ref oNull);

        
Table tbl = doc.Tables.Add(doc.Range(ref start, ref end), 10, 2, ref oNull, ref oNull);
        
Random rnd = new Random();
        
for (int i = 0; i < 10; i++)
        {
           tbl.Rows[i + 1].Cells[1].Range.Text =
"Run# :" + ((int)i + 1).ToString();
           tbl.Rows[i + 1].Cells[2].Range.Text =
"Value :" + rnd.Next(0, 2000).ToString();
        }

        
object oFalse = false;
        app.Visible =
true;
        
try
        {
           doc.Save();
        }
        
catch (Exception ex)
        {
          
if (ex.Message.ToLower().IndexOf("command failed") == -1)
           {
            
throw ex;
           }
        }
        app.Quit(
ref oFalse, ref oFalse, ref oFalse);

What we done is to create a new document, a new table, and fill the table with random values.
Seems very easy but not quite sure how well document :).

Nov 14, 2008

Two new automated blogs

I've been very busy this month. All the exams (for microsoft certification, in the faculty and so on), my extended work day (from 9 to 20 as I was absent
from work for about a month and need to do some extra work to catch my collegues), some ongoing projects I was stupid enough to take and so on...

However, I've found some time to start two new blogs which I consider more as experiment than real blogs:

Sql Exceptions

and :


.NET Exceptions



Both blogs currently contain about 40 posts with Sql and .NET Exceptions which you may find helpful after time. I am saying after time as I plan to automate those blogs so the information there is posted by software and not by myself.

Also users are welcome to post comments. Soon I will publish special format of posts which you can use in order to give your opinion on specific exception and this exception will be automatically published in the post.

Unfortunatelly there is a limitation - Blogger allow me to only publish about 40 posts daily so I wasn't able to create posts about all the exceptions in SQL and .NET Framework.

I will batch post each day (may miss some of the days like weekends for example ;) so in few weeks both blogs will be up to date.

Nov 5, 2008

On the asp.net official site for the very first time!

Well, a lot of people don't consider showing someone on the official asp.net site a big deal. There is a box "Community recognition program" where the most active members as well as yesterday's most active members are shown. I had 102 points for the previous day so I appeared. It really isn't big deal, but I consider it a big start, because it gave me motivation to continue to contribute. It is not about the recognition. In asp.net site you can find a lot of friends also. It is great to help someone and then see something like : "Dude, you're
awesome, you pointed me in the right direction." or "Dude, you saved me a lot of hours" and so on. There are a lot of things I would like to learn about asp.net and I think this forum is a great place to start. Just post a question and in most cases in few minutes some of the experts there will answer you.

Here is a screenshot I will keep close to my heart :D



Oct 21, 2008

C# AddIn - Start Debugging and get the running Internet Explorer instance.

I needed to do this (actually I wanted). I was curious if you can obtain an instance of a Internet Explorer which was started in debugging session. Here is a snipet to do this:

        _applicationObject.Debugger.Go(
false);
        SHDocVw.
ShellWindowsClass windows = new ShellWindowsClass();
        
foreach (SHDocVw.InternetExplorer explorer in windows)
        {
          
if (explorer.LocationURL == string.Empty)
           {
            
// this is our guy!
             ie = explorer;
           }
        }


Note : this snipet should be added somewhere where you have access to the _applicationObject.
This is the variable which is declared automatically when you create new instance. I suggest you to put it into the exec method of the AddIn:

     public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
     {
        _applicationObject.Debugger.Go(
false);
        SHDocVw.
ShellWindowsClass windows = new ShellWindowsClass();
        
foreach (SHDocVw.InternetExplorer explorer in windows)
        {
          
if (explorer.LocationURL == string.Empty)
           {
            
// this is our guy!
             ie = explorer;
           }
        }
     }

You also need to add reference to ShDocVw (Microsoft Shell And Automation Library).
Enjoy!

Oct 19, 2008

Touchless SDK : Very interesting and promising technology each of you guys should play with :)

I came on this yesterday, I was bored because all the projects I am working on are to some degree "standard". No dev chalenge. I wanted to create, to do something interesting.
So I started to browse CodePlex and found this SDK.

Overview :
Touchless SDK is a software development kit to help developers create applications which can be controlled without the standard peripheral devices (mouse, keyboard and so on). It enable you to create a applications which are controlled without the need to touch anything at all, just gestures in the air.
How is this done?
Well, I think there was a lot of research on this topic. We already have programs to detect motion from your video camera, why not try to extract information from those motions? This is
exactly what Touchless does. It captures an info from your camera and if it finds something that is known to be marker - it raises events, to which you can subscribe and do something.
The better news is that Touchless is Open Source project and can be obtained from CodePlex for free.
You can also whach a video on Touchless:





I downloaded this SDK and in less than a minute I made a small program which let's you move your cursor with fingers (I still can't find a good enough way to left and right click ;).
I hope I will have enough time this week to post this simple project so you can get deeper with Touchless as it seems promising technology to me.

Limitations:
Well every good thing has drawbacks. Don't get it wrong. Touchless isn't the standard in this area. It has problems (however I think after it is open source a lot of people can work on it and improve it).
So what are the limitations?
First of all - Touchless is very very very sensitive to light and to colors. It is because the way it works. In order to work, you need to specify a "marker". Marker is the thing the program looks for. So if you have a red tape on your finger and define it as marker, you will be able to command your computer with it. But if there is a object with the same color on the screen and this object is about the same size, it may be found as another marker.

The second problem (at least for the sample project I did) is that most web cameras are not sensitive enough. They are (most of them offcourse) with 640 x 480 pixels resolution. If you are about to move your cursor and your screen resolutions is 1280 x 1024 you will be only able to move the cursor 640 pixels horizontally and 480 pixels vertically (this can be software corrected by moving the cursor 3 or 4 pixels on each pixel that comes from the camera but for sensitive operations (resizing, drawing) it will not be good enough.


However I think the things above will be resolved and we will have another great way to use our computers for almost no extra charge.
I do really wish those guys luck and I will definatelly watch how this project goes and even if I can I will help a bit.
I really fell in love with this toy!

Oct 7, 2008

One more ASP.NET page optimization ...

I wrote two articles on this topic already. The first was that you can earn few bytes from renaming the "javascript:__doPostBack" to "__dp". Then I noticed that I have problems with this. The problem was that in some cases you need to have the "javascript:" prefix.

So my first attempt to do some optimization is considered more unsuccessful than successful.

Now I am going to propose another way.
It is again based on removing / renaming / moving existing things in the page so they can be a bit more optimized.


Let's suppose we have a GridView. We clicked on the "Auto Format" thing and we not only have a GridView, but we have a nice looking grid view. It's great, but it seems to be unefficient. It appears that the GridView will add a
style="" attribute for each row / cell (not quite sure about the exact rules). And it will generate repeating markup, increasing the size of the page and respectivelly - your bandwidth.

I did a small snipet to fix this (not the best solution again but should be kind of starting point).

Here is my code:

     protected override void Render(HtmlTextWriter writer)
     {
        System.IO.
StringWriter stringWriter = new System.IO.StringWriter();
        
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

        
this.EnsureChildControls();
        
base.Render(htmlWriter);
        
string html = stringWriter.ToString();

        AnalyzeStyles(html);
        html = RepairStyles(html);

        writer.Write(html);
     }

    
private void AnalyzeStyles(string html)
     {
        
MatchCollection CSSMatch = Regex.Matches(html, "style=[\"].+?[\"]", RegexOptions.IgnoreCase);
        
foreach (Match mCss in CSSMatch)
        {
          
if (htDuplicates.ContainsKey(mCss.Value))
           {
             htDuplicates[mCss.Value] =
Convert.ToInt32(htDuplicates[mCss.Value]) + 1;
           }
          
else
           {
             htDuplicates.Add(mCss.Value, 0);
           }
        }
     }

    
private string RepairStyles(string html)
     {
        
int classID = 0;
        
int pos;

        
IDictionaryEnumerator iOccurences = htDuplicates.GetEnumerator();
        
this.CSS += "";

        InformaticsWeb.Pages.
Optimized master = (InformaticsWeb.Pages.Optimized)this.Master;
        
        pos =
Regex.Match(html, "", RegexOptions.IgnoreCase | RegexOptions.Singleline).Index + "".Length;
        
        html = html.Insert(pos, CSS);
        
return html;
     }

Please note : AnalyzeStyles adds each of the style="" found on the page (each unique). If it finds secound and third and so on - it increases a counter. The counter is not currently used, but may be later used to decide which of the styles should be converted to CSS classes.

So this code basically takes the page and moves all the style="" attributes in the head section as a CSS classes. I tested and my grid view seems as beautiful as before this code was applied.

Now, does it worth to add this logic?
Well I think you can achieve the same functionality by using Skin files. I am adding this more for reference.
I also did a small excel diagram to show you how much bytes are saved based on the count of the items in the GridView:




Please note that the htDupplicates is a Hashtable, declared as a global variable, so you will need to add it if you want to use this code.

Let me now explain the columns in the excel file shown above.
The “Columns” column displays how much columns does the GridView render. Typically the columns are rendered as a table cells and doesn’t contain any style=”” attributes (at least I couldn’t see any), so this is something you can’t affect. The thing that this optimization affects is the number of rows in your gridview. The more rows you have the more bytes you will get.
The second column displays the number of rows in the grid view.
The third column is the optimized size of the gridview (when the above technique is applied).
The “Size Original” column displays the size for unoptimized page (the same page!).
And the last column shows you the difference before and after.

You can see it in the diagram - for 20 items you have about 842 bytes difference. While for 80 you have about 3,512 (I don’t think there is a live site which displays 80 items at once in a grid view ;).

Oct 3, 2008

Very elegant way to cut few more bytes from your ASP.NET markup and optimize your bandwidth a bit

I was thinking about how can I optimize the markup of a page a bit.
I found a great way (great but not very very very efficient) to do so.
It is based on a strategy that came in my mind recently.

Let's think a bit.
We already have very interesting methods to cut bandwith of an ASP.NET page like for example compressing the view state and so on and so on.
So provided we already have applied those techniques, if we still want to optimize what should we do?

I call my method : iterative profit, you will soon understand why ...

If we have something that repeats few times in the markup and is relatively long as name, if we make it shorter we should win some bytes right?
And if the page is big enough and "the thing" is repeated more times, we
will win more and more bytes.
So each time we cut the name of something, we win few bytes.

The next question is what can we cut in order to optimize our page?
What is the thing that repeats in each web control?

The answer is the "__doPostBack" function. I tried to replace it during the Rendering of the page and was able to cut a bit of the page size, while keeping the source relatively clean of errors (please note the word "relatively").

Here is a sample code:

     protected override void Render(HtmlTextWriter writer)
     {
        System.IO.
StringWriter stringWriter = new System.IO.StringWriter();
        
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
        
base.Render(htmlWriter);
        
string html = stringWriter.ToString();
        html = html.Replace(
"\"javascript:__doPostBack", "\"__dpb");
        writer.Write(html);
     }

I had some issues I haven't yet identified, as I was in a rush to post this as it seems to me a brand new way to optimize pages - to look for repeating elements and cut their names... (I will be happy if there are volunteers to help with this one ;)...


Other things : DoPostBackWithOptions should also be replaced by dpbw for example, this will be done in the future, after I clean the _doPostBack as it still have few problems.


And some more things - we may consider optimizing some of the ASP.NET controls which are known to be "markup unoptimized" like the treeview, gridview for example (At least I think there may be some things in them to optimize).

Any comments are welcome.

Something that a lot of C# developers will miss when designing their classes

The thing is that the developers often forget they can set access modificators at set / get level for a property.

Consider the following classes:

namespace Locals
{
  
class Program
   {
    
static void Main(string[] args)
     {
        
LocalManager LocalMgr = new LocalManager();
        Remote.
RemoteManager RemoteMgr = new Remote.RemoteManager();
        
User usr = new User();

        LocalMgr.Promote(usr);
        
Console.WriteLine("After local promotion: " + usr.Occupation);
     }
   }

  
public class LocalManager
   {
    
public LocalManager() { }
    
public void
style="color:Black;"> Promote(User usr)
     {
        usr.Occupation =
"Chief Officer";
     }
   }

  
public class User
   {
    
private string strOccupation;
    
public User() { }
    
public string Occupation
     {
        
get { return this.strOccupation; }
        
set { this.strOccupation = value; }
     }
   }
}

Here, after the program is executed the Local manager will promote the user and the output will be :
After local promotion: Chief Officer

Now imagine that we want to have the name of the manager who promoted the User, so we can store it in a database. Obviously we need to have an instance of the Manager class, and write the information in the database, prior changing the occupation for the user.

We will want to have a method in the User class, which takes the Manager instance, writes everything needed in the database and then changes the Occupation.
But we can't be sure that all developers will use the method and not the property directly.

Firs let's add a property to the LocalManager class to hold the name of the manager. Then I will create a method to change users occupation, which will take an instance of LocalManager. This will be the only way an external class to change the occupation of a user. After this, we will slightly modificate the code in the main program so everything is called properly. Here is the code:

using System;
using System.Collections.Generic;
using System.Text;

namespace Locals
{
  
class Program
   {
    
static void Main(string[] args)
     {
        
LocalManager mgr = new LocalManager();
        mgr.ManagerName =
"Pavel Donchev";
        
User usr = new User();
        mgr.Promote(usr);
        
Console.WriteLine("After promotion: " + usr.Occupation);
     }
   }

  
public class LocalManager
   {
    
private string strManagerName = string.Empty;

    
public LocalManager() { }
    
public void Promote(User usr)
     {
        usr.Promote(
this, "Chief Officer");
     }
    
public string ManagerName
     {
        
get { return this.strManagerName; }
        
set { this.strManagerName = value; }
     }
   }

  
public class User
   {
    
private string strOccupation;
    
public User() { }
    
public string Occupation
     {
        
get { return this.strOccupation; }
        
private set { this.strOccupation = value; }
     }
    
public void Promote(LocalManager manager, string Occupation)
     {
        
if (null != manager && !string.IsNullOrEmpty(manager.ManagerName))
        {
          
// Do additional work here, for example write the
           // name of the manager in the database amoung with
           // time stamp of the promotion to have audit...

          
this.Occupation = Occupation;
        }
        
else
        {
          
throw new Exception("A valid manager instance and occupation should be passed!");
        }
     }
   }
}

Now our classes are ready. You can give your user class away and be sure that no one can modify the property without passing a valid manager instance (actually the sequence of exceptions will guide your peers to follow the correct logic ;).


Oh, one more thing - we didn't proof that no one can assign the User.Occupation property directly. Well try to do so, you should receive compiler error message:

The property or indexer 'Locals.User.Occupation' cannot be used in this context because the set accessor is inaccessible

Jul 17, 2008

Code Policies - the first step to get rid of boring code policy violations is made.

As I and Vesko (only!) discussed - it is great to follow code policies, and they are saving time. A lot of time. I agree.
I really like to have so strict policies at work so I can find for example the ObjectDataSource of some dropdown, without knowing its name. For example i will type "objDsSomething" or "odsSomething" or "ODSSomething". It really saves time.

I don't really agree with Vesko's opinion that only in the begining you are violating the code policies. I think even developers who worked on the same project for year will violate its policies (not so often offcourse).

The problem is that we are all human beings and we all make mistakes. I decided to do something to help myself get rid of at least the boring code policies - such
as naming conventions.
Here is what I have so far (I started this thing few days ago and I am working on it for about an hour daily after I was all day at work so it may not look very promising but I think it has potential):



When you click on "Validate Current Document" the document which is currently open will be validated against predefined naming conventions. If you violated something you will have this output:



I have few more problems to solve and will be really glad if someone can point me the direction:

1. I need to find a way to add this menu to the context menu for the document and also I would like to add hot key so you can for example validate the document by pression "CTRL + V + D" or something else (this is low priority).
2. I would also like to be able to check the code itself for inadequate assignments, method calls and so on. The CodeModel approach I think, will not allow me to do so.
3. I would like to change those standard icons with custom ;) (low priority).

Currently this thing can fly only for naming conventions.

Jul 13, 2008

Code policies?

I was thinking the other day about how much efforts does it take to strictly follow your company code policies.
They are saving time for sure, but they are also wasting time.

First of all the developer needs to think about the policies all the time. This districts him/her from the real problems.
Second - after the task is completed the developer again needs to check if his / her code follows the code policies.
Third - if there is a code review - the code reviewer will also need to check if there isn't a problem with those code policies, class by class, member by member.

Some of the rules are very very foundamental as for example not to reference the DataAccess Layer from the User Interface Layer.
Other are company level rules - such as
naming conventions, using some classes on some places and not using some classes on some places. Also - using your project util classes instead implementing the same functionality in your class.

While some of the things aren't very easy to note in a code, other are obvious. And while some of the things aren't very easy to automate via AddIn or external program, other can be easilly automated.

In my opinion the developer should be focussed develop some more useful functionality, instead thinking about which rule will he / she broke.
Please note that by writing the above sentence I am not saying - "Drop the code policies!", but "Automate the code policies!". If I had some tool to check if I violate a rule while writing code, I will rewrite my code in order to satisfy this rule. But after I don't have I need to think about those rules while developing, which districts me from what I need to achieve.

I would really appreciate if you drop a comment on the following question(s):

"Does the code policy bother you? Does it take from your time? Does it districts you?"

Thanks in advance!