New answers tagged

1

Software engineering is always a series of trade-offs. You have to give up something to get something else. The unfortunate reality is that we don't always have a full picture of what the impacts are on our system when we start. You've mentioned many principles here, so it makes sense to summarize the idea behind it. Don't Repeat Yourself (DRY) Bottom ...


0

Probably the most reliable way to handle both the normal way and for development. That's to make use of configuration. The built in configuration APIs for Net Core/Standard allow you to merge environment specific configuration with standard configuration. var environment = Environment.GetEnvironmentVariable("Environment"); var builder = new ...


0

NDepend can be used to enforce various coding standards on a .NET Code Base. It has around 200 default code rules that can be browsed here. Also it is easy to customize existing rules or create your own rules since with NDepend a rule is just a C# LINQ query. Disclaimer: I work for NDepend


1

the recommendation is to prefer returning a result object than throwing an exception This is bad advice IMHO, because they are used in different circumstances. Using a result object when an exception is most appropriate is bad. If ValidateUserInput is not able to perform its task because (for example) the process is out of memory, then throwing an ...


0

TL;DR To answer the question, I'm now having a hard time thinking of a time enums are not a code smell on some level. There's a certain intent that they declare efficiently (there is a clearly bounded, limited number of possibilities for this value), but their inherently closed nature makes them architecturally inferior. Excuse me as I refactor tons of my ...


3

There are use cases for both exceptions and result objects, so "cleanliness" of the code is dependent upon the use case. It all depends on how critical it is to stop the execution of the program. Exceptions are the hand grenades of programming. Pull the pin and throw it. The only thing to keep your application from blowing sky high is to catch it and handle ...


1

Methods which throws exceptions are not "honest". You can't recognize if a method is expected to fail or not, by looking at its signature. Compared to [older versions of] Java this was argued to be one of .Net's biggest failings. Java laces Exceptions right into the Method signature; .Net doesn't. Exception handling adds a lot of boiler plate code. ...


0

There are valid reasons for why you may choose to replace enums with something that is, in a certain sense, more flexible and better expresses your design. This is not something you'd apply everywhere (even in the same codebase), though; this is acknowledged in the introductory paragraphs of the Microsoft article you referenced: However, this isn't a ...


3

Basically both of the articles you reference are wrong. You should use enums where you have an enum. You should also have change control on your database. If you bypass your change control processes for your code you can add an enum value, recompile the code on your desktop machine, RDP to the server and copy the binaries over the top of the application and ...


0

Apparently you have two different fields. You want to treat them as one, which immediately gets you into trouble. Treat them as separate instead. You have one enum-backed field Whatever with a fixed number of predefined options. Your logic-bound enum is among these. And then you have another field wich you may refer to as CustomWhatever. This is just a tag ...


2

With enums this is fairly easy. We would just perform a very natural check if (cardType == CardType.Visa). The point is: the values are all there on code to be checked. If you are using a CardType class and there is some behavior that has to be different from one instance to another, then allow the CardType object to know it. So, if there are two ways of ...


2

The goal of extension methods is specifically to be able to extend either classes of other assemblies or interfaces. The recommendation to use them sparingly is right, for several reasons: Extension methods, when used too much, are polluting IntelliSense. This could be extremely annoying when (1) the extension methods were created in a core namespace which ...


5

Extension methods are just syntactic sugar for ordinary static method calls. Extension methods make possible the ability to "spot-weld" methods onto existing types, without requiring inheritance, composition, weaving or any other language mechanisms. But they're just a proxy for an ordinary method call; they don't participate in the design of the class, ...


1

Depending on abstractions, creating single-responsibility classes, and writing unit tests are not exact sciences. It's perfectly normal to swing too far in one direction when learning, go to an extreme, and then find a norm that makes sense. It just sounds like your pendulum has swung too far, and might even be stuck. Here's where I suspect this is going ...


2

So that's a total of 15 classes (excluding POCOs and scaffolding) to perform a fairly straightforward save. That's crazy.... but these classes sound like something I'd write myself. So let's have a look at them. Let's ignore the interfaces and tests for now. BasePathProvider - IMHO any non-trivial project working with files needs it. So I'd assume, there's ...


11

Tasks that used to take 5-10 files can now take 70-100! This is a lie. The tasks never took only 5-10 files. You are not solving any tasks with less than 10 files. Why? Because you're using C#. C# is a high level language. You are using more than 10 files just to create hello world. Oh sure you don't notice them because you didn't write them. So you don't ...


4

I would like to expound on some of the things already mentioned here, but more from a perspective of where object boundaries are drawn. If you're following something akin to Domain-Driven Design, then your objects are probably going to represent aspects of your business. Customer and Order, for example, would be objects. Now, if I were to make a guess ...


0

Singletons pattern generally refers to a single global instance. I.e. a static property in c#. Most of the problems with this is related to the "global" part, or more specifically, the combination of "global" and "mutable". This question goes into the problems with singleton pattern in more details So when you want to use DI for singleton behavior you ...


28

Tasks that used to take 5-10 files can now take 70-100! This is the opposite of the single-responsibility principle (SRP). To get to that point, you must have divided up your functionality in a very fine-grained way, but that's not what the SRP is about -- doing that ignores the key idea of cohesiveness. According to the SRP, software should be divided ...


100

Now, to build a simple file saving application you have a class to check if the file already exists, a class to write the metadata, a class to abstract away DateTime.Now so you can inject times for unit testing, interfaces for every file containing logic, files to contain unit tests for each class out there, and one or more files to add everything to your DI ...


10

It sounds as though your code isn't very well decoupled and/or your task sizes are way too big. Code changes should be 5-10 files unless you're doing a codemod or large scale refactoring. If a single change touches a lot of files, it probably means that your changes cascade. Some improved abstractions (more single responsibility, interface segregation, ...


0

It's contextual. This depends on more than you've mentioned in the answer. At a very basic level, when you maximize reusability, you unite repeated logic and put it in a single location. +---------------+ | | +----+ Loans.HSBC | | | | ...


4

This is going to be a frame challenge answer. It is possible to design base class in a way that I have to pass connection string only once and not for each of the 4 concrete classes? You shouldn't try to achieve what you want to with a base class. Why not? Basically, if you use a base class for this, it might work fine now. Over time, your code will ...


1

I'd recommend following the fail fast principle, so those checks should be in the "setter" methods, eg: public UserBuilder WithName(string name) { if(string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name)); _name = name; return this; } Build should then just create the Person object. Another point is that, if you are going to ...


0

It is possible to design base class in a way that I have to pass connection string only once and not for each of the 4 concrete classes? Short answer - No. If you're going to use inheritance and work with [instances of] subclasses, then you have to use the proper plumbing to allow the derived classes to work with the base class. When you instantiate ...


3

There's an important difference here between "proto2" and "proto3" syntax; you're using "proto3" syntax here (and the Google tooling only supports "proto3" syntax), and in "proto3", zeros are defaults and defaults are zeros; meaning: the only default value for a bool is false, and false is never sent; thus a missing value is false. So if you're using "...


0

What problem are you trying to solve by duplicating the StudentModel properties in the StudentViewModel? Adding this type of facade wrapper does nothing except bloat the code base. Just include the StudentModel instance as a (read only) property of the StudentViewModel and bind directly to its properties. Take a look at my blog posts concerning the division ...


1

My personal favourite public class Foo { private readonly List<SomeClass> _elements = new List<SomeClass>(); public List<SomeClass> Elements => _elements.ToList(); public void Add(SomeClass someClass) { _elements.Add(someClass); } } Reasons The reasons for this design are: The list belongs to Foo. .Add()...


3

In Java in such cases it's usual to have a "default" configuration built by a factory, kept independent from the actual "properly" behaving server. So, your user writes: var server = DefaultServer.create(); while the Server's constructor still accepts all its dependencies and can be used for deep customization.


0

I totally agree with your opinion. We don't want to pollute component usage boundary just for the purpose of unit testing. This is the whole problem of DI based testing solution. I would suggest to use InjectableFactory / InjectableInstance pattern. InjectableInstance are a simple reusable utility classes which are mutable value holder. The component ...


2

It seems like a bad idea, just make a new version with the new namespace. But.... namespace oldNameSpace { [Obsolete("use the new namespace")] public class origionalClass { } } namespace newNameSpace { public class origonalClass: oldNameSpace.origonalClass { } }


4

How do I keep my library backwards-compatible? The short answer is: you can't. If you move a type from one namespace to another, your choices are to manually create a delegation class in the old place that internally maps to the new location (and mark it obsolete), or you make a breaking change. But I'd question what you are proposing anyway. There exists ...


1

Both approaches are exactly equivalent from their flexibility, expressiveness, and testability. For example, in the case that we have a Service but the constructor of your class takes a list, then just call it as: new Foo(service.GetElements()) It really doesn't matter whether the GetElements() method is called within the constructor or outside of it, you ...


2

You isolate external systems. Usage 1: Of course using DI in case you have multiple implementation of your interface seems logic. You have a repository for your SQL Server then another one for your Oracle database. Both share the same interface and you "inject" (this is the term used) the one you want on runtime. This is even not DI, this is basic OO ...


2

It is not necessary to use interfaces to use DI. The primary purpose of DI is to separate construction and usage of objects. Using singletons is rightly frowned upon in most cases. One of the reasons is that it becomes very difficult to get an overview of what dependencies a class has. In your example the ItemSiteController could simply take a ...


2

The helicopter view of DI is simply the ability to swap out an implementation for an interface. While this of course is a boon for testing there are other potential benefits: Versioning implementations of an object If your methods accept interface parameters in the middle layers, you're free to pass whatever implementations you like in the top layer which ...


4

By not using dependency injection you allow yourself to create permanent connections to other objects. Connections you can hide inside where they'll surprise people. Connections that they can only change by rewriting what you're creating. Rather than that you can use dependency injection (or reference passing if you're old school like me) to make what an ...


14

The most "popular" use case for DI (apart from the "strategy" pattern usage you already described) is probably unit testing. Even if you think there will be only one "real" implementation for an injected interface, in case you do unit testing, there is usually a second one: a "mock" implementation with the only purpose of making an isolated test possible. ...


4

You can do both, depending on the role your class plays in the application. Note that if you go with the second case, you still need to get that data from somewhere, so you'll likely also have some other class that looks like your first example. Regarding the first example: constructors shouldn't do extensive work, and you have no way of guaranteeing that ...


3

First of all, are there other parts of the code (outside of Foo) that need to modify Elements? If not, get rid of that set. Secondly, as a complete aside, a _ suffix normally denotes a field in C#, not a parameter. So I'd change the name to just dataAccess. The rule of thumb on whether you need a mock implementation of IDataAccess is that you need one if a ...


0

I could create role "Administrator" and add to it claims "CanAddItem", "CanUpdateItem", etc., but "CanAddItem" doesn't describe a property of a user. Depending on your point of view, your example may just be a bit too pragmatic. From another point of view, a person who is 21 is also of legal age to drink, but they aren't Can Drink Alcohol right? Back to ...


1

You're correct that the idea of DI is to be able to rely on an abstraction (interface) rather than a concrete implementation, but that is only one piece of the puzzle. You still need to instantiate the actual object somewhere else, before passing in to a constructor or injecting it. The bigger part here is how you create that instance. Since simply new-ing ...


5

So you need to construct something once only. Fine. Have access to main? Great. Build it in main once. Main is only called once. Pass it to everything that needs it. Call that passing "dependency injection" if it makes you feel fancy. Done. Don't have access to main because you're using some annoying framework? Find any method that is called once and only ...


3

SRP is a principle, not a Law. You follow it because generally it leads to better code. Code that breaks it, is not by definition bad. In fact there is a lot of code out there that is arguably good, that does not follow this principle. To put this into context: it is a Law that code must compile. Code that does not compile is by definition very bad code. ...


1

It all depends on how far you are willing to go, without breaking YAGNI principle. Personally, I do not really like having the logic of GetStatistics method in this class and strictly speaking, I think it does break SRP. I would rather have a separate class that reads the data, interprets it, and stores it in the Statistics class, and then inject it into ...


6

The number in the ServiceTypes string must match the the member A, B, C, D, right? So start by providing a function which makes access to those members possible by an index. Something along the lines of: int GetMember(Report report,int j) // I assume lstReport[i] is of type "Report" { switch(j) { case 1: return report.A; case 2: ...


3

Q: Should we fetch the Engine and Model from the database by their ids before building the domain model ? Yes, this's what repositories do. If Car is an aggregate, the repository should be capable of fetching whatever Car needs for its initialization. It might load Engine and Model directly from the data store or ask for them to other components. You also ...


4

Contrary to what the article says, it is actually considered best practice to reference other aggregates by ID, and exactly to solve the kind of issue you are facing (having to load a bunch of related entities to construct the root object, which then leads to performance issues). There's an excellent series of articles by Vaughn Vernon that talks about this ...


0

OK, so the article is weird and wrong. Erase it from your memory. Secondly, don't use DTOs. serialise and deserialise your object. Thirdly, just use public setters on domain objects. You really aren't doing yourself any good by trying not to have them. You can then have: Customer c = Json.DeserialiseObject(jsonstring) You don't even have to write the ...


0

(Having java background) This is actually not the use of the factory pattern. In your case, you simply just create a paramtrized object in another class. As long as the same instance is created, you just outsource the construction without any advantage. Your calling class is still depending on the factory class in a 1:1 relationship. public class ...


Top 50 recent answers are included