Moje wątpliwośi związane z obiektowością

0

Witam,
programowania uczę się dość krótko. W zasadzie przerobiłem tylko internetowe kursy c++ a teraz wziąłem się za książkę c# rusz głową. Jest tam sporo o obiektowości, ale często mam jakieś wątpliwości. Chodzi mi tu o taki dryg, takie przeczucie co powinno być metodą, co klasą, jak bardzo rozdzielać ten cały kod. Domyślam się, że jest to dość typowe dla początkujących, gdy zastanawiają się czy lepiej rozbić ten blok kodu na metody, czy nie. Chciałbym jednak, żebyście mi odpowiedzieli tak bardziej praktycznie.

Załóżmy, ze piszę aplikację, która działa jak bot do np. youtube. Bot powinien posiadać możliwości zakładania kont, łapkowania filmów, oglądania ich, pamiętania które filmy odwiedził. No i tu mam pewne wątpliwości - nie tyle jak to okodować, ale w jaki sposób zaprojektować tego bota. Wymyśliłem sobie taki scenariusz:

Obiekt formularza Form1
Będzie on posiadał metody zwracające i ustawiające wartość kontrolek, np. textboxów (chyba to jest jedyna opcja, bo chciałbym, by program był wielowątkowy. Wtedy nie mógłbym z innego wątku zmienić właściwości danego textboxa. Musiałbym to zrobić to wewnątrz metody, gdzie sprawdzałbym właściwość invoke required danego obiektu kontrolki). W taki sposób mógłbym w textboxie wpisać np. login i hasło a bot dodałby nowe konto do listy.

No właśnie: konta. Wydaje mi się, że najlepiej byłoby zrobić klasę Account:

class Account {
	public string Login {get; private set;}
	public string Password {get; private set;}
	public CookieContainer Cookie {get; private set;}

	public Account (string login, string password, CookieContainer cookie) {
		this.Login = login;
		this.Password = password;
		this.Cookie = cookie;
	}
}

Dzięki temu wszystko miałbym spójne. Za każdym razem tworząc obiekt konta miałbym i ciasteczka i wszystkie dane wewnątrz instancji klasy.

Ale co z akcjami np. łapkowania filmów? Mógłbym zrobić klasę link:

class Link {
	public string Url {get; private set;}
	public List<Comment> Comments = new List<Comment>();
	public int Upvotes;
	public int Downvotes;
}

oraz klasę. Bot, która posiadałaby:

class Bot {
	public RestClient Client = new RestClient("http://youtube.com"); //obiekt klasy RestClient
	public List<Account> Accounts = new List<Account>();

	public bool voteVideo(Account account, Video video) {
		//
	}
}

No właście, ale czy oddanie łapki na film powinno być zadaniem klasy Account, czy Bot? To samo z logowaniem na konto. Powinien robić to bot:

public bool Login(Account account) {
	return //sprawdzamy czy konto moze sie zalogowac
}

czy może:

public bool Login(Account account) {
	return account.CanLogin();
}

czy może w klasie Account:

public bool Login() {
	return //sprawdzamy czy mozna sie zalogowac
}

Jak myslicie, ktora opcja jest najlepsza?

Reszta pytan:

  1. Ktore stworzenie listy jest lepsze:
public List<Account> Accounts;
public Bot(Form1 form) {
	this.Accounts = new List<Account>();
}

czy:

public List<Account> Accounts = new List<Account>();
public Bot(Form1 form) {
}
  1. Chciałbym też np. zrobić możliwość dodania historii tego co się dzieje. Takie Console.WriteLine ale np. w textboxie. Nie ma problemu by tę metodę, czy metodę WriteAllText wykonać w każdej klasie, która posiada odpowiedni using. Ale gdybym chciał zrobić własne zapisywanie tekstu, które byłoby dostępne w każdej klasie i umożliwiałoby zapisanie tekstu do textboxa? Na ten moment wpadłem na to, by tak zmodyfikować klase Bot:
class Bot {
	Form1 form;
	
	public Bot(Form1 form) {
	this.form = form
	}
}

Dzięki temu w klasie bot uzyskuję dostęp do referencji formularza, a co za tym idzie dostep do metody np.

public bool AddLog(string message) {
	return this.SetTextboxText(this.historyTextBox);
}
  1. No właśnie, czy funkcja AddLog powinna zwracać bool? Chodzi tu o to, że miałbym możliwość sprawdzenia, czy funkcja się udała modyfikując ją tak:
public bool AddLog(string message) {
	try {
		return this.SetTextboxText(this.historyTextBox);
	} catch {
		return false;
	}
}

Ale czy może należałoby tu użyć zwykłego void? Co o tym myślicie?

  1. Powiedzmy, że w moim bocie za wszystkie akcje będzie odpowiadała klasa Bot. Metody będą miały nagłówek taki:
public bool VoteVideo(Account account, Video video)
public bool VoteComment(Account account, Comment comment)
public bool AddVideo(Account account, File video)

Teraz np. okazuje się, że przed każdą akcją potrzebuję pobrać token z kodu źródłowego. Powinienem zrobić osobną klasę Token i tam umożliwić zwrócenie tokenu po przesłaniu kodu źródłowego:

public string GetToken(Account account, string siteHtml)

czy może całą operację pobierania tokenu powinienem zawrzeć w metodzie tej klasy:

public string GetToken(Account account, Link link)

Druga opcja powodowałaby, że musiałbym dodać usingi do klasy Token tylko zeby zwrocic wartosc.

Czy może pobieranie tokenu powinno być zadaniem klasyBot, a sam token powinien być stringiem, a nie klasą (token to w zasadzie tylko string, ale jako klasa moglby miec wlasciwosc string i metode zwracajaca ten string z kodu zrodlowego strony)

  1. Kolejna sprawa. W funkcji GetToken przekazuję cały obiekt, ale głównie chodzi mi tylko o właściwość CookieContainer tego obiektu. Czy w takim razie powinienem stworzyć funkcje, która przyjmuje za argument obiekt CookieContainer, czy może Account, który ma referencję do obiektu CookieContainer? Co prawda mógłbym zrobić oba sposoby przesłaniając metodę, ale wtedy dochodzą do takiego problemu, że mam pełno przesłoniętych metod, a korzystam albo z jednego, albo z drugiego sposobu.

  2. Publiczne metody i właściwości pisać tak: GetToken, Login, czy tak: getToken, login?

  3. Czy taka struktura programu, który opisałem byłaby dobra:
    form zawiera referencję do obiektu bot.
    bot jako "mózg" całego bota zawiera referencję do obiektu form w celu pisania logów. Posiada on rówież listę obiektów klasy Account oraz listę obiektów klasy Link. Bot posiada wszystkie akcje łapkowania, oglądania, dodawania filmów itd. Za argumenty przyjmuje konta, linki itd.
    Każdy link posiada listę obiektów klasy Comment, która zaś posiada właściwość account, które jest obiektem klasy Account. No właśnie. account powinno być polem czy właściwością? Chodzi o to, by każdy komentarz był przypisany do konkretnego obiektu konta.

2
Ham Burg napisał(a):

Witam,

To my witamy!

Obiekt formularza Form1

A jakby go tak nazwać sensowniej? ;>

chciałbym, by program był wielowątkowy.

Dlaczego?

Dzięki temu wszystko miałbym spójne. Za każdym razem tworząc obiekt konta miałbym i ciasteczka i wszystkie dane wewnątrz instancji klasy.

Dobrze.

Ale co z akcjami np. łapkowania filmów? Mógłbym zrobić klasę link:

Ale czemu chcesz ją nazwać link?

No właście, ale czy oddanie łapki na film powinno być zadaniem klasy Account, czy Bot?

Ja bym powiedział, że Account, bo w rzeczywistości to człowiek (zalogowany jako Account) to robi.

Jak myslicie, ktora opcja jest najlepsza?

Ja bym raczej powiedział, ze jakiś AccountAuthenticator, który na podstawie danych z GUI zwracałby obiekt zweryfikowanego Account.

  1. Ktore stworzenie listy jest lepsze:

Bez różnicy.

  1. No właśnie, czy funkcja AddLog powinna zwracać bool? Chodzi tu o to, że miałbym możliwość sprawdzenia, czy funkcja się udała modyfikując ją tak:

A jak może ta operacja się nie udać, i co masz zamiar zrobić z informacją o niepowodzeniu? Bo moim zdaniem będzie to kawał dobrej, nikomu niepotrzebnej roboty.

  1. Powiedzmy, że w moim bocie za wszystkie akcje będzie odpowiadała klasa Bot. Metody będą miały nagłówek taki:
public bool VoteVideo(Account account, Video video)
public bool VoteComment(Account account, Comment comment)
public bool AddVideo(Account account, File video)

To raczej nie jest dobrze, gdy za wszystkie akcje odpowiada jedna klasa.
A w tym konkretnym przypadku, to czym różni się głosowanie na Video, Comment i File, że potrzebne są oddzielne metody?

Czy może pobieranie tokenu powinno być zadaniem klasyBot, a sam token powinien być stringiem, a nie klasą (token to w zasadzie tylko string, ale jako klasa moglby miec wlasciwosc string i metode zwracajaca ten string z kodu zrodlowego strony)

A z czym jest związany ten token? Nie z kontem czasami?

  1. Publiczne metody i właściwości pisać tak: GetToken, Login, czy tak: getToken, login?

W C# obowiązuje ta pierwsza konwencja.

  1. Czy taka struktura programu, który opisałem byłaby dobra:
    form zawiera referencję do obiektu bot.
    bot jako "mózg" całego bota zawiera referencję do obiektu form w celu pisania logów. Posiada on rówież listę obiektów klasy Account oraz listę obiektów klasy Link. Bot posiada wszystkie akcje łapkowania, oglądania, dodawania filmów itd. Za argumenty przyjmuje konta, linki itd.
    Każdy link posiada listę obiektów klasy Comment, która zaś posiada właściwość account, które jest obiektem klasy Account.

No jak na początkującego może być, chociaż radziłbym poczytać o wzorcu Model View Presenter.

No właśnie. account powinno być polem czy właściwością? Chodzi o to, by każdy komentarz był przypisany do konkretnego obiektu konta.

1 użytkowników online, w tym zalogowanych: 0, gości: 1