initial commit, fork beautifulhugo

This commit is contained in:
wgroeneveld 2017-02-26 13:28:18 +01:00
parent 0e2e1dfeeb
commit 91eec01ea6
301 changed files with 34577 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.DS_Store
public/

62
config.toml Normal file
View File

@ -0,0 +1,62 @@
languageCode = "en-us"
title = "Brain Baking"
baseurl = "http://www.brainbaking.com/"
enableEmoji = true
theme = "beautifulbaking"
pygmentsUseClasses = true
pygmentCodeFences = true
#disqusShortname = "XXX"
#googleAnalytics = "XXX"
[taxonomies]
tag = "tags"
[Params]
subtitle = "Freshly baked thoughts"
logo = "img/avatar-icon.png"
favicon = "img/favicon.ico"
commit = false
[Author]
name = "Wouter Groeneveld"
email = "wouter.groeneveld@gmail.com"
#facebook = "username"
github = "wgroeneveld"
#twitter = "woutergroenev"
#linkedin = "username"
#stackoverflow = "users/XXXXXXX/username"
#soundcloud = "username"
#instagram = "username"
#youtube = "user/username" # or channel/channelname
#spotify = "username"
#itchio = "username"
[[menu.main]]
name = "Blog"
url = "/"
weight = 1
[[menu.main]]
name = "Wiki"
url = "/wiki/"
weight = 2
[[menu.main]]
name = "About me"
url = "/about"
weight = 3
#[[menu.main]]
# identifier = "samples"
# name = "Samples"
# weight = 3
#[[menu.main]]
# parent = "samples"
# name = "Code Sample"
# url = "/post/2016-03-08-code-sample"
#[[menu.main]]
# parent = "samples"
# name = "Test Markdown"
# url = "/post/2015-02-20-test-markdown"

13
content/about.md Normal file
View File

@ -0,0 +1,13 @@
---
bigimg: /img/About Me.jpg
---
# About Me
Hi! Im Wouter Groeneveld, a software developer with a deep passion to inspire others on everything that drives me. That includes lots of goodness, but here are the key facts:
* Test your stuff before writing your code! Im a heavy Test Driven Development (TDD) fanboy and I bark at those who dont! I teach agile software engineering on multiple occasions, ranging from colleagues to schools.
* I love dynamic languages. I also love converting the haters to the dark side. I teach javascript as a dynamic and functional language - it helps to create your own funky labs to people get more engaged.
* Pair programming used as a tool to learn from each other and to improve code quality are two values I believe in.
* Dont limit yourself to your specialty. I like constantly improving my own (and others) skills by trying out something new, reading, and writing.

13
content/page/about.md Normal file
View File

@ -0,0 +1,13 @@
---
bigimg: /img/About Me.jpg
---
# About Me
Hi! Im Wouter Groeneveld, a software developer with a deep passion to inspire others on everything that drives me. That includes lots of goodness, but here are the key facts:
* Test your stuff before writing your code! Im a heavy Test Driven Development (TDD) fanboy and I bark at those who dont! I teach agile software engineering on multiple occasions, ranging from colleagues to schools.
* I love dynamic languages. I also love converting the haters to the dark side. I teach javascript as a dynamic and functional language - it helps to create your own funky labs to people get more engaged.
* Pair programming used as a tool to learn from each other and to improve code quality are two values I believe in.
* Dont limit yourself to your specialty. I like constantly improving my own (and others) skills by trying out something new, reading, and writing.

View File

@ -0,0 +1,176 @@
---
title: Enhancing the builder pattern with closures
date: '2013-11-14'
bigimg: /img/Enhancing the builder pattern with closures.jpg
subtitle: the trainwreck/builder/chaining pattern can be dangerous and here's why
tags:
- closures
- groovy
- 'C#'
- javascript
- java
- functional programming
published: true
---
This post is inspired by Venkat Subramaniam's [Devoxx 2013 talk Thinking Functional Style](http://www.devoxx.be/dv13-venkat-subramaniam.html). See downloads at [agiledeveloper.com](http://www.agiledeveloper.com/downloads.html) which has a rather cool Groovy example.
### Classic builders
For years, I've been using the builder pattern to quickly create new objects to be inserted into the database or to inject our domain objects with the required data. We started with so called "Object Mothers", static methods which simply create and fill up an object, passing in a huge amount of parameters. That quickly became very cumbersome to work with. Most of the time, the code will look like this, whether it's C# or Java doesn't really matter:
public class UserBuilder
{
private UserType_V1_0 type = UserType_V1_0.Administrator;
private string code = "code";
public User_V1_0 Build()
{
User_V1_0 user = new User_V1_0(code, "name", type, "id", "campusId", true);
return user;
}
public UserBuilder WithCode(string code)
{
this.code = code;
return this;
}
public UserBuilder WithType(UserType_V1_0 type)
{
this.type = type;
return this;
}
}
Used this way:
var user = new UserBuilder()
.withCode("AB")
.Build();
Okay, what's happening here?
- Builder objects have `withX()` methods, returning `this` to be able to chain, to fill up every required variable
- default values are provided, so we're not obliged to call every method if we're only interested in one field.
- At the end of the chain, we call `Build()`, which returns our object.
### Enhanced builders
I've never given it much thought, but yes, there are some problems with this implementation (as with everything). The most important one being, can you reuse your instantiated builder? No? Yes? We never assign it, but we **could** if we really wanted to. Since we're **mutating the builder**, you are definatly getting into trouble.
Using a lambda to pass in the work on our builder might solve this:
public class UserBuilder
{
private UserType_V1_0 type = UserType_V1_0.Administrator;
private string code = "code";
private UserBuilder()
{
}
private User_V1_0 Build()
{
return new User_V1_0(code, "name", type, "id", "campusId", true);
}
public static User_V1_0 Build(Func<UserBuilder, UserBuilder> block)
{
var builder = new UserBuilder();
block(builder);
return builder.Build();
}
public UserBuilder WithCode(string code)
{
this.code = code;
return this;
}
public UserBuilder WithType(UserType_V1_0 type)
{
this.type = type;
return this;
}
}
Used this way:
var user = UserBuilder.Build(_ =>
_.WithCode("AB")
.withType(UserType_V1_0.NursingStaff));
Notice that using the character `_` is a convention if there's only one parameter for the lambda, it could also be called "builder" but we still need to use this, as `block(builder)` passes in the temp created builder. What did we solve?
- The actual builder instance is bound within the `Build()` scope. You'll never be able to assign it when using the static method.
- One might say, we reduced some redundancy in the implementation by eliminating the need to call the final `Build()` method, but it's simply being moved.
### Supercharged builders
In Groovy (the devoxx example), we can cleverly use the `.delegate` mechanism to eliminate the need to chain at all. Groovy also reduces the syntax noise a bit (brackets, semicolons). We could create a `Build` method like this:
public static User_V1_0 Build(block) {
new UserBuilder().with block;
// does the same as cloning the block, assigning it with .delegate and executing it.
}
Used this way:
UserBuilder.Build {
Code "AB" // Same as Code("AB");
Type UserType_V1_0.NursingStaff
}
How does this work?
- The `Code()` method does not exist in our block closure, but we assign a delegate to it: our temp lexically scoped `UserBuilder` instance - that's where the method lives. When the code is executed, Groovy first looks for a method within the block, and then tries to fetch it via the delegate.
For more information on groovy delegates, see the [Groovy documentation: Delegation Pattern](http://groovy.codehaus.org/Delegation+Pattern). This works thanks to the late binding of the language and won't statically typed languages such as C#. You might be able to come close using `LINQ` expression trees, but that requires a lot of effort to write a simple DSL.
### Leveraging this principle to DSLs
In Javascript, you can also manage to do something like that using `.prototype` and [prototypal inheritance](http://brainbaking.com/wiki/code/javascript/inheritance) and `apply()` to dynamically bind the `this` context (see [Function.prototype.apply MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)).
Of course, builders are completely redundant in JS. Just create a `JSON` object using `{ key: value }`. Done. But this principle might be interesting for things like creating a "mailer" - as in the devoxx 2013 example:
var mailerPrototype = {
from: function() { console.log("from"); },
to: function() { console.log("to"); },
sub: function() { console.log("sub"); },
body: function() { console.log("body"); },
send: function() { console.log("sending..."); }
};
var mailer = function() {};
mailer.mail = function(block) {
// .prototype magic happens inside Object.create()
block.apply(Object.create(mailerPrototype));
}
// this still sucks, I don't want to use 'this.', can use chaining...
mailer.mail(function() {
this.from("me@gmail.com");
this.to("you@gmail.com");
this.sub("this is my subject");
this.body("hello");
this.send();
});
You'll still need `this.`, sadly. This is not needed in Groovy:
mailer.mail {
from "me@gmail.com"
to "you@gmail.com"
sub "this is my subject"
body "hello"
send()
}
Now **that** looks readable. To be able to create something like that, a language has to:
- have functions as first-class citizens.
- have a clean syntax, to be able to reduce a lot of noise (CoffeeScript can get this done for JS for instance)
- have late binding or duck typing
That said, going back to Java 7 is going to be a major pain in the ass. No, I do not want to create usesless interfaces! (Tip: use `Function` and `Predicate` from [Google Guava](https://code.google.com/p/guava-libraries/)).

View File

@ -0,0 +1,34 @@
---
title: Ending your day with happy thoughts
date: '2013-08-13'
bigimg: /img/Ending your day with happy thoughts.jpg
subtitle: Or how a tiny thing can really help you sleep better
tags: ['self improvement']
---
<div class="summary">
Past new year, I stopped promising silly things to myself. “This year, Ill for sure go jogging several times a week!”or “This year, Ill really get into learning another language!”. We all know how these things go. Not that I made something up on the very day, these ideas are usually carefully crafted in my sketchbook and are lingering there to be exposed and finally executed.
</div>
Originally posted on [Medium](https://medium.com/writers-on-writing/6a9dbf4d8212).
Past new year, I stopped promising silly things to myself. “This year, Ill for sure go jogging several times a week!”or “This year, Ill really get into learning another language!”. We all know how these things go. Not that I made something up on the very day, these ideas are usually carefully crafted in my sketchbook and are lingering there to be exposed and finally executed.
But there was someting I came across to on the internet I really, really liked. Something small and seemingly insignificant. These 365 things are not exactly new, I know. And “keeping notes to sort out your thoughts” is something I already do for years using my sketchbook which I carry with me everywhere.
I found another tiny sketchbook I did not use, grabbed a pencil and put these two objects beside my bed. I labelled the book “365", sewed a little hedgehog friend to give the booklet a fluffy look and started writing before actually going to sleep. You should write one sentence, every day. In this sentence, you should be thankful of someone or somethingthat happened to you today.
Sounds easy? Right. Put it to practice. It sometimes is extremely easy. It sometimes is extremely hard. Really, really hard.
Frustrated? Write.
You should. And by “write”, I dont mean whole pages. Just one sentence: what happened to you today, what did you like? Focus on the good stuff.
I have to admit, sometimes more than other times, I have trouble finding good the good stuff. Some days, my work can be really frustrating, the lawn mower got jammed halfway through the lawn, the bycicle chain broke, … I think you recognize these days.
When I go to sleep, I mull over things that happened that dayits not some deliberate action, and sometimes I cant seem to get rid of certain thoughts. Like how to convince your colleage to use method x and not method y to do work z.
No worriesgrab that pencil and write in your 365 booklet. Start with 2 simple words: “thank you”. These can end in “thank you dear x for retweeting about a meetup I will attend” or “thank you mother for dropping by and cooking hot soup”. (Yes they sound very cliché, make up your own!)
In my experience, mindfully going through your day and thinking about what you liked most gives me happy thoughts and a sort of satisfaction feeling. It helps me sleep. Its interesting to reread previous months.
So, thank you internet for all those amazing blogs and great ideas, even if its as simple as writing down what you liked that day.
Oh, and heres a pro-tip: use a pencil.That way, you can write while lying down in your bed.

View File

@ -0,0 +1,92 @@
---
title: Custom Webdriver Page Factories
bigimg: /img/Custom Webdriver Page Factories.jpg
date: '2014-09-22'
subtitle: Wrapping WebElements to reduce boilerplate clutter
tags: ['unit testing', 'java', 'C#', 'webdriver', 'scenario testing' ]
---
The problem: Webdriver elements returned by `driver.FindElement()` are too generic. There're the `Text`, `SendKeys()` and `Click()` methods/properties (depending your on C#/Java implementation). The solution is to simply wrap all elements inside custom HTML objects which contain specific methods like `ShouldContainValue` or `Type` (okay, that's a one-to-one mapping with `SendKeys()`, but it's a lot less technical!). Instead of
[FindsBy(How = How.CssSelector, Using = ".ux-desktop-taskbar-startbutton")]
private IWebElement startButton;
[FindsBy(How = How.CssSelector, Using = ".other")]
private IWebElement whatever;
You'd find code like
[FindsBy(How = How.CssSelector, Using = ".ux-desktop-taskbar-startbutton")]
private HTMLSubmitButton startButton;
[FindsBy(How = How.CssSelector, Using = ".other")]
private HTMLInputBox whatever;
In java, this is not that difficult. Normally all fields annotated with FindsBy are filled in via reflection with `PageFactory.InitElements()`. (warning: this creates proxies and does not yet actually do the lookup in the DOM tree. This is a good thing, as filling the fields usually happens inside the constructor of a page object.). `initElements` returns the filled page, you can do a few things from there:
- postprocess the page and decorate your fields
- create your own page factory and create your own fields, wrapped around the webdriver proxies
In C#, you're in trouble - the class is sealed, and the proxy classes are internal. Creating your own factory is possible, but produces fuzzy code:
internal class PageFactory
{
private PageFactory()
{
}
private static By FindsByAttributeToBy(FindsByAttribute attribute)
{
return (By) typeof (FindsByAttribute).GetProperty("Finder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(attribute);
}
public static void InitElements(IWebDriver driver, object page)
{
foreach (FieldInfo field in FindAllFieldsAndProperties(page.GetType()))
{
Attribute[] findsByAttribs = Attribute.GetCustomAttributes(field, typeof (FindsByAttribute), true);
if (findsByAttribs.Length > 0)
{
var findsByAttribute = (findsByAttribs[0] as FindsByAttribute);
if (field.FieldType == typeof (IWebElement))
{
field.SetValue(page, FindElement(driver, FindsByAttributeToBy(findsByAttribute)));
}
else if (typeof (IEnumerable).IsAssignableFrom(field.FieldType))
{
field.SetValue(page, FindElements(driver, FindsByAttributeToBy(findsByAttribute)));
}
}
}
}
private static IWebElement FindElement(IWebDriver driver, By by)
{
// warning: create WebProxyElement instead of directly doing a lookup
return driver.FindElement(by);
}
private static IReadOnlyCollection<IWebElement> FindElements(IWebDriver driver, By by)
{
// warning: create WebListProxyElement instead of directly doing a lookup
return driver.FindElements(by);
}
private static IEnumerable<FieldInfo> FindAllFieldsAndProperties(Type type)
{
var list = new List<FieldInfo>();
list.AddRange(type.GetFields(BindingFlags.Instance | BindingFlags.Public));
for (; type != (Type) null; type = type.BaseType)
{
list.AddRange(type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
}
return list;
}
}
If you have a keen eye, you notice a few things:
- caching of the attribute wouldn't work anymore. The default C# WebDriver implementation is fuzzy and I didn't want to copypaste code I won't use.
- proxying won't work anymore, you'd have to use reflection to instantiate internal classes.
- reflection has been used to fetch the `By` instance of the `FindsByAttribute`. Yay.
The above solution is too complex to solve a simple thing. Instead of a custom page factory, in C# we now use extension methods on `IWebElement`. Another possibility would to create wrapper objects on-the-fly but you'd still have to map the "raw" web elements on page objects.

View File

@ -0,0 +1,49 @@
---
title: Faking domain logic
bigimg: /img/Faking domain logic.jpg
date: '2014-09-23'
subtitle: Using C# extensions to create the illusion of domain logic
tags: ['domain driven design', 'C#', 'code smells' ]
---
Sometimes, life is just a little bit more difficult than you imagined the day before. Sometimes, you have to work on a legacy codebase with custom frameworks rooted so deeply you're having lot's of trouble trying to build around them. To make it a bit more concrete, here's an example: imagine a separate DLL for interfaces and a separate DLL for the implementation. This decision was made because we use NHibernate as a data mapper and not to write beautiful domain driven design code. As a result, writing domain logic methods on our "domain" objects is impossible because we have three implementations.
There are a few solutions. The first would be the classic solution, called a "service layer" where you simply dump random "domain" logic. Done.
Then there's a slightly better solution involving abstract classes. But it makes things more complicated, and it's not always allowed to inherit from those classes. Besides, in which DLL should you put them? Dependency Entanglement. Welcome to hotel Cali--- erm, DLL Hell.
So, option number three: use extensions on those interfaces.
public interface IVacancy
{
public string Description { get; set; }
}
would have these implementations:
public class FulltimeVacancy : IVacancy
{
public string Description { get { // ... }; set { field = value; }}
}
public class HalftimeVacancy : IVacancy
{
public string Description { get { // ... }; set { field = value; }}
}
If I'd want to implement something like `RetrieveLocation()` based on for example google maps and other properties, I can place the entry point in an extension class:
public static class IVacancyExtensions
{
public static string RetrieveLocation(this IVacancy vacancy)
{
// do your thing
}
}
Using the right namespace imports, I'm able to call the above method on any concrete implementation of `IVacancy`, regardless of it's (DLL) location. Now, why would I want to keep code like this as close to the original object as possible? this has multiple reasons:
- It makes code easier to read & refactor.
- It reduces the chance of duplication in another service layer, as people often hit "CTRL+SPACE" to find a method from an object or a piece of logic, and don't go looking in service classes.
- It makes code easier to discuss (since it's also easier to read).
- It's isolated and thus easier to test.
- It avoids a lot of [other code smells](http://martinfowler.com/bliki/CodeSmell.html) (deserves it's own article).

View File

@ -0,0 +1,124 @@
---
title: Integration Testing with SQLite
bigimg: /img/Integration Testing with SQLite.jpg
date: '2013-11-04'
subtitle: Decoupling your integrated database environment from your development.
tags: ['unit testing', 'sql', 'C#', 'sqlite' ]
---
This article is based on the notes I've collected on [My Wiki](http://brainbaking.com/wiki/code/db/sqlite).
On previous projects I've worked on, development PCs came with a local version of the database scheme. Each DB change also got rolled out to those computers, which enabled us developers to fool around without breaking anything on the development (or test) environment. This is another step closer to happiness, at least for our proxy customers who didn't have to reinsert their test data every time we flushed something from a table. Sometimes though, there's some lame excuse for not having a local database installed:
- We have a lot of stored procedures and it's too hard to duplicate them locally
- We worked like this for years, why would I want a local DB?
- But then my data is out of sync!
- I tried doing that but my manager says I should focus on delivering content
- Blah blah blah
Installing an Oracle XE runtime on your machine might include working around some issues which can take up some time but it's time well invested, compared to multiple developers connecting to one shared database. In any case, there's another possibility: an **in-memory database**, such as [SQLite](http://www.sqlite.org/). This does still require you to keep the upgrade scripts synced, but also enables you to get rid of a lot of annoying things like *foreign key constraints* for testing purposes.
### Integrating SQLite with .NET
Simply use [System.data.SQLite](http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki). For each OleDb object, there's an equivalent SQLite one in the correct namespace. The only problem is, some of them don't share an abstract object so you'll have to come up with an anti-corruption layer yourself. Create a connection using this connection string:
private SQLiteConnection SqLiteDbConnection()
{
return new SQLiteConnection()
{
ConnectionString = "Data Source=:memory:;Version=3;New=True;DateTimeFormat=Ticks",
Flags = SQLiteConnectionFlags.LogAll
};
}
public void SetupDb()
{
using (var connection = SqLiteDbConnection())
{
connection.Open();
var transaction = connection.BeginTransaction();
var sqLiteCommand = new SQLiteCommand()
{
Connection = (SQLiteConnection) connection,
CommandType = CommandType.Text,
CommandText = GetSchemaCreateSql()
};
sqLiteCommand.ExecuteNonQuery();
transaction.Commit();
}
}
You need to pay attention to the `DateTimeFormat` substring in the connection string as SQLite is "dynamically typed", compared to Oracle. This means it stores dates exactly the same as chars, otherwise you might encounter an error like `"string was not recognized as a valid DateTime"` when executing a select statement.
**Watch out with closing the DB Connection** using an in-memory DB; as this completely resets everything. As soon as you open a connection, you can execute create table commands (read your stored DDL file and do it in bulk).
Your anti-corruption layer between the abstract DB Connection and SQLite/OleDB should expose a few methods. It should be able to query (with or without parameters or providing a `DbCommand`) and possibly stored procedures. This is what I've come up with:
public interface IdbConnection
{
object QueryProcedure(string procedure, IDictionary<string, object> parameters, string outputParameter);
DbParameter CreateParameter(string field, object value);
DbCommand CreateCommand(string query);
DataSet Query(DbCommand command);
DataSet Query(string query);
}
Depending on the implementation, it'll return an `SQLiteCommand` or an `OleDbCommand` instance.
### Creating integration tests, using Record objects
To be able to quickly insert junk in an in-memory table, I came up with a simple object-table mapping which uses reflection to scan for each property of an object, and map that property to a column in a table. Normally you would simply use your domain objects and issue a `save()` or `persist()` call using for instance `NHibernate` but we didn't have anything like that and this was easy to setup.
Create an object for each table in your unit test project, extending `DatabaseInsertable`:
public abstract class DatabaseInsertable
{
protected abstract string GetTable();
public override string ToString()
{
var fieldDict = FieldDictionary();
var fields = "(" + string.Join(",", fieldDict.Keys) + ")";
var values = "(" + string.Join(",", fieldDict.Values) + ")";
return "insert into " + GetTable() + fields + " values " + values;
}
public void Save()
{
DbConnection.Instance.CreateCommand(ToString()).ExecuteNonQuery();
}
private Dictionary<string, string> FieldDictionary()
{
var dictionary = new Dictionary<string, string>();
foreach (var info in this.GetType().GetFields())
{
if (info.GetValue(this) != null)
{
dictionary.Add(info.Name, "'" + info.GetValue(this).ToString() + "'");
}
}
return dictionary;
}
}
For instance:
internal class UnitRecord : DatabaseInsertable
{
public string creator;
public string guid;
protected override string GetTable()
{
return "UNIT";
}
}
Now you can simply issue `new UnitRecord() { creator = "bla"; guid = "lala"; }.Save();` and it's saved into the unit table, yay!

View File

@ -0,0 +1,18 @@
---
title: .NET Memory management VS JVM Memory management
date: '2014-10-24'
subtitle: Increasing your maximum heap size in .NET? Tough luck.
tags: ['memory management', 'CLR', '.NET', 'JVM' ]
---
Memory management is something to keep in mind when deploying and running applications on top of the JVM. Parameters like `Xmx` and `Xms` are things to juggle with when it comes to finding the perfect balance between too much memory hogging (at app startup) and too little, especially if you're working with heavy duty entity mapping frameworks like Hibernate (and you're not so good at writing fast HQL).
When we bumped into an `OutOfMemoryException` in .NET, I got an Xmx flashback and started searching on how to do the same with the CLR.
Turns out you can't.
You can't set max heap size in .Net unless you host the CLR yourself in a process. ([source](http://stackoverflow.com/questions/301393/can-i-and-do-i-ever-want-to-set-the-maximum-heap-size-in-net))
To control the memory allocations of CLR including the max heap size, you need to use the hosting api to host the clr and specifically use the "Memory manager interfaces", some starter info can be found here [MSDN Magazine, column CLR Inside Out : CLR Hosting APIs](http://msdn.microsoft.com/en-us/magazine/cc163567.aspx)
The heap does indeed keep growing until it can't grow any more. (Obviously this is "after attempting to recover memory through GC, grow the heap".) Basically there isn't nearly as much tuning available in the .NET GC as in Java. You can choose the server GC or the client one, and I think there's an option for turning on/off the concurrent GC (I'll find links in a minute) but that's basically it.
See also:
- [Choosing the right garbage collector for your .NET Application](http://www.atalasoft.com/cs/blogs/rickm/archive/2008/05/14/choosing-the-right-garbage-collector-settings-for-your-application-net-memory-management-part-4.aspx)

View File

@ -0,0 +1,55 @@
---
title: Metaprogramming instead of duplication
bigimg: /img/Metaprogramming instead of duplication.jpg
date: '2014-03-14'
subtitle: convention over duplication, good or bad?
tags: ['C#', 'java', 'metaprogramming', 'reflection', 'unit testing', 'mocking' ]
---
So... What's up with all that duplication in your unit tests? Let's take a look at a very recognizable pattern when for instance using `RhinoMock` in `C#`:
[TestInitialize]
public void SetUp()
{
dbConfigurationMock = MockRepository.GenerateMock<IDbConfiguration>();
mountPointLoaderMock = MockRepository.GenerateMock<IMountPointLoader>();
userEnvironmentFactoryMock = MockRepository.GenerateMock<IUserEnvironmentFactory>();
userEnvironmentLoaderMock = MockRepository.GenerateMock<IUserEnvironmentLoader>();
// ...
We agreed to suffix each instance variable with 'Mock' if it's a mock. That way, when you scroll down to an actual test case, it's clear to everyone what's what: mocks, stubs, actual implementations, and so forth. So why should I repeat myself again and again but initializing a bunch of mocks using `GenerateMock`?
In Java using Mockito, the `@Mock` annotation automagically instantiates a mock for you, provided you annotated your test class with `@RunWith(MockitoJUnitRunner.class)`. I would like to apply this pattern to MSTest but there's not a single hook to be found where I can plug in my initialization code. Thanks a bunch.
Example taken from [Mockito docs](http://docs.mockito.googlecode.com/)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;
private ArticleManager manager;
Now, this "problem" is easily solved with a bit of metaprogramming and an abstract class:
- Loop over (private) fields
- Filter out suffixed with 'Mock'
- Initialize.
public abstract class AbstractTestCase
{
[TestInitialize]
public void CreateMocksBasedOnNamingConvention()
{
this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.Name.EndsWith("Mock")).All(InitMock);
}
private bool InitMock(FieldInfo field)
{
field.SetValue(this, MockRepository.GenerateMock(field.FieldType, new Type[]{}));
return true;
}
}
Very easy with `LINQ`. The question is - is metaprogramming or reflection in this case "allowed"? Do you think this is "bad" (because it's implicit), or is the convention of suffixing your fields with 'Mock' good enough? The base test case could also be named something like `MockInitializingTestCase` if that makes you feel better.

View File

@ -0,0 +1,111 @@
---
title: Migrating from Extjs to React gradually
bigimg: /img/Migrating from Extjs to React gradually.jpg
date: '2016-01-26'
subtitle: Migrating from Extjs to React gradually
tags: ['javascript', 'extjs', 'react' ]
---
We were looking for a few alternatives to our big ExtJS 4 application. Since it's not that easy to completely migrate from one front-end framework to the next, a possible solution would be to start developing new parts in another framework. There's a lot of domain logic spread in Ext views and controllers - which shouldn't be there, we are well aware of that. Let's call it "legacy" :-)
The application right now uses Extjs as UI and C# as backend, and lets ext do the loading of the views/controllers (living in app.js like most ext applications). There's no ecosystem set up like modern javascript applications - build systems like Grunt, Gulp, node package managers, Browserify, ... are all not used. We do use sencha command to minify stuff. To be able to develop new modules without having to worry about extjs, one of the possibilities would be to use iframes. That enables us to (scenario) test the module using it's own routing. It's wrapped inside an Extjs view with an iframe:
Ext.define('App.view.utilities.desktop.ReactWindow', {
extend: 'Ext.form.Panel',
alias: 'widget.App_view_utilities_desktop_ReactWindow',
bodyPadding: 5,
width: 600,
layout: {
type: 'vbox',
align: 'stretch'
},
initComponent: function() {
var me = this;
var dynamicPanel = new Ext.Component({
autoEl: {
tag: 'iframe',
style: 'border: none',
src: me.url
},
flex: 1
});
Ext.apply(me, {
title: 'React',
defaults: {
labelWidth: 120
},
items: [dynamicPanel]
});
me.callParent();
}
});
When the module is triggered in the main app, we simply add the panel to the desktop:
this.addPanel(Ext.create('App.view.utilities.desktop.ReactWindow', {
url: 'react/mod/someurl/'
}));
Our app structure in the GUI folder would be something like this:
[GUI]<br/>
* global.asax<br/>
* default.aspx<br/>
**** [app] -> extjs<br/>
**** [react] -> reactjs<br/>
That's simple enough. But how would one be able to open new Ext panels from within the React sub-application? That would be done via custom events thrown to the parent window. Catching these is just a matter of adding this to some controller in Extjs:
window.addEventListener('react', function(e) {
me.onReactEvent(e.detail, e);
});
The `detail` property is part of a custom event, thrown in a react component. This below might be some cell component, taken from the [fixed-data-table](https://facebook.github.io/fixed-data-table/) example:
class MyLinkCell extends React.Component {
clicked(e) {
const el = e.target;
const eventObj = {
'detail': {
'type': 'downloadlink',
'url': 'react/some/detail/url'
}
};
console.log('clicked - "react" event thrown:');
console.dir(eventObj);
if(window.parent) {
window.parent.dispatchEvent(new CustomEvent('react', eventObj));
}
}
render() {
const {rowIndex, field, data} = this.props;
const link = data[rowIndex][field];
return (
<Cell>
<a onClick={this.clicked} href='#'>{link}</a>
</Cell>
);
}
}
Of course this is more or less the same when for instance using Angular2 instead of React, the custom event is part of the JS standard, see [Creating and triggering events](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events) from MDN.
To be able to use source maps in conjunction with Browserify/Watchify, I had to tweak some parameters in package.json:
`watchify index.js --verbose -d -t babelify --sourceMapRelative . --outfile=bundle.js`
Things we still need to research:
- How well does React compare to Angular2 in terms of components? For instance react doesn't include [routing](http://www.kriasoft.com/react-routing/) by default. We'll need to rewrite some already-extjs-custom components in the target framework.
- How should we include the build ecosystem (npm, gulp/grunt/browserify, ...) into our C# build solution and Teamcity build? Will [http://reactjs.net/](http://reactjs.net/) help for instance?
- Can we use [http://reactjs.net/](http://reactjs.net/) to render serverside components?
- Which build tool should we use? We're being overwhelmed by choice: bower/npm as package manager, I've seen stuff like [Webpack in conjunction with React](http://www.christianalfoni.com/articles/2015_10_01_Taking-the-next-step-with-react-and-webpack), ... The list is huge if you've not kept up with the JS technology news.
One of the things we liked a lot was typescript or ES6 and the ability to use `=> ()` and promises. Enabling this requires a transpiler or a polyfill like [Babel JS](https://babeljs.io/), but maybe this as a build step in sencha command will also ease some pain we're having with the current Ext code.

View File

@ -0,0 +1,150 @@
---
title: Bye autotools hello Scons
bigimg: /img/Bye autotools hello Scons.jpg
date: '2014-03-26'
subtitle: Building C++ projects with Scons
tags: ['C++', 'python', 'build ecosystem' ]
---
Remember this?
- `./configure`
- `make`
- `make install`
That's not so bad, as long as you have the right compiler and linker flags configured, depending on the target OS. The real problem, however, is trying to figure out how to alter something if you didn't write the `Makefile` yourself. Or if you in fact did write it, but it was some time ago. Two days. No, four hours.
### The problem
Try to study the autoconf and automake flow diagram, explained [on Wikipedia: the GNU build system](http://en.wikipedia.org/wiki/GNU_build_system). Headache coming up? Suppose we would like to use these ... uhm, "thingies", for a simple C++ project.
First, let me define simple:
- It has some (shared) library dependencies
- The source lives in `src`
- Since it's obviously written the TDD way, the tests live in `test`
Onward, to the `Makefile` creation station!
This is a sample file, from the [Google Test Makefile](https://code.google.com/p/googletest/source/browse/trunk/make/Makefile):
GTEST_DIR = ..
USER_DIR = ../samples
CPPFLAGS += -isystem $(GTEST_DIR)/include
CXXFLAGS += -g -Wall -Wextra -pthread
TESTS = sample1_unittest
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
all : $(TESTS)
clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^
sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
$(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
This first builds the gtest_main.a binary, to be able to link that with our test after the source (sample1.o) has been is built. The syntax is clumsy, simple files require me to have a deep knowledge how flags and linking work, and I don't want to specify everything in one block.
As esr in his blog post [Scons is full of win today](http://esr.ibiblio.org/?p=3089) said, it's a maintenance nightmare. What to do?
There are a few alternatives which aim to cover everything autotools does, such as `QMake` from Trolltech or `CMake` (that actually generates Makefiles. You're not helping, CMake!). Or, one could go for [Scons](http://scons.org/).
### build your software, better.
Scons starts with a single `SConstruct` file, which acts as the makefile. You can bootstrap the default build target using the `scons` command. (cleaning with `scons --clean`). The big deal here is that the contents of that file is simply python (2.7, I know)!
Want to write a utility function to gather all your `cpp` files? Fine, go ahead, `def mystuff():` (you do know this already exists, right? Use `Glob()`) Want to unit test these, and include them? Done. Want to split up everything per source directory? Use `SConscript` files and include these from within your root `SConstruct` using `SConscript('file', 'envVarToExport')`.
This is my blueprint construct file:
env = Environment(CXX = 'g++')
gtest = env.SConscript('lib/gtest/SConscript', 'env')
src = env.SConscript('src/SConscript', 'env')
out = env.SConscript('test/SConscript', 'env gtest src')
# output is an array with path to built binaries. We only built one file - run it (includes gtest_main).
test = Command( target = "testoutput",
source = str(out[0]),
action = str(out[0]) )
AlwaysBuild(test)
Things to note:
- Scons works with [Environments](http://www.scons.org/doc/2.3.1/HTML/scons-user.html#chap-environments) which can be shared and cloned (see below)
- You can share variables with the second parameter
- Executing after a build also works, passing in the result of conscripts.
- Ensure to always build your test with `AlwaysBuild()`
This is the conscript which builds google test:
Import('env')
env = env.Clone(CPPPATH = './:./include')
env.Append(CXXFLAGS = ['-g', '-Wall', '-Wextra', '-pthread'])
gtest = env.Library(target = 'gtest', source = ['src/gtest-all.cc', 'src/gtest_main.cc'])
Return('gtest')
Things to note:
- Fetch the shared variables with `Import()` and return stuff with `Return()` (it's a function)
- specify flags all you want.
- Building something? `Program()`, `Library()` or `SharedLibrary()`.
Source:
Import('env')
env = env.Clone(CPPPATH = './')
src = env.Library(target = 'wizards', source = Glob('*.cc'))
Return('src')
Things to note:
- `Glob()` auto-reads all files in the current dir.
And finally, test, linking both source and google test:
Import('env', 'gtest', 'src')
env = env.Clone()
env.Append(LIBPATH = ['#lib/gtest', '#src'])
env.Append(LIBS = [gtest, src])
out = env.Program(target = 'wizards_unittests', source = Glob('*.cc'))
Return('out')
Things to note:
- Use the hashtag `#` to point to the root dir where the `SConstruct` file resides.
- Linking is as simple as providing `LIBS` and the right path.
So where does that leave us? Yes there's still "syntax" to be learned, even if you're a seasoned python developer; you need to know which function to use for what, that's what the excellent [scons doc](http://www.scons.org/doc/2.3.1/HTML/scons-user.html) is for. I know it made my life a lot easier while trying to do something simple and this is only the tip of the iceberg. Scons is relatively popular according to Stack Overflow, the documentation is excellent and if all else fails you can write your own garbage in a full-fledged dynamic language.
The only really irritating bit is the python 2.7 dependency, so don't forget to use [virtualenv](https://pypi.python.org/pypi/virtualenv).

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,103 @@
---
title: Unit Testing Extjs UI with Siesta
bigimg: /img/Unit Testing Extjs UI with Siesta.jpg
date: '2014-12-23'
subtitle: An attempt to replace instable Webdriver tests with Siesta UI tests
tags: ['unit testing', 'javascript', 'extjs', 'siesta']
---
### WebDriver & js-heavy frameworks ###
Writing scenario tests for javascript-heavy UI webpages can be really difficult. It gets complicated pretty quickly if you're using a lot of async calls or a lot of javascript-heavy UI components. On our current project, we use Extjs as the UI layer in a single-page aspx page to bootstrap our Extjs app. Extjs is a (heavyweight) javascript framework for creating windows, panels, grids, buttons, menus, ... like you're used to when using client/server desktop applications. You define components on a view, behavior on a controller, and data and the way it's loaded on the model.
The problem with Javascript-heavy frameworks like this is that if your team does not have a lot of experience using JS in general, it can get extremely messy and cluttered. Which it did, coupled with a lot of regression (a misplaced ";" could break an entire part of the application), we needed an automated way to catch up with those bugs.
Since I have a lot of experience with WebDriver, we started using it to write scenario tests when the application is deployed. A test should emulate customer behavior: click on a menu, expect a window to be opened, fill in a form and expect something else to happen. It's not isolated but tests everything together.
WebDriver is great, but since a lot of javascript events are happening in the background it's very difficult to write a easily usable DSL to manipulate the UI. One has to wait for ajax calls to finish, for DOM elements to appear or disappear, and so on. Tests became instable and failed sometimes, even sometimes on the CI build but never on your development environment. It takes more and more time to find & fix those things.
### A possible solution: Siesta ###
[Siesta](http://www.bryntum.com/products/siesta/) is a product from Bryntum especially written to unit test Extjs applications, focussing on the UI. Sounds nice, so we decided to check it out as a possible alternative to WebDriver. As the website states:
> Siesta is a JavaScript unit testing tool that can help you test any JavaScript code and also perform testing of the DOM and simulate user interactions. The tool can be used together with any type of JavaScript codebase jQuery, Ext JS, NodeJS, Dojo, YUI etc. Using the API, you can choose from many types of assertions ranging from simple logical JS object
Sounds good, right?
The setup isn't too difficult, after a few hours of fiddling I managed to bootstrap our Extjs application using this index.js file:
var Harness = Siesta.Harness.Browser.ExtJS;
Harness.configure({
title : 'Test Suite',
loaderPath : {
'Ext': '../extjs',
'Ext.ux': '../extjs/ux',
'MyApp': '../app'
},
preload : [
// version of ExtJS used by your application
'../extjs/resources/css/ext-all.css',
'../resources/css/workb.css',
// version of ExtJS used by your application
'../extjs/ext-all-debug.js',
'./app-vars.js',
{
text: "Ext.Loader.setConfig({ 'Ext': '../extjs', 'Ext.ux': '../extjs/ux', 'MyApp': '../app' })"
},
'../extjs/overrides/javascript-overrides.js',
'../extjs/overrides/PFW-overrides.js',
'../app/app.js'
]
});
Harness.start(
'tests/001_sanity.t.js',
'tests/002_window.t.js'
);
Some pitfalls: `loaderPath` isn't evaluated in the preload so you have to reset it with `Ext.Loader.setConfig()` and I had to alter our app.js file. Our directory structure looks like this:
root
-- app
-- extjs
---- ux
-- siesta
---- tests
So you have to watch out for relative paths like `appFolder` in app.js:
Ext.application({
name: 'MyApp',
appFolder: (_siesta ? '../' : '') + 'app',
After that, you can start writing tests. Looking at the examples, the test flow looks a lot like our current WebDriver tests (wait for rows present, wait x seconds, click on this, do that). Here's a simple test to create a view and check if the grid has some rows:
StartTest(function(t) {
t.diag("Creating some window");
var view = Ext.create('MyApp.view.SomeOverview', {
renderTo: Ext.getBody() // required
});
var grid = view.down("grid");
t.chain(
{ waitFor : 'rowsVisible', args : grid }
);
});
![siesta view test in action]({{urls.media}}/siesta.png)
Siesta also comes with it's downsides though.
- JS Test code is really messy. Chaining, async calls, ugly data setup for stores, ... A simple test can get complicated fast and requires advanced JS knowledge not everybody in our team has.
- `waitFor` exposes the same problems we have with our current WebDriver tests, so it's not that much of an improvement
- Test data setup cannot be reused from our backend integration tests (we use the builder pattern there to create data in the DB)
- Creating a view to test doesn't test the controller and vice versa. Still too low level for us.
The biggest problem is that it's still more an integration/unit test than a scenario test and quite tightly coupled to your implementation. Since our implementation is far from perfect, Siesta is not the optimal solution for us. For example, we create stores inside our views and load them in `initComponent()`. No way to provide a stub store with some dummy data. We'd have to refactor 200+ views to create tests. Of course tests should be written before the implementation...
If you would like to know more about Siesta or JS BDD testing, take a look at
- [Pivotallabs blog post](http://pivotallabs.com/sencha-touch-bdd-part-5-controller-testing/)
- [Siesta API doc: Getting started](http://www.bryntum.com/docs/siesta/#!/guide/siesta_getting_started)

View File

@ -0,0 +1,143 @@
---
title: Unit Testing Stored Procedures
bigimg: /img/Unit Testing Stored Procedures.jpg
date: '2013-10-10'
subtitle: And a pragmatic guide on how to include them into your build system.
tags: ['unit testing', 'sql']
---
This article is based on the notes I've collected on [My Wiki](http://brainbaking.com/wiki/code/db/sql).
Test Driven Development (or TDD), it's one of those buzz words which usuallly appear in the same sentence with "scrum" or "XP". But in practice, I've seen few people actually applying it all the way through. What do I mean by that? You're probably very familiar with, say Java or .NET, and you know how to write unit tests in that language using your beloved IDE. That's a good start, right. Maybe you might even do it the test-first way: writing a failing test (letting it fail for the right reason), writing the implementation and maybe some refactoring. Red, Green, Refactor.
But what do you do when you need to step out of your language comfort zone to write some Javascript on the client side? Do you copypaste stuff or try to apply the same techniques as you're used to? You might have heard from test frameworks like [Jasmine](http://pivotal.github.io/jasmine/) and use these. Also good for you! Client side development is very popular, but what about SQL? Do you write tests for stored procedures? I thought so. There are plenty of frameworks available to help you in doing this, for instance [SQL Developer](http://docs.oracle.com/cd/E15846_01/doc.21/e15222/unit_testing.htm) which I used because it's already installed on every developer's PC and has a "friendly" interface.
![sql dev unit test](http://brainbaking.com/wiki/_media/code/db/unittest_sqldev.png)
Once you create a "test repository", SQL Developer will create test tables to store it's unit test descriptions and results, prefixed by "UT_". You can specify whether you'd like to create a new scheme for it or not. When creating a new test, the tool asks you a couple of questions:
1. What do you want to insert or execute before the test? (Setup phase)
2. What stored procedure do you want to execute? (Execute system under test phase)
3. What should the result of the procedure be, or execute a query and check it's results? (Verify phase)
4. What do you want to insert or execute after the test? (Teardown phase)
You can reuse the parts to be executed in the different phases for another unit test, yay! This data will also be stored in the predefined tables.
### But what about existing data when inserting new stuff?
use this as teardown:
ROLLBACK;
### But how do you execute a stored procedure with IN/OUT REF CURSOR arguments?
SQL Developer has some trouble executing that, indeed. In this case, we use a little trick:
1. Create a dummy stored procedure:
create or replace
PROCEDURE UT_DUMMY AS
BEGIN
NULL;
END UT_DUMMY;
2. Execute the dummy procedure in the SUT phase.
3. Use the verify phase to call the actual to test procedure yourself, and do your verification stuff yourself:
DECLARE
P_USERID NUMBER;
MY_P_CURSOR SCHEMA.PACKAGE.Cursor;
cursor_element MY_P_CURSOR.SCHEMA.CursorType;
found boolean;
BEGIN
P_USERID := 11;
found := false;
PACKAGE.MYPROCEDURE(
P_USERID => P_USERID,
P_CURSOR => MY_P_CURSOR
);
WHILE TRUE LOOP
FETCH MY_P_CURSOR INTO cursor_element;
EXIT WHEN MY_P_CURSOR%NOTFOUND;
IF cursor_element.columntocheck = 'My value' THEN
found := true;
END IF;
END LOOP;
IF found = false THEN
raise_application_error(-20000, 'Your error message in here!');
END IF;
END;
### Okay but what about integrating the exeuction of these tests in my build system?
You can use the commandline utility provided by SQL Developer to execute a test or a suite:
ututil -run -suite -name [name] -repo [repo] -db [db] -log 3
It's very interesting to dynamically import and export tests using "-imp" and "-exp", and creating one suite using this PL/SQL:
SET serveroutput ON;
delete from ut_suite_items;
delete from ut_suite;
DROP SEQUENCE ut_suite_items_seq;
CREATE SEQUENCE ut_suite_items_seq
MINVALUE 0
MAXVALUE 999999999999999999999999999
START WITH 0
INCREMENT BY 1;
DECLARE
suiteid VARCHAR2(900) := 'ALL';
utid VARCHAR2(900);
cursor tableCursor is SELECT UT_ID FROM UT_TEST;
BEGIN
dbms_output.enable(10000);
DBMS_OUTPUT.PUT_LINE('Creating one test suite to rule them ALL...');
insert into ut_suite(ut_sid, coverage, name, created_on, created_by, updated_on, updated_by)
values(suiteid, 0, suiteid, null, null, null, null);
open tableCursor;
fetch tableCursor into utid;
WHILE (tableCursor%FOUND) LOOP
insert into ut_suite_items(ut_sid, ut_id, ut_nsid, run_start, run_tear, sequence, created_on, created_by, updated_on, updated_by)
values (suiteid, utid, null, 'Y', 'Y', ut_suite_items_seq.nextval, null, null, null, null);
fetch tableCursor into utid;
END LOOP;
close tableCursor;
commit;
DBMS_OUTPUT.PUT_LINE('SUCCESS - test suite created!');
END;
/
It creates only one suite called 'ALL' which can then be executed. The commandline utility will output "UT_SUCCESS" or throw some kind of exception if one of the tests failed.
### I still get errors using ututil, some ConnectException?
the utility cannot handle any TNS connections you've entered in SQL Developer. Change these to regular connection strings and all will be well. Yes it's a huge disadvantage, and yes the connection settings are stored in your locally installed SQL Developer instance, which also kind of sucks. We needed to install SQL developer on the Build integration PC and configure the same connections within it.
### What about versioning? The tests are stored in my DB, but it doesn't evolve as quickly as the code does!
Right, that's where the import/export thing comes in. We store the actual unit tests in XML format inside our regular source control system, next to the "other" unit tests (in this case in .NET). Every time someone writes a unit test using SQL developer, it extracts that test using:
ututil -exp -test [name] -file [file] ...
which creates an XML file. Executing the tests happen within a wrapper .NET test class, which goes through some steps to setup the DB system correctly:
1. Cleanup all UT_TEST* and UT_SUITE* tables which would contain the acutal tests.
2. Loop through all XML files, and impor them one by one (they get inserted into the cleaned tables)
3. Generate the 'ALL' unit test suite - see PL/SQL above.
4. Execute the test suite using ututil and parse the results from the command line.
That's as far as our imagination and budget goes. We have a stable system which is able to version the XML files - inserting the test data is still dependant on the actual state of the database. One could explore the dynamic creating of tables the stored procedures use, but as our codebase is legacy (read: really really old stuff), we decided not to invest too much time in that.

View File

@ -0,0 +1,40 @@
---
title: 'Unit testing in Legacy Projects: VB6'
date: '2016-12-27'
tags: ['unit testing', 'VB6' ]
---
Thanks to the [Postmodern VB6](https://ihadthisideaonce.com/2015/05/13/postmodern-vb6-a-quick-start-with-simplyvbunit/) article I've found on the internetz, I decided to give [SimplyVBUnit](simplyvbunit.sourceforge.net) a try. My job requires sporadic visual basic 6 code changes in the big legacy project we're converting to C#. It's an administrative system bound to Belgium laws so as you can imagine they change every few months and the old software still has to be complaint to those crazy new rules. As a result, we sometimes dabble in VB6 code. It feels more like drowning, really.
Unit testing is what keeps me from rage-quitting on every project. The SimplyVBUnit syntax is quite nice if you're used to writing NUnit tests: they also work with `Assert.That` for instance:
```vb
Public Sub MyTestMethod_WithSomeArg_ShouldReturn45
Dim isType As Boolean
isType = MyTestMethod(arg1)
Assert.That isType, Iz.EqualTo(45)
End Sub
```
![simply vb unit screenshot](/img/simplyvbunit.png)
The test code is very readable thanks to the [NUnit](https://nunit.org/index.php?p=documentation) influence on SimplyVBUnit. The package is very easy to install, but there are a few gotcha's.
You need to create a separate VBP file (Visual Basic Project) which acts as your UnitTest project with a reference to the SimplyVBUnit package. That's easy enough, but it's a project. That means it can't reference other projects! Our software is basically one large project with heaps of muddy code. Compiling the EXE and referencing that one is not an option for us. That leaves us with a few alternatives:
- Package the test runner and the dependency in your production code. (Hmmm...)
- Create a DLL project and move the test code to the DLL. This requires another build step in our already-too-long-manual-deployment procedure. Nope.
- Create a group (vbg), include both projects, and include modules/forms/class modules to be tested in the unit test project as an existing file. This means both projects will include the same source files. SourceSafe actually notices this if you have a file checked out and will ask you to update the "other" file in the second project.
The group makes it possible to open everything at once. Unit tests live in a subfolder. This is our vbg file:
```
VBGROUP 5.0
Project=program.vbp
StartupProject=UnitTests\UnitTests.vbp
```
Utilizing two projects in one group means switching between both as a startup project. One could use the group to develop and start tests but the vbps for debugging or so. It's all still fairly new for us so we'll see where this will end.
Unit tests are useless if they aren't run (automatically). At this moment we try to avoid coding anything in VB6 at all. If we do, we run the tests manually. At least some parts of the code are tested without bootstrapping the whole application and plowing through various forms to get to the part where you actually changed something...

View File

@ -0,0 +1,54 @@
---
title: Visual Studio 2012 for Eclipse users
bigimg: /img/Visual Studio 2012 for Eclipse users.jpg
date: '2013-10-14'
subtitle: Trying to fill the gap of missing features in VStudio.
tags: ['visual studio', 'eclipse']
---
When switching over to a new editor and new language, I can sometimes get frustrated by missing features I got (very) attached to. This excludes the obvious difference in shortcut keys.
### Shortcuts and refactoring tools ###
One plugin to rule them all: [ReSharpner](http://www.jetbrains.com/resharper/). This productivity tool brings back the incredible development speed to the Visual Studio platform. You can almost map the eclipse (or IntelliJ, since they guys from JetBrains developed it) keys to the ReSharpner keys. If you're used to quickly refactor out variables, introduce classes from parameters or create test classes, you'll be in heaven.
The following shortcuts can be mapped (you're welcome):
| **Eclipse shortcut** | **ReSharpner shortcut** | **description** |
|-----------------------------------|------------|--------|
| CTRL+D | CTRL+L | remove line |
| ALT+DOWN | CTRL+D | duplicate line |
| CTRL+SPACE (CTRL+ENTER) | CTRL+SPACE (TAB) | code completion, select in combobox |
| ALT+SHIFT+UP/DOWN | CTRL+ALT+LEFT/RIGHT | Extend/Shrink selection |
| CTRL+SHIFT+/ | CTRL+ALT+/ | commend line |
| CTRL+SHIFT+1 | ALT+ENTER | quick fix |
| ALT+UP/DOWN | CTRL+SHIFT+ALT+UP/DOWN | move line |
| CTRL+SHIFT+O | CTRL+E, (C)/F | organize imports (and format etc, F = silent) |
| CTRL+F11 | CTRL+U, U | rerun last |
| CTRL+O | ALT+\ | Go to file member |
| CTRL+SHIFT+G | CTRL+SHIFT+ALT+F12 (SHIFT+F12) | find usages |
| F3 | F12 | go to definition |
| CTRL+SHIFT+. | SHIFT+ALT+PGDN | go to next error |
| CTR+, | SHIFT+ALT+PGUP | go to previous error |
| ALT+SHIFT+I | CTRL+R, I | inline variable |
| ALT+SHIFT+R | CTRL+R, R | rename |
| ALT+SHIFT+M | CTRL+R, M | extract method |
| ALT+SHIFT+C | CTRL+R, S | change method signature |
| CTRL+SHIFT+B | F9 | toggle breakpoint |
| CTRL+M | SHIFT+ALT+ENTER | toggle full screen mode |
|-----------------------------------|------------|--------|
Other interesting links:
- [Default keymap PDF overview](http://www.jetbrains.com/resharper/docs/ReSharper70DefaultKeymap_IDEA_scheme.pdf)
- [IntelliJ keymap PDF overview](http://www.jetbrains.com/resharper/docs/ReSharper70DefaultKeymap_IDEA_scheme.pdf)
### Comparing files with each other ###
Simply comparing two files within the editor can be a pain - the easiest way to do it in Eclipse is just select both files, rightclick and select "compare". No such option here. You can compare a file with a previous version from TFS, but not two physically different files, weird. Install [VSCommands](http://vscommands.squaredinfinity.com/) and that problem is also solved:
![compare files in vstudio]({{urls.media}}/compare_files_vstudio2012.png)
It uses the built-in VS2012 comparison window, which is quite nice.

View File

@ -0,0 +1,96 @@
---
title: Webdriver Exception Handling
date: '2015-01-14'
subtitle: What should you do when something goes wrong with your scenario tests
bigimg: /img/Webdriver Exception Handling.jpg
tags: ['unit testing', 'C#', 'webdriver', 'scenario testing' ]
---
As the previous post indicated, we're trying to stabilize our scenario tests created with WebDriver. One of the things we did was trying to capture as much data as possible if something goes wrong. Something like a typical `ElementNotFoundException`, or the less common `StaleElementException` (detached from DOM after evaluation) - these things can be hard to trace if you don't run the tests locally. We also stumbled upon the "it works on my machine" problem - tests succeeding on one development machine but not on the other - mostly related due to timing issues.
So, what should you do when something goes wrong?
- capture what happened! (screenshot)
- capture what happened! (exception stacktrace logging)
- capture what happened! (serverside logging)
WebDriver has a `GetScreenshot()` method you can use to dump an image to a file on exception. We used a bit of pointcut magic using PostSharp to automagically handle every exception without manually having to write each `try { }` clause.
WebDriver().GetScreenshot().SaveAsFile(fileName + ".png", ImageFormat.Png);
After saving the image, we also capture the exception and some extra serverside logging:
File.WriteAllText(fileName + ".txt",
"-- Resolved URL: " + ScenarioFixture.Instance.ResolveHostAndPort() + Environment.NewLine +
"-- Actual URL: " + ScenarioFixture.Instance.Driver.Url + Environment.NewLine +
"-- Exception Message: " + ex.Message + Environment.NewLine +
"-- Stacktrace: " + Environment.NewLine + ex.StackTrace + Environment.NewLine + Environment.NewLine +
"-- Service log: " + Environment.NewLine + ReadServiceLogFromDeployedApp());
Because the webservice is deployed somewhere else (scenario tests run againsst the nightly build IIS webserver), we need to access the logfiles using a ´GET´ call, done with RestSharp:
private static string ReadServiceLogFromDeployedApp()
{
var restClient = new RestClient(ScenarioFixture.Instance.ResolveHostAndPort());
var restRequest = new RestRequest("log/servicelog.txt");
restRequest.AddHeader("Content-Type", "text/plain");
restRequest.AddHeader("Accept", "text/plain");
var response = restClient.Execute(restRequest);
return response.Content;
}
Now, to easily access those files (the screenshot and the written log for each failing test), we wrap the exception in another exception containing a direct link to both files. That enables every developer to simply browse to the failing test on our CI env (teamcity) and simply click on the link!
To be able to do that, combined with the pointcut, implement the `OnException()` hook and call the above code:
[Serializable]
[ScenarioExceptionAspect(AttributeExclude = true)]
public class ScenarioExceptionAspect : OnMethodBoundaryAspect
{
public override void OnException(MethodExecutionArgs args)
{
var exceptionFileName = Directory.GetCurrentDirectory() + @"/" + WebDriverExceptionHandler.Handle(args.Exception);
exceptionFileName = exceptionFileName.Replace(@"C:", @"file://teamcity/c$");
exceptionFileName = exceptionFileName.Replace(@"\", @"/");
throw new Exception("Scenario test failed"
+ Environment.NewLine
+ " -- Screenshot: " + exceptionFileName + ".png"
+ Environment.NewLine
+ " -- Log: " + exceptionFileName + ".txt", args.Exception);
}
}
This introduces one more problem: what if you want to trigger an exception, something like `ExpectedException(typeof(InvalidArgumentException))`? We'll still end up in our aspect and we'll take a screenshot and dump everything. We fixed this by taking a peek at the live stacktrace. I know it's far from ideal, but it serves it's purpose and works pretty well for the moment.
private static bool ExpectedSomeException(StackTrace trace)
{
const int arbitraryMaxDepthToLookForAttribs = 5;
for (var stackElements = 1; stackElements <= arbitraryMaxDepthToLookForAttribs; stackElements++)
{
if (AnyExpectedExceptionInAttribute(trace, stackElements))
{
return true;
}
}
return false;
}
private static bool AnyExpectedExceptionInAttribute(StackTrace trace, int stackElements)
{
var callingMethod = trace.GetFrame(stackElements).GetMethod();
var anyExpectedExceptionAttrib = callingMethod.GetCustomAttributes(typeof(ExpectedExceptionAttribute), true).Any();
return anyExpectedExceptionAttrib;
}
Every instance of a new `StackTrace` element will contain all stack data from that point on, so create one in the onException method, otherwise remember to look "deeper" or further into the stack itself. Yes we could solve that using recursion instead of with an arbitrary number of elements inside a for loop, but we were trying to solve something else and this stood in the way so naturally the reaction was to not invest too much time.
What's the outcome? This:
> Test(s) failed. System.Exception : Scenario test failed
> -- Screenshot: file://teamcity/c$/buildagents/buildAgentOne/work/10dbfc9caad025f8/Proj/ScenarioTests/bin/Debug/ex-15-01-14-15-56-02.png
> -- Log: file://teamcity/c$/buildagents/buildAgentOne/work/10dbfc9caad025f8/Proj/ScenarioTests/bin/Debug/ex-15-01-14-15-56-02.txt
> ----> System.Exception : Root menu could not be opened after 10 tries?
> at Proj.ScenarioTests.ScenarioExceptionAspect.OnException(MethodExecutionArgs args) in c:\buildagents\buildAgentOne\work\10dbfc9caad025f8\Proj\Proj.ScenarioTests\ScenarioExceptionAttributeHandler.cs:line 36
> ...

View File

@ -0,0 +1,19 @@
+++
title = "__template"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"",
"__template"
]
date = "2013-03-12"
+++
# @NS@ >> @!PAGE@
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

18
content/wiki/appendix.md Normal file
View File

@ -0,0 +1,18 @@
+++
title = "appendix"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"",
"appendix"
]
date = "2013-03-12"
+++
~~NOTOC~~
<img style='' src='/img/alphaindex>|'>

View File

@ -0,0 +1,25 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"home"
]
date = "2013-03-12"
+++
# books >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>
## Links
#### Online digitale resources
* http:*www.scribd.com/ (bvb [jQuery novice to Ninja](http:*www.scribd.com/doc/36486402/jQuery-novice-to-Ninja)) (betalend)

31
content/wiki/books/ddd.md Normal file
View File

@ -0,0 +1,31 @@
+++
title = "ddd"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"ddd"
]
date = "2013-03-12"
+++
# Domain Driven Design
## Samenvatting
[Zie Kristof's Wiki](http://www.butskri.comuf.com/wiki/doku.php?id=boeken:ddd)
## Top reasons Why DDD Fails
Schema's gebaseerd op conferentie: http://architects.dzone.com/advice-for-ddd
Klik op images om te vergroten.
<img style='margin-left: auto; margin-right: auto; width: 400px;' src='/img//books/whydddfails_1.jpg'>
Deel twee:
<img style='margin-left: auto; margin-right: auto; width: 400px;' src='/img//books/whydddfails_2.jpg'>

View File

@ -0,0 +1,108 @@
+++
title = "dont_make_me_think"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"dont_make_me_think"
]
date = "2013-03-12"
+++
# Don't Make me Think
Author: Steve Krug<br/><br/>
Subtitle: A common sense approach to Web usability (SE)
[Librarything link](http://www.librarything.com/work/12322)
#### 1. Don't make me Think
> If something is hard to use, I just don't use it as much.
Duidelijkheid is belangrijker bij een website overzicht dan iets wat denkwerk vereist - vandaar de titel van het boek. Niet moeten nadenken *hoe* exact iets gebruikt moet worden, maar iets als vanzelfsprekend aanzien.
#### 2. How we really use the Web
Niemand leest een hele webpagina, men scant sommige tekst blokken en werpt een snelle "blik" op elke pagina. <br/><br/> Facts of life:
1. We don't read pages, we scan them.
2. We don't make optimal choices, we satisfice. (We klikken niet altijd op de beste link maar de meest aannemelijke)
3. We don't figure out how things work, we muddle through. (Als we iets vinden dat werkt, blijven we dit gebruiken)
#### 3. Billboard design 101
1. Maak een duidelijke visuele hiërarchie op de website:
* Hoe belangrijker iets, hoe meer aanwezig (groter lettertype bvb)
* dingen die logischerwijze samenhoren ook effectief samen plaatsen (menu groepen)
* Visueel dingen "nesten"
2. Gebruik conventies in plaats van alles opnieuw uit te vinden.
3. Maak duidelijk wat klikbaar is
4. Vermijd een te "drukke" website (door bvb te veel borders rond menu's te plaatsen)
#### 5. Omit needless words
> Vigorous writing is concise. A sentence should contain no unnecessary words, a paragraph no unnecessary sentences, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts. ((William Strunk Jr. and E.B. White, *The elements of style*))
* Happy talk must die (welkom op onze blablabla website die blablablayawn doet)
* Instructions must die (klik hier en volg stap 1 tot en met 224 blabla)
#### 6. Street signs and Breadcrumbs
> People won't use your website if they can't find their way around it.
Vergelijk op een website iets zoeken met in een warenhuis iets zoeken. Je kan ofwel "browsen" door te navigeren met plaatjes in de rijen, ofwel direct aan personeel vragen waar object x ligt. Als je na een tijdje nog altijd niet gevonden hebt wat je zoekt verlaat je de winkel. Plaats daarom een zoek formulier zo zichtbaar mogelijk, en zorg voor correcte en duidelijke navigatie.
Extra problemen met internet browsen: we hebben geen idee van schaalbaarheid, geen idee van directie of locatie... Een website zou 5 basis elementen altijd aanwezig moeten hebben:
1. Site ID (linksboven, kan op een homepage meer plaats innemen)
2. Een manier om naar de homepage te gaan (buiten klikken op het logo)
3. Een manier om te zoeken
4. "Utilities" (basis links zoals hoe x doen)
5. Secties (de navigatie)
De homepage is hierop een uitzondering (zie volgend stuk)<br/><br/>
Pagina benaming is ook heel belangrijk: consistent, op de juiste plaats en altijd aanwezig.
##### Navigatie
"You are here" -> breadcrumbs (best bovenaan te plaatsen)
* Altijd bovenaan plaatsen
* Gebruik &gt; tussen levels in
* Gebruik een kleiner lettertype
* Gebruik "you are here" prefix
* Zet laatste item in bold (huidige pagina dus)
* Dit is geen vervanging voor een volledige pagina naam!
Tabs als navigatie
* Leggen zichzelf uit
* Moeilijk om te missen
* Mooi met de juiste style (evt JS)
* Ze stellen een fysieke fichebak voor (geven de illusie dat een actieve tab "naar voren" komt, met extra contrast)
#### 7. Home Page
De homepage zou voor de volgende zaken moeten zorgen:
* Site identiteit, missie (waar dient de site voor?)
* Site hiërarchie (wat kan ik hier vinden? Wat doe ik hier?)
* Zoeken!
* Stukjes om te *teasen*, content promo (stukken van een artikel, tijd-gerelateerde content)
* Promotie, reclame deals, ...
* Snelkoppelingen naar bepaalde (belangrijkere) secties buiten de navigatie om
* Registratie indien nodig
Aangezien iedereen iets anders zoekt op een website, maar er slechts één homepage is, moet deze zo robuust mogelijk gemaakt worden zodat alle surfers specifiek voor hun voldoende informatie kunnen verzamelen om te beslissen of ze op de juiste pagina zitten of niet, en dan eventueel over te gaan naar zoeken of navigatie zelf.
Het moet duidelijk zijn vanaf de home page wat de site doet, wat ze te bieden heeft, en ook wat niet! Gebruik hiervoor als hulp een **tagline**.
Home page navigatie kan uniek zijn ten opzichte van de rest van de webpagina. Het logo kan bijvoorbeeld ook groter en duidelijker aanwezig zijn. Het is wel de bedoeling dat alles consistent samen loopt.
Vermijd overmatig gebruik van comboboxen, zeker als navigatie! (Of pulldown menu's). Ze verbergen de eigenlijke menu items, zijn snel onoverzichtelijk en moelijk om te scannen voor onze ogen.

View File

@ -0,0 +1,173 @@
+++
title = "getting_real"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"getting_real"
]
date = "2013-03-12"
+++
# Getting real
http://gettingreal.37signals.com/toc.php
#### The Starting Line
1. Build Less ("underdo your competetion")
2. What's your problem? (Stratch your own itch, zie Rework, "born out of necessity")
3. Fund Yourself
4. Fix Time and Budget, Flex Scope
5. Have an Enemy ("Figure out your app's enemy and use it as a motivator to what it shouldn't be)
6. It shouldn't be a Chore (your passion, or lack thereof, shines through)
> How does a project get to be a year behind schedule? One day at a time. (Fred Brooks)
#### Stay Lean
Agile reclame...
1. Less Mass
2. Lower your Cost of Change
3. The Three Musketeers ("use only three people")
4. Embrace Constraints ("let limitations guide you to creative solutions")
5. Be Yourself
> Differentiate yourself from bigger companies by being personal and friendly.
#### Priorities
1. What's the big Idea (Define the **one-point vision** for your app) -> elevator pitch, 140chars tweet?
2. Ignore details Early on
3. It's a problem when it's a problem
4. Hire the Right Customers
5. Scale Later
6. Make Opinionated software
#### Feature Selection
> **Take whatever you think your product should be and cut it in half**. Pare featuers down until you're left with only the most essential version. Then do it again.
1. Half, not half-assed
2. It just doesn't matter
3. Start with No (make featuers work hard to be implemented)
4. Hidden Costs
5. Can you Handle it? (build something you can handle, not because the competitor also does it)
6. Human solutions (build software for **general concepts** to let people create their own solutions)
7. Forget Feature Requests
8. Hold the Mayo (ask people what they don't want)
#### Process
Impliciete XP reclame...
1. Race the Running Software
2. Rinse and Repeat
3. From Idea to Implementation (brainstorm - paper sketches - HTML screens/CSS mockups - code it)
4. Avoid Preferences
5. "done"!
6. Test in the Wild
7. Shrink your Time
> Decide on the little details so your customers don't have to.
Bvb. maak gewoon 50 units per tabel ipv daar een `property` van te maken.
:exclamation: **Be an executioner**:
> It's so funny when I hear people being so protective of ideas (they want me to sign an NDA to tell me the simplest idea). To me, ideas are worth nothing unless executed. They are just a multiplier. Execution is worth millions. Weak idea ###### 1. Good idea 10. No execution ###### $1. Weak execution $1000. (Derek Sivers)
#### The Organisation
Impliciete scrum team reclame... (Niet UI en backend team, generalists > specialists etc)<br/><br/>
Bijna zelfde stuff als [books/rework]({{< relref "wiki/books/rework.md" >}})?
1. Unity
2. Alone Time (people need uninterrupted time to get things done) vb make half the day "alone time"
3. Meetings are Toxic
4. Seek and Celebrate Small Victories (release something today, 4hour quick wins)
#### Staffing
1. Hire Less & later
2. Kick the Tires
3. Actions, not words
4. Get well rounded individuals
5. You can't fake enthousiasm
6. Wordsmiths (hire good writers)
#### Interface Design
> Another reason to design first is that **the interface is your product**. What people see is what you're selling. If you just slap an interface on at the end, the gaps will show.
1. Interface First
2. [Epicenter design](http://gettingreal.37signals.com/ch09_Epicenter_Design.php)
3. Three State solution
4. The Blank Slate
5. Get Defensive (design for when things go wrong)
6. Context over consistency
7. Copywriting is interface design (every letter matters! Karel stijl)
8. One Interface (incorporate admin functions into the main site design)
#### Code
Impliciete XP practices reclame...
1. Less Software
2. Opinionize for happiness
3. Code Speaks
4. Manage Debt
5. Open Doors (get data out to the world via RSS, APIs etc)
> A happy programmer is a productive programmer. **Choose tools that keep your team excited and motivated**.
#### Words
1. There's nothing functional about a functional spec
2. Don't do dead documents
3. tell me a quick story
4. use real words
5. personify your product
#### Pricing and Signup
1. Free Samples
2. Easy On, Easy off
3. Silly Rabbit, tricks are for kids
4. A Softer Bullet
#### Promotion
1. Hollywood launch
2. A powerful promo site
3. ride the blog wave
4. solicit early
5. promote through education
6. feature food
7. track your logs
8. inline upsell
9. name hook
#### Support
1. Feel the pain
2. Zero Training
3. Answer Quick
4. Through Love
5. In Fine Forum
6. Publicize your Screwups
#### Post-Launch
1. One Month Tuneup
2. Keep the Posts Coming
3. Better, not Beta
4. All Bugs are not created equal
5. Ride Out the storm
6. Keep Up with the Joneses
7. Beware the Bloat Monster
8. Go with the flow

View File

@ -0,0 +1,171 @@
+++
title = "inspiraties"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"inspiraties"
]
date = "2014-03-06"
+++
# Inspirerende Boeken
### Specifieke skills/Organisatorisch
##### Switch
{{< lib "Switch: How to Change Things When Change Is Hard" >}}
> "Inability to change is not lazyness but simply exhaustion". Self control is an exhaustable resource! Spreek zowel de 'olifant' (emotioneel, feeling, smelling) aan als de 'rider' (thinking, reflecting, planning) om mensen te overtuigen.
Komen gelijkenissen in terug van het "director on stage" concept van "Your Brain at Work".
##### Purple Cow: Transform Your Business by Being Remarkable
{{< lib "Purple Cow: Transform Your Business by Being Remarkable" >}}
> Het grootste probleem van bedrijven is angst. Durf net in deze tijden wél opmerkelijk te zijn! Het is niet erg om kritiek te krijgen, het valt net extra op. Een "Opmerkelijk" idee is beter dan een "heel goed" idee!
##### Presentation Zen
{{< lib "Presentation Zen" >}}
> Minder, eenvoudiger, duidelijker en doelmatiger slides opbouwen en presenteren is beter dan meer, gedetailleerder en ingewikkelder slides opbouwen en presenteren.
##### Rework
{{< lib "Rework" >}}
> o.a. "Scratch your own Itch": ontwikkel software voor uw eigen noden en breng het dan naar buiten: zo hecht je veel meer aandacht aan de kwaliteit.
##### Team Geek
{{< lib "Team Geek" >}}
> "Software development is a team sport". Show respect (is there anything you need?), trust (mission statements) & humility (admitting to making mistakes) to yourself, your team, your collaborators, the organization and your users.
En ook: *underpromise, overdeliver.*
##### Peopleware
{{< lib "Peopleware" >}}
> "The fundamental response to change is not logical but emotional!" en ook dit: managing = het team afschermen van interrupts en volledig hun gang laten gaan. Een Manager is nooit "lid" van het team maar zorgt ervoor dat een groep mensen tot een team omgevormd kan worden door diezelfde mensen zelf hun eigen skills te laten ontplooien!
### Self Improvement
##### Search Inside Yourself
{{< lib "Search Inside Yourself" >}}
> Save the world and increase your humble Emotional Intelligence by breathing mindful a few minutes a day.
##### Yes-but, what if everything works out?
{{< lib "Ja-maar wat als alles lukt ?" >}}
> The true voyage of discovery is not in the looking for new landscape, but in looking with different eyes. (Marcel Proust, p73)
Stop met ja-maar te zeggen en begin met ja-en te zeggen. Kijk naar problemen met een andere blik, die nieuwe mogelijkheiden aanbiedt. (Zie Power Thinking). Durf verlangens te hebben (een "vraag gevoel", kan soms 20j duren voor het concreet wordt), banale verlangens hebben ook een positief effect. Focus op wat je wél kan en verbeter dat, in plaats van af te geven op wat je minder kan en dat proberen te verbeteren.
##### The art & Science of remembering everything
{{< lib "Moonwalking with Einstein: The Art and Science of Remembering Everything" >}}
> Monotomy collapses time. Novelty unfolds it. (Michel Siffre, nieuwe ervaringen geven psychologisch de tijdsindruk dat alles sneller gaat)
Onthouden door middel van trucjes (het "geheugenpaleis" e.a.) kan iedereen, ook iemand die niet "intelligent" is. Spreek het holistisch deel van uw hersenen aan, dat nog niet hiervoor getraind is, dus het kan even (tot een jaar) duren. Het aantal dingen dat iemand max. kan onthouden zonder is zelfs lager dan het mythisch cijfer 7.
##### Quiet
{{< lib "Quiet: The Power of Introverts in a World That Can't Stop Talking" >}}
> It's not that I'm smarter, it's that I stick with problems longer. (A. Einstein)
Introverten hebben veel meer focus en persistence, maar zijn sneller angstig dan bored, hebben minder prikkels nodig. Kunnen zich als extraverten gedragen maar dat vergt veel energie, zorg voor relax spots! Zoek meer balans voor beide persoonlijkheden.
#### Zelf-hulp
##### Power Thinking
{{< lib "Learn to Power Think" >}}
> Blik regematig terug op uw eigen leven, stuur bij, sta open voor nieuwe zaken, wijk af en leer anderen kennen, schrijf op wat je voelt.
##### Het heeft Zin
[Els De Schepper - Het heeft Zin](http://www.elsdeschepper.be/boeken/zin/)
> Één grote bevestiging dat reapprisal dé meest kritieke skill is om het leven positief door te komen: bekijk niet alles met uw kortzichtige vooroordelen maar sta toe dat anderen niet dezelfde mening hebben als jou!
#### Gedragstherorie
##### Slaap Lekker
{{< lib "Dreamland: Adventures in the Strange Science of Sleep" >}}
> Tijdens R.E.M. gedeelte van onze slaap zijn de hersenen nog superactief, het is belangrijk om dan op ideeën te kunnen komen. Logische dingen worden onsamenhangend terug doorlopen zonder diepere betekenis.
Ons bioritme volgt de zon, licht is de grootste boosdoener van slaapgebrek van de moderne tijd. Probeer een halfuur tot een uur op voorhand niet meer naar verlichtende schermen te staren! Ontspannen daarvoor werkt ook. Afkoeling is ook belangrijk.
##### Where good Ideas come From
{{< lib "Where good ideas come from" >}}
> De beste ideeën worden jarenlang met zorg uitgebroed en gerealiseerd door andere gelijkaardige mogelijkheden, in de juiste omgeving te ontspruiten en genoeg ruimte te laten om fouten te kunnen en durven maken.
##### Mojo
{{< lib "Mojo how to get it|Mojo" >}}
> Mojo is de positieve uitstraling waarmee we nu iets doen die vanbinnen komt en naarbuiten uitstraalt. Optimism is fuel for change!
##### Your brain at Work
{{< lib "Your brain at Work" >}}
> Merk het gedrag van uw eigen brein op en stel uzelf in staat dit te veranderen, gegeven de kennis over de interne werking van uzelf.
##### Getting Things Done
{{< lib "Getting Things Done" >}}
> Speel véél sneller in op projecten en todo's door een efficiënte manier op te bouwen om direct gedachtes, ideeën en dingen neer te schrijven en wekelijks bij te werken.
##### Pragmatic Thinking & Learning
{{< lib "Pragmatic Thinking & Learning" >}}
> Activeer uw heel brein (L en R mode) door hersenspinsels neer te schrijven, mind maps te tekenen, gedachtenwandelingen te maken, en overal papier dichtbij te hebben.
##### Blink
{{< lib "Blink" >}}
> Leer ook te vertrouwen op uw intuïtie die constant oordelen velt zonder dat je je ervan bewust bent. Combineer dit met logisch denken, en regaeer dan pas!
##### Outliers
{{< lib "Outliers: The Story of Success" >}}
> Succesvolle mensen bouwen succes niet vanaf 0 op: culturele erfenis speelt een enorme rol, samen met het juiste "moment" waarop je je idee de wereld in wil brengen.
### Computer Related
##### Don't make me Think
{{< lib "Don't make me Think" >}}
> Eenduidige en eenvoudige navigatie is van extreem belang om mensen aandacht te laten vestigen op uw website.
### Environmental
##### The story of Stuff
{{< lib "The story of Stuff" >}}
> Reduce, reuse, and then recycle! Plastiek is énorm giftig en deze stoffen zitten reeds in ongeboren baby's!

188
content/wiki/books/mojo.md Normal file
View File

@ -0,0 +1,188 @@
+++
title = "mojo"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"mojo"
]
date = "2013-03-12"
+++
# Mojo
Auteur: Marshall Goldsmith<br/><br/>
{{< lib "Mojo how to get it|Librarything link" >}}
> Het is beter te springen dan geduwd te worden.
1. Marshall Goldsmith
### Jij en je Mojo
##### Wat is mojo?
De **positieve instelling**<br/><br/>
Waarmee we **nu iets doen**<br/><br/>
wat **van binnenuit** komt, <br/><br/>
en **naar buiten uitstraalt**.
##### Jou Mojo meten
Door middel van 2 pijlers:
* Professionele Mojo*
* Motivatie
* Kennis
* Kunde
* Zelfvertrouwen
* Oprechtheid
* Persoonlijke Mojo*
* Geluk
* Beloning
* Betekenis
* Lessen
* Dankbaarheid
Zie http://www.mojothebook.com/about-mojo-book/ voor de persoonlijke mojo score kaart in te vullen en details over elke pijler.
### De mojo-paradox
Onze standaardhouding in het leven is niet om *geluk* (korte termijn) of *betekenis* (lange termijn) te ervaren.<br/><br/>
Onze standaardhouding in het leven is om *inert* ((Embrace change hé)) te zijn.
Vraag u altijd af, op het einde van een dag bijvoorbeeld, bij *alle activiteiten* die je gedaan hebt:
1. Hoeveel voordeel of betekenis op lange termijn heb ik hiermee ervaren?
2. Hoeveel bevrediging of geluk op korte termijn heb ik hiermee ervaren?
De kracht van deze oefening is **zelfevaluatie**! Het vereist doorzettingsvermogen om dingen te veranderen.
> Ik ben wakker.
*- Boeddha*
### Ingrediënten van Mojo
#### Identiteit
1. Herinnerde identiteit: we bouwen verder op onszelf door ons activiteiten te herinneren van hoe we waren.
2. Weerspiegelde identiteit: Andere mensen herinneren zich gebeurtenissen over ons in het verleden.
3. Geprogrammeerde identiteit: Boodschappen die andere mensen uitzenden over wie je bent of wie je zult worden ((Brainwash stijl. Opvoeding, omgeving, werkdruk, ...))
4. Gecreëerde identiteit: waar we in de toekomst aan onszelf gaan werken
#### Presentatie
Pas op voor de **kloof tussen definities van prestaties** - tussen die van u en van anderen. Dit kan uw eigen mojo potentiëel negatief beïnvloeden.
De vraag "*Wat heb jij de laatste tijd bereikt?*" wordt vaak in ons gezicht gesmeerd, en we liegen meestal ook - doordat mensen hun eigen prestaties overschatten. Mensen denken vaak dat ze beter dan de gemiddelde persoon zijn.
#### Reputatie
*Wie denken mensen dat je bent?*. Ben je liever slim dan doeltreffend? Wil je gezien worden als iemand die dingen gedaan krijgt (doeltreffend) of als iemand die enorm goed formules kan bedenken maar er nooit iets mee doet?
Om een reputatie op te bouwen dien je je acties voldoende te **herhalen**. Het roer volledig omgooien stuurt de eerste 2-3 keer een volledig *verkeerd signaal* uit naar mensen die je vorige gedrag gewoon zijn. Mensen met een sterke mojo zijn een kei in het herhalen en na een tijd nemen mensen aan dat die persoon zo is.
#### Aanvaarding
**Leer loslaten**! Zie your brain @ work.
### Mojo-killers
1. Te veel hooi op de vork (leer nee zeggen!)
2. Wachten tot feiten veranderen (handel nu!)
3. Logica zoeken op de verkeerde plaatsen (probeer niet altijd alles te linken en er over na te denken!)
4. Klagen over de baas (zie aanvaarding)
5. Niet willen veranderen vanwege *sunk costs*
6. Vergeten in welke modus we zitten (val niet uit je "werk" rol als het te ontspannen bij collega's wordt)
> Verander jezelf of verander het
2. *Marshall Goldsmith*
### Identiteit: helder krijgen wie je bent
<img style='float: left; width: direct&500|px;' src='/img//books/mojo.jpg'>
#### Tool 1: bepaal welke maatstaven voor jou belangrijk zijn
Geen duidelijke doelen hebben, niet precies zijn, ... Allemaal killers.
Bepaal zelf wat jij belangrijk vindt en handel daarnaar.
#### Tool 2: zoek uit waar je woont
T.o.v. betekenis en geluk en onze dagelijkse activiteiten.
Zie http://www.mojothebook.com/about-mojo-book/ en de "mojo study" voor de mojo enquête. (zie image)
#### Tool 3: Wees de optimist van het stel
Optimisme is aanstekelijk. En belangrijker nog:
> Optimisme is brandstof voor verandering
2. *Marshall Goldsmith*
#### Tool 4: schrap één ding
Denk eens na over het dagelijks leven en schrap één essentiëel ding hiervan. Hoe zou jij je leven verder zetten zonder dat éne?
### Prestatie: maak het makkelijker om dingen gedaan te krijgen
#### Tool 5: bouw op met één steen tegelijk
> Een stapje met een keer!
1. *Bart Gauquie*
Vergeet niet 2 keer nee te zeggen en dán een keer ja.
#### Tool 6: beleef je missie ook in kleine momenten
Blijf met uw "missie" of groot doel in het achterhoofd handelen, ook op momenten waar je het niet verwacht, kleine dingen die grotere veranderingen teweeg brengen, kan het énorm handig zijn.
#### Tool 7: zwem in blauw water
Als de concurrentie te groot is (de vijver is al vol), schakel dan over naar een andere! Wees creatief!
### Reputatie: jouw eigen verhaal in handen nemen
#### Tool 8: wanneer blijven, wanneer weggaan
Gebruik bvb. de mojo scorekaart om te beslissen wat je wil veranderen aan je leven, of om die extra push te krijgen.
Vergeet niet dat zelf beslissen altijd beter is dan die door iemand anders te laten maken!
#### Tool 9: afscheid nemen
Weggaan doe je **altijd in stijl**. Punt aan de lijn.
#### Tool 10: gebruik een statistiek
Reclame voor mojoness...
#### Tool 11: verlaag dat percentage
*Welk percentage* van alle onderliggende communicatietijd wordt besteed aan
1. mensen die vertellen hoe slim, geweldig ze wel niet zijn of die luisteren naar iemand die dat doet of
2. mensen die vertellen hoe stom of ongeschikt iemand wel niet is, of die luisteren naar iemand die dat doet
Het antwoord is **65%**!
### Aanvaarding: verander wat je kunt veranderen, laat los wat je niet kunt veranderen
#### Tool 12: gebruik jouw invloed ook naar boven
Met name als verkoper trucjes ook toepassen op "de baas" om dingen gedaan te krijgen.
#### Tool 13: benoem het en beheers het
Zie your brain @ work
#### Tool 14: geef je vrienden een vrijbrief voor het leven
Het sleutelwoord is hier **vergeving**.

View File

@ -0,0 +1,300 @@
+++
title = "presentation_zen"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"presentation_zen"
]
date = "2013-03-12"
+++
# Presentation Zen
Auteur: Garr Reynolds<br/><br/>
{{< lib "presentation zen|Librarything link" >}}
Leonardo da Vinci:
> Eenvoud is de ultime perfectie
### Presenteren in de wereld van Vandaag
Algemeen idee:
* Teveel tekst in PowerPoint presentaties. Mensen nemen het niet op en raken er niet door geboeid. Resultaat: iedereen geeuwt en valt in slaap
* Bouw uw presentatie rond een geloofwaardig verhaal op met de nodige humor. Hou de slides als verduidelijking maar laat ze **niet** op zichzelf staan!
* Hou het kort. Bedenk wat dé boodschap is om over te brengen. Stel uzelf in plaats van de kijker. Maak het duidelijk, spreek met klare taal.
* Gebruik images om uw verhaal aan te sterken: mensen herinneren hun beter het doel afhankelijk van iets visueel. Maak daar gebruik van.
#### Opbouw presentaties in het conceptuele tijdperk
Bron: {{< lib "A whole new Mind" >}} van Daniel Pink. <br/><br/>
Zowel met L- als R geheugen leren werken in de nieuwe wereld, en de volgende "high touch" talenten spelen hierbij van groot belang:
##### 1. Ontwerp
1. Nooit bewust door de kijker laten opmerken
2. Handig gebruik maken van bijvoorbeeld de 1/3de regel in de fotografiewereld om iets in beeld te brengen
3. Hou rekening met contrast
4. Denk aan eenvoud: 1 of 2 plaatjes is voldoende, met maximum enkele woorden tekst.
##### 2. Verhaal
Feiten zijn in overvloed beschikbaar in deze informatieve wereld, een verhaal hierrond brengen wordt nauwelijks gedaan.
Studenten:
> *De effectiefste docenten zijn echter degenen die ware verhalen vertellen. Niet simpelweg de stof behandelen, maar er persoonlijkheid, karakter en ervarnig doorweven! *
##### 3. Symfonie
*"Het vermogen om schijnbaar niet-verwante stukjes te gebruiken om het totaalbeeld te vormen en te uiten"*
De beste presentatoren kunnen verbanden leggen die we misschien nog niet eerder legden. <br/><br/>
Zodra iemand op iets gewezen wordt, begrijpt hij ook effectief de stof (once you see it...)
1. Symfonie behelst dat we beslissen wat van belang is en de rest loslaten!
2. Betrekking op het gebruik van de héle geest (logica, analyse, synthese en intuïtie) om ons onderwerp zin te geven
##### 4. Empathie
1. U inleven in de kijkers om uw boodschap duidelijker en eenvoudiger naar voren te brengen
2. Nonverbale aanwijzingen van anderen leren begrijpen
##### 5. Spel
Bij veel praatjes kunnen speelsheid en humor er aanzienlijk toe bijdrage om een presentatie beter verteerbaar te maken. <br/><br/>
Dus niet presentaties lelijk, ingewikkeld en zo gedetailleerd mogelijk maken maar aantrekkelijk, eenvoudig en duidelijk!
##### 6. Betekenis
1. Iets nieuws onderwijzen dat zín heeft
2. Een "bijdrage" maken aan uw eigen wereld of alles rondom u. Mensen die naar uw presentatie luisterden die het zinloos vonden worden vaak gefrustreerd.
### Creativiteit en werken met Beperkingen
##### Begin met de kijk van een beginner
Quote van Zen meesters' "blik van een kind": fris, enthousiast, eindeloze mogelijkheden van ideeën en oplossingen<br/><br/>
Shunryu Suzuki:
> In de ogen van een beginner zijn er talloze mogelijkheden, in de ogen van een deskundige slechts een paar
##### U bent creatief
U bent altijd **creatief**!<br/><br/>
Ontdek dit in uzelf met {{< lib "If you want to Write" >}} van Brenda Ueland. Het boek had net zo goed "als u creatief wilt zijn" kunnen heten en is voor alle professionals die iemand iets willen bijleren essentiële leerstof.
Sir Ken Robinson (TED 2006):
> Als u niet bereid bent om fouten te maken, zult u nooit iets origineels bedenken.
##### De kunst om met beperkingen te werken
Met restricties werken wil niet zeggen dat het onmogelijk is om op een geweldig idee te komen!
T.S. Eliot:
> Binnen een strikt kader gedwonen wordt de verbeelding het zwaarst op de proef gesteld en zal hij haar rijkste ideeën produceren. Bij totale vrijheid gaat het werk algauw alle kanten op.
1. *Beperkingen zijn een krachtige bondgenoot in plaats van een vijand*!
2. Het is vaak van groot belang om uzelf beperkingen op te leggen om goed en creatief te kunnen werken.
Bijvoorbeeld: **[Pecha-kucha](http://www.pecha-kucha.org)** presentaties: 20 slides, 20 seconden elk = 6min40
### Analoog plannen
Benadrukken van het belang om weg van de computer te plannen. <br/><br/>
Als je ideeën hebt, kun je zonder machinerie veel doen. Zodra je die ideeën eenmaal hebt, begint de machinerie voor je te werken... Bij de meeste ideeën heb je niet meer nodig dan een stok in het zand.
:exclamation: Merk hier ook weer de agile software engineering/Getting Things done gelijkenissen op:
1. Noteer direct alles wat in je op komt (dus niet "who's got a good idea", zie GTD)
2. Braindump, mindmapping, ...
3. Werk met post-its op een bord om makkelijker te kunnen organiseren
4. Vaart minderen om het geheel te overzien: zie project planning bij GTD en de verschillende niveau's
##### De behoefte aan eenzaamheid
Dr. Ester Bucholz:
> Anderen inspireren ons, informatie voedt ons en oefneing doet ons beter presteren. Maar daarnaast hebben we rust nodig om dingen uit te zoeken, neiuwe ontdekkingen aan te dragen en originele antwoorden te bedenken.
Perioden van eenzaamheid zijn belangrijk om ons creatieve vermogen an te boren!
##### De juiste en verkeerde vragen stellen
Niet focussen op inhoud of te ver voorlopen op de feiten, gas terugnemen en eerst de volgende vragen beantwoorden:
* Hoeveel tijd heb ik?
* Hoe ziet de zaal er uit?
* Op welk tijdstip van de dag vindt mijn presentatie plaats?
* Wie zijn de toeschouwers, wat is hun achtergrond?
* Wat verwachten ze van de presentatie?
* Wat wil ik dat ze doen?
* Waarom hebben ze me gevraagd om te spreken?
* Wat is hét doel van mijn praatje? Welk verhaal hoort hierbij?
* **Wat is mijn absoluut centrale stelling**?
Komt eropneer: 1) wat wil ik zeggen 2) waarom is dat belangrijk.<br/><br/>
Twee dingen kunnen u daarbij helpen:
1. "Dakari Nani" (wat dan nog?) - constant uzelf vragen "wat wil je daarmee zeggen" tijdens voorbereiding
2. De lifttest: Tussen naar lift gaan en naar garage gaan voor auto moet je je doel verkocht krijgen aan een persoon.
##### Hand-outs kunnen u de handen vrij geven
Deel nooit kopieën uit van uw dia's, die kunnen nooit **op zichzelf staan**! Dias versterken uw verhaal, handouts bevatten uw verhaal en meer details.<br/><br/>
Het is dus belangrijk om beide zaken op te splitsen! Vermijd te mixen!
### Het verhaal smeden
##### Wat zorgt ervoor dat een boodschap blijft hangen?
* Eenvoud: Als alles belangrijk is, is niets belangrijk!
* Onverwacht: Verrassing zal aandacht trekken
* Concreet: gebruik spreektaal en geef echte voorbeelden
* Geloofwaardig: statistische gegevens hebben geen enkel nut, hun context waarin dit van belang is wel!
* Emotie: Laat mensen iets *voelen*, speel hierop in.
* Verhaal: mensen communiceren al eeuwen lang door middel van verhalen.
##### Het proces
1. Brainstorming
2. Groeperen en de kern bepalen, één thema centraal laten staan
3. Werk met een storyboard zonder PC en verwerk de gegevens van stap 2 op notes
4. Werk met een storyboard op PC: in de diasorteerweergave/tabelweergave van PowerPoint.
##### Bewerkingen en beperkingen
Knip onnodige zaken van uw verhaal om het zo effectief mogelijk te maken! Hou mensen niet langer dan nodig bezig met uw presentatie. <br/><br/>
Laat bij twijfel direct iets weg. Editeer alles vastbesloten als de eerste draft af is.
### Waarom eenvoud zo belangrijk is
Samen met andere grondregels zoals beperking en natuurlijkheid is eenvoudig in Zen en de Zen-kunsten een sleutelbegrip. Toepassingen zoals theeceremonies((Sado staat voor de Japanse theeceremonie)), haiku, ikebana en sumi-e. enkele begrippen hieruit zijn:
##### Kanso (eenvoud)
Schoonheid en visuele elegantie worden teweeggebracht door alle overbodigheid weg te laten.
##### Shizen (natuurlijkheid)
Verhindert het gebruik van uitgebreide ontwerpen en oververfijning. (beperking dus weer)
##### Shibumi (elegantie)
Elegante eenvoud en helder uitgedrukte bondigheid - ingehouden elegantie. <br/><br/>
Voor meer opvattingen over schoonheid, zie **Wabi-Sabi**: armoede (afwezigheid van materiële rijkdom) en eenzaamheid.
Scott McCloud:
> Door een afbeelding tot zijn essentiële betekenis terug te brengen kan een ontwerper die betekenis versterken.
Hoofdboodschap: *Versterk door te vereenvoudigen*! <br/><br/>
Leer bijvoorbeeld van de kunst van het striptekenen: {{< lib "Understanding comics: the invisible art" >}} (Scott McCloud).
Pas op: eenvoud is niet gemakkelijk en kost meestal méér tijd in plaats van het meestal gedachte minder ("rap iets weglaten, kkdone")
### Presentaties ontwerpen
Algemene ontwerpprincipes, ook zonder designer achtergrond, kan je terugvinden in {{< lib "The non-designer's design book" >}} (Robin Williams)
##### Signal-noise ratio
De vereenvoudiging tussen relevante en irrelevante informatie op een slide. Vaak te drukke slides, te veel contrast zodat het belangrijkste element niet goed in beeld komt, ... Het probleem schuilt meestal in een heel klein hoekje: maak alle visuele aanpassingen zo subtiel mogelijk. Zie {{< lib "Visual Expectations: images and quantities" >}} (Edward Tufte)
Vermijd ook "fancy 3D effectjes" toe te passen, grafieken zijn in hun 2D-vorm duidelijker en makkelijker te interpreteren.
:exclamation: Geen logo's op elke dia! Eerste & laatste dia met bedrijfslogo. De rest vormt ruis!
##### Het beeldsuperioriteitseffect
Vul uitgesproken worden beter aan met foto's, beelden, metaforen, ... <br/><br/>
{{< lib "Going visual: Using images to enhance productivity, decision-making and profits" >}}: gebruik visuele beelden om uw verhaal te vertellen!<br/><br/>
Gebruik het hele scherm voor uw afbeelding, zonder mensen af te leiden met default achtergrond van dia's.
Werken met citaten die in de context van uw verhaal van toepassing zijn werken ook effectief.
##### Lege ruimte
Daisetz Suzuki:
> Leegheid die abusievelijk als louter niets doen kan worden begrepen, is in feite het reservoir van oneindige mogelijkheden.
Lege ruimten impliceren elegantie en klaarheid. Dat geldt zowel voor grafische ontwerpen als voor interieur design.<br/><br/>
Herinner uzelf eraan dat het niet nodig is om alle woorden die je uitspreekt ook op een dia te plakken!
Denk hier aan het evenwicht tussen lege ruimtes, woorden en afbeeldingen.
##### Rasters en de 1/3de regel
Bekijk de "compositie" van uw dia op dezelfde manieren als fotografen hun onderwerp willen vastleggen. <br/><br/>
Hiermee schept u samenhang en estethische kwaliteit.
##### De grote 4
* Contrast: sterke dynamische verschillen vastleggen die onderdelen afscheiden
* Herhaling: bevordert de eenheid en oderlijkheid van uw dia's
* Uitlijning: visueel koppelen via onzichtbare lijnen
* Nabijheid: bij elkaar horende onderdelen groeperen.
### De kunst om volledig aanwezig te zijn
David Bader:
> Wees nu hier aanwezig. Wees later ergens anders. Is dat zo moeilijk?
Focus leggen en concentratie daar laten liggen tijdens het geven van de presentatie is belangrijk!<br/><br/>
Het publiek merkt op als je "opgaat" in je eigen presentatie, of niet weet over wat het gaat. Daarom: **Blijf met uw gedachten bij uw onderwerp**!
Zen principe: *mindfulness*, een verhoogde mate van aandacht. (Referentie GTD e.a.: "flow state of mind")
##### De geest die geen geest is
"Mushin no Shin", een zwaardvechter die volledig in het moment aanwezig is met een *lege geest*. Hij denkt niet na over hoe hij moet zwaardvechten. Op die manier verandert zowel het zwaard als de zwaardvechter in een instrument in de handen van het onbewuste (intuïtie, Dreyfus level5). Zie {{< lib "Zen and Japanese Culture" >}} door Daisetz Suzuki. Het is **het onbewuste dat wonderen van creativiteit verricht**.
Daisetz Suzuki:
> De wateren zijn voortdurend in beweging, maar de maan behoudt zijn sereniteit. De geest beweegt als reactie op tienduizend situaties, maar blijft altijd hetzelfde.
Referentie GTD "mind clear as water"!
##### Leren van Judo
1. Observeer uzelf en uw situatie zorgvuldig, observeer anderen en uw omgeving zorgvuldig
2. Neem het initiatief bij wat u onderneemt
3. Weeg ten volle af en handel besluitvaardig.
4. Weet wanneer u moet stoppen.
5. Blijf in het midden.
Dit zijn 5 judoprincipes besproken in {{< lib "Budo Secrets" >}} (John Stevens), makkelijk overal toepasbaar.
##### Hara Hachi Bu
"Eet tot je 80% vol bent", een Japans principe.<br/><br/>
Ook toepasbaar op presenteren: hou het kort, laat mensen ietwat hongerig achter, verlangend naar meer. Zorg zo dat ze bijvoorbeeld:
* Effectief je hand-out ook lezen
* Eventueel meer opzoekingswerk doen over het onderwerp en bijgevolg
* **Geïnspireerd raken**!
##### Laat de lichten aan
Het publiek moet u altijd kunnen zien. Sta centraal, en niet achter een bureau te klikken/prullen met de presentatie laptop!
### Hoe u zich kunt verbeteren
Dingen om te doen om een betere presentator (of algemener) te worden:
##### Lees en bestudeer
Lees boeken, bekijk documentatie, zoek relevante onderwerpen, ...
http://www.presentationzen.com bevat 75+ referentieboeken.
##### Doe het
Zelfstudie alleen is meestal niet genoeg. Het effectief ook doen helpt enorm!
##### Oefen uw "rechter"-hersenhelft
Verwaarloos uw passies en talenten niet door uw werk op voortouw te nemen. Ga uw gevoel achterna.
##### Ga erop uit
Er zullen nooit fantastische dingen gebeuren als u in uw luie stoel blijft zitten. Leg contacten, trek erop uit, daag uzelf uit en ontwikkel uweigen creativiteit.

View File

@ -0,0 +1,126 @@
+++
title = "productive_programmer"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"productive_programmer"
]
date = "2013-03-12"
+++
# The Productive Programmer
Author: Neal Ford<br/><br/>
{{< lib "Productive programmer|Librarything Link" >}}
Dit is een samenvatting van alle **notes** in essentie, opgedeeld per hoofdstuk.
## Part 1: Mechanics
### Acceleration
* Concentrate on essence, not ceremony.
* The usefulness of an application list is inversely proportional to its length.
* Eye candy looks goot but isn't nutritious.
* Typing is faster than navigation.
* Prefer typing over mousing.
* The address bar is the most efficient Windows interface.
* Take the time to learn all the hidden keyboard shortcuts of your universe.
* Context switching eats time.
* Clipboarding to batches is faster than clipboarding serially.
* Those who remember their history aren't doomed to type it again.
* Embedded command prompts give you access to the best of both worlds.
* Embed the command prompt to make it easier to switch contexts.
* When coding, always prefer the keyboard to the mouse.
* Learn the IDE keyboard shortcuts in context, not by reading long lists.
* When you type a complicated construct for the second time, templatize it.
* For any symmetric operation on multiple lines of text, find a pattern and record a macro.
* The more times you perform a particular operation on a chunck of text, the greater the likehood you'll do it again.
* Don't type the same command over and over again.
* Spend a little time each day to make every day more productive.
<img style='float: left; width: nolink&|px;' src='/img//books/angry_monkeys.png'>
### Focus
* The higher the level of concentration, the denser the ideas.
* THe bigger the haystack, the harder it is to find the needle.
* Replace file hierarchies with search.
* Try simpler searching before resorting to "hard target" searching.
* Take advantage of built-in focus facilities like colors.
* Use links to create virtual project management folders.
* Virtual desktops unclutter your stacks of windows.
### Automation
* Use tools out of their original context when appropriate.
* Don't spend time doing by hand what you can automate.
* Performing simple, repetitive tasks squanders your concentration.
* Finding innovatige solutions to problems makes it easier to solve similar problems in the future.
* Timebox speculative development.
### Canonicality
* Keep a single copy of everything you don't build in version control.
* Use indirection to create friendlier workspaces.
* Use indirection to keep your life in sync (symlinks).
* No matter what you are copying and pasting, reuse by copy and paste is evil.
* Use virtualization to canonicalize dependencies for your projects.
* Don't let object-relational mapping tools violate canonicality.
* Add behavior to generated code via extention, open classes or partial classes.
* Always keep code and schemas in sync.
* Use migrations to create repeatable snapshots of schema changes.
* Out-of-date documentation is worse than none because it is actively misleading.
* For managers, documentation is about risk mitigation.
* Always keep "living" documents.
* Anything that takes real effort to create makes its creator irrationally attached to it.
* Whiteboard + digital camera > CASE tools.
* Generate all the technical documents you can.
* Never keep two copies of the same thing.
* Repetition is the single most diminishing force in software development.
## Part 2: Practice
### Statistic analysis
* Statistic analysis tools represent cheap verification.
### Good citizenship
* Don't create global variables, even the object kind.
### YAGNI
* Don't pay complexity tax unless you absolutely must.
* Software development is first and foremost a communication game.
### Ancient philosophers
* Maximize work on essential complexity; kill accidental complexity.
* Even general-purpose programming languages suffer from the "80-10-10" rule.
* Pay attention to the lore of "ancient" technologies. (Smalltalk lol)
### Meta-programming
* Meta-programming changes your syntactic vocabulary, giving you more ways to express yourself.
### Composed method and SLAP
* Refactoring to composed method reveals hidden reusable code.
* TDD predisposes composed method.
* Encapuslate all implementation details away from public methods.
### Find the perfect Tools
* Find your perfect editor and learn it inside and out.
* Record macros for all symmetrical text manipulations.
* Good knowledge of regexp can save orders of magnitude of effort.
* Don't make round trips when you can batch.
* Use a "real" scripting language for automation chores.
* Keep behavior in (testable) code.
* Pay attention to the evolution of your tools.
* Pay as little complexitax as you can.

View File

@ -0,0 +1,29 @@
+++
title = "purplecow"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"purplecow"
]
date = "2013-03-12"
+++
# Purple Cow: Transform Your Business by Being Remarkable
### Crossing the Chasm
{{< wp "Crossing the Chasm" >}}
<img style='float: left; width: direct&800 |px;' src='/img//books/crossing-the-chasm.png'>
Focus op **Early Adopters** in plaats van "majority"! Waarom?
1. Die mensen geven vroeg feedback
2. Zijn de "niezers" die andere mensen besmetten via mond-op-mond reclame "kijk wat voor iets nieuws ik heb en hoe goed het werkt". Binnen de majority groep is zo niets dat zijn allemaal slechts volgers, en tegen dan is het product "uitgebold".
3. Op dat moment heeft het product nog de meeste waarde.
*Late majority* = Gebaseerd op ervaring van anderen.

View File

@ -0,0 +1,53 @@
+++
title = "quiet"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"quiet"
]
date = "2013-09-17"
+++
# Quiet
> It's not that I am more intelligent, it's that I stay with problems Longer. (A. Einstein)
## Persoonlijkheden in de wereld
### Introverten
1. Energie halen uit alleen zijn, boek lezen, wandelen in bergen, ...
2. Introvert <> niet sociaal, ze zoeken even veel toenadering als anderen, maar dan minder frequent of in (zeer) kleine groepen.
3. Heeft het moeilijk om zijn mening te uiten in grotere groepen, wordt snel overweldigd
4. Hebben veel meer natuurlijke volhouding (zeer fel focussen en toeleggen op 1 probleem)
5. Man of contemplation
6. stress van bvb tornooien bij wedstrijden, tov "anoniem" presteren, gaat beter
### Extraverten
1. Superjoviaal
2. Houdt van netwerken, feestjes, ...
3. Neemt natuurlijkerwijs het voortouw, ongeduldig t.o.v. mening van introverten
4. Man of action
5. Energie halen uit mensen rond hem
6. Haalt juist energie uit het feit dat hij "bekeken" wordt bij wedstrijden (sommige atleten hebben dit net nodig)
### Ambiverten
1. Kunnen beide vormen aan
2. Opgelet met verschil tussen introvert die zich gedraagt als extravert (bvb op werk), haalt energie naar beneden
Ben je een ambivert? Doe de test: http://www.danpink.com/assessment/
> There is no such thing as a pure introvert or extrovert. Such a person would be in the lunatic asylum. ~ Carl G Jung
Denk je dat je een ambivert bent? Beantwoord deze vraag eens:
> “would you prefer to go to a party or read a book?” My first thought was “Depends on the party or book and also how tired I am from the previous night.” But that contextual option wasnt available. Now I realize what a gift it is to be sensible, reasonable and well balanced enough to have the freedom of choice.
Als jij altijd, 100% voor het boek zou gaan ben je een introvert die zich als extravert gedraagd op gelegenheden.
Zie ook http://lonerwolf.com/ambivert/

View File

@ -0,0 +1,278 @@
+++
title = "rework"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"rework"
]
date = "2013-03-12"
+++
# Rework
Author: Jason Fried & David Heinemeier Hansson<br/><br/>
Context: Pragmatic project/company management
{{< lib "Rework|Librarything Link" >}}
## Takedowns
1. Ignore the real world
* Hoofd niet laten hangen als iedereen beweert dat het onmogelijk is, niet geloven!
* Allemaal excuses om het niet te proberen, heeft niets met u te maken.
1. Learning from mistakes is overrated
* Het is bewezen dat mensen die succes hebben een grotere kans op succes hebben in de toekomst
* "Learn by mistake" is dus niet altijd 100% correct
1. Planning is guessing
* Het heeft geen nut om lange termijn plannen op te stellen
* Plan wat uitmaakt op korte termijn, vandaag! Hou op met gokken
* Promoot adaptability/agility, pas u aan op het moment zelf
1. Why grow?
* Groter worden als bedrijf brengt enorm veel nadelen met zich mee
* *Small is not just a stepping stone. Small is a great destination itself.*
1. Workaholism
* Overwerken heeft geen nut, lack of focus, lack of concentration
* Mensen voelen zich verplicht om te blijven en boeken 0 vooruitgang.
1. Enough with "enterpreneurs"
## GO
<img style='float: left; width: nolink&|px;' src='/img//books/rework_enthousiasm.png'>
1. Make a dent in the universe
* Zorg voor een gevoel van verschil
* Aim voor *"This makes my life better"* van de klant uit
* Voor het idee uit, "heb" het niet alleen.
1. Scratch your own itch
* Als er nood is aan een tool intern, maak die dan voor uzelf en verkoop ze daarna!
* Vergroot de band met wat je zelf maakt, is nuttig en vereist minder werk.
1. Start making something
* *Until you start actually making something, an idea is just an idea. And everyone's got one of those*
* Stop met zagen, start met werken!
1. No time is no excuse
* Start met kleine beetjes tijd hier en daar vrij te maken, en aan het idee te werken
* Het perfecte moment zal er nooit zijn!
1. Draw a line in the sand
* Heb een sterke meningsuiting, een sterke visie, en ga nooit over die streep!
* Bvb. nee zeggen tegen de klant als uw bedrijf staat voor eenvoud in gebruik
1. Mission statement impossible
* *Standing for something isn't just about writing it down. It's about believing it and living it.*
1. Outside money is plan Z
* Gefinancierd worden is een enorm slecht idee en heeft veel nadelen en constraints! Gebruik enkel als laatste optie!
1. You need less than you think
* Tegenwoordig is alles dat vereist is een laptop en een plaats om te werken.
* Laat u niet tegenhouden door zogezegde énorme (hardwarematige) requirements. Allemaal voor niets nodig.
1. Start a business, not a startup
2. Building to flip is building to flop
* *You need a commitment strategy, not an exit strategy!*
* Denk nog niet na over hoe quitten zonder verlies of in beslagname van x of y.
1. Less mass
* Enorm veel dingen weerhouden u van actueel werk:
* Lange termijn contracten
* Te veel werknemers
* Meetings
* Politiek
* Lange termijn plannen
* ...
## Progress
1. Embrace constraints
* Minder resources zetten u aan om met beperkte middelen toch iets te realiseren!
* Bart meldde dit voor hij het boek zelf las! Ook overal anders op toepasbaar. => Wekt creativiteit op (hacken iemand anders zijn code)
* Legt weer nadruk op less mass.
1. Build half a product, not a half-assed product (zie onder)
2. Start at the epicenter
* Neem houvast aan het *core concept*, en breid vanaf daar uit
* Alles in scope pakken is onmogelijk! Release early promoot de houvast aan uw core domein.
1. Ignore the details early on (zie boven)
2. Make the call is making progress
* Beslissingen uitstellen heeft geen zin, ze worden dan snel en zonder nadenken afgehandeld.((Komt ook weer terug bij Power Thinking))
* Swap *Let's think about it* voor *Let's decide about it*!
1. Be a curator
2. Throw less at the problem
* *When things aren't working, cut back*. Gooi niet meer geld en resources tegen een probleem aan, maar juist minder.
* Zo werkt in principe XP ook: wanneer er meer werk is, werk dan minder lang, ipv overuren te maken (zie eerder ook weer)!
1. Focus on what won't change
* Probeer minder rekening te houden met fancy dingen die *hot & new* zijn. Focus op substance ipv fasion.
* Focus op permanente features ipv dingen die na verloop van tijd hun stijl verliezen.
1. Tone is in your fingers
* Het maakt niet uit welke tools gebruikt worden, hoe high-end ze ook zijn! Met kladblok bereik je evenveel!
1. Sell your by-products
* Het is onmogelijk om juist 1 ding te maken. Verkoop ook bijproducten die een gevolg zijn van het maken van 1 ding.
1. Launch now
* Release early ((Agile referentie #4556)).
* Focus on core (zie vroeger), fancy effecten is bijzaak. Gebruik de deadline, verschuif het niet!
## Productivity
1. Illusions of agreement
* *The business is littered with dead documents that waste people's time* ((XP referentie #4557))
* Stop met abstractions zoals rapportjes en documentjes maken voor niks.
1. Reasons to quit
* Vraag u op tijd af of het de moeite is om te doen wat er gedaan wordt:
* Is het wel handig?
* Voegt het een waarde toe?
* Verandert dit het gebruik?
* Is het makkelijker op te lossen?
* Wat zou je in de plaats beter kunnen doen?
* Is het echt de moeite?
1. Interruption is the enemy of productivity
* No-brainer. Gebruik bvb een SPOC ((Single point of Contact)) voor interruptions af te leiden. Introduceer no-talk day, ...
1. Meetings are toxic
* Bijna alle meetings verknoeien kostbare tijd die je beter aan iets ander spendeert.
* Indien toch nodig:
* Nodig zo weinig mogelijk mensen uit
* Zet een timer EN GEBRUIK DIE!
* Duidelijke agenda punten.
* Begin met specifieke problemen en eindig met duidelijke doelstellingen ((Zoals een Retrospective dus))
1. Good enough is fine
* *The easiest thing that could possibly work*
1. Quick wins
* Concreet: release in kleine stukken, en enorm vaak in plaats van een lang plan te hebben en nooit iets te geven aan klanten
1. Don't be a hero
* Stop op tijd met iets dat te veel tijd in beslag neemt in plaats van "door te bijten" dat niet de moeite is.
1. Go to sleep (zie eerder)
2. Your estimations suck
* nog maar eens: deel op in kleine stukken en schat die individueel, dan is er een veel kleinere afwijking dan grote dingen inschatten.
1. Long lists don't get done
* Door bvb. backlog beperkingen uit te voeren. Focus op core, ...
1. Make tiny decisions (zie eerder)
## Competitors
1. Don't copy
* Kopiëren is een formule om te **falen**! Iets overnemen zonder te begrijpen wat er staat is compleet nutteloos.
* Zorg voor inzicht en neem dan over, maar nooit letterlijk. Laat u beïnvloeden, maar steel niet.
1. Decommoditize your product (*Pour yourself into your product*)
2. Pick a fight
3. Underdo your competition
* *Cold War mentality is a dead end*
* Productne die hopelos iets anders proberen na te bootsen zijn al op voorhand gedoemd om te falen (zie eerder)
1. Who cares what they are doing?
* Focus u niet op anderen maar op uzelf!
## Evolution
1. Say no by default
* Leer om nee te zeggen tegen klanten. Mensen zeggen standaard ja omdat ze schrik hebben om confrontaties aan te gaan.
* Op die manier merk je sneller wat klanten écht wensen.
1. Let your customers outgrow you
* Customize nooit één product volledig gericht op één klant. Graaf zo niet uw eigen graf!
1. Don't confuse enthousiasm with priority
* Een fijntje speciaal voor mij. Een idee kweekt enorm **(te) veel enthousiasme** en de neiging om alles te laten vallen en dat te implementeren is groot.
* Focus op prioriteiten en de core in plaats van nice to haves!
1. Be at-home good
* Probeer iets te maken wat klanten imponeert, ook als ze thuis zijn in plaats van in de winkel (door te focussen op wawzomg toeters en bellen)
1. Don't write it down
* Request trackers zijn niet nodig, vergeet af en toe wat de klant wilt.
* Wanneer het echt belangrijk is komt het terug en kan het niet meer vergeten worden. Zo filter je het belangrijkste van de nice-to-have zaken beter.
## Promotion
1. Welcome obscurity
* Niet bekend zijn als bedrijf geeft u de kans om nieuwe dingen te proberen - als dit mislukt maak het toch niet uit. Blijf tweaken en inventen!
* Als 1 miljoen mensen uw product gebruiken spreken we over iets totaal anders.
1. Build an audience
* Doe geen beroep op advertenties om klanten te lokken. Doe beroep op een publiek dat naar u komt in plaats van andersom.
* Concreet bvb een blog bijhouden en discussies over design starten, zodat mensen terug komen om te zien wat jij als bedrijf te vertellen hebt.
1. Out-teach your competition
* Outselling the competition gaat nooit lukken, zeker niet als klein bedrijf. En daar win je geen vertrouwen mee.
* Door op te leiden leert men zelf ook veel ((pragmatic thinking & learning referenties zijn er ook ja))
1. Emulate chefs
* chefs delen hun beste recepten met anderen. Als bedrijf moet knowledge ook geshared worden! ((Wikis met kennis?))
* Bedrijven doen meestal paranoïde en geheim, dat is bullshit. Een recept is kopiëerbaar, een bedrijf niet.
* Heb een persoonlijk "kookboek" als bedrijf dat uw visie en geheimen deelt!
1. Go behind the scenes
* Laat mensen zien hoe jij als bedrijf werkt, toon dat in het juiste licht en maak het interessant.
1. Nobody likes plastic flowers
* *Leave the poetry in what you make. When something becomes too polished, it loses its soul. It seems robotic*
* Toon uw tekortkomingen als bedrijf. Niemand houdt van "suits" die elke dag er hetzelfde uitzien met hun kravat.
1. Press releases are spam
* Coverage door middel van pers is vervelend, subjectief en kost geld. Probeer mensen persoonlijker te bereiken.
* *Be remarkable. Stand out.*
1. Forget about the Wall Street journal
2. Drug dealers get it right
* Maak het product zo goed dat mensen altijd terug komen. Geef een vinger en ze willen een hele arm. Ga daarvoor.
1. Marketing is not a department
* Iedereen doet aan marketing door te communiceren! Gebruik al die kleine momenten in plaats van een aparte "afdeling".
1. The myth of the overnight sensation (slow measured growth > overnight success)
## Hiring
1. Do it yourself first
* Huur nooit iemand in voor iets dat ge zelf nooit gedaan hebt. Zo kunt ge beter dat werk inschatten en afstemmen.
* Probeer eerst te leren!
1. Hire when it hurts
* Meestal kan aanwerving uitgesteld worden, probeer zo lang mogelijk zonder vol te houden.
1. Pass on great people
* Ook al is iemand zijn CV wowdemax, neem niemand aan als er geen extra werk is en er geen volk nodig is!
* Werfreserves = zever.
1. Strangers at a coctail party
* Huur aan een trage rate aan, zodat mensen elkaar heel goed kennen en ge weet hoe ver ge met werknemers kunt gaan.
* Een sfeer die je niet wil op het bedrijf: smalltalk (at a coctail party), maar voor de rest niet durven communiceren.
1. Resumés are ridiculous
* Huur afhankelijk van brieven in plaats van CVs!
1. Years of irrelevance
* Het verschil tussen iemand met 6 maand en 6 jaar ervaring is meestal kleiner dan verwacht.
* Het echte verschil ligt hem in de individuele dedicatie en intelligentie.
1. Forget about formal education (zever, gezever)
2. Everybody works
* Mensen die werk delegeren zijn nutteloos
1. Hire managers of one
2. Hire great writers
* Onafhankelijk van het type van job, indien een keuze is, huur de beste schrijver.
1. The best are everywhere (geo-onafhankelijk)
2. Test-drive employees
* Probeer iemand in te huren voor een klein project, bvb iets van 24h, en evalueer het resultaat.
## Damage control
1. Own your bad news
* Het slechte nieuws brengen doe je nog altijd het beste zelf!
* Wees eerlijk en persoonlijk
1. Speed changes everything
* Callcenters + holdtime = lol - geef klanten zo snel mogelijk feedback! Ook bij negatieve zaken.
* Dit verandert de perceptie van de klant zelf
1. How to say you're sorry
* Niet "wij excuseren ons voor het ongemak dat dit kan gekost hebben" maar "het spijt MIJ want [eerlijke en geldige reden]"
* Personaliseer excuses!
1. Put everyone on the front lines
* Hoe meer stappen tussen klanten contact en developers, hoe groter de kans dat iets verloren gaat! ((Wink naar proxies))
* Probeer zo veel mogelijk mensen in contact met de klanten te zetten
1. Take a deep breath
## Culture
1. You don't create a culture
2. Decisions are temporary
* Maak geen problemen die er nog niet zijn in realiteit. Beslissingen die vandaag worden genomen hoeven niet voor altijd te gelden!
* *The ability to change course is one of the big advantages of being small.*
1. Skip the rock stars
2. They're not thirteen
* Behandel werknemers met gespect en geef ze vrijheid. Veel regels opleggen = werkresultaten van iemand van 13 terugkrijgen.
1. Send people home at 5 (zie vroeger)
2. Don't scar on the first cut
* Leg niet direct policies vast als één werknemer iets heeft foutgedaan. Dit brengt de rest ook in een negatief daglicht.
1. Sound like you
* Bedrijfspropaganda en emails moeten niet in 3de persoon geschreven worden, in ingewikkelde academische taaltjes.
* Communiceer zoals je tegen je vrienden praat!
1. Four-letter words
* Vermijd:
* Need - weinig dingen moeten gedaan worden
* Can't - alles kan!
* Easy - *easy is a word to describe other people's jobs*
* Fast - Alles moet snel gebeuren...
* *"We need to add this feature now. We can't launch without, everyone wants it. It's only a little thing so It'll be easy and done fast"* -> full of fail
1. ASAP is poison (zie vermijd snel)
## Conclusion
1. Inspiration is perishable
* Iedereen heeft ideeën, maar inspiratie komt met vlagen. Pak het met beide handen vast en gebruik het op dat moment!
* Inspiratie vervliegt. Op het juiste moment aan het idee werken verzet meer werk dan een week in een dag.

View File

@ -0,0 +1,137 @@
+++
title = "wanted"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"wanted"
]
date = "2013-03-12"
+++
~~NOTOC~~
# Wanted lijstje: BOEKEN
<img style='' src='/img/page>books/wantedfeed&noheader'>
### Fictie
#### Nieuwe series
* Steve Jackson, Ian Livingstone: {{< lib "The Warlock of Firetop Mountain" >}} (spelboek)
* Robin Hobb: {{< lib "Boeken van de Zoon van de Krijger" >}} series
* Robin Hobb: {{< lib "Boeken van de Zieners" >}} series
* Een compendium van échte unaltered verhalven van de Gebroeders van Grimm ("volwassenen" versie)
#### Incomplete series
* Naomi Novik: {{< lib "Temeraire" >}} boek 4
* Sarah Ash: {{< lib "De tranen van Artamon" >}} boek 3
* Lynn Flewelling: {{< lib "The Oracle's Queen" >}} De Tamir trilogy deel 3
### Comics
Comic shops:
1. Mechelsestraat Leuven: http://gobelijn.be/
2. Lazerijstraat Hasselt: Wonderland
#### Fantasy
* {{< lib "Bone: One Volume Edition" >}}
* {{< lib "The Walking Dead compendium" >}}
* {{< lib "Foiled" >}} (schermen, anime)
* {{< lib "The wonderful Wizard of Oz" >}} (Marvel Comics)
#### Actualiteit
* {{< lib "The kolndike" >}} (canadese goldrush)
* {{< lib "Das Kapital" >}} (politieke economie in Duitsland)
* {{< lib "Persepolis Complete" >}} (moslim vrouw opgroeiend in westerse wereld)
* {{< lib "Asterios Polyp" >}} (dualiteit man/vrouw in relatie met kleur, Griekse Mythes)
* {{< lib "The Burma Chronicles" >}} en {{< lib "Pyongyang: A Journey in North Korea" >}} e.a. (reizen, Azië)
* {{< lib "American born Chinese" >}} (opgroeien, conflict, cultuur)
* {{< lib "The Imposter's daughter" >}} (opgroeien, relatie ouders)
* {{< lib "Why I killed Peter" >}} (opgroeien, mishandeling)
### Non-Fictie
Zie http://www.goodreads.com/review/list_rss/5451893?key######08aaee59aeca7ff53af2daae06569683a78b0dc4&shelf%23ALL%23 !
#### Self-awareness
*Prioriteit 1*
* Patterson, Grenny: {{< lib "Change Anything" >}}
* Mihalyi Czikszentmihalyi: {{< lib "Flow: The Psychology of Optimal Experience" >}}
* David Allen: {{< lib "Getting things Done" >}}
* Sir Ken Robinson: {{< lib "Out of Our Minds: Learning to be Creative" >}}
* Seth Godin: {{< lib "Linchpin: Are You Indispensable?" >}}
* Simon Sinek: {{< lib "Start with Why: How Great Leaders Inspire Everyone to Take Action" >}}
* Dan Gilbert: {{< lib "Stumbling on Happiness" >}}
*Prioriteit 2*
* Jeff Hawkings: {{< lib "On Intelligence" >}}
* Jeffrey Swhartz: {{< lib "The Mind and the Brain: Neuroplasticity and the Power of Mental Force" >}}
* Cordelia Fine: {{< lib "A Mind of Its Own: How Your Brain Distorts and Deceives" >}}
#### Voedsel en Koken
* Peter Reinhart: {{< lib "The Bread Baker's Apprentice" >}}
* Gary Taubes: {{< lib "Good calories, bad Calories" >}}
* Phillipe Van Den Bulck: [Verassend Veggie](http://www.bol.com/nl/p/nederlandse-boeken/verrassend-veggie/1001004007615854/index.html)
*
#### Work
*Prioriteit 1* (Zeker kopen en lezen)
* {{< lib "Structure and Interpretation of Computer Programs" >}}
*Prioriteit 2* (Waarschijnlijk lezen, via werk bestellen?)
* {{< lib "The Element: How Finding Your Passion Changes Everything" >}} - Sir Ken Robinson
* {{< lib "The Passionate Programmer: Creating a Remarkable Career in Software Development" >}}
* {{< lib "Dinosaur Brains: Dealing with all those impossible people at work" >}}
* {{< lib "jquery: novice to ninja" >}}
* {{< lib "Javascript: the good parts" >}}
* {{< lib "The land of Lisp" >}}
*Prioriteit 3* (Misschien/ooit)
* {{< lib "Just Enough Software Architecture: A Risk-Driven Approach" >}} - via Ronald, nog te bekijken of het de moeite is?
* {{< lib "Compilers: Principles, Techniques, and Tools" >}}
* {{< lib "Gödel, Escher, Bach: An Eternal Golden Braid" >}}
* {{< lib "Agile Modelling" >}}
* {{< lib "Information Overload - A System for Better Managing Everyday Data" >}} (Guus Pijpers, co-auteur Lifehacking tips boek)
Zie http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read
#### Random onderwerpen
* {{< lib "The Fabric of the Cosmos|The Fabric of the Cosmos, Space, Texture and Reality" >}} (zie Imagining the 10th dimension, zelf minder goed)
##### Evolutieleer
* {{< lib "The Selfish gene" >}} door Richard Downkins (+ analogie goede ideeën, ref. onrechtstreeks via *Where good ideas come from* dankzij Tom)
### Boekenlinks
#### Winkels
Boeken online te koop:
1. http://www.abebooks.co.uk/ (2dehands, Engels) <br/><br/>
2. http://www.amazon.co.uk/ (Engels, gratis verzending > £25) <br/><br/>
3. http://www.proxis.be/ (Technisch) <br/><br/>
4. http://www.bookdepository.co.uk/ (Free delivery worldwide, Engels)
#### Reviews, community sites etc
1. http://www.librarything.com boekenverzamelingen online
2. http://www.goodreads.com share book recommendations (via Linus)

View File

@ -0,0 +1,81 @@
+++
title = "wantedfeed"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"wantedfeed"
]
date = "2013-03-12"
+++
<style type######"text/css" media"screen">
#goodreads_container {
float: right;
background-color: #F2F2DD;
}
.gr_custom_container_1314639342 {
/* customize your Goodreads widget container here*/
border: 1px solid gray;
-moz-border-radius:10px;
-webkit-border-radius:10px;
padding: 10px 5px 10px 5px;
color: #000000;
width: 300px
}
.gr_custom_header_1314639342 {
/* customize your Goodreads header here*/
border-bottom: 1px solid gray;
width: 100%;
margin-bottom: 5px;
text-align: center;
font-size: 120% !important;
margin-left: 0px !important;
}
.gr_custom_each_container_1314639342 {
/* customize each individual book container here */
width: 100%;
clear: both;
margin-bottom: 10px;
overflow: auto;
padding-bottom: 4px;
border-bottom: 1px solid #aaa;
}
.gr_custom_book_container_1314639342 {
/* customize your book covers here */
overflow: hidden;
height: 60px;
float: left;
margin-right: 4px;
width: 39px;
}
.gr_custom_author_1314639342 {
/* customize your author names here */
font-size: 10px;
}
.gr_custom_tags_1314639342 {
/* customize your tags here */
font-size: 10px;
color: gray;
}
.gr_custom_rating_1314639342 {
/* customize your rating stars here */
float: right;
}
</style>
<div id="goodreads_container">
<div id="gr_custom_widget_1314639342"></div>
</div>
<script type######"text/javascript" charset"utf-8" src######"http://www.goodreads.com/review/custom_widget/5451893.Wouter's%20bookshelf:%20to-read?cover_positionleft&amp;cover_size######small&amp;num_books15&amp;order######d&amp;shelfto-read&amp;show_author######1&amp;show_cover1&amp;show_rating######0&amp;show_review1&amp;show_tags######0&amp;show_title1&amp;sort######date_added&amp;widget_bg_colorFFFFFF&amp;widget_bg_transparent######&amp;widget_border_width1&amp;widget_id######1314639342&amp;widget_text_color000000&amp;widget_title_size######medium&amp;widget_widthmedium"></script>

View File

@ -0,0 +1,91 @@
+++
title = "where_good_ideas_come_from"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"where_good_ideas_come_from"
]
date = "2013-03-12"
+++
# Where good ideas come from
{{< lib "Where Good Ideas come From" >}} van Steven Johnson
Zie p75C en p78B en p79C
### 1. The Adjacent Possible
Concept: *Ideeën en uitvindingen die uitgebracht worden, openen de deur voor andere ideeën en uitvindingen*. Kopiëren van anderen (het idee, niet de uitwerking) is niet slecht maar goed, en maakt het mogelijk om bijvoorbeeld verder te breiden op het vorige idee. Een primitieve computer werd reeds volledig mechanisch ontwikkeld (met ballen die tandwielen doen roteren, zie {{< wp "Charles Babbage" >}}'s analytical engine, reeds in **1834** aan begonnen!), voordat elektriciteit uitgevonden werd. Zo'n uitvinding is *zijn tijd voor* - dat wil zeggen, de uitwerking van het idee wordt over het algemeen niet aanvaard of heel moeilijk tot onmogelijk gemaakt op dat bepaald tijdstip.
> All of us live inside our own private versions of the adjacent possible. In our work lives, in our creative pursuits, in the organizations that employ us, in the communities that we inhabit - in all these different environments, we are surrounded by potential new configurations, new ways of breaking out of standard routines.
### 2. Liquid Networks
<img style='float: left; width: |px;' src='/img//books/where-do-good-ideas-come-from.jpg'>
Concept: het overdragen van ideeën van persoon of community A naar B en zo verschillende ideeën combineren om tot iets nieuws te komen (en dan misschien weer een deur naar de volgende mogelijkheid openen, zie punt 1). Een "netwerk" kan zich in verschillende staten bevinden:
* **Air**: bvb. Gas - té aggressief, het vervliegt direct en er zijn er te veel. Vergelijk gas met ideeën die constant veranderen en vervliegen.
* **Liquid**: bvb Water - houdt zuurstof redelijk goed vast en trekt via cohesie andere vloeistoffen aan: een idee dat ronddrijft op het water en mogelijk tegen anderen botst om zich te vergroten.
* **Solid**: bvb Beton - geen enkele staat van verandering mogelijk, "vastgegroeid" in een oud systeem waar niets innoverent kan en zal werken.
Streef zo veel mogelijk naar "liquid networks". Dat wil zeggen: op uw werk, in uw privé leven, ... Zorg dat je jezelf omringt met andere genieën die goede ideeën verspreiden via het liquid network, met innovaties waar je naar op kijkt. Om zelf liquid networks te creëren moet je je omgeving ook zo aanpassen!
Grotere steden waar meer *innovators* wonen, groeien bijgevolg nog sneller door de ideeën die van persoon tot persoon overgedragen worden en zo nog meer nieuwigheden creëren. Al die dingen zijn enkel in het juiste netwerk mogelijk.
> The quickest way to innovate is to make novel connections
Voorbeeld: een wiki bijhouden digitaal kan te *solid* zijn vanwege de geforceerde manier van structureren. Een boek en random dingen op random plaatsen opschrijven is "losser" maar heeft dan weer kans om ideeën te laten "vervliegen" als je het boek niet regelmatig naleest.
### 3. The Slow Hunch
Concept: het "billion dollar idee" ineens krijgen bestaat niet - zulke dingen hebben meestal járen gerijpt in iemands brein. Om zo'n idee te laten ontstaan zijn ook botstingen met anderen nodig (zie punt 2)
> Reading is an unsurpassed vericle for the transmission of interesting new ideas
Tips om tot invallen te komen en de "slow hunch" levende te houden:
1. Noteer alles en herlees regelmatig notities
2. Omgeef uzelf door mensen waar je naar opkijkt of die iets te maken hebben met het idee waar aan je wilt werken
3. Zorg ervoor dat alles in een liquid network zit zodat het *superliniair scalet* in plaats van een *failed spark* wordt
4. Vertrouw op snap judgementes en schrijf ze ook op!
### 4. Serendipity
Concept: **per ongeluk** ergens op stoten door bijvoorbeeld een boekenwinkel te browsen en random titels af te gaan en u te laten leiden door uw gevoel. Of alle gedachten en notities in één plaats bewaren (digitaal, bijvoorbeeld in [DEVONthink](http:*www.devon-technologies.com/products/devonthink/)) en hierdoor zoeken - zo kom je andere ideeën terug tegen (Google's *did you mean ... ?//) en maak je op die manier nieuwe links. Wikipedia's "see also" links die alles met elkaar verbinden.
> {{< wp "Serendipity" >}} is when someone finds something that they weren't expecting to find.
Tegenwoordig onderschatten we te veel de kracht van op iets struikelen (*to stumble upon ideas*) - we zoeken op Google heel gericht naar onderwerp X, of in winkels kopen we Y en negeren we de rest. Kijk rond u, interesseer u ook in andere zaken en domeinen en draag een deel van die kennis over naar uw domein waar je aan dat slow hunch aan het werken bent.
### 5. Error
> The errors of the great mind exceed in number those of the less vigorous one ({{< wp "William Stanley Jevons" >}})
Concept: fouten maken is een essentiëel proces dat incrementeel voor verbeteringen zorgt. Men leert uit fouten en men krijgt andere ideeën uit fouten. Door constant fouten te maken ga je paden verkennen die je nooit eeder verkende - bijvoorbeeld door fout te denken dat een stelling juist is ga je je experiment daarrond richten maar blijkt dat je per ongeluk iets heel anders ondekt. *Transforming error into insight is one of the key functions of the lab conference*.
> Perhaps the history of the errors of mankind, all things considered, is more valuable and interesting than that of their discoveries. Truth is uniform and narrow, it constantly exists, and does not seem to require so much an active energy, as a passive aptitude of soul in order to encounter it. But error is endlessly diversified. ({{< wp "Benjamin Franklin" >}})
### 6. Exaptation
Concept: *aanpasbaarheid aan de omgeving.* Wanneer iets faalt of iets anders gaat dan je verwacht, gooi niet meteen alle ideeën weg. Pas het simpelweg aan, om in de nieuwe omgeving even goed of zelfs beter te kunnen functioneren. Kijk naar moeder natuur: organismen passen zich al miljoenen jaren aan aan hun omgeving.
De {{< wp "water flea" >}} bijvoorbeeld, kloont zichtzelf wanneer alles "goed" gaat. Wanneer alles goed gaat -> more of the same natuurlijk! Echter, wanneer het barre leefomstandigheden zijn, reproduceert deze luis zich via seks. Hierdoor kruisen cellen zich, zodat Nieuwe en andere cellen ontstaan die zich aanpassen aan de omgeving. Klonen brengt meer van hetzelfde, kruisen niet.
> In challenging times, an organism needs new ideas to meet them.
Brein stamcellen kunnen in twee modi werken:
1. Chaos mode
2. Phase locking mode
In mode 2 vuren alle neuronen synchroon af. In mode 1 niet, daardoor is er veel meer kans dat ideeën ontstaan in het brein doordat neuronen "vrij" met elkaar kunnen verbinden of tegen elkaar botsen. Hoe meer in chaos mode, hoe hoger het IQ van de mens ook ligt.
### 7. Platforms
Concept: Door te bouwen op ideeën en rond liquid networks ons gamma aan innovaties uit te breiden, bouwen we platformen waarop we verder kunnen werken. Concreet als voorbeeld: het GPS satelliet systeem, het World Wide Web, ... - deze zaken waren ooit uitvindingen die voor iets heel anders dienden maar groeiden uit tot een immens platform waarop andere mensen ideeën op uitwerkten, en zo voorts. Dit zijn hele communities geworden die vanuit het niets ontstaan zijn.

View File

@ -0,0 +1,115 @@
+++
title = "woordenlijst"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"books",
"woordenlijst"
]
date = "2013-03-12"
+++
# Woordenlijst
## Engelse woorden
^ Engels ^ Synoniem ^ Nederlandse vertaling ^
| Maldaptive | Marked by faulty or inadequate adaptation | Slechte aanpassing |
| colloquially | informal / using conversation | informeel |
| florid | gaudy, flamboyant | "bloemrijk" / overdreven sierlijk |
| probing | to search into or examine thoroughly - investigating | onderzoekend |
| myriad | countless | een enorm groot bedrag |
| valence (electrons) | the relative combining capacity of an atom | ... |
| primordial | constituting a beginning - first formed | "oer-" |
| surge | a strong forward moment, swelling of something | een golf |
| dispersed | to drive or send off | verspreid |
| nascent | beginning to exist or develop | in wording |
| erudite | educated | enorm veel kennis hebbend |
| dissertations | a written essay | thesis |
| calcifying | to become bony (hardened by calcium) | calcificerend? |
| inordinate | not within reasonable limits - extreme, unreasonable | buitensporig |
| of that ilk | of the same class or kind | ? |
| intrinsic | native, innate | intrinsiek |
| perpetrations | to commit | plegen |
| prescient | foresight | voorkennis |
| contemplating | to view with continuous attention - gaze at, behold | overwegend |
| elicited | to draw or bring out - to evoke | oproepen |
| disseminate | to scatter or spread widely - to disperse | verspreiden |
| sprig | a shoot, twig | een takje |
| concocted | to diverse, to make up | verzonnen |
| convey | to carry or bring | overbrengen |
| a finch | a similar bird (songbird) | ... |
| tantalizing | having something that provokes interest or desire | prikkelend |
| murkiness | dark, gloomy, cheerless | donker |
| frontispiece | the front of a building - an illustration facing the cover of a book | "titelplaat" ? |
| accretion | the addition | "aanwas" ? |
| pedigree | ancestral - distinguished | stamboom |
| contemporaries | existing at the same time | tijdgenoten |
| lingua franca | any language that is widely used as a means of communication among speakers of other languages. | ... |
| inebriated | to make drunk, toxiate | "bezatten" |
| proliferating | to increase in number/speed rapidly | profilerend |
| pileated | in the form of a skullcap (see [woodpecker](http://www.alphadictionary.com/goodword/word/pileated)) | ... |
| diminutive | small, little | klein |
| aragonite | {{< wp "aragonite" >}} | mineraal |
| unvarnished | plain, clear - straightforward | onverbloemd |
| meticulous | taking or showing extreme care to details | nauwgezet |
| idiosyncrasies | a characteristic, habit | een eigenaardigheid aan een persoon |
| impunity | immunity to damaging effects as of an action | straffeloosheid |
| incursion | a running in | inval |
| tenured | of holding/having | in aanstelling |
| scarcity | insufficiency | schaarsheid |
| oscillation | the act of swinging and moving from/to - fluctuating | ... |
| inexorable | unalterable | onverbiddelijk |
| rendition | an interpretation | weergave |
| mesmerizing | to compel by fascination | betoverend |
| introspection | mental process observing | introspectie |
| to churn | to produce mechanically in a hurry (like a container or machine to make butter) | ... |
| precipitated | to cast/send violently | neergeslagen |
| to atrophy | to undergo degeneration | ... |
| cubism | a style of painting & sculpture | ... |
| percussive | having an impact/blow | ... |
| to lodge in the head | to household - to store thoughts ? | ?? |
| reverberating | to rebound/recoil | weerkaatsend |
| dilettante | a lover of fine art and science - an amatuer at | ... |
| scorned | an object of contempt (disgrace) | geminacht |
| fastidious | critically or demanding | kieskeurig |
| allegory | fable | allegorie |
| latent | present but not visible, existing as potential | ... |
| barnacle | a person or thing that keeps firm hold of | ... |
| incessantly | continuing without interruption - unceasing | constant |
| contrivance | something obviously planned or forced | vernuft |
| latticce | a window or gate-like object | traliewerk |
| exhiliration | stimulating | ontdrukkend |
| mammalian | belonging to the class of mammalia | zoogdier- |
| untethered | to release from a chain/rope | ongebonden |
| vetted | to check for accuracy | doorlichten |
| fringe | a decorative border (from a raveled edge) | franje |
| parlance | in a manner of speaking | bij wijze van |
| sequestered | to remove/separate | teruggetrokken |
| cloistering | a covered walk/courtyard | opsluiting |
| anomalous | inconsistent | abnormaal |
| acumen | keen insight | scherpzinnigheid |
| cohort | a group or company | een groep |
| dwindling | to fall away/become smaller and smaller | afnemend |
| prodigious | wonderful - marvel | wonderbaarlijk |
| fortnight | 2 weeks | over twee weken |
| excreted | separated from an organic body | uitgescheiden |
| atoll | a ring-shaped coral reef | ... |
| designate | to denote, indicate, name | aanwijzen |
| desolate | laid waste | verlaten |
| emanating | to send forth or to emit | voortbrengend |
| coalesced | grown together into one body | samenvloeiend |
| quibbling | small objections | spitsvondigheden |
| litigiousness | pertaining to lawsuit | betwistbaarheid |
| glutton | a person who eats and drinks excessively | veelvraat |
| winnowing | to drive or blow away by fanning | ... |
| conflagration | a destructive fire | brand |
| anguish | suffering - pain | angst |
| ingrate | ungrateful | ondankbaar |
| scrupulously | precise or exact | nauwgezet |
| disdained | to despise | verachtten |
| slovenly | untidy in appearance or habits | slordig |
| to contort | twist or bend out of shape | verdraaien |

28
content/wiki/code.md Normal file
View File

@ -0,0 +1,28 @@
+++
title = "code"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"",
"code"
]
date = "2013-03-12"
+++
# Code
[<img style='' src='/img//code.jpg|'>]({{< relref "code.md" >}})
## Inhoudsopgave
<img style='' src='/img/indexmenu>code|js navbar nocookie'>
## Links
#### Bijleren: algemeen
* http:*codingkata.org/ - kleine oefeningen afhankelijk van uw skill level in *éénder welke taal//
* http:*www.codeschool.com/ - Learn by Doing - screencasts, tutorials, heel uitgebreid - bvb [Rails for Zombies](http:*railsforzombies.org/)

View File

@ -0,0 +1,23 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"home"
]
date = "2013-03-12"
+++
# Building & Compiling
<img style='' src='/img/indexmenu>.|js navbar nocookie'>
## Log management
1. http://www.splunk.com/ om zaken visueel samen te vatten, zelfde exceptions uit logs te halen, statistiekjes te trekken, ...
2. [unix/cmd]({{< relref "wiki/unix/cmd.md" >}}) tools zoals grep en sed gebruiken om de rest manueel te doen!

View File

@ -0,0 +1,47 @@
+++
title = "ant"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"ant"
]
date = "2013-03-12"
+++
# Ant scripts etc
### JSP files precompilen met tomcat lib
```xml
<project name######"vac Precompilatie" default"precompile-all" basedir=".">
<taskdef classname######"org.apache.jasper.JspC" name"jasper">
<!-- -Dorg.apache.el.parser.SKIP_IDENTIFIER_CHECK=true -->
<classpath id="jasperpath">
```et
<include name="*.jar"/>
</fileset>
```et
<include name="*.jar"/>
</fileset>
</classpath>
</taskdef>
<target name="precompile-all">
<mkdir dir="target/jsp" />
<jasper
validatexml="false"
uriroot="target/vac"
outputdir="target/jsp" />
</target>
</project>
```
Als ge dit bovenstaande gebruikt, jasper als dep. toevoegen (`org.apache.tomcat jasper 6.0.3x`)

View File

@ -0,0 +1,18 @@
+++
title = "grunt"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"grunt"
]
date = "2013-03-12"
+++
# Grunt
:exclamation: Zie [code/javascript/frameworks/yeoman]({{< relref "wiki/code/javascript/frameworks/yeoman.md" >}})

View File

@ -0,0 +1,121 @@
+++
title = "jsunit"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"jsunit"
]
date = "2013-05-17"
+++
# JsUnit Testen
## Integratie met een Ant build
Zie http://www.jsunit.net/
Hoofd JUnit klasse die gestart moet worden als junit tag vanuit ant: **`net.jsunit.StandaloneTest`**<br/><br/>
Voor uitleg over de parameters, zie jsunit website.
:exclamation: Belangrijk: JsUnit draait binnen een aparte context op een embedded Jetty server. Dit wil zeggen dat javascript test suites (html pagina's) die javascript files includen wel binnen de context staan, maar javascript files in een web project binnen eclipse bijvoorbeeld niet. Oplossing: kopiëer alle JS files voordat de test gedraaid wordt binnen de context.
Voor JS files te testen binnen een jar moeten die ook unjarred worden.
### Ant build snippet
```xml
<!-- JsUnit properties -->
<property name######"jsunit.lib.dir" value"${basedir}/../buildscripts/${lib.dir}/jsunit" />
<property name######"jsunit.browserFileNames" value"c:<br/><br/>program files<br/><br/>internet explorer<br/><br/>iexplore.exe,c:<br/><br/>program files<br/><br/>Mozilla Firefox<br/><br/>firefox.exe" />
<property name######"jsunit.port" value"9001" />
<property name######"jsunit.suite" value"suite.html" />
<property name######"jsunit.url" value"http:*localhost:9001/jsunit/testRunner.html?testPage######http:*localhost:9001/jsunit/tests/${jsunit.suite}&amp;autoRuntrue" />
<property name######"jsunit.common.jar" value"${web.lib.dir}/commonResources.jar" />
<property name######"jsunit.src.js" value"${web.dir}/resources/scripts" />
<property name######"jsunit.src.tests" value"test/jsunit" />
<property name######"jsunit.target" value"${target.dir}/jsunit" />
<property name######"jsunit.target.js" value"${jsunit.target}/tests/js" />
<property name######"jsunit.target.tests" value"${jsunit.target}/tests" />
<path id="jsunit.classpath">
```et
</path>
<target name######"jsunit-tests" depends"-clean-reports, -compile-test, -jsunit, -junit-report"/>
<target name######"-jsunit" if"jsunit.tests.present">
<junit failureproperty######"junit.failed" errorproperty"junit.error">
<formatter type######"plain" usefile"false"/>
<classpath refid="jsunit.classpath"/>
<sysproperty key######"java.util.logging.config.file" value"${jsunit.target.tests}/logging.properties"/>
<sysproperty key######"browserFileNames" value"${jsunit.browserFileNames}"/>
<sysproperty key######"description" value"JsUnit server"/>
<sysproperty key######"logsDirectory" value"${report.dir}"/>
<sysproperty key######"port" value"${jsunit.port}"/>
<sysproperty key######"resourceBase" value"${jsunit.target}"/>
<sysproperty key######"url" value"${jsunit.url}"/>
<test name="net.jsunit.StandaloneTest"/>
</junit>
</target>
<target name######"-compile-jsunit" depends"-jsunit-check" if="jsunit.tests.present">
<antcall target="-jsunit-copy-lib" />
<antcall target="-jsunit-copy-common-js" />
<antcall target="-jsunit-copy-tests" />
<antcall target="-jsunit-copy-js" />
<antcall target="-jsunit-build-suite" />
</target>
<target name="-jsunit-check">
<available file######"${jsunit.src.tests}" property"jsunit.tests.present"/>
</target>
<target name="-jsunit-copy-lib">
<copy todir="${jsunit.target}">
```et
</copy>
</target>
<target name="-jsunit-copy-common-js">
<unjar src######"${jsunit.common.jar}" dest"${jsunit.target.js}/common">
<patternset>
<include name="**/*.js" />
<exclude name="**/resourcesmini/**"/>
</patternset>
<mapper type="flatten"/>
</unjar>
</target>
<target name="-jsunit-copy-tests">
<copy todir="${jsunit.target.tests}">
```et
</copy>
</target>
<target name="-jsunit-copy-js">
<copy todir="${jsunit.target.js}">
```et
</copy>
</target>
<target name="-jsunit-build-suite">
<taskdef name######"jsUnitSuiteBuilder" classname"be.cegeka.ant.JsUnitSuiteBuilder" classpath="${jsunit.lib.dir}/java/ant/cegekant.jar" />
<jsUnitSuiteBuilder testdir######"${jsunit.target.tests}" testsuitefilename"${jsunit.target.tests}/${jsunit.suite}"
suitetemplatefilename="${jsunit.target.tests}/suite_template.html"/>
</target>
```
### Suite.html automatisch genereren
`testRunner.html` draait standaard een html pagina als test suite waar alle anderen geïnclude in worden. Een JS test methode moet beginnen met `test`X(). Standaard assertions kunnen gebruikt worden die deel van JsUnit zelf zijn, zie die documentatie.
Om niet altijd de hoofd suite aan te moeten passen, kan een ant plugin gemaakt worden die een bepaald pad scant op html files en deze recursief toevoegt aan de suite zelf. Die wordt bij elke build dus in principe overschreven.
Hiervoor is een plugin geschreven op: http://code.google.com/p/cegekant/<br/><br/>
[Volledige source suite builder](http://code.google.com/p/cegekant/source/browse/trunk/src/be/cegeka/ant/JsUnitSuiteBuilder.java)

View File

@ -0,0 +1,615 @@
+++
title = "maven"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"maven"
]
date = "2013-06-05"
+++
# Maven2 Build stuff
:exclamation: **properties** guide: http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide
## javascript files automatisch minify-en
```xml
<profiles>
<profile>
<id>minify</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warSourceExcludes>**/js/**</warSourceExcludes>
</configuration>
</plugin>
<plugin>
<groupId>net.tqh.plugins</groupId>
<artifactId>uglifyjs-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<sourceDirectory>src/main/webapp/js</sourceDirectory>
<outputDirectory>target/${project.name}-${version}/js</outputDirectory>
</configuration>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>uglify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
```
Bron: https:*github.com/mishoo/UglifyJS - maven plugin gebruikt `Rhino` om dit uit te voeren. Kan ook met `node` uitgevoerd worden - gebruik bij voorkeur `r.js` (zie http:*requirejs.org/docs/optimization.html)
## Argumenten als system property meegeven aan testen
Maven forkt by default dus `-Dbla=blie` gaat niet werken, dit is een property voor het maven java commando, maar niet voor de test zelf.
Oplossing: ` mvn test -DargLine######"-Dsystem.test.propertytest"`
**argLine** gebruiken. Zie:
1. http://www.cowtowncoder.com/blog/archives/2010/04/entry_385.html
2. [maven properties guide](http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide)
## Een single-deps jar mekan met maven assembly
```xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
```
En dan met `mvn assembly:single` uitvoeren. Dit maakt in uw target dir een file genaamd `bla-1.0-SNAPSHOT-jar-with-dependencies.jar`. `java -jar [jar]` werkt dan.
## Een test jar maken met maven assembly
Met `maven assembly` kan je files packagen na het compileren van tests maar voor het runnen. Op die manier kunnen we dus bvb class files in een jar packagen (of resources in een zip). Daarna manueel installeren in de repository ofzoiets.
Plugin:
```xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<executions>
<execution>
<id>create-test-dependency</id>
<phase>process-test-classes</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>gatecontrol</finalName>
<attach>false</attach>
<descriptors>
<descriptor>test-assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
```
De externe assembly file:
```xml
<assembly>
<id>testjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
```ets
```et
<directory>target/test-classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
```
:exclamation: test jars zijn precies niet **transitief** qua dependencies? <br/><br/>
Als je een test-jar (die dus op `scope test` staat) wil includen in je eigen `assembly:single` jar, kan je `classifier tests` gebruiken:
```xml
<dependency>
<groupId>be.bla</groupId>
<artifactId>bla-blie</artifactId>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
```
Dan wordt die test jar mee gepackaged, maar zijn dependencies blijbkaar niet?
## Profiles en properties
#### activeByDefault
Zie http://java.dzone.com/articles/maven-profile-best-practices - **nooit** gebruiken! Waarom?
> This flag activates the profile if no other profile is activated. Consequently, it will fail to activate the profile if any other profile is activated. This seems like a simple rule which would be hard to misunderstand, but in fact it's surprisingly easy to be fooled by its behaviour. When you run a multimodule build, the activeByDefault flag will fail to operate when any profile is activated, even if the profile is not defined in the module where the activeByDefault flag occurs.
In plaats daar van:
```xml
<profile id="nofoobar">
<activation>
<property>
<name>!foo.bar</name>
</property>
</activation>
</profile>
```
## JAXB generatie
#### Genereer endpoints vanaf WSDL
```xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>${org.codehaus.mojo.jaxws.maven.plugin.version}</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<wsdlDirectory>src/resources/wsdl</wsdlDirectory>
<packageName>com.x.interfaces.ws</packageName>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws</sourceDestDir>
</configuration>
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-tools</artifactId>
<version>${com.sun.xml.ws.jaxws.version}</version>
</dependency>
</dependencies>
</plugin>
```
Zie http://rphgoossens.wordpress.com/2011/02/20/developing-a-contract-first-jax-ws-webservice/
Genereer de code met `mvn jaxws:wsimport` goal.
#### Genereer JAXB Java objecten vanaf XSD
Zelfde pincipe, andere `goal`:
```xml
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>${org.jvnet.jaxb2.maven2.maven.jaxb2.plugin.version}</version>
<executions>
<execution>
<id>crm_generation</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaDirectory>src/main/schema</schemaDirectory>
<schemaIncludes>
<include>y.wsdl</include>
</schemaIncludes>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.x.interfaces</generatePackage>
</configuration>
</execution>
</executions>
</plugin>
```
## Integratie met Ant
Maven kan ook ant tasks uitvoeren. Dit door ant code te embedden in de pom.xml op de volgende manier:
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<configuration>
<tasks>
<property name######"target.war" value"bla.war" />
<property name######"zip.name" value"bla.zip" />
<ant antfile######"build.xml" inheritRefs"true" inheritAll="true">
<target name="buildZip" />
</ant>
</tasks>
</configuration>
<goals>
<goal>install</goal>
</goals>
</plugin>
```
Binnen de configuration tag zit ant code, met de ant tag roep ik een externe build xml aan. Op die manier kan je dus een ant buildfile volledig naast een pom.xml maven2 file plaatsen, en properties doorgeven! Die ant task wordt uitgevoerd met het commando `mvn antrun:run` of bij bepaalde geconfigureerde goals.
Voorbeeld: http://maven.apache.org/plugins/maven-antrun-plugin/
#### Aan bepaalde phase hangen
Zie http://www.avajava.com/tutorials/lessons/what-are-the-phases-of-the-maven-default-lifecycle.html
Om nog rap een property file te kopiëren, best aan `prapare-package` phase hangen (maven 2.1+):
```xml
<profiles>
<profile>
<id>env</id>
<activation>
<property>
<name>env</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo message="Env property detected, copying ${env} to output directory..." />
<copy file######"src/main/resources/template/env.${env}.properties" tofile"${project.build.outputDirectory}/env.properties"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
```
## Javadoc genereren
Deze plugin nodig:
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<configuration>
<reportOutputDirectory>release/doc</reportOutputDirectory>
<destDir>javadoc</destDir>
<doctitle>API for ${project.name} ${project.version}</doctitle>
<windowtitle>API for ${project.name} ${project.version}</windowtitle>
</configuration>
</plugin>
```
:exclamation: output dir = `${reportOutputDirectory}/${destDir}`<br/><br/>
Voorbeeld: http://maven.apache.org/plugins/maven-javadoc-plugin/examples/output-configuration.html
## Deployen met maven
### Jetty integratie en auto-deploy
#### jetty run
Integratie met jetty en maven2: gebruik `mvn jetty:run` om automatisch de jetty server op te starten.<br/><br/>
Het is ook mogelijk om die te laten scannen voor resource changes met `scanIntervalSeconds` - server start automatisch (normaal gezien...)
```xml
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<stopPort>9966</stopPort>
<stopKey>comeet</stopKey>
<scanIntervalSeconds>5</scanIntervalSeconds>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>8089</port>
</connector>
</connectors>
</configuration>
</plugin>
```
:exclamation: Vanaf Jetty plugin 7 zijn packages hernoemd en zo, zie http://wiki.eclipse.org/Jetty en de migratie van 6->7->...9
##### Debug poort instellingen
Gebruikt `MAVEN_OPTS` JVM parameters (omdat het proces niet geforked wordt?): http://docs.codehaus.org/display/JETTY/Debugging+with+the+Maven+Jetty+Plugin+inside+Eclipse
```
-Xdebug -Xnoagent -Djava.compiler######NONE -Xrunjdwp:transportdt_socket,address######4000,servery,suspend=y
```
##### JNDI Datasources definiëren
Kan in webapp/WEB-INF/jetty-env.xml:
```xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-*Mort Bay Consulting*DTD Configure*EN" "http:*jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<New id######"partnerwerkingDataSource" class"org.mortbay.jetty.plus.naming.Resource">
<Arg>jdbc/partnerwerkingDataSource</Arg>
<Arg>
<New class="oracle.jdbc.pool.OracleDataSource">
<Set name="URL">${database.url}</Set>
<Set name="user">${database.user}</Set>
<Set name="password">${database.password}</Set>
</New>
</Arg>
</New>
</Configure>
```
wordt dan automatisch door `jetty:run` opgepikt.
#### auto-start bij integratie testen (failsafe plugin)
Als we aan bovenstaande plugin ook nog `executions` opgeven, start jetty automatisch bij `pre-integration-test` en stopt hij automatisch bij `-post-integration-test`:
```xml
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
```
`daemon` moet op **true** staan omdat de bovenstaande plugin (jetty6) geen fork doet en dan natuurlijk geen testen gedraaid worden...
### Tomcat deploy
Op verschillende omgevingen deployen kan door verschillende profielen aan te maken in de pom.xml file, en dan als env. parameter `-Denv=[gewenste env value]` de te deployen mee te geven:
```xml
<profiles>
<profile>
<activation>
<property>
<name>env</name>
<value>test</value>
</property>
</activation>
<properties>
<server.url>http://blatomcat:8888/manager</server.url>
<server.username>user</server.username>
<server.password>pass</server.password>
</properties>
</profile>
</profiles>
```
Die properties die hierboven staan worden dan in deze plugin ingevuld:
```xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.0-beta-1</version>
<configuration>
<url>${server.url}</url>
<username>${server.username}</username>
<password>${server.password}</password>
</configuration>
</plugin>
```
Uitvoeren met `mvn tomcat:deploy [-Denv=x]`<br/><br/>
Voorbeelden en meer uitleg: http://mojo.codehaus.org/tomcat-maven-plugin/
## War name veranderen
Staat default op `${project.build.finalName}` wat neerkomt op artifactId-version.war.
Te veranderen door `<warName>blar</warName>` in `<configuration/>` te plaatsen in de `maven-war-plugin`.<br/><br/>
**Zonder** .war ext. dus.
Zie http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#warName
## Jar source code downloaden
```
mvn dependency:sources
```
Ook mogelijk in de pom door per dependency `downloadSources` op `true` te zetten, of via de `eclipse:eclipse` goal plugin:
```xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
... other stuff ...
</configuration>
</plugin>
</plgins>
</build>
```
Vergeet niet dan als property `-DdownloadSources=true` mee te geven.
#### eclipse:eclipse genereert ook de .project file
Library dependencies worden daar automatisch aan toegevoegd, maar alles staat onder **M2_REPO**/org/.../bla.jar en Eclipse moet weten waar lokaal de repository staat. Zie ook http://maven.apache.org/guides/mini/guide-ide-eclipse.html - Dit commando uitvoeren & eclipse herstarten:
`mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo`
#### Automatisch source files encoden
Je kan met die plugin ook extra configuratie meegeven die de `.java` files qua encoding goed zet:
```xml
<additionalConfig>
```
<name>.settings/org.eclipse.core.resources.prefs</name>
<content>
<![CDATA[eclipse.preferences.version######1${line.separator}encoding/<project>${project.build.sourceEncoding}${line.separator}]]>
</content>
```
</additionalConfig>
```
## Dependency tree tonen
```
mvn dependency:tree > deptree.out
```
Produceert rommel in het volgend formaat:
```
[INFO] [dependency:tree {execution: default-cli}]
[INFO] be.--api:jar:2.21-SNAPSHOT
[INFO] +- be.-support:jar:7.21-SNAPSHOT:compile
[INFO] | +- org.easytesting:fest-assert:jar:1.2:test (scope managed from compile)
[INFO] | | <br/>- org.easytesting:fest-util:jar:1.1:test
[INFO] | +- com.thoughtworks.xstream:xstream:jar:1.3.1:compile
[INFO] | | <br/>- xpp3:xpp3_min:jar:1.1.4c:compile
[INFO] | +- javax.ws.rs:jsr311-api:jar:1.1.1:compile
[INFO] | +- org.objenesis:objenesis:jar:1.2:compile
[INFO] | +- net.sf.ehcache:ehcache:jar:1.6.0:compile
[INFO] | +- log4j:log4j:jar:1.2.15:compile
[INFO] | | <br/>- javax.mail:mail:jar:1.4:compile
[INFO] | +- commons-codec:commons-codec:jar:1.3:compile
[INFO] | +- jmimemagic:jmimemagic:jar:0.1.2:compile
[INFO] | | +- oro:oro:jar:2.0.8:compile
[INFO] | | <br/>- commons-logging:commons-logging:jar:1.1.1:compile (version managed from 1.0.4)
[INFO] | +- commons-io:commons-io:jar:1.4:compile
[INFO] | +- org.htmlcleaner:htmlcleaner:jar:2.1:compile
..
```
## Een bepaalde test draaien via Maven
```
mvn test -Dtest=[testClass] -P [profile]
```
Waarbij `profile` het profiel is die de surefire plugin heeft - bijvoorbeeld:
```xml
<profile>
<id>endtoend</id>
<activation>
<property>
<name>endtoend</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<skip>false</skip>
<argLine>-Xms128M -Xmx512M -XX:MaxPermSize=512M</argLine>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
```
:exclamation: Als een bepaalde jar nog deployed moet worden (naar Jetty bvb) voor het runnen van de test (scenario testen zoals selenium en webdriver), moet de `install` in plaats van `test` goal uitgevoerd worden. <br/><br/>
Het kan *ook* zijn dat nog zaken geïnstalleerd moeten worden in de lokale Maven repository (het root project) -> eerst `mvn clean install` op het root project doen (voor *vac* is dit zo). Dit is omdat het endtoend project daarop afhangt, en de compile dan faalt.
## Een jar manueel in de repository installeren
Gebruik het volgende commando:
> `mvn install:install-file -Dfile######x.jar -DgroupIdcom.group -DartifactId######jarName -Dversion1.0.0 -Dpackaging=jar`
Wens je dit in de **remote repository** te installeren, gebruik dan `mvn deploy:deploy-file` met als extra parameter de url van de repository via de `-Durl=repoUrl` optie.
## De maven java compiler versie goed zetten
Gebeurt in een plugin in de `build` fase:
```xml
<build>
<finalName>test</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
```

View File

@ -0,0 +1,414 @@
+++
title = "appengine"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"maven",
"appengine"
]
date = "2013-03-12"
+++
# Maven Google Appengine
#### maven-cli-plugin gebruiken als semi-hot-deployer
Zie [Mavenizing my project](http://blog.cloudme.org/2010/04/mavenizing-my-project/)
In plaats van betalende JRebel kan je bvb. voor GAE de jetty server op zetten met `gae:run`, maar alles in webapp ziet hij niet als een change.
* In Tab1: `mvn gae:run`.
* In Tab2: `mvn cli:execute` en dan commando's `compile war` in aparte tab die de eerste tab (nog actieve maven) oppikt dan.
Andere mogelijkheid is natuurlijk voor niet-GAE dingen, `jetty:run` gebruiken (zie [code/build/maven]({{< relref "wiki/code/build/maven.md" >}})).
:exclamation: de plugin is **niet werkend met maven 3**, zie https://github.com/mrdon/maven-cli-plugin/wiki/Maven-3.0-Support -
```
INFO]
[INFO] --- maven-cli-plugin:1.0.6:execute (default-cli) @ gatecontrolweb ---
[INFO] Waiting for commands...
maven2> clean
[INFO] Executing: org.apache.maven.plugins:maven-clean-plugin [clean]
[ERROR] Unable to complete running command: clean
java.lang.RuntimeException: org.apache.maven.plugin.MojoExecutionException: Unable to execute mojo
at org.twdata.maven.cli.commands.ExecuteGoalCommand.run(ExecuteGoalCommand.java:111)
at org.twdata.maven.cli.CliShell.interpretCommand(CliShell.java:48)
at org.twdata.maven.cli.CliShell.run(CliShell.java:29)
at org.twdata.maven.cli.AbstractCliMojo.displayShell(AbstractCliMojo.java:144)
at org.twdata.maven.cli.AbstractCliMojo.access$000(AbstractCliMojo.java:22)
at org.twdata.maven.cli.AbstractCliMojo$1.run(AbstractCliMojo.java:116)
Caused by: org.apache.maven.plugin.MojoExecutionException: Unable to execute mojo
at org.shaded.mojoexecutor.MojoExecutor.executeMojo(MojoExecutor.java:106)
at org.twdata.maven.cli.MojoCall.run(MojoCall.java:31)
at org.twdata.maven.cli.commands.ExecuteGoalCommand.runMojo(ExecuteGoalCommand.java:125)
at org.twdata.maven.cli.commands.ExecuteGoalCommand.run(ExecuteGoalCommand.java:104)
... 5 more
Caused by: java.lang.UnsupportedOperationException
at org.apache.maven.plugin.internal.DefaultPluginManager.executeMojo(DefaultPluginManager.java:90)
at org.shaded.mojoexecutor.MojoExecutor.executeMojo(MojoExecutor.java:104)
... 8 more
```
Tof...
#### maven-endpoint-plugin
:exclamation: Google App Engine **endpoint metadata** genereren via maven kan ook en is een totaal andere plugin: http://code.google.com/p/maven-endpoint-plugin/
Hiervoor moet je de volgende repository gebruiken (zit niet in de central repo):
```xml
<repositories>
<repository>
<id>cbreleases</id>
<url>https://repository-michael.forge.cloudbees.com/release</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>cbreleases</id>
<url>https://repository-michael.forge.cloudbees.com/release</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
```
#### maven-gae-plugin
Laatste versie van de "officiele" plugin op https://github.com/maven-gae-plugin/maven-gae-plugin
Een compleet voorbeeld gebaseerd op de jsp archetype:
```xml
<?xml version######"1.0" encoding"UTF-8"?>
<project xmlns######"http:*maven.apache.org/POM/4.0.0" xmlns:xsi"http:*www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http:*maven.apache.org/POM/4.0.0 http:*maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- The Basics -->
<groupId>com.myapp.test</groupId>
<artifactId>testapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>lkjm</name>
<dependencies>
<!-- Google App Engine meta-package -->
<dependency>
<groupId>net.kindleit</groupId>
<artifactId>gae-runtime</artifactId>
<version>${gae.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>${datanucleus.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<!--
J2EE Servlet API. We need it to compile IndexServlet class. You can
probably remove it, if you don't explicitly use Servlets
-->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.5_spec</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<!--
Make use of JSP tags. Remove, if you don't use JSPs
-->
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<type>jar</type>
<scope>runtime</scope>
</dependency>
<!-- These dependencies are here just for enabling logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.24</version>
</dependency>
<!-- Test scope -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<!--
GAE libraries for local testing as described here:
http://code.google.com/appengine/docs/java/howto/unittesting.html
-->
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-labs</artifactId>
<version>${gae.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-stubs</artifactId>
<version>${gae.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-testing</artifactId>
<version>${gae.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.jdo</groupId>
<artifactId>jdo2-api</artifactId>
<version>2.3-eb</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>transaction-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<!--
This plug-in "enhances" your domain model objects (i.e. makes them
persistent for datanucleus)
-->
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>maven-datanucleus-plugin</artifactId>
<version>1.1.4</version>
<configuration>
<!--
Make sure this path contains your persistent classes!
-->
<mappingIncludes>**/model/*.class</mappingIncludes>
<verbose>true</verbose>
<enhancerName>ASM</enhancerName>
<api>JDO</api>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>${datanucleus.version}</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>transaction-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-rdbms</artifactId>
<version>${datanucleus.version}</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-enhancer</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>javax.jdo</groupId>
<artifactId>jdo2-api</artifactId>
<version>2.3-ec</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
<includes>
<include>**/appengine-web.xml</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
<!--
The actual maven-gae-plugin. Type "mvn gae:run" to run project, "mvn
gae:deploy" to upload to GAE.
-->
<plugin>
<groupId>net.kindleit</groupId>
<artifactId>maven-gae-plugin</artifactId>
<version>0.9.5</version>
</plugin>
<!--
Upload application to the appspot automatically, during
release:perform
-->
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<goals>gae:deploy</goals>
</configuration>
</plugin>
<!-- Java compiler version -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- Specify hard-coded project properties here -->
<properties>
<!-- Sets the project's default encoding.
http://docs.codehaus.org/display/MAVENUSER/POM+Element+for+Source+File+Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--
This is just for "eclipse:eclipse" goal to always attempt downloading
sources
-->
<downloadSources>true</downloadSources>
<!--
Specify AppEngine version for your project. It should match SDK
version pointed to by ${gae.home} property (Typically, one used by
your Eclipse plug-in)
-->
<gae.version>1.6.5</gae.version>
<!--
Upload to http://test.latest.<applicationName>.appspot.com by default
-->
<gae.application.version>test</gae.application.version>
<datanucleus.version>1.1.5</datanucleus.version>
</properties>
<profiles>
<!--
We can configure our integration server to activate this profile and
perform gae:deploy, thus uploading latest snapshot to the
http://1.latest.<applicationName>.appspot.com automatically
-->
<profile>
<id>integration-build</id>
<properties>
<gae.application.version>stage</gae.application.version>
</properties>
</profile>
<!--
This profile will activate automatically during release and upload
application to the http://2.latest.<applicationName>.appspot.com (We
might want to set the 2nd version as our applications Default version
to be accessible at http://<applicationName>.appspot.com)
-->
<profile>
<id>release-build</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<properties>
<!--
During release, set application version in appengine-web.xml to 2
-->
<gae.application.version>release</gae.application.version>
</properties>
</profile>
</profiles>
</project>
```
Hiermee kan je:
1. `mvn gae:unpack` uitvoeren om de GAE SDK in uw maven repo te unpacken zodat `${gae.home}` niet nodig is in de pom (vanaf 0.9.5)
1. `mvn gae:run` uitvoeren om een devserver te starten
##### Andere versie
Een oudere versie (??) is deze:
```xml
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${appengine.target.version}</version>
</plugin>
```
Hiermee kan je:
1. `mvn appengine:devserver` gebruiken om lokaal een jetty op te starten, en
1. `mvn appengine:update` om te deployen via de commandline.

View File

@ -0,0 +1,41 @@
+++
title = "releasing"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"maven",
"releasing"
]
date = "2013-03-28"
+++
# Maven Releasing
Opmerking: de te releasen code zetten onder een folder C:/xxx en niet te diep nesten (CVS kan te lange folder structuur niet uitchecken)
#### Hoe een maven release uitvoeren ?
1. (**eenmalig uit te voeren** :exclamation:) voor elke nieuwe release maken we op een gepast moment een CVS 'maintenance release branch' waarop we de laatste bugfixen uitvoeren :
1. deze zal steeds de vorm 'versiez_y_x' hebben waarbij we z_y vervangen door een TOP release nummer b.v. 'versie2_7_x'
2. deze branch wordt later ook gebruikt om maintenance releases op uit te voeren (emergency / extra TOP's om bugfixes door te voeren)
3. gebruik volgend maven commando om de branch aan te maken (gebruik wel de juiste branchname en username/password voor cvs !) :
1. CVS --> mvn release:branch -DupdateBranchVersions######true -DupdateWorkingCopyVersionstrue -DbranchName######versiez_y_x -DautoVersionSubmodulestrue -Dusername######xxxx -Dpasswordyyyyy
2. SVN --> zelfde als CVS, maar zonder username en password
4. bij het uitvoeren van het commando komt maven vragen achter het versienummer in de branch en de nieuwe versie in de hoofdbranch.
5. De branch versie nummer zal 'z.y.0-SNAPSHOT' zijn (in dit voorbeeld '2.7.0-SNAPSHOT')
6. De hoofdbranch versie zal 'z.y+1-SNAPSHOT' zijn (in dit voorbeeld '2.8-SNAPSHOT'
2. update het project via wincvs naar de correcte branch 'versiez_y_x' (in het voorbeeld versie2_7_x).
3. bereidt de nieuwe release voor door het commando mvn release:prepare -Dresume######false -DpreparationGoals"clean install" -DautoVersionSubmodules=true -Dusername######xxxx -Dpasswordyyyyy uit te voeren.
4. Als dit niet lukt met de fout 'address in use', dan moet je de maven opts aanpassen (remote debugging weghalen). Maven zal je vragen achter de release versie nummer (in het voorbeeld wordt dit 2.7.0) en achter de volgende development versie (in het voorbeeld 2.7.1-SNAPSHOT).
5. finaliseer de release via het commando mvn release:perform -Dusername######xxxx -Dpasswordyyyyy
6. pas de pom.xml van relevant projecten aan
7. pas eventueel de prj/pom.xml & vdabbuild.xml aan om je EAR / WAR automatisch in de deployment TAR te stoppen.
#### Hoe skip ik mijn testen bij een release?
`-Darguments="-DskipTests"` meegeven

View File

@ -0,0 +1,42 @@
+++
title = "msbuild"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"msbuild"
]
date = "2014-01-31"
+++
# MSBuild
## Adding/Modifying build steps
##### Q: Hoe kan ik iets aan de build toevoegen zonder de XAML template te wijzigen?
A: Maak een nieuw **dummy solution** met één project, waar in de `csproj` file het volgende bijgevoegd is:
```xml
<Target Name="AfterBuild">
<Exec Condition######" '$(Configuration)|$(Platform)' 'Release|x86' " Command="attrib -r ../../AUP/C-eHealthPortal.aup" />
<BuildUpdate Condition######" '$(Configuration)|$(Platform)' 'Release|x86' " ProjectFile######"../../AUP/C-eHealthPortal.aup" PublishLocations"LOCAL" />
<Exec Condition######" '$(Configuration)|$(Platform)' 'Release|x86' " Command="attrib +r ../../AUP/C-eHealthPortal.aup" />
</Target>
```
(Ter info, `BuildUpdate` is een tag die met een using included werd: `<UsingTask AssemblyFile######"../../AUP/Kjs.AppLife.Update.BuildUpdateTask.dll" TaskName"Kjs.AppLife.Update.MSBuild.BuildUpdate" />`)
:exclamation: Indien volgorde belangrijk is, aan MSBuild als parameter deze solution als laatste builden, zodat de output/bin folder al de juiste gegevens bevat.
## WebServers drop folder
##### Q: Ik wil geen _publishedWebsite.zip waar heel diep PackageTmp in zit maar de exploded dir!
A: Append in `MSBuild` arguments `;DeployOnBuild=true` - zie [MSDN DeployOnBuild property](http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.build.workflow.activities.msbuild.deployonbuild.aspx)
Er is blijkbaar ook een `CreatePackageOnPublish` property (?)

View File

@ -0,0 +1,143 @@
+++
title = "scons"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"scons"
]
date = "2014-03-24"
+++
# SCons
1. [SCons Wiki Frontpage](http://www.scons.org/wiki/FrontPage)
2. [Single HTML Manpage](http://www.scons.org/doc/HTML/scons-man.html#lbAF)
3. [SCons Construction Variables](http://www.scons.org/doc/0.96.90/HTML/scons-user/a3061.html) om bvb de compiler te specifiëren.
### Opsplitsen SConstruct en SConscript
Waarom? http://www.scons.org/doc/2.1.0/HTML/scons-user/c3356.html
Build output definiëren, duplicate source files, etc. Voorbeeld `SConstruct` file:
```python
SConscript('SConscript', variant_dir######'build', duplicate0)
```
Voorbeeld file om Google Test mee te (proberen) builden `SConscript`:
```python
def Glob( pattern ###### '*.*', dir '.' ):
import os, fnmatch
files = []
for file in os.listdir( Dir(dir).srcnode().abspath ):
if fnmatch.fnmatch(file, pattern) :
files.append( os.path.join( dir, file ) )
return files
# construction variables: http://www.scons.org/doc/0.96.90/HTML/scons-user/a3061.html
env ###### Environment(CXX 'g++',
CPPPATH = '../:./include')
# add to library search path env.Append(LIBPATH = ['/usr/local/lib/'])
# add to libraries link path env.Append(LIBS = ['SDL_image','GL'])
env.Append(CPPFLAGS = ['-isystem ./include'])
env.Append(CXXFLAGS = ['-g', '-Wall', '-Wextra', '-pthread'])
env.SharedLibrary(target ###### 'gtest_main.dll', source ['../src/gtest-all.cc'])
# after that, we should link with gtest_main
```
Poging tot converteren van deze voorbeeld `Makefile` - supplied bij de gtest sources:
```
# A sample Makefile for building Google Test and using it in user
# tests. Please tweak it to suit your environment and project. You
# may want to move it to your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = ..
# Where to find user code.
USER_DIR = ../samples
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include
# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = sample1_unittest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h <br/>
$(GTEST_DIR)/include/gtest/internal/*.h
# House-keeping build targets.
all : $(TESTS)
clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
# Builds gtest.a and gtest_main.a.
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c <br/>
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c <br/>
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^
# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.
sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc <br/>
$(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
```

View File

@ -0,0 +1,49 @@
+++
title = "teamcity"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"build",
"teamcity"
]
date = "2015-07-13"
+++
# Teamcity
**Build pipeline** voor continuous deployment: zie [http:*robdmoore.id.au/blog/2012/09/01/maintainable-teamcity-continuous-deployment-pipeline-configuration/](http:*robdmoore.id.au/blog/2012/09/01/maintainable-teamcity-continuous-deployment-pipeline-configuration/)
### Parameters: comboboxen/checkboxen
<img style='' src='/img//code/build/tc_deploy_params.png|'>
**Demo omgeving**
Dit ingeven in "spec":
```
select display######'prompt' label'Demo omgeving' data_11######'FixDemo' data_10'FixDev' data_02######'TestDemo1' data_01'Package' data_04######'TestDemo3' data_03'TestDemo2' data_06######'TestDemo5' data_05'TestDemo4' data_08######'TestDemo7' data_07'TestDemo6' data_09='SERVERNAME'
```
**Modules**
Dit ingeven in "spec":
```
select data_7######'Modx' data_5'Mody.DAL' data_6######'Modz' ... multiple'true'
```
Wordt dan comma-separated doorgegeven via `%Modules%` parameter dat je kan gebruiken in build configuration.
### Artifacts bijhouden
Edit build settings > Artifact paths > `**/packaged.zip` om alle files die zo heten als artifact te bewaren. <br/><br/>
Probleem met HDD space kan opgelost worden met [http:*confluence.jetbrains.com/display/TCD8/Clean-Up](http:*confluence.jetbrains.com/display/TCD8/Clean-Up): Clean-up settings are configured under Administration | Project-related Settings | Build History Clean-up.
Gevolg is dat gebuilde zipfiles gedownload kunnen worden op deze manier:
<img style='float: left; width: nolink |px;' src='/img//code/build/builddeploy.png'>

View File

@ -0,0 +1,25 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"home"
]
date = "2013-08-05"
+++
# C/C++ >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>
#### Nuttige links
* [The 5 minute guide to C Pointers](http://denniskubes.com/2012/08/16/the-5-minute-guide-to-c-pointers/)
* [A tutorial on Pointers and Arrays in C](http://pw1.netcom.com/~tjensen/ptr/pointers.htm)

View File

@ -0,0 +1,189 @@
+++
title = "basics"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"basics"
]
date = "2013-12-02"
+++
# C(++) Basics
## Scope
C++ heeft block level scope, net als Java, alleen is het mogelijk om een variabele binnen een for loop dezelfde naam te geven als een die buiten die block gedefiniëerd is, terwijl dat in Java niet gaat:
```c
int j;
for(int i = 0; i < 10; i++) {
int j = i + 1; // compile fout in java
}
```
### Pointer scope
[auto_ptr](https://en.wikipedia.org/wiki/Auto_ptr) kan gebruikt worden om een pointer automatisch te verwijderen met `delete` wanneer deze scope verliest - alle andere zaken moet je zelf opkuisen.
:exclamation: Dit is deprecated in C++ 11, gebruik [unique_ptr](https://en.wikipedia.org/wiki/Smart_pointer#unique_ptr)
Voorbeeld van wikipedia:
```c
#include <iostream>
#include <memory>
using namespace std;
int main(int argc, char **argv)
{
int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;
y = x;
cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i
return 0;
}
```
## overloading: 'virtual'
In java wordt by default het diepste gedefiniëerde element opgeroepen, in C++ ben je verplicht `virtual` te gebruiken als "optimalisatie" wordt dit standaard niet gedaan... Voorbeeld:
```c
class Simple
{
public:
Simple() : someMember(3) {}
virtual int guessNumber();
int someMember;
};
```
```c
#include "simplecpp.h"
int Simple::guessNumber()
{
return 5;
}
```
Als je nu `guessNumber()` wil overschrijven in een subklasse kan dit:
```c
#include "simplecpp.h"
class Complexer : public Simple
{
public:
Complexer() {}
int guessNumber();
};
```
Merk op, te overschrijven method heropsommen in header file... (??) - hier hoeft geen `virtual` meer bij dan.
```c
#include "complexer.h"
int Complexer::guessNumber()
{
return 10;
}
```
Wat is hier de uitkomst van:
```c
#include "complexer.h"
#include <iostream>
int main()
{
Simple* simple = new Complexer();
std::cout << simple->guessNumber();
delete simple;
}
```
10. Haal `virtual` weg. 5. <br/><br/>
Definiëer `Complexer` zo:
```c
Complexer* complexer = new Complexer();
```
En het is altijd 10.
## Initialisatie
(Voorbeelden van bovenstaande)
```c
#include "complexer.h"
#include <iostream>
int main()
{
Simple simpleInitialized; // oops, I created something?
// Simple simpleInitialized = NULL; cannot convert from 'int' to 'Simple' (#define NULL 0)
Simple* simplePtr;
std::cout << "<br/>n initialiezd: " << simplePtr->someMember;
// Run-Time Check Failure #3 - The variable 'simplePtr' is being used without being initialized
delete simplePtr;
}
```
Wat is hier speciaal aan?
1. In C++ wordt altijd een object aangemaakt als je ze declareert. In Java niet!
2. In C++ is `NULL` gedefiniëerd als `#define NULL 0` - je kan dus niet zomaar iets toekennen hieraan. In C++ 11 heb je `nullptr`
3. Je kan wel een pointer declareren zonder een waarde toe te kennen, en dit geeft dan een run-time fout (zou bvb een `NullPointerException` gooien in java)
## Typecasting
Uitgebreide uitleg: zie http://www.cplusplus.com/doc/tutorial/typecasting/
In C++ is één impliciete conversie mogelijk door middel van de constructor, bijvoorbeeld:
```c
class Something
{
public:
Something(int i) : myVar(i) {}
private:
int myVar;
}
int getal = 10;
Something something = getal; // use constructor
```
Om dit tegen te gaan kan je altijd het `explicit` keyword gebruiken, zodat je dit moet doen:
```c
Something something = Something(getal); // expliciet oproepen constructor
```
Je kan `staic_cast<Type>(var)` gebruiken om explicit constructors aan te roepen, zo kunnen ze dan toch nog gecast worden.
## C++ 11 goodies
Algemeen: [How C++ 11 helps boost your productivity](http://www.informit.com/articles/article.aspx?p=1910142)
1. [Lambdas](http://www.codeproject.com/Articles/277612/Using-lambdas-Cplusplus-vs-Csharp-vs-Cplusplus-CX) zijn mogelijk
2. `nullptr`
3. `auto` keyword, zoals `var` in C# - dit is typesafe en door de compiler zelf bepaald.
4. 100% multithreading support, zie [code/c/threading]({{< relref "wiki/code/c/threading.md" >}})

View File

@ -0,0 +1,89 @@
+++
title = "linking"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"linking"
]
date = "2014-03-26"
+++
# Linking obj/dlls
Probleemstelling: verschillende **solutions**, code over solutions heen willen gebruiken.
Dit compileert by default altijd, maar tijdens het linken van de gecompileerde files loopt het mis. Waarom? Omdat er geen `dllexport` voorzien is.
<br/><br/> Op te lossen:
```c
#ifndef RESOURCE_UTILS_H
#define RESOURCE_UTILS_H
#include "Utility.h"
#ifdef _DLL
#define DllExImport __declspec(dllexport)
#else
#define DllExImport __declspec(dllimport)
#endif
class DllExImport ResourceUtils
{
public:
static RAIIObject<HICON> getIcon(int resourceId);
static RAIIObject<HICON> getIcon(HINSTANCE resourceHandleInstance, int resourceId);
private:
ResourceUtils() {}
};
#endif
```
in de cpp file hoeft niets speciaal meer te staan.
#### Functies exposen voor native calls
Zelfde principe om klassen te exposen met `_ _declspec(dllexport)`. Gebruik eventueel std calls (C# heeft dit nodig): `DllExImport MyStruct* _ _stdcall GetSignals();`.
#### Properties van solutions
##### Die de te exporteren code bevat
1. Configuration type: Dynamic Libraray (DLL)
2. Incremental linking: Yes (/INCREMENTAL)
3. Link Linkage Deps: Yes
4. Output file: *.dll
##### Die de code bevat die gebruik maakt van de dll
1. Linker; Input: Additional dependencies ../OtherSolution.lib
### Shared libraries linken in Unix
`declspec` is Win32 specifiek. Lees alles over GCC Visibility in [GNU GCC Wiki on Visibility](http://gcc.gnu.org/wiki/Visibility). Komt op dit neer:
```c
#if defined(_MSC_VER)
// Microsoft
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)
#elif defined(_GCC)
// GCC
#define EXPORT __attribute__((visibility("default")))
#define IMPORT
#else
// do nothing and hope for the best?
#define EXPORT
#define IMPORT
#pragma warning Unknown dynamic link import/export semantics.
#endif
```
Zie ook [How to write shared Libraries](http://www.akkadia.org/drepper/dsohowto.pdf) by Ulrich Drepper.

103
content/wiki/code/c/mfc.md Normal file
View File

@ -0,0 +1,103 @@
+++
title = "mfc"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"mfc"
]
date = "2013-12-12"
+++
# MFC
:exclamation: MFC en AFX [is hetzelfde](http://en.wikipedia.org/wiki/Microsoft_Foundation_Class_Library):
> One interesting quirk of MFC is the use of "Afx" as the prefix for many functions, macros and the standard precompiled header name "stdafx.h". During early development what became MFC was called "Application Framework Extensions" and abbreviated "Afx". The name Microsoft Foundation Classes (MFC) was adopted too late in the release cycle to change these references
### Strings in MFC
Gebruik `CString` - werkt niet op non-win32 omgevingen.
##### Formatting
Formatten kan bijvoorbeeld met `string.Format(_T("%s in %d"), otherString, otherDecimal);`
:exclamation: Om een string te intialiseren en toe te kennen moet je wel de `_T` macro gebruiken
##### Substringen
`Find` is hetzelfde als `indexOf` in andere talen.
```c++
CString HostServiceProxy::GetCouponFromResponseString(CString response)
{
CString couponKey ###### _T("Coupon");
CString couponPart = response.Mid(response.Find(couponKey) + couponKey.GetLength());
return couponPart.Left(couponPart.Find(_T(";")));
}
```
### Resource handling
Icons en images worden opgeslagen in .rc files die als resources in de code gekoppeld kunnen worden aan bijvoorbeeld een `CButton`. Hoe?
```c
HANDLE hImage = ::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(resourceId), IMAGE_ICON, 16, 15, LR_DEFAULTCOLOR);
if(hImage ###### NULL)
ASSERT(FALSE);
HICON image = static_cast<HICON>(hImage);
```
`HICON` is van `WinDef.h` en `::LoadImage` zit op `WinUser.h`. Zie [MSDN doc](http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx) voor LoadImage.
######= De juiste resource handle vastkrijgen ######=
Als je een MFC DLL maakt, gaat `AfxGetResourceHandle()` verwijzen naar de resource handle van uw DLL zelf. Als je dus resources wil vastpakken van een andere DLL heb je pech. Als je geen MFC DLL maakt kan je dit aanpassen met ` AFX_MANAGE_STATE(AfxGetStaticModuleState( ))`. **Dit gooit echter linking errors** ( error LNK2005: _DllMain@12 already defined) indien je dit vanuit een MFC DLL aanroept - dan is dit niet nodig.
Meer uitleg hierover: zie http://support.microsoft.com/kb/161589
:exclamation: de Afx resource handle kan **altijd** gewijzigd worden door leuke dingen te doen als:
```c
HINSTANCE old = AfxGetResourceHandle();
AfxSetResourceHandle(GetModuleHandle("andereModule"));
```
Gebruik daarom best `::GetModuleHandle(char*)` bij `::LoadImage`.
######= Resources op het juiste moment terug vrijgeven ######=
Resources worden meestal gewrapped in kleine objectjes die bij de constructor de resource alloceren en bij de destructor deze terug vrijgeven in plaats van in `try { ... }` zoiets te moeten doen in Java. Dit pattern is [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) of "Resource Acquisition Is Initialization". Voorbeeld:
```c
template<class TObject>
class RAIIObject
{
public:
explicit RAIIObject(const TObject& obj) : m_Object(obj) {}
RAIIObject() {}
~RAIIObject() {ReleaseObject();}
RAIIObject<TObject>& operator######(const TObject& obj) {if(&obj ! &m_Object) {ReleaseObject(); m_Object = obj;} return *this;}
RAIIObject<TObject>& operator######(const RAIIObject<TObject>& obj) {if(&obj ! this) {ReleaseObject(); m_Object = obj;} return *this;}
TObject& GetObject() {return m_Object;}
const TObject& GetObject() const {return m_Object;}
operator TObject&() {return m_Object;}
operator const TObject&() const {return m_Object;}
private:
void ReleaseObject();
TObject m_Object;
};
template<> inline void RAIIObject<HICON>::ReleaseObject() {::DestroyIcon(m_Object); m_Object = NULL;}
template<> inline void RAIIObject<CBrush>::ReleaseObject() {m_Object.DeleteObject();}
template<> inline void RAIIObject<CBitmap>::ReleaseObject() {m_Object.DeleteObject();}
template<> inline void RAIIObject<CFont>::ReleaseObject() {m_Object.DeleteObject();}
template<> inline void RAIIObject<CMenu>::ReleaseObject() {m_Object.DestroyMenu();}
```

View File

@ -0,0 +1,32 @@
+++
title = "preprocessing"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"preprocessing"
]
date = "2013-12-02"
+++
# Preprocessing
## Handige macro's
##### Exception/Debug informatie expanden
```c++
#define _ERROR_STR2(a) #a
#define _ERROR_STR(a) _ERROR_STR2(a)
#define ERROR_INFO(fn) _T(_ERROR_STR(__FILE__" line: "__LINE__" function: "fn))
```
Te gebruiken als `someFn(ERROR_INFO("bla"))`. Merk op dat `__FUNCTION__` of `__FUNC__` ook gebruikt kan worden, afhankelijk van de C++ compiler, maar dit is geen deel van de standaard (vanaf C++ v11).
De `#a` notatie wordt gebruikt om iets te [stringifyen](http://gcc.gnu.org/onlinedocs/cpp/Stringification.html) in de preprocessor, vandaar de delegate:
> Sometimes you may want to convert a macro argument into a string constant. Parameters are not replaced inside string constants, but you can use the # preprocessing operator instead. When a macro parameter is used with a leading #, the preprocessor replaces it with the literal text of the actual argument, converted to a string constant. Unlike normal parameter replacement, the argument is not macro-expanded first. This is called stringification.

View File

@ -0,0 +1,21 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"testing",
"home"
]
date = "2013-07-17"
+++
# code:c:testing >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

View File

@ -0,0 +1,108 @@
+++
title = "gtest"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"testing",
"gtest"
]
date = "2014-03-26"
+++
# Google Test
Downloaden op https://code.google.com/p/googletest/downloads/list
**Waarom**?
1. Platform onafhankelijk
2. Snelheid
3. Geen gezeik met Managed C++, compatibel met "eender wat" (enige vereiste: `cc` compiler variant)
4. Wordt veel gebruikt (Chromium, Stack overflow)
**Waarom niet**?
1. slechte of geen integratie met VStudio (zie onder)
2. wéér een andere syntax dan MS .NET testen
3. beetje awkward assertions
#### Assertions schrijven
```c
#include "../BaseCode/BaseCode.h"
#include "gtest/gtest.h"
TEST(MyTestCase, MyTest_Success)
{
EXPECT_EQ(2, MySum(1, 1));
}
TEST(MyTestCase, MyTest_Failure)
{
EXPECT_EQ(3, MySum(1, 2));
}
```
Waarbij dan `BaseCode` uw system under test zaken bevat (waar `MySum` defined is)
#### Builden met scons en g++
Tested in Cygwin Win7 & OSX 10.9
```python
Import('env')
env ###### env.Clone(CPPPATH './:./include')
env.Append(CXXFLAGS = ['-g', '-Wall', '-Wextra', '-pthread'])
gtest ###### env.Library(target 'gtest', source = ['src/gtest-all.cc', 'src/gtest_main.cc'])
Return('gtest')
```
Zie [code/build/scons]({{< relref "wiki/code/build/scons.md" >}})
#### Builden met Visual Studio
<img style='float: left;' src='/img//code/c/testing/screenshot.png|'>
Zie http://leefrancis.org/2010/11/17/google-test-gtest-setup-with-microsoft-visual-studio-2008-c/
Er zijn 2 `.sln` files voorzien in de msvc subdir bij de zipfile, één voor statische links en één voor dynamische. Afhankelijk van uw project (.DLL of .LIB gegenereerde uitkomst), ga je één van beiden moeten compileren. Als je van plan bent om `/MDd` te gebruiken (dll + debugging), gebruik dan `gtest-md.sln`.
Daarna kan je een nieuwe solution maken, package naar executable om de test zelf te runnen (om gtest testen te draaien). Verander deze dingen in het project:
1. General > Configuration type = Application (.EXE)
2. C/C++ > General > Additional Include dirs naar gtest/include verwijzen
3. C/C++ > Preprocessor > definitions toevoegen `_VARIADIC_MAX=10`
4. Code generation > Runtime library op `/MDd` of `/MTd` juist zetten (zie boven)
5. Linker > Additional Library directories > gtest/Debug (staan reeds binaries indien compiled)
6. Linker > Input > Additional dependencies = gtestd.lib;gtest_maind.lib;(rest)
7. Linker > System > SubSystem Console `/SYBSYSTEM:CONSOLE`
8. Linker > Input > Module Definition file leeg (indien van DLL naar EXE veranderd kan hier wat brol in zitten)
#### Visual Studio 2012 en STD problemen
Fouten als
```
1>a:<br/>gtest<br/>include<br/>gtest<br/>gtest-printers.h(550): error C2977: 'std::tuple' : too many template arguments
1> b:<br/>program files (x86)<br/>microsoft visual studio 2012<br/>vc<br/>include<br/>utility(73) : see declaration of 'std::tuple'
```
Op te lossen met een preprocessor macro _VARIADIC_MAX=10, zie http://stackoverflow.com/questions/12558327/google-test-in-visual-studio-2012
##### Integratie met Visual Studio 2008/2010
[GoogleTestAddin](http://googletestaddin.codeplex.com/documentation) (kopieer 2 files naar C:<br/>Users<br/>bkwog<br/>Documents<br/>Visual Studio 2008<br/>Addins, map misschien nog aanmaken)
Niet super nuttig, een knopje om testen snel te herdraaien (of één die geselecteerd is), beter dan post-build actie zie boven...
#### Integratie met Visual Studio 2012
[Google Test Adapter](http://visualstudiogallery.msdn.microsoft.com/f00c0f72-ac71-4c80-bf8b-6fe381548031) plugin (1.1 - geen actieve development?)

View File

@ -0,0 +1,140 @@
+++
title = "teamtest"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"testing",
"teamtest"
]
date = "2013-07-17"
+++
# Visual Studio 2005 TeamTest Framework
Hoofdartikel (2005, C# voorbeelden): http://msdn.microsoft.com/en-us/library/ms379625(v=vs.80).aspx
**Waarom**?
1. Zelfde syntax als built-in C# unit tests voor Visual Studio
2. Makkelijker te lezen dan bvb [code/c/testing/gtest]({{< relref "wiki/code/c/testing/gtest.md" >}})
3. Garbage collector van Managed C++, joepie (?)
4. Toch mogelijk om unmanaged native C++ te testen (zie onder), integratie VStudio.
**Waarom niet**?
1. Dropped support voor VS2012? zie [code/c/testing/testexplorer]({{< relref "wiki/code/c/testing/testexplorer.md" >}}) in de plaats (native C++)
2. `/cli` flag miserie (zie onder)
3. Onduidelijke syntax voor hardcore C++ users die niet aan C# gewend zijn
## Visual Studio 2008
Hiervoor moeten we een apart test project aanmaken dat met **/CLR** flag compileert om de .NET test suites te gebruiken (`using namespace Microsoft::VisualStudio::TestTools::UnitTesting;`):
Project > configuration properties > General > Common Language Runtime support
<img style='float: left;' src='/img//code/c/testing/clr_unittests.png |'>
Dit staat op `/clr:safe` indien je met VStudio 2008 een nieuwe test aan maakt via menu Test > New Test > Unit Test
Een voorbeeld header file om te testen:
```c
class MyClass {
public:
MyClass() {};
int addUp(int one, int two);
};
```
```c
#include "myclass.h"
#include <iostream>
using namespace std;
int MyClass::addUp(int one, int two)
{
return one + two;
}
```
#### Managed test code schrijven
Gebruik dezelfde manier als .NET Unit Testing framework met attributes - dit vereist dus de CLR flag. Voorbeeld:
```c
#include "stdafx.h"
#include "../libtest/myclass.h"
using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
namespace unittests
{
[TestClass]
public ref class MyClassTest
{
public:
[TestMethod]
void AddOne()
{
Assert::AreEqual(3, MyClass().addUp(1, 2));
};
};
}
```
**Assert** heeft een hoop static methods
#### een externe klasse testen die van een lib komt
Als je vanuit je test project wil refereren naar productie code/projecten, kan dit een probleem zijn:
```
MyClassTest.obj : error LNK2028: unresolved token (0A00000A) "public: __thiscall MyClass::MyClass(void)" (??0MyClass@@$$FQAE@XZ) referenced in function "public: void __clrcall unittests::MyClassTest::AddOne(void)" (?AddOne@MyClassTest@unittests@@$$FQ$AAMXXZ)
MyClassTest.obj : error LNK2028: unresolved token (0A00000B) "public: int __thiscall MyClass::addUp(int,int)" (?addUp@MyClass@@$$FQAEHHH@Z) referenced in function "public: void __clrcall unittests::MyClassTest::AddOne(void)" (?AddOne@MyClassTest@unittests@@$$FQ$AAMXXZ)
MyClassTest.obj : error LNK2019: unresolved external symbol "public: int __thiscall MyClass::addUp(int,int)" (?addUp@MyClass@@$$FQAEHHH@Z) referenced in function "public: void __clrcall unittests::MyClassTest::AddOne(void)" (?AddOne@MyClassTest@unittests@@$$FQ$AAMXXZ)
```
Dat wil zeggen, het compileert, maat het linkt niet. Oplossing: Voeg dit toe aan uw `stdafx.cpp`:
```c
#pragma comment(lib, "../Debug/libtest.lib")
```
gegeven dat "libtest" uw project under test is. Vanaf dan kan je normaal header files includen in uw test cpp file, zie boven.
#### een externe klasse testen die van een DLL komt
Er wordt pas een `.lib` file gegenereerd wanneer je `declspec(dllexport)` definiëert - wanneer niets exported is, kan er ook niets imported worden... Dus `myClass` aanpassen:
```c
#ifdef FRIENDCLASS_EXPORT
#define FRIENDCLASS __declspec(dllexport)
#else
#define FRIENDCLASS __declspec(dllimport)
#endif
class FRIENDCLASS MyClass {
public:
MyClass();
int addUp(int one, int two);
};
```
En dan het libtest project compileren met de extra preprocessor definitie `FRIENDCLASS_EXPORT` zodat in commandline `/D "FRIENDCLASS_EXPORT"` erbij komt. Zie ook [MSDN Preprocessor definitions](http://msdn.microsoft.com/en-us/library/hhzbb5c8(v=vs.80).aspx), nu kunnen we hierop checken in de code met `#ifdef`. Bovenstaande code doet een export wanneer gedefiniëerd, en een import anders - dit gebeurt wanneer we de header file includen vanuit onze test cpp file.
#### Debugging
:exclamation: [Debug information format flags](http://msdn.microsoft.com/en-us/library/958x11bc(v=vs.80).aspx): `/ZI` ("Edit and Continue feature", retry drukken bij assertion failure) is **niet** ondersteund in combinatie met `/cli`. Debuggen gaat wel op `/Zi` niveau.

View File

@ -0,0 +1,112 @@
+++
title = "testexplorer"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"testing",
"testexplorer"
]
date = "2013-09-05"
+++
# Visual Studio 2012 Test Explorer framework
**Waarom**?
1. Integratie VStudio, zelfde manier om te "runnen" als C# testen
2. __unmanaged__ (native) C++ code testen zonder vettige `/cli` mode die nodig is.
3. Voor mixed team C#/C++ misschien beter/makkelijker?
**Waarom niet**?
1. Weeral iets anders, Team Test buiten? Wat gaat het zijn voor VS3013?
2. Niet 100% dezelfde syntax als C# (toch al closer, maar bvb geen attributes etc)
3. VS2012 only momentel, dus 2008 = kinkloppen
Voorbeeld project in VS2012: <img style='' src='/img//code/c/testing/math_testexplorer_vs2012.zip|'>
#### Assertions schrijven
Gebruik namespace `CppUnitTestFramework` - voorbeeld:
```c
#pragma once
#include "stdafx.h"
#include "CppUnitTest.h"
#include "PlusStub.cpp"
#include "../Math/Plus.h"
#include "../Math/Calculator.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace calc
{
TEST_CLASS(CalculatorTest)
{
private:
int nStartValue;
Calculator* calc;
void CreateCalcSUT()
{
calc = new Calculator(nStartValue);
}
public:
/*testcase template:
TEST_METHOD(Classname_Functionname_SpecialParams_ExpectedResult)
{
param specialParam = specialvalue;
...
param expectation = whatYouExpect;
...
(SUT creation)
(call methods)
...
assert(s)
}*/
TEST_METHOD_INITIALIZE(InitialiseDefaults)
{
calc = NULL;
nStartValue = 5;
}
TEST_METHOD_CLEANUP(CleanupObjects)
{
delete calc;
}
TEST_METHOD(Calculator_Constructor_NoArgument_GetValueZero)
{
int nExpectedValue = 0;
calc = new Calculator();
Assert::AreEqual(nExpectedValue, calc->GetValue());
}
TEST_METHOD(Calculator_Constructor_Five_GetValueFive)
{
nStartValue = 5;
int nExpectedValue = 5;
CreateCalcSUT();
Assert::AreEqual(nExpectedValue, calc->GetValue());
}
};
}
```
<img style='' src='/img//code/c/testing/cppunittesting.png|'>
Zelfde manier om assertions te schrijven.
:exclamation: dit test project heeft GEEN `/clr` flag, dus is ook __unmanaged__, dat is het voordeel.
Zoals gezien op screencap is dit volledig geïntegreerd met VStudio 2012.
[Meer informatie over het nieuwe cpp testing framework 'Test Explorer'](http://msdn.microsoft.com/en-us/library/hh270864.aspx)

View File

@ -0,0 +1,126 @@
+++
title = "threading"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"threading"
]
date = "2013-12-02"
+++
# Threading
Handige links:
1. [Thread synchronization for beginners](http://www.codeproject.com/Articles/7953/Thread-Synchronization-for-Beginners)
## Thread-safe Singleton pattern
Bijna onmogelijk in C++ < v11 blijkbaar?
Onderstaand voorbeeld gebruikt Win32 code (`WaitForSingleObject`) en een mutex om te wachten:
```c++
#pragma once
#include <WinBase.h>
class AddinProcessService
{
static AddinProcessService *singletonInstance;
AddinProcessService() : m_coupon(_T("")), m_hostServiceAddress(_T("")) {}
public:
inline const CString& GetHostServiceAddress() const
{
return m_hostServiceAddress;
}
inline const CString& GetCoupon() const
{
return m_coupon;
}
inline void SetCoupon(CString coupon)
{
m_coupon = coupon;
}
inline void SetHostServiceAddress(CString address)
{
m_hostServiceAddress = address;
}
static AddinProcessService* getSingletonInstance()
{
static volatile int initialized = 0;
static HANDLE mtx;
if (!initialized)
{
if (!mtx)
{
HANDLE mymtx;
mymtx = CreateMutex(NULL, 0, NULL);
if (InterlockedCompareExchangePointer(&mtx, mymtx, NULL) != NULL)
CloseHandle(mymtx);
}
WaitForSingleObject(mtx, 0);
if (!initialized)
{
libInitInternal();
initialized = 1;
}
ReleaseMutex(mtx);
}
return singletonInstance;
};
private:
CString m_hostServiceAddress;
CString m_coupon;
static void libInitInternal()
{
singletonInstance = new AddinProcessService();
}
};
```
:exclamation: Vergeet niet in de cpp file uw singletonInstance pointer te declareren, anders krijg je linker errors: `AddinProcessService* AddinProcessService::singletonInstance;`
In UNIX kan men [pthreads](https://computing.llnl.gov/tutorials/pthreads/) gebruiken, ongeveer op deze manier:
```c++
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst ###### NULL)
{
pthread_mutex_lock(&mutex);
if(inst ###### NULL)
inst = new Foo(...);
pthread_mutex_unlock(&mutex);
}
return *inst;
}
```
Dan kan je `#ifdef WIN32` gebruiken om te switchen tussen beide implementaties.
############ C++ 11 multithreading ############
Vanaf C++ 11 zijn multithreads 100% native supported, dit wil zeggen dat manueel locken met een `mutex` overbodig wordt. Bovenstaande singleton kan gereduceerd worden tot (merk het **static** keyword op, dat is het belangrijkste voor de autolock):
```c++
static Singleton& get(){
static Singleton instance;
return instance;
}
```
Voor meer info, zie http://stackoverflow.com/questions/11711920/how-to-implement-multithread-safe-singleton-in-c11-without-using-mutex

View File

@ -0,0 +1,55 @@
+++
title = "win32specifics"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"c",
"win32specifics"
]
date = "2013-12-12"
+++
# code:c >> Win32 API specifics
#### Get Loaded DLL info from given process
huidig proces: `GetCurrentProcessId()` - dit is een `HANDLE`.
```c++
CString ExceptionHandler::GetLoadedDllInfo() const
{
CString dlls = _T("");
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
if(process ###### NULL)
{
return dlls;
}
HMODULE hMods[1024];
DWORD cbNeeded;
BOOL modules = EnumProcessModules(process, hMods, sizeof(hMods), &cbNeeded);
if(!modules)
{
return dlls;
}
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(process, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
dlls.Format(_T("%s, %s"), dlls, szModName);
}
}
CloseHandle(process);
return dlls;
}
```
Hiervoor moet je `#include <psapi.h>` includen én de psapi.lib file mee linken! Zie [EnumProcessModules MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682631(v=vs.85).aspx).

View File

@ -0,0 +1,20 @@
+++
title = "ceylon"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"ceylon"
]
date = "2013-11-13"
+++
# Ceylon
#### Interessant leesmateriaal
1. [Why is there no protected visibility modifier in Ceylon?](http://ceylon-lang.org/documentation/1.0/faq/language-design/#no_protected_modifier)
2. [Ceylon 1.0 Tour](http://ceylon-lang.org/documentation/1.0/tour/) die vergelijkingen met Java en C# legt op gebied van functies, variabelen, klassen, lambda's, ...

View File

@ -0,0 +1,19 @@
+++
title = "csharp"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp"
]
date = "2013-12-03"
+++
# code >> Csharp
## Inhoudsopgave
<img style='' src='/img/indexmenu>code/csharp|js navbar nocookie'>

View File

@ -0,0 +1,20 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"home"
]
date = "2013-07-19"
+++
# C# Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

View File

@ -0,0 +1,85 @@
+++
title = "aspdotnet"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"aspdotnet"
]
date = "2014-06-30"
+++
# ASP.NET
### Troubleshooting
#### 'WebForm_DoPostBackWithOptions' is undefined in IE1
Probleem: [How to get your ASP.NET application working in IE11](http://blogs.telerik.com/aspnet-ajax/posts/13-12-19/how-to-get-your-asp.net-application-working-in-ie11)
Fix: [App_Browsers](http://www.shubho.net/2011/01/what-is-appbrowsers-folder-in-aspnet.html) folder aanmaken in uw webapp en een `.browser` file toevoegen:
```xml
<browsers>
<browser id######"IE11" parentID"Mozilla">
<identification>
<userAgent match="Trident/(?'layoutVersion'[7-9]|0*[1-9]<br/>d+)(<br/>.<br/>d+)?;(.*;)?<br/>s*rv:(?'version'(?'major'<br/>d+)(<br/>.(?'minor'<br/>d+)))" />
<userAgent nonMatch="IEMobile" />
</identification>
<capture>
<userAgent match="Trident/(?'layoutVersion'<br/>d+)" />
</capture>
<capabilities>
<capability name######"browser" value"IE" />
<capability name######"layoutEngine" value"Trident" />
<capability name######"layoutEngineVersion" value"${layoutVersion}" />
<capability name######"extra" value"${extra}" />
<capability name######"isColor" value"true" />
<capability name######"letters" value"${letters}" />
<capability name######"majorversion" value"${major}" />
<capability name######"minorversion" value"${minor}" />
<capability name######"screenBitDepth" value"8" />
<capability name######"type" value"IE${major}" />
<capability name######"version" value"${version}" />
</capabilities>
</browser>
<!-- Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11,0) like Gecko -->
<browser id######"IE110" parentID"IE11">
<identification>
<capability name######"majorversion" match"11" />
</identification>
<capabilities>
<capability name######"ecmascriptversion" value"3.0" />
<capability name######"jscriptversion" value"5.6" />
<capability name######"javascript" value"true" />
<capability name######"javascriptversion" value"1.5" />
<capability name######"msdomversion" value"${majorversion}.${minorversion}" />
<capability name######"w3cdomversion" value"1.0" />
<capability name######"ExchangeOmaSupported" value"true" />
<capability name######"activexcontrols" value"true" />
<capability name######"backgroundsounds" value"true" />
<capability name######"cookies" value"true" />
<capability name######"frames" value"true" />
<capability name######"javaapplets" value"true" />
<capability name######"supportsCallback" value"true" />
<capability name######"supportsFileUpload" value"true" />
<capability name######"supportsMultilineTextBoxDisplay" value"true" />
<capability name######"supportsMaintainScrollPositionOnPostback" value"true" />
<capability name######"supportsVCard" value"true" />
<capability name######"supportsXmlHttp" value"true" />
<capability name######"tables" value"true" />
<capability name######"supportsAccessKeyAttribute" value"true" />
<capability name######"tagwriter" value"System.Web.UI.HtmlTextWriter" />
<capability name######"vbscript" value"true" />
</capabilities>
</browser>
</browsers>
```
**ofwel** .NET 4.5 op server installeren (ook al gebruik je 4.0!)

View File

@ -0,0 +1,240 @@
+++
title = "classes"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"classes"
]
date = "2014-01-29"
+++
# Classes
## Dynamically creating instances
Gebruik `Activator`:
```csharp
Activator.CreateInstance(type) as MyType
```
## Overrides en shadowing: 'new' en 'virtual'
Zie onder andere:
1. http://stackoverflow.com/questions/1014295/new-keyword-in-method-signature
2. http://stackoverflow.com/questions/9892468/java-is-there-java-equivalent-for-c-sharp-new-keyword-in-method-signature-how
In java zijn alle methods `virtual`, dat wil zeggen dat ze overschrijfbaar zijn (`@Override`) zodat de method in de diepst geneste polymorfe structuur gebruikt wordt. In C# is daarvoor het keyword `virtual` nodig:
```csharp
public class A
{
public virtual void One();
public void Two();
}
public class B : A
{
public override void One();
public new void Two();
}
B b = new B();
A a = b as A;
a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B
```
De concretere klasse moet dan overriden met `override` dat niet gaat als het niet `virtual` is (je kan ook niet overerven waarbij een klasse `sealed` is, zoals `final` in java). Wat hier wel opmerkelijk is, is het gebruik van het keyword `new` in de tweede method "Two". Hierbij kan je de eerste implementatie toch nog hiden, maar je moet wel upcasten! Misschien is dit nog handig bij het schrijven van legacy testen?
Het is in java niet mogelijk om een `final` method te overriden. (Private telt natuurlijk niet mee...) In C# is het [wel mogelijk om halverwege de chain te sealen](http://msdn.microsoft.com/en-us/library/aa645769(v=vs.71).aspx)!
## Closures en Lambda's
Interessante links:
1. [Lambda expressions MSDN C# programming guide](http://msdn.microsoft.com/en-us/library/bb397687.aspx)
2. [Expression Trees MSDN](http://msdn.microsoft.com/en-us/library/bb397951.aspx) hier worden lambda's gebruikt voor LINQ
### Passing on 'work' to a method, to execute the lambda
In Java:
```java
public interface Workable<T> {
public T work();
}
public class MyWork extends Workable<MyObj> {
public MyObj work() {
// do stuff here
}
}
public class Executer {
public <T> T doStuff(Workable<T> w) {
prepare();
T result = w.work();
cleanup();
}
public MyObj createMyObj() {
return doStuff(new MyWork());
}
}
```
Basically, gebruik interfaces. Pijnlijk en verbose. In C# kan je `() =>` gebruiken om een anonieme method aan te maken, en `Func<>` als type gebruiken. <br/><br/>
Concreet voorbeeld:
```csharp
internal virtual T Execute<T>(Func<T> work)
{
Connection.Open();
var transaction = Connection.BeginTransaction();
try
{
var retVal = work.Invoke();
transaction.Commit();
return retVal;
}
catch (Exception)
{
transaction.Rollback();
throw;
}
finally
{
Connection.Close();
}
}
public bool BlaBla()
{
return Execute(() =>
{
// do query stuff in here.
return true;
});
}
```
##### Q: Wat is het verschil tussen een Lambda (>()) en een delegate? ######
A: niets; zie voorbeeld:
```csharp
Func<string, int> giveLength = delegate(string text) { return text.Length; };
Func<string, int> giveLength ###### (text > text.length);
```
de `=>` notatie is nieuwer.
###### Q: Wat is het verschil tussen een expression type en een anonymous type? ######
http://stackoverflow.com/questions/299703/delegate-keyword-vs-lambda-notation
> If you assign the lambda to a delegate type (such as Func or Action) you'll get an anonymous delegate.
If you assign the lambda to an Expression type, you'll get an expression tree instead of a anonymous delegate. The expression tree can then be compiled to an anonymous delegate.
Edit: Here's some links for Expressions.
Zeer interessant artikel: http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx
############ Nested (inner) classes in C# ############
http://blogs.msdn.com/b/oldnewthing/archive/2006/08/01/685248.aspx - C# heeft geen referentie naar de outer class (`$0` die in Java er impliciet is), bijgevolg moet je dit zelf bijhouden.
Zie ook http://stackoverflow.com/questions/4770180/anonymous-inner-classes-in-c-sharp
############ Modules as anonymous inner classes, JavaScript pattern ############
```javascript
var Mod = (function(consoleDep) {
function yo() {
consoleDep.log("yo");
}
return {
hi: yo
};
})(console);
Mod.hi();
```
equals
```csharp
private interface ILoggable
{
void Log(string msg);
}
private class Console : ILoggable
{
public void Log(string msg)
{
Debug.WriteLine(msg);
}
}
[TestMethod]
public void TestMe()
{
var Mod ###### new Func<ILoggable, Dictionary<string, Action>>((consoleDep) >
{
Action yo ###### () > consoleDep.Log("yo");
return new Dictionary<string, Action>
{
{ "hi", yo }
};
})(new Console());
Mod["hi"]();
}
```
Problemen
* cannot assign lambda expression to an implicitly-typed local variable (`var` bij de yo ipv `Action`)
* duck typing for module dependencies??
############= Enums in C# ############=
Zie ook http://stackoverflow.com/questions/469287/c-sharp-vs-java-enum-for-those-new-to-c
> Enumerations in the CLR are simply named constants. The underlying type must be integral. In Java an enumeration is more like a named instance of a type. That type can be quite complex and - as your example shows - contain multiple fields of various types.
Optie 1: gebruik **extensions** (nog altijd een switch nodig omdat het type in algemene vorm binnen komt)
Optie 2: maak uw eigen enum klasse door immutable readonly classes te maken:
```c#
class Planet
{
public static readonly Planet EARTH = new Planet("earth");
private string name;
private Planet(string name)
{
this.name = name;
}
public static IEnumerable<Planet> Values
{
// return set of planets
}
}
```

View File

@ -0,0 +1,147 @@
+++
title = "dynamica"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"dynamica"
]
date = "2014-11-05"
+++
# Dynamica
Zie ook [code/csharp/reflectie]({{< relref "wiki/code/csharp/reflectie.md" >}})
### Expression trees opbouwen
##### Van een MethodInfo instantie naar een Func<>
```csharp
var instanceToMemoize = Activator.CreateInstance<TClassToMemoize>();
foreach (var method in instanceToMemoize.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
{
var parameters ###### method.GetParameters().Select(p > Expression.Constant("test"));
var expr = Expression.Lambda(Expression.Call(Expression.Constant(instanceToMemoize), method, parameters)).Compile();
_Delegates.Add(method.ToString(), expr);
}
```
Argumenten stuk klopt nog niet. Refs:
1. http://stackoverflow.com/questions/2933221/can-you-get-a-funct-or-similar-from-a-methodinfo-object
2. http://stackoverflow.com/questions/11367830/how-to-find-full-name-of-calling-method-c-sharp
##### Memoization
Ook mogelijk via `Func<>` wrappers; zie
1. http://www.jaylee.org/post/2013/04/18/Memoization-and-Immutable-data-in-CSharp-Part-1.aspx
2. http://www.jaylee.org/post/2013/04/22/Immutable-Data-and-Memoization-in-CSharp-Part-2.aspx
Dit is een extension die 2 type arguments aanvaard:
```csharp
public static Func<TArg1, TArg2, TResult> AsMemoized<TArg1, TArg2, TResult>(this Func<TArg1, TArg2, TResult> func)
{
var values = new Dictionary<MemoizedKey<TArg1, TArg2>, TResult>();
return (arg1, arg2) => MemoizedValue(func, arg1, arg2, values);
}
public static Func<TArg, TResult> AsMemoized<TArg, TResult>(this Func<TArg, TResult> funcArg)
{
Func<TArg, object, TResult> func ###### (arg1, arg2) > funcArg(arg1);
var values = new Dictionary<MemoizedKey<TArg, object>, TResult>();
return (arg) => MemoizedValue(func, arg, null, values);
}
private static TResult MemoizedValue<TArg1, TArg2, TResult>(Func<TArg1, TArg2, TResult> func, TArg1 arg1, TArg2 arg2, Dictionary<MemoizedKey<TArg1, TArg2>, TResult> values)
{
TResult value;
var memoizedKey = new MemoizedKey<TArg1, TArg2>(arg1, arg2);
if (!values.TryGetValue(memoizedKey, out value))
{
value ###### values[memoizedKey] func(memoizedKey.Arg1, memoizedKey.Arg2);
}
return value;
}
private class MemoizedKey<TArg1, TArg2>
{
public MemoizedKey(TArg1 arg1, TArg2 arg2)
{
Arg1 = arg1;
Arg2 = arg2;
}
public TArg1 Arg1 { get; private set; }
public TArg2 Arg2 { get; private set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((MemoizedKey<TArg1, TArg2>)obj);
}
public override int GetHashCode()
{
unchecked
{
return (EqualityComparer<TArg1>.Default.GetHashCode(Arg1) * 397) ^ EqualityComparer<TArg2>.Default.GetHashCode(Arg2);
}
}
private bool Equals(MemoizedKey<TArg1, TArg2> other)
{
return EqualityComparer<TArg1>.Default.Equals(Arg1, other.Arg1) && EqualityComparer<TArg2>.Default.Equals(Arg2, other.Arg2);
}
}
```
Equals is nodig voor de `Dictionary` (generated).
### Aspect Oriented Programming
**PostSharp**: [http:*www.postsharp.net](http:*www.postsharp.net)
#### Transacties wiren
Zie [code/csharp/persistence]({{< relref "wiki/code/csharp/persistence.md" >}})
#### Aspects applyen op assembly level
Q: Ik wil AOP toepassen voor alle klassen (& [publieke] methods) in een bepaald project (DLL)<br/><br/>
A: Gebruik [Multicasting aspects](http://www.postsharp.net/aspects/multicasting).
Bijvoorbeeld, om exceptions overal op te vangen, en dan door te delegeren, evt screenshot van de app te nemen:
```csharp
[assembly: ScenarioTests.ScenarioExceptionHandler]
namespace ScenarioTests
{
[Serializable]
[ScenarioExceptionHandler(AttributeExclude = true)]
public class ScenarioExceptionHandler : OnMethodBoundaryAspect
{
public override void OnException(MethodExecutionArgs args)
{
WebDriverExceptionHandler.Handle(args.Exception);
base.OnException(args);
}
}
}
```
De eerste regel, `[assembly:]` is van belang, zie documentatie. Je kan ook verder filteren by visibility etc, zoals in [Spring AOP/AspectJ]({{< relref "wiki/code/java/dynamica/aspectj.md" >}}) de strings in XML gedfiniëerd zijn.

View File

@ -0,0 +1,82 @@
+++
title = "linq"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"linq"
]
date = "2014-01-29"
+++
# Collections, Iterating, ???, Linq (profit)
## yield hocus pocus
Zie [The implementation of iterators in C#](http://blogs.msdn.com/b/oldnewthing/archive/2008/08/12/8849519.aspx) - wordt uitgelegd hoe `yield` door de compiler geïnterpreteerd wordt.
Hiermee is het mogelijk om heel snel uw eigen `IEnumerable` te maken.
> “yield”, [...] which allows you to quickly write iterators without worrying about preserving state.
## Folding, selecting, etc
### Closing over the loop variable
Main article: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx
Opgelet met `foreach` en de manier waarop die geïmplementeerd is (onder C# 5):
```csharp
{
IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();
try
{
int m; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
```
de variabele `m` verandert constant. Wanneer we in een loop dan een `delegate` gebruiken die de variabele uitleest, krijgen we op moment van executie slechts de laatste waarde!
```csharp
var values = new List<int>() { 100, 110, 120 };
var funcs = new List<Func<int>>();
foreach(var v in values)
funcs.Add( ()=>v );
foreach(var f in funcs)
Console.WriteLine(f()); // print 120, 120, 120, whoops??
```
### side-effects
Zie ook [foreach vs ForEach](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx): `LINQ` is ontwikkeld om side-effect free te werken, dit wil zeggen dat er altijd een nieuwe collectie aangemaakt wordt. De volgende code is niet voldoende om in een method een lijst te sorteren:
```csharp
private void sortMe(IEnumerable<string> toSort) {
toSort.ToList().Sort(); // ToList() returns a new list! as it should be
}
```
### naming
1. Gebruik `Select()` in plaats van de JS `transform()`.
2. `Aggregate` is een native `foldLeft` - gebruik `Reverse` om van achter naar voor te beginnen.
3. `All` retrourneert een boolean en is om te controleren of er elementen in een collectie zitten, niet om te transformen of te loopen!
### Achterliggende implementatiedetails
http://community.bartdesmet.net/blogs/bart/archive/2008/08/17/folding-left-right-and-the-linq-aggregation-operator.aspx

View File

@ -0,0 +1,306 @@
+++
title = "linqtosql"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"linqtosql"
]
date = "2015-07-14"
+++
# code:csharp >> Linqtosql
Zie ook [MSDN LinqToSql pagina](https://msdn.microsoft.com/en-us/library/bb425822.aspx)
## Basic
Principe is een **DataContext** object aanmaken waar je je connectionstring aan meegeeft (`Log` kan naar `Console.Out` ofzo). Vanaf dan via het context object werken:
* `context.GetTable<T>().Where(t ######> t.Property x).ToList()` om te queryen
* bij deleten of wijzigen: `.Attach(entity)` en `.DeleteOnSubmit(entity)`
* ...
Modellen: annoteren met `[Table(Name######"tabelnaam")]`, kolommen met `[Column(Name"kolomnaam", IsPrimaryKey ###### true, IsDbGenerated true)]`
Wijzigingen doorvoeren met `SubmitChanges()` door simpelweg properties van modellen te wijzigen, zoals een "echte" ER tool.
## Advanced
#### ManyToOne relaties en domain driven design
In het model: `[Association(ThisKey ###### "ReferenceId", IsForeignKey true)]` attribuut toevoegen.
Als je een Fetch wil doen en associaties ook wenst op te halen moet je dit **altijd meegeven**: `new DataLoadOptions().LoadWith<T>(t => t.AssociationProperty)`. Ook deze loadoptions meegeven aan de context.
Indien dit overgeslagen wordt, zal bij een ToList in LINQ die property niet opgehaald worden. Dit is vervelend om elke keer mee te geven - kan ook generiek, bijvoorbeeld zo:
```csharp
private static void AddLoadOptions<T>(DataContext context) where T : class, new()
{
if (IsAssociation<T>())
{
var loadOps = new DataLoadOptions();
((IAssociationModel)new T()).AssociationsToLoad(loadOps);
context.LoadOptions = loadOps;
}
}
private static bool IsAssociation<T>() where T : class, new()
{
return typeof(IAssociationModel).IsAssignableFrom(typeof(T));
}
```
`AddLoadOptions` altijd aanroepen wanneer een fetch in een repository zou gebeuren. Dit zit er op de interface:
```csharp
public interface IAssociationModel
{
IList<object> AssocationsToAttach();
void AssociationsToLoad(DataLoadOptions loadOps);
}
```
Zo kan iedere entiteit zijn eigen `LoadWith` oproepen.
#### Transacties
Gebruik `TransactionScope` object, aanmaken voor je iets doet en `.Complete()` of `.Dispose()` oproepen. <br/><br/>
Om dit niet de helel tidj zelf te moeten beheren, complexiteit opbergen in een basis Repository klasse, zoiets:
```csharp
using (var repo = Repository.Instance.Transactional())
{
Fetch(); // ...
Delete();
// ...
}
```
om dan in de `Dispose()` de transactie te completen. De transactionele method maakt een scope aan.
## Compleet voorbeeld repository
```chsarp
public class Repository : IRepository
{
private readonly string _ConnectionString;
private DataContext _CurrentContext;
private TransactionScope _TransactionScope;
public Repository(string connectionString)
{
_ConnectionString = connectionString;
}
private Repository(Repository baseRepo)
: this(baseRepo._ConnectionString)
{
_CurrentContext = CreateContext();
_TransactionScope = new TransactionScope();
}
public static IRepository Instance { get; set; }
private bool InTransaction
{
get { return _TransactionScope != null; }
}
public void Add<T>(T entity) where T : class, new()
{
InContext(context =>
{
var table = context.GetTable<T>();
if (IsAssociation<T>())
{
foreach (var toAttach in ((IAssociationModel)entity).AssocationsToAttach())
{
context.GetTable(toAttach.GetType()).Attach(toAttach);
}
}
table.InsertOnSubmit(entity);
});
}
public void Add<T>(IEnumerable<T> entities) where T : class
{
InContext(context => context.GetTable<T>().InsertAllOnSubmit(entities));
}
public void CommitChanges<T>(T entity) where T : class
{
InContext(context =>
{
var entityTable = context.GetTable<T>();
if (!InTransaction)
{
entityTable.Attach(entity);
}
context.Refresh(RefreshMode.KeepCurrentValues, entity);
});
}
public int Count<T>(ICanModifyIQueryable<T> queryModifier) where T : class, new()
{
return InContext(context =>
{
AddLoadOptions<T>(context);
IQueryable<T> list = context.GetTable<T>();
list = queryModifier.ModifyForCount(list);
return list.Count();
});
}
public void Delete<T>(T entity) where T : class
{
InContext(context =>
{
var entityTable = context.GetTable<T>();
if (!InTransaction)
{
entityTable.Attach(entity);
}
entityTable.DeleteOnSubmit(entity);
});
}
public void Dispose()
{
CompleteTransaction();
}
public List<T> Fetch<T>() where T : class, new()
{
return InContext(context =>
{
AddLoadOptions<T>(context);
return context.GetTable<T>().ToList();
});
}
public List<T> FetchBy<T>(Expression<Func<T, bool>> whereClause) where T : class, new()
{
return InContext(context =>
{
AddLoadOptions<T>(context);
return context.GetTable<T>()
.Where(whereClause)
.ToList();
});
}
public List<T> FetchBy<T>(ICanModifyIQueryable<T> queryModifier) where T : class, new()
{
return InContext(context =>
{
AddLoadOptions<T>(context);
IQueryable<T> list = context.GetTable<T>();
list = queryModifier.Modify(list);
return list.ToList();
});
}
public IRepository Transactional()
{
return new Repository(this);
}
private static void AddLoadOptions<T>(DataContext context) where T : class, new()
{
if (IsAssociation<T>())
{
var loadOps = new DataLoadOptions();
((IAssociationModel)new T()).AssociationsToLoad(loadOps);
context.LoadOptions = loadOps;
}
}
private static bool IsAssociation<T>() where T : class, new()
{
return typeof(IAssociationModel).IsAssignableFrom(typeof(T));
}
private void CompleteTransaction()
{
if (_CurrentContext ###### null || !InTransaction)
{
return;
}
try
{
_CurrentContext.SubmitChanges();
_TransactionScope.Complete();
}
finally
{
_TransactionScope.Dispose();
_CurrentContext.Dispose();
_TransactionScope = null;
_CurrentContext = null;
}
}
private DataContext CreateContext()
{
return new DataContext(_ConnectionString) { Log = Console.Out };
}
private void InContext(Action<DataContext> action)
{
InContext(context =>
{
action(context);
return true;
});
}
private T InContext<T>(Func<DataContext, T> action)
{
var context = _CurrentContext;
var newContext = false;
if (context ###### null)
{
context = CreateContext();
newContext = true;
}
try
{
// context.Log = Console.Out;
var value = action(context);
if (newContext)
{
context.SubmitChanges();
}
return value;
}
finally
{
if (newContext)
{
context.Dispose();
}
}
}
}
```

View File

@ -0,0 +1,65 @@
+++
title = "meta"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"meta"
]
date = "2014-02-13"
+++
# Metaprogramming
### Tests on source code contents
Wat is de bedoeling? Lees alle source files in en check of er iets in voorkomt (in onderstaand geval `Bla.Instance`)
De `GoUpThreeDirs` is omdat bij unit testen draaien dit in rootDir/unitTestProject/Bin/Debug uitgevoerd wordt, dat is de huidige dir. wij hebben nodig: rootDir/sourceCodeProject.
```csharp
[TestMethod]
public void StaticInstanceShouldNeverBeUsedExceptInAllowedCases()
{
foreach (var file in Directory.GetFiles(GetSourcePath(), "*.cs", SearchOption.AllDirectories))
{
var source = File.ReadAllText(file);
if (source.Contains(typeof(Bla).Name + ".Instance") && NoStaticRefAllowedInThatFile(file))
{
Assert.Fail("file " + file + " contains a static reference to Bla which is not allowed!" +
"Please use Dependency Injection instead, take a look at the existing repositories as an example.");
}
}
}
private bool NoStaticRefAllowedInThatFile(string file)
{
List<Type> allowedTypesWithInstanceRef = new List<Type>()
{
typeof(Bla),
typeof(Blie)
};
return allowedTypesWithInstanceRef.All(x => !file.Contains(x.Name));
}
private static string GetSourcePath()
{
return GoUpThreeDirectories(Environment.CurrentDirectory) + "<br/><br/>ProjectNameOfSourceCode";
}
private static string GoUpThreeDirectories(string dir)
{
string rootDir = dir;
for (var i ###### 1; i < 3; i++)
{
rootDir = rootDir.Substring(0, rootDir.LastIndexOf("<br/><br/>", StringComparison.Ordinal));
}
return rootDir;
}
}
```

View File

@ -0,0 +1,178 @@
+++
title = "nativecalls"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"nativecalls"
]
date = "2013-12-13"
+++
# C++ Native calls uitvoeren
#### Voorbeeld project
Wat is het probleem:
1. Ik wil Native C++ methods kunnen aanroepen vanuit C#. Dit kan met de `DllImport` attribute.
2. Ik wil structs kunnen remarshallen die uit de native code komen. Dit kan met `StructLayout` en `PtrToStructrue`.
3. Ik wil een char* mappen op een C# string: gebruik `[MarshalAsAttribute(UnmanagedType.LPStr)]` in uw C# struct.
4. Ik wil parameters mee kunnen geven: gebruik de juiste calling method (STD of DECL) instelling, zie `CallingConvention` op `UnmanagedFunctionPointer`.
```c++
#pragma once
#ifdef _DLL
#define DllExImport __declspec(dllexport)
#else
#define DllExImport __declspec(dllimport)
#endif
struct MyStruct
{
char* id;
char* description;
};
DllExImport MyStruct* __stdcall GetSignals();
```
```c++
#include "stdafx.h"
#include "TestClass.h"
DllExImport MyStruct* __stdcall GetSignals()
{
static MyStruct a[] =
{
{ "id1", "desc1" },
{ "id2", "desc2" },
{ "id3", "desc3" }
};
return a;
}
```
```csharp
namespace structArrayImportTest
{
#region
using System;
using System.Runtime.InteropServices;
#endregion
internal class StructImporter
{
// Charset.Ansi is not needed it seems
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
private static extern IntPtr LoadLibrary(
[MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
private static extern IntPtr GetProcAddress(IntPtr hModule,
[MarshalAs(UnmanagedType.LPStr)] string lpProcName);
[DllImport("kernel32", SetLastError ###### true, EntryPoint "GetProcAddress")]
private static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName);
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
private static extern bool FreeLibrary(int hModule);
[StructLayout(LayoutKind.Sequential)]
public class MyStruct
{
[MarshalAsAttribute(UnmanagedType.LPStr)]
public string _id;
[MarshalAsAttribute(UnmanagedType.LPStr)]
public string _description;
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr fGetSignals();
public fGetSignals GetSignals;
public void Import()
{
IntPtr lib = LoadLibrary(@"C:<br/>Users<br/>bkwog<br/>Documents<br/>Visual Studio 2012<br/>Projects<br/>structArrayExportTest<br/>Debug<br/>structArrayExportTest.dll");
// gebruik dumpbin /exports [bla.dll] om ordinal & name van exported functions te bepalen.
IntPtr signalsHandle = GetProcAddressOrdinal(lib, new IntPtr(1));
GetSignals = (fGetSignals) Marshal.GetDelegateForFunctionPointer(signalsHandle, typeof (fGetSignals));
IntPtr myStructs = GetSignals();
int structSize = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine(structSize);
for (int i = 0; i < 3; ++i)
{
// What's the difference between toInt32 & 64 here? Both work...
IntPtr data = new IntPtr(myStructs.ToInt64() + structSize * i);
MyStruct ms = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
Console.WriteLine("id: " + ms._id + " - descr: " + ms._description );
}
}
}
}
```
#### Calling convention
In te stellen via C++ project settings -> advanced -> calling convention, voor alles, of per functie met `__stdcall`. C# werkt hiet default mee. Aanpasbaar in het attribute, zie boven.
Als de calling convention niet overeen zou komen, krijg je bij het uitvoeren in de C# code de volgende fout:
> call to PInvoke function 'structArrayImportTest!structArrayImportTest.StructImporter+fGetSignals::Invoke' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
#### dumpbin
Als je niet met ordinals wenst te werken maar de volledige naam van de functie kan jet met `dumpbin.exe` dit achterhalen:
```
C:<br/>Program Files (x86)<br/>Microsoft Visual Studio 10.0<br/>Common7<br/>IDE>dumpbin /exports TfsAdmin.exe structArrayExportTest.dll
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file TfsAdmin.exe
File Type: EXECUTABLE IMAGE
Dump of file structArrayExportTest.dll
File Type: DLL
Section contains the following exports for structArrayExportTest.dll
00000000 characteristics
52A888CA time date stamp Wed Dec 11 16:46:18 2013
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00011113 ?GetSignals@@YAPAUTestStruct@@XZ
2 1 000110E6 ?GetSize@@YAPAHXZ
Summary
1000 .data
1000 .idata
3000 .rdata
3000 .reloc
11000 .rsrc
8000 .text
10000 .textbss
```
Merk op dat de functie `GetSignals` hier niet die naam heeft, maar `?GetSignals@@YAPAUTestStruct@@XZ`!

View File

@ -0,0 +1,565 @@
+++
title = "persistence"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"persistence"
]
date = "2015-07-13"
+++
# Persistence
## NHibernate
### Second level caching
Gebruik [SysCache2](http://www.codeproject.com/Articles/529016/NHibernate-Second-Level-Caching-Implementation) voor Web projecten. Hoe enablen? DLL ref + in config:
```csharp
Configuration.SessionFactory().Caching.Through<SysCacheProvider>().WithDefaultExpiration(60);
Configuration.SetProperty(Environment.UseSecondLevelCache, "true");
Configuration.SetProperty(Environment.UseQueryCache, "true");
```
In hbm mappings moet je entiteiten cache-baar markeren (read-only, read-write, ... zie docs) met `<cache usage="read-write" />`. Vanaf dan kan je aan Criteria of LINQ queries dingen doen als:
1. `Session.Query<Obj>().Cachable().List()` of
2. `Session.CreateCriteria<Obj>().SetCachable(true)`
Groeperen in "regions" is ook mogelijk, mee te geven met criteria.
#### Clearing everything
```csharp
SessionFactory.EvictQueries();
foreach (var collectionMetadata in SessionFactory.GetAllCollectionMetadata())
SessionFactory.EvictCollection(collectionMetadata.Key);
foreach (var classMetadata in SessionFactory.GetAllClassMetadata())
SessionFactory.EvictEntity(classMetadata.Key);
```
#### Using regions
Sectie toevoegen in `configSections`:
```
<section name######"syscache2" type"NHibernate.Caches.SysCache2.SysCacheSection, NHibernate.Caches.SysCache2"/>
```
En dan dit stuk bijvoorbeeld om syscache2 te configureren:
```
<syscache2>
<cacheRegion name######"RegionName" priority"High">
<dependencies>
<commands>
<add name="test"
command="Select col from dbo.[Table]"
connectionName="default"
connectionStringProviderType="Utilities.Connection.SysCache2ConnectionStringProvider, PFW.Utilities"/>
</commands>
</dependencies>
</cacheRegion>
</syscache2>
```
Queries en entiteiten laten cachen via die naam.
Er is een standaard connectionStringProvider die uit het `connectionStrings` stuk uit de web/app.config uw string uitleest geïmplementeerd: `ConfigConnectionStringProvider`. Indien iets custom nodig zoals in bovenstaand voorbeeld, afleiden van `IConnectionStringProvider` en zelf de connectionstring voorzien (connectionName wordt als parameter meegegeven maar is in dit geval nutteloos).
Op database niveau moet je ook nog een aantal dingen nagaan:
1. Is de dbo user eigenaar van de database voor het region command uit te voeren? (`use [DbName] EXEC sp_changedbowner 'sa`')
2. Is de broker service actief? Indien neen zet aan, zie [code/db/mssql]({{< relref "wiki/code/db/mssql.md" >}})
### LINQ OR queries schrijven
AND queries zijn makkelijk te schrijven met `.Where()` chaining in LINQ. Hoe doe je dit met SQL ORs? Met de PredicateBuilder:
```csharp
/// <summary>
*/ http:*www.albahari.com/nutshell/predicatebuilder.aspx
/// </summary>
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters);
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return f => false;
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters);
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> True<T>()
{
return f => true;
}
}
```
Voorbeeld:
```csharp
var pred = PredicateBuilder.False<IOccupation>();
pred ###### pred.Or(occ > new List<decimal>() {1, 2}.Contains(occ.Id));
pred ###### pred.Or(occ > new List<decimal>() {1, 2}.Contains(occ.Id));
Session.Query<IOccupation>()
.Where(pred)
.ToList();
```
### Sessie contexten
* [Current session architecture](http://www.nhforge.org/doc/nh/en/index.html#architecture-current-session)
Te mappen in xml:
```xml
<property name="current_session_context_class">thread_static</property>
```
Zelf te (un-)binden via:
```csharp
var session = sessionFactory.OpenSession();
if (!CurrentSessionContext.HasBind(sessionFactory))
{
CurrentSessionContext.Bind(session);
}
```
Dan kan je `SessionFactory.GetCurrentSession()` gebruiken.
Een typische manier van werken is session-per-request, in begin van request een sessie openen & binden, en op het einde sluiten. Dit zorgt voor problemen bij asynchrone calls omdat de sessie gebind wordt op `HttpContext` die dan uiteraard verdwenen is. Een tussenoplossing is werken met een hybride sessie context: gebruik de HTTP context indien mogelijk, werk anders met een `ThreadStatic` variabele. Bijvoorbeeld:
```csharp
public class HybridWebSessionContext : WebSessionContext
{
private const string _SessionFactoryMapKey = "NHibernate.Context.WebSessionContext.SessionFactoryMapKey";
[ThreadStatic]
private static IDictionary _ThreadSessionMap;
private ISession ThreadSession
{
set
{
if (_ThreadSessionMap ###### null)
{
_ThreadSessionMap = new Dictionary<ISessionFactoryImplementor, ISession>();
}
if (value ###### null)
{
_ThreadSessionMap.Remove(_Factory);
}
else
{
_ThreadSessionMap[_Factory] = value;
}
}
}
private readonly ISessionFactoryImplementor _Factory;
// This constructor should be kept, otherwise NHibernate will fail to create an instance of this class.
public HybridWebSessionContext(ISessionFactoryImplementor factory) : base(factory)
{
_Factory = factory;
}
protected override IDictionary GetMap()
{
var currentContext = ReflectiveHttpContext.HttpContextCurrentGetter();
if (currentContext != null)
{
return ReflectiveHttpContext.HttpContextCurrentItems[_SessionFactoryMapKey] as IDictionary;
}
return _ThreadSessionMap;
}
protected override ISession Session
{
set
{
base.Session = value;
ThreadSession = value;
}
}
protected override void SetMap(IDictionary value)
{
var currentContext = ReflectiveHttpContext.HttpContextCurrentGetter();
if (currentContext != null)
{
ReflectiveHttpContext.HttpContextCurrentItems[_SessionFactoryMapKey] = value;
return;
}
_ThreadSessionMap = value;
}
}
```
Die dan in de hibernate config injecteren:
```csharp
configuration.SetProperty(NHibernate.Cfg.Environment.CurrentSessionContextClass, typeof(HybridWebSessionContext).AssemblyQualifiedName);
```
Op die manier werkt `Bind()` altijd.
:exclamation: Geen sessie factory sluiten op het einde van de request maar enkel de `ISession` - uw pooling zit in de factory!
############ Transacties ############
* [Getting TransactionScope to play nice with NHibernate](http://www.mattwrock.com/post/2010/12/26/Getting-TransactionScope-to-play-nice-with-NHibernate.aspx)
* [Batching NHibernate's DML Statements](http://thatextramile.be/blog/2008/10/batching-nhibernates-dm-statements/)
* [NHibernate IPreUpdateEventListener & IPreInsertEventListener](http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener)
######= Multiple nested transactions ######=
is **niet** mogelijk in NHibernate! Hier kan je rond werken door een dummy te retourneren (wel `ISession.BeginTransaction()` decoreren op de onderstaande manier)
```csharp
public ITransaction BeginTransaction()
{
if (_Session.Transaction.IsActive)
{
// bad programmer's code, nice going. nested transactions are not supported in NHibernate!
* see http:*rajputyh.blogspot.be/2011/02/nested-transaction-handling-with.html and http://stackoverflow.com/questions/1192111/how-do-i-do-nested-transactions-in-nhibernate
return new HibernateTransactionDummy();
}
var newTransaction = _Session.BeginTransaction();
return newTransaction;
}
```
######= Locking ######=
[NHibernate mapping & concurrency](http://ayende.com/blog/3946/nhibernate-mapping-concurrency) - pessimistic locking kan gedaan worden door in een query de `LockMode` mee te geven:
```csharp
var person = session.Get<Person>(1,LockMode.Upgrade);
```
Binnen een transactie uiteraard. Dit genereert `with(updlock, rowlock)` in de `SELECT` statements. De lock wordt gereleased wanneer de transactie gecommit wordt. Dit is [blijkbaar geen table lock](http://stackoverflow.com/questions/19873880/understanding-effects-of-with-updlock-rowlock-on-a-query-in-sql-server):
> The `updlock` will place update locks on every row being touched (selected) - so this means until the end of the transaction (explicit or implicit), the row(s) touched by the SELECT will have an update lock on them which allows for other transactions to read, but not update or delete the row. The `rowlock` just indicates that you want row-level locks instead of page or table locks. That lock makes sense if you need to select first, then update a row within the same explicit transaction.
It doesn't make it run any faster, and can cause other transactions to be blocked
############ Event listeners ############
:exclamation: in events als `IPreInsertEventListener` moet je zowel het object (via `@Event.Entity`) als de state (via `@Event.State`) wijzigen. Hoe werkt dit met `IPersistEventListener`?
Custom event listener die de Java annotaties zoals `@PrePersist` ea mogelijk maakt in C# met attributes:
```csharp
public class HibernateAttributeEventListener : IPreUpdateEventListener, IPreInsertEventListener, IPersistEventListener, IFlushEntityEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
InvokeMethodsWithAttribute(@event.Entity, @event.Session, typeof(PreUpdate));
return false;
}
public bool OnPreInsert(PreInsertEvent @event)
{
InvokeMethodsWithAttribute(@event.Entity, @event.Session, typeof(PreInsert));
return false;
}
public void OnPersist(PersistEvent @event)
{
InvokeMethodsWithAttribute(@event.Entity, @event.Session, typeof(PrePersist));
}
public void OnPersist(PersistEvent @event, IDictionary createdAlready)
{
}
public void OnFlushEntity(FlushEntityEvent @event)
{
}
private static void InvokeMethodsWithAttribute(object entity, ISession session, Type attributeType)
{
entity.GetType()
.GetMethods()
.Where(method => method.GetCustomAttributes(attributeType, false).Length > 0)
.ForEach(method => Invoke(entity, session, method));
}
private static void Invoke(object entity, ISession session, MethodInfo method)
{
var parameters = method.GetParameters();
if (parameters.Length ###### 0)
{
method.Invoke(entity, new object[] {});
} else if (parameters.Length ###### 1 && parameters[0].ParameterType ###### typeof (ISession))
{
method.Invoke(entity, new object[] {session});
}
else
{
throw new ArgumentException("Error while invoking attribute event method, only 0 or 1 params (ISession) is supported!");
}
}
```
Dit kan je dan aan de config hangen met `_Configuration.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[] {new HibernateAttributeEventListener()};` - moet per type listener dat je wenst te gebruiken. De attributes zijn zo gedefiniëerd (enkel op method):
```csharp
[AttributeUsage(AttributeTargets.Method)]
public class PrePersist : Attribute
{
}
```
:exclamation: Indien state wijzigt in `PrePersist` of `PreUpdate` moet je ook de @event.State wijzigen, naast de state van het object zelf.
Voor details zie [http:*ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener](http:*ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener)
Een manier is bvb om dirty field checks te doen met reflectie:
```csharp
public static Dictionary<string, object> GetFieldValues(this Type type, object obj)
{
return type.GetProperties().ToDictionary(
property => property.Name,
property => property.GetValue(obj, null));
}
private static void Set(IEntityPersister persister, object[] state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index ###### -1)
return;
state[index] = value;
}
// ...
var initialFieldValues = @event.Entity.GetType().GetFieldValues(@event.Entity);
// invoke [makes some fields dirty]
UpdateDirtyFieldValuesInState(@event, state, initialFieldValues);
private static void UpdateDirtyFieldValuesInState(AbstractPreDatabaseOperationEvent @event, object[] state, Dictionary<string, object> initialFieldValues)
{
foreach (var actualValue in @event.Entity.GetType().GetFieldValues(@event.Entity))
{
if (!Equals(initialFieldValues[actualValue.Key], actualValue.Value))
{
Set(@event.Persister, state, actualValue.Key, actualValue.Value);
}
}
}
```
############ Identity generators ############
:exclamation: `identity` gebruikt de native autoincrement aan de DB maar is helemaal niet performant, maakt `batch_size` redundant - veel roundtrips nodig. Een alternatief bijvoorbeeld:
* [NHibernate Custom Id-generator based on hilo](http://daniel.wertheim.se/2011/03/08/nhibernate-custom-id-generator/)
Zie ook [Hibernate doc: mappings](http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html) voor alle mogelijkheden.
Een custom generator die een tabel gebruikt met een kolom die de entity weergeeft werkt zo:
```csharp
public class NHibIdGenerator : TableHiLoGenerator
{
public override void Configure(IType type, IDictionary<string, string> parms, Dialect dialect)
{
if (!parms.ContainsKey("table"))
parms.Add("table", "NHibHiLoIdentities");
if (!parms.ContainsKey("column"))
parms.Add("column", "NextHiValue");
if (!parms.ContainsKey("max_lo"))
parms.Add("max_lo", "100");
if (!parms.ContainsKey("where"))
parms.Add("where", string.Format("EntityName='{0}'", parms["target_table"]));
base.Configure(type, parms, dialect);
}
}
```
En dan in de hibernate mapping:
```xml
<id name######"Id" column"`id`">
<generator class="Utilities.Database.NHibIdGenerator, Utilities" />
</id>
```
Na de komma staat de full-qualified assembly.
############ Probleemoplossing ############
###### can only generate ids as part of bulk insert with either sequence or post-insert style generators ######
Identity generator voor die bepaalde tabel moet een custom post-insert generator zijn (zoals bovenstaande `hilo` generator). Waarom? Dit gaat:
1. eerst in bluk inserts doen
1. dan in bulk ids bepalen afhankelijk van custom generator (bvb tabel met next id)
1. dan in bulk update uitvoeren om id te plaatsten in db
Dit betekent ook dat de ID kolom nullable moet zijn en er geen native generator in de weg mag zitten.
###### There is already an open DataReader associated with this Connection which must be closed first ######
```
Exception:
Exception has been thrown by the target of an invocation.
Inner Exception:
MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first. at MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception) at MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() at MySql.Data.MySqlClient.MySqlTransaction.Rollback() at NHibernate.Transaction.AdoTransaction.Dispose(Boolean isDisposing) in d:<br/>BuildAgents<br/>BuildAgentTwo<br/>work<br/>9126a46c2421d993<br/>PFW.Base<br/>NHibernate<br/>Transaction<br/>AdoTransaction.cs:line 368 at NHibernate.Transaction.AdoTransaction.Dispose() in d:<br/>BuildAgents<br/>BuildAgentTwo<br/>work<br/>9126a46c2421d993<br/>PFW.Base<br/>NHibernate<br/>Transaction<br/>AdoTransaction.cs:line 340 at
...
Exception:Exception has been thrown by the target of an invocation.Inner Exception:System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first. at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlInternalTransaction.Rollback() at System.Data.SqlClient.SqlInternalTransaction.Dispose(Boolean disposing) at System.Data.SqlClient.SqlTransaction.Dispose(Boolean disposing) at NHibernate.Transaction.AdoTransaction.Dispose(Boolean isDisposing) at PFW.Utilities.Layers.ServiceLayer.TransactionalAttribute.OnExit(MethodExecutionArgs args) at ServiceLayer.Person.PersonBaseSL.Persist(IPersonBase person) at FacadeLayer.Person.PersonBaseRF.Persist(HttpRequest request) Exception:Exception has been thrown by the target of an invocation.Inner Exception:System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first. at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlInternalTransaction.Rollback() at System.Data.SqlClient.SqlInternalTransaction.Dispose(Boolean disposing) at System.Data.SqlClient.SqlTransaction.Dispose(Boolean disposing) at NHibernate.Transaction.AdoTransaction.Dispose(Boolean isDisposing) at
...
```
Als we kijken in de code van `MySqlCommand` vinden we:
```csharp
private void CheckState()
{
if (this.connection ###### null)
this.Throw((Exception) new InvalidOperationException("Connection must be valid and open."));
if (this.connection.State != ConnectionState.Open && !this.connection.SoftClosed)
this.Throw((Exception) new InvalidOperationException("Connection must be valid and open."));
if (!this.connection.IsInUse || this.internallyCreated)
return;
this.Throw((Exception) new MySqlException("There is already an open DataReader associated with this Connection which must be closed first."));
}
```
`IsInUse` wordt gezet in de setter van `Reader` in `MySqlConnection`
* Zowel in `MySqlClient` als `SqlClient`, dus client onafhankelijk
* Volgens google betekent dit dat we `ISession` objecten delen over verschillende threads/requests
:exclamation: Probleem was dat wij [PostSharp](http://www.postsharp.net/aspects/examples/transaction) gebruiken maar op de attribute class state bijhielden (de transactie zelf) om die bij onexit te kunnen committen. Andere users herbruiken diezelfde klasse blijkbaar, waarbij user1 transacties van user2 gaat committen etc. Correcte implementatie - zie link postsharp als voorbeeld; of:
```csharp
[Serializable]
public class TransactionalAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
NHibernateFactory.CurrentSession.BeginTransaction();
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
NHibernateFactory.CurrentSession.Transaction.Dispose();
base.OnExit(args);
}
public override void OnSuccess(MethodExecutionArgs args)
{
NHibernateFactory.CurrentSession.Transaction.Commit();
base.OnSuccess(args);
}
}
```
Blijkbaar mag ook `MethodExecutionArgs` gebruikt worden om tijdelijk state in te storen die je bij `OnExit()` terug kan resolven - zie voorbeeld op de [PostSharp website](http://www.postsharp.net/aspects/examples/transaction).
###### Detached entity passed to persist (in een test) ######
Uw Id niet zelf meegeven, steekt een generator in uw mapping...
###### System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection. ######
Oplossing: in hibernate mapping file staan twee keer kolommen gedefiniëerd (eventueel onder een `composite-id`) - deze moet `update` en `insert` attributes op `false` hebben, of niet dubbel gemapped worden, hier kan Hibernate blijkbaar niet mee om gaan...
###### No data type for node [entityProperty] ######
Bij een `HQL` query, wanneer je meer dan 8 properties select, **moet** je een alias gebruiken:
```
select entity.one, entity.two, entity.three, ... from Entity entity where entity.Id in (10, 11)
```
en dus niet
```
select one, two, three from Entity where Id in (10, 11)
```
###### The multi-part identifier "occupation0_.functieid" could not be bound. ######
Impliciete en expliciete joins worden gemixed in uw select statement (al dan niet gewild door NHibernate). Probleem:
```sql
SELECT tbl1.col1, tbl2.col2, tbl3.col3
FROM tbla tbl1, tblb tbl2
INNER JOIN tblc tbl3 on tbl1.joincol = tbl1.joincol
WHERE tbl1.joincol2 = tbl2.joincol2
AND tbl2.joincol3 = tbl3.joincol3
```
er wordt zowel met `INNER JOIN` als met `WHERE` een join gelegd naar andere tabellen. In MSSQL geeft dit problemen (sommige andere DBs niet?). Mogelijke oplossingen in NHibernate:
1. Gebruik Criteria om alles expliciet te joinen (joepie...)
1. Selecteer in een LINQ query geen entiteit maar de Id en map die achteraf
###### Error Code: 1054. Unknown column 'personlite2_.WerknemerID' in 'on clause' ######
* Multiple join in HQL die in de verkeerde volgorde staat? Draai `join x as y join y as z` eens om, zodat de joins andersom gelegd worden.
Concreet voorbeeld:
```sql
SELECT col1, col2, col3
FROM bliebloe
INNER JOIN tabel alias ON alias.x = bliebloe.y,
col4,
INNER JOIN tabel2 alias2 ON alias2.x = bliebloe.y
```
Zou moeten zijn:
```sql
SELECT col1, col2, col3
FROM bliebloe
INNER JOIN tabel alias ON alias.x = bliebloe.y,
INNER JOIN tabel2 alias2 ON alias2.x = bliebloe.y,
col4
```
Maar hoe vertellen we `Hibernate` dit? **zet expliciete joins in uw HQL** in de gewenste volgorde:
''select a.x, b.y, c.z
from a
join a.h as b
join a.i as c''
* In MySQL: syntax join mixen ###### no go, zoals select * from table1, table2 where table1.id table2.key join bla join blie - zowel met komma als met de join operator joinen. Doet Hibernate normaal niet.

View File

@ -0,0 +1,274 @@
+++
title = "reflectie"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"reflectie"
]
date = "2015-02-09"
+++
# Reflectie
## Get Type based on string
Probleem: een fully qualified classname in string vorm is geen `Type` en `Type.GetType()` gaat standaard in de huidige assembly kijken of die klasse daar in steekt. Hoe haal ik dit type op als ik niet vanbuiten weet in welke assembly ik moet gaan kijken? Via uw `AppDomain`:
```csharp
return AppDomain.CurrentDomain.GetAssemblies()
.Single(app ######> app.GetType(fullClassName) ! null)
.GetType(fullClassName);
```
## Get Subclasses/interfaces of class
Gebruik `type.Assembly.GetTypes()` en filter verder.
1. Als je een **interface** wil hebben, moet je `IsAssignableFrom()` gebruiken (in de omgekeerde richting).
2. Als je een **subklasse** wil hebben, moet je ofwel de `.BaseType` property gebruiken als direct kind, ofwel de `IsSubclassOf()` method.
```csharp
public string HandleMessage(IHostService hostService)
{
var requestType = typeof (IHostServiceNativeRequest);
var handlerType = requestType.Assembly.GetTypes()
.Where(requestType.IsAssignableFrom)
.Single(t ######> (NativeRequestInstance(t)).Key Key);
return NativeRequestInstance(handlerType).ParseRequest(hostService);
}
private IHostServiceNativeRequest NativeRequestInstance(Type t)
{
return (IHostServiceNativeRequest) Activator.CreateInstance(t);
}
```
## Reflective instantiation
Zie vorig voorbeeld; een nieuwe instantie van een `Type` maken kan via `Activator.CreateInstance()`.
##### Protected constructor with arguments
```csharp
return (T)Activator.CreateInstance(typeof(T),
BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance,
null, new object[] { arg1 }, CultureInfo.CurrentCulture);
```
## AppDomains
##### Q: Ik wil een DLL dynamisch laden
Gebruik `Assembly.LoadFrom(string)`.
##### Q: Ik wil loopen over alle AppDomains
Niet zo simpel te realiseren: (zie [http:*stackoverflow.com/questions/14758915/get-all-processes-with-their-corresponding-app-domains](http:*stackoverflow.com/questions/14758915/get-all-processes-with-their-corresponding-app-domains))
```csharp
private static List<AppDomainInf> GetAppDomains()
{
IList<AppDomain> mAppDomainsList = new List<AppDomain>();
List<AppDomainInf> mAppDomainInfos = new List<AppDomainInf>();
IntPtr menumHandle = IntPtr.Zero;
ICorRuntimeHost host = new CorRuntimeHost();
try
{
host.EnumDomains(out menumHandle);
object mTempDomain = null;
//add all the current app domains running
while (true)
{
host.NextDomain(menumHandle, out mTempDomain);
if (mTempDomain ###### null) break;
AppDomain tempDomain = mTempDomain as AppDomain;
mAppDomainsList.Add((tempDomain));
}
//retrieve every app domains detailed information
foreach (var appDomain in mAppDomainsList)
{
AppDomainInf domainInf = new AppDomainInf();
domainInf.Assemblies = GetAppDomainAssemblies(appDomain);
domainInf.AppDomainName = appDomain.FriendlyName;
mAppDomainInfos.Add(domainInf);
}
return mAppDomainInfos;
}
catch (Exception)
{
throw; //rethrow
}
finally
{
host.CloseEnum(menumHandle);
Marshal.ReleaseComObject(host);
}
}
```
Ref toevoegen, mscoree.tld in .NET root folder.
############= Generic Type arguments & reflectie ############=
###### Q: Ik wil een Type meegeven dat moet extenden van een basisklasse, waarna ik dat type wil instantiëren. ######
```csharp
protected IList<TInsertable> Load<TInsertable>() where TInsertable : DatabaseInsertable
{
var myInstance = Activator.CreateInstance(typeof(TInsertable));
}
```
:exclamation: `Type` zelf is niet generic omdat dit at-runtime gebruikt wordt voor typeinformatie en de andere dingen at-compiletime. Je kan dus geen `Type<T> where T : MyClass` gebruiken, zoals in Java bijvoorbeeld `Class<? extends MyClass>` gebruikt wordt. Merk op dat in Java er met het generic type argument geen klasse aangemaakt kan worden, zie [code/java/reflectie]({{< relref "wiki/code/java/reflectie.md" >}}) voor java.
###### Q: Ik wil een variabel aantal generic type argumenten definiëren ######
Genaaid, dit gaat niet. Kijk maar naar bijvoorbeeld `Func<>`:
1. `Func<in T1, in T2, out Result>`
2. `Func<in T1, in T2, in T3, out Result>`
3. `Func<in T1, in T2, in T3, in T4, out Result>`
4. ...
Je kan die wel allemaal laten refereren naar één (private) methode die `params[]` gebruikt, bijvoorbeeld onderstaande count:
```csharp
protected int Count<TInsertable>()
where TInsertable : DatabaseInsertable
{
return Count(typeof (TInsertable));
}
protected int Count<TInsertable1, TInsertable2>()
where TInsertable1 : DatabaseInsertable
where TInsertable2 : DatabaseInsertable
{
return Count(typeof (TInsertable1), typeof (TInsertable2));
}
protected int Count<TInsertable1, TInsertable2, TInsertable3>()
where TInsertable1 : DatabaseInsertable
where TInsertable2 : DatabaseInsertable
where TInsertable3 : DatabaseInsertable
{
return Count(typeof (TInsertable1), typeof (TInsertable2), typeof (TInsertable3));
}
private int Count(params Type[] insertableTypes)
{
var count = 0;
foreach (var type in insertableTypes)
{
var select = "select count(*) from " + GetTableOfType(type);
count += Int32.Parse(factory.CreateCommand(this.connection, select).ExecuteScalar().ToString());
}
return count;
}
```
############= Reflectie en dynamisch code genereren ############=
Mogelijk met **Reflection EMIT**, om dynamisch IL code te genereren. IL is de bytecode tussenlaag in .NET, die je ook in C# kan schrijven.
Compleet voorbeeld: http://www.codeproject.com/Articles/121568/Dynamic-Type-Using-Reflection-Emit
Bijvoorbeeld, om een getal te delen door een ander met `getal / other`, genereert de volgende code dit in IL:
```csharp
MethodBuilder mDivide = tbuilder.DefineMethod("Divide", MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.NewSlot |
MethodAttributes.Virtual |
MethodAttributes.Final,
CallingConventions.Standard,
typeof(System.Single),
new Type[] { typeof(System.Int32), typeof(System.Int32) });
mDivide.SetImplementationFlags(MethodImplAttributes.Managed);
ILGenerator dil = mDivide.GetILGenerator();
dil.Emit(OpCodes.Nop);
Label lblTry = dil.BeginExceptionBlock();
dil.Emit(OpCodes.Nop);
dil.Emit(OpCodes.Ldarg_1);
dil.Emit(OpCodes.Ldarg_2);
dil.Emit(OpCodes.Div);
dil.Emit(OpCodes.Conv_R4); // Converts to Float32
dil.Emit(OpCodes.Stloc_1);
dil.Emit(OpCodes.Leave, lblTry);
dil.BeginCatchBlock(typeof(DivideByZeroException));
dil.Emit(OpCodes.Stloc_0);
dil.Emit(OpCodes.Nop);
dil.Emit(OpCodes.Ldstr, "ZeroDivide exception : {0}");
dil.Emit(OpCodes.Ldloc_0);
MethodInfo minfo = typeof(DivideByZeroException).GetMethod("get_Message");
dil.Emit(OpCodes.Callvirt, minfo);
MethodInfo wl = typeof(System.Console).GetMethod("WriteLine", new Type[]
{ typeof(string), typeof(object) });
dil.Emit(OpCodes.Call, wl);
dil.Emit(OpCodes.Nop);
dil.Emit(OpCodes.Ldc_R4, 0.0);
dil.Emit(OpCodes.Stloc_1);
dil.Emit(OpCodes.Leave_S, lblTry);
dil.EndExceptionBlock();
dil.Emit(OpCodes.Nop);
dil.Emit(OpCodes.Ldloc_1);
dil.Emit(OpCodes.Ret);
```
Genereert dit in IL:
```
.method public hidebysig newslot virtual final
instance float32 Divide(int32 firstnum,
int32 secondnum) cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (class [mscorlib]System.DivideByZeroException V_0,
float32 V_1)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: ldarg.1
IL_0003: ldarg.2
IL_0004: div
IL_0005: conv.r4
IL_0006: stloc.1
IL_0007: leave.s IL_0024
} // end .try
catch [mscorlib]System.DivideByZeroException
{
IL_0009: stloc.0
IL_000a: nop
IL_000b: ldstr "ZeroDivide exception : {0}"
IL_0010: ldloc.0
IL_0011: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_0016: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_001b: nop
IL_001c: ldc.r4 0.0
IL_0021: stloc.1
IL_0022: leave.s IL_0024
} // end handler
IL_0024: nop
IL_0025: ldloc.1
IL_0026: ret
}
```

View File

@ -0,0 +1,153 @@
+++
title = "resources"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"resources"
]
date = "2015-10-09"
+++
# C# Resources
## In Tests
Zie [code/csharp/testing]({{< relref "wiki/code/csharp/testing.md" >}})
## Web config
Zie http://msdn.microsoft.com/en-us/library/dd465326(VS.100).aspx
`.NET 4` voorziet een manier om de `Web.config` file automatisch te **transformeren** afhankelijk van uw build configuratie (Debug, Release, custom). Je hebt hier 2 files:
* Web.config (base)
* Web.[BuildConfigName].config (transformer)
Wat in de tweede file staat, gaat toegepast worden op de eerste file. Je kan dus niet zomaar zaken copypasten en overschrijven, maar moet tags die je wil replacen **XDT** transformaties op definiëren:
```xml
<appSettings>
<add key######"Bla" value"blie"/>
</appSettings>
```
met transformer
```xml
<appSettings xdt:Transform="Replace">
<add key######"Bla" value"bloebloe"/>
</appSettings>
```
Zal de hele `appSettings` tag vervangen in de base file. Vergeet dat attribuut en er gebeurt niets.
## Embedded resources ophalen
```csharp
private Stream GetIconAsStream(string icon)
{
return Assembly.GetExecutingAssembly()
.GetManifestResourceStream(
"Full.Namespace.Of.Class.dir.to.image" +
icon);
}
private void CopyIconsToDir(string dir, params string[] iconNames)
{
foreach (var icon in iconNames)
{
var downloadStream = GetIconAsStream(icon);
var tmpFileCreate = File.Create(dir + "<br/><br/>" + icon);
downloadStream.CopyTo(tmpFileCreate);
tmpFileCreate.Close();
downloadStream.Close();
}
}
```
## .CSPROJ file inlezen & parsen
Waarom is dit handig? Om bijvoorbeeld te kunnen kijken welke files allemaal included zijn in uw project en met een test alle SQL files verplicht te laten embedden. <br/><br/>
(Op die manier staan ze niet als "Content" in de XML structuur). Regex op loslaten of XML parsen.
```csharp
private static string ReadProjectFile()
{
var dbAssembly = typeof(AbstractUpdater).Assembly;
* format: 'file:*/C:/Sources/project/UnitTestproject/bin/Debug/project.UnitTest.DLL'
var projectDir = dbAssembly.CodeBase.Substring(0, dbAssembly.CodeBase.IndexOf(".UnitTest", StringComparison.InvariantCulture));
var csprojFile = Directory.GetFiles(projectDir.Replace("file:///", ""), "*.csproj")[0];
var csproj = File.ReadAllText(csprojFile);
return csproj;
}
```
## Managed resources disposen
:exclamation: Zie [Dispose Pattern @ MSDN](http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx); volgende template:
```csharp
public class DisposableResourceHolder : IDisposable {
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder(){
this.resource = ... // allocates the resource
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this); // tell the GC disposing it isn't needed anymore
}
protected virtual void Dispose(bool disposing){
if (disposing){
if (resource!= null) resource.Dispose();
}
}
}
```
#### using()
De .NET CLR vertaalt
```csharp
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
```
naar
```csharp
{ // limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes!= null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
```
Moet dan uw object de interface `IDisposable` implementeren? Harde cast toch?
#### Java VS C#
Beiden plaatsten objecten in een finalizer queue maar het uitvoeren hiervan is nooit gegarandeerd (crash process, iets anders dat kan gebeuren, ...). `IDisposable` kan gebruikt worden om managed resources op te kuisen, **maar moet manueel aangeroepen worden** door clients die dit object gebruiken - hier is ook nog niets van gegarandeerd! Behalve in een `using(obj) { }` block - hierna wordt `Dispose()` aangeroepen, ook als er ondertussen een of andere Exception opgetreden is. In Java 6 en lager moet je dit met `try { } finally { }` manueel doen.
Zie [java resources wiki pagina]({{< relref "wiki/code/java/resources.md" >}})

View File

@ -0,0 +1,42 @@
+++
title = "signing"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"signing"
]
date = "2014-07-11"
+++
# Signing
#### Compile fouten: 'cannot import the following key file'
```
C:<br/>Windows<br/>Microsoft.NET<br/>Framework<br/>v4.0.30319<br/>Microsoft.Common.targets(2455, 5): error MSB3325: Cannot import the following key file: ign.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_0E36C1B21D0EBCA4
```
Oplossen door met `sntool` te registreren en die container naam aan te maken (VS_KEY_...)
#### Assemblies signen
Properties -> Signing -> Sign the assembly aanvinken. Choose a strong name key file... (browse)
#### Friend classes & signed assemblies
In `AssemblyInfo.cs` ook de public key meegeven van de friend assembly:
```csharp
[assembly: InternalsVisibleTo("ServiceLayer.UnitTest, PublicKey=00240000048000002a51cadd46bbd321cda4e67d2...c125d7eb")]
```
##### De public key opvragen van een assembly
Met `sn.exe`, geïnstalleerd onder uw .NET SDK dir, bijvoorbeeld `C:<br/>Program Files (x86)<br/>Microsoft SDKs<br/>Windows<br/>v7.0A<br/>Bin`
`sn -Tp [assembly.dll]` uitvoeren. Of de sign file vastnemen en deze uitlezen. Zie [MSDN Strong Name Tool help](http://msdn.microsoft.com/en-us/library/k5b5tt23(v=vs.110).aspx).

View File

@ -0,0 +1,135 @@
+++
title = "testing"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"testing"
]
date = "2014-06-27"
+++
# Testing met C#/.NET
## Test frameworks
### Selenium/WebDriver
Zie http://www.joecolantonio.com/2012/07/31/getting-started-using-selenium-2-0-webdriver-for-ie-in-visual-studio-c/ - essentiëel identiek aan Java.
#### Chaining - fluent acceptance criteria definitions
Een typische test zou er dan zo kunnen uitzien:
```csharp
[Test]
public void OpenAdminAuthenticationManagement()
{
LogInto()
.OpenAdministrationAuthenticationManagement()
.AuthenticationGrid
.ShouldContainMinAmountRows(1)
.DoubleClickOnRowNr(0)
.ExpectOpened<ModifyUserDetailWindow>()
.UserNameShouldContainSomeValue();
}
```
1. Gebruik overal `return this`
2. Wanneer je niet wil upcasten en in een abstract component `ClickSave()` uw subtype moet retourneren: `public class Panel<T> : Window where T : Panel<T>` en `return (T) this`
3. Wanneer je niet weet wat het volgend scherm is, gebruik `ExpectOpened<Type>()` dat via [code/csharp/reflectie]({{< relref "wiki/code/csharp/reflectie.md" >}}) een instantie aanmaakt van uw component.
### NUnit
#### Attributes
Zoals in JUnit's annotaties `@Before` en `@Test` kan je hier `[SetUp]` en `[Test]` gebruiken. Een test klasse moet met de attribute `[TestFixture]` geplakt worden.
Zie [MSTest en NUnit comparison](http://blogs.msdn.com/b/nnaderi/archive/2007/02/01/mstest-vs-nunit-frameworks.aspx)
**Hoe kan ik dit via command-line uitvoeren?**
Installeer [NUnit](http://nunit.org/?p=download) en pas uw `PATH` aan zodat de install dir er in steekt (program files<br/>nunit). Vanaf dan kan je `nunit-console test.dll` via commandline gebruiken om de test zo uit te voeren.
### MSTest
#### Attributes
Zoals in JUnit's annotaties `@Before` en `@Test` kan je hier `[TestInitialize]` en `[TestMethod]` gebruiken. Er zijn enkele "pitfalls" -
`[ClassInitialize]`, zogezegd het equivalent van `@BeforeClass`, werkt **niet** op base classes: zie http://blogs.msdn.com/b/densto/archive/2008/05/16/using-a-base-class-for-your-unit-test-classes.aspx
Een mogelijke "oplossing" is dit: (let op, niet helemaal hetzelfde)
```csharp
[TestClass]
public abstract class TestBase
{
[AssemblyInitializeAttribute]
public static void Initialize(TestContext context)
{
// put your initialize code here
}
}
```
Of overal de base aanroepen...
## Mocking en stubbing
### Microsoft Fakes
Zie http://msdn.microsoft.com/en-US/library/hh549175
Als je `Fakes` toevoegt als reference, gebeurt er het volgende (enkel voor interfaces):
> The special piece of magic here is the class StubIStockFeed. For every interface in the referenced assembly, the Microsoft Fakes mechanism generates a stub class. The name of the stub class is the derived from the name of the interface, with "Fakes.Stub" as a prefix, and the parameter type names appended.
### Rhino Mocks
Zie http://www.hibernatingrhinos.com/oss/rhino-mocks
##### Automatisch mocking fields initializeren
```csharp
public abstract class AbstractTestCase
{
[TestInitialize]
public void CreateMocksBasedOnNamingConvention()
{
this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.Name.EndsWith("Mock")).All(InitMock);
}
private bool InitMock(FieldInfo field)
{
field.SetValue(this, MockRepository.GenerateMock(field.FieldType, new Type[]{}));
return true;
}
}
```
Hupla.
## Resources en deployment
[How to deploy files for tests](http://msdn.microsoft.com/en-us/library/ms182475.aspx)
Er moeten aan een aantal condities voldaan worden:
* een mstest `.testsettings` XML file waar de tag `<DeploymentEnabled/>` op `true` staat (extra te deployen files zijn daar kinderen van) - dit kan automatisch geëdit worden met VS2010 maar blijkbaar niet meer met VS2012... Als de tag zelf niet voorkomt werkt het in 2012 ook nog (?)
* een resource hebben die op `Content` en `Copy` staat
* Een `DeploymentItem` attribute hebben die de te kopiëren file specifiëert (merk op dat subfolders hier ook ingevuld moeten zijn)
```csharp
[TestClass]
[DeploymentItem("IEDriverServer.exe")]
public abstract class EndToEndTestCase
{
}
```
De deployment items zijn niet nodig als de testen uitgevoerd worden vanuit de bin folder. Meestal is dit een aparte MSTest locatie (temp zoals `C:<br/>Users<br/>bkwog<br/>AppData<br/>Local<br/>Temp<br/>TestResults<br/>bkwog_HI18261 2013-12-23 10_28_54`) waar dan resources niet bij steken maar enkel DLLs en PDBs - bijgevolg problemen...

View File

@ -0,0 +1,173 @@
+++
title = "tfs"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"tfs"
]
date = "2013-07-26"
+++
# Tfs communicator
#### TFS informatie vanuit .NET uitlezen
[OData TFS v2](http://blogs.msdn.com/b/briankel/archive/2013/01/07/odata-service-for-team-foundation-server-v2.aspx) is een tussenlaag `REST API` die je zelf nog op `IIS` kan deployen...
Onderstaande code doet hetzelfde (veel eenvoudiger) in een console appke
```csharp
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
namespace TfsCommunicator
{
[ExcludeFromCodeCoverage]
public class BuildCommunicator : IBuildCommunicator
{
private string tfsServerAddress;
public BuildCommunicator(string tfsServerAddress)
{
this.tfsServerAddress = tfsServerAddress;
}
public BuildStatus GetBuildInformation(int maxDays ###### 5, int maxRuns 10, string teamProject ###### "*", string buildDefinition "")
{
var buildStatus = new BuildStatus();
var builds = GetBuildsFromTfs(maxDays, teamProject, buildDefinition);
var currentDefinition = string.Empty;
foreach (var build in builds)
{
string definitionName = build.BuildDefinition.Name;
var project = MapBuildToProject(build, definitionName);
if (definitionName ###### currentDefinition)
{
AddBuiltToParentProject(buildStatus, definitionName, project, maxRuns);
}
else
{
currentDefinition = definitionName;
buildStatus.Projects.Add(project);
}
}
return buildStatus;
}
private IOrderedEnumerable<IBuildDetail> GetBuildsFromTfs(int maxDays, string teamProject, string buildDefinition)
{
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsServerAddress));
IBuildServer buildServer = tfs.GetService<IBuildServer>();
IBuildDetailSpec spec = string.IsNullOrEmpty(buildDefinition) ?
buildServer.CreateBuildDetailSpec(teamProject) :
buildServer.CreateBuildDetailSpec(teamProject, buildDefinition);
spec.MinFinishTime = DateTime.Now.Subtract(TimeSpan.FromDays(maxDays));
spec.MaxFinishTime = DateTime.Now;
spec.QueryDeletedOption = QueryDeletedOption.IncludeDeleted;
var builds ###### buildServer.QueryBuilds(spec).Builds.OrderBy(b > b.BuildDefinition.Name).ThenByDescending(b => b.FinishTime);
return builds;
}
private static Project MapBuildToProject(IBuildDetail build, string definitionName)
{
var project = new Project
{
DefinitionName = definitionName,
Name = build.TeamProject,
Status = build.Status.ToString(),
StartTime = build.StartTime,
FinishTime = build.FinishTime
};
return project;
}
private void AddBuiltToParentProject(BuildStatus buildStatus, string definitionName, Project project, int maxRuns)
{
var parent ###### buildStatus.Projects.First(p > p.DefinitionName ###### definitionName);
if (parent.Runs.Count < maxRuns)
{
parent.Runs.Add(project);
}
}
}
}
```
```csharp
using System;
using System.Collections.Generic;
namespace TfsCommunicator
{
public class Project
{
public Project()
{
Runs = new List<Project>();
}
public string DefinitionName { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public DateTime StartTime { get; set; }
public DateTime FinishTime { get; set; }
public List<Project> Runs { get; set; }
}
}
```
Deze informatie dan bijvoorbeeld wegschrijven naar een JSON file
```csharp
private static void Main(string[] args)
{
Console.WriteLine("TFS Build status; connecting...");
BuildCommunicator communicator = new BuildCommunicator(ConfigurationManager.AppSettings["tfsServer"]);
while (true)
{
Console.WriteLine("Getting TFS Build info for all projects...");
BuildStatus info = communicator.GetBuildInformation();
CleanBuildStatusFile();
WriteBuildStatusToFile(info);
Console.WriteLine("Written build info to buildstatus.json. [waiting...] ");
Thread.Sleep(20000);
}
}
private static void WriteBuildStatusToFile(BuildStatus info)
{
StreamWriter streamWriter = File.CreateText("buildstatus.json");
new JsonSerializer().Serialize(streamWriter, info);
streamWriter.Close();
}
private static void CleanBuildStatusFile()
{
try
{
File.Delete("buildstatus.json");
}
catch
{
}
}
```

View File

@ -0,0 +1,56 @@
+++
title = "threads"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"threads"
]
date = "2013-12-06"
+++
# Threads
### Locking en singletons
See [C#In Depth: Implementing the Singleton pattern in C#](http://csharpindepth.com/Articles/General/Singleton.aspx)
een `lock()` is heel duur om uit te voeren, daarom wordt er een null check hierrond nog eens geschreven, dat heet **double-check locking**:
```csharp
internal static ContextViewPresenter instance;
private static readonly Object syncRoot = new Object();
public static ContextViewPresenter Instance
{
get
{
if (instance ###### null)
{
lock (syncRoot)
{
if (instance ###### null)
{
instance = new ContextViewPresenter(UserEnvironmentDataProviderSingleton.Instance);
}
}
}
return instance;
}
}
```
############ Thread-local static variables ############
In java kan men `ThreadLocal<>` gebruiken om iets per thread te storen (zoals de gebruiker van een webpagina die per request van de `WebServlet` één nieuwe Thread aanmaakt). <br/><br/>
In C# kan dit ook met de attribute `[ThreadStatic]` voor een field te plaatsen.
:exclamation: Opgelet met ASP.NET - IIS heeft dan een shared threadpool geconfigureerd waar jij geen controle over hebt. Dit wil zeggen dat x threads herbruikt worden, en dus ook uw threadlocal storage.
Oplossing(en): (zie ook [hier](http://piers7.blogspot.be/2005/11/threadstatic-callcontext-and_02.html))
1. Clear waarde op einde van elke request
2. Gebruik `HttpContext` van ASP.NET zelf in plaats van `[ThreadStatic]`. (Zou probleem kunnen zijn in uw domein laag...)

View File

@ -0,0 +1,255 @@
+++
title = "utils"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"csharp",
"utils"
]
date = "2014-03-17"
+++
# Utils Partials
### ObjectExtensions
Waarom? Deep clone van een object maken zonder de boel te (de)-serialiseren.
Bron: https://raw.github.com/Burtsev-Alexey/net-object-deep-copy/master/ObjectExtensions.cs - thank you Alexey
```csharp
public static class ObjectExtensions
{
private static readonly MethodInfo CloneMethod = typeof (Object).GetMethod("MemberwiseClone",
BindingFlags.NonPublic | BindingFlags.Instance);
public static bool IsPrimitive(this Type type)
{
if (type ###### typeof (String)) return true;
return (type.IsValueType & type.IsPrimitive);
}
public static Object Copy(this Object originalObject)
{
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
}
private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
{
if (originalObject ###### null) return null;
var typeToReflect = originalObject.GetType();
if (IsPrimitive(typeToReflect)) return originalObject;
if (typeof (XElement).IsAssignableFrom(typeToReflect)) return new XElement(originalObject as XElement);
if (visited.ContainsKey(originalObject)) return visited[originalObject];
if (typeof (Delegate).IsAssignableFrom(typeToReflect)) return null;
var cloneObject = CloneMethod.Invoke(originalObject, null);
if (typeToReflect.IsArray)
{
var arrayType = typeToReflect.GetElementType();
if (IsPrimitive(arrayType) ###### false)
{
Array clonedArray = (Array) cloneObject;
clonedArray.ForEach(
(array, indices) =>
array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
}
}
visited.Add(originalObject, cloneObject);
CopyFields(originalObject, visited, cloneObject, typeToReflect);
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
return cloneObject;
}
private static void RecursiveCopyBaseTypePrivateFields(object originalObject,
IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
{
if (typeToReflect.BaseType != null)
{
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType,
BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
}
}
private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject,
Type typeToReflect,
BindingFlags bindingFlags =
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy,
Func<FieldInfo, bool> filter = null)
{
foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
{
if (filter != null && filter(fieldInfo) ###### false) continue;
if (IsPrimitive(fieldInfo.FieldType)) continue;
var originalFieldValue = fieldInfo.GetValue(originalObject);
var clonedFieldValue = InternalCopy(originalFieldValue, visited);
fieldInfo.SetValue(cloneObject, clonedFieldValue);
}
}
public static T Copy<T>(this T original)
{
return (T) Copy((Object) original);
}
}
public class ReferenceEqualityComparer : EqualityComparer<Object>
{
public override bool Equals(object x, object y)
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(object obj)
{
if (obj ###### null) return 0;
return obj.GetHashCode();
}
}
```
:exclamation: **Let op met XElement**; sommige API classes voorzien copy constructors die je beter gebruikt ipv via reflectie alle fields over te kopiëren. Bijgevolg if type blabla...
############ EqualsBuilder ############
```csharp
public class EqualsBuilder<T>
{
private readonly T left;
private readonly object right;
private bool areEqual = true;
public EqualsBuilder(T left, object right)
{
this.left = left;
this.right = right;
if (ReferenceEquals(left, right))
{
areEqual = true;
return;
}
if (ReferenceEquals(left, null))
{
areEqual = false;
return;
}
if (ReferenceEquals(right, null))
{
areEqual = false;
return;
}
if (left.GetType() != right.GetType())
{
areEqual = false;
return;
}
}
public EqualsBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> propertyOrField)
{
if (!areEqual)
{
return this;
}
if (left ###### null || right ###### null)
{
return this;
}
var expression = propertyOrField.Body as MemberExpression;
if (expression ###### null)
{
throw new ArgumentException("Expecting Property or Field Expression of an object");
}
Func<T, TProperty> func = propertyOrField.Compile();
TProperty leftValue = func(left);
TProperty rightValue = func((T) right);
if (leftValue ###### null && rightValue ###### null)
{
areEqual &= true;
return this;
}
if (leftValue != null && rightValue ###### null)
{
areEqual &= false;
return this;
}
if (leftValue ###### null && rightValue != null)
{
areEqual &= false;
return this;
}
areEqual &= leftValue.Equals(rightValue);
return this;
}
public bool Equals()
{
return areEqual;
}
}
```
Gebruik:
```csharp
public override bool Equals(object obj)
{
return new EqualsBuilder<FlexMedischGegeven>(this, obj)
.With(x => x.Rownr)
.With(x => x.ColumnName)
.With(x => x.Value)
.With(x => x.Creator)
.Equals();
}
```
############ Mocking DateTime.Now ############
Schrijf een wrapper rond `Now` met behulp van lambda's:
```csharp
using System;
public static class SystemTime
{
private static Func<DateTime> _now;
public static Func<DateTime> Now
{
get
{
if (_now ###### null)
{
Reset();
}
return _now;
}
set { _now = value; }
}
public static void Reset()
{
Now ###### () > DateTime.Now;
}
}
```
Gebruik:
* in `[TestCleanup]` de `Reset()` method aanroepen.
* in uw test body indien gewenst `SystemTime.Now ###### () > new DateTime(2001, 1, 1);` steken.

View File

@ -0,0 +1,20 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"home"
]
date = "2013-03-12"
+++
# code:db >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

View File

@ -0,0 +1,253 @@
+++
title = "mssql"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"mssql"
]
date = "2016-05-24"
+++
# MSSQL
### clustered indexen aanpassen door ze eerst te resolven in een cursor
Onderstaand stukje code for future reference...
```sql
DECLARE @constraint NVARCHAR(MAX)
DECLARE @cmd NVARCHAR(MAX)
DECLARE @table NVARCHAR(MAX)
DECLARE FKCURSOR CURSOR FOR
select distinct name,object_name(parent_object_id) from sys.objects where object_id in
( select fk.constraint_object_id from sys.foreign_key_columns as fk
where fk.referenced_object_id =
(select object_id from sys.tables where name = 'Reference')
)
OPEN FKCURSOR
FETCH NEXT FROM FKCURSOR
INTO @constraint, @table
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = N'ALTER TABLE [dbo].['+@table+'] DROP CONSTRAINT ' + @constraint
EXEC sp_executeSQL @cmd;
FETCH NEXT FROM FKCURSOR
INTO @constraint, @table
END
CLOSE FKCURSOR;
DEALLOCATE FKCURSOR;
```
### constraints met auto-names verwijderen als een kolom hierop depent
Gebruik information schemes om de data hier uit te halen.
Bvb onderstaande code verwijdert de kolom 'isDefault', nadat alle constraints hierrond verwijderd zijn.
```sql
declare @cname varchar(100)
declare @query nvarchar(max)
set @cname = (
SELECT
default_constraints.name
FROM
sys.all_columns
INNER JOIN
sys.tables
ON all_columns.object_id = tables.object_id
INNER JOIN
sys.schemas
ON tables.schema_id = schemas.schema_id
INNER JOIN
sys.default_constraints
ON all_columns.default_object_id = default_constraints.object_id
WHERE
schemas.name = 'dbo'
AND tables.name = 'tblhtmltemplate'
AND all_columns.name = 'isdefault')
set @query = 'alter table tblhtmltemplate drop constraint ' + @cname
if @cname is not null begin
exec sp_executesql @query
end
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name######'tblHtmlTemplate' AND column_name 'isDefault')
BEGIN
alter table tblhtmltemplate drop column isdefault;
END;
```
### functies aanmaken om MySQL syntax te mimicken
```sql
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION ifnull
(
-- Add the parameters for the function here
@value1 datetime, @returnvalue int
)
RETURNS datetime
AS
BEGIN
return isnull(@value1, @returnvalue)
END
GO
```
Zou `IFNull` moeten mimicken, maar je kan enkel `select dbo.ifnull()` doen ipv de native syntax...
### Waar zijn de DB files op de schijf ergens geplaatst?
```sql
SELECT name, physical_name AS current_file_location
FROM sys.master_files
```
Zie ook [MSDN: MSSQL DB file locations](https://msdn.microsoft.com/en-us/library/ms143547.aspx)
### Alter databases gaan traag
1. uitvoeren met `WITH ROLLBACK IMMEDIATE;`
2. uitvoeren in `SINGLE_USER` mode (set op db niveau, dan terug naar `MULTI_USER` zetten)
### Query notifications
Service broker aan zetten: `ALTER DATABASE db_name SET ENABLE_BROKER with rollback immediate`
Hoe checken of reeds enabled is? `select name, database_id, service_broker_guid from sys.databases where is_broker_enabled = 1;`
:exclamation: service broker GUIDs zijn dezelfde indien DB gekopiëerd is, bijgevolg krijg je deze fout indien je `ENABLE_BROKER` tracht uit te voeren op zo'n kopie:
```
cannot be enabled because there is already an enabled Service Broker with the same ID
```
Fix: ([bron](http://www.mssqltips.com/sqlservertip/2789/sql-server-service-broker-error-database-cannot-be-enabled/)) maak een nieuwe broker GUID aan met `SET NEW_BROKER`.
##### In combinatie met NHibernate Syscache2
Zie
* [http:*developer.empinia.org/svn/empinia/vendor/bin/nhibernate/trunk/Doc/html/caches.html](http:*developer.empinia.org/svn/empinia/vendor/bin/nhibernate/trunk/Doc/html/caches.html)
* [http:*tamingcode.com/2013/07/01/cacheable-queries-pitfalls/](http:*tamingcode.com/2013/07/01/cacheable-queries-pitfalls/)
#### Hoe weet ik nu of notification works?
We moeten zien of de **Broker:Conversation** berichten correct op- en afgestuurd worden. Dit kan je best nagaan in SQL Server Profiler:
<img style='float: left; width: nolink |px;' src='/img//code/db/sqlprofiling.png'>
Volgende dingen zouden moeten gebeuren:
1. STARTED_OUTBOUND bericht (conversation)
2. CONVERSING bericht (conversation) van .Net SqlClient applicationName
3. QN:Subscription van .Net SqlClient applicationName
4. QN:Dynamics event subclass Clock run om te zien of het event gequeued is.
#### Pitfalls en errors
##### System.InvalidOperationException: When using SqlDependency without providing an options value, SqlDependency.Start() must be called prior to execution of a command added to the SqlDependency instance.
[Bron](http://richarddingwall.name/2009/10/09/nhibernate-caches-syscache2-dont-forget-to-call-sqldependency-start/)
`SqlDependency.Start(conString)` aanroepen vóór de setup van bvb de NHibernate session factory. Dit moet je zelf doen, ook al gebruik je SysCache2 met regions.
:exclamation: altijd eerst Stop aanroepen!
##### Cannot execute as the database principal because the principal "dbo" does not exist
In SQL Server profiler zichtbaar bij broker events - dit komt vanwege te weinig rechten.
`use [DBNAME] EXEC sp_changedbowner 'sa`' lost dit probleem op (zie profiling)
### MSSQL specifieke syntax
##### Batch processing
`GO`:
The GO command isn't a Transact-SQL statement, but a special command recognized by several MS utilities including SQL Server Management Studio code editor.
The GO command is used to group SQL commands into batches which are sent to the server together. The commands included in the batch, that is, the set of commands since the last GO command or the start of the session, must be logically consistent. For example, you can't define a variable in one batch and then use it in another since the scope of the variable is limited to the batch in which it's defined.
Zie ook [http:*msdn.microsoft.com/en-us/library/ms188037.aspx](http:*msdn.microsoft.com/en-us/library/ms188037.aspx).
:exclamation: Dit is blijkbaar ook wijzigbaar naar een karakterset naar keuze in Management studio options:
<img style='float: left; width: nolink |px;' src='/img//code/db/go_option_mssql.png'>
##### Rename columns
```sql
EXEC sp_RENAME 'TableName.OldColumnName' , 'NewColumnName', 'COLUMN'
```
##### werken met datums
`GETDATE()` is een now timestamp (in MySQL is dit `CURDATE()`. Records selecteren met een bepaalde timestamp ("vanaf"):
```sql
select * from table where datecolumn >= Convert(datetime, '2014-09-11');
```
In Oracle is dit bijvoorbeeld `TO_DATE('26/JAN/2011','dd/mon/yyyy')` in plaats van `Convert()` - in MySQL kan dit rechtstreeks in een bepaald formaat: `WHERE start_date >'2012-11-18';`
### Monitoring
##### ADO .NET Connection pool monitoring
Mogelijk met **Performance monitor** in Win32 (Run -> `perfmon`).
Step-by-step uitleg: (oude versie) [Monitoring DB connections using performance counters](http://www.c-sharpcorner.com/uploadfile/CMouli/monitoring-database-connections-using-performance-counters/)
[Mogelijke counters - MSDN](http://msdn.microsoft.com/en-us/library/ms254503.aspx):
1. NumberOfActiveConnections
2. NumberOfFreeConnections
3. NumberOfPooledConnections
4. ...
<img style='float: left;' src='/img//code/db/addcounters.png |'>
Alles ivm DB connecties in .NET is ook mogelijk te bekijken met de [ANTS Performance profiler](http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/).
##### Aantal momenteel actieve threads bezien
```sql
SELECT
DB_NAME(dbid) as DBName,
COUNT(dbid) as NumberOfConnections,
loginame as LoginName
FROM
sys.sysprocesses
WHERE
dbid > 0
GROUP BY
dbid, loginame
```

View File

@ -0,0 +1,74 @@
+++
title = "mysql"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"mysql"
]
date = "2014-09-11"
+++
# MySQL
### DB Syncing
Mogelijk met verschillende tools, over verschillende DB types heen. Bvb om schema's te syncen tussen MSSQL DBs en MySQL DBs, etc etc. Enkele voorbeeldtools:
* MSSQL: AdeptSQL Diff [http:*www.adeptsql.com/](http:*www.adeptsql.com/)
* MYSQL: SQLyog [https:*www.webyog.com/](https:*www.webyog.com/)
Maakt een SQL DDL aan met het verschil tussen database schema's naar keuze.
<img style='float: left; width: nolink |px;' src='/img//code/db/powertools.png'>
### ADO.NET connection
##### Pooling
Enabled by default, zie [Connector .NET Connection options](http://dev.mysql.com/doc/connector-net/en/connector-net-connection-options.html); voorbeeld:
`Server######server; Port3306; Database######db; Uidroot; Pwd######root; Poolingtrue;`
Dingen als maximum pool size, initial size etc ook instelbaar (zie link)
### Monitoring
##### configuratie properties via SQL uitlezen
Bijvoorbeeld **max connections**: `show variables like "max_connections";`
Allemaal aanpasbaar via `set global max_connections = 200;` (root rechten required)
##### Aantal momenteel actieve threads bezien
`SHOW GLOBAL STATUS where variable_name like '%Threads%';` geeft:
```
Variable_name value
----------------------------
Delayed_insert_threads 0
Slow_launch_threads 0
Threads_cached 8
Threads_connected 56
Threads_created 138
Threads_running 2
```
##### Huidige connecties killen
Zie [Mass killing of MySQL connections](http://www.mysqlperformanceblog.com/2009/05/21/mass-killing-of-mysql-connections/)
Gaat **niet rechtstreeks**; eerst een file maken met `kill` commands en die dan sourcen in een mysql command line:
`select concat('KILL ', id, ';') from information_schema.processlist where host like '%myhost%' into outfile 'c:<br/>a.txt';`
:exclamation: Forward slashen in Windows gebruiken, of dubbele backslash.
Stap 2: `source c:/a.txt` - géén single quotes hierrond (anders error code 22) en geen single baskslash (anders error code 2, = file not found)
MySQL command line opstarten: ga naar bin dir van installed server, en execute `mysql --user###### --pass`.

View File

@ -0,0 +1,64 @@
+++
title = "oledb"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"oledb"
]
date = "2014-02-27"
+++
# Oledb
## Named parameter problem
Blijkbaar werkt `OleDbCommand` nooit met named parameters, maar is de **volgorde van toevoegen** zeer belangrijk. In De query zelf worden '?' tekens gebruikt om een parameter aan te duiden. Dit is zeer vervelend, en maakt het abstraheren van de DB laag moeilijk - andere DB providers staan bijvoorbeeld `@parameter` toe, waarbij de naam wel uitmaakt. Hoe lossen we dat op?
#### Convert named parameters into positional ones
Hocus pocus: (zie ook http://stackoverflow.com/questions/2407685/oledbparameters-and-parameter-names etc)
```csharp
public static OleDbCommand ConvertNamedParametersToPositionalParameters(OleDbCommand command)
{
// OleDb does NOT use named parameters, but we want them! (uses '?')
var newParameters = new List<OleDbParameter>();
command.CommandText ###### Regex.Replace(command.CommandText, "(@<br/><br/>w*)", match >
{
var parameter ###### command.Parameters.OfType<OleDbParameter>().FirstOrDefault(a > a.ParameterName ###### match.Groups[1].Value);
if (parameter != null)
{
var parameterIndex = newParameters.Count;
var newParameter = command.CreateParameter();
newParameter.OleDbType = parameter.OleDbType;
newParameter.ParameterName = "param_" + match + "_" + parameterIndex.ToString();
newParameter.Value = parameter.Value;
newParameters.Add(newParameter);
}
return "?";
});
command.Parameters.Clear();
command.Parameters.AddRange(newParameters.ToArray());
return command;
}
```
######= Gewenste Resultaat ######=
Maakt het mogelijk om dit te doen:
* `SELECT * FROM TABLE WHERE column ###### @name1 AND column2 @name2`
* voeg aan command `new OleDbParameter("@name1", value)` toe
* wordt automagically vervangen door vorige method (kan als extension gebruikt worden)
:exclamation: In [code/db/sqlite]({{< relref "wiki/code/db/sqlite.md" >}}) wordt dit by default ondersteund...

View File

@ -0,0 +1,53 @@
+++
title = "postgresql"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"postgresql"
]
date = "2013-08-09"
+++
# PostgreSQL
Documentatie: http://www.postgresql.org/docs/9.1/static/view-pg-locks.html
pgAdmin: http://www.pgadmin.org/
:exclamation: Heeft géén commit & rollbacks, alles wat uitgevoerd wordt kan niet teruggedraaid worden!
#### Metadata tabellen bekijken
##### Alle views van een bepaald schema
`SELECT count(*) FROM information_schema.views where table_schema = 'public';`, vergeet niet dat `table_schema` `pg_catalog` is voor de metadata tabellen die altijd bestaan in postgres.
##### Alle kolommen
Voorbeeld om alle floats te selecteren (kan afrondingsfouten bevatten, gebruik `numeric` in de plaats):
```sql
SELECT * FROM information_schema.columns where
(data_type = 'real' or
data_type like 'double%')
and table_schema = 'public'
and table_name not like 'view_%'
and table_name not like 'lookup_%';
```
#### Dump van DB nemen
Gebruik hiervoor `pgdump` in bin folder van postgres install dir:
```
C:<br/>Program Files<br/>PostgreSQL<br/>9.1<br/>bin>pg_dump --host######10.16.42.35 --port5432 --username######postgres --schemapublic --format=c --schema-only repository.db > postgresdump_20111020.dmp
```
Verklaring:
* `--format`: c (custom), d (directory), t (tar), p (plain text)
* `--schema`: dump enkel dit stuk

218
content/wiki/code/db/sql.md Normal file
View File

@ -0,0 +1,218 @@
+++
title = "sql"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"sql"
]
date = "2013-09-03"
+++
# code:db >> Sql
## Stored procedures
### Oproepen
Zie http://stackoverflow.com/questions/3991721/run-stored-procedure-in-sql-developer
Gegeven: een procedure `GETPERMISSIONSALL` als volgt gedeclareerd:
```sql
create or replace
PROCEDURE "GETPERMISSIONALL" ( v_actCreator in VARCHAR2, v_repGuid in VARCHAR2, v_userid INT, v_retHasPermission out SMALLINT)
```
De laatste parameter is de return waarde (kunnen meerdere dingen zijn dus). Hoe roep ik nu zoiets aan?
#### In SQL Developer
Definiëer eerst uw variabelen, om ze daarna eventueel af te drukken -
```sql
SET serveroutput on;
DECLARE
v_actCreator VARCHAR2(100);
v_repGuid VARCHAR2(100);
v_userid int;
Output smallint;
BEGIN
/* Assign values to IN parameters */
v_actCreator := '19980121164845.106.1 7';
v_repGuid := '2466B39EFDA94D5E9249D252FF25C4D6';
v_userid := 540;
/* Call procedure within package, identifying schema if necessary */
GETPERMISSIONALL(v_actCreator, v_repGuid, v_userid, Output);
/* Display OUT parameters */
dbms_output.put_line('Output: ' || Output);
END;
/
-- Display OUT parameters
-- print :Output;
```
##### Werken met REF CURSOR
Probleemstelling:
1. Uw procedure retourneert een `REF CURSOR` als IN en OUT variabele
2. Je wil over deze gaan loopen en ergens een resultaat afdrukken of vergelijken
3. openen van een `REF CURSOR` gaat niet.
Gebruik in een `LOOP` dadelijk `FETCH` `INTO`:
```sql
SET serveroutput ON;
DECLARE
P_USERID NUMBER;
MY_P_CURSOR C2MV5_DEV.PKG_WFSEC.Validation_Send_Item_Cursor;
cursor_element C2MV5_DEV.PKG_WFSEC.WFSEC_Send_Item_T;
BEGIN
P_USERID := 11;
PKG_WFSEC.FETCHSENDITEMS(
P_USERID => P_USERID,
P_CURSOR => MY_P_CURSOR
);
WHILE TRUE LOOP
FETCH MY_P_CURSOR INTO cursor_element;
EXIT WHEN MY_P_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(cursor_element.executingdoctorname);
END LOOP;
END;
```
Merk op dat hier bijvoorbeeld `cursor_element` van een bepaald type is dat in een package gedefinieerd is, dat de cursor ook retourneert (`TYPE Validation_Send_Item_Cursor IS REF CURSOR RETURN WFSEC_Send_Item_T;`)
#### In C#
```csharp
public object QueryProcedure(string procedure, IDictionary<string, object> parameters, string outputParameter)
{
var command = new OleDbCommand(procedure);
foreach (var item in parameters)
{
command.Parameters.AddWithValue(item.Key, item.Value);
}
var output = command.Parameters.AddWithValue(outputParameter, 0);
output.Direction = ParameterDirection.Output;
QueryProcedure(command);
return output.Value;
}
```
### Unit testen
#### Met SQL Developer
zie [Oracle docs: Unit Testing in SQL Developer 3+](http://docs.oracle.com/cd/E15846_01/doc.21/e15222/unit_testing.htm)
:exclamation: Read this first: [Unit Testing PL/SQL In SQL Developer problems](http://www.fuzzy.cz/en/articles/unit-testing-plsql-code-in-sql-developer-problems/) - toch niet zo geweldig? <br/><br/>
Kan blijkbaar al niet apart gerund worden (mee in de build? een of nadere bat file van SQLDev zelf?)
<img style='float: left;' src='/img//code/db/unittest_sqldev.png |'>
Als uw stored procedure data wijzigt kan je in de startup en teardown process stappen toevoegen: "table or row copy", om die daarna terug te zetten.
##### Test gerelateerde tabellen opkuisen
Als je database-onafhankelijk testen wil draaien, kan je deze ook exporteren en importeren, en daarna runnen. Een import verwijdert echter niet oude niet-relevante unit tests, dus opkuisen van de UT repository is wel vereist. Hier is een `SQL` stored proc. om de boel te automatiseren:
```sql
SET serveroutput ON;
DECLARE
queryStr VARCHAR2(100);
tableName VARCHAR2(900);
cursor tableCursor is SELECT table_name FROM dba_tables where owner ='user' and table_name like 'UT_TEST_%' or table_name like 'UT_SUITE_%';
BEGIN
dbms_output.enable(10000);
DBMS_OUTPUT.PUT_LINE('Cleaning unit test tables');
open tableCursor;
fetch tableCursor into tableName;
WHILE (tableCursor%FOUND) LOOP
queryStr := 'delete from ' ||tableName;
execute immediate queryStr;
--DBMS_OUTPUT.PUT_LINE(queryStr);
fetch tableCursor into tableName;
END LOOP;
close tableCursor;
commit;
DBMS_OUTPUT.PUT_LINE('SUCCESS - all cleaned!');
END;
/
```
Dit kan je runnen met `sqlplus` op de volgende manier:
```
sqlplus user/pass@db @"fullpath_to_filename.sql"
```
:exclamation: Let op met spaties in filename, gebruik daarom dubbele quotes hierboven.
##### Command-line testen runnen
```
ututil -run -suite -name [name] -repo [repo] -db [db] -log 3
```
Uw repository naam is dezelfde als de DB naam als je Tools > Unit Test > Create/Update Repository... gekozen hebt via SQL Developer.
:exclamation: `ututil` kan de db connectie namen **niet resolven bij TNS** - Gebruik **Connection Identifier** (copypaste desnoods van `tnsnames.ora`)<br/><br/>
Fout die je anders krijgt:
```
D:<br/>oracle<br/>sqldeveloper<br/>sqldeveloper<br/>bin>ututil -run -test -name GETPERMISSIONALL -repo CHCDEV -db CHCTEST -log 3
SEVERE oracle.jdeveloper.db.ConnectionException: Could not connect to database CHCTEST. The error encountered was: Ongeldige verbindingsgegevens opgeg
even.
Controleer de notatie van de URL voor de opgegeven driver.
oracle.jdeveloper.db.DatabaseConnections.getUniqueConnection(DatabaseConnections.java:514)
SEVERE null - oracle.dbtools.unit_test.utils.UtUtils.getRunnerConnection(UtUtils.java:141)
Unable to run test
```
##### Integratie met de build: C#
Een `SqlDeveloperTest` klasse die het volgende doet:
1. voer `sqlplus` uit met bovenstaande cleanup script dat alle repository tabellen cleart
2. voer `ututil` uit met `-imp -repo [repo] -file [xmlfile]`
3. voer `ututil` uit met `-run` zoals boven aangegeven.
De eigenlijke unit testen leven dan in uw source control omgeving zoals `TFS`, in die ene xml file. Op die manier kan je branchen en zo zonder dat die testen vasthangen aan je DB schema. Joepie!
## Problemen
#### NOT IN retourneert geen enkele resultaten ??
voorbeeld:
```sql
select * from sch_vac.VAC_TAKEN
where ikl_id is not null
and ikl_id not in (select iklnummer from VAC_WERFRES_KANDIDATEN)
```
> There are serious problems with subqueries that may return NULL values. It is a good idea to discourage the use of the NOT IN clause (which invokes a subquery) and to prefer **NOT EXISTS** (which invokes a correlated subquery), since the query returns no rows if any rows returned by the subquery contain null values.
Oplossing is dus:
```sql
select * from vac_taken taak where ikl_id is not null
and not exists (select 1 from vac_werfres_kandidaten where iklnummer = taak.ikl_id)
```

View File

@ -0,0 +1,254 @@
+++
title = "sqlite"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"db",
"sqlite"
]
date = "2015-07-17"
+++
# SQLite
### DDLs copypasten van Oracle
Bijvoorbeeld de gegenereerde versie (SQL tab) van Oracle SQL Developer overnemen gaat niet zomaar.
Er zijn enkele verschillen:
1. `NOT NULL ENABLE` wegdoen. `NOT NULL` maakt niets uit aangezien het in-memory is om te testen!
2. `USING INDEX` blabla na de `PRIMARY KEY` statements zijn ook allemaal niet nodig (`STORAGE` etc)
3. speciale defaults of syscalls zoals `sys_guid()` bestaan niet.
4. definities van groottes: wegdoen van `BYTE`: `VARCHAR2(26)` dus.
5. opletten met datums: zie onder.
6. Namespace mag ook weg bij `CREATE TABLE "SPACE"."NAME" (`
### Connection strings
Zie http://www.connectionstrings.com/sqlite/
##### File based
```
Data Source######c:<br/>mydb.db;Version3;
```
##### In-memory
```
Data Source######:memory:;Version3;New=True;
```
Conventie `Data Source=` notatie gehanteerd door [http:*www.connectionstrings.com/sqlite/](http:*www.connectionstrings.com/sqlite/)
Andere notatie
```
FullUri######file::memory:?cacheshared
```
Notatie gehanteerd door [https:*www.sqlite.org/inmemorydb.html](https:*www.sqlite.org/inmemorydb.html)
Versie en New hoeft blijkbaar niet (?)
:exclamation: Elke keer als je een connectie opendoet gaat SQLite de inmemory DB state restoren naar default (dus leeg). Als je dus bvb;
1. connectie open
2. `CREATE TABLE;` brol uitvoeren
3. connectie sluiten
4. roep andere method aan
1. connectie open
1. `SELECT * FROM TABLE;` brol uitvoeren
BOEM no such table...
Zie ook [SQLite in memory create table does not work](http://stackoverflow.com/questions/17477246/sqlite-in-memory-database-create-table-does-not-work).
:exclamation: Hou dus 1x een connectie open voor unit testen bij een `[SetUp]` en geef referenties door.
##### Extra opties meegeven via de connection string
Je kan `PRAGMA` parameters zoals [deze](http://www.sqlite.org/pragma.html#pragma_locking_mode) meegeven.
### Integreren met C#
#### DB Connectie
Gebruik http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki (package `System.data.SQLite (x86/x64)`)
Voor `OleDb` C# code, is er voor elke klasse een equivalent in de `SQLite` namespace, bijvoorbeeld:
```csharp
private SQLiteConnection SqLiteDbConnection()
{
return new SQLiteConnection()
{
ConnectionString ###### "Data Sourcemydb.s3db;",
Flags = SQLiteConnectionFlags.LogAll
};
}
public void SetupDb()
{
using (var connection = SqLiteDbConnection())
{
connection.Open();
var transaction = connection.BeginTransaction();
var sqLiteCommand = new SQLiteCommand()
{
Connection = (SQLiteConnection) connection,
CommandType = CommandType.Text,
CommandText = GetSchemaCreateSql()
};
sqLiteCommand.ExecuteNonQuery();
transaction.Commit();
}
}
```
#### Builden op x86/x64 systemen
Afhankelijk van welke package manager je gebruikt (NuGet bvb.) kan een `SQLite.interop.dll` in submapjes `x86` en `x64` geplaatst worden (Copy always als content). Lokaal werkt dit, maar op de build pc (die bijvoorbeeld enkel 32-bit is) niet, omdat de DLL op dezelfde plaats als de executable verwacht wordt. Hier zijn een paar mogelijke oplossingen voor:
1. Gebruik enkel de 32bit versie. (er is zo'n specifieke package voor)
2. "Hint" de DLL loader om de juiste te gebruiken
```csharp
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet ###### System.Runtime.InteropServices.CharSet.Unicode, SetLastError true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);
```
```csharp
[STAThread]
static void Main()
{
int wsize = IntPtr.Size;
string libdir ###### (wsize 4)?"x86":"x64";
string appPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
SetDllDirectory(System.IO.Path.Combine(appPath, libdir));
// ...
}
```
Zie ook [http:*stackoverflow.com/questions/13028069/unable-to-load-dll-sqlite-interop-dll](http:*stackoverflow.com/questions/13028069/unable-to-load-dll-sqlite-interop-dll)
#### .NET dates en SQLite dates
Als je een `DATE` kolom hebt, en een SQL zoals gewoon `select * from blah;` uitvoert, kan je de volgende fout krijgen:
```
String was not recognized as a valid DateTime
```
Dit komt doordat SQLite dynamisch getypeerd is en voor hem een date hetzelfde als een char is, gebruik daarvoor de `date()` functie om zelf te parsen! Beetje vervelend in de queries...
Een andere mogelijkheid is `DateTimeFormat=Ticks` in de connection string meegeven.
#### Creating integration tests, using Record objects
Maak objecten die extenden van `DatabaseInsertable`:
```csharp
public abstract class DatabaseInsertable
{
protected abstract string GetTable();
public override string ToString()
{
var fieldDict = FieldDictionary();
var fields = "(" + string.Join(",", fieldDict.Keys) + ")";
var values = "(" + string.Join(",", fieldDict.Values) + ")";
return "insert into " + GetTable() + fields + " values " + values;
}
public void Save()
{
DbConnection.Instance.CreateCommand(ToString()).ExecuteNonQuery();
}
private Dictionary<string, string> FieldDictionary()
{
var dictionary = new Dictionary<string, string>();
foreach (var info in this.GetType().GetFields())
{
if (info.GetValue(this) != null)
{
dictionary.Add(info.Name, "'" + info.GetValue(this).ToString() + "'");
}
}
return dictionary;
}
}
```
Zoals bijvoorbeeld
```csharp
internal class UnitRecord : DatabaseInsertable
{
public string creator;
public string guid;
protected override string GetTable()
{
return "UNIT";
}
}
```
Gebruik:
```csharp
new UnitRecord() { creator ###### "bla"; guid "lala"; }.Save(); // done!
// execute your SUT stuff here
```
`DbConnection` gebruikt dan de SQLite versie om een "unit" record aan te maken in de DB. Merk op dat de properties 100% moeten overeenkomen.
Het enige speciale wat in `IntegrationTestCase` gedefiniëerd is, is de "gewone" `OleDbConnection` vervangen door de SQLite verie:
```csharp
public abstract class IntegrationTestCase
{
protected SqLitedbConnection connection;
[TestInitialize]
public void CleanDb()
{
this.connection = new SqLitedbConnection();
DbConnection.Instance = connection; // instead of OleDbConnection, lazyloaded singleton getter property.
}
}
```
Omdat Ole en SQLite soms andere interfaces hebben moeten we er zelf een anticorruptie laag (de IConnection interface) tussen zetten:
```csharp
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
public interface IdbConnection
{
object QueryProcedure(string procedure, IDictionary<string, object> parameters, string outputParameter);
DbParameter CreateParameter(string field, object value);
DbCommand CreateCommand(string query);
DataSet Query(DbCommand command);
DataSet Query(string query);
}
```
Het verschil is altijd een `SQLiteCommand` in plaats van een `OleDbCommand` aanmaken. Er zijn soms ook subtiele verschillen in het aanmaken en doorgeven van de parameters.

50
content/wiki/code/dev.md Normal file
View File

@ -0,0 +1,50 @@
+++
title = "dev"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"dev"
]
date = "2013-03-12"
+++
# code >> Dev
## Tools etc
Notepad++ **JSON Formatter**:
`JSONViewer` voor notepad++: http://sourceforge.net/projects/nppjsonviewer/ - doet:
1. json viewer treeview geselecteerde json
2. format json (heel handig voor `POST` body gepaste hierin)
## Links
#### Mocking tools
* https://gomockingbird.com/ (niet gratis, van Jan zijn werkgroepje)
* http://balsamiq.com/products/mockups (gratis maar om de 5 minuten een dialog wegklikken)
* http://www.mockflow.com/
#### Algemene development tools
##### Tracking
* https://www.pivotaltracker.com/ - simple, collaborative, single-view project tracking/management
* http://leankitkanban.com/ - online Kanban tracking (betalend)
#### Tech blogs
* http://www.dzone.com/links/index.html
Voor **javascript**: zie [Javascript home page]({{< relref "wiki/code/javascript/index.md" >}})
#### Designer blogs
* http://www.smashingmagazine.com/
* http://www.alistapart.com/
* http://css-tricks.com/

View File

@ -0,0 +1,310 @@
+++
title = "dynamiclangs"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"dynamiclangs"
]
date = "2013-03-12"
+++
# Dynamic Languages: Constructs vergelijken
Deze pagina vergelijkt verschillende dynamische talen in een poging om een overzicht te maken tussen de alsmaar groeiende lijst. De meest gebruikte features van zulke talen worden hieronder opgelijst.
## Het verschil tussen MOPs en Prototypal inheritance
:exclamation: Javascript heeft géén **Meta Object Protocol** (MOP) dat de taal dynamisch maakt, maar bouwt verder op prototypes. Dat wil zeggen dat het klassieke inheritance systeem niet bestaat in Javascript, maar wel nagebootst kan worden door objecten te laten afleiden van objecten. De vergelijkingstabellen hieronder tonen hoe Javascript zich kan *gedragen* als een klassieke OO taal, dat wil niet automatisch zeggen dat dit de beste manier is om JS te gebruiken!
De volgende dynamische talen beschikken wel over een MOP:
1. Groovy
2. Python
3. Ruby
4. Smalltalk dialecten
5. LISP dialecten (bvb. Runtime MOPs via `CLOS`)
6. Perl 6
7. OpenC++ (bvb. Compiletime MOPs door C++ te parsen en analyseren)
[Ruby VS Javascript metaprogramming](http://fingernailsinoatmeal.com/post/292301859/metaprogramming-ruby-vs-javascript):
> The most interesting thing about the Javascript example is that it is exactly the same as the example of adding a dynamic method to a class. There is no difference because Javascript functions **are** closures. The ubiquity of closures in Javascript is extremely powerful and, makes metaprogramming very easy.
Voor meer informatie, zie wiki entry over **[Javascript inheritance]({{< relref "wiki/code/javascript/inheritance.md" >}})**
# Vergelijkingstabellen
## Dynamica van de taal: Metaprogramming
### Methods toevoegen
#### Op klasse niveau
^ Javascript ^ Groovy ^
| ```javascriptString.prototype.isTrue = function() {
return this ###### "true";
}``` | ```javaString.metaClass.isTrue = {
delegate ###### "true"
}``` |
Javascript bevat enkele *common pitfalls* hierrond, zie [JS Inheritance]({{< relref "wiki/code/javascript/inheritance.md" >}}).
Groovy staat ook toe om *constructors* toe te voegen op deze manier. <br/><br/>
Methods "lenen" gaat ook met de **&.** operator in Groovy om de pointer naar een method vast te krijgen. In JS gewoon de "key" (methodnaam) als referentie gebruiken.
######= Op instance niveau ######=
^ Javascript ^ Groovy ^
| ```javascript"someString".isTrue = function() {
return this ###### "true";
}``` | ```java"someString".metaClass.isTrue = {
delegate ###### "true"
}``` |
Voor beide talen op exact dezelfde manier dus, op een *instance* zelf.((Groovy 1.6+ heeft dit standaard, anders uw metaClass nog correct aanpassen! Zie http://groovy.codehaus.org/Per-Instance+MetaClass ))
Als Groovy problemen geeft, kan het zijn doordat `ExpandoMetaClass` niet geconfigureerd staat voor *inheritance*:
```java
ExpandoMetaClass.enableGlobally()
```
############ Methods catchen ############
Met "catchen" wordt "*decoreren*" bedoeld. van alle calls op van method namen die niet bestaan en doe ermee wat je wilt.
^ Javascript ^ Groovy ^
| **niet** mogelijk | ```javaSomeClass.metaClass.methodMissing = { name, arguments ->
switch(name) {
case "bla": return "blaing eh"
break;
}
}
assert "blaing eh" ###### new SomeClass().bla()
``` |
Groovy kan ook **alle methods** opvangen, ook de bestaande, door de MOP hook `invokeMethod`, `get/setProperty`, `propertyMissing` etc te overriden - op `Object` of `metaClass` niveau, op deze manier:
```java
class SomeClass {
def invokeMethod(String name, args) {
switch(name) {
case "bla": return "blaing eh"
break;
default:
// delegate.invokeMethod name, arguments makes an infinite loop! it's a tarp!
delegate.metaClass.getMetaMethod(name, arguments).invoke(delegate, arguments)
}
}
}```
En ja, dat werkt [Ook met static methods in Groovy](http://groovy.codehaus.org/ExpandoMetaClass+-+Overriding+static+invokeMethod)!
:exclamation: Rhino en SpiderMonkey implementaties van JavaScript (Firefox' JS parser bijvoorbeeld) ondersteunen wel een magic missing method, genaamd `__noSuchMethod__` en een hele hoop andere nifty dingen zoals `__defineGetter__` en `__lookupSetter__`. Meer informatie in [deze blogpost](http://offthelip.org/?p=101) te vinden. Voorbeeld in Firefox+Firebug:
```javascript
SomeClass.prototype.__noSuchMethod__ = function(name, arguments) {
console.log("calling method " + name + " with arguments " + arguments);
if(name ###### "bla") {
return "blaing eh";
}
}
"blaing eh" ###### new SomeClass().bla() // true
```
Merk op dat in Groovy zoiets niet bestaat, we overriden **ender welke methodCall**, daarom dat in de `default` van het `switch` statement nog altijd een delegate invoke moet gebeuren!
############ Properties toevoegen ############
^ Javascript ^ Groovy ^
| ```javascriptvar gapingHoleInTheGalaxy = function() {}
gapingHoleInTheGalaxy.theSun = "extraHot"; // method 1
gapingHoleInTheGalaxy['theSun'] = "extraHot"; // method 2
gapingHoleInTheGalaxy.explode = function() {
console.log("Explosion!")
}``` | ```javadef gapingHoleInTheGalaxy = new Expando()
gapingHoleInTheGalaxy.theSun = "extraHot" // method 1
gapingHoleInTheGalaxy['theSun'] = "extraHot" // method 2
gapingHoleInTheGalaxy.explode = {
println "Explosion!"
}``` |
:exclamation: Groovy heeft een speciale klasse `Expando` die dynamisch toelaat om eender wat toe te voegen, zowel *closures* als *properties* op dezelfde manier. Enige nadeel: deze code kan niet gemengd worden met Java als byte code. Bij gewone klassen kan dit niet en moet dit via de `metaClass` gaan. Bij Javascript werkt dit omdat op eender welk moment het prototype van een object veranderd kan worden en er geen onderscheid is tussen closures en functions.
Merk op dat hier de quotes nodig zijn om via de `[]` operator closures aan iets te hangen.
Het is wél mogelijk om properties via `metaClass` toe te voegen door de methodnaam de javaBean specificatie te laten volgen, bvb `metaClass.getBrol ###### {}` zodat men `def x inst.brol` kan uitvoeren.
############ Itereren over methods ############
^ Javascript ^ Groovy ^
| ```javascriptfor(propertyName in someInstance) {
var propertyValue = someInstance[propertyName]
if(typeof propertyValue ###### "function") {
var retVal = eval("someInstance." + propertyName + "(args)"); // method 1
retVal = propertyValue(args) // method 2
} else {
console.log(propertyName + " property with value " + propertyValue);
}
}``` | ```javaString.metaClass.methods.each {
def methodName = it.name // now what? methods are on class level
def retVal = someInstanceOfString."${methodName}"
}
someInstanceOfString.properties.each {
println "${it.key} property with value ${it.value}"
}``` |
############= Variable arguments ############=
############ varargs core ############
^ Javascript ^ Groovy ^
| ```javascriptfunction bla() {
for(arg in arguments) { console.log(arg); }
}
bla(1, 2, 3);
``` | ```javadef bla(Object[] args) { // method 1
def bla(Object... args) { // classic Java 1.5 method 2
args.each{ println it }
}
bla(1, 2, 3);
}``` |
Een map meegeven gaat altijd natuurlijk, om argumenten expressiever te maken, zoals configuratie: (Groovy vb.)
```java
def bla(Map args) {
println args.stuff
}
bla(stuff: "wow", c: 3)
```
############ Argument spreading ############
^ Javascript ^ Groovy ^
| ```javascriptfunction bla(a, b) {
return a + b + 2;
}
var args = [1, 2];
bla(1, 2) ###### bla.apply(this, args) // 5
``` | ```javadef bla(a, b) {
a + b + 2
}
def args = [1, 2]
bla(1, 2) ###### bla(*args)
``` |
############ Fixed arguments ############
^ Javascript ^ Groovy ^
| ```javascriptfunction bla(a, b, c) {
if(!c) var c = 0;
console.log("a: " + a + ", b: " + b + ", c: " + c);
}
bla(1, 2) // 1, 2, 0
bla(1, 2, 3); // 1, 2, 3
``` | ```javadef bla(a, b, c = 0) {
println "a: $a, b: $b, c: $c"
}
def blaWow = bla.curry(1)
blaWow(2) // 5, 2, 0
bla(1, 2) // 1, 2, 0
bla(1, 2, 3) // 1, 2, 3
``` |
Merk op dat bij JS er gecontroleerd moet worden of een variabele daadwerkelijk is ingevuld of niet. `curry` is niet standaard aanwezig maar kan eenvoudig geïmplementeerd worden, zoals deze snippet van het *Prototype* framework:
```javascript
function curry() {
if (!arguments.length) return this;
var __method ###### this, args slice.call(arguments, 0);
return function() {
var a = merge(args, arguments);
return __method.apply(this, a);
}
}
```
Dit roept in essentie de eigenlijke method op (met `apply`) met een aantal parameters predefined.
############= String interpolatie ############=
^ Javascript ^ Groovy ^
| **niet** mogelijk | ```javadef dinges = "mijn dingetje"
"$dinges is a dong" ###### "mijn dingetje is a dong"
``` |
JS extentie om dit mogelijk te maken: zie [Prototype JS interpolate](http://www.prototypejs.org/api/string/interpolate), bvb:<br/><br/>
`"#{dinges} is a dong".interpolate({dinges: "mijn dingetje"}) ###### "mijn dingetje is a dong"`<br/><br/>
Merk op dat dit eenvoudig een regex door de string laat lopen.
Merk op dat bij Groovy dit zeer krachtig is en hele expressies in strings kunnen gegoten worden zoals `"bla ${this.method} jong"`. Ook methods aanroepen zoals this."${methodName}" werkt.
############ Template parsing ############
Grotere brokken tekst interpoleren werkt via *templates*. In Prototype JS is er een `Template` klasse [aanwezig](http:*www.prototypejs.org/api/template), in Groovy zit een uitgebreide en uitbreidbare [template engine](http:*groovy.codehaus.org/Groovy+Templates):
^ Javascript ^ Groovy ^
| ```javascriptvar myTemplate = new Template('The TV show #{title} was created by #{author}.');
var show = {title: 'The Simpsons', author: 'Matt Groening', network: 'FOX' };
myTemplate.evaluate(show);``` | ```javadef string = "The TV Show ${title} was created by ${author}."
def myTemplate = new groovy.text.SimpleTemplateEngine().createTemplate(string)
def show = [ title: "The Simpsons", author: "Matt Groening", network: "FOX" ]
myTemplate.make(show).toString()
``` |
############= Evaluatie van expressies ############=
^ Javascript ^ Groovy ^
|```javascriptvar y = 20;
var X = function() {
this.y = 10;
this.boem = function() {
console.log(eval("10 * this.y")); // 100, without "this" = 200 (window scope)
}
}
new X().boem()``` | ```javaclass X {
def y = 20
def boem = {
def y = 10
println Eval.x(y, "10 * y") // 100
}
}
new X().boem()``` |
Groovy voorziet gemakkelijkheidshalve een paar methods op `Eval` zoals `Eval.me` (zonder params), x/xy/xyz. Wanneer iets uitgebreidere evaluatie nodig is gebruiken we `GroovyShell`:
```java
def binding = new Binding(x: 10, y: 100)
def shell = new GroovyShell(binding)
def retVal = shell.evaluate('''
def local = "uncatchable"
catchable = x * y
10
''')
assert retVal ###### 10
assert binding.catchable ###### 100 // method 1
assert binding.getVariable("catchable") ###### 100 // method 2
```
Alles wat geëvalueerd wordt zit binnen een `Script` klasse, daarom dat het `def` keyword niet nodig is, en enkel dient om lokale variabele te instantiëren. Merk op dat het zelfs zo mogelijk is om nieuwe klassen in te laden, of om Groovy code te evalueren met `GroovyShell` binnen Java klassen!
############= Scope chain aanpassen ############=
Dit is voor beide talen niet 100% hetzelfde: Groovy maakt het mogelijk om objecten te extenden on-the-fly met `use`, terwijl Javascript de lexicale scope chain kan aanpassen met `with`.
^ Javascript ^ Groovy ^
|```javascriptwith(window.screen) {
console.log(width);
}``` | ```javadir = new File("/tmp")
use(ClassWithEachDirMethod.class) {
dir.eachDir {
println it
}
}
``` |

View File

@ -0,0 +1,64 @@
+++
title = "htaccess"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"htaccess"
]
date = "2015-01-06"
+++
# .htaccess stuff
Basisprincipe van rewriterules: altijd `RewriteEngine On` en `RewriteBase /` toevoegen.
Daarna: `RewriteCond` slaat enkel op **éérstvolgende** `RewriteRule` regel.
#### Request exceeded the limit of 10 internal redirects due to probable configuration error
[bron](http://stackoverflow.com/questions/1611506/request-exceeded-the-limit-of-10-internal-redirects-due-to-probable-configuratio)
Gebruik `!^map/` voor de rule om bepaalde folders uit te sluiten als ze al herschreven zijn.
#### square bracket rules: rewrite flags
[zie ook docs](http://httpd.apache.org/docs/2.2/rewrite/flags.html)
1. NC: case insensitive
2. L: stop processing other rules (final)
3. R=123: redirect HTTP code
#### Redirecten - moved
[bron](http://enarion.net/web/htaccess/migrate-domains/)
Van oud naar nieuw domeinnaam:
```
RewriteCond %{HTTP_HOST} savesourdough.com$ [NC]
RewriteRule ^(.*)$ http://www.redzuurdesem.be/$1 [L,R=301]
```
1. Kan ook om bvb van `www` naar `http` of omgekeerd te redirecten.
2. `^(.*)$` catcht alles achter het domein in een parameter `$1`
#### Redirecten - verschillende domeinen
```
RewriteEngine On
#ADD TRAILING SLASH TO DIRECTORY IF NONE EXISTS
RewriteRule ^([^<br/>.]+[^/])$ http://%{HTTP_HOST}/$1/ [L]
RewriteCond %{HTTP_HOST} ^(www.)?site1.com$ [NC]
RewriteCond %{REQUEST_URI} !site1/ [NC]
RewriteRule ^(.*)$ /site1/$1 [L]
RewriteCond %{HTTP_HOST} ^(www.)?site2.com$ [NC]
RewriteCond %{REQUEST_URI} !site/ [NC]
RewriteRule ^(.*)$ /site2/$1 [L]
```

View File

@ -0,0 +1,19 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"home"
]
date = "2013-07-10"
+++
# code >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

68
content/wiki/code/java.md Normal file
View File

@ -0,0 +1,68 @@
+++
title = "java"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java"
]
date = "2013-05-17"
+++
# Java Stuff
## Inhoudsopgave
<img style='' src='/img/indexmenu>java|js context navbar nocookie'>
## Snippets
#### Upcasting hacks & tricks
Vies van `instanceof`? Gebruik `isAssignableFrom` om op een abstracte logica te implementeren die een interface nodig heeft enkele niveaus verder.<br/><br/>
Op die manier hebben we geen diamond inheritance nodig! Check it out:
```java
@SuppressWarnings("unchecked")
final void generateUidIfNotYetFilledIn() {
if (HasUid.class.isAssignableFrom(this.getClass())) {
HasUid hasUid = (HasUid) this;
if (isEmpty(hasUid.getUid())) {
hasUid.setUid(getEntityUidGenerator().generateFor((Class<? extends HasUid>) this.getClass()));
}
}
}
```
#### ReplaceAll case Insensitive
Geen `StringUtils` van apache commons method beschikbaar als `replaceIgnoreCase`... Stom!
```java
public class Main {
public static void main(String[] argv) throws Exception {
String str = "Abc abc";
String result = str.replaceAll("(?i)abc", "DEF");
System.out.println("After replacement:<br/>n" + " " + result);
}
}
```
Vergeet niet speciale regex karakters te escapen zoals `<br/><br/>[` de *brackets* etc.
## Pitfalls
#### Java versies
1. Java 7 & java 6 mixen: gebruik `-XX:-UseSplitVerifier` als VM argument wanneer exceptions zoals "expecting invalid stackmap frame..." zich voordoen. - Wat doet dit arumgent eigenlijk? [Java 7 Bytecode verification](http://chrononsystems.com/blog/java-7-design-flaw-leads-to-huge-backward-step-for-the-jvm.)
#### APIs
1. `Arrays.asList()` retourneert een *read-only* lijst! `add()` throwt een `UnsupportedOperationException`.
2. guava's `transform()` ea zijn **lazy-loaded**, let op met transacties en inner class state!

View File

@ -0,0 +1,20 @@
+++
title = "home"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"home"
]
date = "2014-01-29"
+++
# code:java >> Home
## Inhoudsopgave
<img style='' src='/img/indexmenu>.|js navbar nocookie'>

View File

@ -0,0 +1,53 @@
+++
title = "dynamica"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"dynamica"
]
date = "2013-03-12"
+++
# Dynamica
Hier zitten stukjes code om java meer dynamiek te geven (voorzover dat mogelijk is...)
Veel collectie gerelateerde dingen (`filter`, `map` etc) is reeds geïmplementeerd: http://code.google.com/p/guava-libraries/
### Reduce met optellen
```java
public class CollectionUtil {
public static interface EnkelvoudigeTeller<TellerType> {
boolean magMeegeteldWorden(TellerType object);
}
public static interface MeervoudigeTeller<TellerType> {
int geefAantalMeegeteld(TellerType object);
}
public static <TellerType> int tel(Collection<TellerType> objecten, MeervoudigeTeller<TellerType> teller) {
int geteld = 0;
for (TellerType object : objecten) {
geteld += teller.geefAantalMeegeteld(object);
}
return geteld;
}
public static <TellerType> int tel(Collection<TellerType> objecten, final EnkelvoudigeTeller<TellerType> teller) {
return tel(objecten, new MeervoudigeTeller<TellerType>() {
@Override
public int geefAantalMeegeteld(TellerType object) {
return teller.magMeegeteldWorden(object) ? 1 : 0;
}
});
}
}
```

View File

@ -0,0 +1,158 @@
+++
title = "aspectj"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"dynamica",
"aspectj"
]
date = "2013-03-12"
+++
# Loadtime weaving met aspectJ
## Spring weaving
Zie **demo projectje**: <img style='' src='/img//code/java/dynamica/weaving-test.zip|'>
:exclamation: Vanaf versie 3.0 moet `spring-instrument` in plaats van `spring-agent` gebruikt worden! (bestaat niet meer)
Zie http://static.springsource.org/spring/docs/3.1.0.RELEASE/reference/htmlsingle/#aop
Weavers:
1. **aspectj jar** `-javaagent:C:<br/>dvl.home<br/>env<br/>aspectj<br/>aspectjweaver-1.6.11.jar`
2. **spring-instrument jar** `-javaagent:C:/dvl.home/prj/comeet/tools/spring-instrument-3.1.0.RELEASE.jar`
#### Wat heb je nodig om loadtime weaving te laten werken
##### applicationContext.xml
* met spring-configured (zelfde als `org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect` bean, zie [spring docs](http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html))
* met `load-time-weaver` op
```xml
<?xml version######"1.0" encoding"UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http:*www.springframework.org/schema/beans http:*www.springframework.org/schema/beans/spring-beans-3.0.xsd
http:*www.springframework.org/schema/context http:*www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:spring-configured/>
<context:component-scan base-package="be.test"/>
<context:load-time-weaver/>
</beans>
```
##### juiste manier van opzetten beans
-> Een bean die `@Component` annotated is waar een andere bean die `@Configurable` ge-`new`t wordt, die via `@Autowired` injecties bevat
bijvroobeeld:
-> `SomeBean`
```java
@Component
public class SomeBean {
private final SomeBeanToInject someBeanToInject;
@Autowired
public SomeBean(SomeBeanToInject someBeanToInject) {
System.out.println("creating some bean, got injected: " + someBeanToInject);
this.someBeanToInject = someBeanToInject;
}
public OtherBean createOtherBean() {
return new OtherBean();
}
}
```
-> `OtherBean`
```java
@Configurable
public class OtherBean {
private SomeBeanToDynamicallyInject someBeanToDynamicallyInject;
@Autowired
public void setSomeBeanToDynamicallyInject(SomeBeanToDynamicallyInject someBeanToDynamicallyInject) {
System.out.println("Setting some dynamically injected bean! : " + someBeanToDynamicallyInject);
this.someBeanToDynamicallyInject = someBeanToDynamicallyInject;
}
}
```
-> `SomeBeanToDynamicallyInject`
```java
@Component
public class SomeBeanToDynamicallyInject {
public String message = "dynamically injected";
}
```
#### AspectJ en Junit testing
De annotatie `@EnableLoadTimeWeaving` heb je **NIET** nodig. Het is ook niet nodig om java config klasse te verwijzen, de context xml pikt dit met component scanning op!
```java
@ContextConfiguration(locations = { "../../applicationContext.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeBeanTest {
@Autowired
private SomeBean someBean;
@Test
public void someBeanIsDynamicallyInjected() {
Assert.assertTrue(someBean.createOtherBean().isDynamicallyInjected());
}
}
```
:exclamation: **Unit- en Integratietesten opsplitsen in andere source folders**! Waarom?<br/><br/>
Omdat, ééns als een class file ingeladen is door de JVM, deze in het geheugen blijft zitten, en de volgende keer dat een andere test binnen dezelfde suite deze wilt gebruiken en verwacht dat die enhanched is (dus `@Autowired` geïnjecteerd), dit niet zo is, omdat een vorige gewone unit test hier een `new` van gedaan heeft en dit reeds in het geheugen steekt.
Is hier een oplossing voor? `ClassLoader` cache clearen op een of andere manier? Zie http://members.iinet.net.au/~macneall/Java/ClassReloading.html -
> Java classes themselves are dumped from memory when the classloader that loaded them is garbage collected. So the way to dynamically reload a class is to make sure that you control the classloader for that class. So when, all the references to instances of that class are gone, and you null the classloader itself, the runtime should collect the class itself. Then, next time an object of that class is used, it needs to be loaded again.
Probleem doet zich voor met `mvn clean install` maar soms niet in eclipse??
## aop.xml configuratie
Deze wordt blijkbaar gebruikt om te bepalen wat er precies gewoven moet worden - als die er NIET is gaat hij by default alles weaven en een warning tonen in de console log:
```
[AppClassLoader@17943a4] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
```
File moet in **src/main/resources/META-INF/aop.xml** staan (op classpath). Content bvb:
```xml
<?xml version="1.0"?>
<aspectj>
<aspects>
<weaver options="-Xlint:ignore -nowarn">
<include within="@org.springframework.beans.factory.annotation.Configurable be.bla.blie..*" />
</weaver>
</aspects>
</aspectj>
```
##### options
1. `-Xlint:ignore -nowarn` negeert alle warnings dat bepaalde zaken niet gewoven kunnen worden
2. `-verbose` print meer debuginfo
3. `-showWeaveInfo` print wat wanneer gewoven wordt.

View File

@ -0,0 +1,84 @@
+++
title = "innerclasses"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"dynamica",
"innerclasses"
]
date = "2013-03-12"
+++
# code:java:dynamica >> Innerclasses
Java is geen dynamische taal maar je kan wel gebruik maken van een aantal handige trucjes om duplicatie te vermijden.
Bijvoorbeeld om **state bij te houden** en de implementatie zelf in een **inner klasse** te voorzien:
```java
private interface CrmEndpointWorker {
void call(Holder<Status> status, Holder<String> result);
}
public CrmImportGatewayAction forCreation() {
return new CrmImportGatewayAction(Action.CREATE);
}
public CrmImportGatewayAction forUpdating() {
return new CrmImportGatewayAction(Action.UPDATE);
}
public CrmImportGatewayAction forDeletion() {
return new CrmImportGatewayAction(Action.DELETE);
}
public CrmImportGatewayAction forDeactivating() {
return new CrmImportGatewayAction(Action.DEACTIVATE);
}
public class CrmImportGatewayAction {
private final Action actionType;
public CrmImportGatewayAction(Action actionType) {
this.actionType = actionType;
}
private CrmEndpointWorker accessdeviceAction(final List<Accessdevice> devices) {
return new CrmEndpointWorker() {
@Override
public void call(Holder<Status> status, Holder<String> result) {
getEndpoint().accessdeviceAction(actionType, new CrmConverter().convertDevices(devices), status, result);
}
};
}
public String sendAccessdevices(List<Accessdevice> devices) {
return callCrmEndpoint(accessdeviceAction(devices));
}
}
```
Wat is hier cool aan?
In plaats van 4 verschillende methods te voorzien op deze klasse:
* voor creation
* voor deletion
* voor updating
* voor activating
Kan je dit nu zo doen:
```java
service.forCreation().sendAccessdevices();
service.forDeletion().sendAccessdevices();
```
En de `Enum actionType` is toegankelijk binnen die inner klasse en wordt zo mee doorgegeven naar in dit geval de SOAP Endpoint call.
Prachtig, toch?

View File

@ -0,0 +1,263 @@
+++
title = "listmerger"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"dynamica",
"listmerger"
]
date = "2013-03-12"
+++
# code:java:dynamica >> Listmerger
```java
public final class ListMerger<ItemType, ItemTypeAfterConversion> {
private final Function<ItemType, ItemTypeAfterConversion> itemConverterFn;
public ListMerger() {
this.itemConverterFn = identityFn();
}
public ListMerger(Function<ItemType, ItemTypeAfterConversion> itemConverterFn) {
this.itemConverterFn = itemConverterFn;
}
private Function<ItemType, ItemTypeAfterConversion> identityFn() {
return new Function<ItemType, ItemTypeAfterConversion>() {
@SuppressWarnings("unchecked")
@Override
public ItemTypeAfterConversion apply(ItemType input) {
return (ItemTypeAfterConversion) input;
}
};
}
public final void mergeLists(List<? extends ItemType> oldList, List<? extends ItemType> newList, ListMergable<ItemType> mergable) {
List<ItemTypeAfterConversion> oldTransformed = new ArrayList<ItemTypeAfterConversion>(transform(oldList, itemConverterFn));
List<ItemTypeAfterConversion> newTransformed = new ArrayList<ItemTypeAfterConversion>(transform(newList, itemConverterFn));
for (ItemType item : new ArrayList<ItemType>(oldList)) {
if (!newTransformed.contains(itemConverterFn.apply(item))) {
mergable.itemHasBeenRemoved(item);
} else {
mergable.itemHasBeenChangedInOldList(item);
}
}
for (ItemType item : new ArrayList<ItemType>(newList)) {
if (!oldTransformed.contains(itemConverterFn.apply(item))) {
mergable.itemHasBeenAdded(item);
} else {
mergable.itemHasBeenChangedInNewList(item);
}
}
}
}
```
En de test:
```java
public class ListMergerTest {
private AtomicInteger integer = null;
private AtomicInteger amount = null;
@Before
public void setUp() {
this.integer = new AtomicInteger();
this.amount = new AtomicInteger(0);
}
@Test
public void noItemsChanged() {
new ListMerger<Integer, Long>(intToLongFn()).mergeLists(Lists.newArrayList(1, 3), Lists.newArrayList(1, 3), new ListMergable<Integer>() {
@Override
public void itemHasBeenRemoved(Integer item) {
throw new UnsupportedOperationException();
}
@Override
public void itemHasBeenChangedInOldList(Integer item) {
amount.set(amount.get() + 1);
}
@Override
public void itemHasBeenChangedInNewList(Integer item) {
}
@Override
public void itemHasBeenAdded(Integer item) {
throw new UnsupportedOperationException();
}
});
assertThat(amount.get()).isEqualTo(2);
}
@Test
public void itemHasBeenAddedUsingIdentity() {
new ListMerger<Integer, Integer>().mergeLists(Lists.newArrayList(1, 3), Lists.newArrayList(1, 2, 3), new ListMergable<Integer>() {
@Override
public void itemHasBeenRemoved(Integer item) {
throw new UnsupportedOperationException();
}
@Override
public void itemHasBeenChangedInOldList(Integer item) {
}
@Override
public void itemHasBeenChangedInNewList(Integer item) {
}
@Override
public void itemHasBeenAdded(Integer item) {
integer.set(item);
amount.set(amount.get() + 1);
}
});
assertThat(amount.get()).isEqualTo(1);
assertThat(integer.get()).isEqualTo(2);
}
@Test
public void itemHasBeenAdded() {
new ListMerger<Integer, Long>(intToLongFn()).mergeLists(Lists.newArrayList(1, 3), Lists.newArrayList(1, 2, 3), new ListMergable<Integer>() {
@Override
public void itemHasBeenRemoved(Integer item) {
throw new UnsupportedOperationException();
}
@Override
public void itemHasBeenChangedInOldList(Integer item) {
}
@Override
public void itemHasBeenChangedInNewList(Integer item) {
}
@Override
public void itemHasBeenAdded(Integer item) {
integer.set(item);
amount.set(amount.get() + 1);
}
});
assertThat(amount.get()).isEqualTo(1);
assertThat(integer.get()).isEqualTo(2);
}
@Test
public void itemHasBeenRemovedUsingIdentity() {
new ListMerger<Integer, Integer>().mergeLists(Lists.newArrayList(1, 3), Lists.newArrayList(1), new ListMergable<Integer>() {
@Override
public void itemHasBeenRemoved(Integer item) {
integer.set(item);
amount.set(amount.get() + 1);
}
@Override
public void itemHasBeenChangedInOldList(Integer item) {
}
@Override
public void itemHasBeenChangedInNewList(Integer item) {
}
@Override
public void itemHasBeenAdded(Integer item) {
throw new UnsupportedOperationException();
}
});
assertThat(amount.get()).isEqualTo(1);
assertThat(integer.get()).isEqualTo(3);
}
@Test
public void itemHasBeenRemoved() {
new ListMerger<Integer, Long>(intToLongFn()).mergeLists(Lists.newArrayList(1, 2, 3), Lists.newArrayList(1, 3), new ListMergable<Integer>() {
@Override
public void itemHasBeenRemoved(Integer item) {
integer.set(item);
amount.set(amount.get() + 1);
}
@Override
public void itemHasBeenChangedInOldList(Integer item) {
}
@Override
public void itemHasBeenChangedInNewList(Integer item) {
}
@Override
public void itemHasBeenAdded(Integer item) {
throw new UnsupportedOperationException();
}
});
assertThat(amount.get()).isEqualTo(1);
assertThat(integer.get()).isEqualTo(2);
}
private Function<Integer, Long> intToLongFn() {
return new Function<Integer, Long>() {
@Override
public Long apply(Integer input) {
return new Long(input);
}
};
}
}
```
Voorbeeld van gebruik:
```java
final List<Location> removedLocations = new ArrayList<Location>();
final List<Location> addedLocations = new ArrayList<Location>();
new ListMerger<Location, Location>().mergeLists(oldLocations, carpark.getLocations(), new ListMergable<Location>() {
@Override
public void itemHasBeenAdded(Location item) {
addedLocations.add(item);
}
@Override
public void itemHasBeenRemoved(Location item) {
removedLocations.add(item);
}
@Override
public void itemHasBeenChangedInOldList(Location item) {
}
@Override
public void itemHasBeenChangedInNewList(Location item) {
}
});
if (!removedLocations.isEmpty()) {
crmImportGatewayService.forDeletion().sendCarparkLocations(carpark, removedLocations);
}
if (!addedLocations.isEmpty()) {
crmImportGatewayService.forCreation().sendCarparkLocations(carpark, addedLocations);
}
```

View File

@ -0,0 +1,75 @@
+++
title = "encoding"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"encoding"
]
date = "2013-03-12"
+++
# Page Encoding
Alles zou in UTF-8 mode moeten staan. Daarvoor moeten verschillende dingen aangepast worden.
Een goede manier om te proberen of dit werkt is in een inputfield ALT+456 te typen
Dat zou *╚* moeten genereren, een 90° gedraaide dubbelgelijnde hoek.
Inspect via debug in een action geeft op de form dan normaal Lj als het niet correct geëncode is.
De waarde naar de DB kopiëren en dan terugkomen terwijl de DB niet correct geëncode is geeft *+* weer dan.
De waarde op inspect geeft vreemde vierkante tekens als uw struts filter niet correct gemapt is (zie onder).
Dit is nodig om POST gegevens te kunnen decoderen vanuit UTF-8!
## Eclipse console output naar UTF-8
http://paranoid-engineering.blogspot.com/2008/05/getting-unicode-output-in-eclipse.html
1. add -Dfile.encoding=UTF-8 to your eclipse.ini
2. make sure your Eclipse Console font supports Unicode. You can try it out by typing unicode characters directly to console with keyboard. Console Font is set in Window -> Preferences -> General -> Appearance -> Colors and Fonts -> Debug -> Console Font
3. if you are NOT using Windows, set your system encoding to UTF-8. You should now see Unicode characters in Console after restarting Eclipse.
4. if you are using Windows or do not want to change your OS encoding, you will have to avoid using System.out stream directly. Instead, wrap it up with java.io.printstream:```java
PrintStream sysout = new PrintStream(System.out, true, "UTF-8");
sysout.println("<br/>u2297<br/>u0035<br/>u039e<br/>u322F<br/>u5193");
```
1. if you are using Log4J with Console Appender, make sure to set the encoding property to UTF-8. Example:```java
#TRACE appender
log4j.appender.stdout.trace=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.trace.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.trace.encoding=UTF-8
log4j.appender.stdout.trace.layout.ConversionPattern=%p [%c] - %m%n
log4j.appender.stdout.trace.Threshold=TRACE
```
##Tomcat server in UTF-8 zetten
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q3
Vooral:
Set URIEncoding="UTF-8" on your <Connector> in server.xml
##Zet uw webpagina rendering in UTF-8
1. Overal in jsps charencoding=UTF-8 ipv ISO plaatsen (in de header en in de jsp directive)
2. Voor struts: een filter maken die op de request de encoding manueel naar UTF-8 plaatst (zie apache link bovenaan)<br/><br/> Die doet het volgende in de filter:```java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
```
1. In struts-config de controller in UTF-8 encoden
##Oracle database server in UTF-8 zetten
Voor DBAs, niet te vergeten natuurlijk, anders worden speciale chars die niet in ISO liggen incorrect opgeslaan.
Men kan zelf controleren welke encoding momenteel gebruikt wordt met
```sql
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET'
```
Kan bvb. *WE8MSWIN1252* uitkomen.

View File

@ -0,0 +1,86 @@
+++
title = "google-api"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"google-api"
]
date = "2013-03-12"
+++
# Google-api
## Google Endpoints Client lib
##### Genereren van java files
```bash
Timestamp: Tue Dec 11 12:41:31 CET 2012
#!/bin/sh
echo "--- COMPILING..."
mvn clean compile
echo "--- REMOVING OLD FILES & COPYING TO WEB-INF..."
rm -rf ./war/WEB-INF/devices-*
rm -rf ./war/WEB-INF/classes
cp -rf ./target/classes ./war/WEB-INF/
echo "--- GENERATING ENDPOINTS..."
/Users/jefklak/development/appengine/bin/endpoints.sh get-java-client-lib be.klak.gatecontrolweb.DevicesController
echo "--- EXTRACTING SOURCE JAR..."
cd ./war/WEB-INF
rm -rf devices
unzip devices-v1-java.zip
cd devices
unzip `ls | grep sources.jar`
cp -rf com ~/development/gatecontrol/receiver/src/main/java
echo "--- DONE!"```
##### maven deps voor de client
```xml
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.13.1-beta</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.13.2-beta</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>1.13.1-beta</version>
</dependency>
```
oauth is de enige compile dependency die aangeduid staat, maar api-client is nodig voor de algemene http transport - zie http://code.google.com/p/google-api-java-client/
Een client call maken kan je dan zo doen:
```java
NetHttpTransport transport = new NetHttpTransport();
// laatste param is voor credentials mee te geven
Devices devices = new Devices.Builder(transport, new JacksonFactory(), null).build();
try {
devices.houses().all().execute().getItems();
} catch (IOException e) {
e.printStackTrace();
}
```
`JacksonFactory` zit blijkbaar nergens in buiten in de `google-http-client-jackson2` lib.
Authenticatie etc: **zie [google-api-java-client OAuth2 wiki](http://code.google.com/p/google-api-java-client/wiki/OAuth2)**

View File

@ -0,0 +1,55 @@
+++
title = "logging"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"logging"
]
date = "2013-03-12"
+++
# code:java >> Logging
## Log4j Gebruiken over verschillende threads heen
**Probleem**: JMS handlers die bijvoorbeeld tegelijk starten en loggen naar éénzelfde file met `Logger.getLogger(x)`. Als een thread crasht en de andere afwerkt, maar we de volgorde van wegschrijven niet kunnen garanderen, hoe kunnen we dan dit onerscheid maken?
Oplossing: met `NDC` (Nested Diagnostic Context) - zie http://logging.apache.org/log4j/1.2/manual.html
Voorbeeld:
```java
protected static final Logger jmsLogger = Logger.getLogger("jmsLogger");
private void log(String message) {
jmsLogger.info("Incoming JMS Message (" + getClass().getSimpleName() + "): " + message);
}
@Override
public void doHandle(String textMessage) {
try {
String usernameFromTextMessage = getUsernameFromTextMessage(textMessage);
NDC.push(currentThread().getName() + "#" + currentThread().getId() + "@" + usernameFromTextMessage);
log("Started handling: " + textMessage);
VacatureSecurityInitializer.initConsulentUserInContext(usernameFromTextMessage);
handleTextMessage(textMessage);
log("Completed handling");
} finally {
resetSecurityContext();
NDC.pop();
}
}
```
`NDC.push()` zou een unieke parameter moeten binnen pakken, dit wordt geprepend aan de log ouput:
```
[INFO ] 23/03/2012 15:19:07 jmsLogger - JZAMAN - Incoming JMS Message (VerwijzingVersieVerhoogdHandler): Completed handling
```

View File

@ -0,0 +1,96 @@
+++
title = "monitoring"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"monitoring"
]
date = "2014-04-15"
+++
# Monitoring
## JBOSS As a Windows service & monitoring params
https://community.jboss.org/wiki/JBossNativeWindows
Als JBoss via `jbossvc.exe` als een windows service geconfigureerd is, lijkt het moeilijk om `JAVA_OPTS` mee te geven om JMX poorten in te stellen e.a. (debugging misschien) - zie onder. Die executable callt basically `run.bat`, dus alle customizaties gewoon daar doen.
Staat standaard dit in:
```
set JAVA_OPTS######-Dprogram.name%PROGNAME% %JAVA_OPTS%
```
## Java JMX Monitoring
Op de JVM: gebeurt met **JMX**.
##### Enablen
Params voor JMX te enablen op de queue:
```
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port######3000 -Dcom.sun.management.jmxremote.sslfalse -Dcom.sun.management.jmxremote.authenticate=false"
```
##### JMX URLs opbouwen
```service:jmx:rmi:*/jndi/rmi:*server.com:3000/jmxrmi```
indien de remote server op server.com draait op poort 3000 (zie boven). Drie slashen na 1ste rmi, twee na de 2de en 1 tussen jndi en rmi in.
##### Java Monitoring console
Opstarten van **jconsole.exe** in JVM bin folder, gebruik bovenstaande URL. <br/><br/>
Dan is het mogelijk om jmx-exposed beans te inspecten en remote methods uit te voeren, plus de draaiende JVM te monitoren qua geheugen etc.
##### Spring gebruiken om beans te exposen
```java
<bean class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key######"bean:nameBeanName" value-ref="someBean" />
</map>
</property>
<property name######"registrationBehaviorName" value"REGISTRATION_IGNORE_EXISTING" />
</bean>
```
## Geheugen monitoren
Kan bijvoorbeeld met **VisualVM** - je kan met JMX connecten en dan een dump nemen op de remote locatie waar de JVM op draait. Als er een `PermGen space` out of memory zich voor doet kunnen we de dump file analyseren en er hopelijk iets nuttig uit halen.
##### Automatisch een dump nemen na out of memory
Doen met volgende JVM params:
```
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/tomcat/dumps
```
Zorg ervoor dat het heap dump path schrijfbaar is...
##### PermGen en reflectie
Als er een hele hoop klassen tegelijk aangemaakt worden (inner classes = PermGen space, objecten zitten gewoon op de heap, beginnend met eden), komt de PermGen space misschien in het gedrang. Aan te passen met:
```
-XX:MaxPermSize=400M
```
:exclamation: Deze worden blijkbaar door de JVM standaard niet garbage-collected. Zie http://stackoverflow.com/questions/3334911/what-does-jvm-flag-cmsclassunloadingenabled-actually-do - je kan dit wel forceren met de volgende parameters:
```
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
```
Er wordt daar een voorbeeld aangehaald ivm JAXB die een hoop proxy objecten tegelijk aanmaakt via `java.lang.reflect.Proxy`. Een entity root kopiëren door middel van relfectie cloning zou bijvoorbeeld ook een potentiëel probleem kunnen zijn.

View File

@ -0,0 +1,211 @@
+++
title = "oraclegeometry"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"oraclegeometry"
]
date = "2013-03-12"
+++
# Oracle Geometries
## SDO_GEOMETRY Mappen in de DB
Via Hibernate: met een `UserType` implementatie
```java
public Object nullSafeGet(ResultSet resultSet, String[] strings, Object o) throws HibernateException, SQLException {
STRUCT geometry = (STRUCT) resultSet.getObject(strings[0]);
if (resultSet.wasNull() || geometry ###### null) {
return null;
}
return new Geometry(JGeometry.load(geometry));
}
/**
* setNull(i, Types.OTHER or Types.STRUCT) results in "unknown column type" exceptions!
*/
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i) throws HibernateException, SQLException {
if (o ###### null) {
preparedStatement.setNull(i, Types.STRUCT, OracleSpatialDialect.MSYS + "." + OracleSpatialDialect.SDO_GEOM_TYPE_COLUMN);
} else {
if (o instanceof Geometry) {
Connection oracleConnection = ((DelegatingConnection) preparedStatement.getConnection()).getInnermostDelegate();
STRUCT struct = JGeometry.store(((Geometry) o).getInnerGeometry(), oracleConnection);
preparedStatement.setObject(i, struct);
}
}
}
```
Merk op dat de `store()` method op `JGeometry` effectief een oracle connectie object nodig heeft (harde cast gebeurt in de implementatie). een struct object kan dan omgevormd worden naar `JGeometry` (te downloaden: *sdoapi* jar, Oracle Spatial Java API). Het `Geometry` object is iets dat hierrond gewrapped is. Dit heeft een aantal voordelen:
1. Afscheiden spatial api dependency rest van de code
2. Makkelijk converteren van `SDO_GEOMETRY('...') String` waarde naar object en omgekeerd
############= Van String naar Object en omgekeerd ############=
```java
public class Geometry implements Cloneable, Serializable {
private static final String MDSYS_POINT_TYPE = "MDSYS.SDO_POINT_TYPE";
private static final String MDSYS_ORDINATE_ARR = "MDSYS.SDO_ORDINATE_ARRAY";
private static final String MDSYS_ELEMENT_ARR = "MDSYS.SDO_ELEM_INFO_ARRAY";
private static final String MDSYS_GEOM = "MDSYS.SDO_GEOMETRY";
final static int SRID = 327680;
private final JGeometry geometry;
public Geometry() {
this.geometry = null;
}
public Geometry(String sdoGeometry) throws GeometryConversionException {
try {
this.geometry = disassembleSdoGeometry(sdoGeometry);
} catch (Exception disassemblingEx) {
throw new GeometryConversionException(disassemblingEx);
}
}
public Geometry(JGeometry jGeometry) {
this.geometry = jGeometry;
}
public JGeometry getInnerGeometry() {
return geometry;
}
@Override
public String toString() {
return toSDOGeometryString();
}
private JGeometry disassembleSdoGeometry(String sdoGeometry) {
return new JGeometry(retrieveGeometryType(sdoGeometry), //
retrieveSRID(sdoGeometry), //
retrievePointTypeX(sdoGeometry), //
retrievePointTypeY(sdoGeometry), //
retrievePointTypeZ(sdoGeometry), //
retrieveElemInfo(sdoGeometry), //
retrieveOrdinatesArray(sdoGeometry) //
);
}
private int retrieveGeometryType(String sdoGeometry) {
String geometryType = StringUtils.substringBetween(sdoGeometry, "(", ",");
return Integer.parseInt(geometryType.trim());
}
private int retrieveSRID(String sdoGeometry) {
String sridString = StringUtils.substringBetween(sdoGeometry, ",", ",");
return Integer.parseInt(sridString.trim());
}
private double retrievePointTypeX(String sdoGeometry) {
return retrievePointTypes(sdoGeometry)[0];
}
private double retrievePointTypeY(String sdoGeometry) {
return retrievePointTypes(sdoGeometry)[1];
}
private double retrievePointTypeZ(String sdoGeometry) {
return retrievePointTypes(sdoGeometry)[2];
}
private double[] retrievePointTypes(String sdoGeometry) {
double[] result = new double[3];
String pointTypesAsString = StringUtils.substringBetween(sdoGeometry, MDSYS_POINT_TYPE + "(", ")");
if (pointTypesAsString != null) {
result = toDoubleArray(pointTypesAsString);
}
return result;
}
private int[] retrieveElemInfo(String sdoGeometry) {
String elemInfoArray = StringUtils.substringBetween(sdoGeometry, MDSYS_ELEMENT_ARR + "(", ")");
return toIntArray(elemInfoArray);
}
private double[] retrieveOrdinatesArray(String sdoGeometry) {
String ordinatesArray = StringUtils.substringBetween(sdoGeometry, MDSYS_ORDINATE_ARR + "(", ")");
return toDoubleArray(ordinatesArray);
}
public String toSDOGeometryString() {
if (geometry ###### null)
return null;
StringBuilder string = new StringBuilder(MDSYS_GEOM + "(");
string.append(getGeometryType() + ",");
string.append(geometry.getSRID() + ",");
if (geometry.getPoint() ###### null) {
string.append("null,");
} else {
string.append(MDSYS_POINT_TYPE);
string.append(toStringDoubleArray(geometry.getPoint()));
string.append(",");
}
if (geometry.getElemInfo() ###### null) {
string.append("null,");
} else {
string.append(MDSYS_ELEMENT_ARR);
string.append(toStringIntArray(geometry.getElemInfo()));
string.append(",");
}
if (geometry.getOrdinatesArray() ###### null) {
string.append("null");
} else {
string.append(MDSYS_ORDINATE_ARR);
string.append(toStringDoubleArray(geometry.getOrdinatesArray()));
}
return string.append(")").toString();
}
private int getGeometryType() {
return (geometry.getDimensions() * 1000 + geometry.getType());
}
@Override
public Object clone() {
return (geometry ###### null ? new Geometry() : new Geometry((JGeometry) geometry.clone()));
}
@Override
public int hashCode() {
return (geometry ###### null ? 0 : geometry.hashCode());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Geometry))
return false;
JGeometry other = ((Geometry) obj).geometry;
return new EqualsBuilder().append(geometry, other).isEquals();
}
```
############= Joins uitvoeren ############=
Een Join kan uitgevoerd worden met een Oracle Geometry functie in de database: [SDO_GEOM.SDO_UNION](http://download.oracle.com/docs/html/A85337_01/sdo_objg.htm#857626). Die voegt twee `SDO_GEOMETRY` objecten samen tot een maar er is ook nog metadata nodig dat ergens anders zit:
```sql
SELECT SDO_GEOM.SDO_UNION(?, diminfo, ?, diminfo) FROM ALL_SDO_GEOM_METADATA WHERE owner ###### ? and table_name ?
```
`NULL` is toegelaten dus het is zo eenvoudig om een recursieve method aan te maken.
:exclamation: **Opgelet** Het is nodig om de voorgaande SQL in een `PreparedStatement` te steken indien de geometrie coördinaten +1.000 items bevatten. Zelfs in SQL Developer gaat dit niet. Foutboodschap dan: __*ORA-00939*: too many arguments for function__

View File

@ -0,0 +1,38 @@
+++
title = "persistence"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"persistence"
]
date = "2013-03-12"
+++
# Persistence
## JPA Collections mapping
### Hoe map ik een koppeltabel zonder die als entiteit zelf in ons domein te hebben?
Zo:
```java
@OneToMany(fetch ###### LAZY, cascade { MERGE, PERSIST })
@JoinTable(name = "physicalzonezonealias",
joinColumns ###### @JoinColumn(name "physicalzone", referencedColumnName = "id"),
inverseJoinColumns ###### @JoinColumn(name "zonealias", referencedColumnName = "id"))
@SequenceGenerator(name ###### "physicalzonezonealias_id", sequenceName "physicalzonezonealias_id", allocationSize = 1)
@CollectionId(columns ###### @Column(name "id"), type ###### @Type(type "int"), generator = "physicalzonezonealias_id")
private List<Zonealias> zoneAliases = new ArrayList<Zonealias>();
```
Wat is hier leuk aan?
* Gebruik `@JoinTable`, tabel zelf vervuilt domein niet
* Extra primary key kolom kan je ook mappen met '@CollectionId'' (Hibernate specifiek), die dan verwijst naar een generator!
Dat laatste is niet nodig als de primary key constraint op beide foreign keys zit.

View File

@ -0,0 +1,85 @@
+++
title = "play"
draft = false
tags = [
"",
"Users",
"jefklak",
"Downloads",
"pages",
"code",
"java",
"play"
]
date = "2013-03-12"
+++
# Play! Framework 1.2
:exclamation: Heel interessante `.gitignore` default configuratie voor Play terug te vinden op https://github.com/github/gitignore
### Dependencies Toevoegen
Toevoegen in dependencies.yml - default maven2 repo is niet nodig:
```
require:
1. play -> crud
2. org.easytesting -> fest-assert 1.4
```
Daarna altijd `play dependencies --sync` of eventueel `play eclipsify` en F5 op eclipse project.
#### Lokale repository als directory
```
repositories:
1. Local_repo:
type: iBiblio
root: "file:///C:/Documents%20and%20Settings/Jefklak/.m2/repository/"
contains:
1. be.klak -> *
2. ch.ntb -> *
```
#### Test libraries
**Niet mogelijk om apart te packagen**! Tenzij met speciale `id`, maar dan moet je de hele tijd bij `play run` switchen en de juiste id als parameter meegeven...
### Entities
#### Querying
```java
List<JPABase> entities = Entity.findAll();
```
#### Creating
```java
@Entity
public class Thing extends Model {
public String name;
}
```
-> Geen `@Id` nodig, dit zit bij Play1 in uw `Model` class. Dit is dus **niet zo voor play2**.
#### Testing
Extending van `UnitTest` voor "integratietesten":
```java
public class HorseIntegrationTest extends UnitTest {
@Test
public void canBePersisted() {
new Horse("joske").save();
List<JPABase> horses = Horse.findAll();
assertEquals(1, horses.size());
assertEquals("joske", ((Horse) horses.iterator().next()).name);
}
}
```

Some files were not shown because too many files have changed in this diff Show More