<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Programmierung &#8211; Karl Jepertinger IT Consulting</title>
	<atom:link href="https://www.jepertinger-itconsulting.de/category/programmierung/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.jepertinger-itconsulting.de</link>
	<description>Consultant as a Service!</description>
	<lastBuildDate>Fri, 29 Jun 2018 19:27:26 +0000</lastBuildDate>
	<language>de-DE</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.1</generator>
	<item>
		<title>SQLAlchemy: Joined Table Inheritance</title>
		<link>https://www.jepertinger-itconsulting.de/2018/06/29/sqlalchemy-joined-table-inheritance/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Fri, 29 Jun 2018 19:23:31 +0000</pubDate>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[object relationaler mapper]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sqlalchemy]]></category>
		<category><![CDATA[sqlite]]></category>
		<guid isPermaLink="false">http://www.jepertinger-itconsulting.de/?p=859</guid>

					<description><![CDATA[Eigentlich lässt die Dokumentation des ORM SQLAlchemy für Python keine Wünsche offen. Auch das Klassenmapping mit Polymorphy ist gut dokumentiert. Was aber noch etwas zu kurz kommt ist die Datenbanksicht. Ich möchte hier das Beispiel der Dokumentation aufgreifen. Von einer &#8230; <a href="https://www.jepertinger-itconsulting.de/2018/06/29/sqlalchemy-joined-table-inheritance/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Eigentlich lässt die Dokumentation des <a href="https://de.wikipedia.org/wiki/Objektrelationale_Abbildung" target="_blank" rel="noopener">ORM</a> <a href="http://docs.sqlalchemy.org/en/latest" target="_blank" rel="noopener">SQLAlchemy</a> für Python keine Wünsche offen. Auch das <a href="http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/inheritance.html?highlight=joined%20table%20inheritance" target="_blank" rel="noopener">Klassenmapping mit Polymorphy</a> ist gut dokumentiert. Was aber noch etwas zu kurz kommt ist die Datenbanksicht.</p>
<p>Ich möchte hier das Beispiel der Dokumentation aufgreifen.<br />
Von einer Basisklasse &#8222;Employee&#8220; werden zwei weitere Klassen &#8222;Manager&#8220; und &#8222;Engineer&#8220; abgeleitet.</p>
<p>Grundsätzlich gibt es verschiedene Strategien Klassenhirarchien abzubilden</p>
<ul>
<li>Joined Table Inheritance:<br />
Bei dieser Variante gibt es für jede Klasse eine eigene Tabelle. Die beiden Subklassen erhalten eigene Tabellen mit Referenzen auf die Basisklasse.</li>
<li>Single Table Inheritance:<br />
In dieser Form wird die ganze Klassenhierarchie in einer einzelnen Tabelle abgebildet. Aus Blick des Python Codes ist alles sauber. In der Datenbank gibt es aber in der Tabelle Felder, die nur abhängig vom Typ befüllt werden dürfen. Echte Datenbank-Constraints sind damit fast unmöglich.</li>
<li>Concrete Table Inheritance:<br />
Hier gibt es auch wieder für jede Klasse eine Tabelle. Diesesmal haben die Subklassen aber keine Foreign Key Beziehung mit der Basisklasse. Jede Tabelle dupliziert auch die Spalten der Basisklasse. Aus Sicht der Datenbank gibt es nun keine Zentrale Tabelle mehr in der alle &#8222;Employees&#8220; erfasst sind. Es lässt sich damit auch kein Foreign Key Constraint mehr setzen.</li>
</ul>
<p>Um ein sauberes Datenbankmodell zu erhalten, ist somit nur die &#8222;Joined Table Inheritance&#8220; zu empfehlen:</p>
<ul>
<li>Auf Spaltenebene können ohne Problem Check-Constraints und Not-Null-Constraints definiert werden.</li>
<li>Auch ohne die Kenntnis des SQLALchemy Mappings ergibt sich für andere Anwendungen ganz automatisch welche Felder für welche Klasse gefüllt werden können.</li>
<li>Die Basisklasse kann durch andere Tabellen via Foreign Key Constraint referenziert werden.</li>
</ul>
<p>Wie wird nun eine Joined Table Inheritance in Python gemappt?</p>
<pre class="brush: python; title: ; notranslate">
class Employee(Base):
    __tablename__ = 'employee'
    Id = Column(Integer
                , primary_key=True)
    Name = Column(String(50))

class Manager(Employee):
    __tablename__ = 'manager'
    Id = Column(Integer
                , ForeignKey(Employee.Id)
                , primary_key=True)
    ManagerStatus = Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'manager',
    }

class Engineer(Employee):
    __tablename__ = 'engineer'
    Id = Column(Integer
                , ForeignKey(Employee.Id)
                , primary_key=True)

    EngineerDegree= Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'engineer',
    }
</pre>
<p>Daraus lassen sich diese Create-Statements generieren.</p>
<pre class="brush: python; title: ; notranslate">
create_engine('sqlite:///', echo= True)
Base.metadata.create_all(bind=engine)
</pre>
<pre class="brush: sql; title: ; notranslate">

CREATE TABLE employee (
	&quot;Id&quot; INTEGER NOT NULL, 
	&quot;Name&quot; VARCHAR(50), --Felder der Basisklasse sind hier  ...
	PRIMARY KEY (&quot;Id&quot;)
);
-- und werden in den abgeleiteten Tabelle nicht mehr wiederholt
CREATE TABLE engineer (
	&quot;Id&quot; INTEGER NOT NULL, 
	&quot;EngineerDegree&quot; VARCHAR(50), 
	PRIMARY KEY (id), 
	FOREIGN KEY(id) REFERENCES employee (&quot;Id&quot;)
);

CREATE TABLE manager (
	&quot;Id&quot; INTEGER NOT NULL, 
	&quot;ManagerStatus&quot; VARCHAR(50), 
	PRIMARY KEY (id), 
	FOREIGN KEY(id) REFERENCES employee (&quot;Id&quot;)
);
</pre>
<p>Wichtig ist dabei der Fremdschlüssel in den abgeleiteten Klassen, der auf die Basisklasse zeigt:</p>
<pre class="brush: python; title: ; notranslate">
#Employee.Id bezieht sich dabei auf den Klassen/Attributnamen,
#nicht etwa auf Tabellen oder Spaltenbezeichnungen
Id = Column(Integer,ForeignKey(Employee.Id), primary_key=True)
</pre>
<p>Vergisst man diesen Fremdschlüssel erhält man folgende Meldung:</p>
<blockquote><p>  Can&#8217;t find any foreign key relationships between &#8218;employee&#8216; and &#8218;manager&#8216;.</p></blockquote>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Regular Expressions und Top Level Domains</title>
		<link>https://www.jepertinger-itconsulting.de/2017/10/04/regular-expressions-und-top-level-domains/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Wed, 04 Oct 2017 19:20:00 +0000</pubDate>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[domain]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[länge]]></category>
		<category><![CDATA[prüfung]]></category>
		<category><![CDATA[regexp]]></category>
		<category><![CDATA[validierung]]></category>
		<guid isPermaLink="false">https://www.jepertinger-itconsulting.de/?p=766</guid>

					<description><![CDATA[Eine häufige Aufgabe in der Programmierung ist das suchen/validieren von Email-Adressen. Mal davon abgesehen, dass ein regulärer Ausdruck nur bedingt dazu benutzt werden kann, funktionieren filtern grobe Näherungen schon mal die meisten. Dies ist eine grobe Näherung wie sie in vielen &#8230; <a href="https://www.jepertinger-itconsulting.de/2017/10/04/regular-expressions-und-top-level-domains/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Eine häufige Aufgabe in der Programmierung ist das suchen/validieren von Email-Adressen. Mal davon abgesehen, dass ein regulärer Ausdruck nur <a href="http://www.regular-expressions.info/email.html" target="_blank" rel="noopener">bedingt </a>dazu benutzt werden kann, funktionieren filtern grobe Näherungen schon mal die meisten. <span id="more-766"></span>Dies ist eine grobe Näherung wie sie in vielen Programmen bereits hinterlegt ist. Auch im Internet finden sich noch oft Ausdrücke wie dieser (<a href="https://stackoverflow.com/questions/29392621/regex-to-extract-email" target="_blank" rel="noopener">Quelle</a>):</p>
<p><code><span class="pln">strPattern  </span><span class="pun">=</span> <span class="str">"^([a-zA-Z0-9_\-\.]+)@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$"</span></code></p>
<p>In diesem Blogpost geht es mir im besonderen um das Matching der Toplevel-Domain. Dabei ist vielfach noch hinterlegt, dass diese zwischen zwei und drei Buchstaben lang sein muss. Das gilt aber leider nur bei &#8222;country code top level domains&#8220;, die eben einem Land gehören. Generische Top Level Domains sind meist länger. Eine&#8220;.info&#8220;-Domain ist valide, würde aber von obigem Regex nicht gematcht.</p>
<p><code><span class="pln">strPattern  </span><span class="pun">=</span> <span class="str">"^([a-zA-Z0-9_\-\.]+)@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]<strong>{2,}</strong>)$"</span></code></p>
<p>Obiger Regex ist derweil immer noch nur eine Näherung an den IEEE-Standard, filtert aber längere Toplevel-Domains nicht mehr aus.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Raspberry PI 3 : Mono Installation</title>
		<link>https://www.jepertinger-itconsulting.de/2016/03/29/raspberry-pi-3-mono-installation/</link>
					<comments>https://www.jepertinger-itconsulting.de/2016/03/29/raspberry-pi-3-mono-installation/#comments</comments>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Tue, 29 Mar 2016 07:02:23 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[IOT]]></category>
		<guid isPermaLink="false">http://www.jepertinger-itconsulting.de/?p=660</guid>

					<description><![CDATA[Um auf dem Raspberry mit .Net Apps arbeiten zu können muss zuerst die entsprechende Laufzeitumgebung installiert werden. Unter Linux ist dies die freie Umgebung Mono. Im Vergleich zum Original bringt sie ein paar Einschränkungen mit, die aber bei der Programmierung &#8230; <a href="https://www.jepertinger-itconsulting.de/2016/03/29/raspberry-pi-3-mono-installation/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Um auf dem Raspberry mit .Net Apps arbeiten zu können muss zuerst die entsprechende Laufzeitumgebung installiert werden. Unter Linux ist dies die freie Umgebung <a href="https://de.wikipedia.org/wiki/Mono_%28Software%29" target="_blank">Mono</a>. Im Vergleich zum Original bringt sie ein paar Einschränkungen mit, die aber bei der Programmierung auf dem Raspi nicht weiter ins Gewicht fallen sollten.</p>
<p>Zur Installation genügt auf dem auf Debian basierenden Raspbian der Aufruf des Paketmanagers auf der Konsole:</p>
<p><em>sudo apt-get install mono-complete</em></p>
<p>Nachdem nun die eigene .Net App auf den Raspy kopiert wurde lässt sie sich einfach starten:</p>
<p><em>mono APP-NAME.exe</em></p>
<p>Grundsätzlich funktioniert die Installation auch über:</p>
<p><em>sudo apt-get install mono</em></p>
<p>Dies produziert dann beim Start  einer eigenen App eine Menge Assembly Not Found Exceptions.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.jepertinger-itconsulting.de/2016/03/29/raspberry-pi-3-mono-installation/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Extension Methods vs. Reflection</title>
		<link>https://www.jepertinger-itconsulting.de/2015/04/21/extension-methods-vs-reflection/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Tue, 21 Apr 2015 09:11:23 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">http://www.jepertinger-itconsulting.de/?p=547</guid>

					<description><![CDATA[Reflection bezeichnet (nicht nur im .Net Bereich) die Möglichkeit, zur Laufzeit die Metainformationen einer Anwendung zu nutzen. Fragestellungen wie &#8222;Wieviele Properties hat die Klasse?&#8220; können beantwortet werden, ohne dass die reflektierte Klasse zur Programmierzeit bekannt ist/war. Für die alltägliche Businesslogik &#8230; <a href="https://www.jepertinger-itconsulting.de/2015/04/21/extension-methods-vs-reflection/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Reflection bezeichnet (nicht nur im .Net Bereich) die Möglichkeit, zur Laufzeit die Metainformationen einer Anwendung zu nutzen. Fragestellungen wie &#8222;Wieviele Properties hat die Klasse?&#8220; können beantwortet werden, ohne dass die reflektierte Klasse zur Programmierzeit bekannt ist/war. Für die alltägliche Businesslogik eignet sich Reflection nur bedingt &#8211;  wohl aber für allerlei Querschnittsaufgaben. Auditing, Logging oder dynamische Oberflächen werden damit möglich.<span id="more-547"></span></p>
<p>Extension Methods wurden mit .Net 3.5 eingeführt und erlauben es einen Type zu erweitern ohne von ihm abzuleiten. So können bequem sogar &#8222;sealed&#8220; Types wie System.String erweitert werden &#8211; z.B. um eigene Substring Funktionen. Eine ebenfalls sehr nützliche Funktionalität ist es (generische) Interfaces mit konkretem Code zu hinterlegen, ohne alle Ableitungen des Interfaces zu überarbeiten zu müssen. Eine Extension Method zu IList erweitert also sofort alle Klassen die darauf aufbauen.</p>
<p>Das alles macht im ersten Moment den Eindruck einer <a title="Mehrfachvererbung in Wikipedia" href="https://de.wikipedia.org/wiki/Mehrfachvererbung" target="_blank">Mehrfachvererbung</a>. Das suggeriert auch Visual Studio, indem es die Extension- mit den Instanz-Methoden zusammen anzeigt:<a href="http://www.jepertinger-itconsulting.de/wp-content/uploads/2015/03/extensionmethod_multipleinheritance_visualstudio.jpg" rel="lightbox-0"><img loading="lazy" class="aligncenter wp-image-554 size-full" src="http://www.jepertinger-itconsulting.de/wp-content/uploads/2015/03/extensionmethod_multipleinheritance_visualstudio.jpg" alt="extensionmethod_multipleinheritance_visualstudio" width="471" height="174" srcset="https://www.jepertinger-itconsulting.de/wp-content/uploads/2015/03/extensionmethod_multipleinheritance_visualstudio.jpg 471w, https://www.jepertinger-itconsulting.de/wp-content/uploads/2015/03/extensionmethod_multipleinheritance_visualstudio-300x111.jpg 300w" sizes="(max-width: 471px) 100vw, 471px" /></a>In Wirklichkeit handelt es sich aber nur um &#8222;<a title="Syntax Sugar in der Wikipedia" href="https://en.wikipedia.org/wiki/Syntactic_sugar" target="_blank">Syntax Sugar</a>&#8222;, also einer reinen Vereinfachung für den Programmierer &#8211; intern sind das verschiedene Klassen.</p>
<p>Das hat mehrere Konsequenzen:</p>
<ul>
<li>Extension Methods können keine Interfaces implementieren</li>
<li>sie können keine abstracten Methoden ausprogrammieren</li>
<li>per Reflection sind Extensions nicht in der eigentlichen Klasse zu finden</li>
</ul>
<p>Der Versuch die Extension auf normalem Wege per Reflection zu finden scheitert:</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
MethodInfo method = typeof(MyClass)
   .GetType()
   .GetMethod(&quot;ExtensionMethod&quot;);
Assert.IsNotNull(method); //Dieser Test wird scheitern
</pre>
<p>Die gesuchte Methode ist eben nicht im gleichen Typ definiert, sondern in einer beliebigen anderen Klasse.</p>
<p>Um alle Extension Methods zu einer bestimmten Klasse zu finden, ist es notwendig alle Typen der Assembly (oder AppDomain) nach Methoden zu durchsieben die zum gesuchten Type (&#8222;TypeToSearchFor&#8220;) erfüllen:</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
var methods = TypeToSearchFor.Assembly
  .GetTypes()
  .Where(t =&gt;
       t.CustomAttributes
       .where(a =&gt; a.AttributeType == typeof(ExtensionAttribute))
       .Count() == 1
       )
  .SelectMany(t =&gt; t.GetMethods())
  .Where(m=&gt;m.IsStatic == true)
  .Where(m =&gt; m.GetParameters().Count() != 0)
  .Where(m =&gt; m.GetParameters()[0].ParameterType == TypeToSearchFor)
  ;
</pre>
<p>Als Anhang befindet sich ein <a href="https://www.jepertinger-itconsulting.de/?download=566" title="Testprojekt" rel="nofollow" class="ddownload-link id-566 ext-zip">Testprojekt</a> mit :</p>
<ul>
<li>BeispielKlasse und Extension dazu</li>
<li>TestProjekt mit Reflection zum Suchen der Methoden</li>
<li>ReflectionHelper Klasse zum Suchen aller Extension Methods</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Codeanalyse &#8211; Einarbeitung in fremden Code</title>
		<link>https://www.jepertinger-itconsulting.de/2014/07/09/codeanalyse-einarbeitung-in-fremden-code/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Wed, 09 Jul 2014 09:18:41 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Programmierung]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=154</guid>

					<description><![CDATA[Es gibt wohl kaum eine schwierigere/nervigere Aufgabe als fremden Code zu warten oder weiterzuentwickeln. Gerade wenn es dann angeht Incidents/Changes einzuarbeiten kann das zum Topfschlagen im Minenfeld werden. Also wie am besten die Minen identifizieren? Wie kann ich mich möglichst &#8230; <a href="https://www.jepertinger-itconsulting.de/2014/07/09/codeanalyse-einarbeitung-in-fremden-code/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Es gibt wohl kaum eine schwierigere/nervigere Aufgabe als fremden Code zu warten oder weiterzuentwickeln.<br />
Gerade wenn es dann angeht Incidents/Changes einzuarbeiten kann das zum Topfschlagen im Minenfeld werden.<br />
Also wie am besten die Minen identifizieren? Wie kann ich mich möglichst schnell in den Code einarbeiten? Wie kann möglichst schnell und umfassend ein Code Review entstehen ?</p>
<p>Ein Ansatz um den Code in Zahlen zu fassen sind Code Metriken&#8230; <span id="more-154"></span>Visual Studio 2010 Team Foundation Edition hat das bereits integriert und liefert auf Knopfdruck eine Auswertung aller bestehenden Klassen und Methoden.</p>
<ul>
<li>Maintainability Index</li>
<li>Cyclomatic Complexity</li>
<li>Depth of Inheritance</li>
<li>ClassCoupling</li>
<li>Lines of Code</li>
</ul>
<p>Aber was hat das nun zur Aussage ?</p>
<p>Von hinten angefangen:</p>
<p><strong>Lines of Code</strong><br />
Das ist wohl das am leichtesten zu verstehende Metrik, und bezeichnet schlicht und ergreifend die Anzahl der Zeilen pro Klasse. Wer hier Klassen findet, die jenseits der 1.000 (oder 10.000 !!??) oder Methoden die jenseits der 100 Zeilen gefunden hat, ist vom Hot Spot des Codes nicht weit entfernt.</p>
<p><strong>Class Coupling</strong><br />
Bezeichnet die Anzahl der Klassen die von dieser Klasse oder Methode referenziert werden. Um so mehr Klassen benutzt werden, um so komplizierter der (Unit-) Test , um so schwerer die Wiederverwendung. Gibt es wenige Objekte die quasi alle anderen Klassen referenzieren ist dies die Implementierung eines <a title="God-Object" href="http://de.wikipedia.org/wiki/Antipattern#Gottobjekt" target="_blank">God-Object-Antipatterns</a>.</p>
<p><strong>Depth of Inheritance</strong><br />
Auch hier gilt, um so mehr Ableitungen, um so schwerer ist es für jemand aussenstehenden sich einzuarbeiten. Mit dieser Metrik konnte ich bisher am wenigstens anfangen, da viele Objekte z.B. für die Peristierung relativ unkritische Basisklassen besitzen.</p>
<p><strong>Cyclomatic Complexity</strong><br />
Salop formuliert, wird bei dieser Metrik die Anzahl der Kontrollstrukturen (if, switch&#8230;) gezählt. Je höher desto schlechter.<br />
Auf die Klasse gesehen ist die Aussagekraft meiner Meinung nach nicht hoch, für die einzelne Methode allerdings um so mehr! Eine Methode mit vielen komplexen, verschachtelten If-Statements macht die Einarbeitung nicht leichter. Gerne wird dieser Code auch mit Antipattern wie Magic Strings kombiniert.<br />
Diese Problematik lässt sich i.d.R. durch bessere Strukturierung des Codes und Objektorientierung vermeiden.</p>
<p><strong>Maintainability Index</strong><br />
&#8230; ist sozusagen das Aggregat aus allen anderen Metriken. Je niedriger desto schlechter.<br />
Visual Studio markiert alles unter 30 als rot. Meiner Erfahrung nach ist die Grenze des Guten schon bei unter 50 erreicht und ein Blick in den Code ist notwendig.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Erste Version von jeperti.IrcLogger released!</title>
		<link>https://www.jepertinger-itconsulting.de/2014/05/06/erste-version-von-jeperti-irclogger-released/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Tue, 06 May 2014 20:25:43 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=316</guid>

					<description><![CDATA[Seit gerade eben finden Sie unter Downloads und Services die erste Version meiner Bibliothek &#8222;jeperti.IrcLogger&#8220; die es einer .Net Anwendung in Kombination mit der Microsoft Enterprise Libarary erlaubt Logging Einträge in einen IRC Channel zu schreiben. Erfahren Sie hier mehr darüber &#8230; <a href="https://www.jepertinger-itconsulting.de/2014/05/06/erste-version-von-jeperti-irclogger-released/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Seit gerade eben finden Sie unter <a title="Downloads und Services" href="http://blog.jepertinger-itconsulting.de/downloads-und-services/">Downloads und Services</a> die erste Version meiner Bibliothek &#8222;jeperti.IrcLogger&#8220; die es einer .Net Anwendung in Kombination mit der Microsoft Enterprise Libarary erlaubt Logging Einträge in einen IRC Channel zu schreiben.</p>
<p>Erfahren Sie <a title="jeperti.IrcLogger" href="http://www.jepertinger-itconsulting.de/jeperti-irclogger/">hier</a> mehr darüber !</p>
<p>Ich freue mich über Ihr Feedback!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sortieren in Linq</title>
		<link>https://www.jepertinger-itconsulting.de/2011/12/20/sortieren-in-linq/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Tue, 20 Dec 2011 20:59:56 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=183</guid>

					<description><![CDATA[Angenommen man möchte eine Liste von Personen sortieren. Die Klasse sieht in etwa wie diese aus: Das Sortieren nach Nachnamen ist noch einfach: Aber was, wenn zwei Personen den gleichen Nachnamen haben? Das ist nicht die Lösung. Die Liste wird &#8230; <a href="https://www.jepertinger-itconsulting.de/2011/12/20/sortieren-in-linq/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Angenommen man möchte eine Liste von Personen sortieren. Die Klasse sieht in etwa wie diese aus:</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
public class Person
{
public int ID { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
}
</pre>
<p>Das Sortieren nach Nachnamen ist noch einfach:</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">

List&lt;Person&gt; personen = new List&lt;Person&gt;();
//.......Laden der Liste

personen.OrderBy(p =&gt; p.Nachname);

</pre>
<p>Aber was, wenn zwei Personen den gleichen Nachnamen haben?</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
personen.OrderBy(p =&gt; p.Nachname).OrderBy(p =&gt; p.Vorname);
</pre>
<p>Das ist nicht die Lösung. Die Liste wird nun nur noch nach Vorname sortiert.</p>
<p>Die Lösung ist die Extension &#8222;ThenBy&#8220;, damit wird nun innerhalb eines Nachnamens nach Vornamen sortiert &#8211; wie gewünscht!</p>
<pre class="brush: csharp; title: ; notranslate">
personen.OrderBy(p =&gt; p.Nachname).ThenBy(p =&gt; p.Vorname);
</pre>
<p>Ich persöhnlich sortiere zum Schluss gerne noch nach etwas syntetischem &#8211; beispielsweise der ID.<br />
Das hat den Vorteil, dass selbst im unmöglichsten Fall (in diesem Beispiel, dass zwei den gleichen Vor- und Nachnamen haben) immer eine definierte Reihenfolge festgelegt ist. Selbst in diesem Fall, erhält der User in der Oberfläche immer eine definierte Reihenfolge. Gerade bei PLinq kann man sich ja auf die Reihenfolge gar nicht mehr verlassen..</p>
<pre class="brush: csharp; title: ; notranslate">
personen.OrderBy(p =&gt; p.Nachname).ThenBy(p =&gt; p.Vorname).ThenBy(p=&gt;p.ID);
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Cache Api Fehlermeldung: Cache ist nicht verfügbar</title>
		<link>https://www.jepertinger-itconsulting.de/2011/11/22/cache-api-fehlermeldung-cache-ist-nicht-verfugbar/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Tue, 22 Nov 2011 18:22:01 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=189</guid>

					<description><![CDATA[Heute habe ich mich mit der CacheApi in ASP.Net beschäftigt. Diese bietet in ASP.Net Seiten ähnlich dem Application oder Session Object die Möglichkeit Werte/Objekte zu speichern, ist hier aber intelligenter und verwirft die Objekte nach einer festgelegten Zeitdauer. Die Intellisense &#8230; <a href="https://www.jepertinger-itconsulting.de/2011/11/22/cache-api-fehlermeldung-cache-ist-nicht-verfugbar/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Heute habe ich mich mit der CacheApi in ASP.Net beschäftigt.</p>
<p>Diese bietet in ASP.Net Seiten ähnlich dem Application oder Session Object die Möglichkeit Werte/Objekte zu speichern, ist hier aber intelligenter und verwirft die Objekte nach einer festgelegten Zeitdauer. Die Intellisense Hilfe zu den Methoden ist selbsterklärend: Ablauf nach einer Zeitspanne, nach einem absolutem Datum &#8230;</p>
<p>Selbsterklärend ? Dachte ich&#8230;  Bei der Verwendung erhielt ich beim ersten Zugriff auf Cache aus einer aspx-CodeBehind-Klasse heraus eine HTTPException mit der Meldung &#8222;Cache is not available&#8220; bzw &#8222;Cache ist nicht verfügbar&#8220;.  Lange habe ich nach der Lösung gesucht; vielleicht muss man den Cache ja irgendwo (web.config, Page Directive etc) aktivieren?! Aber nichts. Auch Google stellt sich dumm.</p>
<p>Letztenendes ist die Lösung einfach statt nur &#8222;Cache.Get(&#8230;&#8220;  &#8222;HttpContext.Current.Cache&#8230;&#8220; zu verwenden. Leider habe ich keine Erklärung parat woran es liegt ?!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Performanceoptimierung oder was .Net wirklich macht</title>
		<link>https://www.jepertinger-itconsulting.de/2011/05/16/performanceoptimierung-oder-was-net-wirklich-macht/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Mon, 16 May 2011 18:46:12 +0000</pubDate>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Programmierung]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=162</guid>

					<description><![CDATA[Es kursiert immer wieder das Gerücht, dass bestimmte Anweisungen im Code &#8222;schneller&#8220; und besser sind als andere. Gerade Entwickler die in älteren Sprachen angefangen haben, trauen den &#8222;neuen&#8220; Sprachen nicht über den Weg. Auf der Suche nach Erklärungen habe ich &#8230; <a href="https://www.jepertinger-itconsulting.de/2011/05/16/performanceoptimierung-oder-was-net-wirklich-macht/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Es kursiert immer wieder das Gerücht, dass bestimmte Anweisungen im Code &#8222;schneller&#8220; und besser sind als andere. Gerade Entwickler die in älteren Sprachen angefangen haben, trauen den &#8222;neuen&#8220; Sprachen nicht über den Weg.</p>
<p>Auf der Suche nach Erklärungen habe ich mich nun selber auch mal mit der Performance von alltäglichen Code beschäftigt. Wie wäre es z.B. mit String Operationen ? Da gibt es doch immer das Gerücht, das die Verbindung von Strings über &#8222;+&#8220; viel zu langsam ist. Damit fange ich doch gleich mal an&#8230;.<span id="more-162"></span>Also schnell mal den Code hier hingepinselt (Code1) und auch gleich die Verbesserung dazu (Code2).</p>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
//Code1
Stopwatch watch = Stopwatch.StartNew();
string res = &quot;abc&quot; + &quot;abc123&quot;;
watch.Stop();
</pre>
<pre class="brush: csharp; highlight: [20]; title: ; notranslate">
//Code2
Stopwatch watch = Stopwatch.StartNew();
string res = String.Concat(&quot;abc&quot; + &quot;abc123&quot;);
watch.Stop();
</pre>
<p>Die Klasse Stopwatch zeigt, wie der Name schon sagt, die vertrichene Zeit an. Mit etwas Code drum rum zum Aufwärmen und Mitteln der Ausführungszeiten komme ich zu dem Schluss, dass beide 0 Millisekunden brauchen. Ein unbefriedigendes Ergebnis. Also die Messung umgestellt auf Ticks. Das Ergebnis ist, dass mit jeder Wiederholung die Ergebnisse etwas variieren, zwischen 1 und 4 Ticks. Das ist kein Unterschied&#8230;  Was ist da also los ? Was macht .Net hier wirklich ?</p>
<p>Um das weiter zu analysieren gibt es Profiler. Es gibt diverse Kaufprodukte (z.B. <a href="http://www.red-gate.com/"> Redgate Performance und Memory Profiler</a> ), aber auch Microsoft bietet gut versteckt einen Memory Profiler an.  Unter <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=be2d842b-fdce-4600-8d32-a3cf74fda5e1">dem Link</a> gibt es den CLRProfiler für  .Net 4 direkt von Microsoft. Man startet über den Profiler sein eigenes Programm und kann auswerten was das eigene Programm so treibt.</p>
<p>32bit Profiler starten, &#8222;Start Application&#8220;, Pfad auswählen und Programm ausführen lassen. Nachdem es ausgeführt wurde, Klick auf View, Call Graph.</p>
<p>Das Erste was man sieht sind Unmengen von Aufrufen, die mit dem eigenen Programm nichts zu tun haben  &#8211; damit verbrät also .Net schon für ein einfaches Consolenprogramm mehrere MB&#8230;</p>
<p style="text-align: left;">Wenn man die Ansicht etwas einschränkt kommt folgendes Ergebnis für meine beiden Möglichkeiten heraus:</p>
<p style="text-align: left;"><a href="http://blog.jepertinger-itconsulting.de/wp-content/uploads/2011/05/stringperf.jpg" rel="lightbox-0"><img loading="lazy" class="aligncenter wp-image-173 size-medium" title="Call Graph String Concat" src="http://www.jepertinger-itconsulting.de/wp-content/uploads/2011/05/stringperf-300x196.jpg" alt="" width="300" height="196" srcset="https://www.jepertinger-itconsulting.de/wp-content/uploads/2011/05/stringperf-300x196.jpg 300w, https://www.jepertinger-itconsulting.de/wp-content/uploads/2011/05/stringperf.jpg 663w" sizes="(max-width: 300px) 100vw, 300px" /></a>Zu sehen ist eine zusammengestellte, gefilterte Ansicht der beiden relevanten Methoden. Der übersichtlichkeit halber Methode2 vor Methode 1.</p>
<p style="text-align: left;">Was ist da zu sehen ? Die Methode StringConcat2 führt  &#8211;  wie auch im Code zu sehen  &#8211; String.Concat aus. Aber was ist da bei StringConcat1 passiert ? Da findet sich auch ein String.Concat Aufruf darin! Den Aufruf der Klasse Datetime habe ich selber noch eingefügt, um überhaupt einen Aufruf bei der zweiten Methode zu sehen. Anscheinend hat .Net meine sinnlose Verbindung von nichtssagenden Strings ebenfalls für sinnlos befunden und gleich mal wegoptimiert. Erst durch das Hinzufügen eines &#8222;+ Datetime.Now.ToString()&#8220; habe ich quasi volle Überzeugungsarbeit geleistet, sodass der Profiler auch etwas anzuzeigen hatte &#8230;</p>
<p style="text-align: left;">Folgerungen:</p>
<ul>
<li>Das .Net-Runtime-Environment überarbeite den Code in nicht unerheblichem Maße</li>
<li>Die Diskussion um die bessere Variante derart einfacher, einzeiliger Stringverkettungen ist denkbar unsinnig.</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Meine erste Coding Dojo- Erfahrung</title>
		<link>https://www.jepertinger-itconsulting.de/2011/02/25/meine-erste-coding-dojo-erfahrung/</link>
		
		<dc:creator><![CDATA[Karl Jepertinger]]></dc:creator>
		<pubDate>Fri, 25 Feb 2011 18:53:49 +0000</pubDate>
				<category><![CDATA[Programmierung]]></category>
		<guid isPermaLink="false">http://blog.jepertinger-itconsulting.de/?p=116</guid>

					<description><![CDATA[Ein Coding Dojo ist eine Veranstaltung bei der sich viele motivierte Entwickler treffen um eine gestellte Aufgabe zu lösen. Die gestellte Aufgabe wird dann meistens in Gruppenarbeit gelöst und die Ergebnisse der Menge präsentiert. Die Aufgabe ist bewusst nicht scharf &#8230; <a href="https://www.jepertinger-itconsulting.de/2011/02/25/meine-erste-coding-dojo-erfahrung/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Ein Coding Dojo ist eine Veranstaltung bei der sich viele motivierte Entwickler treffen um eine gestellte Aufgabe zu lösen. Die gestellte Aufgabe wird dann meistens in Gruppenarbeit gelöst und die Ergebnisse der Menge präsentiert. Die Aufgabe ist bewusst nicht scharf umrissen und auch nicht besonders anspruchsvoll. Ziel ist es dann aber diese Aufgabe so gut wie möglich zu lösen und dabei über die Entwicklung zu reflektieren.</p>
<p>Am Montag war es dann soweit,mein erstes Coding-Dojo.</p>
<p>Ausgerichtet wurde es von der <a href="https://www.xing.com/net/pri811180x/netdojo/">.Net Coding Dojo Gruppe</a>.<br />
Stattgefunden hat es bei <a href="http://www.panoramio.com/photo/17541148">Microsoft in Unterschleißheim</a> bei München.<br />
Die Aufgabe war einen <a href="http://schuchert.wikispaces.com/Katas.NextPreviousPaginatorForWebPages">Paginator</a> zu bauen, also eine Klasse die die Seitenfunktionalität von Listen im Web abbildet.</p>
<p>Aufgeteilt in mehrere kleine Gruppen, war die Aufgabe mit Extreme Programming und <a href="http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung">TDD</a> zu lösen.<br />
Schon nach kurzer Zeit war die Diskussion groß, weil jeder für diese Aufgabe eine andere Lösung dazu im Kopf hatte oder gar die Aufgabe unterschiedlich verstanden hatte</p>
<p>Sehr interessant war dann auch, was dann nach ca. 3 Stunden bei den verschiedenen Gruppen herausgekommen ist, auch wenn längst nicht alle Gruppen die Anforderungen erfüllt haben.<br />
Mein Lernerfolg fürs nächste mal: Ist die Aufgabe auch noch so einfach, Finger weg von der Tastatur und erst mal das Ziel definieren.</p>
<p>Prädikat: Empfehlenswert!</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
