Hot answers tagged

249

What is the purpose of a constructor? It returns a newly constructed object. What does an infinite loop do? It never returns. How can the constructor return a newly constructed object if it doesn't return at all? It can't. Ergo, an infinite loop breaks the fundamental contract of a constructor: to construct something.


204

Exceptions do not contain useful details because the concept of exceptions has not matured yet enough within the software engineering discipline, so many programmers do not understand them fully, and therefore they do not treat them properly. Yes, IndexOutOfRangeException should contain the precise index that was out of range, as well as the range that was ...


195

This is a "standards smell" to me. Whenever I see coding standards with specific limits in them, I worry. You almost always run into a case where a method needs to be bigger than the standard allows (whether it's line length/count, number of variables, number of exit points, etc). Standards should be more like guidelines, and allow sufficient leeway for ...


191

Whilst many, including "Uncle Bob", advise not to use I as a prefix for interfaces, doing so is a well-established tradition with C#. In general terms, it should be avoided. But if you are writing C#, you really should follow that language's conventions and use it. Not doing so will cause huge confusion with anyone else familiar with C# who tries to read ...


185

S = Single Responsibility Principle So I'd expect to see a well organised folder/file structure & Object Hierarchy. Each class/piece of functionality should be named that its functionality is very obvious, and it should only contain logic to perform that task. If you saw huge manager classes with thousand of lines of code, that would be a sign that ...


177

As an exercise, first let's verify your logic. Though as we'll see, you have bigger problems than any logical problem. Call the first condition A and the second condition B. You first say: Looking specifically at section two, I know that if section one is true, then section two will also be true. That is: A implies B, or, in more basic terms (NOT A) ...


174

Utility methods should not throw on empty collections. Your API clients would hate you for it. A collection can be empty; a "collection-that-must-not-be-empty" is conceptually a much more difficult thing to work with. Transforming an empty collection has an obvious outcome: the empty collection. (You may even save some garbage by returning the parameter ...


174

I find the code hard to read with the goto statements. I would recommend structuring your enum differently. For example, if your enum was a bitfield where each bit represented one of the choices, it could look like this: [Flags] public enum ExampleEnum { One = 0b0001, Two = 0b0010, Three = 0b0100 }; The Flags attribute tells the compiler that ...


167

The general rule to follow is that structs should be small, simple (one-level) collections of related properties, that are immutable once created; for anything else, use a class. C# is nice in that structs and classes have no explicit differences in declaration other than the defining keyword; so, if you feel you need to "upgrade" a struct to a class, or ...


166

The problem with your basic example isn't the null check, it's the silent fail. Null pointer/reference errors, more often than not, are programmer errors. Programmer errors are often best dealt with by failing immediately and loudly. You have three general ways to deal with the problem in this situation: Don't bother checking, and just let the runtime ...


163

To answer your question about extant research But has anything been written or researched on recognizing the point where striving for code brevity stops being useful and becomes a barrier to comprehension? Yes, there has been work in this area. To get an understanding of this stuff, you have to find a way to compute a metric so that comparisons can be ...


163

Sobczak isn't talking about corporate ownership. The "half" language that he is missing is all those things that you can't do in many modern languages, even though as a well-educated computer expert he knows they could be made possible: inherit from as many classes as you like. Assign any object to any other without type constraints. Control allocation and ...


155

I have a bag with five potatoes in it. Are there .Any() potatoes in the bag? "Yes," you say. <= true I take all of the potatoes out and eat them. Are there .Any() potatoes in the bag? "No," you say. <= false I completely incinerate the bag in a fire. Are there .Any() potatoes in the bag now? "There is no bag." <= ArgumentNullException


150

SRP is perhaps the most misunderstood software principle. A software application is built from modules, which are built from modules, which are built from... At the bottom, a single function such as CheckInput will only contain a tiny bit of logic, but as you go upward, each successive module encapsulates more and more logic and this is normal. SRP is not ...


140

At what point should a developer be allowed to choose his tools? When they don't impact your team. Am I looking at this the wrong way? Absolutely. Yes, you have a short deadline. Yes, you could get it done faster in Rails. But the company as a whole needs to deploy and maintain the application. If the company has a stable of good C# developers, then it ...


136

for vs. foreach There is a common confusion that those two constructs are very similar and that both are interchangeable like this: foreach (var c in collection) { DoSomething(c); } and: for (var i = 0; i < collection.Count; i++) { DoSomething(collection[i]); } The fact that both keywords start by the same three letters doesn't mean that ...


135

Downcasting is unpopular, maybe a code smell I disagree. Downcasting is extremely popular; a huge number of real-world programs contain one or more downcasts. And it is not maybe a code smell. It is definitely a code smell. That's why the downcasting operation is required to be manifest in the text of the program. It's so that you can more easily notice ...


135

IMO the root of the problem is that this piece of code shouldn't even exist. You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and ...


134

Modifying code to make it more testable has benefits beyond testability. In general, code that is more testable Is easier to maintain, Is easier to reason about, Is more loosely coupled, and Has a better overall design, architecturally.


133

There are two fundamental advances with the structured approach that can't be emulated using text logs without (sometimes extreme levels of) additional effort. Event Types When you write two events with log4net like: log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt"); log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt"); ...


129

but crashing your client's software is still not a good thing It most certainly is a good thing. You want anything that leaves the system in an undefined state to stop the system because an undefined system can do nasty things like corrupt data, format the hard drive, and send the president threatening emails. If you cannot recover and put the system back ...


128

Back in those days, developers were working much closer to the metal. C was essentially a higher level replacement for assembly, which is almost as close to the hardware as you can get, so it was natural you needed pointers to be efficient in solving coding problems. However, pointers are sharp tools, which can cause great damage if used carelessly. Also, ...


120

I am a bit confused by the MSDN C# documentation which states that & and | are logical operators and that && and || are conditional operators. I keep calling &&, || and ! logical operators, so I am wrong? No; you're correct. There are numerous small, mostly unimportant nomenclature errors in the MSDN documentation; I tried to get as ...


119

It depends on whether the static classes maintain state or not. Personally, I have no problem with stateless functions thrown together in a static class.


115

If you create one per query / transaction, it is much easier to manage "closing" the connections. I can see why common sense dictates that you should open one and use it throughout, but you will run into problems with dropped connections and multithreading. So your next step will be to open a pool, say of 50, connections and keep them all open, doling them ...


112

You excluded the crucial part for simplicity. The repository is the abstraction layer for persistence. We separate out persistence into its own layer so that we can change the persistence technology more easily when we need to. Therefore, having SQL outside of the persistence layer completely foils the effort of having a separate persistence layer. As a ...


111

You don't do DRY because someone wrote it in a book somewhere that it's good to do, you do DRY because it actually has tangible benefits. Specifically from that question: If you repeat yourself, you can create maintainability issues. If doStuff1-3 all have similarly structured code and you fix a problem in one, you could easily forget to fix the problem ...


111

If you felt compelled to expand a one liner like a = F(G1(H1(b1), H2(b2)), G2(c1)); I wouldn't blame you. That's not only hard to read, it's hard to debug. Why? It's dense Some debuggers will only highlight the whole thing at once It's free of descriptive names If you expand it with intermediate results you get var result_h1 = H1(b1); var result_h2 ...


111

What Color Is Your Function? You may be interested in Bob Nystrom's What Color Is Your Function1. In this article, he describes a fictional language where: Each function has a color: blue or red. A red function may call either blue or red functions, no issue. A blue function may only call blue functions. While fictitious, this happens quite regularly in ...


109

Checking for uniqueness and then setting is an antipattern; it can always happen that the ID is inserted concurrently between checking time and writing time. Databases are equipped to deal with this problem through mechanisms like constraints and transactions; most programming languages aren't. Therefore, if you value data consistency, leave it to the expert ...


Only top voted, non community-wiki answers of a minimum length are eligible