The tools and libraries you use should help you, they can help your hardware and so on. but in the end, they should make your life easier.
Take memcached for example, who does memcached help? Does it help your database server? yes, and thats a good thing! Does it help you? no, not realy, it forces you to make sure you invalidate keys, collect values from multiple sources and clutters your code and so on. Im not saying you shouldnt use memcached, im saying maybe you should use something in between, maybe you should find another library that helps you with using memcached. If you cant find such a library, maybe there is something else that can solve your problem, instead of solving the symptom of the problem.
Let me explain what i mean, il continue to use memcached as the example. Why is it you use memcached? because your database cant keep up. The symptom of this is that your webpage gets slow. You "solve" this by giving the database less to do. But what your realy doing is solving the symptom, ie adding memcache and asking your database less, speeds upp the webpage again. But your problem is realy still there: you cant get the data up from the database fast enough. You are just giving your users old data. yes, this data can be unchanged. but its still old.
A solution to the problem, would be to store the data somewhere else, perhaps some nosql storage if that works. Or perhaps you dont even need to store it in a database, if your in java maybe something like terracotta can solve it. I dont realy care, but solve the problem, not the symptom. And more important, the solution should help you, not make you work harder.
This is not meant as a bash against sql databases or memcached, they can be good tools. But they are often missused. My point is, your tools should not force you to work harder, or make your code more error prone. They should help you, and make your life easier, not only your hardwares life. Its not about what tools you use, its how you use them.
måndag 14 juni 2010
torsdag 10 juni 2010
Writing code is hard work
This post started out as a comment to: http://wolfie.github.com/2010/06/09/method-hierarchies.html
But when i had posted the comment i felt that i had more to say, so here we go:
You do not get clean, readable, maintainable code by just writing short methods, or by just writing some junit tests, or by just refactoring some code now and then. You get clean code by hard work, practise, and discussions.
If you encounter a bug in legacy code, and realise it is in a 1500 line class, you dont just find the problem and fix it. You treat the problem.
You do this by writing unit tests until you have isolated the problem (yes it is possible to write tests for the code, if you dont think so. go buy michael feathers book: http://amzn.to/9q7cNn).
When you have isolated the problem with a failing test, you make the test pass. If you have to change code that is not under test, you write tests for it first. Then you fix the problem, in as small increments as possible, with a run of tests for each increment.
When you have fixed the problem. You have most likely improved the design and readability of the class, if you havent. Do one small change to improve it.
Why should you write small methods? why not just keep theese 4 lines in the other method? its the only place it is used anyway!
For several reasons:
It raises the abstractionlevel to extract methods.
It is easier to click on a methodcall to find what it does, then to ignore 4 lines in a method.
It is easier to verify that 4 lines does what they are expected to do, if they are in a method with a good name. Then just 4 lines among 100 in a big method.
It is easier to write a junit test for a 4 line method, then for 4 lines in a 100 line method.
The problem with your codebase is not that someone wrote crap 4 years ago. It is that you didnt improve it everytime you touched it.
It is not someone elses code that is hard to read, everyone should own the code, it is your code that is hard to read!
I love code reviews, not the code reviews that involve one "chief architect" saying "thats not god enough, fix it". But the code reviews that involve 2-3 people disucssing someones code, why does that method have that name? could we improve a junit test here? could we extract another method? does this class do to many things? and so on. Dont review every single row of code, but thoose lines you review, do it well, discuss it, learn from it, improve from it. The goal of a code review is not perfect code. It is that one year from now, you have improved from it.
I realise now that i havent mentioned TDD or pair-programing. But you already do that anyway, right?
dont forget, software craftmanship is not about speed, it is about quality.
But when i had posted the comment i felt that i had more to say, so here we go:
You do not get clean, readable, maintainable code by just writing short methods, or by just writing some junit tests, or by just refactoring some code now and then. You get clean code by hard work, practise, and discussions.
If you encounter a bug in legacy code, and realise it is in a 1500 line class, you dont just find the problem and fix it. You treat the problem.
You do this by writing unit tests until you have isolated the problem (yes it is possible to write tests for the code, if you dont think so. go buy michael feathers book: http://amzn.to/9q7cNn).
When you have isolated the problem with a failing test, you make the test pass. If you have to change code that is not under test, you write tests for it first. Then you fix the problem, in as small increments as possible, with a run of tests for each increment.
When you have fixed the problem. You have most likely improved the design and readability of the class, if you havent. Do one small change to improve it.
Why should you write small methods? why not just keep theese 4 lines in the other method? its the only place it is used anyway!
For several reasons:
It raises the abstractionlevel to extract methods.
It is easier to click on a methodcall to find what it does, then to ignore 4 lines in a method.
It is easier to verify that 4 lines does what they are expected to do, if they are in a method with a good name. Then just 4 lines among 100 in a big method.
It is easier to write a junit test for a 4 line method, then for 4 lines in a 100 line method.
The problem with your codebase is not that someone wrote crap 4 years ago. It is that you didnt improve it everytime you touched it.
It is not someone elses code that is hard to read, everyone should own the code, it is your code that is hard to read!
I love code reviews, not the code reviews that involve one "chief architect" saying "thats not god enough, fix it". But the code reviews that involve 2-3 people disucssing someones code, why does that method have that name? could we improve a junit test here? could we extract another method? does this class do to many things? and so on. Dont review every single row of code, but thoose lines you review, do it well, discuss it, learn from it, improve from it. The goal of a code review is not perfect code. It is that one year from now, you have improved from it.
I realise now that i havent mentioned TDD or pair-programing. But you already do that anyway, right?
dont forget, software craftmanship is not about speed, it is about quality.
onsdag 7 april 2010
Actors in java with akka, cont persistence
Ok, maybe we want our messages to be stored in a database in case something goes wrong?
I will use redis, so you will need to setup a local redis server. this is very simple read more on redis homepage: http://code.google.com/p/redis/
if you prefer cassandra or any other nosql database akka supports (check http://doc.akkasource.org/persistence ) you simply have to change RedisStorage to your storage solution.
Adding storage is usually allot of work. or at least some work. in akka, it is trivial:
in your maven pom.xml add:
in Chatserver.java
this is what changed:
i added an @transactionrequired annotation to the class, this means that all methods in ChatServer will be done in a stm transaction. you can read more about that in the akka docs: http://doc.akkasource.org/transactors
Then i changed the Vector to a PersistentVector. this is a datatype provided by akka, that stores its content in a database. There are several databases supported, Cassandra and redis are two examples. they all work with the same Peristent Datastructures, in addition to Vector there are for ex: PersistentMap and PersistentQueue.
I initiate this Vector in a method with the @inittransactionalstate annotation, this method should be called by magic by akka, but its currently not. so until a very near future when that is fixed, i decided to call that method in the login method in ChatSession.
Thats it, our messages are now stored in a redis database. if you installed redis with default settings, and use the default config for akka, it will find the database without any configuration.
I will use redis, so you will need to setup a local redis server. this is very simple read more on redis homepage: http://code.google.com/p/redis/
if you prefer cassandra or any other nosql database akka supports (check http://doc.akkasource.org/persistence ) you simply have to change RedisStorage to your storage solution.
Adding storage is usually allot of work. or at least some work. in akka, it is trivial:
in your maven pom.xml add:
<dependency>
<groupid>se.scalablesolutions.akka</groupId>
<artifactid>akka-persistence-redis_2.8.0.Beta1</artifactId>
<version>0.8</version>
</dependency>
this will include the dependencies we need to store everything.in Chatserver.java
@transactionrequired
public class ChatServer {
@Inject
public ChatServer() {
}
private List<Message> messages = new ArrayList<Message>();
private Set<ChatSession> sessions = new HashSet<ChatSession>();
private PersistentVector<byte[]> storage;
@inittransactionalstate
public void init() {
storage = RedisStorage.getVector("Storage");
}
this is what changed:
i added an @transactionrequired annotation to the class, this means that all methods in ChatServer will be done in a stm transaction. you can read more about that in the akka docs: http://doc.akkasource.org/transactors
Then i changed the Vector to a PersistentVector. this is a datatype provided by akka, that stores its content in a database. There are several databases supported, Cassandra and redis are two examples. they all work with the same Peristent Datastructures, in addition to Vector there are for ex: PersistentMap and PersistentQueue.
I initiate this Vector in a method with the @inittransactionalstate annotation, this method should be called by magic by akka, but its currently not. so until a very near future when that is fixed, i decided to call that method in the login method in ChatSession.
Thats it, our messages are now stored in a redis database. if you installed redis with default settings, and use the default config for akka, it will find the database without any configuration.
Actors in java with akka, cont
I continue where my last post left us.
We now have a fully working chat, we can send messages and we will recieve messages that other users send.
The system is far from perfect. Lets try to improve it.
When i send a message, i have to wait until the server has sent it out to all the users before i can send another message, or look at the log. We could just wrap it in a Runnable and use a executor to make the call async. But that is pretty uggly code, and it can soon start to lead to problems.
Instead, lets use akka to introduce actors. if you want to know why and what actors are, there are alot of reading on the web. you can start with akka's homepage for ex: www.akkasource.org
first, we need to add the akka repository and dependency to our maven pom.
now lets change some code, remember the testcase we had? with the Guice Injector, lets rewrite that.
As you can see, not much have changed.
We still have our guiceModule where we configure ChatSession.
But now we have a ActiveObjectConfigurator, we could call this an extension to guice. For now, ignore all the Strange things like RestartStrategy and LifeCycles we will look at them later.
lets look at the integrationTest method, the only difference here is that instead of creating a GuiceInjector, we use the ActiveObjectConfigurator, and with getExternalDependency, we can get an instance of ChatSession. But now, every method is fire and forget. ie, after we call the method we will return immediatly.
Now we have a much more scalable solution. next, it is time to store our messages in a database.
We now have a fully working chat, we can send messages and we will recieve messages that other users send.
The system is far from perfect. Lets try to improve it.
When i send a message, i have to wait until the server has sent it out to all the users before i can send another message, or look at the log. We could just wrap it in a Runnable and use a executor to make the call async. But that is pretty uggly code, and it can soon start to lead to problems.
Instead, lets use akka to introduce actors. if you want to know why and what actors are, there are alot of reading on the web. you can start with akka's homepage for ex: www.akkasource.org
first, we need to add the akka repository and dependency to our maven pom.
<repositories>
<repository>
<id>akka.repository</id>
<name>Akka Maven Repository</name>
<url>http://scalablesolutions.se/akka/repository</url>
</repository>
</repositories>
and
<dependency>
<groupId>se.scalablesolutions.akka</groupId>
<artifactId>akka-core_2.8.0.Beta1</artifactId>
<version>0.8</version>
</dependency>
now lets change some code, remember the testcase we had? with the Guice Injector, lets rewrite that.
public class IntegrationTest {
ActiveObjectConfigurator conf = new ActiveObjectConfigurator();
@Before
public void setup() {
MessageDispatcher dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("test");
conf.addExternalGuiceModule(new AbstractModule() {
@Override
protected void configure() {
bind(ChatSession.class);
}
}).configure(new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
new Component[]{
new Component(ChatServer.class, new LifeCycle(new Permanent()), 10000, dispatcher)}).inject().supervise();
}
@Test
public void integrationTest() throws InterruptedException {
final ChatSession userOne = conf.getExternalDependency(ChatSession.class);
userOne.setUserName("userOne");
userOne.login();
final ChatSession userTwo = conf.getExternalDependency(ChatSession.class);
final ChatSession userThree = conf.getExternalDependency(ChatSession.class);
userTwo.setUserName("userTwo");
userTwo.login();
Thread.sleep(100); //to ensure login is done
userOne.sendMessage("Hello");
userTwo.sendMessage("Another Message 1");
assertEquals(2, userOne.getLog().size());
assertEquals(2, userTwo.getLog().size());
assertEquals(userTwo.getLog(), userOne.getLog());
}
}
As you can see, not much have changed.
We still have our guiceModule where we configure ChatSession.
But now we have a ActiveObjectConfigurator, we could call this an extension to guice. For now, ignore all the Strange things like RestartStrategy and LifeCycles we will look at them later.
lets look at the integrationTest method, the only difference here is that instead of creating a GuiceInjector, we use the ActiveObjectConfigurator, and with getExternalDependency, we can get an instance of ChatSession. But now, every method is fire and forget. ie, after we call the method we will return immediatly.
Now we have a much more scalable solution. next, it is time to store our messages in a database.
Actors in java with akka
I am currently working my way through the akka tutorial, except that im using java instead of scala. I am also trying to make it in smaller steps, and trying to keep it runnable as much as possible. I have removed import statements and such to make it shorter, the full code can be found at github: http://github.com/bobo/akka_sample_java
Lets start withough any akka or other magic, except for Guice.
I started by creating a chatserver:
It might seem weird to have the Vector store byte[] instead of message, but later we will change it to a PersistentVector, and that uses byte[] to store it in the backend.
And we need some clients:
Here we inject the Chatserver with @Inject directly on the variable declaration
we can use it in a simple testcase:
Here we create two chatsessions with our guice injector. And since we have bound ChatServer as a singleton they will have the same instance of chatserver injected.
Now the next step is to add akka to the project. i will add that to a seperate post
Lets start withough any akka or other magic, except for Guice.
I started by creating a chatserver:
public class ChatServer {
@Inject
public ChatServer() {
}
private List<Message> messages = new ArrayList<Message>();
private Set<ChatSession> sessions = new HashSet<ChatSession>();
private Vector<byte[]> storage = new Vector<byte[]>();
public void login(ChatSession chatSession) {
sessions.add(chatSession);
}
public List<Message> getLog() {
return Collections.unmodifiableList(messages);
}
public void sendMessage(Message message) {
storeMessage(message);
for (ChatSession chatSession : sessions) {
chatSession.recieveMessage(message);
}
}
private void storeMessage(Message message) {
messages.add(message);
storage.add(message.toString().getBytes());
}
}
This is just a simple class, that stores messages in byteformat in a vector.It might seem weird to have the Vector store byte[] instead of message, but later we will change it to a PersistentVector, and that uses byte[] to store it in the backend.
And we need some clients:
public class ChatSession {
private String userName;
private final List<Message> messages = new ArrayList<Message>();
@Inject
private ChatServer chatServer;
public void login() {
chatServer.login(this);
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void recieveMessage(Message message) {
messages.add(message);
}
public void sendMessage(String text) {
Message message = new Message(userName, text);
chatServer.sendMessage(message);
}
public List<Message> getLog() {
return messages;
}
}
Here we inject the Chatserver with @Inject directly on the variable declaration
we can use it in a simple testcase:
public class IntegrationTest {
Module m;
@Before
public void setup() {
m = new AbstractModule() {
@Override
protected void configure() {
bind(ChatSession.class);
bind(ChatServer.class).asEagerSingleton();
}
};
}
@Test
public void integrationTest() throws InterruptedException {
Injector inj = Guice.createInjector(m);
final ChatSession userOne = inj.getInstance(ChatSession.class);
userOne.setUserName("userOne");
userOne.login();
final ChatSession userTwo = inj.getInstance(ChatSession.class);
userTwo.setUserName("userTwo");
userTwo.login();
userOne.sendMessage("Hello");
userTwo.sendMessage("Another Message 1");
Thread.sleep(400); //wait for messages to finish
assertEquals(2, userOne.getLog().size());
assertEquals(2, userTwo.getLog().size());
assertEquals(userTwo.getLog(), userOne.getLog());
}
}
Here we create two chatsessions with our guice injector. And since we have bound ChatServer as a singleton they will have the same instance of chatserver injected.
Now the next step is to add akka to the project. i will add that to a seperate post
fredag 12 mars 2010
Hide boilerplate in netbeans
Im using the Netbeans 6.9m1, while looking for the code coverage plugin, i found something called "extended java editor" I added it without thinking and planed to look what it is later.
Then going back to my editorwindow this is what i found:
To make it more visible what it does here is a before image:
In other words,
Then going back to my editorwindow this is what i found:
To make it more visible what it does here is a before image:
In other words,
- it hides the Bundle lookups and instead shows the text in my bundle file.
- hides the type on the right side of collections (new ArrayList<~>())
- shows inner classes as closures
And this without changing any code.
I think this makes the code allot easier to read. and it hilights other things that should be changed. For example i dont think ServerRootNode.getDefaultInstance().getConnection().addPropertyChangeListener...
looks that bad in the before picture. but in the after picture it looks horrible.
There might be more things this plugin does that i haven't seen yet, i tried to find more information about it but there doesn't seem to be much.
söndag 15 november 2009
Keep it pretty
One thing i dont like with scala, is that alot of the code i see, is uglier then alot of the java code i see. This is probably partly because im more used to java. But also because scala has some great and powerfull features that not always make the code easier to read.
I have been dooing some refactoring in Scala. Mostly to get used to reading Scala code. I have encounterd some things that are not possible in java, that can make it abit harder to read scala code.
I totaly see why today is a method. But i dont see why it should be inside formatAge. When i read code, i want to read the usages of a method before i read the implementation.
Isnt it easier to see what formatAge does? Is it realy that horrible that today gets a little bigger scope?
I dont realy like the way TimeFormatter is used either. It looks almost like static methods in java are beeing called. But its actually a new class beein instansiated and a method on that instance beeing called. Im not sure how want it. But im sure scala can make it pretty!
I have been dooing some refactoring in Scala. Mostly to get used to reading Scala code. I have encounterd some things that are not possible in java, that can make it abit harder to read scala code.
def formatAge(date: Date): String = {
def today(d1: DateTime) = d1.getDayOfYear == new DateTime().getDayOfYear
val dateTime = new DateTime(date)
if (showAsAge_?)
TimeFormatter(dateToAgeSeconds(date.getTime)).colonSeparated
else
if (today(dateTime)) fmtNoDay.print(dateTime) else fmt.print(dateTime)
}
I totaly see why today is a method. But i dont see why it should be inside formatAge. When i read code, i want to read the usages of a method before i read the implementation.
def formatAge(date: Date): String = {
val dateTime = new DateTime(date)
if (showAsAge_?)
TimeFormatter(dateToAgeSeconds(date.getTime)).colonSeparated
else
if (today(dateTime)) fmtNoDay.print(dateTime) else fmt.print(dateTime)
}
def today(d1: DateTime) = d1.getDayOfYear == new DateTime().getDayOfYear
Isnt it easier to see what formatAge does? Is it realy that horrible that today gets a little bigger scope?
I dont realy like the way TimeFormatter is used either. It looks almost like static methods in java are beeing called. But its actually a new class beein instansiated and a method on that instance beeing called. Im not sure how want it. But im sure scala can make it pretty!
Prenumerera på:
Inlägg (Atom)