问:
Parameter management in OOP application
I'm writing a medium size OOP application in C++ as a way to practice OOP principles.

I have several classes in my project, and some of them need to access run-time configuration parameters. These parameters are read from several sources during application start-up.  Some are read from a config file in the users home-dir, some are command line arguments (argv).

So I created a class ConfigBlock. This class reads all the parameter sources and stores it in an appropriate data structure. Examples are path- and filenames which can be changed by user in the config file, or the --verbose CLI flag. Then, one can call ConfigBlock.GetVerboseLevel() in order to read this specific parameter.

My question: Is it good practice to collect all such runtime config data in one class?

Then, my classes need access to all these parameters. I can think of several ways to achieve this, but I'm not sure which one to take. A class' constructor can be a given a reference to my ConfigBlock, like

```<code>public:
    MyGreatClass(ConfigBlock &config);
</code>```

Or they just include a header "CodingBlock.h" which contains a definition of my CodingBlock:

```<code>extern CodingBlock MyCodingBlock;
</code>```

Then, only the classes .cpp file needs to include and use the ConfigBlock stuff.

The .h file does not introduce this interface to the user of the class.
However, the interface to ConfigBlock is still there, however, it's hidden from the .h file.

Is it good to hide it this way?

I want the interface to be as small as possible, but in the end, I guess every class which needs config parameters has to have a connection to my ConfigBlock. But, what should this connection look like?

答:
Usually the configuration of an application is consumed primarily by factory objects. Any object relying on configuration should be generated from one of those factory objects. You could utilize the Abstract Factory Pattern to implement one class that takes in the whole ConfigBlock object. This class would expose public methods to return other factory objects, and would only pass in the part of the ConfigBlock relevant to that particular factory object. That way the config settings "trickle down" from the ConfigBlock object to its members, and from the Factory factory to the factories.

I'll use C# since I know the language better, but this should be easily transferable to C++.

public class ConfigBlock
{
    public ConfigBlock()
    {
        // Load config data and
        // connectionSettings = new ConnectionConfig();
        // connectionSettings...
    }

    private ConnectionConfig connectionSettings;

    public ConnectionConfig GetConnectionSettings()
    {
        return connectionSettings;
    }
}

public class FactoryProvider
{
    public FactoryProvider(ConfigBlock config)
    {
        this.config = config;
    }

    private ConfigBlock config;

    public ConnectionFactory GetConnectionFactory()
    {
        ConnectionConfig connectionSettings = config.GetConnectionSettings();

        return new ConnectionFactory(connectionSettings);
    }
}

public class ConnectionFactory
{
    public ConnectionFactory(ConnectionConfig settings)
    {
        this.settings = settings;
    }

    private ConnectionConfig settings;

    public Connection GetConnection()
    {
        return new Connection(settings.Hostname, settings.Port, settings.Username, settings.Password);
    }
}
```

<p>After that you need some sort of class that acts as the "application" that gets instantiated in your main procedure:</p>

```// Your main procedure (yeah I'm bending the rules of C# a tad here,
// but you get the point).
int Main(string[] args)
{
    Application app = new Application();

    app.Run();
}

public class Application
{
    public Application()
    {
        config = new ConfigBlock();
        factoryProvider = new FactoryProvider(config);
    }

    private ConfigBlock config;
    private FactoryProvider factoryProvider;

    public void Run()
    {
        ConnectionFactory connections = factoryProvider.GetConnectionFactory();
        Connection connection = connections.GetConnection();

        connection.Connect();

        // Enter into your main loop and do what this program is meant to do
    }
}
```

As one last note, this is known as a "provider object" in .NET speak. Provider objects in .NET seem to marry configuration data to factory objects, which is essentially what you want to do here.

See also Provider Pattern for Beginners. Again, this is geared towards .NET development, but with C# and C++ both being object oriented languages, the pattern should be mostly transferable between the two.

Another good read that is related to this pattern: The Provider Model.

Lastly, a critique of this pattern: Provider is not a pattern

Title: Parameter management in OOP application

Body:
Usually the configuration of an application is consumed primarily by factory objects. Any object relying on configuration should be generated from one of those factory objects. You could utilize the Abstract Factory Pattern to implement one class that takes in the whole ConfigBlock object. This class would expose public methods to return other factory objects, and would only pass in the part of the ConfigBlock relevant to that particular factory object. That way the config settings "trickle down" from the ConfigBlock object to its members, and from the Factory factory to the factories.

I'll use C# since I know the language better, but this should be easily transferable to C++.

public class ConfigBlock
{
    public ConfigBlock()
    {
        // Load config data and
        // connectionSettings = new ConnectionConfig();
        // connectionSettings...
    }

    private ConnectionConfig connectionSettings;

    public ConnectionConfig GetConnectionSettings()
    {
        return connectionSettings;
    }
}

public class FactoryProvider
{
    public FactoryProvider(ConfigBlock config)
    {
        this.config = config;
    }

    private ConfigBlock config;

    public ConnectionFactory GetConnectionFactory()
    {
        ConnectionConfig connectionSettings = config.GetConnectionSettings();

        return new ConnectionFactory(connectionSettings);
    }
}

public class ConnectionFactory
{
    public ConnectionFactory(ConnectionConfig settings)
    {
        this.settings = settings;
    }

    private ConnectionConfig settings;

    public Connection GetConnection()
    {
        return new Connection(settings.Hostname, settings.Port, settings.Username, settings.Password);
    }
}

After that you need some sort of class that acts as the "application" that gets instantiated in your main procedure:

// Your main procedure (yeah I'm bending the rules of C# a tad here,
// but you get the point).
int Main(string[] args)
{
    Application app = new Application();

    app.Run();
}

public class Application
{
    public Application()
    {
        config = new ConfigBlock();
        factoryProvider = new FactoryProvider(config);
    }

    private ConfigBlock config;
    private FactoryProvider factoryProvider;

    public void Run()
    {
        ConnectionFactory connections = factoryProvider.GetConnectionFactory();
        Connection connection = connections.GetConnection();

        connection.Connect();

        // Enter into your main loop and do what this program is meant to do
    }
}

As one last note, this is known as a "provider object" in .NET speak. Provider objects in .NET seem to marry configuration data to factory objects, which is essentially what you want to do here.

See also Provider Pattern for Beginners. Again, this is geared towards .NET development, but with C# and C++ both being object oriented languages, the pattern should be mostly transferable between the two.

Another good read that is related to this pattern: The Provider Model.

Lastly, a critique of this pattern: Provider is not a pattern


问:
Is 4-5 years the “Midlife Crisis” for a programming career?
I’ve been programming C# professionally for a bit over 4 years now. For the past 4 years I’ve worked for a few small/medium companies ranging from “web/ads agencies”, small industry specific software shops to a small startup. I've been mainly doing "business apps" that involves using high-level programming languages (garbage collected) and my overall experience was that all of the works I’ve done could have been more professional. A lot of the things were done incorrectly (in a rush) mainly due to cost factor that people always wanted something “now” and with the smallest amount of spendable money. I kept on thinking maybe if I could work for a bigger companies or a company that’s better suited for programmers, or somewhere that's got the money and time to really build something longer term and more maintainable I may have enjoyed more in my career. I’ve never had a “mentor” that guided me through my 4 years career. I am pretty much blog / google / self taught programmer other than my bachelor IT degree.

I’ve also observed another issue that most so called “senior” programmer in “my working environment” are really not that senior skill wise. They are “senior” only because they’ve been a long time programmer, but the code they write or the decisions they make are absolutely rubbish! They don't want to learn, they don't want to be better they just want to get paid and do what they've told to do which make sense and most of us are like that. Maybe that’s why they are where they are now. But I don’t want to become like them I want to be better. I’ve run into a mental state that I no longer intend to be a programmer for my future career. I started to think maybe there are better things out there to work on. The more blogs I read, the more “best practices” I’ve tried the more I feel I am drifting away from “my reality”. But I am not a great programmer otherwise I don't think I am where I am now. I think 4-5 years is a stage that can be a step forward career wise or a step out of where you are.

I just wanted to hear what other have to say about what I’ve mentioned above and whether you’ve experienced similar situation in your past programming career and how you dealt with it. Thanks.

答:
Here is a book:

Apprenticeship Patterns : guidance for the aspiring software craftsman / David H. Hoover, O’Reilly, 2010

If you are planning a career in Agile Software Development, then this book contains good advice. The foreword is by Ward Cunningham. See also the author’s site. 125 pages.

OwnerDisplayName: Jeff

ContentLicense: CC BY-SA 2.5

OwnerDisplayName: rleir


答:
First question: is it good practise to collect all such runtime config data in one class?

Yes. It is better to centralize runtime constants and values and the code to read them.

A class' constructor can be a given a reference to my ConfigBlock

This is bad: most of your constructors will not need most of the values. Instead, create interfaces for everything that is not trivial to construct:

old code (your proposal):

```<code>MyGreatClass(ConfigBlock &config);
</code>```

new code:

```<code>struct GreatClassData {/*...*/}; // initialization data for MyGreatClass
GreatClassData ConfigBlock::great_class_values();
</code>```

instantiate a MyGreatClass:

```<code>auto x = MyGreatClass{ current_config_block.great_class_values() };
</code>```

Here, current_config_block is an instance of your ConfigBlock class (the one that contains all your values) and the MyGreatClass class receives a GreatClassData instance. In other words, only pass to constructors the data they need, and add facilities to your ConfigBlock to create that data.

Or they just include a header "CodingBlock.h" which contains a definition of my CodingBlock:

```<code> extern CodingBlock MyCodingBlock;
</code>```

Then, only the classes .cpp file needs to include and use the ConfigBlock stuff. The .h file does not introduce this interface to the user of the class. However, the interface to ConfigBlock is still there, however, it's hidden from the .h file. Is it good to hide it this way?

This code suggests that you will have a global CodingBlock instance. Don't do that: normally you should have an instance declared globally, in whatever entry point your application uses (main function, DllMain, etc) and pass that around as an argument wherever you need (but as explained above, you should not pass the entire class around, just expose interfaces around the data, and pass those).

Also, don't tie your client classes (your MyGreatClass) to the type of CodingBlock; This means that, if your MyGreatClass takes in a string and five integers, you will be better off passing in that string and integers, than you will be passing in a CodingBlock.

ContentLicense: CC BY-SA 3.0

Title: Parameter management in OOP application

Body:
I'm writing a medium size OOP application in C++ as a way to practice OOP principles.

I have several classes in my project, and some of them need to access run-time configuration parameters. These parameters are read from several sources during application start-up.  Some are read from a config file in the users home-dir, some are command line arguments (argv).

So I created a class ConfigBlock. This class reads all the parameter sources and stores it in an appropriate data structure. Examples are path- and filenames which can be changed by user in the config file, or the --verbose CLI flag. Then, one can call ConfigBlock.GetVerboseLevel() in order to read this specific parameter.

My question: Is it good practice to collect all such runtime config data in one class?

Then, my classes need access to all these parameters. I can think of several ways to achieve this, but I'm not sure which one to take. A class' constructor can be a given a reference to my ConfigBlock, like

```<code>public:
    MyGreatClass(ConfigBlock &config);
</code>```

Or they just include a header "CodingBlock.h" which contains a definition of my CodingBlock:

```<code>extern CodingBlock MyCodingBlock;
</code>```

Then, only the classes .cpp file needs to include and use the ConfigBlock stuff.

The .h file does not introduce this interface to the user of the class.
However, the interface to ConfigBlock is still there, however, it's hidden from the .h file.

Is it good to hide it this way?

I want the interface to be as small as possible, but in the end, I guess every class which needs config parameters has to have a connection to my ConfigBlock. But, what should this connection look like?

Body:
First question: is it good practise to collect all such runtime config data in one class?

Yes. It is better to centralize runtime constants and values and the code to read them.

A class' constructor can be a given a reference to my ConfigBlock

This is bad: most of your constructors will not need most of the values. Instead, create interfaces for everything that is not trivial to construct:

old code (your proposal):

MyGreatClass(ConfigBlock &config);

new code:

struct GreatClassData {/*...*/}; // initialization data for MyGreatClass
GreatClassData ConfigBlock::great_class_values();

instantiate a MyGreatClass:

auto x = MyGreatClass{ current_config_block.great_class_values() };

Here, current_config_block is an instance of your ConfigBlock class (the one that contains all your values) and the MyGreatClass class receives a GreatClassData instance. In other words, only pass to constructors the data they need, and add facilities to your ConfigBlock to create that data.

Or they just include a header "CodingBlock.h" which contains a definition of my CodingBlock:

 extern CodingBlock MyCodingBlock;

Then, only the classes .cpp file needs to include and use the ConfigBlock stuff. The .h file does not introduce this interface to the user of the class. However, the interface to ConfigBlock is still there, however, it's hidden from the .h file. Is it good to hide it this way?

This code suggests that you will have a global CodingBlock instance. Don't do that: normally you should have an instance declared globally, in whatever entry point your application uses (main function, DllMain, etc) and pass that around as an argument wherever you need (but as explained above, you should not pass the entire class around, just expose interfaces around the data, and pass those).

Also, don't tie your client classes (your MyGreatClass) to the type of CodingBlock; This means that, if your MyGreatClass takes in a string and five integers, you will be better off passing in that string and integers, than you will be passing in a CodingBlock.


问:
What is the exact ingenuity of Unix pipe
I have heard the story of how Douglas Mcllroy came up with the concept and how Ken Thompson implemented it in one night.

As far as I understand, pipe is a system call which shares a piece of memory between two processes where one process writes and other reads from.

As someone who is not a familiar with OS internals or concepts, I was wondering what exactly is the "genius" in the story?
Is it the idea of two processes sharing memory? Or is it the implementation? Or both?

PS: I am aware of the utility of the pipe or how to use it in shell. The question is about concept and implementation of the |

答:
So I tried to do a bit of research on this by looking for PDP-10 / TOPS-10 manuals in order to find out what the state of the art was before pipes. I found this, but TOPS-10 is remarkably hard to google. There are a few good references on the invention of the pipe: an interview with McIlroy, on the history and impact of UNIX.

You have to put this into historical context. Few of the modern tools and conveniences we take for granted existed.

"At the start, Thompson did not even program on the PDP itself, but instead used a set of macros for the GEMAP assembler on a GE-635 machine."(29) A paper tape was generated on the GE 635 and then tested on the PDP-7 until, according to Ritchie, "a primitive Unix kernel, an editor, an assembler, a simple shell (command interpreter), and a few utilities (like the Unix rm, cat, cp commands) were completed. At this point, the operating system was self-supporting, programs could be written and tested without resort to paper tape, and development continued on the PDP-7 itself."

A PDP-7 looks like this. Note the lack of an interactive display or hard disk. The "filesystem" would be stored on the magnetic tape. There was up to 64kB of memory for programs and data.

In that environment, programmers tended to address the hardware directly, such as by issuing commands to spin up the tape and process characters one at a time read directly from the tape interface. UNIX provided abstractions over this, so that rather than "read from teletype" and "read from tape" being separate interfaces they were combined into one, with the crucial pipe addition of "read from output of other program without storing a temporary copy on disk or tape".

Here is McIlroy on the invention of grep. I think this does a good job of summing up the amount of work required in the pre-UNIX environment.

"Grep was invented for me. I was making a program to read text aloud through a voice synthesizer. As I invented phonetic rules I would check Webster's dictionary for words on which they might fail. For example, how do you cope with the digraph 'ui', which is pronounced many different ways: 'fruit', 'guile', 'guilty', 'anguish', 'intuit', 'beguine'? I would break the dictionary up into pieces that fit in ed's limited buffer and use a global command to select a list. I would whittle this list down by repeated scannings with ed to see how each proposed rule worked."

"The process was tedious, and terribly wasteful, since the dictionary had to be split (one couldn't afford to leave a split copy on line). Then ed copied each part into /tmp, scanned it twice to accomplish the g command, and finally threw it away, which takes time too."

"One afternoon I asked Ken Thompson if he could lift the regular expression recognizer out of the editor and make a one-pass program to do it. He said yes. The next morning I found a note in my mail announcing a program named grep. It worked like a charm. When asked what that funny name meant, Ken said it was obvious. It stood for the editor command that it simulated, g/re/p (global regular expression print)."

Compare the first part of that to the cat names.txt | awk '{print $2 ", " $1}' | sort | uniq | column -c 100 example. If your options are "build a command line" versus "write a program specifically for the purpose, by hand, in assembler", then it's worth building the command line. Even if it takes a few hours of reading the (paper) manuals to do it. You can then write it down for future reference.


答:
Short answer:

You don't need all settings for each of modules/classes in your code. If you do, then there is something wrong with your object-oriented design. Especially in case of unit testing setting all of variables that you don't need and passing that object would not help with reading or maintaining.

Title: Parameter management in OOP application


问:
Isn't the use of pointer variables a memory overhead?
In languages like C and C++, while using pointers to variables we need one more memory location to store that address. So isn't this a memory overhead? How is this compensated? Are pointers used in time critical low memory applications? </p>

答:
So isn't this a memory overhead?

It is indeed a memory overhead, but a very small one (to the point of insignificance).

How is this compensated?

It is not compensated. You need to realize that data access through a pointer (dereferencing a pointer) is extremely fast (if I remember correctly, it uses just one assembly instruction per dereference). It is fast enough that it will be in many cases the fastest alternative you have.

Are pointers used in time critical low memory applications?

Yes.


答:
My answer is no. I now am a software developer for 7 years, and my fun it's still getting better. (I'm doing desktop apps in C# at the moment)

For the part of not feeling senior yourself, I recommend two things:

Go to a big company with experienced people

Get yourself a good education. I do not know what this means where you live, but at my place they have a great post-degree course that is 2.5 years part-time. This opened my eyes for good software and development in general.

Title: Is 4-5 years the “Midlife Crisis” for a programming career?

Body:
I’ve been programming C# professionally for a bit over 4 years now. For the past 4 years I’ve worked for a few small/medium companies ranging from “web/ads agencies”, small industry specific software shops to a small startup. I've been mainly doing "business apps" that involves using high-level programming languages (garbage collected) and my overall experience was that all of the works I’ve done could have been more professional. A lot of the things were done incorrectly (in a rush) mainly due to cost factor that people always wanted something “now” and with the smallest amount of spendable money. I kept on thinking maybe if I could work for a bigger companies or a company that’s better suited for programmers, or somewhere that's got the money and time to really build something longer term and more maintainable I may have enjoyed more in my career. I’ve never had a “mentor” that guided me through my 4 years career. I am pretty much blog / google / self taught programmer other than my bachelor IT degree.

I’ve also observed another issue that most so called “senior” programmer in “my working environment” are really not that senior skill wise. They are “senior” only because they’ve been a long time programmer, but the code they write or the decisions they make are absolutely rubbish! They don't want to learn, they don't want to be better they just want to get paid and do what they've told to do which make sense and most of us are like that. Maybe that’s why they are where they are now. But I don’t want to become like them I want to be better. I’ve run into a mental state that I no longer intend to be a programmer for my future career. I started to think maybe there are better things out there to work on. The more blogs I read, the more “best practices” I’ve tried the more I feel I am drifting away from “my reality”. But I am not a great programmer otherwise I don't think I am where I am now. I think 4-5 years is a stage that can be a step forward career wise or a step out of where you are.

I just wanted to hear what other have to say about what I’ve mentioned above and whether you’ve experienced similar situation in your past programming career and how you dealt with it. Thanks.

OwnerDisplayName: Marcel


答:
So isn't this a memory overhead?

Yes.... no... maybe?

This is an awkward question because imagine the memory addressing range on the machine, and a software that needs to persistently keep track of where things are in memory in a way that can't be tied to the stack.

For example, imagine a music player where the music file is loaded on a button push by the user and unloaded from volatile memory when the user tries to load another music file.

How do we keep track of where the audio data is stored? We need a memory address to it. The program not only needs to keep track of the audio data chunk in memory but also where it is in memory. Thus we need to keep around a memory address (i.e., a pointer). And the size of the storage required for the memory address is going to match the addressing range of the machine (ex: 64-bit pointer for a 64-bit addressing range).

So it's kind of "yes", it does require storage to keep track of a memory address, but it's not like we can avoid it for dynamically-allocated memory of this sort.

How is this compensated?

Talking about just the size of a pointer itself, you can avoid the cost in some cases by utilizing the stack, e.g. In that case, compilers can generate instructions which effectively hard-code the relative memory address, avoiding the cost of a pointer. Yet this leaves you vulnerable to stack overflows if you do this for large, variable-sized allocations, and also tends to be impractical (if not outright impossible) to do for a complex series of branches driven by user input (as in the audio example above).

Another way is to use more contiguous data structures. For example, an array-based sequence might be used instead of a doubly-linked list which requires two pointers per node. We can also use a hybrid of these two like an unrolled list which stores only pointers in between every contiguous group of N elements.

Are pointers used in time critical low memory applications?

Yes, very commonly so, as many performance-critical applications are written in C or C++ which are dominated by pointer usage (they might be behind a smart pointer or a container like std::vector or std::string, but the underlying mechanics boil down to a pointer which is used to keep track of the address to a dynamic memory block).

Now back to this question:

How is this compensated? (Part Two)

Pointers are typically dirt cheap unless you're storing like a million of them (which is still a measly* 8 megabytes on a 64-bit machine).

* Note as Ben pointed out that a "measly" 8 megs is still the size of the L3 cache. Here I used "measly" more in the sense of total DRAM use and the typical relative size to the memory chunks a healthy usage of pointers will point to.

Where pointers get expensive is not pointers themselves but:

Dynamic memory allocation. Dynamic memory allocation tends to be expensive since it has to go through an underlying data structure (ex: buddy or slab allocator). Even though these are often optimized to death, they're general-purpose and designed to handle variable-sized blocks which require that they do at least a bit of work resembling a "search" (albeit lightweight and possibly even constant-time) to find a free set of contiguous pages in memory.

Memory access. This tends to be the bigger overhead to worry about. Whenever we access memory allocated dynamically for the first time, there's a compulsory page fault as well as cache misses moving the memory down the memory hierarchy and down into a register.

Memory Access

Memory access is one of the most critical aspects of performance beyond algorithms. A lot of performance-critical fields like AAA game engines focus a great deal of their energy towards data-oriented optimizations which boil down to more efficient memory access patterns and layouts.

One of the biggest performance difficulties of higher-level languages which want to allocate each user-defined type separately through a garbage collector, e.g., is that they can fragment memory quite a bit. This can be especially true if not all objects are allocated at once.

In those cases, if you store a list of a million instances of a user-defined object type, accessing those instances sequentially in a loop might be quite slow since it's analogous to a list of a million pointers which point to disparate regions of memory. In those cases, the architecture wants to fetch memory form upper, slower, bigger levels of the hierarchy in large, aligned chunks with the hope that surrounding data in those chunks will be accessed prior to eviction. When each object in such a list is allocated separately, then often we end up paying for it with cache misses when each subsequent iteration might have to load from a completely different area in memory with no adjacent objects being accessed prior to eviction.

A lot of the compilers for such languages are doing a really great job these days at instruction selection and register allocation, but the lack of more direct control over memory management here can be killer (though often less error-prone) and still make languages like C and C++ quite popular.

Indirectly Optimizing Pointer Access

In the most performance-critical scenarios, applications often use memory pools which pool memory from contiguous chunks to improve locality of reference. In such cases, even a linked structure like a tree or a linked list can be made cache-friendly provided that the memory layout of its nodes are contiguous in nature. This is effectively making pointer dereferencing cheaper, albeit indirectly by improving the locality of reference involved when dereferencing them.

Chasing Pointers Around

Assume we have a singly-linked list like:

```<code>Foo->Bar->Baz->null
</code>```

The problem is that if we allocate all these nodes separately against a general-purpose allocator (and possibly not all at once), the actual memory might be dispersed somewhat like this (simplified diagram):

When we start chasing pointers around and access the Foo node, we start off with a compulsory miss (and possibly a page fault) moving a chunk from its memory region from slower regions of memory to faster regions of memory, like so:

This causes us to cache (possibly also page) a memory region only to access a portion of it and evict the rest as we chase pointers around this list. By taking control over the memory allocator, however, we can allocate such a list contiguously like so:

... and thereby significantly improve the speed at which we can dereference these pointers and process their pointees. So, albeit very indirect, we can speed up pointer access this way. Of course if we just stored these contiguously in an array, we wouldn't have this issue in the first place, but the memory allocator here giving us explicit control over memory layout can save the day when a linked structure is required.

* Note: this is a very oversimplified diagram and discussion about the memory hierarchy and locality of reference, but hopefully it's appropriate for the level of the question.

Title: Isn't the use of pointer variables a memory overhead?

Body: In languages like C and C++, while using pointers to variables we need one more memory location to store that address. So isn't this a memory overhead? How is this compensated? Are pointers used in time critical low memory applications? </p>

Body:
So isn't this a memory overhead?

Yes.... no... maybe?

This is an awkward question because imagine the memory addressing range on the machine, and a software that needs to persistently keep track of where things are in memory in a way that can't be tied to the stack.

For example, imagine a music player where the music file is loaded on a button push by the user and unloaded from volatile memory when the user tries to load another music file.

How do we keep track of where the audio data is stored? We need a memory address to it. The program not only needs to keep track of the audio data chunk in memory but also where it is in memory. Thus we need to keep around a memory address (i.e., a pointer). And the size of the storage required for the memory address is going to match the addressing range of the machine (ex: 64-bit pointer for a 64-bit addressing range).

So it's kind of "yes", it does require storage to keep track of a memory address, but it's not like we can avoid it for dynamically-allocated memory of this sort.

How is this compensated?

Talking about just the size of a pointer itself, you can avoid the cost in some cases by utilizing the stack, e.g. In that case, compilers can generate instructions which effectively hard-code the relative memory address, avoiding the cost of a pointer. Yet this leaves you vulnerable to stack overflows if you do this for large, variable-sized allocations, and also tends to be impractical (if not outright impossible) to do for a complex series of branches driven by user input (as in the audio example above).

Another way is to use more contiguous data structures. For example, an array-based sequence might be used instead of a doubly-linked list which requires two pointers per node. We can also use a hybrid of these two like an unrolled list which stores only pointers in between every contiguous group of N elements.

Are pointers used in time critical low memory applications?

Yes, very commonly so, as many performance-critical applications are written in C or C++ which are dominated by pointer usage (they might be behind a smart pointer or a container like std::vector or std::string, but the underlying mechanics boil down to a pointer which is used to keep track of the address to a dynamic memory block).

Now back to this question:

How is this compensated? (Part Two)

Pointers are typically dirt cheap unless you're storing like a million of them (which is still a measly* 8 megabytes on a 64-bit machine).

* Note as Ben pointed out that a "measly" 8 megs is still the size of the L3 cache. Here I used "measly" more in the sense of total DRAM use and the typical relative size to the memory chunks a healthy usage of pointers will point to.

Where pointers get expensive is not pointers themselves but:

Dynamic memory allocation. Dynamic memory allocation tends to be expensive since it has to go through an underlying data structure (ex: buddy or slab allocator). Even though these are often optimized to death, they're general-purpose and designed to handle variable-sized blocks which require that they do at least a bit of work resembling a "search" (albeit lightweight and possibly even constant-time) to find a free set of contiguous pages in memory.

Memory access. This tends to be the bigger overhead to worry about. Whenever we access memory allocated dynamically for the first time, there's a compulsory page fault as well as cache misses moving the memory down the memory hierarchy and down into a register.

Memory Access

Memory access is one of the most critical aspects of performance beyond algorithms. A lot of performance-critical fields like AAA game engines focus a great deal of their energy towards data-oriented optimizations which boil down to more efficient memory access patterns and layouts.

One of the biggest performance difficulties of higher-level languages which want to allocate each user-defined type separately through a garbage collector, e.g., is that they can fragment memory quite a bit. This can be especially true if not all objects are allocated at once.

In those cases, if you store a list of a million instances of a user-defined object type, accessing those instances sequentially in a loop might be quite slow since it's analogous to a list of a million pointers which point to disparate regions of memory. In those cases, the architecture wants to fetch memory form upper, slower, bigger levels of the hierarchy in large, aligned chunks with the hope that surrounding data in those chunks will be accessed prior to eviction. When each object in such a list is allocated separately, then often we end up paying for it with cache misses when each subsequent iteration might have to load from a completely different area in memory with no adjacent objects being accessed prior to eviction.

A lot of the compilers for such languages are doing a really great job these days at instruction selection and register allocation, but the lack of more direct control over memory management here can be killer (though often less error-prone) and still make languages like C and C++ quite popular.

Indirectly Optimizing Pointer Access

In the most performance-critical scenarios, applications often use memory pools which pool memory from contiguous chunks to improve locality of reference. In such cases, even a linked structure like a tree or a linked list can be made cache-friendly provided that the memory layout of its nodes are contiguous in nature. This is effectively making pointer dereferencing cheaper, albeit indirectly by improving the locality of reference involved when dereferencing them.

Chasing Pointers Around

Assume we have a singly-linked list like:

Foo->Bar->Baz->null

The problem is that if we allocate all these nodes separately against a general-purpose allocator (and possibly not all at once), the actual memory might be dispersed somewhat like this (simplified diagram):

When we start chasing pointers around and access the Foo node, we start off with a compulsory miss (and possibly a page fault) moving a chunk from its memory region from slower regions of memory to faster regions of memory, like so:

This causes us to cache (possibly also page) a memory region only to access a portion of it and evict the rest as we chase pointers around this list. By taking control over the memory allocator, however, we can allocate such a list contiguously like so:

... and thereby significantly improve the speed at which we can dereference these pointers and process their pointees. So, albeit very indirect, we can speed up pointer access this way. Of course if we just stored these contiguously in an array, we wouldn't have this issue in the first place, but the memory allocator here giving us explicit control over memory layout can save the day when a linked structure is required.

* Note: this is a very oversimplified diagram and discussion about the memory hierarchy and locality of reference, but hopefully it's appropriate for the level of the question.


问:
What question is answered by DDD?
What is the problem that is solved by Domain Driven Design?

I understand what Object Oriented Programming brought and see the issues it addressed and how, and in what aspect/scenaria, it made the live of a developer easier. But I so far failed to see the big picture of what DDD does bring us. For sure this is due to the fact that I am just starting with DDD and maybe it is something I will just know at the end (after working with it for some years). But if not and it is possible to summarize the big picture in some sentences please share them with me.

What I got so far:

DDD helps to define a common language to discuss a software project for example. To understand what is happening in a domain, e.g. how the business works, what operations are possible and under which conditions. What data has to be stored and how it should be grouped.

Is this the big picture? I think there is more to it but I cannot yet see it.

Edit

There exists a similar question What is Domain Driven Development in practical terms?. However this question has a different focus when asking what DDD is while I would like to learn to what problem DDD is the solution. One given answer to that is really excellent and does also include possible answers to my question. I cannot judge whether this answer includes the complete answer to my question but right now my intuition tells me it does not.

答:
Domain Driven Design is fundamentally a remedy for our tendency to bleed the technical and "philosophical" objects and concerns into each other. Even in cases where we have a strong sense that these two things are best addressed as separate concerns, it can be tough to consistently make the right divisions without a clear rule.

And so, the basic rule is, "create and maintain a distinctly recognizable part of your application (the domain) into which you contain your pure, business-recognizable objects and methods, the names of which any business person should recognize."

It's about avoiding the situations wherein both the business rules and the technology are hard to change because they're not well-isolated from each other.

In my own experience with web applications, I've found that when DDD and DDD-like principles are not explicitly adhered to, there is a strong tendency to bake business rules right into UI code. So, you end up with multiple copies of business rules (one for each page), and neither those UI's nor the business rules can be easily changed.

Title: What question is answered by DDD?


答:
I think DDD deals with a somewhat understated concept, which I call the "Problem/Solution Separation". And it solves the issue of Problem Reuse instead of just Solution Reuse.

As I see it, you should model problem elements in a way that is not dependent on how it would be solved. That would be the "analysis" part of OOAD, where you define conceptually what are the elements of the problem. Meanwhile, as you go further developing your solution - that is, designing one of the possible solutions - you add elements that pertain specifically to that solution. That would be the "design" part of the application, where you define how those elements from the problem should be manipulated, or how they are expected to interact so that the problem is solved.

As a concrete example, I develop medical software (biosignal data-capturing, processing and visualization, mostly). Our company has a handful of software products, each solving quite similar problems in slightly different ways, depending on medical specialty. Upon analysis, that is, analysis of the problem, we've seen the same recurring concepts over and over. Those concepts were designed into objects (or interfaces, or abstract classes), and put in an assembly called Company.BioSignals.DomainModel. Now we have a one-to-many mapping between a problem-related, circumscribed part of the codebase, and a set of solution-related parts of the codebase.

Title: What question is answered by DDD?

Body:
What is the problem that is solved by Domain Driven Design?

I understand what Object Oriented Programming brought and see the issues it addressed and how, and in what aspect/scenaria, it made the live of a developer easier. But I so far failed to see the big picture of what DDD does bring us. For sure this is due to the fact that I am just starting with DDD and maybe it is something I will just know at the end (after working with it for some years). But if not and it is possible to summarize the big picture in some sentences please share them with me.

What I got so far:

DDD helps to define a common language to discuss a software project for example. To understand what is happening in a domain, e.g. how the business works, what operations are possible and under which conditions. What data has to be stored and how it should be grouped.

Is this the big picture? I think there is more to it but I cannot yet see it.

Edit

There exists a similar question What is Domain Driven Development in practical terms?. However this question has a different focus when asking what DDD is while I would like to learn to what problem DDD is the solution. One given answer to that is really excellent and does also include possible answers to my question. I cannot judge whether this answer includes the complete answer to my question but right now my intuition tells me it does not.


问:
Where Should I Keep Stored Procedure Names in my Code?
I've taken over some code at work that has a database repository file that keeps stored procedure names in constants.  The file looks like this:

```<code>class DatabaseRepository
{
    private const string SP_GET_EMPLOYEES = "GetEmployees";
    private const string SP_GET_DEPARTMENTS = "GetDepartments";
    private const string SP_GET_MANAGERS = "GetManagers";
    // Many more stored procedure constants ...

    public EmployeeList GetEmployees()
    {
        return RunCommand(DatabaseRepository.SP_GET_EMPLOYEES);
    }

    //more methods below that call the stored procedures
}
</code>```

I find it annoying to deal with these constants when I'm working on the boundary between the code and the stored procedures.

If I want to know what stored procedure a method is using, I have to scroll up or go-to-definition for the constant.  I then usually have to scroll back to or search for the method in question because I may be working on that method.

Going the other direction, if I want to know what method calls a given stored procedure (there's usually only one), I have to search the code for the stored procedure name, copy the string constant's name, and then search the code for that string constant.

In both cases #1 and #2, I could prevent searching and scrolling and going-to-definition if the stored procedure names were not constant strings but were actually hard coded as magic strings in the methods themselves.

I like this approach better:

```<code>class DatabaseRepository
{
    public EmployeeList GetEmployees()
    {
        return RunCommand("GetEmployees"); //magic string
    }

    //more methods below that call the stored procedures
}
</code>```

Are there any benefits that I'm not seeing to keeping stored procedure names in constants?  I know that it's helpful if more than one method uses that stored procedure.  That way, if the stored procedure name changes, I only need to make one change rather than multiple changes.  In my experience however, because of their nature, stored procedure names rarely change.

Is it better to have stored procedure names hard coded in magic strings as opposed to kept in constant strings?  I know all of the reasons why we should avoid magic strings, but I think this is an exception.

答:
Short answer: you are fully correct, using constants is not the only possible solution for cases like this, and yours is probably better.

Longer answer: the whole idea of constants fulfills three purposes:

creating a "single source of information" in your program, one and only one place where the names are defined

mapping a string to something more typesafe, which the compiler can check at compile time, and the "intellisense" in your IDE can pick up

making it obvious where to change the code when adding new stored procedures

Given you have exactly one method in the DatabaseRepository class calling the SP, all those methods are listed one after another, and it is the only place where the SPs are called from, then all three purposes are satisfied by your suggestion. Just see this as "a way to define constants for your SP names with different means that the usual const syntax", and not as "magic strings".

Note that the real benefit of using wrapper methods instead of constants comes when your SP have parameters. Then not using constants will keep the full SP signature mapping in one place, namely that function, and not in two places (a constant at the beginning the class, and several hundred lines later a wrapper method).


答: Funny i've just come across this.... I've had enough of programming and plan to leave, but seem to have had the career you desire. Maybe best to follow this thread of mine and hopefully the answers will help us both: https://stackoverflow.com/questions/2055669/how-to-find-part-time-development-it-work I understand your frustration</p>

OwnerDisplayName: Jonathan


问:
What is it called when threads are waiting but not deadlocked
The definition of a deadlock is when two or more threads cannot complete their execution because they are mutually blocked and waiting for something from the other thread(s).

Is there a similar term for when two or more threads take a long time to finish, rather than never finish, because they're waiting for another thread to complete?

答:
The term for this type of behaviour is Thread Synchronization. Also sometimes called serialization because the threads must get in line and go through that piece of code serially.

Lock Contention is a dimension that can be used to measure and predict the performance of a piece of code that requires thread synchronization. If 8 threads are contending for a lock vs. 4 threads, that speaks to how slowly your requests are going to complete for instance.

Thread Starvation is what occurs when all threads are busy, but new requests are coming in and there are no threads to service those requests. Thread starvation can be a side effect of contention, but you can have a highly-contentious system blocking everything into single threading without getting thread starvation depending on the size of your thread pool and or the number of work requests coming in.

So in short, when you have multiple threads contending for a single thing, those threads are said to be synchronized - or serialized in some parlances.

Further Reading

Lock Contention on Wikipedia

Starvation on Wikipedia


答:
On many operating systems, it is possible to lock a mutex with a timeout. The timeout is typically either infinite (no timeout) or zero (a check whether a mutex is locked or not). Obviously I could have a mutex with a 12 hour timeout, so a "deadlock" would lock down the application for 12 hours without doing anything and then the deadlock stops. </p>

<p>On the other hand, if I try to acquire a mutex, and someone else holds it, working hard for twelve hours, that may not be optimal, but on a single core machine it might not even waste time. Of course that's not a deadlock - I think I've heard the term "livelock" for it, where one thread is locked out for a long time, but the application as a whole actually makes good progress. </p>

Title: What is it called when threads are waiting but not deadlocked

Body:
The definition of a deadlock is when two or more threads cannot complete their execution because they are mutually blocked and waiting for something from the other thread(s).

Is there a similar term for when two or more threads take a long time to finish, rather than never finish, because they're waiting for another thread to complete?

Body:
On many operating systems, it is possible to lock a mutex with a timeout. The timeout is typically either infinite (no timeout) or zero (a check whether a mutex is locked or not). Obviously I could have a mutex with a 12 hour timeout, so a "deadlock" would lock down the application for 12 hours without doing anything and then the deadlock stops.

On the other hand, if I try to acquire a mutex, and someone else holds it, working hard for twelve hours, that may not be optimal, but on a single core machine it might not even waste time. Of course that's not a deadlock - I think I've heard the term "livelock" for it, where one thread is locked out for a long time, but the application as a whole actually makes good progress.


问:
How can I diagnose async/await deadlocks?
I am working with a new codebase that makes heavy use of async/await. Most of the people on my team are also fairly new to async/await. We generally tend to hold to Best Practices as Specified by Microsoft, but generally need our context to flow through the async call and are working with libraries that don't ConfigureAwait(false).

Combine all of those things and we run into async deadlocks described in the article... weekly. They don't show up during unit testing, because our mocked data sources (usually via Task.FromResult) aren't enough to trigger the deadlock. So during runtime or integration tests, some service call just goes out to lunch and never returns. That kills the servers, and generally makes a mess of things.

The problem is that tracking down where the mistake was made (usually just not being async all the way up) generally involves manual code inspection, which is time consuming and not automate-able.

What's a better way of diagnosing what caused the deadlock?

答:
Ok - I am not sure whether the following will be of any help to you, because I made some assumptions in developing a solution which may or may not be true in your case. Maybe my "solution" is too theoretical and only works for artifical examples - I have not done any testing beyond the stuff below.

In addition, I would see the following more a workaround than a real solution but considering the lack of responses I think it might still be better than nothing (I kept watching your question waiting for a solution, but not seeing one getting posted I started playing around with the issue).

But enough said: Let's say we have a simple data service which can be used to retrieve an integer:

```<code>public interface IDataService
{
    Task<int> LoadMagicInteger();
}
</code>```

A simple implementation uses asynchronous code:

```<code>public sealed class CustomDataService
    : IDataService
{
    public async Task<int> LoadMagicInteger()
    {
        Console.WriteLine("LoadMagicInteger - 1");
        await Task.Delay(100);
        Console.WriteLine("LoadMagicInteger - 2");
        var result = 42;
        Console.WriteLine("LoadMagicInteger - 3");
        await Task.Delay(100);
        Console.WriteLine("LoadMagicInteger - 4");
        return result;
    }
}
</code>```

Now, a problem arises, if we are using the code "incorrectly" as illustrated by this class. Foo incorrectly accesses Task.Result instead of awaiting the result like Bar does:

```<code>public sealed class ClassToTest
{
    private readonly IDataService _dataService;

    public ClassToTest(IDataService dataService)
    {
        this._dataService = dataService;
    }

    public async Task<int> Foo()
    {
        var result = this._dataService.LoadMagicInteger().Result;
        return result;
    }
    public async Task<int> Bar()
    {
        var result = await this._dataService.LoadMagicInteger();
        return result;
    }
}
</code>```

What we (you) now need is a way to write a test which succeeds when calling Bar but fails when calling Foo (at least if I understood the question correctly ;-) ).

I'll let the code speak; here's what I came up with (using Visual Studio tests, but it should work using NUnit, too):

DataServiceMock utilizes TaskCompletionSource<T>. This allows us to set the result at a defined point in the test run which leads to the following test. Note that we are using a delegate to pass back the TaskCompletionSource back into the test. You might also put this into the Initialize method of the test and use properties.

```<code>TaskCompletionSource<int> tcs = null;
this._dataService.LoadMagicIntegerMock = t => tcs = t;

Task<int> task = null;
TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());

tcs.TrySetResult(42);

var result = task.Result;
Assert.AreEqual(42, result);

this._end = true;
</code>```

What's happening here is that we first verify that we can leave the method without blocking (this would not work if someone accessed Task.Result - in this case we would run into a timeout as the result of the task is not made available until after the method has returned).

Then, we set the result (now the method can execute) and we verify the result (inside a unit test we can access Task.Result as we actually want the blocking to occur).

Complete test class - BarTest succeeds and FooTest fails as desired.

```<code>[TestClass]
public class UnitTest1
{
    private DataServiceMock _dataService;
    private ClassToTest _instance;
    private bool _end;

    [TestInitialize]
    public void Initialize()
    {
        this._dataService = new DataServiceMock();
        this._instance = new ClassToTest(this._dataService);

        this._end = false;
    }
    [TestCleanup]
    public void Cleanup()
    {
        Assert.IsTrue(this._end);
    }

    [TestMethod]
    public void FooTest()
    {
        TaskCompletionSource<int> tcs = null;
        this._dataService.LoadMagicIntegerMock = t => tcs = t;

        Task<int> task = null;
        TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());

        tcs.TrySetResult(42);

        var result = task.Result;
        Assert.AreEqual(42, result);

        this._end = true;
    }
    [TestMethod]
    public void BarTest()
    {
        TaskCompletionSource<int> tcs = null;
        this._dataService.LoadMagicIntegerMock = t => tcs = t;

        Task<int> task = null;
        TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Bar());

        tcs.TrySetResult(42);

        var result = task.Result;
        Assert.AreEqual(42, result);

        this._end = true;
    }
}
</code>```

And a little helper class to test for deadlocks / timeouts:

```<code>public static class TaskTestHelper
{
    public static void AssertDoesNotBlock(Action action, int timeout = 1000)
    {
        var timeoutTask = Task.Delay(timeout);
        var task = Task.Factory.StartNew(action);

        Task.WaitAny(timeoutTask, task);

        Assert.IsTrue(task.IsCompleted);
    }
}
</code>```

Body:
Ok - I am not sure whether the following will be of any help to you, because I made some assumptions in developing a solution which may or may not be true in your case. Maybe my "solution" is too theoretical and only works for artifical examples - I have not done any testing beyond the stuff below.

In addition, I would see the following more a workaround than a real solution but considering the lack of responses I think it might still be better than nothing (I kept watching your question waiting for a solution, but not seeing one getting posted I started playing around with the issue).

But enough said: Let's say we have a simple data service which can be used to retrieve an integer:

public interface IDataService
{
    Task<int> LoadMagicInteger();
}

A simple implementation uses asynchronous code:

public sealed class CustomDataService
    : IDataService
{
    public async Task<int> LoadMagicInteger()
    {
        Console.WriteLine("LoadMagicInteger - 1");
        await Task.Delay(100);
        Console.WriteLine("LoadMagicInteger - 2");
        var result = 42;
        Console.WriteLine("LoadMagicInteger - 3");
        await Task.Delay(100);
        Console.WriteLine("LoadMagicInteger - 4");
        return result;
    }
}

Now, a problem arises, if we are using the code "incorrectly" as illustrated by this class. Foo incorrectly accesses Task.Result instead of awaiting the result like Bar does:

public sealed class ClassToTest
{
    private readonly IDataService _dataService;

    public ClassToTest(IDataService dataService)
    {
        this._dataService = dataService;
    }

    public async Task<int> Foo()
    {
        var result = this._dataService.LoadMagicInteger().Result;
        return result;
    }
    public async Task<int> Bar()
    {
        var result = await this._dataService.LoadMagicInteger();
        return result;
    }
}

What we (you) now need is a way to write a test which succeeds when calling Bar but fails when calling Foo (at least if I understood the question correctly ;-) ).

I'll let the code speak; here's what I came up with (using Visual Studio tests, but it should work using NUnit, too):

DataServiceMock utilizes TaskCompletionSource<T>. This allows us to set the result at a defined point in the test run which leads to the following test. Note that we are using a delegate to pass back the TaskCompletionSource back into the test. You might also put this into the Initialize method of the test and use properties.

TaskCompletionSource<int> tcs = null;
this._dataService.LoadMagicIntegerMock = t => tcs = t;

Task<int> task = null;
TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());

tcs.TrySetResult(42);

var result = task.Result;
Assert.AreEqual(42, result);

this._end = true;

What's happening here is that we first verify that we can leave the method without blocking (this would not work if someone accessed Task.Result - in this case we would run into a timeout as the result of the task is not made available until after the method has returned).

Then, we set the result (now the method can execute) and we verify the result (inside a unit test we can access Task.Result as we actually want the blocking to occur).

Complete test class - BarTest succeeds and FooTest fails as desired.

[TestClass]
public class UnitTest1
{
    private DataServiceMock _dataService;
    private ClassToTest _instance;
    private bool _end;

    [TestInitialize]
    public void Initialize()
    {
        this._dataService = new DataServiceMock();
        this._instance = new ClassToTest(this._dataService);

        this._end = false;
    }
    [TestCleanup]
    public void Cleanup()
    {
        Assert.IsTrue(this._end);
    }

    [TestMethod]
    public void FooTest()
    {
        TaskCompletionSource<int> tcs = null;
        this._dataService.LoadMagicIntegerMock = t => tcs = t;

        Task<int> task = null;
        TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());

        tcs.TrySetResult(42);

        var result = task.Result;
        Assert.AreEqual(42, result);

        this._end = true;
    }
    [TestMethod]
    public void BarTest()
    {
        TaskCompletionSource<int> tcs = null;
        this._dataService.LoadMagicIntegerMock = t => tcs = t;

        Task<int> task = null;
        TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Bar());

        tcs.TrySetResult(42);

        var result = task.Result;
        Assert.AreEqual(42, result);

        this._end = true;
    }
}

And a little helper class to test for deadlocks / timeouts:

public static class TaskTestHelper
{
    public static void AssertDoesNotBlock(Action action, int timeout = 1000)
    {
        var timeoutTask = Task.Delay(timeout);
        var task = Task.Factory.StartNew(action);

        Task.WaitAny(timeoutTask, task);

        Assert.IsTrue(task.IsCompleted);
    }
}


问:
Why should I use a Dockerfile instead of a batch script?
I'm new to Docker and feeling my way around. My plan is to build a typical web app using Nginx+Rails+Postgress, all of which will be in the one container. I'm not (currently) doing anything complex like linking images.

I'm a lone developer, and my build process thus far is:

Edit Dockerfile

docker build

Fix bugs, and if I like the outcome then commit the Dockerfile to a git repo.

Iterate over steps 1-3 as I change the build.

docker push my/image periodically, as useful versions emerge.

Why instead would I not:

docker pull a basic image e.g. Ubuntu

docker run -t -i my/image /bin/bash

wget http://git.host.com/installation-script.sh | bash

If bugs then scrap image and edit installation-script.sh to fix bugs.

Iterate over 1-4.

docker push my/image periodically, as above.

I'm aware of issues with 'wget shell-script | bash', however it would be more familiar to me.

Instinctively I feel that using a Dockerfile is the best way to go, but I'm not sure why. I think it would be useful for Docker beginners to understand why Dockerfile is (or isn't) best practice. If I was deploying linked containers would I realise the awesome power of the Dockerfile? Does Dockerfile affect the "quality" (size, whatever?) of the final image?

答:
One great reason for doing as much work as you can in the Dockerfile is Docker caching.  A great practical example of this is for skipping bundle install on rails apps every time you test a new build.

You might be able to emulate caching using your script combined with a docker volume, but you'd be stuck doing a lot of your own plumbing work.

OwnerDisplayName: ukosteopath


问:
What is "recorded" relationship in a class diagram?

Composite aggregates Part, Container contains Content, and Recorder records. Recorded are all very common relationships between classes in a class diagram. Creator suggests that the enclosing container or recorder class is a good candidate for the responsibility of creating the thing contained or recorded. Of course, this is only a guideline.

From the book: http://authors.phptr.com/larman/uml_ooad/index.html

What is this recorder? Any example would be appreciated.

答:
I think there is some poor grammar and incorrect punctuation going on here. My best guess is that it should read as follows:

The following [generic examples] are all very common relationships between classes in a class diagram:

Composite aggregates Part

Container contains Content

Recorder records Recorded

[The] creator [some person introduced before this quotation] suggests that the enclosing Container or Recorder class is a good candidate for the responsibility of creating the thing contained or recorded [the Content and Recorded classes respectively, in the above examples]. Of course, this is only a guideline.

Text in square brackets is fully my own supposition, the rest is merely rearranged and differently punctuated.

If my guesswork is correct, then the Recorder is merely a generic and not particularly meaningful example of a class that could have some relationship to another class.

More tangible, real-world examples might be:

Company employs Employee

Doctor treats Patient

Shipment contains Order Item

If the text had used these examples, you probably wouldn't have been asking about the meaning or significance of the term Doctor!


答: what do you do when "personal projects" no longer give you sufficient learning or motivation?</p>


问:
Is event sourcing only for when writes are rare?
I'm reading up on event sourcing and can't stop asking myself if it only makes sense in exotic situations where writes are very rare or military-grade auditing is required.

A non-exceptional system with any significant usage might produce between hundreds and thousands of writes per day, translating to, say, a million or 2 writes (thus events) per year of operation. Merging millions of objects (events) just to get the current state sounds like a ludicrous proposition, when compared to a straight-up read from a traditional storage. Yet, event sourcing is behind some of the most performant  systems (think LMAX).

So, what am I missing? Is restoring state from the event stream even commonly done? Or is the idea to rarely have to do this and instead use a different storage altogether for normal operations (i.e. use the Query storage from CQRS), and restore from events only in exceptional cases (like replication, auditing etc.)?

答:
So, what am I missing?

Taking a guess.

The first thing that you may be missing is that you only need to reload the events for the state you are rebuilding.  If you can model your transaction boundaries cleanly, each object can write out events tagged with its own id, and then read back in only those events.  Using a relational database for event storage, there would be an indexed id column to speed that query.  Using EventStore, each object would have its own stream.

It takes some care in your model to do this cleanly, as you want to be sure that you are only modifying a single object in each transaction, and therefore you need to take some care that you are correctly isolating each invariant that you are trying to enforce.

In cases where that isn't fast enough, you still have the possibility of creating snapshots of your state (memoization) , and persisting that in "traditional storage".  Each snapshot gets tagged with the sequence number of the last event used to build the snapshot; on reload, the repository grabs that snapshot first, then applies newer events to it.  (This implies some reasonable way to grabbing the more recent snapshots -- either the events are also tagged with the sequence number, or you have some efficient way to read the event stream backwards until you get to your starting point.)

There's still an advantage over the usual approach here, being that your snapshots can be built in parallel to your writes, rather than being merged with them: you just put an event listener in some other thread/process, and let it merrily along writing out to the snapshot store on whatever schedule seems reasonable.  After all, the snapshot doesn't need to be particularly timely -- just often enough that the work of re-applying the newer events doesn't blow your SLA.

(Snapshotting does complicate migration; any changes to the serialization of the model will invalidate the snapshot cache.  Of course, you can rebuild snapshots using the new serialization as part of the migration, and then "catch up" when the changes go live.)

Is restoring state from the event stream even commonly done?

Yes, it is.  What normally is shown in CQRS examples is that the Application layer, after ensuring that the submitted command is well formed, the application layer will load the domain object from a repository, where the load is a default constructor followed by a replay of the event stream (or equivalently, a call to a factory with a list of events).

Two other, contradictory thoughts.

There could be a cache behind the repository interface

Cache invalidation is one of the two hard problems.


答:
You only need the extra memory usage (4-8 bytes per pointer, typically) while you need that pointer.  There are many techniques which make this more affordable.

The most fundamental technique that makes pointers powerful is that you don't need to keep every pointer.  Sometimes you can use an algorithm to construct a pointer from a pointer to something else.  The most trivial example of this is array arithmetic.  If you allocate an array of 50 integers, you don't need to keep 50 pointers, one to each integer.  You typically keep track of one pointer (the first one), and use pointer arithmetic to generate the others on the fly.  Sometimes you may keep one of those pointers to a specific element of the array temporarily, but only while you need it.  Once you're done, you can discard it, as long as you kept enough information to regenerate it later, if you need it.  This may sound trivial, but its exactly the kind of conservation tools you'll use if you truly care about how many pointers you are keeping in memory.

In extremely tight memory situations, this can be used to minimize cost.  If you are working in a very tight memory space, you usually have a good sense of how many objects you need to manipulate.  Instead of allocating a bunch of integers one at a time and keeping full pointers to them, you may take advantage of your developer knowledge that you'll never have more than 256 integers in this particular algorithm.  In that case, you might keep a pointer to the first integer, and keep track of an index using a char (1 byte) rather than using a full pointer (4/8 bytes).  You might also use algorithmic tricks to generate some of these indices on the fly.

This kind of memory conscientiousness was very popular in the past.  For example, NES games would rely extensively on their ability to cram data and generate pointers algorithmically rather than having to store them all wholesale.

Extreme memory situations can also lead one to do things like allocating all of the spaces you operate on at compile time.  Then the pointer you have to store to that memory is stored in the program rather than the data.  In many memory constrained situations, you have separate program and data memory (often ROM vs RAM), so you may be able to adjust the way you use your algorithm to push the pointers into that program memory.

Fundamentally, you can't get rid of all of the overhead.  However, you can control it.  By using algorithmic techniques, you can minimize the number of pointers you can store.  If you happen to be using pointers to dynamic memory, you'll never get below the cost of keeping 1 pointer to that dynamic memory spot, because that's the bare minimum amount of information needed to access anything in that block of memory.  However, in ultra-tight memory constraint scenarios, this tends to be the special case (dynamic memory and ultra-tight memory constraints tend to not appear in the same situations).


问:
APIs and functional programming
From my (admittedly limited) exposure to functional programming languages, such as Clojure, it seems that encapsulation of data has a less important role. Usually various native types such as maps or sets are the preferred currency of representing data, over objects. Furthermore, that data is generally immutable.

For example, here's one of the more famous quotes from Rich Hickey of Clojure fame, in an interview about the matter:

Fogus: Following that idea—some people are surprised by the fact that Clojure does not engage in data-hiding encapsulation on its types. Why did you decide to forgo data-hiding?

Hickey: Let’s be clear that Clojure strongly emphasizes programming to abstractions. At some point though, someone is going to need to have access to the data. And if you have a notion of “private”, you need corresponding notions of privilege and trust. And that adds a whole ton of complexity and little value, creates rigidity in a system, and often forces things to live in places they shouldn’t. This is in addition to the other losing that occurs when simple information is put into classes. To the extent the data is immutable, there is little harm that can come of providing access, other than that someone could come to depend upon something that might change. Well, okay, people do that all the time in real life, and when things change, they adapt. And if they are rational, they know when they make a decision based upon something that can change that they might in the future need to adapt. So, it’s a risk management decision, one I think programmers should be free to make. If people don’t have the sensibilities to desire to program to abstractions and to be wary of marrying implementation details, then they are never going to be good programmers.

Coming from the OO world, this seems to complicate some of the enshrined principles I've learned over the years. These include Information Hiding, the Law of Demeter and Uniform Access Principle, to name a few. The common thread being that encapsulation allows us to define an API for others to know what they should and shouldn't touch. In essence, creating a contract that allows for the maintainer of some code to freely make changes and refactorings without worrying about how it might introduce bugs into the consumer's code (Open/Closed principle). It also provides a clean, curated interface for other programmers to know which tools they can use to get at or build upon that data.

When the data is allowed to be directly accessed, that API contract is broken and all those encapsulation benefits seem to go away. Also, strictly immutable data seems to make passing around domain-specific structures (objects, structs, records) much less useful in the sense of representing a state and the set of actions that can be performed on that state.

How do functional codebases address these issues that seem to come up when the size of a codebase grows enormous such that APIs need to be defined and lots of developers are involved on working with specific parts of the system? Are there examples of this situation available that demonstrate how this is handled in these type of codebases?

答:
First of all, I'm going to second Sebastian's comments on what is functional proper, what is dynamic typing.  More generally, Clojure is one flavor of functional language and community, and you shouldn't generalize too much based on it.  I'll make some remarks from more of an ML/Haskell perspective.

As Basile mentions, the concept of access control does exist in ML/Haskell, and is often used.  The "factoring" is a bit different from conventional OOP languages; in OOP the concept of a class plays simultaneously the role of type and module, whereas functional (and traditional procedural) languages treat these orthogonally.

Another point is that ML/Haskell are very heavy on generics with type erasure, and that this can be used to provide a different flavor of "information hiding" than OOP encapsulation.  When a component only knows the type of a data item as a type parameter, that component can be safely handed values of that type, and yet it will be prevented from doing much with them because it doesn't know and cannot know their concrete type (there's no universal instanceof or runtime casting in these languages).  This blog entry is one of my favorite introductory examples to these techniques.

Next: in the FP world it's very common to use transparent data structures as interfaces to opaque/encapsulated components.  For example, interpreter patterns are very common in FP, where data structures are used as syntax trees that describe logic, and fed to code that "executes" them.  State, properly said, then exists ephemerally when the interpreter runs that consumes the data structures.  Also the interpreter's implementation can change as long as it still communicates with the clients in terms of the same data types.

Last and longest: encapsulation/information hiding is a technique, not an end.  Let's think a bit about what it provides.  Encapsulation is a technique for reconciling the contract and the implementation of a software unit.  The typical situation is this: the system's implementation admits of values or states that, according to its contract, should not exist.

Once you look at it this way, we can point out that FP provides, in addition to encapsulation, a number of additional tools that can be used to the same end:

Immutability as the pervasive default.  You can hand transparent data values to third party code.  They cannot modify them and put them into invalid states.  (Karl's answer makes this point.)

Sophisticated type systems with algebraic data types that allow you to finely control the structure of your types, without writing lots of code.  By judiciously using these facilities you can often design types where "bad states" are just impossible.  (Slogan: "Make illegal states unrepresentable.")  Instead of using encapsulation to indirectly control the set of admissible states of a class, I'd rather just tell the compiler what those are and have it guarantee them for me!

Interpreter pattern, as mentioned already.  One key to designing a good abstract syntax tree type is to:

Try and design the abstract syntax tree data type so that all values are "valid."

Failing that, make the interpreter explicitly detect invalid combinations and cleanly reject them.

This F# "Designing with types" series makes for pretty decent reading on some of these topics, particularly #2.  (It's where the "make illegal states unrepresentable" link from above comes from.)  If you look closely, you'll note that in the second part they demonstrate how to use encapsulation to hide constructors and prevent clients from constructing invalid instances.  As I said above, it is part of the toolkit!

Title: APIs and functional programming


答:
I've been a software developer for twenty-one years -- among other things, that means I've been doing this long enough to drink! ;-) But seriously, though, I can't imagine doing anything else as well or as joyously as programming. I'm apparently one of those rare birds that really love this job.

I was recently freshening up my resume, and I noticed that I've had many, many jobs in the last two decades -- mostly contracts. But what I realized in looking at that long list is that the jobs I loved most (and the ones I stayed at the longest) were with software firms, i.e. companies whose business model involved selling software to customers. The following theories are probably not universally applicable, but they go far to explain my experience.

As I see it, the difference between a software shop and your typical IT shop is surprisingly obvious. It's merely a question of what those in upper management understand. If the company gets most of its revenue from software, then the top brass will really grok software and how it's made. But if revenue comes from selling widgets, they generally don't have the faintest inkling of what it takes to keep their IT infrastructure running, let alone the processes behind software development. Worse, even though they delegate the task to IT staff, they try to map the IT processes to what they know, with results that generally range from disappointing to disastrous.

One reason is that there's a wide range of talent out there, from the merely competent to the software virtuoso. This runs completely counter to the cookie-cutter, one-size-fits-all mentality that works so well for unskilled and semi-skilled positions. The expectation that any one developer can be replaced with any other with a similar "skillset" may seem ludicrous to us, but often seems perfectly reasonable to a management structure that's focused on raw numbers. If this seems incredible, just look at how many shops are still trying to make the Waterfall model work.

You don't necessarily need all virtuosos on your team, but you need at least one or two. And part of their role must be to mentor the junior people so they can grow into the role (or wash out -- it happens). Otherwise, bad-to-mediocre junior code will prevail, with its attendant misfactoring and bloat. Once that cancer sets in, the code rapidly becomes unmaintainable, productivity across the team falls sharply, and people start to burn out.

This creates turnover, until finally somebody says, "We can't keep this thing going anymore! Let's scrap it and start over!" The investment in the legacy codebase goes out the window, and the process starts all over again. "But this time will be different," you promise yourself. And for a while it is. Then somebody hires away your rock star, and you're left with undirected junior people trashing your shiny new codebase all over again.

Lather. Rant. Repent.

But I digress... So, to answer your original question: No, half a decade is not the midlife of a software career. It's more an Age of Reason, perhaps -- the place in your career where the scales fall from your eyes and you start to see the business for what it is. The realizations come in a different order for everyone, and that colors the conclusions you may draw along the way. But hang in there -- if you come out the other side sane, you'll have a much healthier perspective, and you'll ultimately find this crazy business we're in more rewarding than ever before.

OwnerDisplayName: Eric Lloyd


问:
How viable is it to have a single webapp over several private small repositories?
We are a low budget team working on a web app. Due some complications we might need to work remotely from January and onward. After some consulting and googling, we concluded that several small repositories is the cheaper option.   We're thinking in:

Backend and services

Middleware

Front End

This way we can separate in relevant teams, each one working remotely in their repository. How viable is it to have our app in several private small repositories?

Additionally what considerations should we take if we were to work this way?

Note: I'm asking about a single, big project divided over several small repositories. This differs from the  related questions asked on this site, because they are asking for multiple projects in either one or several repositories.  Additionally, we chose to dived the project, mostly because we aren't willing to invest a single big private repository unless we are going to stick with it.

答:
"...we concluded that several small repositories is the cheaper option."

That's great. Divide and conquer. You break the effort into logical pieces, give each piece to a different hard-core team, work like mad for a few months, bring everything together, and...

and...

Well, it'll be a damn nightmare. It definitely won't be cheaper. Why would it be?

The largest "cost" in any software project is communication. You don't save money by writing code faster. That's the secret programmers won't admit. (Psst. Don't tell anyone. It really doesn't matter how fast you write code.) The time spent writing code is absolutely dwarfed by the time spent planning and talking and negotiating and fighting and talking and meeting and talking some more and compromising and realizing you shouldn't have compromised and promising to do better and yelling and wishing and "solutioning" (that's not a word, dammit) and looping back and pinging and talking and not being able to sleep.

So, you break your work into discrete chunks and hand each chunk off to a separate team. What did you just do? You added communication burden. If you're lucky and your teams are perfect, there's absolutely no cost difference between one big repository and a few small repos. If you're not lucky (few are), breaking into separate teams will actually cost more. It's hard enough to stay in synch when you're all in the same code base, stepping on each others' toes. Now imagine how hard it will be when three different teams think the requirements mean something slightly different (with no way to correct quickly because they're not breaking the other teams' stuff), have slightly different cultures, and, in the end, are very motivated to avoid blame when things go wrong so they're more than willing to throw the other teams under the bus.

I know, I know... your teams are better than that. But are they really? Are you confident enough to bet money on it?

Look, in either approach (big repo/many little repos) you're going to have to mock out a bunch of crap in the beginning. You start working blind. As soon as possible, as soon as they're available, you should start using concrete implementations from the other layers. This will identify problems and misunderstandings early. Sure, it will be a little bumpy, but it's a hell of a lot less bumpy than developing independently with a shaky spec and a handshake, and then folding things together late.

My point is, big repo/little repos isn't the issue. What matters is how you structure your teams. Ideally, your teams have small independent identities within a larger cohesive identity. Kinda like organs in an organism or maybe a slime mold. Regardless of how you structure the code, give everyone a chance to bump into each other. Make communication easy. Make mistakes together and fix them early and often.


答:
In many situations pointers actually save memory. A common alternative to using pointers is to make a copy of a data structure. A full copy of a data structure will be bigger than a pointer.

One example of a time critical application is a network stack. A good network stack will be designed to be "zero copy" - and to do this requires clever use of pointers.


问:
Why is it inappropriate to use UML diagrams to plan how your code will be organized?

So, yes, diagrams can be inappropriate at times. When are they inappropriate? When you create them
  without code to validate them, and then intend to follow them. There is nothing wrong with drawing a diagram to
  explore an idea.

Agile Software Development: Principles, Patterns, and Practices - Robert C. Martin

What exactly does he mean by this? Isn't UML designed to help plan out how to structure your code before "diving in"? What's the point of using it if you don't follow the diagrams you came up with?

Context: In this chapter, Uncle Bob makes a UML diagram for the Score Keeper of a Bowling game. Then he goes on to develop the program in a test driven manner, without consulting the UML diagram. The resulting program is nothing like the UML diagram, and Uncle Bob comes to the conclusion quoted above.

答:
I guess that not every programming idiom (or design, or code) fits into UML (which I admit I don't know well -only read a few books on it-, I never used it, and I probably dislike it).

Plain C code (e.g. the source code of the Linux kernel) might not be exactly modeled by UML.

Ocaml code (with its modules and functors) or even C++11 code (with lambdas and templates) might not fit into UML.

Multistage programming à la MetaOcaml probably don't fit into UML.

Prolog code or Common Lisp code probably does not fit into UML.

See also this answer & this question of mine.

Read Scott's Programming Language Pragmatics and Van Roy's Concepts, Techniques and Models of Computer Programming books, then ask yourself if every programming model there fit into UML.

See also Martin Fowler's Is Design Dead? blog.


问:
If you could only have one programming related book on your bookshelf what would it be and why?
One per answer please. I'll add my favourite as an answer.</p>

答:
Worth mentioning:

The Mythical Man-Month


答:
I would suggest that if you really enjoy programming then make the time to work on your own projects that interest you, outside of work.  Even if you’re handed a dream job, the day-to-day reality of working on professional level software can often take the fun out of it, just like anything else in life.

There’s a good reason why programmers get paid well (it’s incredibly difficult to build and maintain software systems, it’s fraught with compromises, and you’re often working under high-pressure time constraints).

My advice is to work hard while at work, learn what you can from those around you who know more or have more experience (even if you think you can do better than them), and continue to enjoy the thing that got you into this mess in the first place: a passion for programming.

OwnerDisplayName: dvanaria


问:
Why can't we use IP address instead of cookies in identifying the client in servlets?
I know we have some extra advantages in using the cookies over IP address, but my question is Why can't the container just remember the IP address of the client in identifying the client when he visit his site again? Is it possible for the container to remember the client with the help of IP address?</p>

答:
Apart from that two computers can be behind a NAT and have the same IP-address, your concept of client needs to be right.

The client is very much NOT the computer you're communicating with, but the browser running on that computer.

Your browser doesn't care much about which ip-address your computer has, your operating system does. And that's why you can't rely on ip-addresses. The browser does care about cookies and they're under the browsers control. That's why you use cookies for sessions.


问:
How to find a subset of size k such that the minimum distance between values is maximum
Suppose I have a sorted array which contains n integers.

How do I find subset of size k such that the minimum distance between all pairs of integers in the subset is maximized, I mean they are at maximal distance.

example: array a[]={1,2,6,7,10} and k=3,

subset = {1,6,10}, the minimum distance is 4 between 10 and 6.

Wrong subsets:

{1,7,10} , minimum distance is 3

{1,2,6} , minimum distance is 1

My first thought was to get all the combinations in the size of k, then calculate the distance of each one. But the time complexity would be O(n!), and the interviewer doesn't like it. Dynamic Programming is the hint he gave me, but I still have no idea.

He suggested that I can start from a[0], find a[0]+x=Y also in the array... and then Y+x and so on k-1 times, also kth element will be a[n-1], but I couldn't get him. I don't know why there must be such a x, like in the example above, the correct answer is {1,6,10}, the distance between 1 and 6 is 5, and it's 4 between 6 and 10, then what should x be?

答:
For some given lists and sizes, it may have many correct answers.

I would try a greedy algorithm instead of backtracking: Given an sub-selection, if one wants to extend it to an extra element, one simply have to select the new one, since the maximum of minimal distances can only decrease as the number of elements increases. Complexity: O(k*n*n), which is a better than O(n!).

If you ignore special cases (size > list.size, etc.):

```<code>List<Int> maxmin(List<Int> l, int size)
{
   Int head = l.subList(0, 1);
   List<Int> tail = l.subList(1, l.size());
   more(head, tail, size-1);
}

private List<Int> more(List<Int> selected, List<Int> available, int size)
{
   if(size == 0) return selected;
   else
   {
      int max = maxByMin(available, selected);
      selected.add(max);
      available.remove(max);
      return more(selected, available, size-1);
   }
}

private int maxByMin(List<Int> candidates, List<Int> elements)
{
   int maxMin = Integer.MIN_VALUE;
   int maxVal = candidates(0);

   for(int candidate : candidates)
   {
      int minDist = Integer.MAX_VALUE;

      for(int element : elements)
      {
         int dist = math.abs(candidate, element);
         if(dist < minDist)
         {
             minDist = dist;
         }
      }

      if(minDist > maxMin)
      {
         maxMin = minDist;
         maxVal = candidate;
      }
   }
   return candidate;
}
</code>```

In Scala:

```<code>def maxmin(l: Seq[Int], size: Int): Seq[Int] =
{
  def more(selected: Seq[Int], reminder: Seq[Int], size: Int): Seq[Int] =
  {
     if(size == 0) selected
     else
     {
        val max = reminder.maxBy(x => selected.map(y => math.abs(y - x)).min)
        more(selected :+ max, reminder diff Seq(max), size-1)
     }
  }

  more(Seq(l.head), l.tail, size-1)
}
</code>```

I did not checked the Java code, but the Scala one seems OK. Otherwise, please provide a counter-example because that probably means I not understood the problem.

Body:
For some given lists and sizes, it may have many correct answers.

I would try a greedy algorithm instead of backtracking: Given an sub-selection, if one wants to extend it to an extra element, one simply have to select the new one, since the maximum of minimal distances can only decrease as the number of elements increases. Complexity: O(k*n*n), which is a better than O(n!).

If you ignore special cases (size > list.size, etc.):

List<Int> maxmin(List<Int> l, int size)
{
   Int head = l.subList(0, 1);
   List<Int> tail = l.subList(1, l.size());
   more(head, tail, size-1);
}

private List<Int> more(List<Int> selected, List<Int> available, int size)
{
   if(size == 0) return selected;
   else
   {
      int max = maxByMin(available, selected);
      selected.add(max);
      available.remove(max);
      return more(selected, available, size-1);
   }
}

private int maxByMin(List<Int> candidates, List<Int> elements)
{
   int maxMin = Integer.MIN_VALUE;
   int maxVal = candidates(0);

   for(int candidate : candidates)
   {
      int minDist = Integer.MAX_VALUE;

      for(int element : elements)
      {
         int dist = math.abs(candidate, element);
         if(dist < minDist)
         {
             minDist = dist;
         }
      }

      if(minDist > maxMin)
      {
         maxMin = minDist;
         maxVal = candidate;
      }
   }
   return candidate;
}

In Scala:

def maxmin(l: Seq[Int], size: Int): Seq[Int] =
{
  def more(selected: Seq[Int], reminder: Seq[Int], size: Int): Seq[Int] =
  {
     if(size == 0) selected
     else
     {
        val max = reminder.maxBy(x => selected.map(y => math.abs(y - x)).min)
        more(selected :+ max, reminder diff Seq(max), size-1)
     }
  }

  more(Seq(l.head), l.tail, size-1)
}

I did not checked the Java code, but the Scala one seems OK. Otherwise, please provide a counter-example because that probably means I not understood the problem.


问:
Set keep-alive for Java ServerSocket
In a multi client server application, I need to know when each client connection is dead on the server side.<br>
After set keep-alive for client (and change default time from 2 hours to 10 second) each client could know when disconnected from server, but on the server side, Java doesn't have any method to set keep-alive like client socket. </p>

答: Java's ServerSocket returns a new Socket object for each client that connects. This Socket object is the same type as is used in a client, so supports exactly the same options. You can simply set the keepalive option there.</p>

Title: Set keep-alive for Java ServerSocket


问:
Is 4-5 years the “Midlife Crisis” for a programming career?
I’ve been programming C# professionally for a bit over 4 years now. For the past 4 years I’ve worked for a few small/medium companies ranging from “web/ads agencies”, small industry specific software shops to a small startup. I've been mainly doing "business apps" that involves using high-level programming languages (garbage collected) and my overall experience was that all of the works I’ve done could have been more professional. A lot of the things were done incorrectly (in a rush) mainly due to cost factor that people always wanted something “now” and with the smallest amount of spendable money. I kept on thinking maybe if I could work for a bigger companies or a company that’s better suited for programmers, or somewhere that's got the money and time to really build something longer term and more maintainable I may have enjoyed more in my career. I’ve never had a “mentor” that guided me through my 4 years career. I am pretty much blog / google / self taught programmer other than my bachelor IT degree.

I’ve also observed another issue that most so called “senior” programmer in “my working environment” are really not that senior skill wise. They are “senior” only because they’ve been a long time programmer, but the code they write or the decisions they make are absolutely rubbish! They don't want to learn, they don't want to be better they just want to get paid and do what they've told to do which make sense and most of us are like that. Maybe that’s why they are where they are now. But I don’t want to become like them I want to be better. I’ve run into a mental state that I no longer intend to be a programmer for my future career. I started to think maybe there are better things out there to work on. The more blogs I read, the more “best practices” I’ve tried the more I feel I am drifting away from “my reality”. But I am not a great programmer otherwise I don't think I am where I am now. I think 4-5 years is a stage that can be a step forward career wise or a step out of where you are.

I just wanted to hear what other have to say about what I’ve mentioned above and whether you’ve experienced similar situation in your past programming career and how you dealt with it. Thanks.

答:
Unless you find a job doing what you already wanted to be doing with your knowledge of programming, working full time on a related-yet-uninteresting part of programming will dull your interest in what you liked to begin with.

Or, someone with a fierce interest in self-guiding robotics using modern path planning algorithms doing web development work full time probably won't want to see a computer at home, much.  The same person plowing their way to the career they actually wanted and not stopping halfway will often gladly work more than a 40 hour week, go home happy, and wake up rested in the morning.

In theory, at least.

OwnerDisplayName: Dean J