Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 31st, 2008, 4:12 PM   #1
archaios7
Newbie
 
Join Date: Jul 2008
Location: Seattle, WA
Posts: 6
Rep Power: 0 archaios7 is on a distinguished road
Values being passed by reference?

So I'm trying to use an object ("InfoStorer") to store a dictionary ("InfoHolder") and some functions related to entering & retrieving the information. Everything seems fine when I store the information, yet when I try to retrieve it nothing happens.

I'm pretty sure it's either my ClearTextBoxes method nulling all the values in my TextBoxes and thus nulling the values in my dictionary too. So my question is is there a better way to clear the text boxes? Will I need to deep clone my List<TextBox>, which from my reading online seems overly difficult? Or am I completely off base and the problem is somewhere else?

By the way, I'm just getting a good grasp on C#, so any other recommendations for my code would be welcome. Thanks for any and all help in advance

namespace ClaimaintInfo
{
    partial class Form1
    {
        ClaimaintInfoStorer InfoStorer = new ClaimaintInfoStorer();

        public List<TextBox> packer()  // Pulls the strings from the "TextBox"es to store - Also Empties "TextBox"es.
        {
            List<TextBox> info = new List<TextBox>();
            
            info.Add(NameTextBox);
            info.Add(CellTextBox);
            info.Add(PhoneTextBox);
            info.Add(AddressTextBox);
            info.Add(POBoxTextBox);
            info.Add(CityTextBox);
            info.Add(StateTextBox);
            info.Add(ZipTextBox);
            info.Add(EmailTextBox);

            // clearTextBoxes(info);

            return info;
        }

        internal static void clearTextBoxes(List<TextBox> info)
        {
            if (info[0].Text != null) // Clears "TextBox"es .Text - Checks to see if they need to be cleared.
            {
                int x = 0; // For iterating through info's "TextBox"es

                do
                { // Makes "TextBox"es .Text null.
                    info[x].Text = null;
                    x++;
                } while (x < info.Count);
            }
        }
    }

    public class ClaimaintInfoStorer // Class to handle info saving/loading of info - TEMP until I start working with DBs
    {
        /* Object to store Claimaint Info in. */
        internal Dictionary<string, List<TextBox>> infoHolder = new Dictionary<string, List<TextBox>>();

        public void HoldInfo(List<TextBox> tempInfoHolder) // Store info by adding to infoHolder
        {
            if (infoHolder.ContainsKey(tempInfoHolder[0].Text))
            {

            }
            else
            {
                infoHolder.Add(tempInfoHolder[0].Text, tempInfoHolder); // tempInfoHolder as a value for my dict needs to be a list of strings
            }
        }

        public List<TextBox> GetInfo(string name) // Method to retrieve info from InfoHolder
        {
            List<TextBox> tempHolder = new List<TextBox>();
            foreach (KeyValuePair<string, List<TextBox>> pair in infoHolder)
            {
                if (pair.Key == name)
                    tempHolder = pair.Value;
            }
            return tempHolder;
        }
    }
}

namespace ClaimaintInfo
{
    partial class Form1
    {
        private void MouseClickSaveButton(object sender, EventArgs e)
        {

        }

        private void MouseClickAddClaimaint(object sender, EventArgs e)
        {
            InfoStorer.HoldInfo(packer());
            ClaimatsListBox.Items.Add(packer()[0].Text);
            /* clearTextBoxes(tempDeleter); */
        }

        private void DoubleClickLoadClaimaint(object sender, EventArgs e)
        {
            string name = ClaimatsListBox.SelectedItem.ToString();
            List<TextBox> tempPacker = packer();
            List<TextBox> tempHolder = InfoStorer.GetInfo(name);
            for (int i = 0; i < tempHolder.Count; i++)  // Unpacks info from my List<TextBox> returned from InfoStorer.GetInfo(name) into "TextBox"es
                tempPacker[i].Text = tempHolder[i].Text;
        }
    }
}
archaios7 is offline   Reply With Quote
Old Aug 1st, 2008, 6:53 AM   #2
lectricpharaoh
SEXY SHOELESS GOD OF WAR!
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Wet west coast of Canada
Posts: 1,197
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: Values being passed by reference?

Note: you might want to wander over to 'Community Introductions' and make an intro thread.

Your problem is that you're handing off references to the textboxes, rather than the strings. Thus, when you clear the textboxes, you're left holding references to textboxes without any data. Another, larger issue is that this closely couples your logic (ie, your ClaimantInfo class- yes, you spelled it wrong :p) with your user interface. Try changing the interface, such as by making it into a console app, or web app, and you'll suddenly have big issues, and you'll need to rewrite the class. Now, while you could instead store <textboxname>.Text in your list (making it a List<string> rather than List<TextBox>), I think your best bet is to rewrite this, and use an approach like so:

Have your ClaimantInfo class contain the various fields, such as name, address, phone number, etc. These will all be private data members of the appropriate type (many will be string, but some, like zip code, can be int); just use your judgment to decide on the type.

After that, make some public properties that your other classes (such as the main form) can use. Here's an example of the ClaimantInfo class:
C# Syntax (Toggle Plain Text)
  1. namespace ClaimantInfoTest
  2. {
  3. class ClaimantInfo
  4. {
  5. private string _name;
  6. private string _address;
  7. private string _email;
  8. private string _phone;
  9. private int _zipCode;
  10.  
  11. public ClaimantInfo(string name, string address, string phone, string email, int zipCode)
  12. {
  13. _name = name;
  14. _address = address;
  15. _phone = phone;
  16. _email = ((email != null) && (email != "")) ? email : "<no email provided>";
  17. _zipCode = zipCode;
  18. }
  19.  
  20. public string Name
  21. {
  22. get
  23. {
  24. return _name;
  25. }
  26. set
  27. {
  28. _name = value;
  29. }
  30. }
  31.  
  32. public string Address
  33. {
  34. get
  35. {
  36. return _address;
  37. }
  38. set
  39. {
  40. _address = value;
  41. }
  42. }
  43.  
  44. public string Phone
  45. {
  46. get
  47. {
  48. return _phone;
  49. }
  50. set
  51. {
  52. _phone = value;
  53. }
  54. }
  55.  
  56. public string Email
  57. {
  58. get
  59. {
  60. return _email;
  61. }
  62. set
  63. {
  64. _email = value;
  65. }
  66. }
  67.  
  68. public int ZipCode
  69. {
  70. get
  71. {
  72. return _zipCode;
  73. }
  74. set
  75. {
  76. _zipCode = value;
  77. }
  78. }
  79. }
  80. }
You'll probably want more fields (and you should split the name up into first and last names), but you get the idea. Next, you can make a simple test form. I made one with several textboxes named txtName, txtAddress, and so on. There is also a multiline textbox called txtDisplay (this is used to display the list). Lastly, there are labels for each textbox (so the user knows what the field is for), and two buttons called btnAdd and btnDisplay. The form looks like this:



The code (excluding the designer-generated stuff, which is huge and pointless to post, since you don't have to actually write it) looks like so:
C# Syntax (Toggle Plain Text)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8.  
  9. namespace ClaimantInfoTest
  10. {
  11. public partial class ClaimantTestUI : Form
  12. {
  13. private List<ClaimantInfo> ciList = new List<ClaimantInfo>();
  14.  
  15. public ClaimantTestUI()
  16. {
  17. InitializeComponent();
  18. }
  19.  
  20. private void btnAdd_Click(object sender, EventArgs e)
  21. {
  22. // make sure textboxes have stuff in them, and that the zip code one holds an
  23. // integer. only then will we make a new ClaimaintInfo object and add it to
  24. // the list. email may be blank, as it's not mandatory
  25. int zip;
  26. if ((txtName.Text != "") && (txtAddress.Text != "") && (txtPhone.Text != "") && (int.TryParse(txtZipCode.Text, out zip)))
  27. ciList.Add(new ClaimantInfo(txtName.Text, txtAddress.Text, txtPhone.Text, txtEmail.Text, zip));
  28. else
  29. MessageBox.Show("You must fill in all fields except for 'email'.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
  30. }
  31.  
  32. private void btnDisplay_Click(object sender, EventArgs e)
  33. {
  34. // temporarily prevent txtDisplay from redrawing itself as we add text, as
  35. // this can cause a nasty flicker as each claimaint is added
  36. txtDisplay.SuspendLayout();
  37. txtDisplay.Text = "";
  38. foreach (ClaimantInfo ci in ciList)
  39. txtDisplay.AppendText(string.Format("Name: {0,-29}\nAddress: {1,-26}\nPhone Number: {2,-21}\nEmail: {3,-28}\nZip: {4}\n\n", ci.Name, ci.Address, ci.Phone, ci.Email, ci.ZipCode));
  40. // let the control redraw itself as normal
  41. txtDisplay.ResumeLayout();
  42. }
  43. }
  44. }
Excuse the long lines; I'm on a widescreen display and I hate wrapping them, as it makes reformatting things a pain in the ass. If you want to cut-and-paste it, use the 'toggle plain text' link in the [code] block. This also has the benefit of removing the line numbers, which will make your compiler choke if you leave them in.

Anyways, I'll explain a few things in case you're confused by the code. First, in the ClaimantInfo class, note how I have private member variables (I like to prefix them with an underscore, to make it clear, but this is just a naming convention of mine). I also have properties, which are basically methods (in fact, they actually compile down to methods with names like get_Name() and such). However, you access them as though they were public fields (ie, public data members). If you look at various controls, they use properties extensively (the Text property, the ForeColor property, etc). Basically, when you're in the designer, all those things you see listed in the Properties window are- you guessed it- properties.

Now, you might be wondering why we prefer properties to actually exposing a field (ie, making the field itself public). First is that you should never make your class state data accessible unless you need to. Make it protected if you intend the class to be inherited, and want subclasses to have access. Otherwise, make it private. If you need class A to have access to some of class B's members, but don't want it accessible to everyone, use internal or protected internal access. This way, other code can't muck about with your class's guts, and possibly assign invalid values and otherwise compromise your class's integrity. Obviously, there are exceptions; if you have constants or read-only fields (fields marked with the readonly keyword can only be initialized in the class's constructor), then exposing these directly is just as safe as using a property (though it might violate your naming conventions).

A second, and more important, reason to use properties is that since it's basically a method call, we can do much more complex operations than simply setting or returning a value. For the get property, you can calculate values on the fly and return those. For the set property, you can do validation. Imagine if we used some kind of regular expression validation (look up 'regular expressions' if you don't know what they are) to ensure that the email address field actually was in the correct format (ie username@domain). Another benefit is you can update other fields and call other code. For example, when you change the Text property of txtSomething, it needs to redraw itself with the new text. If Text was a public field instead of a property, you'd need to follow every change with a call such as txtSomething.Update().

Anyways, that's why we use properties. As to how, you just have the property type and name, followed by braces, and inside those braces, you have either a get or set accessor, or both (a property that only has one is either read-only or write-only). Both accessors will have another set of braces, as you can see in the ClaimantInfo class I posted. For a get accessor, it mustreturn something matching the property type (ie, the exact type, or for properties whose type is a class or interface, a compatible type such as the declared class type or one derived from it, or a class or struct implementing the declared interface). If this is Greek to you, just remember it needs to return the type you declared it as (a string property's get must return a string, and so on). For a set accessor, it doesn't need to do anything- the code will compile fine- but obviously, if you didn't want to write the code, you'd just make it a read-only property. If you do write code in the set accessor, the name value is a placeholder for what was passed in to the property. Remember I said properties are basically methods? Well, a set accessor will basically compile to the method void set_xxx(<datatype> value). Thus, if I say txtSomething.Text = "hello world", then inside the property's set accessor, value will be of type string (this is because that's the type of the property) and hold "hello world" (because that's what was passed in).

Anyways, that's it for the ClaimantInfo class. As far as the form code goes, it's pretty straightforward. I'm not sure if you've used string.Format() before, but if not, check it out on MSDN. It's a very handy method. Another method I've used is the int.TryParse() method. This takes two parameters (at least, the version I used here does). The first is a string to try to parse, and the second is a reference to an int. Note the use of the out keyword rather than ref. Both are the same, except out tells the compiler that it's okay if the variable hasn't been initialized, so it doesn't complain about 'use of unassigned local variable', and puke on your shoes. The method returns a bool, with true indicating it was successfully parsed. If you're interested, the other basic types (long, float, etc) have TryParse() methods of their own that work in a similar manner. I much prefer using this method to Parse(), as the latter will throw an exception if the data can't be parsed. I'd much rather have a true/false return value that simply tells me whether or not it worked, and if not, I can pop up a message bitching at the user.

Anyways, like many of my posts, this has been pretty long-winded (your word of the day: loquacious). Let me know if you have any questions about the code.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 1st, 2008, 8:22 AM   #3
xavier
Professional Programmer
 
xavier's Avatar
 
Join Date: Oct 2004
Location: .ro
Posts: 406
Rep Power: 5 xavier is on a distinguished road
Send a message via Yahoo to xavier
Re: Values being passed by reference?

WOW lectricpharaoh - you have way too much free time
__________________
Don't take life too seriously, it's not permanent !
xavier is offline   Reply With Quote
Old Aug 1st, 2008, 10:00 AM   #4
JD-Salinger
Unknown
 
JD-Salinger's Avatar
 
Join Date: Apr 2008
Location: unknown
Posts: 87
Rep Power: 1 JD-Salinger is on a distinguished road
Re: Values being passed by reference?

lectricpharaoh is one of my favorite... if there's goin to be the most dilligent PFO member its gotta be lectricpharaoh
__________________
-------------------------------------------------------------------------
I thought what I'd Do was, I'd pretend to be one of those deaf mutes
------------------------------------------------------------------------
JD-Salinger is offline   Reply With Quote
Old Aug 1st, 2008, 1:08 PM   #5
archaios7
Newbie
 
Join Date: Jul 2008
Location: Seattle, WA
Posts: 6
Rep Power: 0 archaios7 is on a distinguished road
Re: Values being passed by reference?

Wow, that was way more helpful than I could've expected.

I understand about the public/private/internal stuff and the get/set stuff, but your explanations gave me a few more insights into how they work. I guess I shouldn't cut corners when I'm learning and make most things public eh? lol

I'll play with your code some and post again if I have any specific questions. Thanks again.
archaios7 is offline   Reply With Quote
Old Aug 1st, 2008, 7:45 PM   #6
lectricpharaoh
SEXY SHOELESS GOD OF WAR!
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Wet west coast of Canada
Posts: 1,197
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: Values being passed by reference?

Quote:
Originally Posted by JD-Salinger
lectricpharaoh is one of my favorite... if there's goin to be the most dilligent PFO member its gotta be lectricpharaoh
Naw, xavier's right- I've got too much time on my hands.
Quote:
Originally Posted by archaios7
Wow, that was way more helpful than I could've expected.
Thanks.
Quote:
Originally Posted by archaios7
I understand about the public/private/internal stuff and the get/set stuff, but your explanations gave me a few more insights into how they work. I guess I shouldn't cut corners when I'm learning and make most things public eh? lol
Heh, nope. Make them private (this is the default if you don't specify, but I like to explicitly mark things as such, just for clarity). If you need to loosen them up later, you always can. However, properties are generally the way to go. If you're concerned about the property method call adding overhead to your program, don't be. First, if you're doing any validation, calculations, etc in the accessor, it couldn't be a simple field access anyways. Second, it's not likely to be a performance bottleneck in your program (especially for a UI-driven program, where the slowest component is the lump of meat across the keyboard). Third, if your accessors are simply getting or setting a private field, a smart compiler will likely optimize this to a straight access (and the C# compiler is pretty smart).
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 12th, 2008, 1:58 PM   #7
archaios7
Newbie
 
Join Date: Jul 2008
Location: Seattle, WA
Posts: 6
Rep Power: 0 archaios7 is on a distinguished road
Re: Values being passed by reference?

Well I played around with it, have a few more questions/issues now though. First off, I don't seem to be using the get/set properties; are they just there for future expansion? If I continue to not use them should I just delete them?

Secondly, I don't think I fully understand how to seperate my logic from my UI code. I can't access my TextBoxes outside of the partial ClaimantUI class, should I change my TextBox objects to "internal" instead of "private" so I can work with them outside of my events? Or did I misunderstand and it's best keep that with the UI, so if I ever needed to run this on a console I wouldn't have extra code floating around that does nothing because I'd never use text boxes in a console?

Also, I tried having the zip as an int (in the long run I plan to do that) but it gets angry at me if I don't enter a zip code and tries to parse and empty string to an int. So that brings me to my other issue; What if I don't have all the information but want to save the first/last name, phone, and email? Do I need another method overloader for each combination of information, or is there an easier more elegant way of doing that? Maybe I'm just making it too complex.

The basic purpose for this code is store contact info for various insurance claimants; the in house program we use at work currently has no way of storing that information except in a section used for making notes on phone calls and it is a royal pain to hunt through my notes to find someone's address. Some claims can have multiple claimants and when I am first notified of a claim I don't always have all their contact info. Sometimes it's just a name and address, other times it's a name and phone number, sometimes it's just a name. Also my boss should be setting me up with a database soon that I can play around with, so I can just use that store my info instead of a dictionary<> soon.

So here's a screet shot of my UI, just a note I do plan on adding a a larger textbox for easy copying/pasting of the info soon -


And my code -
    class ClaimantInfo
    {
        private string _firstName;
        private string _lastName;
        private string _address;
        private string _poBox;
        private string _city;
        private string _state;
        private string _zip; // spits out errors as an int when trying to convert an empty string to an int.
        private string _phone;
        private string _cell;
        private string _email;

        /* get/set properties for above listed private variables */
        public string firstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
        public string lastName
        {
            get { return _lastName; }
            set { _lastName = value; }
        }
        public string address
        {
            get { return _address; }
            set { _address = value; }
        }
        public string poBox
        {
            get { return _poBox; }
            set { _poBox = value; }
        }
        public string city
        {
            get { return _city; }
            set { _city = value; }
        }
        public string state
        {
            get { return _state; }
            set { _state = value; }
        }
        public string zip
        {
            get { return _zip; }
            set { _zip = value; }
        }
        public string phone
        {
            get { return _phone; }
            set { _phone = value; }
        }
        public string cell
        {
            get { return _cell; }
            set { _cell = value; }
        }
        public string email
        {
            get { return _email; }
            set { _email = value; }
        }

        /* Initialize ClaimantInfo and assign base variables */
        public ClaimantInfo(string firstName, string lastName, string address, string poBox,
            string city, string state, string zip, string phone, string cell, string email)
        {
            _firstName = firstName;
            _lastName = lastName;
            _address = address;
            _poBox = poBox;
            _city = city;
            _state = state;
            _zip = zip;
            _phone = phone;
            _cell = cell;
            _email = email;
        }

        public ClaimantInfo(string firstName, string lastName)
        {

            _firstName = firstName;
            _lastName = lastName;
        }
    }
public partial class ClaimantUI : Form
    {
        private Dictionary<string, ClaimantInfo> ciDict = new Dictionary<string, ClaimantInfo>();

        public ClaimantUI()
        {
            InitializeComponent();
        }

        private void Saver()
        {
            if (ciDict.ContainsKey(LastNameTextBox.Text))
                MessageBox.Show("You already have a claimaint with the same last name", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else if ((FirstNameTextBox.Text != "") && (LastNameTextBox.Text != ""))  // Check to see if there is a First & Last Name
                if ((AddressTextBox.Text == ""))  // If there is no address, just save the first/last name.
                {
                    ciDict.Add(LastNameTextBox.Text, new ClaimantInfo(FirstNameTextBox.Text, LastNameTextBox.Text));
                    ClaimantListBox.Items.Add(LastNameTextBox.Text);
                    clearTextBoxes();
                }
                else // If there is an address save all info.
                {
                    ciDict.Add(LastNameTextBox.Text, new ClaimantInfo(FirstNameTextBox.Text, LastNameTextBox.Text, AddressTextBox.Text, POBoxTextBox.Text, CityTextBox.Text, StateTextBox.Text, ZipTextBox.Text, PhoneTextBox.Text, CellTextBox.Text, EmailTextBox.Text));
                    ClaimantListBox.Items.Add(LastNameTextBox.Text);
                    clearTextBoxes();
                }
            else
                MessageBox.Show("You must enter a first and last name.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void clearTextBoxes() // Used to empty textboxes before/after a load/save
        {
            FirstNameTextBox.Text = "";
            LastNameTextBox.Text = "";
            AddressTextBox.Text = "";
            POBoxTextBox.Text = "";
            CityTextBox.Text = "";
            StateTextBox.Text = "";
            ZipTextBox.Text = "";
            PhoneTextBox.Text = "";
            CellTextBox.Text = "";
            EmailTextBox.Text = "";
        }

        private void unpacker(string name) // Takes values saved in ciDict and displays them in the text boxes.
        {
            FirstNameTextBox.Text = ciDict[name].firstName;
            LastNameTextBox.Text = ciDict[name].lastName;
            AddressTextBox.Text = ciDict[name].address;
            POBoxTextBox.Text = ciDict[name].poBox;
            CityTextBox.Text = ciDict[name].city;
            StateTextBox.Text = ciDict[name].state;
            PhoneTextBox.Text = ciDict[name].phone;
            CellTextBox.Text = ciDict[name].cell;
            EmailTextBox.Text = ciDict[name].email;
        }

        private void ClickAddButtonEvent(object sender, EventArgs e) // Checks textboxes to make sure they hold (correct) values, if they do then a new ClaimantInfo object is created and added to the list.
        {
            Saver();
        }

        private void DoubleClickLoadClaimantInfo(object sender, MouseEventArgs e)
        {
            string name = ClaimantListBox.SelectedItem.ToString();

            foreach (KeyValuePair<string, ClaimantInfo> pair in ciDict)
            {
                try
                {
                    if (pair.Key == name)
                    {
                        clearTextBoxes();
                        unpacker(name);
                    }
                    else if (pair.Key != name)
                        continue;
                    else
                        throw new IndexOutOfRangeException();
                }
                catch ( IndexOutOfRangeException )
                {
                    MessageBox.Show("Whoops, that shouldn't have happened", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        private void ClickSaveButtonEvent(object sender, EventArgs e) // Same as add, only closes the window after saving.
        {
            Saver();
            Close();
        }
    }

Sorry for the long winded post, and thanks in advance again for any help you guys can offer.
archaios7 is offline   Reply With Quote
Old Aug 12th, 2008, 3:21 PM   #8
lectricpharaoh
SEXY SHOELESS GOD OF WAR!
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Wet west coast of Canada
Posts: 1,197
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: Values being passed by reference?

Quote:
Originally Posted by archaios7
Well I played around with it, have a few more questions/issues now though. First off, I don't seem to be using the get/set properties; are they just there for future expansion? If I continue to not use them should I just delete them?
The idea is to use them now. Say you have a ClaimantInfo object. You want to find out the person's name? You use the Name property, like string name = ci.Name or some such. When you have a collection of ClaimantInfo objects, you will still be using the properties to get the details of the specific claimant.
Quote:
Originally Posted by archaios7
Secondly, I don't think I fully understand how to seperate my logic from my UI code. I can't access my TextBoxes outside of the partial ClaimantUI class, should I change my TextBox objects to "internal" instead of "private" so I can work with them outside of my events?
You shouldn't be directly accessing the form's controls from outside the form. Let's say you have a class that acts as a container for an arbitrary number of ClaimantInfo objects. Right now, this might be a class that has a List<ClaimantInfo> full of claimants, but later on, it might be a class that makes queries to an underlying database. It really doesn't matter, as long as you have a consistent interface. Basically, you need to consider what you need to do, and it boils down to CRUD (I didn't pick the acronym). It stands for Create, Retrieve, Update, and Delete. These are the four types of functionality, and if you've got them, it doesn't matter how you're storing the data. You can be stuffing it in a database, writing it to a plain file, or whatever. Basically, they work as follows:

Create adds a new record (duh). This will probably include checks for validity of values (the values make sense) as well as making sure certain fields are filled in. For example, it's reasonable to allow a blank email field, but probably not reasonable to allow blank name fields.

Retrieve is your find functionality. You will probably have several methods here, each using different criteria (search by name, search by client ID, etc). Some will return a single record (if it's in the list) or nothing (null, empty object, whatever- it depends on your implementation) if no match is found (searching by ID is an example here, since IDs should be unique). Others will return an arbitrary number of records, such as when searching by name.

Update gives you the ability to edit a record. It's pretty straightforward; as long as a record exists, you can modify it, and write it back. Note that certain fields on a record might be read-only; it should be possible to change the name or address associated with a claimant, but changing the ID value should probably not be allowed.

Delete is about the easiest there is. If it's there, remove it; otherwise, do nothing. It's a good idea to have some kind of return value that indicates success or failure, but this goes for all the CRUD functions.
Quote:
Originally Posted by archaios7
Or did I misunderstand and it's best keep that with the UI, so if I ever needed to run this on a console I wouldn't have extra code floating around that does nothing because I'd never use text boxes in a console?
Keep it with the UI. If you have a container class, as described above, you can call it from your UI, whether it's a GUI or a console UI.

In fact, you may want an additional 'layer' here; this is the so-called 'three tier' approach. The three tiers, or layers, are the UI layer, which has your user interface, the business logic layer, and the data access layer. The data access one is responsible for maintaining the records on some form of persistent storage (disk files, database, whatever). The business logic layer sits between the DA and UI layers, and enforces certain rules. Thus, your UI code will call the BLL, rather than directly calling the methods in the DA tier. For example, you might not want to allow deletion of claimants with outstanding claims, so the business logic layer could enforce this.

Using the three-tier approach will initially complicate the design and implementation, but it allows for a clearer separation of different kinds of functionality, which can make things easier in the long run. Let's say your boss comes up with some new policy he wants you to implement in the code; putting it into the business logic layer will allow you to leave the other two layers unchanged. Likewise, let's say you've originally got the DA tier implemented as flat file storage, and the boss says he wants it stored in a database instead. You can change this tier, but the other tiers don't care (or even know) about the changes.
Quote:
Originally Posted by archaios7
Also, I tried having the zip as an int (in the long run I plan to do that) but it gets angry at me if I don't enter a zip code and tries to parse and empty string to an int. So that brings me to my other issue; What if I don't have all the information but want to save the first/last name, phone, and email? Do I need another method overloader for each combination of information, or is there an easier more elegant way of doing that? Maybe I'm just making it too complex.
Well, this is where your business rules come into play (whether or not you use a separate layer for this). Decide which fields are mandatory, and which can remain blank, and code accordingly. It's entirely reasonable to allow certain fields to remain empty, and fill them in at a later date.
Quote:
Originally Posted by archaios7
The basic purpose for this code is store contact info for various insurance claimants; the in house program we use at work currently has no way of storing that information except in a section used for making notes on phone calls and it is a royal pain to hunt through my notes to find someone's address. Some claims can have multiple claimants and when I am first notified of a claim I don't always have all their contact info. Sometimes it's just a name and address, other times it's a name and phone number, sometimes it's just a name. Also my boss should be setting me up with a database soon that I can play around with, so I can just use that store my info instead of a dictionary<> soon.
Sounds like you've been stuck with some piece-of-crap legacy system there. Upgrading or replacing it will almost certainly be worthwhile, but the thing is, you're going to have to be very careful with implementing the new system. You need to be sure that it's reliable before you migrate from the old system, and one thing that will help (besides rigorous testing) is to run both concurrently for a while, and verify the results against the original system. Of course, this means more work for whoever's doing your data entry, as they will need to enter it in both systems, rather than just one (this is where a good UI comes in, as it can make the data entry go faster).

Of course, if you simply mean you're going to run this alongside the original system, with this new one tracking only contact info (and not any of the uber-critical claim stuff, then you don't need to worry as much about bugs. This is not to say you shouldn't test the code, but rather that if the consequences of failure are less severe, you can justify spending less time in testing.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 12th, 2008, 3:52 PM   #9
archaios7
Newbie
 
Join Date: Jul 2008
Location: Seattle, WA
Posts: 6
Rep Power: 0 archaios7 is on a distinguished road
Re: Values being passed by reference?

Quote:
Of course, if you simply mean you're going to run this alongside the original system, with this new one tracking only contact info (and not any of the uber-critical claim stuff, then you don't need to worry as much about bugs. This is not to say you shouldn't test the code, but rather that if the consequences of failure are less severe, you can justify spending less time in testing.
Basically my boss developed this program slowly over the last 10-15 years, mainly in C++ but he has been shifting to C# slowly over the past two years. My original intent was to copy his programs functionality and have it run under mono on linux and windows too. Now not to get to off topic but the linux compatibility might never happen (Only .Net 1.1 being supported by mono); so I figured I'd just start writing modules/scripts/whatever to add functionality to his program for now. After I get my feet wet I want to do a complete rewrite of this program but no idea when I will be getting around to doing that.

Anyways, thanks for your explanation about the differing layers approach. You explain these concepts pretty darn good.
archaios7 is offline   Reply With Quote
Old Aug 13th, 2008, 11:04 AM   #10
BstrucT
Hobbyist Programmer
 
BstrucT's Avatar
 
Join Date: Dec 2007
Location: Durban, South-Africa
Posts: 206
Rep Power: 1 BstrucT is on a distinguished road
Re: Values being passed by reference?

Quote:
Originally Posted by archaios7 View Post
You explain these concepts pretty darn good.
Great example, thanks lectricpharaoh.

As allways, your explanation have inlightened more than just the thread starter, and I will now commence programming on the same topic discussed.
__________________
"Common sense is the collection of prejudices acquired by age eighteen." - Albert Einstein
BstrucT is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump