Is there a good reason to write code in Program.cs

2019-03-11 17:55发布

问题:

I am working on a pretty large application and my tech lead and I are not seeing eye to eye on certain things.

One of them is regarding console applications. These applications are being ported to C# from shell scripts. Some of these scripts are reasonably large (300-400 lines of code after conversion) and do things like I/O, Email and database access.

For each of these scripts I created a class. Each class has a Run method which calls any methods/operations that are within. Inside Program.cs/ main, I create an object of said class and call Run. Program.cs contains 4-5 lines of code. Clean and simple.

My tech lead wants to get rid of the script classes and just have everything inside the main method of program.cs. His reasoning is that it is too confusing the way it is.

It feels awkward having to do it this way as the class no longer becomes reusable/package-able into a class library without having to fiddle with the main method.

Unit tests seem like they are unaffected since you can instantiate Program.cs itself, but again....this feels clunky. Are there any benefits to doing it his way that I am not seeing? Are there any benefits my way? Is there a general practice when dealing with large applications and content in your main method?

Thank you for your time.

回答1:

It feels awkward having to do it this way as the class no longer becomes reusable/package-able into a class library without having to fiddle with the main method.

It doesn't have to be that way.

For example, each of your scripts could still have the same structure it does, but also have a private static void Main(string[] args) method. (It could be non-private if you want - it all depends on your needs.)

That way it's standalone (can be compiled as a single input to a single output then run) which can occasionally be handy, but could also be used as part of a class library. The presence of a Main method in no way prevents the class being used from other classes, after all.

It's not clear whether you've got one Program.cs file or one per script. If you've got one per script, each of which is just 4-5 lines, that does seem somewhat pointless.

Now this certainly wouldn't be how I'd normally structure a large application - but if the point is to have several "scripts" each of which can be run standalone, then giving each class a Main method doesn't seem too bad.

In fact, what I often do for demo purposes is have several classes with Main methods in a single project, then have a separate entry point (which is in Program.cs) which uses reflection to find all the others and then allows the user/presenter to choose which one to run.

If all your code makes sense to have in a single class, then having a tiny extra entry method doesn't seem such a problem. If it's actually a case of too much code for a single class regardless of where the entry point is, that's a different matter. (So if you stuck to having a single ScriptClass when actually you should give different tasks to different classes, that would be bad too.) Likewise if he really is insisting on all the code being in a single method, that's definitely a problem for testing and maintainability.

I suggest you set the entry point disagreement aside for the moment: work out the cleanest way to structure everything else about the code, and then it really doesn't matter whether the Main method goes in Program.cs or within another class.



回答2:

I think you're creating work for yourself, honestly. I can't tell from the details in your description - but if shell scripts have been working, why structure it where structure was apparently not needed?

You're stating that modularity and repackaging into an external library is something that you'll need to do - I would counter "why?" (this is what I mean by extra work).

If you create a simple set of methods in a single file - that's a single file! It, by definition, will be easier to work with then multiple projects etc.

That said - it's hard to know what we're talking about unless there are some more details. If it's "send a nightly report and email these people" - yeah that's something that doesn't need a class library and a ton of modularity. Run a method, you're done.



回答3:

You do know that the entry point of a console application is configurable, right?

My preferred method would be:

class MeaningfullyNamedProgram { 
    public static void Main(string[] args) {
        var program = new MeaningfullyNamedProgram(args);
        program.Run();
    }

    public MeaningfullyNamedProgram(string[] args) { 
    }

    public Run() {
        // well structured, broken-out code follows 
    }
}

Point the entry point of the project at MeaningfullyNamedProgram.Main

NOTE: I'll leave it as an exercise for the reader, but you could create a base class for this using generics, and save yourself some typing.



回答4:

Your tech lead needs a good talking to! Putting everything into the Program.cs is not the way forward.



回答5:

Well, his way is conceptually simpler, in that it's how programs were written before the subroutine was invented ....

Your way is better: it supports reusability and would be easier to modify and to debug.

The only other justification I can think of for his way was that if it was taking significantly longer for you to do it your way than it would be to do it his way. But that's a case of short-term thinking on his part. Your way will stand the test of time better.



回答6:

Your tech lead is wrong. The method you propose is a lot more reasonable -- it allows for the consolidation of different scripts easily. Each script having its own Main method can get clunky, especially if you are planning on having an application that can run several of these at a time.



回答7:

Splitting the logic out into a separate class (or classes) is the way to go. Putting it all into one spot violates the principles of SOLID and DRY design. You're definitely on the right track with your approach.

The more you keep your classes focused on single roles the easier your life will be for maintenance and testing.



回答8:

If the functionality can be consumed by other means than a console program, of course you should keep them in a nicelly modelled class library. To save a few lines of code by entangeling command line parameter processing with encapsulated functionality does not make sense given the fact that the concerns were originally separated anyway. Maybe your tech lead should find more productive tasks for you IMHO.



标签: c# main