How truly "evil" are cyclic namespace dependencies within a single assembly. I understand using multiple assemblies changes everything and something like that wouldn't compile, but what is the real risk of doing it within a single assembly?
No risk at all - feel free to reference anything you want within the same assembly.
However this approach will make you application brittle and hard to scale. A better approach is to try and keep your components as orthogonal as possible.
What the language and compiler allow you to do is not necessarily what is best for long-term developments needs (bug fixes, scaling, new features, etc.). You ought to strive for loose coupling and high cohesion.
namespaces are a way to provide a logical organization to your code. They provide a way to reuse names by applying it within a certain context. There is nothing wrong with having classes in two namespaces depend on each other.
Cyclic depedancies in assemblies is a bit more complex. Last I checked visual studio wouldn't allow this type of relationship directly.
I don't think there are any risks per se, and in some cases it's certainly the natural way of doing things. System.Text.StringBuilder obviously uses System.String, and I'd be very surprised if nothing in the System namespace used StringBuilder in turn.
It's probably worth just checking your design every so often: question whether you should be able to separate the functionality into separate components. Quite often the answer will be "no", at which point just move on with no feeling of guilt :)
Related
I have a confusion with the cyclic references and communication patterns between view and controller(logic) classes.
Below image is a simple UML, which logic and view has their references and can talk with each other freely.
Cyclic reference UML example
But as I know, cyclic references are BAD, veryyy BAD. My friend showed me below UML as an solution to overcome this issue. We can just inherit these classes with interface and reference interfaces to this classes. As he said, its not counted as an cyclic referencing, but in my opinion its just an illusion.
Basic solution UML example
Back to the questions:
Is coupling scripts still bad if they are cohesive little structures in the big chunk of our code.
Does the second UML can be evaluated as better design, instead of first one. And is it cycling references?
Even for the these two cohesive coupled class (but decoupled from all of the other classes in the codebase). Should I implement better solution?
I ve read this blogpost which serves better solutions: https://www.sebaslab.com/the-truth-behind-inversion-of-control-part-i-dependency-injection/ , in the "Object Communication and Dependency Injection" section. Blogger mentiones 4 different communication method. The second UML is I think the first one he mentioned.
Do you guys have better solution, both for view-logic object communication and general whole codebase object communication?
I would not say that cyclical dependencies are always bad. It implies a strong coupling between components, but in some cases is can be useful to use multiple strongly coupled classes instead of a single much larger class.
If you want to reduce coupling, interfaces is the typical way to go. But it might be sufficient with a single interface, i.e. either IController or IView, that should be sufficient to remove any cycles.
However, the common model when writing things like UIs is to follow a Model-View-ViewModel, where the view references the view model, that in turn references the model. This does not really remove the circular references, since the view needs to know when the view model has changed. But it is abstracted by the use of events.
Events and delegates can often be used as a lighter weight alternative to interfaces. There are also patterns using event-managers, where you can send and listen to events of a specific type, without needing direct references between all the objects, but I'm somewhat skeptical of this, since I suspect it could be difficult to get an overview of what objects send and listens to some event-type.
In the end it usually depend on what specifically you want to do. Events are good when you want a fairly loose coupling, but are not well suited for complex interactions. For such cases interfaces might be better, but they do not really add much if classes are strongly coupled. As a rule of thumb when adding interfaces, you should ask yourself: What other implementations of this interface will be made? if the answer is none, then don't add it, at least not for the moment.
I would also not put to much stock on technical interviewers, since poor interview questions seem fairly common.
I realize this question is not completely cut and dry, but in general how do you know when an object has too many types?
I'm currently supporting a project in which I am unfamiliar with the baseline but am tasked to basically do bug fixes in a push to work down the number of items in our SPR database. I keep coming across classes that extend many different interfaces, including one such class which extends a total of twelve. Many others extend 7 or 8.
Now I know it's good design practice to depend on interfaces rather than concrete implementations, but is this going too far? Is this an actual code smell and potentially a sign of bad design, or am I just overreacting and depending on circumstance, it can be normal for a class to extend seven, eight, and even twelve different interfaces? It is tiring grepping through the baseline trying to track down the actual concrete type(s) of an object that implements twelve interfaces.
To be able to prove that code smell you have to answer (correct answers in parethesis):
Is the object in question used to fulfill twelve different purposes? YES
Are those purposes too closely related? NO
Are there porposes for that object that are never used? NO
Are there purposes for that object that are seldom used which can be part of a more generic purpose? NO
Are there purposes which are not purposes at all but just markers used in runtime? NO
There are probably more questions to answer, feel free to add in comments.
As you said, this isn't cut and dry, but it definitely is something worth looking at. I think the best way to answer your question is with another question: "Does each class have a clearly defined purpose and set of responsibilities?" If the answer is Yes, then it might be that the design is fine, or at worst, has interfaces that are too granular.
To help with your searching problem, is there an IDE you can load the code up in to help with visualizing and navigating the inheritance tree?
Although granular interface definitions can be difficult to maintain, in my opinion, I dont see this as a sign of bad design.
Usually this kind of thing is a characteristic of a dynamic, agile system. I.e. One that's function is evolving over time.
Also I see it as a sign that the designer is thinking in a good OO way.
This is not to say that the code could not be refactored and some of the interface definitions merged, indeed this is now a much easier task thanks to all the interface definitions. Imagine trying to refactor the objects otherwise!
A class could extend 12 interfaces, but if those 12 contracts represent an intersection of behavior such that the object still has just one responsibility, that is A-OK. Time and again, in large enterprisey projects the pieces which are most difficult to maintain are the classes which try to do too many different things. Here's an example:
An application which does routing and recommendation for first responders (police, fire, etc) has a class Mapping, which does:
geocoding and reverse geocoding (turning lat & long into an address, and vice-versa)
drawing the map image to screen, with traffic and routing 'highlights'
finding routes between different locations
analyzing traffic patterns provided by third party data sources
The original designer of the system must have thought "well, these are all map & location related tasks, so yeah this should be one class". Unfortunately, this made it impossible to change one of those bits of functionality later because everything was so tightly coupled.
Find seams in the functionality provided by various components in your application. Separate those seams into cohesive contracts (interfaces) between the components, where each unit is capable of providing a valuable 'service' (not in the webservice sense) to its consumers. To go back to my previous example, we eventually broke up the Mapping class (Project Yoko) into:
Geocoder
MapRenderer
RouteRenderer
RouteBuilder
TrafficRenderer (inherited from RouteRenderer)
TrafficDatasource
The individual components had runtime resolved dependencies, which allowed us to introduce Unit and System Tests, finding several bugs in the pre-existing routing logic, besides providing a host of other benefits. In general, if you can see a logical separation of responsibilities in a class, you probably should break it off.
Take a look at some of the classes in .Net's System.Collections.Generic namespace - many of them support 7+ interfaces. It's not something to be worried about (from a design point of view). A class should implement any and all interfaces which it was intended to implement.
So there's not a numeric limit to the number of interfaces a class should implement. The only question is whether those interfaces make sense for the class.
As Eric pointed out, worst case scenario is that the interfaces are too granular. This sounds like it's the case. IMO from a purely design perspective it's the same issue as database over-normalization. If you can manage to consolidate many interfaces even where some things are redundant, and if you can do so without loss of manageability, you should.
I would say this is highly dependent on how broad the range of services covered by those interfaces are. The interface segregation principle encourages splitting large interfaces into smaller, highly cohesive interfaces that may support a very small set of services. If this is the case with the interfaces in codebase that you're working with and the interfaces create a logical grouping of services when combined then it may not be a big deal. If the interfaces are large or seem disparate when grouped then you are dealing with potentially flawed design.
I have been developing some components for our products at work, and one of them is based off the flow layout panel.
What i would like to do is provide a custom designer for it, but without loosing the features provided by it's default designer (System.Windows.Forms.Design.FlowLayoutPanelDesigner) which is marked as internal.
Using Reflector i thought i would just implement it again myself, seeing as it inherits from 'FlowPanelDesignerand that fromPanelDesigner` all of which are internal.
Why would these classes be specifically marked as internal? Is it due to them being specifically for Visual Studio use, and thus not 'framework' code?
Also, is there an easier option that re-implementing all the functionality?
Exposing code from a library has a high cost associayed with it. Exposing from a framework library even higher.
Ii strongly pushes you to maintain binary (and likely source) compatibility for the life of the product. Worse these are just the sort of things that vendors would be tempted to use which would mean that MS breaking any contracts on these classes would likely break a widget used my many hundreds or thousands of paying customers.
Breaking backward compatibility is something MSFT has historically avoided doing (witness the number of interfaces called Foo2, Foo3 and the methods call Blah and BlahEx).
As they have steadily incurred considerable 'debt' in this manner over their life they have realised that avoiding these issues from the very beginning is the cheapest way to reduce such problems in the future. Thus any new public apis must justify their existence very strongly.
Design time code generation is the sort of area that strongly calls for improvements over the lifetime of a software eco-system (look at the partial class changes in VS for a major change in this area but there a many other smaller ones). By exposing classes which are heavily dependent on this infrastructure they would have limited their scope for changing the very infrastructure they view as their competitive advantage.
As such the sensible, safe approach is not to expose such classes. I certainly would have taken the same approach without being a company of Microsoft's size and customer base.
I don't know, but I'll guess Microsoft's answer would be either "That's just the way we made it", or "We wanted to reduce the burden of maintaining backwards compatibility."
I'm creating a library for use with an application that I am building. I am building a name space structure similar to below.
MyNamespace.Validation
MyNamespace.Reports
MyNamespace.Transactions
MyNamespace.DataImport
etc...
Would it be best practice to create a solution with multiple projects for each sub namespace or one project with multiple class files for each sub namespace? Thanks.
There are pros and cons to both approaches, which you need to personally decide between for your own circumstance.
Pro to multiple projects:
Separate assemblies allow the compiler to provide more strict guidance, potentially preventing coupling from creeping through. This allows you to maintain the dependencies better.
Separate assemblies can be loaded as needed in other projects, potentially easing reuse.
Separate assemblies can prevent unnecessary code from being loaded into a process, since they're loaded on demand.
Cons to multiple projects:
More complex deployment, as more files need deployment (minor)
Slower build/compile, and even potentially load times from loading multiple assemblies (minor)
Personally, I think the pros far outweigh the cons in most cases. I typically will split my namespaces into separate assemblies, provided they are not related. In your case, you're working on 4 very different concepts, so my gut feeling is that splitting makes the most sense.
I would say it depends.
First, it's best practice to put each class in its own file.
If you go with one project, I would create folders for each namespace inside that project, and put the code files in the appropriate folder.
Doing the above, Visual Studio will automatically create new class files within the correct namespace
I think the real question here is this though:
If this is only ever going to be used once, putting everything in one project would make sense. However, if this code is going to be reusable, you should think if you would ever reuse just a part (or one sub-namespace) of this library. If the answer is yes, I would break apart the namespaces into separate projects, so in the future, you could only include the projects you needed.
I would go for the one solution with multiple projects.
Advantages:
- Each project can be a separate dll
- All projects in one solution for easy navigating between files
Deciding exactly how to break up your solution is subjective - and it really depends on the specifics of your code.
However, one thing is certain: maintaining multiple assemblies has drawbacks! This article is particularly good at describing those drawbacks, observing how they add costs at development time, compile time, deployment time, and runtime.
I use as few assemblies as possible, aiming for a single assembly while isolating volatile areas of the domain. When multiple assemblies are clearly appropriate or required (and they often are, particularly to enforce decoupling), I do my best to group interfaces that will change at the same time into the same assemblies.
I have usually followed the pattern with one assembly is one namespace and the DLL name is in the namespace. Easier to find what DLLs to reference
I have used OO programming languages and techniques years ago (primarily on C++) but in the intervening time haven't done much with OO.
I'm starting to make a small utility in C#. I could simply program it all without using good OO practice, but it would be a good refresher for me to apply OO techniques.
Like database normalization levels, I'm looking for a checklist that will remind me of the various rules of thumb for a 'good' object oriented program - a concise yes/no list that I can read through occasionally during design and implementation to prevent me from thinking and working procedurally. Would be even more useful if it contained the proper OO terms and concepts so that any check item is easily searchable for further information.
What should be on a checklist that would help someone develop good OO software?
Conversely, what 'tests' could be applied that would show software is not OO?
Objects do things. (Most important point in the whole of OOP!) Don't think about them as "data holders" - send them a message to do something. What verbs should my class have? The "Responsibility-Driven Design" school of thinking is brilliant for this. (See Object Design: Roles, Responsibilities, and Collaborations, Rebecca Wirfs-Brock and Alan McKean, Addison-Wesley 2003, ISBN 0201379430.)
For each thing the system must do, come up with a bunch of concrete scenarios describing how the objects talk to each other to get the job done. This means thinking in terms of interaction diagrams and acting out the method calls. - Don't start with a class diagram - that's SQL-thinking not OO-thinking.
Learn Test-Driven Development. Nobody gets their object model right up front but if you do TDD you're putting in the groundwork to make sure your object model does what it needs to and making it safe to refactor when things change later.
Only build for the requirements you have now - don't obsess about "re-use" or stuff that will be "useful later". If you only build what you need right now, you're keeping the design space of things you could do later much more open.
Forget about inheritance when you're modelling objects. It's just one way of implementing common code. When you're modelling objects just pretend you're looking at each object through an interface that describes what it can be asked to do.
If a method takes loads of parameters or if you need to repeatedly call a bunch of objects to get lots of data, the method might be in the wrong class. The best place for a method is right next to most of the fields it uses in the same class (or superclass ...)
Read a Design Patterns book for your language. If it's C#, try "Design Patterns in C#" by Steve Metsker. This will teach you a series of tricks you can use to divide work up between objects.
Don't test an object to see what type it is and then take action based on that type - that's a code smell that the object should probably be doing the work. It's a hint that you should call the object and ask it to do the work. (If only some kinds of objects do the work, you can simply have "do nothing" implementations in some objects... That's legitimate OOP.)
Putting the methods and data in the right classes makes OO code run faster (and gives virtual machines a chance to optimise better) - it's not just aesthetic or theoretical. The Sharble and Cohen study points this out - see http://portal.acm.org/citation.cfm?doid=159420.155839 (See the graph of metrics on "number of instructions executed per scenario")
Sounds like you want some basic yes/no questions to ask yourself along your way. Everyone has given some great "do this" and "think like that" lists, so here is my crack at some simple yes/no's.
Can I answer yes to all of these?
Do my classes represent the nouns I am concerned with?
Do my classes provide methods for actions/verbs that it can perform?
Can I answer no to all of these?
Do I have global state data that could either be put into a singleton or stored in class implementations that work with it?
Can I remove any public methods on a class and add them to an interface or make them private/protected to better encapsulate the behavior?
Should I use an interface to separate a behavior away from other interfaces or the implementing class?
Do I have code that is repeated between related classes that I can move into a base class for better code reuse and abstraction?
Am I testing for the type of something to decide what action to do? If so can this behavior be included on the base type or interface that the code in question is using to allow more effect use of the abstraction or should the code in question be refactored to use a better base class or interface?
Am I repeatedly checking some context data to decided what type to instantiate? If so can this be abstracted out into a factory design pattern for better abstraction of logic and code reuse?
Is a class very large with multiple focuses of functionality? If so can I divide it up into multiple classes, each with their own single purpose?
Do I have unrelated classes inheriting from the same base class? If so can I divide the base class into better abstractions or can I use composition to gain access to functionality?
Has my inheritance hierarchy become fearfully deep? If so can I flatten it or separate things via interfaces or splitting functionality?
I have worried way too much about my inheritance hierarchy?
When I explain the design to a rubber ducky do I feel stupid about the design or stupid about talking to a duck?
Just some quick ones off the top of my head. I hope it helps, OOP can get pretty crazy. I didn't include any yes/no's for more advanced stuff that's usually a concern with larger apps, like dependency injection or if you should split something out into different service/logic layers/assemblies....of course I hope you at least separate your UI from your logic.
Gathered from various books, famous C# programmers, and general advice (not much if any of this is mine; It is in the sense that these are various questions i ask myself during development, but that's it):
Structs or Classes? Is the item you're creating a value of it's own, make it a struct. If it's an "object" with attributes and sub-values, methods, and possibly state then make it an object.
Sealed Classes: If you're going to be creating a class and you don't explicitly need to be able to inherit from it make it sealed. (I do it for the supposed performance gain)
Don't Repeat Yourself: if you find yourself copy-past(a/e)ing code around then you should probably (but not always) rethink your design to minimize code duplication.
If you don't need to provide a base implementation for a given abstract class turn it into an interface.
The specialization principle: Each object you have should only do one thing. This helps avoid the "God-object".
Use properties for public access: This has been debated over and over again, but it's really the best thing to do. Properties allow you to do things you normally can't with fields, and it also allows you more control over how the object is gotten and set.
Singletons: another controversial topic, and here's the idea: only use them when you Absolutely Need To. Most of the time a bunch of static methods can serve the purpose of a singleton. (Though if you absolutely need a singleton pattern use Jon Skeet's excellent one)
Loose coupling: Make sure that your classes depend on each other as little as possible; make sure that it's easy for your library users to swap out parts of your library with others (or custom built portions). This includes using interfaces where necessary, Encapsulation (others have mentioned it), and most of the rest of the principles in this answer.
Design with simplicity in mind: Unlike cake frosting, it's easier to design something simple now and add later than it is to design complex now and remove later.
I might chuck some or all of this out the door if i'm:
Writing a personal project
really in a hurry to get something done (but i'll come back to it later.... sometime..... ;) )
These principles help guide my everyday coding and have improved my coding quality vastly in some areas! hope that helps!
Steve McConnell's Code Complete 2 contains a lot of ready to use checklists for good software construction.
Robert C. Martin's Agile Principles, Patterns, and Practices in C# contains a lot of principles for good OO desgin.
Both will give you a solid foundation to start with.
Data belongs with the code that operates on it (i.e. into the same class). This improves maintainability because many fields and methods can be private (encapsulation) and are thus to some degree removed from consideration when looking at the interaction between components.
Use polymorphism instead of conditions - whenever you have to do different things based on what class an object is, try to put that behaviour into a method that different classes implement differently so that all you have to do is call that method
Use inheritance sparingly, prefer composition - Inheritance is a distinctive feature of OO programming and often seen as the "essence" of OOP. It is in fact gravely overused and should be classified as the least important feature
Have I clearly defined the
requirements? Formal requirements documentation may not be necessary, but you should have a clear vision before you begin coding. Mind-mapping tools and prototypes or design sketches may be good alternatives if you don't need formal documentation. Work with end-users and stakeholders as early as possible in the software process, to make sure you are implementing what they need.
Am I reinventing the wheel? If you are coding to solve a common problem, look for a robust library that already solves this problem. If you think you might already have solved the problem elsewhere in your code (or a co-worker might have), look first for an existing solution.
Does my object have a clear, single purpose? Following the principle of Encapsulation, an object should have behavior together with the data that it operates on. An object should only have one major responsibility.
Can I code to an interface? Design By Contract is a great way to enable unit testing, document detailed, class-level requirements, and encourage code reuse.
Can I put my code under test? Test-Driven Development (TDD) is not always easy; but unit tests are invaluable for refactoring, and verifying regression behavior after making changes. Goes hand-in-hand with Design By Contract.
Am I overdesigning? Don't try to code a reusable component. Don't try to anticipate future requirements. These things may seem counterintuitive, but they lead to better design. The first time you code something, just implement it as straightforwardly as possible, and make it work. The second time you use the same logic, copy and paste. Once you have two working sections of code with common logic, you can easily refactor without trying to anticipate future requirements.
Am I introducing redudant code? Don't Repeat Yourself (DRY) is the biggest driving principal of refactoring. Use copy-and-paste only as a first step to refactoring. Don't code the same thing in different places, it's a maintenance nightmare.
Is this a common design pattern, anti-pattern, or code smell? Be familiar with common solutions to OO design problems, and look for them as you code - but don't try to force a problem to fit a certain pattern. Watch out for code that falls into a common "bad practice" pattern.
Is my code too tightly coupled? Loose Coupling is a principle that tries to reduce the inter-dependencies between two or more classes. Some dependencies are necessary; but the more you are dependent on another class, the more you have to fix when that class changes. Don't let code in one class depend on the implementation details of another class - use an object only according to its contract.
Am I exposing too much information? Practice information hiding. If a method or field doesn't need to be public, make it private. Expose only the minimum API necessary for an object to fulfill its contract. Don't make implementation details accessible to client objects.
Am I coding defensively? Check for error conditions, and Fail Fast. Don't be afraid to use exceptions, and let them propagate. In the event your program reaches an unexpected state, it's much, much better to abort an operation, log a stack trace for you to work with, and avoid unpredictable behavior in your downstream code. Follow best practices for cleaning up resources, such as the using() {} statement.
Will I be able to read this code in six months? Good code is readable with minimal documentation. Put comments where necessary; but also write code that's intuitive, and use meaningful class, method, and variable names. Practice good coding style; if you're working on a team project, each member of the team should write code that looks the same.
Does it still work? Test early, test often. After introducing new functionality, go back and touch any existing behavior that might have been affected. Get other team members to peer review and test your code. Rerun unit tests after making changes, and keep them up to date.
One of the best sources would be Martin Fowler's "Refactoring" book which contains a list (and supporting detail) of object oriented code smells that you might want to consider refactoring.
I would also recommend the checklists in Robert Martin's "Clean Code".
SOLID
DRY
TDD
Composition over inheritance
Make sure you read up and understand the following
Encapsulation
(Making sure you only expose the minimal state and functionality to get the job done)
Polymorphism
(Ability for derived objects to behave like their parents)
The difference between and interface and an abstract class
(An abstract class allows
functionality and state to be shared
with it's descendants, an interface
is only the promise that the
functionality will be implemented)
I like this list, although it might be a little dense to be used as a checklist.
UML - Unified Modeling Language, for object modeling and defining the structure of and relationships between classes
http://en.wikipedia.org/wiki/Unified_Modeling_Language
Then of course the programming techniques for OO (most already mentioned)
Information Hiding
Abstraction
Interfaces
Encapsulation
Inheritance / Polymorphism
Some of the rules are language agnostic, some of the rules differ from language to language.
Here are a few rules and comments that contradict some other the previously posted rules:
OO has 4 principles:
Abstraction, Encapsulation, Polymorphism and Inheritence.
Read about them and keep them in mind.
Modelling - Your classes are supposed to model entities in the problem domain:
Divide the problem to sub-domains (packages/namespaces/assemblies)
then divide the entities in each sub-domain to classes.
Classes should contain methods that model what objects of that type do.
Use UML, think about the requirements, use-cases, then class diagrams, them sequences.
(applicable mainly for high-level design - main classes and processes.)
Design Patterns - good concept for any language, implementation differs between languages.
Struct vs. class - in C# this is a matter of passing data by value or by reference.
Interface vs. base-class, is a base-class, does an interface.
TDD - this is not OO, in fact, it can cause a lack of design and lead to a lot of rewriting. (Scrum for instance recommends against it, for XP it is a must).
C#'s Reflection in some ways overrides OO (for example reflection based serialization), but it necessary for advanced frameworks.
Make sure classes do not "know of" other classes unless they have to, dividing to multiple assemblies and being scarce with references helps.
AOP (Aspect Oriented Programming) enhances OOP, (see PostSharp for instance) in a way that is so revolutionary that you should at least look it up and watch their clip.
For C#, read MS guidelines (look up guidelines in VS's MSDN help's index),
they have a lot of useful guidelines and conventions there
Recommended books:
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
C# 3.0 in a Nutshell