Скажем, у меня есть структура XML-файл для импорта в базу данных:Разве добавление новых полей (и/или методов) нарушает OCP (открытый закрытый принцип)?
<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>
Основываясь на первоначальном требовании я создал эту классовую структуру:
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; }
}
Во втором выпуске проекта, мы имели 3 новые требования:
- Полет должен иметь узел назначения
- Все пассажиры должны га в Номер паспорта
- Все американские пассажиры должны иметь номер социального страхования (номер социального страхования)
XML-структура этих требований:
<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>
Вопрос-1: Если изменить код структура, как показано ниже, нарушает принцип Open Close Принцип 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; }
}
Вопрос-2: Как вы думаете, что я должен использовать абстрактный класс для этой структуры для лучшего и более короткого кода? Если да, есть ли какие-либо негативные последствия для проверки?
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; }
}
Что вас беспокоит, следуя за SOLID на зуб или выполняйте свои требования? У вас есть новое требование. Добавление свойства не нарушает никаких правил. Даже если у вас есть потребители вашего кода там, кто ссылается на ваш код, добавление свойства в класс не повредит, если вы не измените интерфейс [как вы обнаружили]. Вы должны задать себе вопрос, кто использует ваш код? Если это всего лишь внутренний код, и у вас есть контроль над полной базой, вы можете сделать что угодно. Если вы хотите поддерживать обратную совместимость во многих случаях, вам нужно использовать абстрактные классы. –
@ T.S. На самом деле, я просто пытаюсь понять принцип открытого/закрытого. Я подготовил этот пример, чтобы понять границы. Насколько я понимаю из нескольких статей, даже у Джона Скита есть некоторые проблемы с этим принципом (ссылка на эту ссылку) (https://codeblog.jonskeet.uk/2013/03/15/the-open-closed-principle- в обзоре/)). –
Все шаблоны программирования, принципы и догмы имеют критику. Вы действительно не должны следовать ни одному из этих вопросов. Это полезно, хотя, если вы объясните кому-то, как что-то работает, что у вас есть подсистема, разработанная с использованием P-шаблона, bla-bla, они вас понимают. Просто посмотри.NET, чтобы лучше понять принцип o-c. .NET во многих случаях имеет интерфейс и абстрактный класс. Таким образом, вы можете написать полностью пользовательский реализованный объект или полагаться на базовую реализацию, предоставленную вам. Но тогда это зависит от вас, вы хотите оставить свой объект открытым или закрытым - закрытым классом. –