Valhalla Legends Forums Archive | .NET Platform | Code Reusability - Class Dependencies

AuthorMessageTime
NicoQwertyu
I'm trying to teach myself to follow best practice/coding standards/write reusable code. I'd like to write a simple text file reader/writer to re-teach myself how to code. Two methods of the class will output the entire file, and one function will output the "next" line in the file. My question concerns the first method: what is the most efficient/flexible/reusable format to output (string array, arraylist, collection, queue, stringbuilder array)?

Edit: To explain the title... If I return a collection, I would need to always include System.Collections, so any future app that uses this class will be dependant on System.Collections as well. Good? Bad? Doesn't matter?
March 19, 2008, 9:49 PM
laurion
[quote author=NicoQwertyu link=topic=17398.msg177136#msg177136 date=1205963348]
Edit: To explain the title... If I return a collection, I would need to always include System.Collections, so any future app that uses this class will be dependant on System.Collections as well. Good? Bad? Doesn't matter?
[/quote]
Well it's a part of basic .NET framework; it doesn't require any additional dependencies, so I don't see why it would be a bad thing to use it. I'm not too familiar with .NET, though, so wait for someone else to throw in their 2 cents before making a decision.
March 19, 2008, 10:58 PM
NicoQwertyu
[quote author=Tazo link=topic=17398.msg177141#msg177141 date=1205967518]
[quote author=NicoQwertyu link=topic=17398.msg177136#msg177136 date=1205963348]
Edit: To explain the title... If I return a collection, I would need to always include System.Collections, so any future app that uses this class will be dependant on System.Collections as well. Good? Bad? Doesn't matter?
[/quote]
Well it's a part of basic .NET framework; it doesn't require any additional dependencies, so I don't see why it would be a bad thing to use it. I'm not too familiar with .NET, though, so wait for someone else to throw in their 2 cents before making a decision.
[/quote]

I'm not too familiar with .NET either, which is where the confusion is coming from. I'm just trying to figure out the best way to do this so that it's both easily reusable and efficient.
March 19, 2008, 11:31 PM
St0rm.iD
Most efficient thing to do would be to pass it an output stream to write the data to, I would think.
March 21, 2008, 4:08 AM
Myndfyr
[quote author=Banana fanna fo fanna link=topic=17398.msg177149#msg177149 date=1206072483]
Most efficient thing to do would be to pass it an output stream to write the data to, I would think.
[/quote]
I think it really depends what he means by "output."  If he means "return a variable," then that's one thing.  If he means "write to a file," that means something else.

Either way, there are already methods in the .NET Framework for doing this.  File.ReadAllText()/File.WriteAllText(), and StreamReader.ReadLine()/StreamWriter.WriteLine().
March 21, 2008, 5:07 PM
NicoQwertyu
[quote]I think it really depends what he means by "output."  If he means "return a variable," then that's one thing.  If he means "write to a file," that means something else.[/quote]
By "output" I ment return a variable, which is why I said this:
[quote]... (string array, arraylist, collection, queue, stringbuilder array)[/quote]


[quote]Either way, there are already methods in the .NET Framework for doing this.  File.ReadAllText()/File.WriteAllText(), and StreamReader.ReadLine()/StreamWriter.WriteLine().[/quote]
I'm aware of this. I've already stated that this is a learning excercise for me.


[quote][W]hat is the most efficient/flexible/reusable format to output (string array, arraylist, collection, queue, stringbuilder array)?[/quote]
March 21, 2008, 10:54 PM
Myndfyr
Honestly I don't think your question is a valid one.  You're thinking of "efficiency" in what could be arguably called the wrong sense. 

By convention, the correct return value is string[] for the one that returns many lines, and just string for the one that returns a single line.  ArrayList, Collection, Queue, and List<T> are all meaningless data structures that don't add anything useful to your code.  StringBuilder is probably inappropriate as well, because you want to make it clear that the result is immutable; since a StringBuilder is a mutable type, it doesn't buy you anything.

I recommend taking a look at this Wikipedia article on cohesion -- it'll explain what I mean about how you're thinking about this problem in the wrong way.
March 21, 2008, 11:08 PM
NicoQwertyu
[quote]By convention, the correct return value is string[] for the one that returns many lines, and just string for the one that returns a single line.[/quote]
That pretty much answered my question. I understand that this isn't the most useful class I'm trying to write, because I'm reinventing the wheel, but it was a way for me to ease into a new language with something I'm already comfortable with (string/file manipulation). And switching from a structured approach to an object oriented one is something that is giving me trouble, despite all the articles I try to read. It just seems that everything I'm doing in .NET I could have easily done in VB6/C. The logic hasn't seem to of changed, though the syntax has, and I'm still using classes to modulate my code just as I would in any other language.

Really, the best way to explain my mental block is something I read Grok type in a recent post. I'm trying to put a round VB6 post into a square VB.NET hole. It works, but I don't seem to be understanding the point.

[quote]ArrayList, Collection, Queue, and List<T> are all meaningless data structures that don't add anything useful to your code.[/quote]
For my own personal uses of the code, I wanted the data returned already split for me and put into a nice little array that I could manipulate and use easily. Ease of use has always been the purpose of encapsulation for me.

At first it seemed like a simply task. I'll just return a string array. That's what I would have done in VB6 and C++. However, this is .NET, and there are so many built-in features I'm not familiar with (arraylist, collection, queue, list), and I wanted to know if it was a better choice to use one of those instead.

By "better choice," I mean from a reusability perspective. Of course I can return a string array and put it into a collect myself. Of course I can just return a collection, and not need to do any extra work. But maybe I won't want it returned as a collection in another project. Maybe I should use a stringbuilder array, since most of the time I'm going to want to manipulate the data I've returned. These are the problems I presented myself with that led me to these forums, so see if anyone knew of a standard or "best" way to do it.

Forget for a moment that this has anything to do with manipulating text files. This is something I'm going to have to deal with regardless of what I'm writing. Do I return a normal array (integer array, string array, it doesn't matter), or do I use one of these built-in, unfamiliar classes that come with the .NET framework?

If the answer is one of the former simplistic arrays, what is the purpose of the .NET framework?

[quote]StringBuilder is probably inappropriate as well, because you want to make it clear that the result is immutable; since a StringBuilder is a mutable type, it doesn't buy you anything.[/quote]
Almost any time I request information from a text file, I'm going to want to do some kind of string manipulation on it. I've read that StringBuilder is more efficient, because it doesn't need to reallocate memory every time a change is made, which is why I brought up StringBuilder.

[quote]I recommend taking a look at this Wikipedia article on cohesion -- it'll explain what I mean about how you're thinking about this problem in the wrong way.[/quote]

Cohesion is decreased if:
The responsibilities (methods) of a class have little in common.
Methods carry out many varied activities, often using coarsely-grained or unrelated sets of data.

Unless I misunderstand the point of the article, which is entirely possible, my class is cohesive. Every method in the class is related to text file manipulation, and every method has its own single purpose for being.




And on a side note, I want to thank you for sticking with me. I'm not very good with putting my thoughts into words, so sometimes it's hard to understand what exactly I'm asking.
March 22, 2008, 2:37 AM
Myndfyr
[quote author=NicoQwertyu link=topic=17398.msg177162#msg177162 date=1206153434]
Unless I misunderstand the point of the article, which is entirely possible, my class is cohesive. Every method in the class is related to text file manipulation, and every method has its own single purpose for being. [/quote]
That's correct, except you also said this:

[quote author=NicoQwertyu link=topic=17398.msg177162#msg177162 date=1206153434]
Forget for a moment that this has anything to do with manipulating text files. This is something I'm going to have to deal with regardless of what I'm writing.[/quote]

The idea is that you shouldn't really try to detach the return value from the data you're manipulating.

I use Visual Studio Team Suite, which has a bunch of extra items.  One of the design rules says that when I have methods (not necessarily properties) I should consider using a Collection rather than an array.  There are times when this is appropriate and times where it's not.

What I meant about data structures being useless: structures like an ArrayList, a Queue, a Stack, and the like are useful for internal implementation details.  I don't believe I've ever run across an instance where it is useful to expose these kinds of data structures to the world outside of a class, primarily because when you do, you lose control over the class.  Consider the following class:

[code]
public class ChatQueue {
  private Queue<string> _waitingMessages = new Queue<string>();

  public Queue<string> WaitingMessages {
    get { return _waitingMessages; }
  }
}
[/code]

This class violates the principle of encapsulation because it doesn't protect your internal implementation details.  You're not losing a reference to your Queue -- it protects it in that way -- but you have no control over what goes into the queue.  Rather, what you do is a sort of mock inheritence, where you don't actually inherit from the object that you're extending, but rather use a principle called containment.  Redesigned, the above class might look like this:

[code]
public class ChatQueue {
  private Queue<string> _waitingMessages = new Queue<string>();

  public string Dequeue()
  {
    return _waitingMessages.Dequeue();
  }

  public void Enqueue(string message)
  {
    _waitingMessages.Enqueue(message);
  }
}
[/code]

This kind of approach allows you to control what gets into your queue -- you can do this:
[code]
public void Enqueue(string message)
{
  if (message == null) throw new ArgumentNullException("message");
  if (message.Length == 0) throw new ArgumentOutOfRangeException("message", message, "Message cannot be a zero-length string.");
  _waitingMessages.Enqueue(message);
}
[/code]

[quote author=NicoQwertyu link=topic=17398.msg177162#msg177162 date=1206153434]
[quote]StringBuilder is probably inappropriate as well, because you want to make it clear that the result is immutable; since a StringBuilder is a mutable type, it doesn't buy you anything.[/quote]
Almost any time I request information from a text file, I'm going to want to do some kind of string manipulation on it. I've read that StringBuilder is more efficient, because it doesn't need to reallocate memory every time a change is made, which is why I brought up StringBuilder.
[/quote]
The catch here is the way the data is used.  The data that was actually in the file is immutable, unless you're going to actually edit the file (which opens up an entirely new can of worms, and in which case the StringBuilder is not appropriate anyway).  StringBuilder is in fact better than working with strings, particularly when dealing with concatenation.

Here are some examples of when StringBuilder is appropriate vs. non-string-builder:
[code]
string MakeSingleLineFromMultiple(string[] lines)
{
    int capacity = 0;
    foreach (string line in lines) capacity += line.Length;
    StringBuilder sb = new StringBuilder(capacity);
    foreach (string line in lines) sb.Append(line);
}

string[] UppercaseLines(string[] lines)
{
    List<string> resultLines = new List<string>(lines.Length);
    foreach (string line in lines)
        resultLines = line.ToUpper(CultureInfo.CurrentCulture);
    return resultLines.ToArray();
}
[/code]

For other notes: as I've shown several times, I use generics.  It is almost always preferable to use the collection types defined in System.Collections.Generic rather than System.Collections, because they enforce type safety.  Consider:
[code]
List<string> strings = new List<string>();
strings.Add("Hello,");
strings.Add("world!");
strings.Add(10); // compiler error.

ArrayList strings2 = new ArrayList();
strings2.Add("Hello,");
strings2.Add("world!");
strings2.Add(10); // compiler is ok!
[/code]
Besides not knowing whether each element is REALLY the type you expect, you have to deal with casting.  Unfortunately, generics were not added to the .NET Framework until version 2, and so we have to live with the archaic data structures left over from 1.x.

As for "what is the purpose," well, there are many.  On one hand, it's designed to provide a common API that can be used from multiple programming languages, such as C#, Python (via IronPython), C++, and Visual Basic.  The other is that it's designed to be a rich class library.  The point is that you shouldn't be exposing some of those types of objects -- the #1 principle of object-oriented programming is encapsulation, or the principle of information hiding.  It allows you to manage complexity in a way that makes sense.

I praise Steve McConnell a lot on my blog and at work.  I highly recommend picking up Code Complete, 2nd edition.  I learned more about programming from that book than anything else.  (Well, the first edition - I haven't finished reading the second one yet).

Hope that helps make sense :)
March 22, 2008, 7:49 AM
NicoQwertyu
Thank you very much. Your entire post was so helpful, I really can't even quote pieces of it to comment on. :)

Coming from VB6--self-tought VB6--I've picked up a lot of bad habits along the way. I'm trying to forget everything I've learned and start with a clean slate, with .NET, learning the coding standards and best practices before I even begin. Everything from naming conventions, to code readbility, to... well just everything. And typing ".NET standards best practices" into google yeilds few quality results.
March 22, 2008, 8:26 AM

Search