-2

I have a Windows Form with A LOT of controls separated into groups based on the day (Monday, Tuesday, etc.), and functions dependent on the controls within that day. I want to find a better way to structure my code, because right now it feels and looks like spaghetti.

Currently, my code is technically working, but it's a mess. It's way too long, and when I need to edit some of my functions I'm having to edit them for 7 different days and find/replace control names and stuff.

With the help of a more experienced colleague who suggested using parameters (duh), I've found a way to simplify it some. I haven't applied it to my main code yet, but have played around with it in a simpler test environment.

The problem now is that I have an absurd number of parameters that I'm hoping can be grouped somehow.

I've looked into the GroupBox control, but it doesn't seem to do what I hoped.

Here's a simplified example of code that I'm working with. In my actual code, there are a lot more controls involved, and therefore a lot more parameters.

private void validate(DateTimePicker start, DateTimePicker end, DateTimePicker lunch, Label day)
{
    if ((lunch.Value < start.Value || lunch.Value >= end.Value))
    {
        day.Visible = true;
    }
    if ((lunch.Value >= start.Value && lunch.Value < end.Value))
    {
        day.Visible = false;
    }
}

I have a feeling I should be using an array to group these? Can anyone confirm? Thanks.

TL;DR: How can you group a lot of parameters for passing to a function?

  • 1
    Since everything is working, the question sounds off-topic here. I believe that it can be an interesting case, but I am afraid it will not be answered here, because it is too broad, opinion-based and is not Q&A-style in general. Try to split your question to specific cases of what you want and can't achieve with your code, and provide minimal reproducible example with code, so that we can help. – Yeldar Kurmangaliyev Dec 26 '18 at 22:14
  • This sounds like a prime mentorship opportunity, one that few on SO seem to have. You should start by asking your colleague this question. It would be a shame if [s]he weren't willing to use that experience to help you grow as a developer. – madreflection Dec 26 '18 at 22:21
  • 1
    It already is specific though? I want to know if there’s a way to group all of the parameters/controls so that I don’t have to pass 10+ parameters to my function. There’s nothing else to split up. – irisshootsface Dec 26 '18 at 22:23
  • 1
    My colleague is not a c# programmer. He works with PowerShell so the only clue he was able to give me was the using parameters one. He doesn’t know syntax or details for c#. I have another colleague that’s more experienced with c# but he is on vacation til the beginning of next year. (Sorry for brief responses, I’m on mobile right now.) – irisshootsface Dec 26 '18 at 22:24
  • Did he say "no"? Regardless of language, he seems to have a good idea of *what* to do, if not *how* to do it. That's something. – madreflection Dec 26 '18 at 22:30
  • 1
    Let me clarify. I'm not sure, compared to you guys, how experienced he actually is. I think he'd probably still classify himself as a novice. He does not know c#, he knows powershell and has a basic understanding of programming. His job role allows him to spend a lot more time learning while mine does not, as well. When I explained my original problem to him last week he threw out the parameter/argument suggestion but said he doesn't know exactly how to do it in C#, so I went out and learned how to do it today. It's great, but I need more. I came to SO because neither mentor is working today. – irisshootsface Dec 26 '18 at 22:36
  • 1
    I am going to edit my OP as well since I found a simpler way to word what I need. I apologize for writing novel length posts, I don't always know what information is relevant or not or how to properly word my question/problem. – irisshootsface Dec 26 '18 at 22:37
  • 1
    @YeldarKurmangaliyev I've edited my OP a bit to hopefully clarify exactly what I need. I came here assuming that this was simply me lacking knowledge of the fundamentals, and that there was something basic I could be pointed in the direction of to achieve what I'm doing. If it's actually that subjective and would require a more complicated solution then that changes things. I'll delete it if that's the case. My intention isn't to spam or anything like that. Apologies. – irisshootsface Dec 26 '18 at 22:49
  • 1
    @madreflection You are correct that this is prime mentorship opportunity and I would much prefer to work with someone directly. They just aren't available right now and I'm super gung-ho about working on this project during my downtime this week :D – irisshootsface Dec 26 '18 at 22:51

1 Answers1

1

I'm not sure if the small scope you share with us is enough to give a meaningful answer; but neither I'm sure sharing with us a bigger part of the code would be really helpful.

Anyway, with the small information you gave us, I can think of a couple suggestions:

1. Create a custom control.

If you say you have group of controls that repeat themselves once for each day of the week, and each group of control executes the same logic, it would be better to create a custom control that contains both all the controls each day needs, and the logic within each group of controls. Add methods, functions and events to control its behaviour and its interaction with the rest of the form. Then just put as many instances of that control as you need, and let the control control itself.

2. Don't pass controls as parameters, pass their values.

Passing the controls as parameters adds little to no value to your code, increases complexity, tightens coupling and could even be considered a code smell. Instead, create methods and function that receive values as parameters, and call them using the values of the controls. With this, you could even create a POCO that contains all the values needed, and receive that as parameter - just make sure each POCO is related to the logical design and not to the functions instead (i.e. don't create one for each function; create 4 or 5 that can contain all necesary values and receive as many as needed in each function). This would also be a step into the 'decoupling' direction, allowing you to eventually separate your code in layers.

3. Use return values instead of reference parameters. One thing that increases the number of parameters received by your method is that you also receive the object whose state will be modified by it. You could instead return a value and assign it to the target control, both reducing the number of parameters and increasign the usefullness of your function.

Taking these points in consideration, and using your example, instead of this:

private void validate(DateTimePicker start, DateTimePicker end, DateTimePicker lunch, Label day)
{
    if ((lunch.Value < start.Value || lunch.Value >= end.Value))
    {
        day.Visible = true;
    }
    if ((lunch.Value >= start.Value && lunch.Value < end.Value))
    {
        day.Visible = false;
    }
}

You could have this:

private bool validate(DateTime start, DateTime end, DateTime lunch)
{
    return lunch < start || lunch > end;
}

public bool validateControl()
{
    //executes all validations
    this.lblDay.Visible = validate(dtpStart.Value, dtpEnd.Value, dtpLunch.Value);
}
Josh Part
  • 2,154
  • 12
  • 15
  • Beat me to it. :) I was going to suggest, however, that `validate` return `true` for the opposite condition (i.e. true means that it passed validation, which is that lunch is between the start and end of the day) and set `this.lblDay.Visible` to the negative of its result. – madreflection Dec 26 '18 at 23:28
  • Yikes! This is going to take me a bit to comprehend, I apologize. But thank you SOO much for a detailed answer. I didn't want to copy paste my entire code because.. it really is a LOT (probably would need to go into a pastebin or something..) and I feel like it would have just resulted in insta-downvotes and also would have made me look lazy or something. Every time I come here I play a game of "okay how do I best word this to get the least amount of downvotes and will I get banned." I don't know if this is the solution I need yet or not, but should I hit the check button and accept it anyway? – irisshootsface Dec 26 '18 at 23:38
  • The User Control idea is exactly what I was thinking. If it's absolutely necessary to handle the controls within your function and not just handle the control's values (as Josh so wisely suggested), then creating a User Control and passing it in as a parameter will give you complete control and access over everything in the User Control. – Frank Ball Dec 26 '18 at 23:45
  • @madreflection yeah, that would make sense, too, but I think the right choice entirely depends on what is actually a "valid" date for OP. – Josh Part Dec 27 '18 at 00:39
  • @JoshPart I agree, and based on the overcomplicated test that conflates business logic and UI logic, I believe OP may need to rethink what that is. As I read it, the logic and the names of the controls suggest that a label (presumably with a validation error message) is being displayed when something is *invalid*. Would it not make sense then to set the label's `Visible` property to the logical negative of the *valid* determination? Maybe I'm being too pedantic with this suggestion but I think there's value in the thought process. – madreflection Dec 27 '18 at 01:35
  • @madreflection yeah, the fact that I actually visualize differently what the "validation" process means (the "name" of the day is shown when the start and end selected dates don't clash with the lunch time...?) should be a red flag for OP that maybe his entire logic requires a rework (which is usually very scary on scenarios that include lots of input controls and repeated functions); let's just hope that this question is actually the first step in the right direction for OP to refactor his code. – Josh Part Dec 27 '18 at 01:43
  • @JoshPart would you like to see the full code? You'll probably laugh at me. What I'm actually doing.. is validation. I'm having certain labels (red exclamation marks) appear to the user as visual cues when they input invalid values. Right now, I have working code that makes these visual cues appear if they enter a value for a break/lunch that is outside of the currently designated shift start/end times. That works, but I went to go add even MORE validation in, checking like.. if breaks/lunches will overlap. And that's when I was like "this is too complicated.. there has to be an easier way." – irisshootsface Dec 27 '18 at 20:55
  • @joshpart to top it all off, I was aware that there was some kind of built-in validation method(???) or something that C# can do, but I have NO IDEA how to use it. So I just started doing all of this.. on my own. While trying to learn. It's a mess. – irisshootsface Dec 27 '18 at 20:56
  • @joshpart I saw someone word it best kind of like this: I'm basically trying to get to my destination by riding a bicycle, and everyone expects me to just fly a jet, but I didn't even know we COULD fly jets, not to mention I'm lacking resources for learning to fly jets lol and all I really know how to do is walk and ride a bicycle (with training wheels, looking at you Visual Studio). – irisshootsface Dec 27 '18 at 21:01
  • 1
    @irisshootsface what we meant is that, with the chunk of code you shared it was confusing what such code was supposed to do; now, as I see you're somewhat learning C# (don't know if programming in general), here's a little PSA: start thinking less in the "easiest way" and more in the "right way"; the right way is the less complex, less problematic one to change and mantain, and this doesn't necessarily mean is the easiest way to do things (nor does it mean there's only one, absolute "right way", but that's a story for another time) – Josh Part Dec 28 '18 at 00:09