问:
Advantages of using .dll files over linking .cs files to projects (for my own generic helper classes / extension methods)
I have a helper project which I use in all the applications that I create. It contains some extension methods and a bunch of generic helper classes, controls etc. I update/extend the helper project from time to time. These are usually small and unrelated projects, and I am the only person working on all of them.

I tried two approaches for using it

add .cs files directly (Add as link) to each project where I use them

compile it as .dll and add it as reference

I see some benefits and drawbacks of these approaches.

The first one:

is simpler, because the helper classes get compiled into the exe file, therefore I can often very easily provide just a single .exe file that will work just fine. Because I add as link, I can be pretty sure that whenever I build any project that uses the helper, the helper files will be the latest version.

is even simpler, because I can separate the files, so that my extension methods that run fine on .NET 4.0 can be referenced separately from the ones that require .NET 4.5, which means that the app as a whole can run on .NET 4.0

Allows to debug through the code, with all the benefits of breakpoints etc etc...

doesn't seem to be 'best practice'

The second one:

appears to be the right approach, but:

requires me to deliver a separate .dll file, which for some reason is much more difficult for users (they tend to share my programs without the .dll, which then crashes on startup)

as it gets compiled into a single .dll, it will require the highest version of .NET - many of my users don't have .NET 4.5 and only some elements of my helper class require this, which means I can be forcing some people to update their systems for no reason

I also need to make sure that whenever I update any of my programs, I also deliver the .dll file - even though I don't know if it has been changed since the last version, or not (it could have been, but it could as well be the same version). I cannot see a simple way to determine that, without keeping track of assembly version, which is additional work. For now, when I update my programs, I only deliver updated exe, and I like to keep it small and low profile.

So, what is the actual benefit for using the .dll file here? Please note, that I am the only person editing code of all the applications and the helper files.

Also, to clarify - the apps are usually very little, whereas the code contained in the helper classes is completely generic to all of them (some simple string-comparison, paths or XML operations etc)

Actually, someone made me realize just now that there's a third option.
As I have the helper code in a separte project, I can add this project to solutions of each of my separate applications - which works kind of like 'Add as link' for single files, except I only add a single project...
But as noticed by Doc Brown, this essentially means that .dll will need to be added to the project anyway...

Yet another thing which is kind of in favour of not using the dll files is the ability to debug through the helper class actively...

答:
You already spotted most of the pros and cons. Using cs files as references is indeed more lightweight and often easier to manage.  However, I recommend to use this approach exclusively when your cs files are fully self-contained and do not have any special build requirements.

Using separate DLLs

will make dependencies to other utilities or libraries explicit (so as long as you do not have such dependencies, it will work fine)

will allow you to define specific build configurations (for example, if a class only works in x86 configuration, or needs at least .NET 4.0, the build configuration of the assembly makes this requirement explicit).

So especially if you have lots of single-class, self contained components, using reference to files is fine, but if you have components referencing other components, or specific build requirements, I would recommend to use DLLs.

To mitigate the problems with managing many separate DLLs, you can either create an installer package, or utilize ILMerge, which can embed a set of assemblies into a single executable. In our environment, we deal with the problem differently, by using a deploy script for each application. This script makes sure all needed DLLs are always delivered to production when a new application release is published.


问:
How to consume standard routed API in a clean way?
Let's take an example of a generic API endpoint that looks as follows:

https://api.imgur.com/3/gallery/{section}/{sort}/{window}/{showViral}/{page}
```

<p>Conditions on this endpoint are as follows:</p>

<ol>
<li>Arguments are optional. Default values will be used if not provided.</li>
<li>All the earlier arguments must be provided in order to use an argument. So in this example, if I were to get posts of page no 2, I must provide section, sort, window and showViral values.</li>
</ol>

<p>I am trying to create a C# wrapper around such endpoints. My method looks somewhat as follows:</p>

```public static async Task<List<Image>> GetGallery(Section? section = null, Sort? sort = null, Window? window = null, bool? showViral = null, int? page = null)
{
    string uri = "gallery";
    if (section != null)
    {
        uri += "/" + section.ToString().ToLower();
        if(sort != null)
        {
            uri += "/" + sort.ToString().ToLower();
            if(window != null)
            {
                uri += "/" + window.ToString().ToLower();
                if (showViral != null)
                {
                    uri += "/" + showViral.ToString();
                    if (page != null)
                    {
                        uri += "/" + page;
                    }
                }
            }
        }
    }
    JObject response = await NetworkHelper.ExecuteRequest(uri);
    return response["data"].ToObject<List<Image>>();
}
```

I'm not really happy with this implementation. This code looks very ugly. Any thoughts on how I can improve this?

答:
You can write a fluent solution. It needs some interfaces, but the usage for a client is very simple and guided, since autocompletion will automatically suggest two possibilities at each point: Images or the subcriteria, e.g. Sort(...);

So for the client, the usage would be like this:

```<code>var g = // get gallerygetter from somewhere

// get all images
var images = g.Get().Images;

// subsets
var images = g.Get().Section(section).Sort(sort).Images;

var images = g.Get()
    .Section(section)
    .Sort(sort)
    .Window(window)
    .ShowViral(showViral)
    .Page(page)
    .Images;
</code>```

Now of course, in order to support such a nice use, you need some interfaces. But you can implement all those in a single class.

```<code>public interface IGallerySectionSortWindowShowViralPage : IGallery
{
    IGallery Page(int x);
}

public interface IGallerySectionSortWindowShowViral : IGallery
{
    IGallerySectionSortWindowShowViralPage ShowViral(bool x);
}

public interface IGallerySectionSortWindow : IGallery
{
    IGallerySectionSortWindowShowViral Window(Window w);
}

public interface IGallerySectionSort : IGallery
{
    IGallerySectionSortWindow Sort(Sort s);
}

public interface IGallerySection : IGallery
{
    IGallerySectionSort Section(Section s);
}

public IGallery
{
    Task<List<Image>> Images { get; }
}

public IGalleryGetter : IGallery
{
    IGallerySection Get();
}

public Gallery
    : IGallery
    , IGalleryGetter
    , IGallerySection
    , IGallerySectionSort
    , IGallerySectionSortWindow
    , IGallerySectionSortWindowShowViral
    , IGallerySectionSortWindowShowViralPage
{
    private string uri = "gallery";

    public Task<List<Image>> Images
    {
        JObject response = await NetworkHelper.ExecuteRequest(uri);
        return response["data"].ToObject<List<Image>>();
    }

    public IGallerySection Get()
    {
        return this;
    }

    public IGallerySectionSort Section(Section section)
    {
        uri += "/" + section.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindow Sort(Sort sort)
    {
        uri += "/" + sort.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindowShowViral Window(Window window)
    {
        uri += "/" + window.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindowShowViralPage ShowViral(bool show_viral)
    {
        uri += "/" + show_viral.ToString().ToLower();
        return this;
    }

    public IGallery Page(int page)
    {
        uri += "/" + page.ToString().ToLower();
        return this;
    }

}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
You can write a fluent solution. It needs some interfaces, but the usage for a client is very simple and guided, since autocompletion will automatically suggest two possibilities at each point: Images or the subcriteria, e.g. Sort(...);

So for the client, the usage would be like this:

var g = // get gallerygetter from somewhere

// get all images
var images = g.Get().Images;

// subsets
var images = g.Get().Section(section).Sort(sort).Images;

var images = g.Get()
    .Section(section)
    .Sort(sort)
    .Window(window)
    .ShowViral(showViral)
    .Page(page)
    .Images;

Now of course, in order to support such a nice use, you need some interfaces. But you can implement all those in a single class.

public interface IGallerySectionSortWindowShowViralPage : IGallery
{
    IGallery Page(int x);
}

public interface IGallerySectionSortWindowShowViral : IGallery
{
    IGallerySectionSortWindowShowViralPage ShowViral(bool x);
}

public interface IGallerySectionSortWindow : IGallery
{
    IGallerySectionSortWindowShowViral Window(Window w);
}

public interface IGallerySectionSort : IGallery
{
    IGallerySectionSortWindow Sort(Sort s);
}

public interface IGallerySection : IGallery
{
    IGallerySectionSort Section(Section s);
}

public IGallery
{
    Task<List<Image>> Images { get; }
}

public IGalleryGetter : IGallery
{
    IGallerySection Get();
}

public Gallery
    : IGallery
    , IGalleryGetter
    , IGallerySection
    , IGallerySectionSort
    , IGallerySectionSortWindow
    , IGallerySectionSortWindowShowViral
    , IGallerySectionSortWindowShowViralPage
{
    private string uri = "gallery";

    public Task<List<Image>> Images
    {
        JObject response = await NetworkHelper.ExecuteRequest(uri);
        return response["data"].ToObject<List<Image>>();
    }

    public IGallerySection Get()
    {
        return this;
    }

    public IGallerySectionSort Section(Section section)
    {
        uri += "/" + section.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindow Sort(Sort sort)
    {
        uri += "/" + sort.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindowShowViral Window(Window window)
    {
        uri += "/" + window.ToString().ToLower();
        return this;
    }

    public IGallerySectionSortWindowShowViralPage ShowViral(bool show_viral)
    {
        uri += "/" + show_viral.ToString().ToLower();
        return this;
    }

    public IGallery Page(int page)
    {
        uri += "/" + page.ToString().ToLower();
        return this;
    }

}


答: DLLs are handy when an application is large and there are pieces that require updates, but not the entire application. So, if you're writing MS Word, it's handy to have the spell-check code in a DLL that can be updated without having to update the entirety of MS Word. If what you're writing is a small utility app (or a series of self-contained apps that happen to all use the same code) it doesn't make much difference whether the code is embedded in the app(s) or not. </p>

Title: Advantages of using .dll files over linking .cs files to projects (for my own generic helper classes / extension methods)

Body:
I have a helper project which I use in all the applications that I create. It contains some extension methods and a bunch of generic helper classes, controls etc. I update/extend the helper project from time to time. These are usually small and unrelated projects, and I am the only person working on all of them.

I tried two approaches for using it

add .cs files directly (Add as link) to each project where I use them

compile it as .dll and add it as reference

I see some benefits and drawbacks of these approaches.

The first one:

is simpler, because the helper classes get compiled into the exe file, therefore I can often very easily provide just a single .exe file that will work just fine. Because I add as link, I can be pretty sure that whenever I build any project that uses the helper, the helper files will be the latest version.

is even simpler, because I can separate the files, so that my extension methods that run fine on .NET 4.0 can be referenced separately from the ones that require .NET 4.5, which means that the app as a whole can run on .NET 4.0

Allows to debug through the code, with all the benefits of breakpoints etc etc...

doesn't seem to be 'best practice'

The second one:

appears to be the right approach, but:

requires me to deliver a separate .dll file, which for some reason is much more difficult for users (they tend to share my programs without the .dll, which then crashes on startup)

as it gets compiled into a single .dll, it will require the highest version of .NET - many of my users don't have .NET 4.5 and only some elements of my helper class require this, which means I can be forcing some people to update their systems for no reason

I also need to make sure that whenever I update any of my programs, I also deliver the .dll file - even though I don't know if it has been changed since the last version, or not (it could have been, but it could as well be the same version). I cannot see a simple way to determine that, without keeping track of assembly version, which is additional work. For now, when I update my programs, I only deliver updated exe, and I like to keep it small and low profile.

So, what is the actual benefit for using the .dll file here? Please note, that I am the only person editing code of all the applications and the helper files.

Also, to clarify - the apps are usually very little, whereas the code contained in the helper classes is completely generic to all of them (some simple string-comparison, paths or XML operations etc)

Actually, someone made me realize just now that there's a third option.
As I have the helper code in a separte project, I can add this project to solutions of each of my separate applications - which works kind of like 'Add as link' for single files, except I only add a single project...
But as noticed by Doc Brown, this essentially means that .dll will need to be added to the project anyway...

Yet another thing which is kind of in favour of not using the dll files is the ability to debug through the helper class actively...


问:
Why can't I call a constructor in itself?
I am currently porting the class NumberRange from Java to C#.

I am writing this constructor and I wonder whether I can call a constructor in itself. Something like this:

```<code>public NumberRange(Double num1, Double num2)
{
    if (num1 <= num2)
    {
        Min = num1;
        Max = num2;
    }
    else
    {
        NumberRange(num2, num1);
        // Min = num2;
        // Max = num1;
    }
}
</code>```

.NETFiddle

This is not a big deal, but I am curious. I think it is to prevent messing with constructor by creating a Stack Overflow during a class creation.

So, why can't I call a constructor in itself?

Edit:

I remind that my question was about the "why" and not the "how". If you ask yourself how I implemented this, just read my code here.

答:
You can call a constructor from a constructor but you need a different syntax and to call a different constructor. I intentionally changed the signature for the private constructor to differentiate the two. It isn't good in this example since they should logically have the same signature</p>

```<code>public NumberRange(Double num1, Double num2)
    : this(Math.Min(num1, num2), Math.Max(num1, num2), true) { }
private NumberRange(Double num1, Double num2, bool differentSignature){
    Min = num1;
    Max = num2;
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
You can call a constructor from a constructor but you need a different syntax and to call a different constructor. I intentionally changed the signature for the private constructor to differentiate the two. It isn't good in this example since they should logically have the same signature

public NumberRange(Double num1, Double num2)
    : this(Math.Min(num1, num2), Math.Max(num1, num2), true) { }
private NumberRange(Double num1, Double num2, bool differentSignature){
    Min = num1;
    Max = num2;
}


问:
Do you actually write 'clean code'?
I have seen some programmers tweaking their code over and over again not only to make it 'work good', but also to make it 'look good'.

IMO, 'clean code' is actually a compliment indicating your code is elegant, perfectly understandable and maintainable. And the difference comes out when you have to choose between an aesthetically appealing code vs. code that's stressful to look at.

So, how many of you actually write 'clean code'? Is it a good practice? What are the other benefits or drawbacks of this?

答:
I like code to be readable, but the most important thing is consistency. For me that means consistency with naming conventions and spacing between functions, parenthesis on the same line or the next line of the if statement, etc.

Of course, there are times when someone programs something with a consistent code style and it still drives me insane. Especially code that doesn't "breath". For example:

```<code>void function1(){
    //whatever code
}
int fooBar(){
    //whatever else
}
Foo* someOtherFooBar(int value){
    if(value){
        //do something
    }
    return ...;
}
</code>```

Well... It looks worse with Objective-C methods, and with lots and lots of nested if statements, and lines much longer than 80 characters. But it still annoys me :)

Title: Do you actually write 'clean code'?

Body:
I like code to be readable, but the most important thing is consistency. For me that means consistency with naming conventions and spacing between functions, parenthesis on the same line or the next line of the if statement, etc.

Of course, there are times when someone programs something with a consistent code style and it still drives me insane. Especially code that doesn't "breath". For example:

void function1(){
    //whatever code
}
int fooBar(){
    //whatever else
}
Foo* someOtherFooBar(int value){
    if(value){
        //do something
    }
    return ...;
}

Well... It looks worse with Objective-C methods, and with lots and lots of nested if statements, and lines much longer than 80 characters. But it still annoys me :)

ContentLicense: CC BY-SA 2.5


问:
Any benefits of splitting web project stylesheets?
Regarding the fact that C in CSS stands for Cascade, so generally speaking rules described in one file can modify/subsitute rules in other files, can we claim that all project css files should be concatenated to a single file in most cases.

Because browser still won't get all style computed till all rules will be taken into consideration.

In other words, is there any sense in parallelizing download of styles for web project. What will be the rule of thumb to decide whether css  file should be splitted into multiple or vice versa?

May be, say, we can claim that there are "crucial" css properties - like dimensions, paddings and margins - and less crucial - like colors, transitions etc.? And that less crucial styles could be downloaded as a separate resource?

答:
As with many projects - management.
I have a project where I maintain 5 Less stylesheets but are compiled into a single file.

This makes it easy to go to where I need to go but only need to include a single file for the project. Minifying it further shrinks the file.

I do have other CSS files for third party scripts and whatnot, but for the site its how I have been managing it.


问:
Under the hood of Java application servers resources
We are used to Node.js / Python / Insert X.

Moving to a Java EE stack, it seems to me like all of the resources are 'press this button', 'do that' without any actual architectural explanation.

For the time being I'm interested in answers to the following questions (I'm completely ignorant on the topic, so some of them may sound stupid):

How does the Rest-API fit into the picture? It seems like EE Servers don't implement them themselves, so one has to use Jenkins. What is it? How does the server understand how to reroute requests to the 'Jenkins classes'

How are these 'Jenkins classes' handled? Does the server create a new thread for each request?

答:
Jenkins is actually a CI tool, did you mean JAX-RS? That's the Java API for RESTful web services. There's an introductory tutorial here.

The way it works is you have to provide an implementation of the JAX-RS API (Jersey is the reference implementation, it may be installed with your server or available as an add-on). Once that is in place, you simply define a servlet mapping that directs service requests to the JAX-RS servlet. That servlet then takes care of figuring out how to direct it to the implementation classes that service the particular request.


问:
What does "amortized" mean in "amortized analysis" of algorithms?
"amortize" mean

reduce or extinguish (a debt) by money regularly put aside.

i.e. to pay  off of debt with a fixed repayment schedule in regular installments over a period of time.

In amortized analysis of algorithms, does "amortize" also mean to reduce something by something else regularly put aside?

答:
Amortized worst-case analysis is called so because of its analogy to finance.

Amortized worst-case analysis looks at multiple successive operations on a data structure instead of treating every operation individually. The idea is that, unless you are developing a hard-realtime system, you will be more interested in how the system performs overall than how it performs at every single instant.

For example, think about how you would implement a dynamic (i.e. resizable) array: you would guess a suitable size for the array, then start adding elements to it one-by-one. At some time, the array is full, and when you add a new element, you have to create a new, bigger, array and copy all the existing elements over to the new array. That's an O(n) operation. So, the worst-case for adding an element to a dynamic array is O(n). That's clearly undesirable, a static array has O(1), and we don't want our dynamic arrays to be significantly slower than static arrays.

So, the worst-case is O(n). But … how often does that worst-case occur? Well, it turns out that if we do the resizing right, in particular, if we resize exponentially (e.g. double the size everytime the array is full), resizing happens rather rarely.

Intuitively, resizing needs to occur less than every O(n) operations, and it takes O(n) time, so overall the array seems to behave as if it had O(1) add time, even though it doesn't. Only the one call which actually ends up triggering the resize will be slow, all others will be fast, and there are far more fast calls than slow calls (in fact, there are more than O(n) times more fast calls than slow calls).

If you want all the gory details for how exactly amortized worst-case analysis is defined, how to perform it, and how to prove that dynamic arrays have O(1) amortized worst-case add, you should consult an algorithms textbook.

But the intuition is this: just like taking on a loan to buy a big machine amortizes itself over time, because the bigger machine means you make more money which allows you to pay back the loan, allocating a larger array and copying all the elements over amortizes itself because there will be a large number of "fast adds" that allow you to "pay back" the time penalty you took on that one slow add. That's why it's called "amortized analysis", because it allows you to "borrow time" for infrequent slow operations and pay that time back with frequent fast operations.

Note that this is still different from expected worst-case analysis and average-case analysis. Those have probability distributions and random variables, but amortized worst-case analysis is still deterministic worst-case, it just looks at the "bigger picture" of how a data structure is used over time.


答:
You can improve this by separate the path joining method.

```<code>public static string BuildPath(params object[] paths) {
    string result = "";
    if (paths != null) {
        foreach(var path in paths) {
            if (path == null) break;
            result += "/" + path;
        }
    }
    return result;
}
</code>```

Then your implementation will make more sense, because it is one-liner

```<code>string uri = BuildPath("gallery", section, sort, window, showViral, page);
</code>```

I did this in a fiddler here: https://dotnetfiddle.net/w9n0wg. Kindly noted that this is mimicking of your code behaviour, and does not do URL path encoding at all.

Title: How to consume standard routed API in a clean way?

Body:
Let's take an example of a generic API endpoint that looks as follows:

https://api.imgur.com/3/gallery/{section}/{sort}/{window}/{showViral}/{page}
```

<p>Conditions on this endpoint are as follows:</p>

<ol>
<li>Arguments are optional. Default values will be used if not provided.</li>
<li>All the earlier arguments must be provided in order to use an argument. So in this example, if I were to get posts of page no 2, I must provide section, sort, window and showViral values.</li>
</ol>

<p>I am trying to create a C# wrapper around such endpoints. My method looks somewhat as follows:</p>

```public static async Task<List<Image>> GetGallery(Section? section = null, Sort? sort = null, Window? window = null, bool? showViral = null, int? page = null)
{
    string uri = "gallery";
    if (section != null)
    {
        uri += "/" + section.ToString().ToLower();
        if(sort != null)
        {
            uri += "/" + sort.ToString().ToLower();
            if(window != null)
            {
                uri += "/" + window.ToString().ToLower();
                if (showViral != null)
                {
                    uri += "/" + showViral.ToString();
                    if (page != null)
                    {
                        uri += "/" + page;
                    }
                }
            }
        }
    }
    JObject response = await NetworkHelper.ExecuteRequest(uri);
    return response["data"].ToObject<List<Image>>();
}
```

I'm not really happy with this implementation. This code looks very ugly. Any thoughts on how I can improve this?

Body:
You can improve this by separate the path joining method.

public static string BuildPath(params object[] paths) {
    string result = "";
    if (paths != null) {
        foreach(var path in paths) {
            if (path == null) break;
            result += "/" + path;
        }
    }
    return result;
}

Then your implementation will make more sense, because it is one-liner

string uri = BuildPath("gallery", section, sort, window, showViral, page);

I did this in a fiddler here: https://dotnetfiddle.net/w9n0wg. Kindly noted that this is mimicking of your code behaviour, and does not do URL path encoding at all.


问:
Should curly braces appear on their own line?
Should curly braces be on their own line or not? What do you think about it?

```<code>if (you.hasAnswer()) {
    you.postAnswer();
} else {
    you.doSomething();
}
</code>```

or should it be

```<code>if (you.hasAnswer())
{
    you.postAnswer();
}
else
{
    you.doSomething();
}
</code>```

or even

```<code>if (you.hasAnswer())
    you.postAnswer();
else
    you.doSomething();
</code>```

Please be constructive! Explain why, share experiences, back it up with facts and references.

答:
You should never do the 3rd method.

Skimping on braces might save you a few keystrokes the first time, but the next coder who comes along, adds something to your else clause without noticing the block is missing braces is going to be in for a lot of pain.

Write your code for other people.


问:
Are debugging skills important to become a good programmer?
Along with the other qualities should a programmer need good debugging skills? If I have an applicant who was not able to find the error in the given program, but was able to solve all puzzles and programs, should I consider him for the job? </p>

<p>EDIT :- The puzzles are normal red,blue and red-blue balls like. The programs are like  finding continuous k zeros in an array. The debugging program is something which fails because of condition which should be >=, but instead is >. Everything is on paper. </p>

答:
I'd add a little more to the situation in pointing out the error and see what reaction the person has.  Are they overly dramatic about the, "D'oh! I'm an idiot, that was so dumb..." type, overly apathetic in the, "Yeah, whatever dude," camp, or was there active listening on what was wrong with some kind of apology or remark to denote that they get that they messed up something they should have resolved?  Just something to think about in future situations.

To debug in a timely fashion is a great skill.  This is a bit different than giving someone a problem where it gets fixed when it gets fixed.  Sometimes there has to be aggressive measures taken to save the system which should be acknowledged as I'd imagine most companies wouldn't like to have sales halted for weeks while someone fixes a bug in the accounting software the company uses.


问:
Can an outside component interact with lower layers directly in a strictly layered architecture
If we have a strictly layered architecture, can we allow outside components to interact directly with the lower layeres?

More specifically:

In my lower layers, I am providing a service, and in the top most layer I have a layer called Applications which is basically various set of applications that can use that service. Users (which are considered entities outside the system) can interact with the Application layer through standard protocols. Pretty much similar to what happens in the Internet's architecture. Now if I have users of different types, say admins, ordinary users, ...; do they have to do all the interactions with the system through application layer or can we allow some types of the users to directly interact with the lower layers as well?

答:
"Layered Architecture" is a discipline you impose on yourself and other developers.

So yes its quite possible for you or anyone with access to skip the layers.

This can happen by accident if a developer misinterprets the guidelines.

By design e.g. you let a certain application which runs complex queries to access the database directly instead of using the service interface.

By malice, hackers seldom follow the architectural guidelines.


问:
Usage of class libraries (dlls) - Reference or copy source
I'm working on a big project for the first time and right now I'm using 15 dll's from different sources. Having all these dll's in my output directory together with my .exe is "polluting" that folder a lot.

From most of these dll's I have the source code that I could copy into a single dll of my own reducing the amount of dll's I have in the .exe folder. This looks like a tedious task though... The thing is that, every project I will make in the future will use some of these dll's because they have some very handy controls. (One of these dll's is the WPF Toolkit.)

What it comes down to: Is there an easy way to either reduce the amount of dll's in the .exe folder? Is having so many dll's bad? Is copying source code into you own project an anti-pattern?

答:
Having many DLLs is not necessarily bad. Historically, DLLs have two primary trade-offs:

They require more time when loading. When required they must be loaded into memory and locations mapped out to allow jumping into function locations. If a DLL is not preloaded at program start, this might mean pauses while a program is loading.

They require less space, assuming DLLs are centrally located and reused in multiple programs.

However, modern hardware nullifies these attributes. Modern computers are so fast that unless you literally have hundreds of DLLs to load, the delay will be barely noticeable, if at all. Modern storage capacities are through the roof, and the extra space required by not sharing libraries is generally not noticed. My Android phone has two orders of magnitude more storage than my first desktop computer (and some of the old timers around here can outdo that).

If you are still concerned about this, consider static linking your libraries into your program executable. Do not simply copy the source code.

Static linking has some potential advantages:

You never need be concerned about using the wrong version of a DLL.

If you can shrink your program down to a single file it becomes easier to make portable. Note that this is neither necessary nor sufficient to make an app portable, it only makes the job easier. This may or may not be a concern.

Modern linkers do a pretty good job removing dead code when static linking. For example, I have seen DLLs in the tens of megabytes. Toolkits such as Qt can be that large. If you are only using a small portion of the toolkit, consider static linking instead. The linker can elide all of the unused (dead) code, bringing the combined size of your code and the library code to something much more reasonable.

Saving the best for last: some compilers support whole-program optimizations. This can potentially increase the run-time speed of your program, typically at a severe cost during compile time.

There is one disadvantage to static linking a large amount of code into the primary executable:

The initial load time is longer. The entire executable must normally be loaded into memory, globals initialized, entry logic run, etc. before main() can be called. This could be a lengthy delay before control passes to your program. Some larger programs (e.g. MS Office) get around this by offloading much of the program into DLLs which are loaded after main() is called: this allows the opportunity to display a splash (loading) screen. If you static link everything, you cannot do this.

This might not even be an issue for you. Most programs are not large enough to require a loading screen. Besides, modern hardware is lightning fast compared to the dark ages when this was a truly serious decision.

It is critical that you do not simply copy the source code:

Most, if not all, OSI-approved licenses will allow you to link code units. That is part of what makes "open source" to be "open."

Linking code reduces coupling compared to copying code. While the code references are the same, it is easier to upgrade to a newer library version if you can simply drop in a new static library and link away.

Depending on the compatibility of the licenses used in your code and each library, you might not be allowed to copy the code in and still be in compliance with the licenses. That may create a derivative or combined work, which opens several cans of worms (one can for each combination of licenses). That is a headache you do not want. Further discussion on the topic is dangerously close to legal advice, so I recommend simply avoiding the whole issue and going the linking route after you read the relevant licenses.


问:
When is documentation, unit testing, QA and refactoring meant to be done in a 2 week agile sprint?
The team I am working on is trying to do agile development with 2 week sprints.  I think we must be doing something wrong however, as we have to work like madmen to get the features implemented in the 2 weeks, leaving barely a few hours at the end for a quick QA cycle and no time for documentation or writing unit tests and definitely no time to ever refactor anything.

When should documentation etc. be done if one where to practice agile as it was originally envisioned?

Needless to say the way we are doing it now, many bugs escape into the field, and then people have to be yanked off their sprint task to work on hotfixes, which adds to the stress.

Note this is different to another question posted on this site (the "QA takes 12 weeks" question), as in our case the QA process is quite short and does not hold up the process as such, it just gets squeezed into the end.

答:
There are a few approaches that you can take.

It seems like the ultimate problem that I'd want to address the "work like madmen" part. You should be striving for a sustainable pace, that is a level of effort that you can sustain indefinitely. The idea that you need to "work like madmen", yet aren't able to produce a quality product seems to be an issue.

How do you create a sustainable pace?

From a process perspective, take a look at your team organization. It seems like quality assurance is happening at the end. Consider the idea of a cross-functional team that works together. Don't put quality at the end, but involve quality at every step of the way. You may want to leverage continuous integration to help achieve this - if you have dedicated testers, regularly (nightly?) put changes into their hands and get feedback. Use automated tests to make sure that what they have is close to being correct, at least based on the developers interpretations of the expected results. If they find issues, update your automated tests to help prevent them from recurring.

From a team perspective, take a look at your sprint length. The length is almost always presented as 1-4 weeks. 2 weeks is on the shorter end of the spectrum. Maybe you'll be better off with longer sprints - adding an extra week or two.

From an estimation perspective, consider your definition of done. When is a story done? When it's implemented and unit tested? When it's integrated? When it's been integrated and passed acceptance criteria? It sounds like you need a solid definition of done and estimate the story points against the complete effort. That complete effort should likely include refactoring, unit testing, integration testing, and the acceptance testing effort. Make the whole team part of the effort.


答:
A simple solution using LINQ:

```<code>string CreatePath(params string[] segments)
{
    var includedSegments = segments.TakeWhile(segment => segment != null));
    return String.Join("/", includedSegments);
}
</code>```

Then you just need to pass your string segment arguments in order, converted to string. Alternatively you could do the string conversion inside:

```<code>string CreatePath(params object[] segments)
{
    var includedSegments = segments.TakeWhile(segment => segment != null)).Select(segment => segment.ToString());
    return String.Join("/", includedSegments);
}
</code>```

Body:
A simple solution using LINQ:

string CreatePath(params string[] segments)
{
    var includedSegments = segments.TakeWhile(segment => segment != null));
    return String.Join("/", includedSegments);
}

Then you just need to pass your string segment arguments in order, converted to string. Alternatively you could do the string conversion inside:

string CreatePath(params object[] segments)
{
    var includedSegments = segments.TakeWhile(segment => segment != null)).Select(segment => segment.ToString());
    return String.Join("/", includedSegments);
}


答:
The first thing to do is to recognise that your current approach isn't working. The amount of tasks being allocated to each sprint is causing you to have to cut corners and incur technical debt (eg bugs being released to customers). That technical debt then has to be repaid in subsequent sprints, slowing up future development.

You clearly have recognised that you have a problem. Your next task therefore is to explain this problem to management. They are expecting more than can be delivered and they are hurting the company as a result. Communicate this to them.

Finally you need a solution. That solution is to redefine when a task is done. Each task needs time for refactoring, unit testing, "QA" testing and documentation. Therefore agree with the team and management that all these activities must be carried out before a task is done. Then adjust your task estimates to allow for these activities. This will mean less tasks are scheduled in a sprint. Either accept (as an organisation) that less can be achieved in two weeks, or increase your sprint duration.

Title: When is documentation, unit testing, QA and refactoring meant to be done in a 2 week agile sprint?

Body:
The team I am working on is trying to do agile development with 2 week sprints.  I think we must be doing something wrong however, as we have to work like madmen to get the features implemented in the 2 weeks, leaving barely a few hours at the end for a quick QA cycle and no time for documentation or writing unit tests and definitely no time to ever refactor anything.

When should documentation etc. be done if one where to practice agile as it was originally envisioned?

Needless to say the way we are doing it now, many bugs escape into the field, and then people have to be yanked off their sprint task to work on hotfixes, which adds to the stress.

Note this is different to another question posted on this site (the "QA takes 12 weeks" question), as in our case the QA process is quite short and does not hold up the process as such, it just gets squeezed into the end.


问:
Development environment for lots of websites with Git
I have 5 different websites that use exactly the same code, apart from they have an uploads folder with different contents (AKA images that aren't consistent through every site) and also a config file which has a few settings like whether this is a production environment, which database to use etc.

My problem is I have 5 different versions of the back-end system that should be the same for every site.

So, cue Git. I've just started learning and now understand the basics and need to choose a workflow for my development environment. This workflow will ideally allow me to swiftly switch between one website to another (with the same back-end, different images/config file).

My thoughts on how to achieve this

My idea is to have a branch for each of the different websites. On the master branch is where the back-end code will sit and will have all commits related to the back-end code. Then, create 5 other branches which contain the unique uploads' folders and the config file for each site. Then, when I want to view a different site I just git branch site3 and all the uploads load and the correct database is selected etc.

Does this sound like the right sort of approach? I'm looking for a reliable development workflow that I can use to scale up to 50 sites that I can maintain with ease. The idea is to have all the sites feed from the same back-end, but still be visually different when I switch to the relevant site branch (so I have an accurate representation of each website).

答:
It sounds like you are trying to get the site configuration into your version control system (git). This sounds like a bad idea, especially if you want 1 branch per config.

You'd be best served by only storing the source code in git, and keep the rest as configuration on the server, outside of git. Either as a config file (database credentials), site-specific templates, or where possible: in the database. Every look&feel should be decoupled from the code, and where things differ per project, make a customization hook in the config.

Alternatively, if you really want this in git, I'd suggest having per-site settings in separate directories/file, and use a simple symbolic link with the name current to point to the specific configuration directory/file.

One of the projects I worked on has two separate branches for two specific layouts, and it already turned into a maintenance nightmare a few months in. Bad idea.


答:
You have pretty much summed it up in your question, I only have a couple of points to add.

Mono Options is a great example of a NuGet package that uses the first approach very well.

Alternatively, if you decide to use dlls you can use tools like Costura to embed that reference in your executable as an embedded resource. To use it just add the Costura.Fody package:

```<code>Install-Package Costura.Fody
</code>```

Body:
You have pretty much summed it up in your question, I only have a couple of points to add.

Mono Options is a great example of a NuGet package that uses the first approach very well.

Alternatively, if you decide to use dlls you can use tools like Costura to embed that reference in your executable as an embedded resource. To use it just add the Costura.Fody package:

Install-Package Costura.Fody


问:
Why use `stash@{n}`?
git stash apply stash@{n} contains a number of hard to type characters and repeats some information.

Is there a reason for repeating the stash and using the at-sign and braces instead of something easier to type, like git stash apply n, for instance?

答:
This is actually a simple instance of a much more general syntax for specifying symbolic references (basically, all the things in .git/refs). From the current git documentation on revisions:

<refname>@\{<date>\}, e.g. master@{yesterday}, HEAD@\{5 minutes ago\}

A ref followed by the suffix @ with a date specification enclosed in a brace pair (e.g. {yesterday}, {1 month 2 weeks 3 days 1 hour 1 second ago} or {1979-02-26 18:30:00}) specifies the value of the ref at a prior point in time. This suffix may only be used immediately following a ref name and the ref must have an existing log ($GIT_DIR/logs/<ref>). Note that this looks up the state of your local ref at a given time; e.g., what was in your local master branch last week. If you want to look at commits made during certain times, see --since and --until.

<refname>@\{<n>\}, e.g. master@{1}

A ref followed by the suffix @ with an ordinal specification enclosed in a brace pair (e.g. {1}, {15}) specifies the n-th prior value of that ref. For example master@{1} is the immediate prior value of master while master@{5} is the 5th prior value of master. This suffix may only be used immediately following a ref name and the ref must have an existing log ($GIT_DIR/logs/<refname>).

@\{<n>\}, e.g. @{1}

You can use the @ construct with an empty ref part to get at a reflog entry of the current branch. For example, if you are on branch blabla then @{1} means the same as blabla@{1}.

@\{-<n>\}, e.g. @\{-1\}

The construct @\{-<n>\} means the <n>th branch/commit checked out before the current one.

<branchname>@{upstream}, e.g. master@{upstream}, @{u}

The suffix @{upstream} to a branchname (short form @{u}) refers to the branch that the branch specified by branchname is set to build on top of (configured with branch.<name>.remote and branch.<name>.merge). A missing branchname defaults to the current one.

It's very understandable why the stash@{0} syntax would seem unnecessarily ornate if you've only seen it used in the context of stash refs.

Title: Why use `stash@{n}`?


问:
Where is the best place to store users' profile pictures?
I run a website that is hosted on Microsoft Azure and I'd like to store users' profile pictures.
Which storage solution would be better ? I'm aware of a few ways to do so :

Store images as blobs in database (but I need to render it via a controller)

Store images as base64 in database (but I need to render it via a controller)

Store images on disk (in app_data ?) and store the file name in database

Maybe there are other ways. Please tell me what could be my best choices ?

答: Storing images is one of the classic use cases of Blob Storage.  You can configure a Web Job to kick off each time an image is uploaded for any processing you may need to do (resize, generate a thumbnail, etc).  You can also serve up the images right from blob storage - just store the image URL in your db.  No need to serialize the images or have them pass through your application.</p>


问:
Using a Dr. Dobb's article source code in commercial software
I am considering adding a plugin system to a commercial project and I've found a Dr. Dobb's article that describes in detail with source code a plugin framework for C and C++. The article doesn't mention a license.

Is is generally safe to use such source code in commercial software?

答:
Looking at the Terms of Service on their website, UBM LLC (presumably the parent company of Dr. Dobbs) reserves all rights to the material, with the exception of articles contributed by users.

All [content], excluding any of your Postings (individually and/or
  collectively, "Material"), are the property of UBM LLC.

Which means that the author of the article must provide permission.  Since that permission isn't made clear in the article, you'll have to contact the author directly.

In practice, it's generally assumed that, if you're sharing code like this over the Internet, you intend it to be copied and used by others, else why would you be putting it on the Internet?  But it's still a good idea to get explicit permission; simply putting one's code on the Internet doesn't automatically confer any specific usage rights to anyone else.

The only people who have implicit usage rights for Dr. Dobbs articles are UBM LLC, who require those rights to be conferred to them as a condition of article posting.


问:
Throwing an exception if some property is not present in a properties file
it's not a big programming problem, but I'm curious if it should be done better. So I have a config file which I'm reading via java.util.Properties class. When property is not present in a file getProperty() method returns null. I would like to throw an exception if any property is not present in config file. So how should I do it?

Two ideas comes to mind, but I think there should be other way to do it. The first is that after every call of getProperty() I would do if (prop == null) throw new SomeException, but it wouldn't look nice if there would be identical ifs after every two lines. Second approach is to make one big if after all properties are read and just check them all at once.

答:
The best solution would be to build a class Configuration which you initialize with either the location of the properties file, or a properties object, and then gets all the information it needs from that in the constructor, and throw an exception if it can't find the necessary information (or use a default value if you can use one).

This has the benefit that after startup, you know that you have all the values you need, and never have to check again. No need to spread the if statements all over your code.

Also, if you use defaults, you have them in one place, even if you use the setting in multiple places. Nice and DRY.

The not-null checking can be a utility notNull(value, message) method which returns value, allowing you to reduce if-statements.

Down-side: you end up with a God-object knowing all configuration names. This again can be solved by instantiating different SubComponentNameConfiguration objects for the specific sub-components.

PS: the real fun happens when certain properties mean "read some specific configuration from file at location value"


问:
Advantages of using .dll files over linking .cs files to projects (for my own generic helper classes / extension methods)
I have a helper project which I use in all the applications that I create. It contains some extension methods and a bunch of generic helper classes, controls etc. I update/extend the helper project from time to time. These are usually small and unrelated projects, and I am the only person working on all of them.

I tried two approaches for using it

add .cs files directly (Add as link) to each project where I use them

compile it as .dll and add it as reference

I see some benefits and drawbacks of these approaches.

The first one:

is simpler, because the helper classes get compiled into the exe file, therefore I can often very easily provide just a single .exe file that will work just fine. Because I add as link, I can be pretty sure that whenever I build any project that uses the helper, the helper files will be the latest version.

is even simpler, because I can separate the files, so that my extension methods that run fine on .NET 4.0 can be referenced separately from the ones that require .NET 4.5, which means that the app as a whole can run on .NET 4.0

Allows to debug through the code, with all the benefits of breakpoints etc etc...

doesn't seem to be 'best practice'

The second one:

appears to be the right approach, but:

requires me to deliver a separate .dll file, which for some reason is much more difficult for users (they tend to share my programs without the .dll, which then crashes on startup)

as it gets compiled into a single .dll, it will require the highest version of .NET - many of my users don't have .NET 4.5 and only some elements of my helper class require this, which means I can be forcing some people to update their systems for no reason

I also need to make sure that whenever I update any of my programs, I also deliver the .dll file - even though I don't know if it has been changed since the last version, or not (it could have been, but it could as well be the same version). I cannot see a simple way to determine that, without keeping track of assembly version, which is additional work. For now, when I update my programs, I only deliver updated exe, and I like to keep it small and low profile.

So, what is the actual benefit for using the .dll file here? Please note, that I am the only person editing code of all the applications and the helper files.

Also, to clarify - the apps are usually very little, whereas the code contained in the helper classes is completely generic to all of them (some simple string-comparison, paths or XML operations etc)

Actually, someone made me realize just now that there's a third option.
As I have the helper code in a separte project, I can add this project to solutions of each of my separate applications - which works kind of like 'Add as link' for single files, except I only add a single project...
But as noticed by Doc Brown, this essentially means that .dll will need to be added to the project anyway...

Yet another thing which is kind of in favour of not using the dll files is the ability to debug through the helper class actively...

答:
Your third option is the most appropriate (add it as a separate "class library" project to the solution). This combines the benefits of all approaches:

Your "helper project" is always up to date on all different projects.

You can reference the code of the project when you want to quickly see changes.

You can build it for the correct .NET version each time.

You can embed a DLL in an exe anyway, so don't worry about that you can just have that as part of your build.

We do this all the time and I can't do anything but recommend this approach.

Another fourth alternative you have not mentioned is to put it on a private NuGet repository which would let you version it correctly and reference it without the extra project in each solution.


问:
I feel stuck in the center of Python, How to get past beginner
I really apologize if this doesn't follow the S.O rules but I need a little help, I personally still classify myself as a beginner in python, Yet I've wrote a very small and VERY SURE impractical program for my boss to use.

I know I'm still a beginner because simple things still perplex me but every book I read for beginners honestly just rehashes what I do already know but every 'more advanced' book doesn't really allow me to learn, they depend on example files and I never really understand why they built 'said' function or 'said' class. So onto my question...

Is there any recommendations on a book or ANYTHING that pushes me out of this stage, I've used head first and normally they are really good but my issue there is they have me back tracking just to move forward again, It worked in HTML but its confusing in Python, basically I think I need to build a program while following along, Again I like HeadFirst's style but I need something that isn't going to make me have to remember one thing just to forget it...

for record, I've checked into some O'Reilly books

答:
Try the book "Hello World! Computer Programming for Teens and Other Beginners" by Warren and Carter Sande is how I learned Python Scripting, or I've heard "Hello! Python" by Anthony Briggs is also a fantastic book. </p>

<p>Focus on organizing your programs with functions, comments, and some sort of structure to how it flows. Don't forget: A Program is simply a set of instructions the computer follows. Make it easy to read and understand. </p>

Body:
Try the book "Hello World! Computer Programming for Teens and Other Beginners" by Warren and Carter Sande is how I learned Python Scripting, or I've heard "Hello! Python" by Anthony Briggs is also a fantastic book.

Focus on organizing your programs with functions, comments, and some sort of structure to how it flows. Don't forget: A Program is simply a set of instructions the computer follows. Make it easy to read and understand.


问:
What are you telling yourself if you can't understand new concept, paradigm, feature ...?
Programming always required to learn new concepts, paradigms, features and technologies and I always have been failed at first attempt to understand new concept what i encounter. I start to blame and humiliate myself without remember before how i understood new concept which i hadn't understand it before.

I can hardly stop to tell myself "why i cant understand ? Am i stupid or idiot ? Yes, i am stuppiiddddd!!!"

What your inner voice tells if you can not understand new concept after spend long time till been tired or hopeless ?

How do you handle your self-esteem in such situations ?

答:
This is more a question of psychology than programming.  When Freud spoke of defense mechanisms, this is essentially what he was talking about:  mechanisms that protect your self-image when it is threatened.  Some of them are considered more mature and healthy than others.

Some of the defense mechanisms you want to avoid (and that come up frequently in my experience):

rationalization - "I can't understand this concept because it is just too complex."

idealization - "The people who came up with this concept are just so much smarter than me.  I can't understand it no matter how hard I try."

projection - "The people who came up with this concept just don't know enough about the subject matter to make the concept any good."

reaction formation - "I'm just too smart for this."

Rationalization is one that I especially see a lot in programmers.  We have a tendency to assume that not understanding something means that it is complex, which isn't necessarily true.

That said, here are some of the more healthy defense mechanisms that work for me:

altruism - Once you've mastered the concept, write a blog post about it to explain it to others or explain it to your team.  Using your struggles to help others is a good self-image booster.

humor - Make jokes about your problems.  This makes the concepts seem less threatening without avoiding them altogether.

identification - Find someone you think is really good at this and model your approach on theirs.

anticipation - Budget time to learn concepts in advance so that you don't have to rush yourself into understanding them.

sublimination - Channel your thoughts into more positive ones.  Start exercising or pick up a new hobby.

thought suppression - Whenever you find yourself saying "I'm so stupid..." suppress that thought and move back to the subject at hand.  This is surprisingly effective.


问:
read file bytewise and find information
i am a hobby php-dev and have the following problem:

i have a rar-file, whose header is damaged, therefor extracting is not fully possible. the contents are non-compressed, and can be read with eg. a hex-editor. the archive contains jpeg-files, but because of the damaged header, some of them are not extractable in winrar. i have tried repairing, but a good portion of the file remains broken.

i want to read the file in, and look for the bytes that indicate start and end of a jpeg (from what i know they are FFD8FF for start and FFD9FF for end). using a hex-editor i have managed to find some of those bytes, and also extracting the image into a file and view it does work. since the file is 500mb, i want to do this automatically, and since i am php-friendly, i would like to do it there :-)

i know how to read a file bytewise (fread), what i am having difficulties is, parsing the file correctly in hex, so i can identify the starts and ends. what i am thinking about is something like this (in pseudocode):

```<code>while( READ FILE UNTIL EOF ){
    if( CURRENTBYTES == FFD8FF ){
        $jpeg_file = READ FILE UNTIL CURRENTBYTES == FFD9FF
        fwrite($jpeg_file, "xyz.jpg");
        // return to while, looking for next FFD8FF
    }
}
</code>```

could someone give me a hint, how the reading and identifying would be done best? the main question is, how can i read a file until a start-byte, then save the following, then look for the next start-byte? efficiency, security, code beauty are no concern, i just want all the pics :-)

many thanx for any helps

答:
Since efficiency is no concern, and 500mb is not that large anymore, the simplest option would be:

read the file into string $blob (hint: file_get_contents).

get each separate part into an array $parts. Ugly solution: preg_match_all('/\xff\xd8\xff(.*?)\xff\xd9\xff/', $blob, $matches), and inspect the shape of the list $matches afterwards.

safe each $part in a separate file, by for instance using the md5sum of the file as filename. (md5sum ought to be good enough for this)

This should be enough I suppose.

Title: read file bytewise and find information


问:
CakePHP - Element Overkill
While implementing a flash game portal I decided to "component-ize" my views.  The repeating elements were a no brainer and the templates for these were placed in elements.  I pass through data from the controller to the element via the view using the Html helper.

This is all working fine, and except for a very minor subset of elements, I haven't had too many issues with complicated logic in the view in order to massage parameters - in other words they have all been completely pass-through and therefore very transparent to the elements.

Here-in lies my problem.  I realize I have over 20 elements which far eclipses my paltry 8-10 views and 3 controllers.  I've also had the urge to turn almost everything into a "component" and convert it into an element.  For example, I have a rating control that is used on only one page - the game play page - and I recently contemplated converting it to an element.  I'm wondering if I've gone overboard at this point.

So, in summary, my question boils down to what are the best practices when using the CakePHP Html helper and what makes a chunk of html a candidate for an element (aside from the the obvious of only writing it once).  I've read the cakePHP manual and it gives "rough" guidelines but I'm looking for some "field level" or real world experience to guild my decisions.

TIA

答:
You're on the right track. Typically you will want to use an Element either to cleanup a code and reduce the amount of HTML or to create a re-usable code segment.

I will assume you are using CakePHP3, which also has View Cells. View Cells are essentially an Element with a mini-controller. This will help also reduce the code within your parent controllers and allow the Cells to be reused as well.

In my experience, if there is no logic required an Element is the way to go, when logic is required, I use Cells.

You can learn more about the difference in the CakePHP manual. I have included two references, one to Elements and one to Cells.

Elements:
http://book.cakephp.org/3.0/en/views.html#elements

Cells:
http://book.cakephp.org/3.0/en/views/cells.html

Title: CakePHP - Element Overkill


问:
How does this example from Robert Martin's book violate the Single Responsibility Principle?
According to the book "Clean Code" on page 38, the following lines of code violate the single responsibility principle. However, I cannot understand how there are "multiple" reasons for it to change?

```<code>public Money CalculatePay(Employee e)
throws InvalidEmployeeType {
    switch (e.type) {
        case COMMISSIONED:
            return calculateCommissionedPay(e);
        case HOURLY:
            return calculateHourlyPay(e);
        case SALARIED:
            return calculateSalariedPay(e);
        default:
            throw new InvalidEmployeeType(e.type);
    }
}
</code>```

It seems to me that the purpose of this class is singular: to calculate the pay of commissioned, hourly, or salaried employees--and these three functions are at the same level of abstraction and one level below the top-most CalculatePay(). Is he referring to the fact that more employee types might be added?

答:
There are five concerns here:

Determine which type of pay to calculate.

Calculate commissioned pay.

Calculate hourly pay.

Calculate salaried pay.

Validate the employee type.

What might compel us to modify the class containing this method?

Perhaps we add a new type of employee. Now we need to add new calculation logic.

Perhaps we modify an existing type of employee. Now we need to modify an existing employee type's logic.

Multiple types of employees have their calculations in the same class. Each type of employee is a reason for this class to change. Hence, it violates the Single Responsibility Principle.

Moving each pay type to its own class (think: Strategy pattern) would localize the reasons to change to one class per employee type, giving each one reason to change.

Finally, using dynamic dispatch to select the pay calculation further separates the concerns by offloading the selection and validation logic itself to the compiler.


问:
Time complexity of update and lookup in binary random access list
I'm trying to get through one of the exercises in Okasaki's "Purely Functional Data Structures," where he presents a zeroless binary numbers as a structure for random-access list, and asks to

9.6 Show that lookup and update on element i now run in O(log i) time.

"now" here contrasts zeroless representation with a plain binary tree backed random access list, for which the lookup and update time was estimated as O(log n).

The approach in both cases similar: we maintain a Cons list of "digits", with every non-zero digit containing a tree of size corresponding to the digit's weight. The list as a whole is a binary (or a zeroless binary) representation of the number of elements in the list.

For example, a list of 6 elements, [1, 2, 3, 4, 5, 6] (binary for 6 is 111, zeroless binary is 22) will look as

```<code>[
  Zero,
  One(Node(Leaf(1), Leaf(2)),
  One(Node(Node(Leaf(3), Leaf(4)), Node(Leaf(5), Leaf(6))))
]
</code>```

in binary, or

```<code>[
  Two(Leaf(1), Leaf(2)),
  Two(Node(Leaf(3), Leaf(4)), Node(Leaf(5), Leaf(6))
]
</code>```

in zeroless binary representation. Now, the lookup and update times are defined by the time you spend locating the tree with the i-th element, and by the time you spend navigating that tree.

What I don't get is why loookup of i th element in a binary random access list takes O(log n) rather than O(log i)? We need to locate the tree containing the i th element — that's O(log i), navigation within the tree is capped by O(log w), where w is the size of the tree, which is clearly less than i*2.

What do I miss?

答:
Well, compliments to @snowman for the advice to rewrite the question in plain English — I came up with an answer while doing that.

The O(log n) boundary comes from the way binary numbers work: they have zeroes. For instance, a binary for 8 is 100, or, reversed, 001. So the binary random access list of 8 elements (e.g. [1, 2, 3, 4, 5, 6, 7, 8]) will have the following structure:

```<code>[
  Zero,
  Zero,
  One(
    Node(
      Node(
        Node(Leaf(1), Leaf(2)),
        Node(Leaf(3), Leaf(4))
      ),
      Node(
        Node(Leaf(5), Leaf(6)),
        Node(Leaf(7), Leaf(8))
      )
    )
  )
]
</code>```

Here, it's clear that any element will take exactly 2 log n steps to get to (if you don't trust me on this one, play with n = 2^k, e.g. 256, 1024, 65536...). So the premise that "We need to locate the tree containing the i th element — that's O(log i), navigation within the tree is capped by O(log w), where w is the size of the tree, which is clearly less than i*2" was basically all wrong: the size of the tree does not depend on the element's index, and the position of the tree is dictated by the bits of n, not i.

In zeroless numbers, on contrary, we always have at least one tree of each possible size, so we can be sure that the tree will indeed be located in O(log i), and its size will be not more than 2i.

Body:
Well, compliments to @snowman for the advice to rewrite the question in plain English — I came up with an answer while doing that.

The O(log n) boundary comes from the way binary numbers work: they have zeroes. For instance, a binary for 8 is 100, or, reversed, 001. So the binary random access list of 8 elements (e.g. [1, 2, 3, 4, 5, 6, 7, 8]) will have the following structure:

[
  Zero,
  Zero,
  One(
    Node(
      Node(
        Node(Leaf(1), Leaf(2)),
        Node(Leaf(3), Leaf(4))
      ),
      Node(
        Node(Leaf(5), Leaf(6)),
        Node(Leaf(7), Leaf(8))
      )
    )
  )
]

Here, it's clear that any element will take exactly 2 log n steps to get to (if you don't trust me on this one, play with n = 2^k, e.g. 256, 1024, 65536...). So the premise that "We need to locate the tree containing the i th element — that's O(log i), navigation within the tree is capped by O(log w), where w is the size of the tree, which is clearly less than i*2" was basically all wrong: the size of the tree does not depend on the element's index, and the position of the tree is dictated by the bits of n, not i.

In zeroless numbers, on contrary, we always have at least one tree of each possible size, so we can be sure that the tree will indeed be located in O(log i), and its size will be not more than 2i.


问:
In a "Revisional Data Model," where does code that preserves a previous record's state belong?
When I say "Revisional Data Model", I mean a data model where information is never lost: Deletes never destroy any rows, and updates always cause an insert somewhere else to preserve a row's previous state before the update.

There are a few I've read about, and heard from colleagues:

Triggers in the database. The main reason why I don't like this approach is because if you depend on triggers to enforce revision integrity, the application becomes tied to the database server. If using an ORM with different providers (Oracle, MySQL, T-SQL, etc), you may need to alter some SQL to switch between them.

Human-readable trace logs. Last year I played Business Analyst for a project with a new developer because one of our sister departments was slammed with important deadlines.  She insisted that, despite the requirements I gathered and the schemas I modeled, she would insert a stored procedure to be executed with each create/update/delete statement. This sproc would just write out the old data as a formatted string, and save it to a ERRORS_LOG table in the database. Her goal was to help her with debugging the application in case anything went wrong: she wanted a trace.

Creating sister tables. This approach is like having 2 databases living in the same context. For the table Person there would be a PersonHistory table, for Product there would be ProductHistory, and so on. The schemas would be identical, and each time a change happened in the entity table, the previous state would be inserted into ProductHistory.

If you have an application where you want to allow users to "undelete" or "restore previous version" of an entity, only #3 seems like a workable solution. However, since each pair (entity and its history) have the same model/schema, they can in fact be combined. By adding bool/bit properties like IsCurrentVersion and IsDeleted, you can slice a single entity set into different states within the WHERE clause. Consider this example #4.

One disadvantage of #4 is that the database tables become hard to read when you select all rows. Mining data from a db server ide would require pretty extensive use of views, which causes the same problem as in option #1. Looking at all of the different states together in the same table makes it much more difficult to read. With approach #3, you need to look in a different table to find previous versions & deletes.

We've been using approach #4 with success. We have a RevisableEntity supertype with properties that indicate when data was changed, who changed it, whether it was deleted, archived, or modified. Updates occur on rows just as they would under normal circumstances. However as part of the same action, a corresponding insert is made into the same table / entity set. The insert contains the same values as the update before it was updated. The updated row, in addition to whatever changes were made by the user, also updates the when and who properties.

Now for my question: Where does this code belong? In the domain, or in the repository implementation? There are certain aspects of this that are storage dependent, which hint at putting the code where your ORM coupling is. However there are other aspects that the domain / application layers should be able to trust. Maybe the domain entities should manage their own revisional integrity, or maybe there should be a factory to coordinate?

答:
First, to answer to your question: To which layer does that code belong?

I would go with the layer of your actual code repository and not your database (procedures, events, etc). That think looks for me to be a business logic, and is good to keep all the business logic in the same layer (now, we talk about the code layer vs database layer)

How  will I do it?

Do you really need to keep your historical data in the same way? normalized?

You could have a single table  like this

id

table_pm_key

table

serialized object (you  may define what ever means that: attributes, relationships)

revision_id

revision_data

last_mark - optional

parent_revision  -optional

In your ORM code, you could listen for update/delete on tables you want, and add automatically to this table


问:
How does Functional Programming's immutability feature work with CQS?
Given immutability (which is often encouraged and said to be one of building blocks of functional programming) and CQS (which says that commands should not return a value other than void/unit), how do these work together?

For example:

How would you perform a series of commands (eg multiple file copies, which can throw all kinds of exceptions but should not crash the program), and collect their success or failure+reason in a list of results?

I can imagine some solutions in OO like throwing events or giving access to a Report instance (either static or passing it in by reference), but what are the possibilities in functional languages which do not break CQS?

答:
In Haskell, commands are first-class values.  Consider the copyFile function from the System.Directory module.  Its signature is this:

```<code>copyFile :: FilePath -> FilePath -> IO ()
</code>```

copyFile is a function that takes two FilePaths as its arguments, and returns a command (type IO ()).  This command, when executed, copies the file from the first location to the second one.  So note that:

The function does not copy the file.  It just returns a command.

Evaluating an expression and executing a command are different things in Haskell.

Haskell is so command oriented that it has commands instead of statements or blocks.  It is so command-oriented that an executable Haskell program is a a command, written in Haskell, that the compiler translates to object code.

Since commands are first-class values, you can make a list of commands.  Suppose you have a list of source/destination pairs:

```<code>locations :: [(FilePath, FilePath)]
locations = [("source1", "dest1"), ("source2", "dest2"), ...]
</code>```

Using map you can turn this into a list of commands that copy the files:

```<code>copyCommands :: [IO ()]
copyCommands = map (\(from, to) -> copyFile from to) locations
</code>```

And Haskell has standard functions for building complex commands out of lists of commands; for example, the sequence_ function that will convert a list of commands into a command that executes the contents in sequence.

```<code>copyFiles :: [(FilePath, FilePath)] -> IO ()
copyFiles = sequence_ . map (\(from, to) -> copyFile from to)
</code>```

Or, written idiomatically:

```<code>copyFiles :: [(FilePath, FilePath)] -> IO ()
copyFiles = for_ (uncurry copyFile)
</code>```

That uses two standard utility functions:

```<code>for_ toAction values = sequence_ (map toAction values)

uncurry f (a, b) = f a b
</code>```

That's not yet what you want, however, because:

It doesn't collect the errors that happen during file copies;

It will quit copying files when the first one fails.

But that's easy to fix.  First we write a wrapper around copyFile that catches its exceptions and wraps the result in an Either type (using tryIO from Control.Error.Util to catch the exceptions, and runExceptT to unwrap it from the monad transformer):

```<code>tryCopyFile :: FilePath -> FilePath -> IO (Either IOException ())
tryCopyFile from to = runExceptT (tryIO (copyFile from to))
</code>```

And now given a list of (from, to) pairs, we can just use the standard traverse function to construct a command that, when executed, executes the individual commands and the list of our their results (failures and successes):

```<code>tryCopyFiles :: [(FilePath, FilePath)] -> IO [Either Exception ()]
tryCopyFiles = traverse (uncurry tryCopyFile)
</code>```

Note the type IO [Either IOException ()]; this is the type of commands (IO ...) that, when executed, produce a list ([...]) whose elements are either an IOException or unit.

So the answer is that, once you get past the very steep learning curve, it's really easy.

Body:
In Haskell, commands are first-class values.  Consider the copyFile function from the System.Directory module.  Its signature is this:

copyFile :: FilePath -> FilePath -> IO ()

copyFile is a function that takes two FilePaths as its arguments, and returns a command (type IO ()).  This command, when executed, copies the file from the first location to the second one.  So note that:

The function does not copy the file.  It just returns a command.

Evaluating an expression and executing a command are different things in Haskell.

Haskell is so command oriented that it has commands instead of statements or blocks.  It is so command-oriented that an executable Haskell program is a a command, written in Haskell, that the compiler translates to object code.

Since commands are first-class values, you can make a list of commands.  Suppose you have a list of source/destination pairs:

locations :: [(FilePath, FilePath)]
locations = [("source1", "dest1"), ("source2", "dest2"), ...]

Using map you can turn this into a list of commands that copy the files:

copyCommands :: [IO ()]
copyCommands = map (\(from, to) -> copyFile from to) locations

And Haskell has standard functions for building complex commands out of lists of commands; for example, the sequence_ function that will convert a list of commands into a command that executes the contents in sequence.

copyFiles :: [(FilePath, FilePath)] -> IO ()
copyFiles = sequence_ . map (\(from, to) -> copyFile from to)

Or, written idiomatically:

copyFiles :: [(FilePath, FilePath)] -> IO ()
copyFiles = for_ (uncurry copyFile)

That uses two standard utility functions:

for_ toAction values = sequence_ (map toAction values)

uncurry f (a, b) = f a b

That's not yet what you want, however, because:

It doesn't collect the errors that happen during file copies;

It will quit copying files when the first one fails.

But that's easy to fix.  First we write a wrapper around copyFile that catches its exceptions and wraps the result in an Either type (using tryIO from Control.Error.Util to catch the exceptions, and runExceptT to unwrap it from the monad transformer):

tryCopyFile :: FilePath -> FilePath -> IO (Either IOException ())
tryCopyFile from to = runExceptT (tryIO (copyFile from to))

And now given a list of (from, to) pairs, we can just use the standard traverse function to construct a command that, when executed, executes the individual commands and the list of our their results (failures and successes):

tryCopyFiles :: [(FilePath, FilePath)] -> IO [Either Exception ()]
tryCopyFiles = traverse (uncurry tryCopyFile)

Note the type IO [Either IOException ()]; this is the type of commands (IO ...) that, when executed, produce a list ([...]) whose elements are either an IOException or unit.

So the answer is that, once you get past the very steep learning curve, it's really easy.


答:
Whether a dll is more beneficial or not depends on several factors:

The size of the code (when compiled).

How many exes use it.

How often you intend to update the code.

Whether or not the exes are intended to be kept together or exist
completely seperately.

The purpose of a shared library is to take code that is common to multiple executables and centralise it so that all executables share a copy. This is intended to save space and make code easier to update.

If the amount of code in your helper class is very small, it may not be worth moving it to a dll as the overhead of the code being in a dll may counteract the space saving benefit of having it centralised.

Additionally, if you're only making a few executables, the size of the code in each executable may be small enough to not be an issue. However, the more executables you have using the same code, the more beneficial it would be to have the code moved into a dll.

As a simplified example, say your helper class compiles to 128 bytes in an exe file, but when moved to a dll, the dll is 512 bytes. If you only have 3 executables, you would be saving space by including the code in the executables. However if you had 5 executables, you would then be at the point where you would be better off having a dll because the combined space taken up by 5 copies of the code (5 * 128 = 640 bytes) is more than the space taken up by having the code in a dll (512 bytes).

Now say for example you find a bug in your helper code. If you compiled all your executables with the code baked in, you have to recompile every single executable and then redistribute the recompiled versions. If you compiled the code to a dll, you would only have to recompile and redistribute the one dll, and the bug would automagically be fixed for all of the executables using it.

Lastly, for a program to find a dll it has to know where to look for the dll. If you are keeping all your executables together, you can just put the dll in the same directory and they'll all find it straight away. If you're intentionally keeping them separated, it becomes harder to coordinate them to use the same dll.


问:
Parallelism implies concurrency but not the other way round right?
I often read that parallelism and concurrency are different things. Very often the answerers/commenters go as far as writing that they're two entirely different things. Yet in my view they're related but I'd like some clarification on that.

For example if I'm on a multi-core CPU and manage to divide the computation into x smaller computation (say using fork/join) each running in its own thread, I'll have a program that is both doing parallel computation (because supposedly at any point in time several threads are going to run on several cores) and being concurrent right?

While if I'm simply using, say, Java and dealing with UI events and repaints on the Event Dispatch Thread plus running the only thread I created myself, I'll have a program that is concurrent (EDT + GC thread + my main thread etc.) but not parallel.

I'd like to know if I'm getting this right and if parallelism (on a "single but multi-cores" system) always implies concurrency or not?

Also, are multi-threaded programs running on multi-cores CPU but where the different threads are doing totally different computation considered to be using "parallelism"?

答:
Parallelism simply means doing many tasks simultaneously; on the other hand concurrency is the ability of the kernel to perform many tasks by constantly switching among many processes.

In order to achieve parallelism it is important that system should have many cores only then parallelism can be achieved efficiently. And there is lot of hit on performance and lot of overhead is incurred if parallelism is tried on a single core machine.

For example, earlier system had only one core and CPU schedulers would give an illusion of parallelism by constantly switching between processes allowing each process to make progress.


问:
How is possible for a program to write on the same line?
Many programs are capable to "rewrite" on the same line, not in a STDOUT way.

For example scp write the percentage or many installation programs will show you the nice rotating wheel.

How it works?

答:
They use a console handling library like ncurses or use \b or \r escape sequences to do it

More info:

https://stackoverflow.com/questions/656504/how-to-overwrite-stdout-in-c

https://stackoverflow.com/questions/517127/how-do-i-write-output-in-same-place-on-the-console

https://stackoverflow.com/questions/465348/how-can-i-print-over-the-current-line-in-a-command-line-application/465360#465360


答:
Assuming that you are talking about console programs, and not progress dialogs in a GUI, the effect of overwriting the last line can be achieved with STDOUT and with just about any console.

Most consoles support the "carriage return" character, which brings the current output position to the beginning of the current line, without otherwise altering what is shown on the console. In most programming languages, this character is represented by the escape sequence \r.

When producing output with carriage return characters in it, the text after a carriage return will overwrite the last line that was written before it.

If you redirect the output the ouput from a program like scp (that produces a progress indication) to a file, then in many cases the file will look similar to this (using the escape sequence for the carriage return character):

```<code> 10%\r
 20%\r
 30%\r
 40%\r
 50%\r
 60%\r
 70%\r
 80%\r
 90%\r
100%\r
\n
</code>```

Title: How is possible for a program to write on the same line?

Body:
Many programs are capable to "rewrite" on the same line, not in a STDOUT way.

For example scp write the percentage or many installation programs will show you the nice rotating wheel.

How it works?

Body:
Assuming that you are talking about console programs, and not progress dialogs in a GUI, the effect of overwriting the last line can be achieved with STDOUT and with just about any console.

Most consoles support the "carriage return" character, which brings the current output position to the beginning of the current line, without otherwise altering what is shown on the console. In most programming languages, this character is represented by the escape sequence \r.

When producing output with carriage return characters in it, the text after a carriage return will overwrite the last line that was written before it.

If you redirect the output the ouput from a program like scp (that produces a progress indication) to a file, then in many cases the file will look similar to this (using the escape sequence for the carriage return character):

 10%\r
 20%\r
 30%\r
 40%\r
 50%\r
 60%\r
 70%\r
 80%\r
 90%\r
100%\r
\n


问:
When is the best time to compute rating changes in a PHP application?
Imagine a simple PHP application where an user can post notes and the other users can upvote or downvote them.

We want to implement a system where each note has a different rating (normal, good, great ...) based on the number of upvotes and downvotes it has.

My question is: When should I handle these rating changes?

My first idea was to check every time an user votes on a note if the vote doesn't change it's rating (e.g. from normal to good) but considering that voting on notes will be one of the most frequently used features on our site, it might slow down the site a lot.

We could also implement a cron job which fires every, let's say, half an hour and checks if the number of votes on every note corresponds to its rating but I suppose that would be a waste of our resources since most of the notes might not have been voted on during that time interval.

答: I would suggest, if you have the capability to daemonize processes on your server, that the best way of doing this would be to include in the 'Notes' object itself the business rules of ratings changes, to notify a message queue service (such as rabbitmq) when ratings change, and consume the message queue in the daemonized service in order to notify users that their note has a changed rating. This will allow you to keep individual vote request response times snappy and deal with the notification asynchronously.</p>


问:
Cross application cookie access
It was my understanding that cookies are transferred with each subsequent http request, yet if I log in to a web application that uses cookie authentication, say on my browser, other applications on the same machine don't seem to send these previous cookies with their requests to the same address. Is my understanding of cookies incorrect?

答:
Cookies are transferred "with each subsequent http request", on that browser. Cookie storage is browser-specific.

Unless browsers choose to share their cookie cache somehow, or read those of other applications (which would brand them as malware pretty quickly), they only know of the cookies set in that browser

Title: Cross application cookie access


问:
MVP / MVC role of the Model (not anemic one) clashes with presenter / controller role (responsibilities in the right place, Model OR Presenter)?

Problem?

I have been looking at MVP implementation and process to design a good domain model (not anemic). It says that the domain model should have its own behavior and not being a simple data model (like DTO).

In my case (my application), it turns out that controllers architecture is following the model architecture (player model, player controller, game model, game controller, ...). So I think my model is anemic because my model objects does not contains references to other models objets, they define a lot of accessors methods (get & set) and finally their core methods only modify their own object properties.

How do I integrate a Model handling business logic into MVP architecture? And who should manage which kind of action? Does the presenter architecture have to follow the model architecture? Should a presenter only have access to a part of the model or all of them? Does the presenter have to listen to model modification and react accordingly? Any concret resource on the net with examples?

Solution?

Create a structured Model with inheritance and behavior. Link related model objects (like collections, property of another model object, ...). Finally listen to model events modification into controllers for sending requests onto network.

But, in that case, the role of the controller is very small, because the model handle almost every modification itself. Isn't it better to "flatten" the model hierarchy, so they are not dependency between each others ?

I am confused.

Here is an example of my current app architecture

In the following cases, I think the model is anemic.

Context: In multiplayer game application over network. Let's say we have two players with a certain amount of balls that they have to throw into a barrel (players have their own barrel each). Its a turn based game.

So the domain model would be (properties are not typed):

Game (playerTurn)

Player (name, score, number of balls thrown)

Ball (color, weight)

Barrel (distance, points, list of balls thrown into)

In the MVP representation, I would create three Presenters:

GameController

PlayerController

BarrelController

Example of use

Use case n°1: The player (real one) throws a ball

In resume, player throws a ball. Event is dispatched to GameController which validate action over network and responds back by delegating event to each specific controller.

code for generating (and modify) diagramm ()

```<code>View -> PlayerController : onThrowBall()
PlayerController -> GameController : onPlayerThrowsBall()
GameController -> GameModel : isTurn()
GameModel --> GameController : true
GameController -> Network : onPlayerThrowsBall()
Network --> GameController : true
GameController -> GameModel : updateTurn(player)
GameController -> PlayerController : throwBall()
PlayerController -> PlayerModel : updateBallThrownCount()
PlayerController -> View : update()
</code>```

Use case n°2: The thrown ball fall into the barrel

Same principe, action is dispatched for validation (and perform potential related action into parent controllers). Finally, barrel is updated by BarrelController (add ball) and player model is updated by PlayerController (update score).

code for generating (and modify) diagramm ()

```<code>View -> BarrelController : onBallFallIntoBarrel()
BarrelController -> PlayerController : onBallFallIntoBarrel()
PlayerController -> GameController : onBallFallIntoBarrel()
GameController -> GameModel : isTurn()
GameModel --> GameController : true
GameController -> Network : onPlayerThrowsBallIntoBarrel()
Network --> GameController : true
GameController -> GameModel : updateTurn()
GameController -> PlayerController : throwBallIntoBarrel()
PlayerController -> BarrelController : throwBallIntoBarrel()
BarrelController -> BarrelModel : addBall()
PlayerController -> PlayerModel : updateScore()
PlayerController -> View : update()
</code>```

答:
You are looking for Domain Driven Design.

Domain-driven design (DDD) is an approach to developing software for complex needs by deeply connecting the implementation to an evolving model of the core business concepts.

This is the opposite of Anemic Domain Model.

Check out Crafting Wicked Domain Models for a more hands on example.


问:
Should I create a class if my function is complex and has a lot of variables?
This question is somewhat language-agnostic, but not completely, since Object Oriented Programming (OOP) is different in, for example, Java, which doesn't have first-class functions, than it is in Python.

In other words, I feel less guilty for creating unnecessary classes in a language like Java, but I feel like there might be a better way in the less boilerplate-y languages like Python.

My program needs to do a relatively complex operation a number of times.
That operation requires a lot of "bookkeeping", has to create and delete some temporary files, etc.

That's why it also needs to call a lot of other "suboperations" - putting everything into one huge method isn't very nice, modular, readable, etc.

Now these are approaches that come to my mind:

1. Make a class that has one public method only and keeps the internal state needed for the suboperations in its instance variables.

It would look something like this:

```<code>class Thing:

    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
        self.var3 = []

    def the_public_method(self, param1, param2):
        self.var4 = param1
        self.var5 = param2
        self.var6 = param1 + param2 * self.var1
        self.__suboperation1()
        self.__suboperation2()
        self.__suboperation3()

    def __suboperation1(self):
        # Do something with self.var1, self.var2, self.var6
        # Do something with the result and self.var3
        # self.var7 = something
        # ...
        self.__suboperation4()
        self.__suboperation5()
        # ...

    def suboperation2(self):
        # Uses self.var1 and self.var3

#    ...
#    etc.
</code>```

The problem I see with this approach is that the state of this class makes sense only internally, and it can't do anything with its instances except call their only public method.

```<code># Make a thing object
thing = Thing(1,2)

# Call the only method you can call
thing.the_public_method(3,4)

# You don't need thing anymore
</code>```

2. Make a bunch of functions without a class and pass the various internally needed variables between them (as arguments).

The problem I see with this is that I have to pass a lot of variables between functions. Also, the functions would be closely related to each other, but they wouldn't be grouped together.

3. Like 2. but make the state variables global instead of passing them.

This would be no good at all, since I have to do the operation more than once, with different input.

Is there a fourth, better, approach? If not, which one of these approaches would be better, and why? Is there something I'm missing?

答:
Why not compare your needs to something that exists in the standard Python library, and then see how that is implemented?

Note, if you don't need an object, you can still define functions within functions. With Python 3 there is the new nonlocal declaration to allow you to change variables in your parent function.

You might still find it useful to have some simple private classes inside your function to implement abstractions and tidying up operations.