Showing posts with label Coding Practices. Show all posts
Showing posts with label Coding Practices. Show all posts

Saturday, August 06, 2011

Checking for integer ranges - C# to C

I had tough time explaining what should be the correct mechanism for checking integer range for a developer coming from C# to C.

Intention is to check a value within the range of 0 to 4. Anything less than 0 and above four is invalid.

Expression written is

((http_method > -1) && (http_method < 5))

I wrote a review comment to change expression as

(Method >= 0) && (Method <= 4))

Comment is not accepted and led to a discussion, rather argument.

I said I have a problem with first part of expression

(http_method > -1)

The '-1' could be tricky depending upon type of http_method.

And in this case http_method is unsigned int and returned false even for correct range.

It took a while to explain the expression is invalid.

Though C# has an 'uint' type, an 'int' would suffice the need in most of the scenarios.

So using correct data type is one part of it. Also when it comes to checking ranges it is always recommended to check inclusive ranges rather than outer ranges. One simple reason for that is test cases. Test cases with inclusive range are considered as positive test cases and boundary range are considered as negative test cases.

Technically there is no binding to follow inclusive range check. But it is a good convention to follow.

Wednesday, July 25, 2007

Collections Best Practices

This is referenced form an article in August issue of CLR Inside Out. Link

The basic purpose of collections is to tie certain objects together as a group because they have some logical connection to each other.

General criteria to select a particular collection object goes like this

  1. Are you going to be adding all the elements at once?
  2. Are you going to be dynamically adding and removing elements?
  3. Do you only need to iterate over the entire collection, or do you also need to locate and use specific elements?
  4. Are you exposing your collection through a public API?
  5. What are the performance characteristics and requirements of your application?


If you’re using the .NET Framework 2.0 or later, using the old non-generic collections is strongly discouraged. Following table shows the mapping between

.NET 1.0 Collection classes and .NET 2.0 Generic collection classes

Non-GenericGeneric Replacement
ArrayListList<T>
BitArrayNo replacement exists
CollectionBaseCollection<T>
ComparerComparer<T>
CompatibleComparerComparer<T>
DictionaryBaseKeyedCollection<TKey,TItem>
HashtableDictionary<TKey,TValue>
ICollectionICollection<T>
IDictionaryIDictionary<TKey,TValue>
IListIList<T>
QueueQueue<T>
ReadOnlyCollectionBaseReadOnlyCollection<T>
SortedListSortedList<TKey, TValue>
StackStack<T>

Pros and Cons of each type:

Dictionary
When you want additions(fast), removals(fast), and lookups(average) to be very quick, and when you are not concerned about the order of the items in the collections, your first inclination should be to use a System.Collections.Generic.Dictionary<TKey, TValue>.

List
If your usage pattern requires few deletions and mostly additions, and if it is important for you to keep the collection in order, you may want to choose a List<T>. If you do not care about sorting or inserting items in the middle, nor do you care about looking up individual items in the list but want to iterate over complete list.

Queue
to implement a first-in-first-out (FIFO) order

Stack
to implement a last-in-first-out (LIFO) order

LinkedList
when you need to maintain order yet still achieve fast inserts. But increases increased activity by the garbage collector. While the actual act of inserting an item into a LinkedList<T> is much faster than doing so into a List<T>, finding the particular location at which you want to insert a new value still requires traversing the list to find the correct location.

SortedDictionary
uses a balanced tree implementation as the underlying data store; this provides relatively fast lookups and maintains items in a sorted order, but insertions will most likely be slower.

SortedList
which uses two separate arrays to maintain the keys and the values separately and to maintain them both in order

Extending Collections
The System.Collections.ObjectModel.Collection<T> class implements all of the standard collection interfaces, and your custom collection type can simply derive from Collection<Double> in order to provide the additional overload methods. You could also use extension methods in C# 3.0 to achieve the same.

Gist on Collection Interfaces

IEnumerable
methods:
GetEnumerator - returns IEnumerator

IEnumerator
methods:
Reset
Current
MoveNext

ICollection - extends IEnumerable
methods:
Add
Remove
Clear
Contains
CopyTo - copies items to an array
properties:
Count - Readonly count
IsReadOnly - items cannot be removed or added
(mutable items can be modified even if the collection is read-only).

IList - extends ICollection
methods:
IndexOf
Insert
RemoveAt
indexer: allows to get and set any item in the collection, just as you can when using arrays


IDictionary - extends ICollection
methods:
Add - overload that associates a key with the item that is added
ContainsKey - method will check for the existence of a particular key
Properties:
Keys - returns an ICollection of all the keys
Values - returns an ICollection of all the values
remove - overload based on the key instead of the value
indexer: using the key.

Wednesday, July 18, 2007

Add-ins Plug-ins Extensions

I cant find any reference which explains how Add-ins, Plug-ins and Extensions differ from one other. I just cant accept them to be synonyms.

Here is an account of how I interpret each one. Please correct me or point me to appropriate source.

Add-ins
I guess add-ins are those modules which bring-in a specific fuctionality, at runtime, for such requirements which are unknown at build time. That mean Application is unaware about source of Add-ins. Normally they are chosen from list to add. eg.Excel Ad-Ins

Plug-ins
I guess Plug-ins are those modules for which an adapter is built inside the application at build time. Thus a trust relation ship exists between application and Plug-In at Runtime.

Extensions
I guess Extensions are those modules which are added to bring in additional functionality by installation and probably with a restart of main application. Extensions operate in isolation with build time functionality.

Saturday, September 03, 2005

Nice Coding practice for byte packing

I am trying to write a code to using SOCK_RAW using PACKET protocol family PF_PACKET.
My intention to find out healthiness of Target with minimum overhead. Instead of trying to call connect i want to use ICMP protocols like ping. While doing that i thought why cant I do event ARP. Then started looking for some sample code for ARP.

I found Blacky Room at fdin. He got simple codes for lower level Ethernet Protocols. Ofcourse the site is in Japanese language. But can access code samples.

One good thing i liked at these code samples is the way packing of bytes is done before calling send. In the following function , buffer is a character array. And eth and arp are just pointers.
Iinitially these pointers are just addressed to respective positions. Then as members are filled buffer is ready.

Normally i do other way around. First i update structures and then assign to each byte of buffer like buf[0] = arp->arp_hrd.

But this method essentially eliminates second copy and more secure.


int send_arprequest(int sock, struct dev *dev, struct addr *src, struct addr *dst)
{
struct sockaddr_ll sll;
struct ether_header *eth;
struct ether_arp *arp;
char buf[sizeof(struct ether_header) + sizeof(struct ether_arp)];

memset(&sll, 0, sizeof(sll));
sll.sll_family = PF_PACKET;
sll.sll_ifindex = dev->index;
sll.sll_halen = ETH_ALEN;
memcpy(&sll.sll_addr, dst->mac, ETH_ALEN);

memset(buf, 0, sizeof(buf));
eth = (struct ether_header *)buf;
arp = (struct ether_arp *)((char *)eth + sizeof(struct ether_header));

/* arp header */
arp->arp_hrd = htons(ARPHRD_ETHER);
arp->arp_pro = htons(ETH_P_IP);
arp->arp_hln = ETH_ALEN;
arp->arp_pln = IP_LEN;
arp->arp_op = htons(ARPOP_REQUEST);
memcpy(arp->arp_sha, src->mac, ETH_ALEN);
memcpy(arp->arp_spa, &(src->ip), IP_LEN);
memset(arp->arp_tha, 0, ETH_ALEN);
memcpy(arp->arp_tpa, &(dst->ip), IP_LEN);

/* ether_header */
memcpy(eth->ether_shost, src->mac, ETH_ALEN);
memcpy(eth->ether_dhost, dst->mac, ETH_ALEN);
eth->ether_type = htons(ETH_P_ARP);

/* send to arp request packet */
return sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *)&sll, sizeof(sll));
}