Avatar billede Henrik_B Novice
10. april 2025 - 19:47 Der er 10 kommentarer

Vejledning i god opbygning af program, erklæring af lister og modeller.

Jeg har et par grundlæggende spørgsmål omkring data og lister af data. Jeg leder efter vejledning i hvor jeg erklærer mine variable, og hvordan jeg loader mine lister smartest.

Jeg benytter C# i Visual Studio Community 2022. Jeg forsøger at opbygge tingene efter samme opskrift som beskrevet af Tim Corey (Youtube).

Jeg har et par lister i mit program. De er af en kompleks type, som jeg læser ind fra hver sin tekst-fil. Jeg kan godt lave modeller til hver type, jeg kan også godt lave en liste med typerne, og fylde dem op. Spørgsmålet er bare om jeg kan gøre det smartere.

I mit hovedprogram har jeg min main-procedure og mine lister erklæret.

public partial class MainForm : Form
{
  public static List<ForsteModel> ForsteListe = new();
  public MainForm()
  {
      InitializeComponent();
      loadForste(Path);
  }
}

Jeg vil gerne lave en funktion, der kan erstatte new() på listen. Altså noget a'la

public static List<ForsteModel> ForsteListe = LoadForste(Path);

Mine spørgsmål er :

1. Er det det rigtige sted at erklære mine lister ? Altså i main proceduren ?
2. Hvordan (og hvor) vil en professionel lave en loadfunktion til en liste ? I main, i et ListLibrary, eller sammen med objektet i ModelLibrary ?
3. Tim Corey siger at alle modeller skal ligge i et ModelLibrary. Skal alle load-af-lister så ligge i et ListLibrary ?

M.v.h. Cobol-programmøren
Avatar billede arne_v Ekspert
10. april 2025 - 21:28 #1
Der er forskellige måder at gøre noget sådant på.

Men jeg tænker noget a la:


namespace Model
{
    public class Noget
    {
        ...
    }
    ...
}


namespace DataAccess
{
    public class DataLoader
    {
        public List<Noget> loadNoget()
        {
            ...
        }
        ...
    }
    ...
}


public class Application
{
    private List<Noget> noget;
    public Application()
    {
        DataLoader loader = new DataLoader();
        noget = loader.loadNoget();
        ...
    }
    public void Run()
    {
      ...
    }
    ...
}
public class Program
{
    public static void Main(string[] args)
    {
        Application app = new Application();
        app.Run();
    }
}
Avatar billede arne_v Ekspert
11. april 2025 - 19:09 #2
Avatar billede Jordegern Seniormester
12. april 2025 - 12:28 #3
Jeg har en kommentar til dit spørgsmål.
Jeg skriver frit fra leveren.

Du spørger om det kan gøres smartere.
Lige meget hvad man taster og hvor lang tid man bruger på det, kan det altid gøres smartere.
Hvis du har tastet noget der virker, så brug det.

Så spørger du om det rigtige sted at loade listerne.
Det rigtige sted er hurtigst muligt.
Så er tingene klar, når de skal bruges.

Hvis jeg skal komme med et uopfordret godt råd, så bliv færdig, og så videre ud over stepperne.
Avatar billede arne_v Ekspert
13. april 2025 - 02:32 #4
OK. Udfra din signatur antager jeg at du kender Cobol godt. Lad mig prøve at illustrere med udgangspunkt i Cobol!
Avatar billede arne_v Ekspert
13. april 2025 - 02:33 #5
data.txt:


1 AAA
2 BBB
3 CCC
Avatar billede arne_v Ekspert
13. april 2025 - 02:34 #6
orig.cob:


identification division.
program-id. orig.

environment division.
input-output section.
file-control.
    select in-file assign to "data.txt" organization is line sequential.

data division.
file section.
fd in-file.
01 in-record.
    03 in-iv pic 9(1) display.
    03 in-space pic x(1).
    03 in-sv pic x(3).
working-storage section.
01 eof-flag pic x.
01 num-data pic s9(9) comp.
01 i pic s9(9) comp.
01 temp pic x(3).
01 data-record occurs 100 times.
    03 data-iv pic 9(1) display.
    03 data-sv pic x(10).

procedure division.
main-paragraph.
    perform read-paragraph
    perform modify-paragraph
    perform dump-paragraph
    stop run.
read-paragraph.   
    open input in-file
    move 'N' to eof-flag
    move 0 to num-data
    perform until eof-flag = 'Y'
        read in-file
            at end move 'Y' to eof-flag
            not at end perform
                compute num-data = num-data + 1
                move in-iv to data-iv(num-data)
                move in-sv to data-sv(num-data)
            end-perform
        end-read
    end-perform
    close in-file.
modify-paragraph.
    perform varying i from 1 by 1 until i > num-data
        compute data-iv(i) = data-iv(i) + 1
        move data-sv(i) to temp
        string "|" delimited by size temp delimited by size "|" delimited by size into data-sv(i)
    end-perform.
dump-paragraph.
    perform varying i from 1 by 1 until i > num-data
        display data-iv(i) " " data-sv(i)
    end-perform.


Tested med GnuCOBOL.

Måske ikke helt optimal kode. Jeg er ikke specielt god til Cobol.
Avatar billede arne_v Ekspert
13. april 2025 - 02:35 #7
Først laver vi en C# version med næsten samme struktur som Cobol d.v.s. en masse static data og metoder.

OneToOne.cs:


using System;
using System.Collections.Generic;
using System.IO;

public class Data
{
    public int Iv { get; set; }
    public string Sv { get; set; }
}

public class Program
{
    private static IList<Data> lst = new List<Data>();
    public static void Main(string[] args)
    {
        Read();
        Modify();
        Dump();
    }
    public static void Read()
    {
        using(StreamReader sr = new StreamReader("data.txt"))
        {
            string line;
            while((line = sr.ReadLine()) != null)
            {
                lst.Add(new Data { Iv = int.Parse(line.Substring(0, 1)), Sv = line.Substring(2, 3) });
            }
        }
    }
    public static void Modify()
    {
        foreach(Data o in lst)
        {
            o.Iv = o.Iv + 1;
            o.Sv = "|" + o.Sv + "|";
        }
    }
    public static void Dump()
    {
        foreach(Data o in lst)
        {
            Console.WriteLine("{0} {1}", o.Iv, o.Sv);
        }
    }
}
Avatar billede arne_v Ekspert
13. april 2025 - 02:36 #8
Så går vi lidt OO med non+static data og metoder.

FirstOO.cs:


using System;
using System.Collections.Generic;
using System.IO;

public class Data
{
    public int Iv { get; set; }
    public string Sv { get; set; }
}

public class Application
{
    private IList<Data> lst = new List<Data>();
    public void Read(string fnm)
    {
        using(StreamReader sr = new StreamReader(fnm))
        {
            string line;
            while((line = sr.ReadLine()) != null)
            {
                lst.Add(new Data { Iv = int.Parse(line.Substring(0, 1)), Sv = line.Substring(2, 3) });
            }
        }
    }
    public void Modify()
    {
        foreach(Data o in lst)
        {
            o.Iv = o.Iv + 1;
            o.Sv = "|" + o.Sv + "|";
        }
    }
    public void Dump()
    {
        foreach(Data o in lst)
        {
            Console.WriteLine("{0} {1}", o.Iv, o.Sv);
        }
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        Application app = new Application();
        app.Read("data.txt");
        app.Modify();
        app.Dump();
    }
}
Avatar billede arne_v Ekspert
13. april 2025 - 02:37 #9
Så lidt flere klasser. Reelt en forberedelse til næste trin.

MoreOO.cs


using System;
using System.Collections.Generic;
using System.IO;

public class Data
{
    public int Iv { get; set; }
    public string Sv { get; set; }
}

public class TextReader
{
    public IList<Data> Read(string fnm)
    {
        IList<Data> res = new List<Data>();
        using(StreamReader sr = new StreamReader(fnm))
        {
            string line;
            while((line = sr.ReadLine()) != null)
            {
                res.Add(new Data { Iv = int.Parse(line.Substring(0, 1)), Sv = line.Substring(2, 3) });
            }
        }
        return res;
    }
}

public class ConsoleDumper
{
    public void Dump(IList<Data> lst)
    {
        foreach(Data o in lst)
        {
            Console.WriteLine("{0} {1}", o.Iv, o.Sv);
        }
    }
}

public class Application
{
    private IList<Data> lst;
    private TextReader rd;
    private ConsoleDumper dmp;
    public Application()
    {
        rd = new TextReader();
        dmp = new ConsoleDumper();
    }
    public void Read(string fnm)
    {
        lst = rd.Read(fnm);
    }
    public void Modify()
    {
        foreach(Data o in lst)
        {
            o.Iv = o.Iv + 1;
            o.Sv = "|" + o.Sv + "|";
        }
    }
    public void Dump()
    {
        dmp.Dump(lst);
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        Application app = new Application();
        app.Read("data.txt");
        app.Modify();
        app.Dump();
    }
}
Avatar billede arne_v Ekspert
13. april 2025 - 02:40 #10
Og så er vi klar til at dele vores program op i:
* DomainModel
* DataAccess
* Presentation
* Demo

Og det er en opdeling som svarer til den opdeling du har h'rt om (omend jeg nok har lavet det lidt anderledes).

AdvOO.cs:


using System;
using System.Collections.Generic;
using System.IO;

namespace DomainModel
{
    public class Data
    {
        public int Iv { get; set; }
        public string Sv { get; set; }
    }
}

namespace DataAccess
{
    using DomainModel;
    public interface IReader
    {
        public IList<Data> Read(string loc);   
    }
    public enum ReaderType { TEXT }
    public class ReaderFactory
    {
        public static IReader Get(ReaderType typ)
        {
            switch(typ)
            {
                case ReaderType.TEXT:
                    return new TextReader();
                default:
                    throw new Exception("Unknown reader type");
            }
        }
    }
    internal class TextReader : IReader
    {
        public IList<Data> Read(string fnm)
        {
            IList<Data> res = new List<Data>();
            using(StreamReader sr = new StreamReader(fnm))
            {
                string line;
                while((line = sr.ReadLine()) != null)
                {
                    res.Add(new Data { Iv = int.Parse(line.Substring(0, 1)), Sv = line.Substring(2, 3) });
                }
            }
            return res;
        }
    }
}

namespace Presentation
{
    using DomainModel;
    public interface IDumper
    {
        public void Dump(IList<Data> lst);
    }
    public enum DumperType { CONSOLE }
    public class DumperFactory
    {
        public static IDumper Get(DumperType typ)
        {
            switch(typ)
            {
                case DumperType.CONSOLE:
                    return new ConsoleDumper();
                default:
                    throw new Exception("Unknown dumper type");
            }
        }
    }
    internal class ConsoleDumper : IDumper
    {
        public void Dump(IList<Data> lst)
        {
            foreach(Data o in lst)
            {
                Console.WriteLine("{0} {1}", o.Iv, o.Sv);
            }
        }
    }
}

namespace Demo
{
    using DomainModel;
    using DataAccess;
    using Presentation;
    public class Application
    {
        private IList<Data> lst;
        private IReader rd;
        private IDumper dmp;
        public Application()
        {
            rd = ReaderFactory.Get(ReaderType.TEXT);
            dmp = DumperFactory.Get(DumperType.CONSOLE);
        }
        public void Read(string fnm)
        {
            lst = rd.Read(fnm);
        }
        public void Modify()
        {
            foreach(Data o in lst)
            {
                o.Iv = o.Iv + 1;
                o.Sv = "|" + o.Sv + "|";
            }
        }
        public void Dump()
        {
            dmp.Dump(lst);
        }
    }
   
    public class Program
    {
        public static void Main(string[] args)
        {
            Application app = new Application();
            app.Read("data.txt");
            app.Modify();
            app.Dump();
        }
    }
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester