Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

Ars programatica

Udělat dobrý sotware je řemeslo, udělat výjimečný software je umění
Microsoft TechDays 2012

Když jsem poprvé uviděl Windows 8, pochopil jsem, že tohle je tak radikální změna, že by nebylo od věci, kdybych mi k tomu řekl něco někdo, kdo ví co, jak a proč, nejlépe někdo od Microsoftu. Proto jsem, ač podobné akce v poslední době zanedbávám, vyrazil na Microsoft TechDays.

 

Musím přiznat, že Microsoftu někdy nerozumím. Například nechápu, proč preview Windows 8 nedal svým lidem v předstihu, aby se s nimi mohli řádně seznámit, ale ve stejném termínu, jako široké veřejnosti. To si pak připadám jako v páté třídě, když přišel převrat a naráz byla zrušena výuka ruštiny a nahrazena výukou západních jazyků, které ale samozřejmě neměl kdo učit, takže se toho zhostili ruštinářky, které byly v němčině snad jen tři lekce před námi. Tato výtka ovšem směřuje za vedením, lidé z české pobočky se svého úkolu zhostili na výbornou.

 

Ale k věci: dobrá zpráva je, že Windows 8 nenahrazují klasický desktop, ale představují jen další možnost UI, určenou především pro tablety a podobná zařízení zaměřená na konzumaci obsahu. Metro (jak se nové „telefonoidní“ prostředí jmenuje) není určeno k pořizování dát.

 

Programovací model je velmi striktní, ale z pohledu aplikací určených pro koncového „cool“ uživatele podle mě zcela postačují a troufám si tvrdit, že lidé – konzumenti si na něj zvyknou a přijdou mu na chuť.

 

Dokonce i Visual Studio se nesmělými krůčky pokouší dospět. Nová verze (zatím rovněž v betě a s neustáleným označením) vypadá dobře a zdá se umět některé zajímavé věci, hlavně co se editoru kódu týče, které v dosavadních verzích chyběly, otázka ale je, zda bude alespoň tak rychlé, jako VS2010, tj. pomalé a nestabilní.

 

Celkově bych řekl, že Microsoft nespí na vavřínech, má co nabídnout a má pár dobrých nápadů. Jestli se ovšem ujmou, to bude záležet i na tom, jak moc bude vývoj aplikací pro Windows 8 bolet, tj, jak kvalitní a spolehlivé budu vývojářské nástroje a jaké administrativní nároky bude Microsoft na vývojáře klást (např. nutnost udávat číslo platební karty při zakládání i trial účtu na Azure).

 

Škoda, že se Microsoftu nevyhnuly obligátní potíže, jako problémy se sítí, či pomalé internetové připojení, kvůli kterým příliš mnoho demo ukázek skončilo bezvýsledně s tím, že teď to nejde a není čas to řešit, takže si to domyslete, protože ukázka nebude (o přestávkách se všechno opravit nedá.)

 

P.S. Silverlight, který měl ještě před půl rokem v ústech lidí Microsoft budoucnost jistou a zářivou, byl definitivně pohřeben spolu s ostatními pluginy do prohlížeče.

Konfigurace CodeRush Xpress

Rozhodl jsem sevyzkoušet rozšíření pro Visual Studio z rodiny „productivity tools" CodeRushXpress. Jedná se o bezplatnou a notně očesanou verzi placeného nástrojeCodeRush, který jsem ke svému velkému překvapení vyhodnotil jako užitečnější,než vyhlášený ReSharper. Verze zdarma je sice určena především k tomu, abyuživatele namlsala, přesto však není zcela nepoužitelná, nabízí některé úpravykódu a především mé oblíbené zvýrazňování výskytů identifikátoru. Na rozdíl od „dospělé"verze jsem však po nainstalování marně hledal možnosti konfigurace - v Optionsnic a samostatné menu, stejně jako vlastní toolbar se nekonal; editaci konfiguračníchXML souborů jsem předem zamítl). Nakonec pomohl help: konfigurační dialog proCodeRush Xpress se vyvolá klávesovou zkratkou Ctrl+Alt+Shift+O

Posted: 19. dubna 2010 13:03 by pbouda | 3 Comments
Vedeno pod: ,
Seznam changesetů v TFS za období

Seznam všech (mých) changesetů vytvořených v nějakém časovém intervalu od-do lze získat z příkazové řádky utilitou tf.exe následovně:

tf history * /r /user:username /version:Dyyyy-mm-dd~Dyyyy-dd-mm

 

Interval se zadává jako specifická verze, datum je určeno prefixem "D" a data jsou oddělena "~" (vlnovkou). Je-li zadáno pouze jedno datum, má význam do.

Posted: 7. prosince 2009 14:35 by pbouda | 2 Comments
Vedeno pod: ,
WCF a WF v .NET 4.0
Starší, nikoliv však zastaralé články a připrovavovaných novinkách v .NET 4.0 (VS 2010)
 
(via Mike Taulty's Blog)
Když uživatel nemůže pracovat s TFS-WA, i když má všechna práva

Expozé

Tento příspěvěk by se stejně dobře mohl jmenovat "lovcovy zápisky z honu na duchy". Bude asi trochu zmatečný, stejně jako moje ponětí o tom, co se vlastně dělo a čím že jsem to nakonec vyřešil.

Úvod do problému

Chtěl jsem dalšímu uživateli umožnit přístup do TFS přes TFS Web Access, zopakoval jsem tedy postup, který v minulosti zafungoval u jiného uživatele, tj. přidal jsem ho do skupiny Contributors příslušného projektu. Ale ouha - to co předtím fungovalo, tentokráte naprosto selhalo. Každý jeho pokus o přístup do TFS skončil s chybou "Unable to create workitemstore see exceptions for more details."

InnerException jsem se samozřejmě nikde nedohledal, ale občas se podařilo v TFS-WA vymámit tuto chybu: "RebuildCallersViews: Connecting Domain User could not be validated. ---> RebuildCallersViews: Connecting Domain User could not be validated. ---> RebuildCallersViews: Connecting Domain User could not be validated."

To už bylo lepší, ale pořád málo

Vyšetřování

Po chvíli práce s vyhledávačem jsem zjistil, že chyba je pravděpodobně v synchronizaci informací mezi doménou a tabulí  TFSWorkItemTracking..ADObjects. To lze ověřit tímto SQL:

select next_id - 1 as GSSMaxIdenditySeqId from TFSIntegration..tbl_sequence_ids where name = 'identity_cache'
select max(seqid) as WITMaxIdentitySeqId, MAX(LastSyncUTC) as LastSyncUTC from TFSWorkItemTracking..ADObjects

Pokud jsou data synchronní, oba dotazy by měly vrátit stejné ID. V mém případě stejná nebyla, takže stopa.

Jenže proč k synchronizaci nedochází?

Nejprve jsem zkontroloval joby v SQL serveru a zjistil, že některé z nich jsou nastaveny tak, aby běžely pod účtem kolegy, který již před delší dobou odešel. Přenastavil jsem je tedy na platný účet - a nic.

Vyšetřování pokračuje

Po další chvíli práce s vyhledávačem jsem se dostal k tomuto SQL:

select [address], [domain], [account_name], [deleted]
from TfsIntegration..tbl_subscription s
join TfsIntegration..tbl_security_identity_cache i
on s.subscriber = i.sid
where s.delivery_type = 2

Account name by měl být platný účet a příznak deleted by měl být false (respektive 0). A zde byl opět již neexistující účet bývalého kolegy. Zajásal jsem a tbl_subscription.account_name nastavil na SID platného účtu - a nic.

Řešení?

Poslední krok, po kterém se tabule sesynchronizovaly a nově přidaný uživatel se mohl konečně přihlásit, byl restart IIS a smazání cache TFS-WA (ta je standardně v \Program Files\Microsoft Visual Studio 2008 Team System Web Access\Cache\).

A proč řešení s otazníkem? Protože si nejsem po všem tom laborování jistý, co přesně bylo rozhodující pro vyřešení problému s přihlašováním, zda všechno (i špatný account jobu), nebo jen část (oprava v tbl_subsriptions a restart IIS), a jestli jsem náhodou neudělal ještě něco důležitého (například update TfsWorkItemTracking.dbo.Persons set fRebuildWrite = 1, kterýžto SQL jsem objevil na jedné otevřené záložce browseru), na co jsem mezitím zapomněl.

 

Posted: 15. června 2009 15:29 by pbouda | 0 Comments
Vedeno pod: ,
Chybná stavová ikona u souboru v TFS

Někdy se stává, že v Solution Exploreru jsou u souborů uložených v TFS zobrazeny špatné stavové ikony, které naznačují, že soubor je check-out někým jiným, přestože to není pravda (jak lze ověřit přes Source Control Explorer). Příkaz Refresh Status z menu File / Source Control nepomůže, nepomůže ani znovuvytvořit workspace... Ne že by kvůli tomu nešlo kompilovat, nebo tak něco, ale mate to.

Nakonec jsem s největší pravděpodobností odpověď nalezl: stává se to u souborů, které jsou shelvsetu. Každopádně zrušit shelvset pomohlo, jenom mne mate, že u klienta jsem měl shelvsetů nepočítaně a přitom se ikonky zobrazovaly správně.

Integrace WinMerge do Visual Studia

Během práce u klienta jsem si pro "Compare" operace ve Visual Studiu (TFS) nainstaloval WinMerge a po návratu od něj (u klienta jsem dělal na jeho počítači) jsem zjistil, že už se bez něj nedokáži obejít a že mi standardní komparátor ve VS nestačí. A že jsem zapomněl, jak WinMerge pro spolupráci s VS správně nakonfigurovat. A protože se mi to nechtělo zjišťovat, obrátil jsem se s důvěrou na Strýčka Googla a našel původní dva články, ze kterých jsem vycházel:Using winmerge as a merge tool in Visual Studio Team Suite a Using WinMerge with TFS.

Postup je jednoduchý:

  1. Nainstalovat WinMerge
  2. Menu Tools, položka Options, pak ve stromu Source Control, pod ním Visual Studio Team Foundation Server a na něm tlačítko Configure User Tools...
  3. Vybrat .exe WinMerge a správně zadat Arguments
    1. Compare: /x /e /ub /wl /dl %6 /dr %7 %1 %2
    2. Merge: /x /e /ub /wl /dl %6 /dr %7 %1 %2 %4

Má to jenom jednu chybu, a sice když je v nastavení WinMerge zašrtnuto "Allow only one instance tu run" a člověk se jej z VS pokusí otevřít ještě jednou, neotevřou se porovnávané soubory jako nová záložka v běžící instanci WinMerge, ale skončí to s podivnou chybou "The system cannot find the file specified". A vypadá to spíše na chybu VS, protože ten file (v TFSTemp), kterého se WinMerge domáhá, skutečně neexistuje.

Jeremy Miller : Cohesion And Coupling

Zajímavý článek od Jeremy Millera Cohesion And Coupling vyšel již před časem v MSDN Magazine.

Obsah

  • Decrease Coupling
  • Increase Cohesion
  • Eliminate Inappropriate Intimacy
  • The Law of Demeter
  • Tell, Don't Ask
  • Say It Once and Only Once
  • Wrapping Up 

Základní principy

  1. Keep things that have to change together as close together in the code as possible.
  2. Allow unrelated things in the code to change independently (also known as orthogonality).
  3. Minimize duplication in the code.

 

Solution Folders

Užitečnou pomůckou pro organizaci projektů (větší solution jich může obsahovat i řádově desítky) jsou solution folders - složky, které existují pouze v rámci solution a projekty v nich mohou být zařazeny bez ohledu na své fyzické umístění na disku. Velmi dobrý příklad je zde, jiný dobrý příklad nabízí např. Enterise Library, viz následující screenshoty:

 

 
Organizace na disku

 

 

 Organizace v Solution Exploreru

Mažeme na 116%

Nikdy nedefinovaný zákona zachování souborů by mohl znít: Lze smazat pouze tolik souborů, kolik jich bylo na filesystém uloženo. Total Commander jich však zvládne smazat mnohem více:

 

(Jistě, je to důsledek numerické chyby, nebo nějaké optimalizace, ale přeci jenom to člověka zarazí: co když opravdu začal mazat i něco víc, než co smazat měl?)

Špíček - zadávání velkých čísel nadvakrát

Problém, o kterém chci dnes mluvit, je úzce svázán s konkrétními technologiemi, takže asi nikomu trn z paty nevytrhne, nicméně jako inspirace a příklad toho, jakým způsobem se jednotlivé komponenty vzájemně ovlivňují a k jakým potížím to může vést, poslouží myslím celkem dobře.

 

Budiž chyba: Do prvku UI ButtonEdit (součást DevExpress), který je nabindován na dataset a má nastavenu numerickou maskou, nejde zadat více než 10 číslic jinak, než tak, že uživatel pole opustí a opět se do něj vrátí.

 

Po nikam nevedoucím laborování s nastavením masky a bindingu, následovaném chvilkou hledání na stránkách podpory výrobce je bezprostřední příčina a tedy i řešení na světě: The problem is that your TextEdit control is bound to an integer value. However, the integer type cannot accept more than 10 digits. The solution is to bind the control to a long value.

 

S touto znalostí je oprava již snadná: stačí při inicializaci (v InitializeComponent()) nastavit vlastnost EditValue controlu na hodnotu typu, který má větší rozsah než Int32, např: EditValue = 0L; nebo EditValue = new decimal(new int[] {0, 0, 0, 0}); (pozn. nelze použít EdiValue = 0m; protože s tímto zápisem se nevypořádá VS designer).

 

Tím se také vysvětluje, proč pomáhalo zadávání nadvakrát, tedy opustit kontrol a zase se do něj vrátit. Při opuštění se hodnota zapsala do datasetu, to vyvolalo změnovou událost, na kterou kontrol zareagoval načtením hodnoty z datového zdroje. A protože tato hodnota byla již typu Decimal, kontrol se tomu přizpůsobil a umožnil zadávání čísel přesahujících rozsah Int32.

 

Jenže stále zůstává otázka proč? Proč se kontrol chová, jako by byl nabindován na hodnotu typu Int32, když příslušný sloupec v datasetu je typu Decimal, respektive Int64? Tak na tuto otázku bohužel nemám lepší odpověď, než že to někdo naprogramoval tak, že se nezjišťuje typ vlastnosti, na kterou je kontrol nabindován, ale typ hodnoty, kterou binding vrátí. A je-li tato hodnota null (což u nově založené řádky v datasetu je), pak se kontrol chová, jako by byl bindován na defaultní Int32.

Rychlost volání delegátů

Cituji z (jinak velmi zajímavého, doporučuji k přečtení) článku The cost of enumerating in .NET:

Delegate dispatch still isn’t quite the speed of virtual method dispatch.  And delegates bound to static methods are actually slightly slower than those bound to instance methods, which is why you’ll notice a slight difference in the original “s” versus “i” measurements.  The reason is subtle.  There is a delegate dispatch stub that is meant to call the target method: when the delegate refers to an instance method, the ‘this’ reference pushed in EAX points to the delegate object when it is invoked and the stub can simply replace it with the target object and jump; for static methods, however, all of the arguments need to be “shifted” downward, because there is no ‘this’ reference to be passed and therefore the first actual argument to the static method must take the place of the current value in EAX.

Override virtuálních vlastností

Virtuální vlastnosti jsou definovány takto:

public class Base
{
  private bool isValid;

  public virtual bool IsValid
  {
    get { return this.isValid; }
    set { this.isValid = true; }
  }
}

Kód, který pro předefinování takto definované vlastnosti v potomkovi vygeneruje VS po "expanzi" klíčového slova override (a který jsem většinou slepě používal) je následující:

public class Derived : Base
{
  private bool hasInvalidItems = false;

  public override bool IsValid
  {
    get
    {
      
// & this.hasInvalidItems je implementace specifická pro třídu Derived

      return base.IsValid & this.hasInvalidItems; 
    }
    set
    {
      base.IsValid = value;
    }
  }
}

Jazyk C# však umožňuje předefinovat pouze getter/setter, přičemž pro nepředefinovaný accessor se použije implementace z předka:

public class Derived : Base
{
  private bool hasInvalidItems = false;

  public override bool IsValid
  {
    get
    {
      return base.IsValid & this.hasInvalidItems;
    }
  }

}

Musím kajícně přiznat, že přes letitou praxi jsem na tuto vlastnost C# přišel teprve nedávno. Přitom to není nic překvapivého, uvědomí-li si člověk, jak jsou vlastnosti realizovány na úrovni IL, je to zcela logické (tak jsem to ostatně také přišel - úvahou).

P.S. Jaký je překlad termínu override do češtiny? Nenapadá mne nic, co by nebylo matoucí a zavádějící.

Posted: 5. září 2008 16:42 by pbouda | 6 Comments
Vedeno pod: ,
Chyba 14001 při spuštění windows service

Byl jsem poněkud zaskočen tím, že se mi najednou nepodařilo spustit službu, která dříve bez problému chodila, a na níž se nezměnilo nic jiného, než že byla nově zkompilována po přechodu na VS2008. Chybová zpráva zněla:

System error 14001 has occurred.

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

Protože se v ní hovoří o "application configuration", začal jsem hledat příčinu v chybném .config souboru. Také jsem si ale povšiml, že k selhání služby dojde tak rychle po pokusu o spuštění, že velmi pravdepodobně není vůbec nataženo CLR a spuštěn .NET kód, takže .config není vůbec použit.

Začal jsem tedy pečlivěji pátrat v Event Logu, ve kterém jsem nakonec nalez několik záznamů ze zdroje SideBySide, které se týkají příslušné služby:

  • Syntax error in manifest or policy file "Service.exe.Config" on line 2. The manifest file root element must be assembly.
  • The application failed to launch because of an invalid manifest.
  • The CliView Application Server Host Service service failed to start due to the following error: This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
  • A také poněkud matoucí Generate Activation Context failed for Service.exe. Reference error message: The operation completed successfully.

Z těchto záznamů jsem usoudil, že chyba je někde v manifestu aplikace, což bylo nepříjemné, protože je to pro mne španělská vesnice, a navíc s ním nikde vědomě nepracuji.

Nakonec jsem však řešení nalezl poměrně rychle ve Visual Studiu v Project Properties na záložce Application. Zde je ve spodní části sekce Resources, v ní volba Icon and Manifest a pod ní Manifest. Zde je možno vybrat mezi Embed manifest with default settings (defaultní volba) a Create application without a manifest. Stačí přepnout na Create application without a manifest, překompilovat a chodí to.

Mám však jisté pochybnosti o tom, že toto je skutečná příčina problémů, spíše si myslím, že by měl být způsob, jak vytvořit aplikaci s manifestem tak, aby mohla být zároveň spouštěna jako windows service.

Inicializéry (C# 3.0)

Jednou z novinek v jazyce C# 3.0 jsou inicializéry (anglicky initializers), typický zástupce rodu syntaktický cukr. Jedná o speciální konstrukci, která volitelně následuje po volání konstruktoru a ve které je umožněn implicitní přistup k nově vytvořené instanci a jejím datovým (pole, vlastnosti) členům. Zřejmější to bude na příkladu:

Mějme třídu Alfa:

public class Alfa
{
public int i;
public string s;
}

Její instanci je s pomocí inicializéru možno vytvořit takto:

Alfa a = new Alfa { i = 1, s = "a" };

což je zcela ekvivalentní zápisu: 

Alfa newAlfa = new Alfa();
newAlfa.i
= 1;
newAlfa.s
= "a";
Alfa a
= newAlfa;

(Poznámka: Závorky ve volání konstroktoru nejsou při použití inicializátoru povinné, takže Alfa a = new Alfa { i = 1, s = "a" }; a Alfa a = new Alfa () { i = 1, s = "a" }; jsou zcela rovnocenné zápisy.)

Z tohoto pohledu se tedy zdá, že inicializér nic nového nepřináší. Využití inicializéru je především v souvislosti s anonymní typy a LINQ. V následujícím příkladě (alfas je kolekce instancí třídy Alfa): 

var small = from a in alfas select new {Number = a.i};

představuje výraz new {Number = a.i} vytvoření instance anonymního typu. Kompilátor z inicializéru vyčte strukturu anonymního typu a především jména vlastností, která by ze standarní syntaxe konstruktoru nebylo vyčíst nedala.

Inicializace kolekcí

Větší použití zřejmě nalezne inicializér při vytváření kolekcí. Výše zmiňovanou kolekci alfas je s pomocí inicializéru možno vytvořit následovně:

 

List<Alfa> alfas = new List<Alfa>
{
new Alfa {i=1, s="one"},
new Alfa {i=2, s="two"},
new Alfa {i=3, s="three"},
};

což je ekvivalentní zápisu:

List<Alfa> alfas = new List<Alfa>();
Alfa a;
a
= new Alfa();
a.i
= 1;
a.s
= "one";
alfas.Add(a);
a
= new Alfa();
a.i
= 2;
a.s
= "two";
alfas.Add(a);
a
= new Alfa();
a.i
= 3;
a.s
= "three";
alfas.Add(a);

Který z obou zápisů je čitelnější je nabíledni.

Inicializace členských proměnných

Inicializéry umožňují též komplexní inicializaci členských proměnných třídy v deklaraci, což bylo zatím nutno řešit v explicitně konstruktoru. Opět ukáži na příkladu, protože tak to bude nejsrozumitelnější:

public class UsingInitializers
{
private List<Alfa> alfaList = new List<Alfa>
{
new Alfa {i=1, s="one"},
new Alfa {i=2, s="two"},
new Alfa {i=3, s="three"},
};
};

Vnořené inicializéry

Mějme kromě výše zmíněné třídy Alfa ještě třídu Omega:

public class Omega
{
public Alfa alfa;
}

Její instanci je s pomocí inicializéru možno vytvořit takto:

Omega w = new Omega { alfa = new Alfa { i = 3, s = "w" } };

Pozor, vnořený inicializér nevytváří instanci, kterou inicializuje. Proto je ve výše uvedeném příkladě třeba použít new Alfa(). Pokud by ovšem třída Omega byla definována následovně:

public class Omega2
{
public Alfa alfa = new Alfa();
}

Potom lze napsat jen:

Omega2 w2 = new Omega2 { alfa = { i = 3, s = "w" } };

Podobný zápis, ale s třídou Omega, tedy:

Omega w = new Omega { alfa = { i = 3, s = "w" } };

způsobí run-time exception.

 

(Pozn. Opravil jsem některé chyby, na které jsem byl upozorněn v komentářích).

Posted: 5. srpna 2008 16:18 by pbouda | 8 Comments
Vedeno pod: , ,
Více článků Další stránka »
Vyvojar.cz na prodej!