Rather new to OOP..
I am gonna build a number of small applications that will support our main business.
These apps:
-Will need some common data classes
-The above classes may change in the future as far as properties are concerned (will add properties when ERP versions advance).
For example i have a class:
public class Lot
{
public string SSCC { get; set; }
public InventoryItem Item { get; set; }
public string DescriptionLocalLot { get; set; }
public string DescriptionEnglishLot { get; set; }
public DateTime ProductionDate { get; set; }
public string Shift { get; set; }
public string WorkOrder { get; set; }
public string ProductionLine { get; set; }
public string BarcodeEAN14 { get; set; }
public decimal Boxes { get; set; }
public decimal Units { get; set; }
public decimal Pieces { get; set; }
public DateTime LastUpdated { get; set; }
public string LastUser { get; set; }
public Warehouse LastWarehouse { get; set; }
public string ProductionLot { get; set; }
public string PalletSequence { get; set; }
}
The above class will be used by almost all applications (Windows forms or ASP pages). Ihave put this definition in a separate file called CommonClasses.
Should i define these classes as Abstract or Interfaces better? In most cases these classes will not include methods.
A class should describe all of an object's properties as well as methods that can act upon it. Not all are going to be used at once; but they are provided so that all the behavior is understood and state of an object can be tracked.
The class described in your code seems like a candidate for a concrete class. It provides a set of properties that are stored in memory and act in relation to one object. If you require additional functionality at a later point, you can extend the class to provide this.
If however, each instance of the class requires different implementation; then you should consider abstract class, or perhaps interface.
You should use concrete classes in your case if the change is common for all applications which are using these classes.
Related
We're attempting to build a somewhat basic reporting system for our analytics team to use. It's our third or fourth iteration of the same system, but we're doing a consolidation and rewrite of a large portion of the backend logic to make generating reports easier going forward.
One issue we're having is forming the interfaces that will be implemented by our reporting widgets in order to push them through to our ViewComponents.
An example of a couple widgets may look something like the following:
public interface IWidget<T>
{
WidgetType WidgetType { get; set; }
string WidgetName { get; set; }
T ViewModel { get; set; }
}
public class ChartWidget : IWidget<Chart>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public Chart ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.Chart;
}
}
public class HeadlineBarWidget : IWidget<HeadlineBarData>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public HeadlineBarData ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.HeadlineBar;
}
}
But the report will contain a collection of widgets, and that collection will need to be iterated over in the View in order to fetch the proper ViewComponents and supply them with the matching model that they expect. Unfortunately, it appears most collection types need to ensure type safety, and I need a way to make this a bit better. As it stands now, our IWidget object defines ViewModel as an object, and I don't think this is a good practice.
Let's say I have an XML file structure to import to a database:
<Flight>
<FlightName>FN 7777</FlightName>
<Passengers>
<American>
<FirstName>Michael</FirstName>
<LastName>Smith</LastName>
</American>
<American>
<FirstName>Jack</FirstName>
<LastName>Brown</LastName>
</American>
<German>
<FirstName>Hans</FirstName>
<LastName>Schaefer</LastName>
</German>
<Ukranian>
<FirstName>Sergei</FirstName>
<LastName>Osipenko</LastName>
<CanSpeakRussian>true</CanSpeakRussian>
</Ukranian>
</Passengers>
</Flight>
Based on initial requirement I created this class structure:
public class Flight
{
public Flight()
{
Passengers = new List<IPassenger>();
}
public string FlightNr { get; set; }
public List<IPassenger> Passengers { get; set; }
public void SomeMethod()
{
...
}
}
public interface IPassenger
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class German : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class American : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Ukranian : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool CanSpeakRussian { get; set; }
}
In the second release of the project, we had 3 new requirements:
Flight must have a Destination node
All passengers must have a Passport Number
All American passengers must have SSN (social security numbers)
The XML structure of these requirements is:
<Flight>
<FlightName>FN 7777</FlightName>
<Destination>Chicago</Destination>
<Passengers>
<American>
<FirstName>Michael</FirstName>
<LastName>Smith</LastName>
<PassportNr>US123456</PassportNr>
<SSN>123-45-6789</SSN>
</American>
<American>
<FirstName>Jack</FirstName>
<LastName>Brown</LastName>
<PassportNr>US556699</PassportNr>
<SSN>345-12-9876</SSN>
</American>
<German>
<FirstName>Hans</FirstName>
<LastName>Schaefer</LastName>
<PassportNr>DE112233</PassportNr>
</German>
<Ukranian>
<FirstName>Sergei</FirstName>
<LastName>Osipenko</LastName>
<CanSpeakRussian>true</CanSpeakRussian>
<PassportNr>UK447788</PassportNr>
</Ukranian>
</Passengers>
</Flight>
Question-1:
If I change the code structure as below, does it break Open Close Principle of SOLID?
public class Flight
{
public Flight()
{
Passengers = new List<IPassenger>();
}
public string FlightNr { get; set; }
public string Destination { get; set; }
public List<IPassenger> Passengers { get; set; }
}
public interface IPassenger
{
string FirstName { get; set; }
string LastName { get; set; }
string PassportNr { get; set; }
}
public class German : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PassportNr { get; set; }
}
public class American : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PassportNr { get; set; }
public string SSN { get; set; }
}
public class Ukranian : IPassenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool CanSpeakRussian { get; set; }
public string PassportNr { get; set; }
}
Question-2:
Do you think that I should use abstract class for this structure for better and shorter code? If so, is there any negative implication for testability?
public class Flight
{
public Flight()
{
Passengers = new List<Passenger>();
}
public string FlightNr { get; set; }
public string Destination { get; set; }
public List<Passenger> Passengers { get; set; }
}
public abstract class Passenger
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PassportNr { get; set; }
}
public class German : Passenger
{
}
public class American : Passenger
{
public string SSN { get; set; }
}
public class Ukranian : Passenger
{
public bool CanSpeakRussian { get; set; }
}
A quote from Agile Principles, Patterns and Practices by Robert Martin (must read):
Modules that conform to OCP have two primary attributes.
They are open for extension. This means that the behavior of the
module can be extended. As the requirements of the application change,
we can extend the module with new behaviors that satisfy those
changes. In other words, we are able to change what the module does.
They are closed for modification. Extending the behavior of a module
does not result in changes to the source, or binary, code of the
module. The binary executable version of the module—whether in a
linkable library, a DLL, or a .EXE file—remains untouched.
(Note that when it says “module”, it doesn't necessarily mean an assembly of some sort, but also smaller-scale things like classes and compilation units.)
What's important here is that it's about behavior. What you have there is a hierarchy of data structures, more or less void of any behavior. So as it stands, it's hard to say whether your code violates OCP or not, as it's not exactly applicable.
Violations of OCP usually come together with some type-based switches or conditionals. Does any behavior of the Flight class depend on what type of passengers it has? If so, it could come in different shapes, such as:
if (passenger is Kefiristani) {
performSuperStrictSecurityChecks(passenger);
}
or move this ugly code into the performSecurityChecks method of the Passenger class, and then in the Flight class just do
passenger.performSecurityChecks(); // non-virtual call
Or just do it the OOP way, hurray polymorphism!
passenger.performSecurityChecks(); // virtual call
Now suppose a new class of passenger, Tumbombalooni, appears, which also requires Super Strict Security Checks. In the first two cases you have to change some code outside of the new class, and that precisely what is meant by that they are not closed. In the last case, you don't have to change anything.
The first example violates SRP, of all things. It may also violate OCP on the assembly level, if your classes are not internal, and someone outside of your assembly may extend them, and now they have to go change your code to make it work. If they are internal, then it's debatable whether it violates OCP or not, but the violation of SRP is even worse anyway.
The second example definitely violates OCP. Extending a class should not force authors of the derived class to change anything in the base classes. In fact, they may not be able to.
The last example doesn't violate OCP. The class is still extendable, and extension doesn't require modifications, just writing new code. That's what OCP is all about.
To answer your original question: does adding new fields (and/or methods) break OCP? No, by itself it doesn't. But when adding or changing something in a derived class forces you to make some changes to the base class(es), then OCP is broken.
One thing about OCP is that it's virtually impossible to never ever break it at all. A certain requirement for a derived class may force you to change something in a base class anyway. If you plan ahead for every possible such change, you risk over-engineering everything, and then something you didn't think of comes and bites you anyway. But when it happens, you could deal with it in different ways, and it's better to add a virtual method to the base class just once and then reimplement this method in new derived classes, rather than falling into the same trap again and again, until your code becomes effectively unmaintainable.
I have threeType MaliOp, LoanEBD, PrmEBD
public class MaliOp
{
public int Id { get; set; }
public int OldId { get; set; }
public byte MaliTable { get; set; }
public string Date { get; set; }
public short OpState { get; set; }
}
public class LoanEBD : MaliOp
{
public int? BId { get; set; }
public int? Loan { get; set; }
public int? PayerBimeGozar { get; set; }
[NotMapped]
public int OldId { get; set; }
}
public class PrmEBD : MaliOp
{
public int? PayerBimeGozar { get; set; }
public int? BId { get; set; }
[NotMapped]
public int OldId { get; set; }
}
the two Entity PrmEBD and LoanEBD Inherit from MaliOp. I want create DBContext in Entity Framework by by using this three types.
I have three Table in Database fro each one of them.
I don't want to use any EF Inhertance Strategy and add each one as Independent Types. but can't and EF Use either one of Inhertance strategy.
How can I do that?
create a IMaliOp Interface and let MaliOp implement it.
let the two classes implement the IMaliOp interface as well
Then use automapper (or something similar) to automatically transfer the information from the Entity object to your regular object.
This two classes would represent DTO (data transfer object). there are many strategies, out there for DTO-s
You should avoid having Classes inherit Entities, otherwise you applications classes will get too tightly coupled, and changes might prove them self to become too painful
In your context, override OnModelCreating;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PrmEBD>().ToTable("PrmEBDs");
modelBuilder.Entity<LoanEBD>().ToTable("LoanEBD");
modelBuilder.Entity<MaliOp>().ToTable("MaliOp");
}
This will create three separate tables in your database.
You will need to make sure that when you do a query over MaliOp, that you don't pull in instances from all three tables. You may want to go wit the approach of creating a common interface for all three, so that they don't actually inherit from each other, too
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
I've read several articles about bunch of EF and DTO, and I need some clarification about using EF Code First and DTO in n-tier scenario with WCF.
Let's look a these classes:
public class Order
{
public int Id { get; set; }
public DateTime ShipDate { get; set; }
public ObservableCollection<OrderDetail> Details { get; private set; }
}
public class OrderDetail
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal Quantity { get; set; }
}
When user want to edit existing order, my client application (WPF MVVM app) requests some DTO, which then being converted to Order instance. Then, user makes some changes in order through UI - e.g., changes ShipDate, removes two positions, modifies one, and adds one.
Now I want to deliver changes to the server. As far as I understand DTO concept, I need to construct some DTO type, containing info about changes has been made:
[DataContract]
public class UpdateOrderDTO
{
[DataMember]
public DateTime ShipDate { get; set; }
[DataMember]
public Collection<OrderDetail> NewDetails { get; private set; }
[DataMember]
public Collection<OrderDetail> ModifiedDetails { get; private set; }
[DataMember]
public Collection<OrderDetail> DeletedDetails { get; private set; }
}
But when, and where should I to create this DTO? I mean, I can't create it on submitting changes - there's no change tracking information in Order class.
Looks like, this object have to be created together with Order after it was requested for edition by user. This allows to track changes... Am I wrong?
Please note, that the question isn't about STEs. For some reasons, I don't want/can't use them in current project.
Thanks a lot for sharing your experience.