import java.util.Scanner; public class MenuDemo { private Scanner sc; //Seuraavaksi alustettavaan taulukkoon menu-vaihtoehdot private final String[] menuItems = {"Tiedosto","Muokkaa","Ohje"}; public MenuDemo() { this.sc = new Scanner(System.in); } public void start() { String input=""; do { System.out.println("Valitse väliltä 1-" +(this.menuItems.length) +"! [ENTER] - Exit"); for (int x=0;x<this.menuItems.length;x++) { System.out.println("" +"["+(x+1) +"] - "+ menuItems[x]); } input = sc.nextLine(); int intInput = 0; if (!input.equalsIgnoreCase("")) { try { intInput = Integer.parseInt(input); } catch (NumberFormatException e) { this.start(); } } if (intInput >=1 && intInput <=menuItems.length) { act(intInput); } } while (!input.equalsIgnoreCase("")); } public void act(int pick) { System.out.println ("Valintasi:" +pick+ " ("+this.menuItems[pick-1] +")"); } public static void main(String[] args) { MenuDemo example = new MenuDemo(); example.start(); } }
Julkaisin tämän eilen illalla 26.03.2021, mutta editoin koodia toimivammaksi 27.03.2021 ja nyt se toimii täydellisesti.
Jere Sumell kirjoitti:
Julkaisin tämän eilen illalla 26.03.2021, mutta editoin koodia toimivammaksi 27.03.2021 ja nyt se toimii täydellisesti.
Onko täydellinen toiminta suunnitellusti niin että poistuminen pääloopista tapahtuu NumberFormatExceptionin kanssa vai kenties muusta syystä?
Lisäksi staattisiin luokkamuuttujiin ei kuulu viitata luokkainstanssin this kautta.
Joo, totta!
poistin tuon static-määritelmän tuosta menuItems, olkoon nyt sitten pelkästään final private -näkyvyysmääreeltään vakio.
Joo, ihan tarkoituksella heitin poikkeuksen ylemmälle tasolle, kun jos käyttäjä syöttää Enterillä tyhjän merkkijonon, tuo Integer -luoka -parseInt -staattinen metodi heittää tuon poikkeuksen.
No ei tämä siinä mielessä ihan täydellinen ole, kun sama se on, mitä merkkijonoa käyttäjä syöttää, mikä ei ole kokonaisluku, niin tulee tuo poikkeuksen heitto, miten parantelisin tätä?
No ainakin tyypitä poikkeuksesi oikein. Tarkoituksesi on "kuunnella" mainittua NumberFormatExceptionia, joten käytä sitä tyyppiä geneerisen Exceptionin sijaan.
Valitsemasi lähestymistapa sovelluksesta poistumiseen poikkeuksen kautta on sinällään ihan ok. Varsinkin pythonin kanssa tuollainen on aika yleistä ja jopa natiivikirjastossa hyödynnetään kyseistä kikkaa.
Ratkaisussasi on kuitenkin se vika, että pelkästään koodia katsomalla on vaikea ymmärtää, onko toimintamalli suunnitelmallista vai onnellinen sattuma. Nythän mikä tahansa poikkeus saa ohjelman sulkeutumaan "hallitusti", mikä ei ole vikojen jäljittämisen kannalta hyvä juttu.
Tässä on muutamia kommentteja:
Koodista saa vaikutelman, että valikko olisi tarkoitus lopettaa tyhjällä merkkijonolla, mutta tosiasiassa kyseiseen tarkastukseen ei edes päästä, kun poikkeus lentää tekstiä kokonaisluvuksi muunnettaessa. Yleensä olisi järkevää ottaa tuollainen poikkeus kiinni jo funktion sisällä ja tehdä siellä järkevä ratkaisu, esimerkiksi lopettaa silmukka (break) tai ohittaa viallinen syöte ja pyytää uusi tilalle.
Indekseillä kikkailu tuolla tavalla johtaa usein virheeseen. Ainakin kannattaisi rajoittaa kikkailu yhteen funktioon: kun kerran tulostaMenu pyytää yhden suurempaa lukua käyttäjältä, olisi järkevää siinä myös korjata syöte takaisin yhden pienemmäksi – tämän delegointi act-funktioon on sekavaa. Vaihtoehtoinen ”ratkaisu” olisi tyhjä kohta listan alussa, jolloin indeksit olisivat heti oikein tulostuksessa voisi aloittaa kohdasta 1; toisaalta silloin taulukon pituus olisi harhaanjohtavasti yhden suurempi kuin tulostettavien kohtien määrä.
Nimeämistä kannattaisi miettiä. Miksi koodissa on funktio tulostaMenu, kun kaikki muut nimet ovat englanniksi? Miksi nimi on tulostaMenu, kun funktiossa myös ajetaan silmukkaa, luetaan syötettä ja kutsutaan toimintoa?
Yleisesti ottaen koodi näyttää siltä, että se sisältää nimenomaan alkeet (tulostamisen ja kokonaisluvun lukemisen) yksinkertaisella tavalla toteutettuna eikä varsinaisesti kuitenkaan helpota valikon tekoa tai auta tekstipohjaisen valikon tärkeämmissä ongelmakohdissa.
Kiitos palautteesta!
Itsellänikin kävi mielessä, että tuon poikkeuksen voisi käsitellä jossain muualla, kuin olion ilmentymän metodikutsun yhteydessä, vaikka juuri metodin sisällä, ja jos syöte on virheellinen, niin pyytäisi validia syötettä uudestaan.
Toi yhdellä lisääminen juuri siitä syystä, koska taulukko-indeksointi alkaa nollasta, ja sama onko se +1 tuossa kohtaa, kun pitäisi jossain kohtaa kuitenkin ottaa kantaa siihen, missä kohtaa taulukkoa käyttäjän valinta sijaitsee.
Java 8:ssa näköjään ei enää ole .flush() -metodia saatavilla, mitä aiemmissa Java-versioissa oli.
Tuo nimien valinta ei ole tosiaan yhdenmukanen, jos muuttaisi tuon tulostaMenu -englanniksi, ja valitsisi jonkin kuvaavamman nimen.
On tämäkin jo tyhjää parempi, mutta poikkeuksen käsittely eri paikkaan, ja jos pitäisin tuon act-metodissa lenghth-1, enkä lisäisi tyhjää merkkijonoa 0-alkioon tuossa menuItems -taulukossa.
Sekin olisi tietenkin yksi, jos 0-alkioon lisäisi poistumisen ohjelmasta, tai paluun edelliseen valikkoon, jos niitä olisi useampia noiden vaihtoehtojen alavalikoita, niin sittenhän tuo do-while -rakenteen lopetusehto muuttuisi. Mutta silti pitäisi poikkeus käsitellä, juuri kuten 'metabolix' totesit, niin varmaan olisi järkevää funktion sisällä käsitellä se.
Jos poikkeuksen heittää vielä main-metodista ylemmäs, ohjelmahan tulostaa tuon poikkeuksen heiton jälkeen sen outputin, mikä siitä Integer.parseInt -errorista tulee pinnalle.
Nyt perjantaina päivitin vielä vähän tätä koodia, enkä enää keksi siihen mitään korjattavaa. päätin nyt tuon NumberFormatExceptionin käsittelyn hoitaa tuon käyttäjän syotteen jälkeen metodin sisällä.
Lisäksi korjasin tuon "tulostaMenu" -valikon nimen, vaikka "start" -nimelle, vaikka start() -metodi ainakin Javassa viittaa säikeiden parissa ohjelmointiin.
En ole koskaan tehnyt teollisuudessa mitään Javalla tyokseni, vaikka olen hakenut Java - tyopaikkoja, että saisi käytännon teollisuuskoodista uutta oppia ja kasvua ohjelmoijana kehittymiseen.
Mahtaako täällä Ohjelmointiputkassa jollakulla olla jotain painavaa sanottavaa, minkälaista problematiikkaa tämän kaltaisiin tekstivalikko-käyttoliittymiin teollisuusympäristossa liitetään ohjelmoijan näkokulmasta. Varmaan tekstikäyttoliittymiä suunnitellaan jossain ohjelmistoyrityksessä vieläkin.
Kun kerraan ollaan olio kielessä niin menun oliottaminen sopisi hyvin.
Se voisi olla
Menu menu = new Menu({"Tiedosto","Muokkaa","Ohje"})
sitten kaikki mitä on start() olisi ite Menu luokan sisällä...
Tuo voisi olla ihan käyttokelpoinen idea tuo Menu - tietotyypin ohjelmointi.
En vaan keksi kovin äkkiä, mitä muuta tuon menun tulostamisen lisäksi settereiden ja gettereiden lisäksi siihen sisällyttäisi.
Varmaankaan ei kannata Menu-tietotyyppiä ohjelmoidessa ohjelmoida tuota act-metodia, kun luokka, jossa Menu - ilmentymä/olio luodaan, niin se voisi saada tuon käyttäjän tekemän valinnan getValinta() -metodilla ulos Menusta, tai millä nimellä sitten muuttuja kulkeekaan ohjelmassa , niin sitten toimintometodit sijaitsee jossain muualla.
Varmaan vielä yhden koodin pistän tätä tekstikäyttoliittymä Javalla näytille tänne putkan pahnoille, jos esittäisin seuraavaksi sen oman näkemykseni tuosta Menu - luokasta, ja sitten koodin tarkastelijan vastuulle jäisi ohjelmoida testiluokka, jolla pääsee luokan toimintoihin käsiksi.
/* * Menu - tietotyyppi, jonka pääasiallinen tehtävä on tulostaa haluttu tekstivalikko ruudulle ja tallentaa käyttäjän valinta * int - tyyppiseen userChoice -muuttujaan. * * Kiitos Ohjelmointiputkan vakiopalstalaisille vinkeistä läpi 'Tekstikäyttoliittymä Javalla" -projektin. * * 02.04.2021 * Ohjelmointi Jere Sumell * jere.sumell@iki.fi * jjsume@github * * Menu -tietotyyppi (Java), jonka tekijä on Jere Sumell, on lisensoitu Creative Commons Nimeä-JaaSamoin 4.0 Kansainvälinen -lisenssillä. * Perustuu teokseen osoitteessa umpihanki.tuntikirjuri.net/DataAssets/Menu.java. */ import java.util.Scanner; public class Menu { //Attribuutit private Scanner sc; private int userChoice; private String[] menuItems; //parametrillinen konstruktori public Menu(String[] items) { this.sc = new Scanner(System.in); this.menuItems = items; } //Muita metodeita //Metodi tulostaa valikon ja kysyy käyttäjäsyotettä. public void start() { String input=""; do { System.out.println("Valitse väliltä 1-" +(this.getMenuItems().length) +"! [ENTER] - Exit"); for (int x=0;x<this.getMenuItems().length;x++) { System.out.println("" +"["+(x+1) +"] - "+ this.getMenuItems()[x]); } input = sc.nextLine(); int intInput = 0; if (!input.equalsIgnoreCase("")) { try { intInput = Integer.parseInt(input); } catch (NumberFormatException e) { this.start(); } } if (intInput >=1 && intInput <=this.getMenuItems().length) { this.setUserChoice(intInput); break; } } while (!input.equalsIgnoreCase("")); } //setterit ja getterit public int getUserChoice() { return userChoice; } public void setUserChoice(int userChoice) { this.userChoice = userChoice; } public String[] getMenuItems() { return menuItems; } public void setMenuItems(String[] menuItems) { this.menuItems = menuItems; } //toString - ylikirjoitus (overriding) public String toString() { return "Valikko Menu - tietotyyppi 1.0"; } }
Siinä on nyt Tietotyyppi 'Menu' -ohjelmoitu parametrillisella konstruktroilla, vaikka niitä on muitakin konstruktoreita.
Enää tuo ei tuosta ainakaan merkittävästi muutu, niin rohkenin pistää koodin jakoon Creative Commons -lisenssillä, vaikka ei se nyt varmaan monikaan noudata lisenssiehtoja, ja vapaasti kun julkaisen koodini näin, niin enhän pysty mitenkään valvomaan sen käyttoa. Jonkinlainen ohjelmakoodin käyttoasteen monitorointi-ohjelma pitäisi olla siinä missä verkkoliikenne-monitorointiohjelmiakin, esim Wireshark, mutta käytännossa itselleni sama, ei tuo nyt mikään rakettitieteen huippusaiaisuus ole.
No nyt se on jaossa, ni jos joku tykkää ottaa käyttoon tuon johonkin projektiin, niin olen vain otettu. Liitin mukaan sähkopostiosoitteeni, jos koodi leviää joskus johonkin, niin voi lähettää sitten palautteen sähkopostitse.
LISÄYS 18:39
Poistin tuosta konstruktorista tuon start-metodin kutsun, kun älykkäämmin ohjelma toiii sitten, kun tietotyyppiä käyttävä ohjelmoija oliomuuttujan luonnin jälkeen kohdistaa oliomuuttujan kautta .-notaatiolla tuota start-metodia siinä kohtaa, kun haluaa valikon tulostuvan.
Ei ole järkeä tulostaa valikkoa väälttämättä joka kerta uuden Menu-olion luonnin yhteydessä. Nyt se on omasta mielestäni melko bueno!
LISÄYS/PARaNNuS 19:05
Huomasin, että tuo käyttäjän valinta pitää tallentaa tuolla if-lauseen sisällä, jonka jälkeen breakilla koko silmukasta ulos sen jälkeen, kun ensin olio-ilentymän userChoice -arvo on tallennettu muistiin.
Jere Sumell kirjoitti:
Varmaan vielä yhden koodin pistän tätä tekstikäyttoliittymä Javalla näytille tänne putkan pahnoille, jos esittäisin seuraavaksi sen oman näkemykseni tuosta Menu - luokasta, ja sitten koodin tarkastelijan vastuulle jäisi ohjelmoida testiluokka, jolla pääsee luokan toimintoihin käsiksi.
Kun olit kiinostunut tuosta työmaailmasta niin aikuisten oikeasti se menee juuri niinpäin että ohjelmoijan vastuulla jää testiluokan tekeminen eikä suinkaan toisin päin.
No se on toki selvää, mutta saa nyt kuka tahtoo tuota Menu-luokkaa kokeilla, ohjelmoida mieleisensä testiluokan. Itse tein MenuTesti -luokan, ja tuo tietotyyppi toimii kivasti.
Tässä oma näkemys oo menusta:
public class MenuItem { private String title; public MenuItem(String itemTitle) { this.title = itemTitle; } public String printItem() { return title; } } import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class MyMenu { private final List<MenuItem> menuItems = new ArrayList<>(); public MyMenu(String... itemTitles) { for (String itemTitle : itemTitles) { MenuItem menuItem = new MenuItem(itemTitle); menuItems.add(menuItem); } } public String printMenu() { StringBuilder sb = new StringBuilder(); int itemNum = 0; for (MenuItem menuItem : menuItems) { sb.append(String.format("%d: %s\n", itemNum, menuItem.printItem())); itemNum++; } return sb.toString(); } public int show() { Scanner sc = new Scanner(System.in); while (true) { System.out.println(printMenu()); int choiceMin = 0; int choiceMax = menuItems.size() - 1; String chooseBetween = String.format("Valitse väliltä %d - %d", choiceMin, choiceMax); System.out.println(chooseBetween); String keyInput = sc.nextLine(); if (keyInput != null) { if (keyInput.isBlank()) { return -1; } boolean showTip; try { int choice = Integer.parseInt(keyInput); if (choice < choiceMin || choice > choiceMax) { showTip = true; } else { return choice; } } catch (NumberFormatException e) { showTip = true; } if (showTip) { System.out.format("Valitse väliltä %d - %d\n", choiceMin, choiceMax); } } } } } public class MenuTest { public static void main(String[] args) { MyMenu menu = new MyMenu("Tiedosto", "Muokkaa", "Ohje"); int choice = menu.show(); if (choice == -1) { System.out.format("Ei valintaa!\n"); } else { System.out.format("Valittu: %d\n", choice); } } }
Jere Sumell kirjoitti:
No se on toki selvää, mutta saa nyt kuka tahtoo tuota Menu-luokkaa kokeilla, ohjelmoida mieleisensä testiluokan. Itse tein MenuTesti -luokan, ja tuo tietotyyppi toimii kivasti.
Kun tämä on koodivinkit osasto niin koodivinkkien olisi hyvä olla sellaisia mitä voi itse kokeilla. Eikä sellaisia että toimii minulla hyvin mutta en kerro miten.
No julkaisen nyt yksinkertaisen testiluokan tuolle Menu -tietotyypin käytölle, todellisuudessa jos ajatellaan, että alavalikossa olisi vielä paluu edelliseen valikkoon, niin tuolla Switch-rakenteessa pitäisi ensin tarkistaa oliomuuttujan nimi, jonka ilmentymän valikon se sitten tulostaa käyttäjän palatessa edelliseen valikkoon, ja tässä nyt ei sitä ole.
/* * Menu - tietotyypin demo-esimerkki testiluokasta. * * Jere Sumell 03,04,2021 * jere.sumell@iki.fi * jjsume@github * */ public class MenuTesti implements Runnable { private String[] mainMenuItems; private String[] tiedostoMenuItems; private int mainMenuChoose; private Menu mainMenu; private Menu tiedostoMenu; public MenuTesti() { this.mainMenuItems = new String[]{"Tiedosto","Muokkaa","Ohje"}; this.tiedostoMenuItems = new String[]{"Avaa","Tallenna"}; this.mainMenu = new Menu(mainMenuItems); } public void start() { do { mainMenu.start(); this.run(); } while (this.mainMenuChoose != mainMenu.getUserChoice()); act(this.mainMenuChoose); } public void act(int x) { switch (x) { case 1: System.out.println("->Tiedosto->"); this.tiedostoMenu = new Menu(this.tiedostoMenuItems); this.tiedostoMenu.start(); break; default: System.out.println("foo"); } } public static void main(String[] args) { MenuTesti example = new MenuTesti(); example.start(); } @Override public void run() { while (this.mainMenuChoose != mainMenu.getUserChoice()) { this.mainMenuChoose = mainMenu.getUserChoice(); } } }
_Pete_ kirjoitti:
Tässä oma näkemys oo menusta:
No joo, top-down -ajattelutavalla tuo on ihan oikein, että tuo valikkoitemikin on omassa luokassa, mutta siellä voisi olla ylikirjoitettuna tuo toString() -metodiin tuo valikkotekstinimikkeen tulostus, kun se on ainut attribuutti tuossa MenuItem-luokkassa, ja set-get metoditkin voisi olla, mutta se nyt on sivuseikka tässä kohtaa.
Ihan mielenkiintoisen oloinen ratkaisu, luonaa se noinkin.
Pistin tuon Menu -tietotyypin lähdekoodi -tiedoston ja tuon MenuTesti.java -tiedoston lähdekoodin jakoon "TKT-Roina" -Dropbox-kansiooni.
Kansiossa on joitain muitakin tiedostoja, jotka liittyvät tekniikan laitoksen yhteen aineopintokurssin kotitehtäviin, mutta ei niissä mitään ole, sama vaikka joku katsoo tai hakukone indeksoi nekin johonkin maailman aikaan jossaina kohtaa.
Suora linkki lähdekooditiedostojen, josta niitä voi tarkastella tai ladata omalle koneelle
https://www.dropbox.com/sh/ypzwk9n5he96ydz/
_Pete_ kirjoitti:
Tässä oma näkemys oo menusta:
Tuo MenuItem -valikko ja koko sinun toteutustapasi on mielenkiintoinen ja käyttökelpoisempi tuo listaan MenuItem -olioiden kautta valikon vaihtoehtojen listaaminen etenkin, jos suunnittelee graafista käyttöliittymää. Alkuperäinen aihe ja idea oli itselläni jonkinlainen tekstikäyttöliittymän valikkoihin liittyvä problematiikka.
Jos ajatellaan, että kun käyttäjän syöte täytyy jotenkin käsitellä, siihen täytyy ottaa kantaa ja ohjelmoida tietokone toimimaan sen mukaan, niin yleisin tietokoneen syöttöläite on mitä tulee mieleen, niin näppäimistö, niin tuo numero-syöte toimii tekstikäyttöliittymässä, mutta graafisessa käyttöliittymässä, jos sellaista ohjelmoi ja suunnittelee, niin yleensä näppäimistöltä ei anneta, kuin ehkä pikanäppäin-komentoja, jolloin tuo numerointi ei toimi, valikkovalintaa ei voi käsitellä tuon käyttäjän syöttämän numeron perusteella.
Graafisessa käyttöliittymässä tuohon MenuItem -luokkaan voisi lisätä pikanäppäinyhdistelmlän, esim leikepöydälle kopoiointi yleensä CTRL+C, mutta sitten näppäimistön kuuntelurajapinnan implementointi tai KeyAdapterin periyttäminen sen toteutus on jossain muualla, kuin tuolla yleisessä MenuItem -luokassa siinäkin tapauksessa.
Tuossa MenuTesti-koodissa ei tunnu olevan päätä eikä häntää. Runnable-rajapinnan toteuttaminen on selvästi väärin, kun run-metodi ei tee mitään järkevää. Ylipäänsä koodin sirottelu noin moneen metodiin on vain sekavaa. Koodin while-silmukat ovat täysin hyödyttömiä, kun ne väistämättä ajetaan vain kerran.
MenuTesti tiivistyisi siis näin, jos halutaan pitää mukana Runnable-rajapinta:
public class MenuTesti implements Runnable { public static void main(String[] args) { new MenuTesti().run(); } @Override public void run() { Menu mainMenu = new Menu(new String[]{"Tiedosto", "Muokkaa", "Ohje"}); mainMenu.start(); switch (mainMenu.getUserChoice()) { case 1: System.out.println("->Tiedosto->"); Menu tiedostoMenu = new Menu(new String[]{"Avaa", "Tallenna"}); tiedostoMenu.start(); break; default: System.out.println("foo"); } } }
Tai vielä paremmin ilman turhaa Runnable-rajapintaa:
public class MenuTesti { public static void main(String[] args) { Menu mainMenu = new Menu(new String[]{"Tiedosto", "Muokkaa", "Ohje"}); mainMenu.start(); switch (mainMenu.getUserChoice()) { case 1: System.out.println("->Tiedosto->"); Menu tiedostoMenu = new Menu(new String[]{"Avaa", "Tallenna"}); tiedostoMenu.start(); break; default: System.out.println("foo"); } } }
Menu-luokassakin useiden metodien sotkeminen tähän alkeelliseen ”valikkoon” on täysin turhaa. Se vain vaikeuttaa käyttöä ja tekee koodista epäselvemmän. Esimerkiksi tuo logiikka, jossa valikko ensin ajetaan ja sitten tulos pitää hakea erikseen toisella metodilla, on aivan järjenvastainen.
Jos kerran Menu-luokan toivottu toiminnallisuus on se, että käyttäjä voi valita merkkijonoista yhden, selvempää olisi laittaa tällainen toiminnallisuus yhdeksi funktioksi, jolle annetaan merkkijonot ja joka palauttaa käyttäjän valinnan (korjattuna nollasta alkavaksi, jotta indeksointi olisi ohjelmoijalle selvä).
Eli selvempää olisi, jos yllä olevan testikoodin voisi kirjoittaa seuraavasti:
public class MenuTesti { public static void main(String[] args) { switch (Menu.choice("Tiedosto", "Muokkaa", "Ohje")) { case 0: System.out.println("->Tiedosto->"); Menu.choice("Avaa", "Tallenna"); break; default: System.out.println("foo"); } } }
Menu.choice-metodin toteuttaminen jäisi sitten työpaikan hakijan vastuulle.
Jos taas aletaan ihan oikeaa valikkoluokkaa tehdä, sen pitäisi sisältää muutakin, esimerkiksi sisäkkäisten valikkojen järkevä käsittely. Nykyinen luokkasi ei todellakaan käsittele ”tekstikäyttöliittymän valikkoihin liittyvää problematiikkaa”, koska se problematiikka ei ole tekstin tulostus ja kokonaisluvun kysyminen vaan varmasti juuri se sisäkkäisten valikkojen järkevä toteutus kaikkine poikkeustilanteineen (esimerkiksi: joistain valinnoista ei olisi mahdollista tulla takaisin, jostain pitäisi hypätä eri kohtaan valikkorakenteessa, valikon vaihtoehtojen pitäisi muuttua dynaamisesti joidenkin valintojen seurauksena, tekstivalikon seassa pitäisi olla tekstin tai lukuarvon syöttöön sopivia ruutuja tai vaikka nuolilla ohjattavia liukupalkkeja).
Jere Sumell kirjoitti:
koodia saa käyttää Creative Commons -lisenssin alaisuudessa
Tämä vaatisi tarkennusta, koska Creative Commons -lisenssejä on useita ja niiden vaatimukset ovat olennaisesti erilaiset. Mahdollisesti tarkoitit esimerkiksi lisenssiä CC BY-NC-ND 4.0, jos kerran haluat kieltää koodin muokkaamisenkin. (Toisaalta jos kiellät tämän koodisi muokkaamisen, en usko, että kukaan haluaa sitä tuollaisenaan käyttää.)
Kiitos palautteesta, 'Metabolix".
Olkoon nyt näin sitten, aika loppuun asti käsitelty tämä case, ja kuhan nyt pistin tuon Creative Commons -lisenssin ilman lisämääreitä, kun sama mikä lisenssi on kyseessä, niin käytännossa sillä ole mitään merkitystä paitsi teoriassa suoja on puolellani alkuperäiskoodin luojana, mutta käytänossa kun valvonta puuttuu täysin, ja koodi on julkaistu vapaasti täällä foorumilla koko maailmalle, ja voi ladata Dropbox -kansiostani, tosiaan sitä ei voi mitenkään valvoa miten joku käyttää koodia. Out of my control, ja sellaisista asioista ei kannata menettää younia, mitkä eivät ole omassa hallinnassa.
Ohjelmistokehityspuoleen ja verkkotietoturvaankin, mitä enimmäkseen opiskelin AMK-tradenomi - opinnoissani, siihen mitalin kääntopuolen pimeään puoleen liittyy paljon sellaista, mikä voi koitua haitaksi jossain kohtaa jonkin sellaisen asian seurauksesta, mihin ei voi itse vaikuttaa mitenkään.
Hienoa, että sievensit ja järjenssit ja selvensit pääni tästä Runnable-rajapinnan käyttoonotosta tuossa MenuTesti - luokasta. Ehkä oma ratkaisuni testiluokasta ei ollut niin loppuun saakka hiottu, niinkuin totesitkin.
Kaikki creditit teille kaikille palsta-aktiiveille, joka sai minussa heräämään uusia näkokulmia.
LISÄYS 11:36
Tuosta valvonnasta vielä, kun alkuperäisohjelmoijana itselläni on teoriassa tuo suoja ja omistajaoikeus -suhde tuohon koodiin, niin jos ajatellaan, että perustaisin ohjelmistoyrityksen, haluaisin tehdä lähdekoodillani jotain bisnestä, niin kaikki omat oikeudenomistukset ovat yritykseni omaisuutta, puhutaan tietotekniikka-firmojen osalta data assets, ja yleensä kaikki omistukst ja pääomat, patentit mm. on asioita, jotka vaikuttavat arivioituun markkina-arvoon jos on aikomuksena myydä yritys yrityskaupat tehdä jossain vaiheessa, kun isommat ostaa pienempiä pois alta. Vaikka olisi, mitä minulla ei ole, jokin arviolta mildardin euron arvon edestä immateriaali-oikeudenomistuksia aineettomaan omaisuuteen, jos en käytännössä pysty aktiivisesti valvomaan käytännössä pitäisi olla palkattuna sellainen puolustusjuristi, joka pystyy ajamaan ja "ampumaan" top-down -law -menetelmällä kaikki bisnestä häiritsevät tekijät, ohjelmistoyrityksen näkökulmasta piraatit alas oikeusprosessien kautta, niin käytännössä siinä herää se kysymys, onko sillä yritykselläni mitään markkina-arvoa.
Paras olisi tietysti, jos itsellä lakikoulusta juristin paperit sen teknisen osaamisen lisäksi, että pystyisi pyörittämään ohjelmistoyritystä, ja jos löytää jotain lisäarvoa tuottavaa lähdekoodia omasta portfoliosta, niin sittenhän kaikki olisi hyvin. Jos yritys kasvaa jossain vaiheessa isommaksi, vaikka olisi sata huippu-top-down -ajattelumaailman juristia omassa armeijassa ajamassa ja valvomassa, ja suojaamassa yrityksen data assets, omaisuutta, niin ei silti aivan kaikkea voi poissulkea.
Jos ajatellaan jotain Bill Gatesin perustamaa Microsoftia, kun esimerkiksi kaikki Windowsit on ohjelmistopatentin alla, mutta Bill Gates onkin jotain lakiopintoja suorittanut juristi koulutukseltaan, eikä tietokonetieteilijä, ja hän on pystynyt aluksi valvomaan johonkin pisteeseen saakka ja suojaamaan omia patentteja lakiopintojensa avulla.
Itse olen vaikka olen sulkenut melkein työmarkkinoille siirtymisen lähes kokonaan pois elämästäni, niin kyllä nyt tekniikasta ainakin maisterin paperit ajattelin suorittaa tuon tradenomi-tutinnon lisäksi varmaan, ja sitten unohdan liikemaailman, se nyt ei kiinnosta juuri yhtään juuri siitä syystä, kun en omaa juristin koulutusta, ja ikääkin alkaa olemaan sen verran, että kannattaneeko sitä edes enää hankkia tekniikan opintojen jälkeen, jos aikoo jotain rahaa tehdä vielä elämän kääntyessä keski-ikään ja vanhuuteen.
Runnable interface on Javassa tarkoitettu threadaukseen
https://docs.oracle.com/javase/8/docs/api/java/
Eikä sitä siis normaalisti kuulu käyttää noin että on toteutettu sen run() metodi ja sitä kutsutaan suoraan vaan sitä käytetään uuden Threadin luontiin.
class Foo implements Runnable { public Foo() { Thread t = new Thread(this); t.start(); } public void run() { //uudessa threadissa ajettava koodi } }
Jere Sumell kirjoitti:
kuhan nyt pistin tuon Creative Commons -lisenssin ilman lisämääreitä
Melkoiset tarinat jaksoit kirjoittaa asian vierestä, kun huomautettiin että ei ole mitään "Creative Commons" -lisenssiä.
Kuten itsekin huomasit, niin käytännössä lisenssin valinnalla ei tässä tapauksessa olisi merkitystä, niin miksi edes laittaa mitään lisenssiä? Tai jos kuitenkin haluaa määrittää lisenssin, niin miksei sitä sitten voisi tehdä kunnolla?
No voin mä lisätä lisämääritteet sitten, kun olen selvin päin.
Vaikka yritän minimoida netin käytön, ja mitä ainakin kirjoittelun nettiin vaikka en mitään automaattikirjoitusta Notepadilla harrastakkaan humalassa, ni voihan sinne nyt sen ihan periaatteesta lisätä.
Mitä tulee laajaan tarinointiin, niin kunhan nyt kirjoitin näkemykseni, miten isot tekee bisnestä ainakin Amerikassa, kun oli sopiva asiayhteys. Olen humaanilta pohjaltani tarinankertoja. Runoilijahan musta alun perin piti tulla.
Vielä kukaan ei ole esittänyt matemaattisessa muodossa, miten tietokoneen saisi ohjelmoitua kirjoittamaan automaattidekkaria, että siinä olisi jotain järkeä. Siihen liittyy kieliteknologoia, tekoälytutkimus ja koneoppiminen, mutta voi olla että omanikaan elinaikani puitteissa siihen vain pitää tyytyä, että fiktiivinen romaani pitää kirjoittaa mallasviskin ja tekstinkäsittelyohjelman kanssa sanasta sasnaan ihan puhtaalta paperilta, Eli tietokonekaan taivu nyt ihan kaikkeen vielä.
Mutta tämä tästä. Pääisäisoluiden jälkeen vähän hövelimmällä juttutuulella.
Jere Sumell kirjoitti:
Tosiaan sitä ei voi mitenkään valvoa miten joku käyttää koodia. – – Jos en käytännössä pysty aktiivisesti valvomaan käytännössä pitäisi olla palkattuna sellainen puolustusjuristi,
Ei juristi hoida valvontaa tai estä väärinkäyttöä. Juristi hoitaa oikeusjuttuja sitten, kun mahdollinen syyllinen on löytynyt.
Tiukat rajoitukset eivät sovellu järkevästi pieniin esimerkkeihin tai harjoituksiin, koska tällaisilla koodeilla ei ole suojeltavaa arvoa. Rajoitukset johtavat vain siihen, että koodeista ei ole hyötyä sinulle eikä muille.
Kun kiellät koodin levittämisen ja käytön, koodi ei päädy sinun nimelläsi muualle kuin sinne, missä itse julkaiset sen. Pahantahtoinen kopioija voi joka tapauksessa kopioida sen omalla nimellään ja muokata sitä niin, ettei sitä tunnista samaksi, ja silloin mahdollinen maine koodista menee hänelle. Kuten itsekin totesit, käytännössä et pysty tällaista toimintaa valvomaan.
Jos taas antaisit luvan kopiointiin ja levitykseen järkevällä lisenssillä (melko arvottoman koodin tapauksessa esim. MIT-lisenssi tai LGPL), ehkä teoriassa koodi ja sinun nimesi voisi päätyä isompiin projekteihin ja saisit näkyvyyttä ja mainetta. Parhaimmillaan voisit saada osan kunniasta jopa silloin, kun joku muu parantelee koodia.
Tai jos asia ei suuresti kiinnosta, voit jättää lisenssin kokonaan pois. Kieltoihin verrattuna et menetä mitään. Tai jos koodin käytön rajoittaminen tuntuu tärkeältä, helpoin keino on pitää ne koodit kokonaan poissa julkisuudesta.
Jere Sumell kirjoitti:
jjsume@github – – jos löytää jotain lisäarvoa tuottavaa lähdekoodia omasta portfoliosta, niin sittenhän kaikki olisi hyvin.
Vilkaisin GitHub-tililläsi olevaa ”portfoliota”. Koodit näyttävät enemmän sellaisilta, joilla tienataan pari opintopistettä ohjelmoinnin alkeiskurssilla, eivät sellaisilta, joilla näytetään taitoja työnhaussa. Kyllä nyt portfoliossa pitäisi olla jokin ihan oikeasti käyttökelpoinen ohjelma tai kirjasto eikä mitään muutaman rivin harjoituksia.
Metabolix kirjoitti:
Vilkaisin GitHub-tililläsi olevaa ”portfoliota”. Koodit näyttävät enemmän sellaisilta, joilla tienataan pari opintopistettä ohjelmoinnin alkeiskurssilla, eivät sellaisilta, joilla näytetään taitoja työnhaussa. Kyllä nyt portfoliossa pitäisi olla jokin ihan oikeasti käyttökelpoinen ohjelma tai kirjasto eikä mitään muutaman rivin harjoituksia.
Portfolion arvoa kasvattaisi myös että muutaman rivin jutut jopa kääntyisivät ja myös toimisivat oikeasti :) Tähän asiaan auttaa ettei harrasta tekijän mainitsemaa kännikoodausta.
Itekin myönnän, että Github-Profiilissani ei nyt maailmaa kovinkaan paljon parantavaa koodia olekaan.
Silloin, kun tutustuin Githubiin, ja miten sinne lisätään tavaraa, innostuin joksikin aikaa noita simppeleitä koodeja sinne lisäämään, mitä siellä nyt on, ja viime tuppaamisesta sinne on jo aikaa.
Vaikka käytän ohjelmistokehitysympäristönä Linux Mint -käyttöjärjestelmää, ja Linuxissahan on git -päätteeltäkin saatavilla kätevästi, ja suosikki IDEni Java-ohjelmoinnin suhteen on Eclipse, niin sehän on Cross-platform, johon on noi liitännäisten määrä aika mukava, millä sitä on mahdollista laajentaa, niin käsittääkseni Eclipseenkin saa Gitin integroitua, jos tykkää versionhallintaa harrastaa, tai on mukana jossain git-projektissa.
Ymmärrän hyvin, että juristit ei hoida valvontaa, mutta käytännössä viimeinen vaihe on se, että kun valvonnan tuloksena ollaan tehty johtopäätelmä, että joku taho rikkoo lisenssisopimusta, niin kyllä jos rikkomus on tarpeeksi laaja-alainen tai vakava, niin se päätyy juristin työtehtäväksi, liiketalous-näkökulmasta, jos unohtaa tekniikan parissa työtehtäviään hoitavat välistä.
Kännikoodailustakin on vähän kokemusta, voi olla pientä viihde-arvoa tuottavaa toimintaa ainoastaan pienessä nousuhumalassa, kun alkaa ottaa pohjia, mutta ei ohjelmointia voi täysiverisesti tehdä humalassa. Sama, niin kuin shakki on älykäs lautapeli, ja perinteiset lautapelitkin voi nostaa viihtyvyysarvoa hyvässä illanistujaisseurassa, mutta ei shakkiakaan mielellään pelaa humalassa.
Shakkia ja ohjelmointia yhdistää loogiikka ja matematiikka, ja pelien pelaamiseen ylipäätään algoritminen ajattelu. Ohjelmointikin taitaa olla jos tarpeeksi syvälle mennään, niin puhtaasti matematikkaa, tai ainakin mitä lähemmäs mennään rautatasoa ohjelmakoodin tuottamisessa.
Yksi syy varmaankin siihen, miksi monella kokeneella hyvällä ohjelmoijalla on todella hyvä kuukausipalkka, kun firman täytyy ostaa tekniikka ainoastaan kerran, ja ohjelmointi ei ole mitään rentoa työntekoa, vaan henkisesti kuormittavaa, vaikka joskus 90-luvun lopussa ensimmäisen IT-buumin aikaan oli varmaan firmoja, joissa puhuttiin rennosta duunin teosta, jossa kolaa saa automaatista, ja alasta luotiin kovinkin mediaseksikäs imago. Sittemmin ala on vakiintunut, ja IT-duunipaikat on verrattavissa todellakin mihin tahansa muuhun raskaaseen tuottavaan tyohon, josta yritysten pitäisi maksaa kunnon palkka.
Nyt on pääsiäisoluet juotu, ja lisättynä tuo Creative Commons -lisenssiteksti.
Aihe on jo aika vanha, joten et voi enää vastata siihen.