Els programadors, en general, anem aprenent segons fem, a vegades per gust, a vegades per motius laborals. I m'he trobat una reflexió interessant sobre l'aprenentatge al blog d'Scott Hanselman que vaig seguint segons va publicant.
Ell explica que se li acosta un jove i li pregunta que ha d'estudiar, per que estava preocupat per la universitat que li ensenyen .NET i ara el que es porta és .NET Core. I ell li contesta:
For the young person I spoke to, yes .NET Core may be a little different from .NET Framework, and they might both be different from Ruby or JavaScript, but strings are strings, loops are loops, memory is memory, disk I/O is what it is, and we all share the same networks. Processes and threads, ports, TCP/IP, and DNS - understanding the basic building blocks are important.
Drive a Honda or a Jeep, you'll still need to replace your tires and think about the road you're driving on, on the way to the grocery store.
Jo sempre critico els programadors que no saben com funciona un disc, com va una cache, perque al fi i al cap el hardware és la carretera que ens porta. O per els que presumeixen de fer les coses en l'últim llenguatge de moda: recordo que un string és un string, un bucle un bucle i un if... Ademés sempre penso en el manteniment del software. Quantes explicacions ha de rebre un ésser humà per entendre el codi d'un programa? A vegades quan els compiladors incorporen millores, no són tan una millora com un inconvenient... veiem aquesta del C# 8.0, primer el codi clàssic:
He sigut contagiat d'aquesta plaga que assola la nostra civilització i he anat al cine a veure aquesta pelic. Es pot dir que ara ets un friki si no l'has vist, per que les xifres són tremendes.
Un aspecte digne de menció d'aquestes pelis és la coherència interna, fan servir els mateixos actors de les pelis originals inclús els secundaris. Des de les series de Capitan Amèrica, Thor, Ironman, Hulk, Guardianes de la Galaxia, Spiderman... i també fan pelis presentació d'herois secundaris com Black Panther, Dr. Strange, Capitana Marvel.
Per altra banda jo no imaginava quan feien totes aquelles pelis que confluirien en un sol argument, curiós com han fet la barreja. I curiós també com els X-Men s'han mantingut apart.
L'argument és el de sempre, els bons matxaquen els dolents. Però la gràcia d'aquesta és la forma de fer-ho, ha de ser divertit. Sobretot el Thor d'aquesta peli està molt bé, he rigut amb ell i el Rocket.
Fa un temps vaig fer el hashejador, un software multifil que per cada disc dur calcula el hash dels fitxers que estan en un BBDD i compara el resultat amb el que ja té guardat. Serveix per protegir-se del bit rotting. El cert és que hem va força bé, quan tingui temps el milloraré per fer servir SHA256 enlloc de SHA1 però això serà una altra història. L'inconvenient que li veig al hashejador és que necessita una BBDD, una infraestructura, etc...
El PowerShell disposa d'una comanda Get-FileHash que calcula hashs de fitxers, però no els guarda enlloc, els treu per pantalla. Suposo que es podria escriure alguna utilitat que el guardi en un fitxer de text però aleshores també caldria escriure una altra "cosa" (referint-me al llenguatge del PowerShell) per tal que compari els hashs existents amb el que es calcula en aquell moment. Però jo no sóc de fer coses en PowerShell.
Per això ha sortit el petit hashejador, una utilitat per calcular els hash de fitxers i deixar el resultat en un fitxer XML dins la mateixa carpeta on estan els fitxers. Més endavant el petit hashejador pot fer el procés de verificació per veure que tot està a lloc. El problema que li veig és que permet detectar errors però no corregir-los, es a dir el petit hashejador et dirà que no li encaixa la verificació d'un fitxer però un cop detectat... que fas? Com el recuperes? Això ho fa el seu germà gran que verifica un fitxer en diferents discs durs i llavors saps quina còpia és la bona. Però de moment, el petit hashejador només fa això, detectar sense corregir.
El petit hashejador és una aplicació de línia de comandes (o "aplicación de consola") formada per un programa principal i una classe. El programa principal té la funció de verificar i la de crear el fitxeret amb els hashos, la de guardar i llegir el fitxer XML. No és que sigui gaire complicat. Primer el programa principal:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace Hasher
{
classProgram
{
privatestaticstring ExecutablePath = "";
privatestaticstring CarpetaAProcessar = "";
privatestaticbool Recursiu = false;
staticvoid Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
ExecutablePath = Path.GetDirectoryName(AppPath);
try
{
if (args.Length > 0)
{
string Accio = args[0].ToLower();
if (args.Length > 1)
{
if (args[1] != null)
{
CarpetaAProcessar = args[1];
}
}
if (args.Length > 2)
{
if (args[2] != null)
{
if (args[2].ToLower() == "-r")
{
Recursiu = true;
}
}
}
if (CarpetaAProcessar != "")
{
if (!Directory.Exists(CarpetaAProcessar))
{
Console.WriteLine("Carpeta no trobada: " + CarpetaAProcessar);
return;
}
}
else
{
Console.WriteLine("Carpeta a processar no informada");
return;
}
switch (Accio)
{
case"crea":
crea(CarpetaAProcessar);
break;
case"verifica":
if (!File.Exists(CarpetaAProcessar + "\\hasher.xml"))
{
Console.WriteLine("No hi ha fitxer de hashos.");
return;
}
verifica(CarpetaAProcessar);
break;
default:
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r]\" crea un fitxer XML amb els Hash dels fitxers, -r indica recursiu");
Console.WriteLine("\"verifica path [-r]\" verifica que els fitxers tinguin el Hash -r indica recursiu");
break;
}
}
else
{
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r]\" crea un fitxer XML amb els Hash dels fitxers -r indica recursiu");
Console.WriteLine("\"verifica path [-r]\" verifica que els fitxers tinguin el Hash -r indica recursiu");
}
}
catch(Exception Err)
{
Console.WriteLine(Err.Message);
}
}
publicstaticstring ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
publicstaticstring ObtenirData()
{
returnDateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
publicstaticvoid verifica(string pPath)
{
Console.WriteLine(ObtenirData() + " - verificant carpeta: " + pPath);
SHA256 mySHA256 = SHA256.Create();
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
try
{
if (File.Exists(pPath + "\\ " + objFitxer.Value.Nom))
{
FileInfo fiFitxer = newFileInfo(pPath + "\\ " + objFitxer.Value.Nom);
if (fiFitxer.Length != objFitxer.Value.MidaEnBytes)
{
Console.WriteLine("Fitxer amb mida diferent: " + fiFitxer.Name);
objFitxer.Value.Estat = "MIDA DIFERENT, actual: " + fiFitxer.Length;
}
else
{
FileStream fileStream = fiFitxer.Open(FileMode.Open, FileAccess.Read, FileShare.None);
// Be sure it's positioned to the beginning of the stream.
fileStream.Position = 0;
// Compute the hash of the fileStream.byte[] hashValue = mySHA256.ComputeHash(fileStream);
string hashValueStr = ConvertByteArrayToHexString(hashValue);
// Close the file.
fileStream.Close();
if (hashValueStr == objFitxer.Value.Hash)
{
objFitxer.Value.Estat = "VERIFICAT";
}
else
{
Console.WriteLine("Fitxer amb hash canviat: " + fiFitxer.Name);
objFitxer.Value.Estat = "NO COINCIDEIX";
}
}
}
else
{
objFitxer.Value.Estat = "ESBORRAT";
}
objFitxer.Value.DataVerificacio = DateTime.Now;
}
catch (IOException e)
{
Console.WriteLine($"I/O Exception: {e.Message}");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"Access Exception: {e.Message}");
}
}
Save(pPath, DicFitxers);
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach(string Carpeta in Carpetes)
{
verifica(Carpeta);
}
}
}
publicstaticDictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = newXmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = newDictionary<string, clsFitxer>();
Doc.Load(pPath + "\\hasher.xml");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
llistaDeFitxer = Fitxers.ChildNodes;
foreach (XmlNode Fitxer in llistaDeFitxer)
{
objFitxer = new clsFitxer();
Nom = Fitxer.SelectSingleNode("descendant::nom");
Hash = Fitxer.SelectSingleNode("descendant::hash");
DataCreacio = Fitxer.SelectSingleNode("descendant::datacreacio");
DataVerificacio = Fitxer.SelectSingleNode("descendant::dataverificacio");
Estat = Fitxer.SelectSingleNode("descendant::estat");
MidaEnBytes = Fitxer.SelectSingleNode("descendant::midaenbytes");
objFitxer.Nom = Nom.InnerText;
objFitxer.Hash = Hash.InnerText;
objFitxer.DataCreacio = DateTime.ParseExact(DataCreacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.DataVerificacio = DateTime.ParseExact(DataVerificacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.Estat = Estat.InnerText;
objFitxer.MidaEnBytes = long.Parse(MidaEnBytes.InnerText);
DicFitxers.Add(objFitxer.Nom, objFitxer);
}
return DicFitxers;
}
publicstaticvoid crea(string pPath)
{
Console.WriteLine(ObtenirData() + " - creant fitxer hashos: " + pPath);
if (File.Exists(pPath + "\\hasher.xml"))
{
File.Delete(pPath + "\\hasher.xml");
}
SHA256 mySHA256 = SHA256.Create();
DirectoryInfo dir = newDirectoryInfo(pPath);
FileInfo[] files = dir.GetFiles();
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = newDictionary<string, clsFitxer>();
foreach (FileInfo Fitxer in files)
{
try
{
if (Fitxer.Name.ToLower() != "hasher.exe" && Fitxer.Name.ToLower() != "hasher.xml")
{
FileStream fileStream = Fitxer.Open(FileMode.Open);
// Be sure it's positioned to the beginning of the stream.
fileStream.Position = 0;
// Compute the hash of the fileStream.byte[] hashValue = mySHA256.ComputeHash(fileStream);
string hashValueStr = ConvertByteArrayToHexString(hashValue);
// Close the file.
fileStream.Close();
objFitxer = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
DicFitxers.Add(Fitxer.Name, objFitxer);
}
}
catch (IOException e)
{
Console.WriteLine($"I/O Exception: {e.Message}");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"Access Exception: {e.Message}");
}
}
Save(pPath, DicFitxers);
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
crea(Carpeta);
}
}
}
publicstaticvoid Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = newXmlDocument();
XmlNode Fitxers;
XmlNode Fitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
Doc.LoadXml("<?xml version=\"1.0\" standalone=\"yes\"?><fitxers></fitxers>");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Fitxer = Doc.CreateNode(XmlNodeType.Element, "fitxer", "");
Nom = Doc.CreateNode(XmlNodeType.Element, "nom", "");
Hash = Doc.CreateNode(XmlNodeType.Element, "hash", "");
DataCreacio = Doc.CreateNode(XmlNodeType.Element, "datacreacio", "");
DataVerificacio = Doc.CreateNode(XmlNodeType.Element, "dataverificacio", "");
Estat = Doc.CreateNode(XmlNodeType.Element, "estat", "");
MidaEnBytes = Doc.CreateNode(XmlNodeType.Element, "midaenbytes", "");
Nom.InnerText = objFitxer.Value.Nom;
Hash.InnerText = objFitxer.Value.Hash;
DataCreacio.InnerText = ObtenirData(objFitxer.Value.DataCreacio);
DataVerificacio.InnerText = ObtenirData(objFitxer.Value.DataVerificacio);
Estat.InnerText = objFitxer.Value.Estat;
MidaEnBytes.InnerText = objFitxer.Value.MidaEnBytes.ToString();
Fitxer.AppendChild(Nom);
Fitxer.AppendChild(Hash);
Fitxer.AppendChild(DataCreacio);
Fitxer.AppendChild(DataVerificacio);
Fitxer.AppendChild(Estat);
Fitxer.AppendChild(MidaEnBytes);
Fitxers.AppendChild(Fitxer);
}
Doc.Save(pPath + "\\hasher.xml");
}
publicstaticstring ConvertByteArrayToHexString(byte[] ba)
{
StringBuilder sb = newStringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString().ToUpper();
}
}
}
Després la classe:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hasher
{
class clsFitxer
{
publicstring Nom { get; set; }
publicDateTime DataCreacio { get; set; }
publicDateTime DataVerificacio { get; set; }
publiclong MidaEnBytes { get; set; }
publicstring Hash { get; set; }
publicstring Estat { get; set; }
public clsFitxer()
{
}
public clsFitxer(string pNom, DateTime pDataCreacio, DateTime pDataVerificacio, long pMidaEnBytes, string pHash, string pEstat)
{
Nom = pNom;
DataCreacio = pDataCreacio;
DataVerificacio = pDataVerificacio;
MidaEnBytes = pMidaEnBytes;
Hash = pHash;
Estat = pEstat;
}
}
}
I fet!
#29/04/2019 17:36 Programació C# Autor: Alex Canalda
Allà pel 1980 els russos van fer l'operació "Infektion" on volien fer creure que el SIDA era un experiment militar dels USA que s'havia escapat. També van publicar un manual de desinformació que adaptat als nous temps quedaria com:
Trobar esquerdes en la societat: demogràfiques, econòmiques, socials, ètniques...
Plantar distorsions: creant narratives alternatives, veritats "diferents" creïbles que apuntin a aquestes esquerdes.
Embolcallar aquestes veritats "diferents" en algo que sigui veritat. Per augmentar la credibilitat.
Anar construint audiències: poc a poc amb els mitjans tecnològics actuals FB, Twitter, etc... anar disseminant la propaganda.
Amagar la teva mà: fer veure que les històries venen d'algun altra lloc.
Cultivar idiotes útils, "believers" o creients, que inclús poden anar més enllà del plantejament inicial.
Negar estar involucrat, sempre. Encara que sigui evident.
Jugar a llarg plaç, potser aquest cop no, però a força de repetir una mentida potser acaba sent veritat.
Ho he trobat al Schneier, més que res per saber on estem. Crec que en aquesta campanya electoral aquest manual s'està aplicant molt bé. En algunes coses hem recorda al F.U.D, però més detallat i més elaborat.
Fa uns dies, aprofitant que el canvi climàtic ens ha donat un temps primaveral hem anat d'excursió amb els nens, per la natura natural del món mundial. El cas es que hem trobat que aquesta excursió es pot fer amb nens, i pels adults de ciutat, sedentaris, que ens cansem només d'anar a la cantonada també va bé. Es a dir té una dificultat zero, inexistent. Fàcil, fàcil.
Resulta que cap al 1914 a Bagà, van decidir fer un trenet pel mig del bosc per tal de portar els troncs del bosc fins a la serradora de Berga. I clar els trenets no poden ni tenir gaire desnivell ni fer corbes molt tancades, perfecte per caminar sense cansar-se.
No és que el tren anés fins a Berga però sí fins a Gisclareny, encara que nosaltres només vam fer un tram que va fins Bagà (no fos que ens canséssim). És força pla, i està acondicionat per nens, no poden caure (bé, segur que hi ha algun que s'hi esforça molt molt i ho aconsegueix, però un nen normal no cau amb les bones baranes que hi ha), i té alguns elements "divertits" com túnels i ponts penjant. Al llarg de tot el trajecte hi ha bones vistes.
Va ser un dia molt maco, 100% recomanat! Més informació aquí i aquí.
El llibre segueix el ritme dels anteriors, un ritme extra-lent, amb una mica d'acció (poqueta) i el que m'ha estranyat és que l'acció final passa d'una forma inesperada i confusa, ni rellegint he aconseguit entendre el que passava al final de tot. Però tinc que confessar que quan hem passa això tiro de Viquipèdia i llavors faig un "aaaaah, era això". M'ha estranyat aquest estil confús. Ara estic al següent i ja he tornat a la normalitat.
[Spoilers] En Perrin persegueix als segrestadors de la seva dóna, la Elaine va consolidant el seu poder com a reina i en Mat retorna a les seves aventures a Ebou Dar. Allí coneix a la seva futura dóna, "La Filla de les nou llunes", la Tuon. Que resulta que és la princesa hereva dels Seanchan. Com ell vol fugir de Ebou Dar i ella els descobreix, va i la segresta. En Rand es fa Warder de la Elaine, la Aviendha i la Min. I deixa embarassada a la Elaine.
Però la part principal és el final, on en Rand viatja amb la Nyaeve a Shadar Logoth on amb l'ajut dels massius potenciadors de la màgia Choedan Kal neteja de corrupció el Saidin. Així els mags home no es tornaran bojos. Això resulta en la creació d'una bola sobre la ciutat maleïda que explota i la destrueix. [/Spoilers]
Els llibres no estan malament, però són excessivament llargs e innecessàriament descriptius. I quan ha d'explicar el que realment importa va i ho fa d'una forma confusa... Pfffff... Aquest té un "pse, pse" de valoració, Next!
He vist les tres temporades d'aquesta sèrie. Mmmmmm... No està malament, però... hi ha vegades que notes la mantega com s'allarga en massa superfície de pa.
[Spoilers] Partint de la base que l'argument no és creïble, tracta de la venjança d'un home que els anglesos li han matat la dona i el fill en el nou mon. Combinat amb el tràfic de pells, negocis xungos, etc... Hi ha la jefa de la taverna que està enamorada del "bo", el jove que arriba d'Anglaterra al nou mon, el gay sàdic, el dolent molt dolent... Les temporades són curtes, 8 - 10 episodis, i apa. Acaba que el "bo" mata al dolent, per mi massa ràpid. I deixen la porta oberta a una 4arta temporada ja que tot just descobreix que el seu fill potser no és mort, que el van vendre d'esclau... [/Spoilers]
La serie distreu, però no enganxa (així es pot veure amb calma, suposo que no enganxa ja que a vegades allarguen massa el tema), està ben feta i té bons paisatges. Recomanable si no es té res millor a fer.
Imaginem un petit país llunyà on hi ha dos partits (que governen amb la mateixa ineptitud) però es van alternant en el govern. Clar, quan uns estan al poder els altres no poden robar diners... Uis! Quin rollo no? Per això alguna ment pensant va inventar les privatitzacions.
Clar, en aquell país hi havien moltes empreses públiques on es col·locaven els afins i cada cop que es canviava el govern apa! Tots al carrer i posar els nous. I si no anaven al carrer quedaven arraconats sense utilitat però cobrant. Però vet aquí un dia que uns van pensar... i si privatitzem...
Clar, el privatitzar té dues "grans avantatges" (notis el sarcasme), cobres una millonada per gastar en coses que guanyin vots i de rebot col·loques a afins en les noves cúpules empresarials. Aquestes noves cúpules NO seran renovades quan pugi el partit contrari, per que clar és empresa "privada". Com a corol·lari, en aquesta empresa privatitzada pots fer oposició a les polítiques de l'altra, sabotejar-lo i si van mal dades i estas al carrer sempre els pots demanar algun lloc de treball on no treballis i cobris. Una idea genial! En aquell país ho van fer, i ara els va molt bé /s (sarcasme).
Aquest és el llibre 8 de la sèrie i segueix la pauta habitual, amb el ritme normal i molt descriptiu de l'autor. Encara que té un xic més d'acció que els anteriors, però no gaire més.
[Spoilers]Elayne Trakand, Nynaeve al'Meara, Aviendha, fan servir la "cassola dels vents", un ter'angreal, per tornar a posar el clima a lloc, traient el calor antinatural que ha generat el DarkOne. Just acabar fugen de la invasió dels Seanchan mitjaçant Traveling cap a Andor, on la Elayne inicia la seva reclamació sobre el tro.
Perrin Aybara va a Ghealdan a parlar amb el Masema Dagar, l'autoproclamat profeta del Dragon, pel camí rescata a Morgase, la reina caiguda de Andor. Aconsegueix un jurament de vassallatge de la Alliandre, Queen of Ghealdan. Al final del llibre els Shaido segresten a la seva dona, la Faile.
Egwene al'Vere, Amyrlin Seat de les rebels Aes Sedai, manipula els seus seguidors per tal d'aconseguir més control i fa un Travel per arribar a Tar Valon i posar-lo sota setge.
Rand al'Thor, amb els seus mags Asha'man i Illianers, lluiten contra els Seanchan a Altara. Encara que guanya els primers enfrontament, en Rand perd el control mentre fa servir el sa'angreal 'Callandor', i al final hi ha un empat. Retorna a Cairhien, i allí en Rand es atacat per en Dashiva un mag traidor, però falla en matar-lo. [/Spoilers]
Pse, li sobra molta palla, les sobre-descripcions es mengen l'acció. A vegades passa algo i es perd en mig de tanta descripció. Cansa molt, estar pàgines i pàgines descrivint coses sense que passi res. La solució és la lectura ràpida, perds detalls però no et mores d'avorriment. A vegades tinc que rebobinar una mica per que em passo de llarg, per contra va bé per agafar el son si un dia llegeixo abans d'anar a dormir, aleshores ho llegeixo tot :D. A pel següent!