There is an application code in which you need to dynamically determine the type of file (HTML or TXT) by content and, depending on the type of file received, call the appropriate processing algorithm.

interface IFileType { void Process(); } class HtmlFile : IFileType { public void Process() { Console.WriteLine("HTML"); } } class TxtFile : IFileType { public void Process() { Console.WriteLine("TXT"); } } class FileTypeHandler { public static IFileType Define(string fileContent) { var file = fileContent.IndexOf("<html"); if (file != -1) { return new HtmlFile(); } else { return new TxtFile(); } } } class FileProcessor { public void ProcessFile(string fileName) { StreamReader fileStream = new StreamReader(File.OpenRead(fileName)); string fileContent = fileStream.ReadToEnd(); fileStream.Close(); var fileType = FileTypeHandler.Define(fileContent); fileType.Process(); } } class Program { static void Main(string[] args) { FileProcessor fileProcessor = new FileProcessor(); fileProcessor.ProcessFile(@"d:\index.html"); Console.ReadKey(); } } 

Conclusion:

HTML

Everything works as it should. I am interested in how flexible my code is to the appearance of new types of files in the future , for example JSON. After all, with the advent of the new class implementing the IFileType interface, the algorithm for determining the type of the content in the class IFileType will also change .

Have I designed everything correctly, regarding the principle of openness / closeness?

  • You can add a method to the interface that will check if the file format is. - Monk
  • I'm more confused about how you define HTML, the rest seems to look normal. How your definition method works for the text: "The opening and closing <html> tags in the document are optional, but ....", it seems to me that it is wrong. Well, actually directly from the quote, and if these tags are not, but the file is still an HTML document? - rdorn
  • @rdorn, I agree with you - the format definition code is not so hot). This algorithm will be constantly changing. The main FileProcessor that his changes are not forced to change the code in the ProcessFile() method of the class FileProcessor . - Adam
  • @adamshakhabov yes, logically, nothing more is needed. When in doubt about the correctness of the format definition, give it to plain text, and raw binary, if even plain text is definitely not recognized. - rdorn
  • I would make a Dictionary of actions instead of if. var dict = new Dictionary <int, Action> (); dict.Add (1, () => doCatThing ()); dict.Add (0, () => doDogThing ()); - user2455111

1 answer 1

I see the following problems in your code.

The FileTypeHandler method contains definition logic for all formats. At this stage, it's not scary, because there are not many of them, but if their number increases, the method will become confusing and difficult to expand.

I recommend creating entities for each format and implementing the definition in them. This will avoid confusion and make it easier to add new ones.

I will give the code, as I would implement in this situation. There are some minor simplifications. I wrote it in java, but I think you will figure it out.

 enum FormatTypes { TXT("txt", new TxtDetector()), HTML("html", new HtmlDetector()); public final String name; private final Detector detector; FormatTypes(String name, Detector detector) { this.name = name; this.detector = detector; } } interface Detector { boolean isCorrectType(String fileName, String content); } class TxtDetector implements Detector { } class HtmlDetector implements Detector { } class DetectorHandler { public static String getType(String fileName) { String content = //Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ содСрТимого for (FormatTypes types : FormatTypes.values()) if (types.detector.isCorrectType(fileName, content)) //просто Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π°, //ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈ нСобходимости Π² FormatTypes ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ ΠΊΠ°ΠΊΡƒΡŽ Ρ‚ΠΎ Π»ΠΎΠ³ΠΈΠΊΡƒ return types.name; throw new IllegalArgumentException("type is not supported"); } } 
  • Unfortunately, the definition of the file type is generally not so easy to decompose. - Pavel Mayorov
  • By the way, if you write in Java - why do you need extra classes at all? All logic could fit in FormatTypes. - Pavel Mayorov
  • @PavelMayorov, yes, the type definition decomposition is complicated. This was the main design complexity in this code. But nevertheless, Artem is not a bad option offered. - Adam
  • @PavelMayorov extra classes are you talking about classes that implement Detector? Of course, the format definition logic can be crammed into enum, but through separate classes in my opinion, a more extensible solution is obtained and it looks better. - Artem Konovalov
  • @PavelMayorov did not understand why the definition of a class is simply not decomposed? What's wrong with my option? Each Detector contains its own logic, it does not depend on others. why is it not decomposition? - Artem Konovalov