hoping a grandmaster can shed some light. Very high overview is that I am no beginner to coding, but still new to OOP. This set of message classes is at the heart of a large simulation application we're writing, and I don't want to do it stupidly--this interface cuts the application in half, from sequencer to executer and vice-versa.
My question is whether or not it's a bad idea to have an inheritance hierarchy this deep (image is not yet fleshed out, might go 5 or 6 deep in the end). This is as opposed to having some of the child classes just have a directed association to their parent class, instead of inheriting.
I've read that a deep inheritance hierarchy is not a good idea, and that if a child class is inheriting simply to have the parent's data, then you should simply include the parent as data in the child, but I'm having a hard time wrapping my head around why. What bad thing is going to happen to us if I decided to make an inheritance hierarchy 7-deep or something like that? Clearly there's a small performance hit, and changing things at the top of the hierarchy is going to have huge ripples throughout the app, but other than that I don't see an issue. Aside, I care little about minor differences in performance.
(bonus question: Is there an off-the-shelf package that handles this kind of stuff? We have most of the low level physical simulations handled, but the sequencing program we're going to have to write. I just have this suspicion that what I've laid out is very similar to what about 10,000 simulation developers before me did.)
(bonus question #2: any masters of both simulation systems and OOP programming, that would not hate living in Los Angeles? We're hiring.)
that if a child class is inheriting simply to have the parent's data
This is a bad idea. There's this understanding that you define base classes as the most generic of contracts that a set of (concrete) classes are going to honor. This typically means that your contract is about behavior and not implementation.
What bad thing is going to happen to us if I decided to make an inheritance hierarchy 7-deep or something like that?
The major issues here are mundane:
Fragile base classes (changes to base are a nightmare for the derived)
Increased coupling (with too many base classes comes tight coupling)
Encapsulation weakens
Testing issues (leaf level overridden methods can't just be tested to reproduce end-user behavior correctly always due to multiple chained calls here and there)
Maintenance (comes from strong coupling)
(You many want to peruse this paper on Why Ada isn't popular, particularly, Item 6, para 6.)
Is there an off-the-shelf package that handles this kind of stuff?
I'm not sure what you are looking for, but if you're looking for an automated hierarchy simplifier then I don't know of any. Also if such a package exists it'll be highly dependent on your language of choice and you haven't mentioned one.
Note that most of the times such issues can be resolved by looking at alternatives like aggregation or traits or dependency injection or whatever. These are design time issues and are typically (IMO) best ironed out on a whiteboard than with a compiler and millions of LOC.
Seeing this question quite late, but I have had many thoughts on this and have been bitten with deep inheritance hierarchies. One reason they are bad is because you will inevitably get the classification wrong as you specialize the many subclasses. However, once you have the class structure in place it will be hard to change because doing so would break client code.
I blogged about this here.
Old question, but active issue in software development and wanted to add an opinion that may help.
Maintenance overhead can't be estimated when you touch the base classes with DI. This is a major drawback that recently affected our 3 level deep inheritance structure.
Also, if you base is a template, expect to violate SOL(I)(D) if you have too many children with just 1 derived parent in 3 levels for example.
Generally, just to access data I'd choose an adequate design pattern or pass the data pointer if it doesn't violate SOLID. Depending on whether you just read or write, I'd also avoid getters and setters to avoid the Quasi-Classes. It's rare case that default children are 'protected' and I think the structure in this case is a candidate to be flawed by design.
Related
I’m build a calendar/entry/statistics application using quite complex models with a large number of relationships between models.
In general I’m concerned of performance, and are considering different strategies and are looking for input before implementing the application.
I’m completely new to DBContextPooling so please excuse me for possible stupid questions. But has DBContextPooling anything to do with the use of multiple DBContext classes, or is the use related to improved performance regardless of a single or multiple DBContext?
I might end up implementing a larger number of DBsets, or should I avoid it? I’m considering to create multiple DBContext Classes for simplicity, but will this reduce memory use and improve performance? Would it be better/smarter to split the application into smaller projects?
Is there any performance difference in using IEnumerable vs ICollection? I’m avoiding the use of lists as much as possible. Or would it be even better to use IAsyncEnumerable?
Most of your performance pain points will come from a complex architecture that you have not simplified. Managing a monolithic application result in lots of unnecessary 'compensating' logic when one use case is treading on the toes of another and your relationships are so intertwined.
Optimisations such as whether to use Context Pooling or IEnumerable vs ICollection can come later. They should not affect the architecture of your solution.
If your project is as complex as you suggest, then I'd recommend you read up on Domain Driven Design and Microservices and break your application up into several projects (or groups of projects).
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/
Each project (or group of projects) will have its own DbContext to administer the entities within that project.
Further, each DbContext should start off by only exposing Aggregate Roots through the DbSets. This can mean more database activity than is strictly necessary for a particular use case but best to start with a clean architecture and squeeze that last ounce of performance (sometimes at the cost of architectural clarity), if and when needed.
For example if you want to add an attendee to an appointment, it can be appealing to attack the Attendee table directly. But, to keep things clean, and considering an attendee cannot exist without an appointment, then you should make appointment the aggregate root and only expose appointment as an entry point for the outside world to attack. That appointment can be retrieved from the database with its attendees. Then ask the appointment to add the attendees. Then save the appointment graph by calling SaveChanges on the DbContext.
In summary, your Appointment is responsible for the functionality within its graph. You should ask Appointment to add an Attendee to the list instead of adding an Attendee to the Appointment's list of attendees. A subtle shift in thinking that can reduce complexity of your solution an awful lot.
The art is deciding where those boundaries between microservices/contexts should lie. There can be pros and cons to two different architectures, with no clear winner
To your other questions:
DbContext Pooling is about maintaining a pool of ready-to-go instantiated DbContexts. It saves the overhead of repeated DbContext instantiation. Probably not worth it, unless you have an awful lot of separate requests coming in and your profiling shows that this is a pain point.
The number of DbSets required is alluded to above.
As for IEnumerable or ICollection or IList, it depends on what functionality you require. Here's a nice simple summary ... https://medium.com/developers-arena/ienumerable-vs-icollection-vs-ilist-vs-iqueryable-in-c-2101351453db
Would it be better/smarter to split the application into smaller
projects?
Yes, absolutely! Start with architectural clarity and then tweak for performance benefits where and when required. Don't start with performance as the goal (unless you're building a millisecond sensitive solution).
In his post SOLID: the next step is Functional, Mark Seemann states:
If you keep driving your design towards smaller and smaller interfaces, you'll eventually arrive at the ultimate Role Interface: an interface with a single method [...] If you apply the SRP and ISP like that, you're likely to evolve a code base with many fine-grained classes that each have a single method. That has happened to me more than once.
My concern is about cohesion of such classes. Does this approach drive to
functional cohesion? Are those classes incohesive?
Is there a bad influence on code coherence?
There's a great definition of cohesion presented in the book Growing object oriented software guided by tests, that states the following:
An element’s cohesion is a measure of whether its responsibilities
form a meaningful unit. For example, a class that parses both dates
and URLs is not coherent, because they’re unrelated concepts. Think of
a machine that washes both clothes and dishes—it’s unlikely to do both
well. At the other extreme, a class that parses only the punctuation
in a URL is unlikely to be coherent, because it doesn’t represent a
whole concept. To get anything done, the programmer will have to find
other parsers for protocol, host, resource, and so on. Features with
“high” coherence are easier to maintain.
This probably goes into the subjective territory pretty quickly, but I would argue that SRP and cohesion are both directly related and orthogonal concepts sometimes. If you have classes with only one method, then sure, it's cohesive in a sense that it does one thing only. But also, you lose something as well, ie. the class is now too fine grained to be useful by itself.
In a functional style, having such classes makes a lot of sense. It's all about composing functions to achieve a result. C# makes this style possible, but also pretty verbose as well, so I completely agree with Seemann when he argues for F# in the case you are designing your codebase in such a manner anyway.
The question of is this good or bad design is a subjective one, but I think we can say a few things objectively. One method classes are by their nature almost guaranteed to respect the SRP (sure, you can still miss the point and make god classes with an all powerful method). So code written in such a way should have all the benefits we would expect, ie. be loosely coupled, composable and maintainable. But there is something to say about losing the big picture of such code as well.
I would argue that some combination of the two is required in most cases, leaning towards classes with a single method in most of the codebase. For example, you could write most of your low level code like a reusable collection of libraries, having such classes. Once you get closer to the API level, you would compose such classes to get the logic you want, and then expose such logic to your clients as more cohesive chunks of functionality. Clients would get the benefit of having a more cohesive high level code paths to follow, leading to more convenient use and greater discoverability of functionality your library supports, while also having all the benefits of having your low level code being written in such a way to be maintainable and flexible to change.
So, I'm working on new software, but I have no choice but to brownfield the database. I would like to use Entity Framework where it makes sense.
Here's my dilemma:
Since the tables are very wide, and I can't change this, I will probably make heavy use of projection to limit the width of the datasets that I query.
I do want to make use of navigation properties where it makes sense
From what I've seen, a lot of people use a model where there is a single DbContext class for the whole project.
So,
I'm weighing these pro's and cons, and I'm wondering what the established best practices might be:
Use 1 DbContext.
There could be A LOT of "pollution" here, with bunches of projections of the data inside of the 1 context class. This sounds like it could become a maintenance nightmare.
Don't make my projections dbsets at all -- just make them plain old objects and select new MyProject {..} into them.
This offers the benefit of keeping my projections in module-specific assemblies and namespaces, but now I get NO navigation/lazy loading/ etc.
Be evil?? and use multiple DbContexts?
I'm not really sure what the maintenance story looks like here, but I'm kind of starting to lean in this direction. My biggest problem with it is that it feels like I'm swimming against the current -- not many people seem to do this, but for a large system, it seems like it could be the best option.
Thoughts?
I think you must use POCO or DTO for data transfer between different layers of application. Use ViewModel to send data to View.
Consider using Repository Pattern and UoW to have a better and efficient architecture in this scenario. Limit the use of navigation properties till repository otherwise they makes entity heavy while transferring those across layers (Use POCO or DTO).
If you are doing as above, then I do not think using multiple DbContexts would give you any benefit. Thanks.
currently working on a GUI application using JavaFX 2 as framework. Used in Java allready and know the principles of data binding.
As the functional style programming in scala advocates the use of imutable values (vals), there is a gap.
Is there an other solution than having an mutable fx-property based presentation model for the gui and and immutable model for application logic with an conversion layer?
Greets,
Andreas
Since your question is a bit vague, please forgive if this is largely based on personal opinion: There are, to my knowledge, no other approaches to the mutable property model. I would however argue that you don't want one:
First of, functional programming, at least from a puristic point of view, attempts to avoid side effects. User interfaces, however, are exclusively about causing side effects. There is a slight philosophical mismatch to begin there.
One of the main benefits of immutable data is that you don't have to deal with control structures to avoid concurrent modification. However, JavaFX's event queue implements a very strict single-threaded approach with an implicit control of read and write access. On the other hand, user interface components fit the idea of mutable objects better than most other fields of programming. The node structure is, after all, an inherent hierarchy of stateful components.
Considering this, I think trying to force a functional and immutable paradigm on JavaFX is not going to work out. Instead, I would recommend building a translation layer based on keypath selections - e.g. binding a Label to display an (immutable) Person's name to the Person, not the name property, and having a resolver handle the access to the name attribute. Basically, this would mean having a combination of Bindings#select and a JavaBeanStringProperty.
We are developing an extension (in C# .NET env.) for a GIS application, which will has predefined types
for modeling the real world objects, start from GenericObject, and goes to more specific types like Pipe and Road with their detailed properties and methods like BottomOfPipe, Diameter and so on.
Surely, there will be an Object Model, Interfaces, Inheritance and lots of other essential parts in the TypeLibrary, and by now we fixed some of them. But as you may know, designing an Object Model is a very ambiguous work, and (I as much as I know), can be done in many different ways and many different results and weaknesses.
Is there any distinct rules in designing O.M.: the Hierarchy, the way of defining Interfaces, abstract and coclasses enums?
Any suggestion, reference or practice?
A couple of good ones:
SOLID
Single responsibility principle
Open/closed principle
Liskoff substitution principle
Interface segregation principle
Dependency inversion principle
More information and more principles here:
http://mmiika.wordpress.com/oo-design-principles/
Check out Domain-Driven Design: Tackling Complexity in the Heart of Software. I think it will answer your questions.
what they said, plus it looks like you are modeling real-world entities, so:
restrict your object model to exactly match the real-world entities.
You can use inheritance and components to reduce the code/model, but only in ways that make sense with the underlying domain.
For example, a Pipe class with a Diameter property would make sense, while a DiameterizedObject class (with a Diameter property) with a GeometryType property of GeometryType.Pipe would not. Both models could be made to work, but the former clearly corresponds to the problem domain, while the latter implements an artificial (non-real-world) perspective.
One additional clue: you know you've got the model right when you find yourself discovering new features in the code that you didn't plan from the start - they just 'naturally' fall out of the model. For example, your model may have Pipe and Junction classes (as connectivity adapters) sufficient to solve the immediate problem of (say) joining different-diameter pipes to each other and calculating flow rates, maximum pressures, and structural integrity. You later realize that since you modeled the structural and connectivity properties of the Pipes and Junctions accurately (within the requirements of the domain) you can also create a JungleGym object from connected pipes and correctly calculate how much structural load it will bear.
This is an extreme example, but it should get the point across: correct object models support extension and often manifest beneficial unexpected properties and features (not bugs!).
The Liskov Substitution Principle, often expressed in terms of "is-a".
Many examples of OOP would be better off making use of "has-a" (in c++ private inheritance or explicit composition) rather than public inheritance ("is-a")
Getting Inheritance right is hard. Doing so with interfaces (pure virtual classes) is often easier than for base/sub classes
Check out the "principles" of Object oriented design. These have guidelines for all the questions you ask.
References:
"Object oriented software construction" by Robert Martin
http://www.objectmentor.com/resources/publishedArticles.html
Checkout the "Design Principles" articles at the above site. They are the best references available.
"BottomOfPipe"? Is that another way of saying the depth of the Pipe below the Road?
Any kind of design is difficult and can be done different ways. There are no guarantees that your design will work when you create it.
The advantage that people who design ball bearings and such have is many more years of experience and data to determine what works and what does not. Software doesn't have as much time or hard data.
Here's some advice:
Inheritance means IS-A. If that doesn't hold, don't use inheritance.
A deep hierarchy is probably a sign of trouble.
From Scott Meyers: Make non-leaf classes interfaces or abstract.
Prefer composition to inheritance.